slack_morphism/models/common/
mod.rs

1use chrono::serde::ts_seconds;
2use chrono::{DateTime, NaiveDate, TimeZone, Utc};
3use rsb_derive::Builder;
4use rvstruct::ValueStruct;
5use serde::{Deserialize, Serialize};
6use serde_with::{serde_as, skip_serializing_none};
7use std::hash::Hash;
8use std::*;
9use url::Url;
10
11mod user;
12
13pub use user::*;
14
15mod team;
16
17pub use team::*;
18
19mod channel;
20
21pub use channel::*;
22
23mod pin;
24
25pub use pin::*;
26
27mod reaction;
28
29pub use reaction::*;
30
31mod star;
32
33pub use star::*;
34
35mod bot;
36
37pub use bot::*;
38
39mod icon;
40
41pub use icon::*;
42
43mod formatters;
44
45pub use formatters::*;
46
47mod emoji;
48
49pub use emoji::*;
50mod assistant;
51pub use assistant::*;
52
53#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
54pub struct SlackTs(pub String);
55
56impl SlackTs {
57    pub fn to_date_time_opt(&self) -> Option<DateTime<Utc>> {
58        let parts: Vec<&str> = self.value().split('.').collect();
59        if let Ok(ts_int) = parts[0].parse::<i64>() {
60            match Utc.timestamp_millis_opt(ts_int * 1000) {
61                chrono::LocalResult::None => None,
62                chrono::LocalResult::Single(result) => Some(result),
63                chrono::LocalResult::Ambiguous(first, _) => Some(first),
64            }
65        } else {
66            None
67        }
68    }
69}
70
71#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
72pub struct SlackScheduledMid(pub String);
73
74#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
75pub struct SlackTeamId(pub String);
76
77#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
78pub struct SlackEnterpriseSubteamId(pub String);
79
80#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
81pub struct SlackAppId(pub String);
82
83#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
84pub struct SlackChannelId(pub String);
85
86#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
87pub struct SlackClientMessageId(pub String);
88
89impl SlackTextFormat for SlackChannelId {
90    fn to_slack_format(&self) -> String {
91        format!("<#{}>", self.value())
92    }
93}
94
95#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
96pub struct SlackChannelType(pub String);
97
98#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
99pub struct SlackConversationId(pub String);
100
101#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
102pub struct SlackActionId(pub String);
103
104#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
105pub struct SlackActionType(pub String);
106
107#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize, ValueStruct)]
108pub struct SlackUserId(pub String);
109
110#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize, ValueStruct)]
111pub struct SlackUserGroupId(pub String);
112
113impl SlackTextFormat for SlackUserId {
114    fn to_slack_format(&self) -> String {
115        format!("<@{}>", self.value())
116    }
117}
118
119impl SlackTextFormat for SlackUserGroupId {
120    fn to_slack_format(&self) -> String {
121        format!("<!subteam^{}>", self.value())
122    }
123}
124
125#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize, ValueStruct)]
126pub struct SlackBotId(pub String);
127
128#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
129pub struct SlackDateTime(#[serde(with = "ts_seconds")] pub DateTime<Utc>);
130
131#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
132pub struct SlackDate(pub String);
133
134impl SlackDate {
135    pub fn to_naive_date(&self) -> Option<NaiveDate> {
136        NaiveDate::parse_from_str(self.value(), "%Y-%m-%d").ok()
137    }
138}
139
140#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
141pub struct SlackLocale(pub String);
142
143#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
144pub struct SlackCursorId(pub String);
145
146#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
147pub struct SlackColor(pub String);
148
149#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
150pub struct SlackCallbackId(pub String);
151
152#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
153pub struct SlackTriggerId(pub String);
154
155#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
156pub struct SlackViewId(pub String);
157
158#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
159pub struct SlackCommandId(pub String);
160
161#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
162pub struct SlackClientId(pub String);
163
164#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
165pub struct SlackClientSecret(pub String);
166
167impl fmt::Debug for SlackClientSecret {
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
169        write!(f, "SlackClientSecret(len:{})", self.value().len())
170    }
171}
172
173#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
174pub struct SlackApiTokenScope(pub String);
175
176#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
177pub struct SlackVerificationToken(pub String);
178
179impl fmt::Debug for SlackVerificationToken {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
181        write!(f, "SlackVerificationToken(len:{})", self.value().len())
182    }
183}
184
185#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
186pub struct SlackSigningSecret(pub String);
187
188impl fmt::Debug for SlackSigningSecret {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
190        write!(f, "SlackSigningSecret(len:{})", self.value().len())
191    }
192}
193
194#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
195pub struct EmailAddress(pub String);
196
197#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
198pub struct PhoneNumber(pub String);
199
200#[serde_as]
201#[skip_serializing_none]
202#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
203pub struct SlackResponseMetadata {
204    #[serde(default)]
205    #[serde_as(as = "serde_with::NoneAsEmptyString")]
206    pub next_cursor: Option<SlackCursorId>,
207}
208
209#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
210pub enum SlackConversationType {
211    #[serde(rename = "im")]
212    Im,
213    #[serde(rename = "mpim")]
214    Mpim,
215    #[serde(rename = "private_channel")]
216    Private,
217    #[serde(rename = "public_channel")]
218    Public,
219}
220
221#[allow(clippy::to_string_trait_impl)]
222impl ToString for SlackConversationType {
223    fn to_string(&self) -> String {
224        match self {
225            SlackConversationType::Im => "im".into(),
226            SlackConversationType::Mpim => "mpim".into(),
227            SlackConversationType::Private => "private_channel".into(),
228            SlackConversationType::Public => "public_channel".into(),
229        }
230    }
231}
232
233#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
234pub struct SlackResponseUrl(pub Url);
235
236#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
237pub struct SlackWebSocketsUrl(pub Url);
238
239impl SlackWebSocketsUrl {
240    pub fn to_debug_url(&self) -> Self {
241        Self(Url::parse(format!("{}&debug_reconnects=true", self.value()).as_str()).unwrap())
242    }
243}
244
245#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
246pub struct SlackTeamUrl(pub Url);
247
248#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
249pub struct SlackUnfurlId(pub String);
250
251#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
252pub struct SlackMimeType(pub String);
253
254#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
255pub struct SlackEmoji(pub String);
256
257impl SlackEmoji {
258    pub const SMILE: &'static str = ":smile:";
259    pub const SPEECH_BALLOON: &'static str = ":speech_balloon:";
260    pub const HEAVY_CHECK_MARK: &'static str = ":heavy_check_mark:";
261}
262
263#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
264pub enum SlackShortcutType {
265    #[serde(rename = "message")]
266    Message,
267    #[serde(rename = "global")]
268    Global,
269}
270
271#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
272pub struct SlackEventType(pub String);
273
274#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize, ValueStruct)]
275pub struct SlackEnterpriseId(pub String);
276
277#[cfg(test)]
278mod test {
279    use super::*;
280
281    #[test]
282    fn test_slack_date_time() {
283        let dt = SlackDateTime(
284            DateTime::parse_from_rfc3339("2020-01-01T00:42:42Z")
285                .unwrap()
286                .into(),
287        );
288        let json = serde_json::to_value(&dt).unwrap();
289        assert_eq!(json.as_u64().unwrap(), 1577839362);
290    }
291}