Skip to main content

revolt_database/events/
client.rs

1use iso8601_timestamp::Timestamp;
2use revolt_result::Error;
3use serde::{Deserialize, Serialize};
4
5use revolt_models::v0::{
6    AppendMessage, Channel, ChannelSlowmode, ChannelUnread, ChannelVoiceState, Emoji,
7    FieldsChannel, FieldsMember, FieldsMessage, FieldsRole, FieldsServer, FieldsUser,
8    FieldsWebhook, Member, MemberCompositeKey, Message, PartialChannel, PartialEmoji,
9    PartialMember, PartialMessage, PartialRole, PartialServer, PartialUser, PartialUserVoiceState,
10    PartialWebhook, PolicyChange, RemovalIntention, Report, Server, User, UserSettings,
11    UserVoiceState, Webhook,
12};
13
14use crate::{Account, Database, Session};
15
16/// Ping Packet
17#[derive(Serialize, Deserialize, Debug, Clone)]
18#[serde(untagged)]
19pub enum Ping {
20    Binary(Vec<u8>),
21    Number(usize),
22}
23
24/// Fields provided in Ready payload
25#[derive(PartialEq, Debug, Clone, Deserialize)]
26pub struct ReadyPayloadFields {
27    pub users: bool,
28    pub servers: bool,
29    pub channels: bool,
30    pub members: bool,
31    pub emojis: bool,
32    pub voice_states: bool,
33    pub user_settings: Vec<String>,
34    pub channel_unreads: bool,
35    pub policy_changes: bool,
36}
37
38impl Default for ReadyPayloadFields {
39    fn default() -> Self {
40        Self {
41            users: true,
42            servers: true,
43            channels: true,
44            members: true,
45            emojis: true,
46            voice_states: true,
47            user_settings: Vec::new(),
48            channel_unreads: false,
49            policy_changes: true,
50        }
51    }
52}
53
54/// Protocol Events
55#[derive(Serialize, Deserialize, Debug, Clone)]
56#[serde(tag = "type")]
57pub enum EventV1 {
58    /// Multiple events
59    Bulk {
60        v: Vec<EventV1>,
61    },
62    /// Error event
63    Error {
64        data: Error,
65    },
66
67    /// Successfully authenticated
68    Authenticated,
69    /// Logged out
70    Logout,
71    /// Basic data to cache
72    Ready {
73        #[serde(skip_serializing_if = "Option::is_none")]
74        users: Option<Vec<User>>,
75        #[serde(skip_serializing_if = "Option::is_none")]
76        servers: Option<Vec<Server>>,
77        #[serde(skip_serializing_if = "Option::is_none")]
78        channels: Option<Vec<Channel>>,
79        #[serde(skip_serializing_if = "Option::is_none")]
80        members: Option<Vec<Member>>,
81        #[serde(skip_serializing_if = "Option::is_none")]
82        emojis: Option<Vec<Emoji>>,
83        #[serde(skip_serializing_if = "Option::is_none")]
84        voice_states: Option<Vec<ChannelVoiceState>>,
85
86        #[serde(skip_serializing_if = "Option::is_none")]
87        user_settings: Option<UserSettings>,
88        #[serde(skip_serializing_if = "Option::is_none")]
89        channel_unreads: Option<Vec<ChannelUnread>>,
90
91        #[serde(skip_serializing_if = "Option::is_none")]
92        policy_changes: Option<Vec<PolicyChange>>,
93    },
94
95    /// Ping response
96    Pong {
97        data: Ping,
98    },
99
100    /// Release the bees.
101    Bees,
102
103    /// New message
104    Message(Message),
105
106    /// Update existing message
107    MessageUpdate {
108        id: String,
109        channel: String,
110        data: PartialMessage,
111        #[serde(default)]
112        clear: Vec<FieldsMessage>,
113    },
114
115    /// Append information to existing message
116    MessageAppend {
117        id: String,
118        channel: String,
119        append: AppendMessage,
120    },
121
122    /// Delete message
123    MessageDelete {
124        id: String,
125        channel: String,
126    },
127
128    /// New reaction to a message
129    MessageReact {
130        id: String,
131        channel_id: String,
132        user_id: String,
133        emoji_id: String,
134    },
135
136    /// Remove user's reaction from message
137    MessageUnreact {
138        id: String,
139        channel_id: String,
140        user_id: String,
141        emoji_id: String,
142    },
143
144    /// Remove a reaction from message
145    MessageRemoveReaction {
146        id: String,
147        channel_id: String,
148        emoji_id: String,
149    },
150
151    /// Bulk delete messages
152    BulkMessageDelete {
153        channel: String,
154        ids: Vec<String>,
155    },
156
157    /// New server
158    ServerCreate {
159        id: String,
160        server: Server,
161        channels: Vec<Channel>,
162        emojis: Vec<Emoji>,
163        voice_states: Vec<ChannelVoiceState>,
164    },
165
166    /// Update existing server
167    ServerUpdate {
168        id: String,
169        data: PartialServer,
170        #[serde(default)]
171        clear: Vec<FieldsServer>,
172    },
173
174    /// Delete server
175    ServerDelete {
176        id: String,
177    },
178
179    /// Update existing server member
180    ServerMemberUpdate {
181        id: MemberCompositeKey,
182        data: PartialMember,
183        #[serde(default)]
184        clear: Vec<FieldsMember>,
185    },
186
187    /// User joins server
188    ServerMemberJoin {
189        id: String,
190        // Deprecated: use member.id.user
191        #[deprecated = "Use member.id.user instead"]
192        user: String,
193        member: Member,
194    },
195
196    /// User left server
197    ServerMemberLeave {
198        id: String,
199        user: String,
200        reason: RemovalIntention,
201    },
202
203    /// Server role created or updated
204    ServerRoleUpdate {
205        id: String,
206        role_id: String,
207        data: PartialRole,
208        #[serde(default)]
209        clear: Vec<FieldsRole>,
210    },
211
212    /// Server role deleted
213    ServerRoleDelete {
214        id: String,
215        role_id: String,
216    },
217
218    /// Server roles ranks updated
219    ServerRoleRanksUpdate {
220        id: String,
221        ranks: Vec<String>,
222    },
223
224    /// Update existing user
225    UserUpdate {
226        id: String,
227        data: PartialUser,
228        #[serde(default)]
229        clear: Vec<FieldsUser>,
230        event_id: Option<String>,
231    },
232
233    /// Relationship with another user changed
234    UserRelationship {
235        id: String,
236        user: User,
237    },
238    /// Settings updated remotely
239    UserSettingsUpdate {
240        id: String,
241        update: UserSettings,
242    },
243
244    /// User has been platform banned or deleted their account
245    ///
246    /// Clients should remove the following associated data:
247    /// - Messages
248    /// - DM Channels
249    /// - Relationships
250    /// - Server Memberships
251    ///
252    /// User flags are specified to explain why a wipe is occurring though not all reasons will necessarily ever appear.
253    UserPlatformWipe {
254        user_id: String,
255        flags: i32,
256    },
257    /// New emoji
258    EmojiCreate(Emoji),
259
260    /// Update existing emoji
261    EmojiUpdate {
262        id: String,
263        data: PartialEmoji,
264    },
265
266    /// Delete emoji
267    EmojiDelete {
268        id: String,
269    },
270
271    /// New report
272    ReportCreate(Report),
273    /// New channel
274    ChannelCreate(Channel),
275
276    /// Update existing channel
277    ChannelUpdate {
278        id: String,
279        data: PartialChannel,
280        #[serde(default)]
281        clear: Vec<FieldsChannel>,
282    },
283
284    /// Delete channel
285    ChannelDelete {
286        id: String,
287    },
288
289    /// User joins a group
290    ChannelGroupJoin {
291        id: String,
292        user: String,
293    },
294
295    /// User leaves a group
296    ChannelGroupLeave {
297        id: String,
298        user: String,
299    },
300
301    /// User started typing in a channel
302    ChannelStartTyping {
303        id: String,
304        user: String,
305    },
306
307    /// User stopped typing in a channel
308    ChannelStopTyping {
309        id: String,
310        user: String,
311    },
312
313    /// User acknowledged message in channel
314    ChannelAck {
315        id: String,
316        user: String,
317        message_id: String,
318    },
319
320    /// New webhook
321    WebhookCreate(Webhook),
322
323    /// Update existing webhook
324    WebhookUpdate {
325        id: String,
326        data: PartialWebhook,
327        remove: Vec<FieldsWebhook>,
328    },
329
330    /// Delete webhook
331    WebhookDelete {
332        id: String,
333    },
334
335    /// Auth events
336    CreateAccount {
337        account: Account,
338    },
339    CreateSession {
340        session: Session,
341    },
342    DeleteSession {
343        user_id: String,
344        session_id: String,
345    },
346    DeleteAllSessions {
347        user_id: String,
348        exclude_session_id: Option<String>,
349    },
350
351    /// Voice events
352    VoiceChannelJoin {
353        id: String,
354        state: UserVoiceState,
355    },
356    VoiceChannelLeave {
357        id: String,
358        user: String,
359    },
360    VoiceChannelMove {
361        user: String,
362        from: String,
363        to: String,
364        state: UserVoiceState,
365    },
366    UserVoiceStateUpdate {
367        id: String,
368        channel_id: String,
369        data: PartialUserVoiceState,
370    },
371    UserMoveVoiceChannel {
372        node: String,
373        from: String,
374        to: String,
375        token: String,
376    },
377    /// User's active slowmodes
378    UserSlowmodes {
379        slowmodes: Vec<ChannelSlowmode>,
380    },
381    VoiceCallUpdate {
382        initiator_id: String,
383        channel_id: String,
384        started_at: Option<Timestamp>,
385        ended: bool,
386    },
387}
388
389impl EventV1 {
390    /// Publish helper wrapper
391    pub async fn p(self, channel: String) {
392        #[cfg(not(debug_assertions))]
393        redis_kiss::p(channel, self).await;
394
395        #[cfg(debug_assertions)]
396        info!("Publishing event to {channel}: {self:?}");
397
398        #[cfg(debug_assertions)]
399        redis_kiss::publish(channel, self).await.unwrap();
400    }
401
402    /// Publish user event
403    pub async fn p_user(self, id: String, db: &Database) {
404        self.clone().p(id.clone()).await;
405
406        // TODO: this should be captured by member list in the future and not immediately fanned out to users
407        if let Ok(members) = db.fetch_all_memberships(&id).await {
408            for member in members {
409                self.clone().server(member.id.server).await;
410            }
411        }
412    }
413
414    /// Publish private event
415    pub async fn private(self, id: String) {
416        self.p(format!("{id}!")).await;
417    }
418
419    /// Publish server member event
420    pub async fn server(self, id: String) {
421        self.p(format!("{id}u")).await;
422    }
423
424    /// Publish internal global event
425    pub async fn global(self) {
426        self.p("global".to_string()).await;
427    }
428}