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