aboutsummaryrefslogtreecommitdiffstats
path: root/filamento/src/presence.rs
blob: e406ccec35af5caacebde5b62ba435e2a974169d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use chrono::{DateTime, Utc};
use stanza::{client::presence::String1024, xep_0203::Delay};

use crate::caps;

#[derive(Debug, Default, Clone)]
pub struct Online {
    pub show: Option<Show>,
    pub status: Option<String>,
    pub priority: Option<i8>,
}

#[derive(Debug, Clone, Copy)]
pub enum Show {
    Away,
    Chat,
    DoNotDisturb,
    ExtendedAway,
}

#[derive(Debug, Default, Clone)]
pub struct Offline {
    pub status: Option<String>,
}

#[derive(Debug, Clone)]
pub enum PresenceType {
    Online(Online),
    Offline(Offline),
}

#[derive(Debug, Clone)]
pub struct Presence {
    pub timestamp: DateTime<Utc>,
    pub presence: PresenceType,
}

impl Online {
    pub fn into_stanza(
        self,
        timestamp: Option<DateTime<Utc>>,
    ) -> stanza::client::presence::Presence {
        stanza::client::presence::Presence {
            show: self.show.map(|show| match show {
                Show::Away => stanza::client::presence::Show::Away,
                Show::Chat => stanza::client::presence::Show::Chat,
                Show::DoNotDisturb => stanza::client::presence::Show::Dnd,
                Show::ExtendedAway => stanza::client::presence::Show::Xa,
            }),
            // TODO: enforce message length in status message
            status: self.status.map(|status| stanza::client::presence::Status {
                lang: None,
                status: String1024(status),
            }),
            priority: self
                .priority
                .map(|priority| stanza::client::presence::Priority(priority)),
            delay: timestamp.map(|timestamp| Delay {
                from: None,
                stamp: timestamp,
            }),
            c: Some(caps::c()),
            ..Default::default()
        }
    }
}

impl Offline {
    pub fn into_stanza(
        self,
        timestamp: Option<DateTime<Utc>>,
    ) -> stanza::client::presence::Presence {
        stanza::client::presence::Presence {
            r#type: Some(stanza::client::presence::PresenceType::Unavailable),
            status: self.status.map(|status| stanza::client::presence::Status {
                lang: None,
                status: String1024(status),
            }),
            delay: timestamp.map(|timestamp| Delay {
                from: None,
                stamp: timestamp,
            }),
            c: Some(caps::c()),
            ..Default::default()
        }
    }
}

impl From<PresenceType> for stanza::client::presence::Presence {
    fn from(value: PresenceType) -> Self {
        match value {
            PresenceType::Online(online) => online.into_stanza(None),
            PresenceType::Offline(offline) => offline.into_stanza(None),
        }
    }
}

impl From<Presence> for stanza::client::presence::Presence {
    fn from(value: Presence) -> Self {
        match value.presence {
            PresenceType::Online(online) => online.into_stanza(Some(value.timestamp)),
            PresenceType::Offline(offline) => offline.into_stanza(Some(value.timestamp)),
        }
    }
}