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
131impl SlackDateTime {
132 pub fn now() -> Self {
133 Self(Utc::now())
134 }
135}
136
137#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
138pub struct SlackDate(pub String);
139
140impl SlackDate {
141 pub fn to_naive_date(&self) -> Option<NaiveDate> {
142 NaiveDate::parse_from_str(self.value(), "%Y-%m-%d").ok()
143 }
144}
145
146#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
147pub struct SlackLocale(pub String);
148
149#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
150pub struct SlackCursorId(pub String);
151
152#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
153pub struct SlackColor(pub String);
154
155#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
156pub struct SlackCallbackId(pub String);
157
158#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
159pub struct SlackTriggerId(pub String);
160
161#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
162pub struct SlackViewId(pub String);
163
164#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
165pub struct SlackCommandId(pub String);
166
167#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
168pub struct SlackClientId(pub String);
169
170#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
171pub struct SlackClientSecret(pub String);
172
173impl fmt::Debug for SlackClientSecret {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
175 write!(f, "SlackClientSecret(len:{})", self.value().len())
176 }
177}
178
179#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
180pub struct SlackApiTokenScope(pub String);
181
182#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
183pub struct SlackVerificationToken(pub String);
184
185impl fmt::Debug for SlackVerificationToken {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
187 write!(f, "SlackVerificationToken(len:{})", self.value().len())
188 }
189}
190
191#[derive(Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
192pub struct SlackSigningSecret(pub String);
193
194impl fmt::Debug for SlackSigningSecret {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
196 write!(f, "SlackSigningSecret(len:{})", self.value().len())
197 }
198}
199
200#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
201pub struct EmailAddress(pub String);
202
203#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
204pub struct PhoneNumber(pub String);
205
206#[serde_as]
207#[skip_serializing_none]
208#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Builder)]
209pub struct SlackResponseMetadata {
210 #[serde(default)]
211 #[serde_as(as = "serde_with::NoneAsEmptyString")]
212 pub next_cursor: Option<SlackCursorId>,
213}
214
215#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
216pub enum SlackConversationType {
217 #[serde(rename = "im")]
218 Im,
219 #[serde(rename = "mpim")]
220 Mpim,
221 #[serde(rename = "private_channel")]
222 Private,
223 #[serde(rename = "public_channel")]
224 Public,
225}
226
227#[allow(clippy::to_string_trait_impl)]
228impl ToString for SlackConversationType {
229 fn to_string(&self) -> String {
230 match self {
231 SlackConversationType::Im => "im".into(),
232 SlackConversationType::Mpim => "mpim".into(),
233 SlackConversationType::Private => "private_channel".into(),
234 SlackConversationType::Public => "public_channel".into(),
235 }
236 }
237}
238
239#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
240pub struct SlackResponseUrl(pub Url);
241
242#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
243pub struct SlackWebSocketsUrl(pub Url);
244
245impl SlackWebSocketsUrl {
246 pub fn to_debug_url(&self) -> Self {
247 Self(Url::parse(format!("{}&debug_reconnects=true", self.value()).as_str()).unwrap())
248 }
249}
250
251#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
252pub struct SlackTeamUrl(pub Url);
253
254#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
255pub struct SlackUnfurlId(pub String);
256
257#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
258pub struct SlackMimeType(pub String);
259
260#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
261pub struct SlackEmoji(pub String);
262
263impl SlackEmoji {
264 pub const SMILE: &'static str = ":smile:";
265 pub const SPEECH_BALLOON: &'static str = ":speech_balloon:";
266 pub const HEAVY_CHECK_MARK: &'static str = ":heavy_check_mark:";
267}
268
269#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
270pub enum SlackShortcutType {
271 #[serde(rename = "message")]
272 Message,
273 #[serde(rename = "global")]
274 Global,
275}
276
277#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, ValueStruct)]
278pub struct SlackEventType(pub String);
279
280#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize, ValueStruct)]
281pub struct SlackEnterpriseId(pub String);
282
283#[cfg(test)]
284mod test {
285 use super::*;
286
287 #[test]
288 fn test_slack_date_time() {
289 let dt = SlackDateTime(
290 DateTime::parse_from_rfc3339("2020-01-01T00:42:42Z")
291 .unwrap()
292 .into(),
293 );
294 let json = serde_json::to_value(&dt).unwrap();
295 assert_eq!(json.as_u64().unwrap(), 1577839362);
296 }
297}