Skip to main content

revolt_database/events/
client.rs

1use authifier::AuthifierEvent;
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::Database;
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    /// New message
100    Message(Message),
101
102    /// Update existing message
103    MessageUpdate {
104        id: String,
105        channel: String,
106        data: PartialMessage,
107        #[serde(default)]
108        clear: Vec<FieldsMessage>,
109    },
110
111    /// Append information to existing message
112    MessageAppend {
113        id: String,
114        channel: String,
115        append: AppendMessage,
116    },
117
118    /// Delete message
119    MessageDelete {
120        id: String,
121        channel: String,
122    },
123
124    /// New reaction to a message
125    MessageReact {
126        id: String,
127        channel_id: String,
128        user_id: String,
129        emoji_id: String,
130    },
131
132    /// Remove user's reaction from message
133    MessageUnreact {
134        id: String,
135        channel_id: String,
136        user_id: String,
137        emoji_id: String,
138    },
139
140    /// Remove a reaction from message
141    MessageRemoveReaction {
142        id: String,
143        channel_id: String,
144        emoji_id: String,
145    },
146
147    /// Bulk delete messages
148    BulkMessageDelete {
149        channel: String,
150        ids: Vec<String>,
151    },
152
153    /// New server
154    ServerCreate {
155        id: String,
156        server: Server,
157        channels: Vec<Channel>,
158        emojis: Vec<Emoji>,
159        voice_states: Vec<ChannelVoiceState>,
160    },
161
162    /// Update existing server
163    ServerUpdate {
164        id: String,
165        data: PartialServer,
166        #[serde(default)]
167        clear: Vec<FieldsServer>,
168    },
169
170    /// Delete server
171    ServerDelete {
172        id: String,
173    },
174
175    /// Update existing server member
176    ServerMemberUpdate {
177        id: MemberCompositeKey,
178        data: PartialMember,
179        #[serde(default)]
180        clear: Vec<FieldsMember>,
181    },
182
183    /// User joins server
184    ServerMemberJoin {
185        id: String,
186        // Deprecated: use member.id.user
187        #[deprecated = "Use member.id.user instead"]
188        user: String,
189        member: Member,
190    },
191
192    /// User left server
193    ServerMemberLeave {
194        id: String,
195        user: String,
196        reason: RemovalIntention,
197    },
198
199    /// Server role created or updated
200    ServerRoleUpdate {
201        id: String,
202        role_id: String,
203        data: PartialRole,
204        #[serde(default)]
205        clear: Vec<FieldsRole>,
206    },
207
208    /// Server role deleted
209    ServerRoleDelete {
210        id: String,
211        role_id: String,
212    },
213
214    /// Server roles ranks updated
215    ServerRoleRanksUpdate {
216        id: String,
217        ranks: Vec<String>,
218    },
219
220    /// Update existing user
221    UserUpdate {
222        id: String,
223        data: PartialUser,
224        #[serde(default)]
225        clear: Vec<FieldsUser>,
226        event_id: Option<String>,
227    },
228
229    /// Relationship with another user changed
230    UserRelationship {
231        id: String,
232        user: User,
233    },
234    /// Settings updated remotely
235    UserSettingsUpdate {
236        id: String,
237        update: UserSettings,
238    },
239
240    /// User has been platform banned or deleted their account
241    ///
242    /// Clients should remove the following associated data:
243    /// - Messages
244    /// - DM Channels
245    /// - Relationships
246    /// - Server Memberships
247    ///
248    /// User flags are specified to explain why a wipe is occurring though not all reasons will necessarily ever appear.
249    UserPlatformWipe {
250        user_id: String,
251        flags: i32,
252    },
253    /// New emoji
254    EmojiCreate(Emoji),
255
256    /// Update existing emoji
257    EmojiUpdate {
258        id: String,
259        data: PartialEmoji,
260    },
261
262    /// Delete emoji
263    EmojiDelete {
264        id: String,
265    },
266
267    /// New report
268    ReportCreate(Report),
269    /// New channel
270    ChannelCreate(Channel),
271
272    /// Update existing channel
273    ChannelUpdate {
274        id: String,
275        data: PartialChannel,
276        #[serde(default)]
277        clear: Vec<FieldsChannel>,
278    },
279
280    /// Delete channel
281    ChannelDelete {
282        id: String,
283    },
284
285    /// User joins a group
286    ChannelGroupJoin {
287        id: String,
288        user: String,
289    },
290
291    /// User leaves a group
292    ChannelGroupLeave {
293        id: String,
294        user: String,
295    },
296
297    /// User started typing in a channel
298    ChannelStartTyping {
299        id: String,
300        user: String,
301    },
302
303    /// User stopped typing in a channel
304    ChannelStopTyping {
305        id: String,
306        user: String,
307    },
308
309    /// User acknowledged message in channel
310    ChannelAck {
311        id: String,
312        user: String,
313        message_id: String,
314    },
315
316    /// New webhook
317    WebhookCreate(Webhook),
318
319    /// Update existing webhook
320    WebhookUpdate {
321        id: String,
322        data: PartialWebhook,
323        remove: Vec<FieldsWebhook>,
324    },
325
326    /// Delete webhook
327    WebhookDelete {
328        id: String,
329    },
330
331    /// Auth events
332    Auth(AuthifierEvent),
333
334    /// Voice events
335    VoiceChannelJoin {
336        id: String,
337        state: UserVoiceState,
338    },
339    VoiceChannelLeave {
340        id: String,
341        user: String,
342    },
343    VoiceChannelMove {
344        user: String,
345        from: String,
346        to: String,
347        state: UserVoiceState,
348    },
349    UserVoiceStateUpdate {
350        id: String,
351        channel_id: String,
352        data: PartialUserVoiceState,
353    },
354    UserMoveVoiceChannel {
355        node: String,
356        from: String,
357        to: String,
358        token: String,
359    },
360    /// User's active slowmodes
361    UserSlowmodes {
362        slowmodes: Vec<ChannelSlowmode>,
363    },
364}
365
366impl EventV1 {
367    /// Publish helper wrapper
368    pub async fn p(self, channel: String) {
369        #[cfg(not(debug_assertions))]
370        redis_kiss::p(channel, self).await;
371
372        #[cfg(debug_assertions)]
373        info!("Publishing event to {channel}: {self:?}");
374
375        #[cfg(debug_assertions)]
376        redis_kiss::publish(channel, self).await.unwrap();
377    }
378
379    /// Publish user event
380    pub async fn p_user(self, id: String, db: &Database) {
381        self.clone().p(id.clone()).await;
382
383        // TODO: this should be captured by member list in the future and not immediately fanned out to users
384        if let Ok(members) = db.fetch_all_memberships(&id).await {
385            for member in members {
386                self.clone().server(member.id.server).await;
387            }
388        }
389    }
390
391    /// Publish private event
392    pub async fn private(self, id: String) {
393        self.p(format!("{id}!")).await;
394    }
395
396    /// Publish server member event
397    pub async fn server(self, id: String) {
398        self.p(format!("{id}u")).await;
399    }
400
401    /// Publish internal global event
402    pub async fn global(self) {
403        self.p("global".to_string()).await;
404    }
405}