1 /**
2   Implementations of Discord events.
3 */
4 
5 module dcord.gateway.events;
6 
7 import std.algorithm,
8        std..string,
9        std.stdio,
10        std.datetime,
11        std.array,
12        std.conv;
13 
14 import dcord.types,
15        dcord.gateway,
16        dcord.bot.command;
17 
18 /**
19   A wrapper type for delegates that can be attached to an event, and run after
20   all listeners are executed. This can be used to ensure an event has fully passed
21   through all listeners, or to avoid having function/stack pointers within plugin
22   code (which allows for dynamically reloading the plugin).
23 */
24 alias EventDeferredFunc = void delegate();
25 
26 /**
27   Base template for events from discord. Handles basic initilization, and some
28   deferred-function code.
29 */
30 mixin template Event() {
31   @JSONIgnore
32   Client client;
33 
34   @JSONIgnore
35   VibeJSON raw;
36 
37   /**
38     Array of functions to be ran when this event has completed its pass through
39     the any listeners, and is ready to be destroyed.
40   */
41   @JSONIgnore
42   EventDeferredFunc[] deferred;
43 
44   this(Client c, VibeJSON obj) {
45     version (TIMING) {
46       auto sw = StopWatch(AutoStart.yes);
47       c.log.tracef("Starting create event for %s", this.toString);
48     }
49 
50     this.raw = obj;
51     this.client = c;
52     this.deserializeFromJSON(obj);
53 
54     version (TIMING) {
55       this.client.log.tracef("Create event for %s took %sms", this.toString,
56         sw.peek().to!("msecs", real));
57     }
58   }
59 
60   /**
61     Used to defer a functions execution until after this event has passed through
62     all listeners, and is ready to be destroyed.
63   */
64   void defer(EventDeferredFunc f) {
65     this.deferred ~= f;
66   }
67 
68   /**
69     Calls all deferred functions.
70   */
71   void resolveDeferreds() {
72     foreach (ref f; this.deferred) {
73       f();
74     }
75   }
76 }
77 
78 /**
79   Sent when we initially connect, contains base state and connection information.
80 */
81 class Ready {
82   mixin Event;
83 
84   ushort     ver;
85   string     sessionID;
86 
87   @JSONSource("user")
88   User       me;
89 
90   Guild[]    guilds;
91   Channel[]  dms;
92 }
93 
94 /**
95   Sent when we've completed a reconnect/resume sequence.
96 */
97 class Resumed {
98   mixin Event;
99 }
100 
101 /**
102   Sent when a channel is created.
103 */
104 class ChannelCreate {
105   mixin Event;
106 
107   @JSONFlat
108   Channel  channel;
109 }
110 
111 /**
112   Sent when a channel is updated.
113 */
114 class ChannelUpdate {
115   mixin Event;
116 
117   @JSONFlat
118   Channel  channel;
119 }
120 
121 /**
122   Sent when a channel is deleted.
123 */
124 class ChannelDelete {
125   mixin Event;
126 
127   @JSONFlat
128   Channel  channel;
129 }
130 
131 /**
132   Sent when a guild is created (often on startup).
133 */
134 class GuildCreate {
135   mixin Event;
136 
137   @JSONFlat
138   Guild  guild;
139 
140   bool unavailable;
141 }
142 
143 /**
144   Sent when a guild is updated
145 */
146 class GuildUpdate {
147   mixin Event;
148 
149   @JSONFlat
150   Guild  guild;
151 }
152 
153 /**
154   Sent when a guild is deleted (or becomes unavailable)
155 */
156 class GuildDelete {
157   mixin Event;
158 
159   Snowflake  guildID;
160   bool       unavailable;
161 }
162 
163 /**
164   Sent when a guild ban is added.
165 */
166 class GuildBanAdd {
167   mixin Event;
168 
169   Snowflake guildID;
170   User  user;
171 }
172 
173 /**
174   Sent when a guild ban is removed.
175 */
176 class GuildBanRemove {
177   mixin Event;
178 
179   Snowflake guildID;
180   User  user;
181 }
182 
183 /**
184   Sent when a guilds emojis are updated.
185 */
186 class GuildEmojisUpdate {
187   mixin Event;
188 }
189 
190 /**
191   Sent when a guilds integrations are updated.
192 */
193 class GuildIntegrationsUpdate {
194   mixin Event;
195 }
196 
197 /**
198   Sent in response to RequestGuildMembers.
199 */
200 
201 class GuildMembersChunk {
202   mixin Event;
203 
204   Snowflake guildID;
205   GuildMember[] members;
206 
207 /+
208   void load(JSONDecoder obj) {
209     obj.keySwitch!("guild_id", "members")(
210       { this.guildID = readSnowflake(obj); },
211       { loadMany!GuildMember(this.client, obj, (m) { this.members ~= m; }); },
212     );
213 
214     auto guild = this.client.state.guilds.get(this.guildID);
215     foreach (member; this.members) {
216       member.guild = guild;
217     }
218   }
219 +/
220 }
221 
222 /**
223   Sent when a member is added to a guild.
224 */
225 class GuildMemberAdd {
226   mixin Event;
227 
228   @JSONFlat
229   GuildMember  member;
230 }
231 
232 /**
233   Sent when a member is removed from a guild.
234 */
235 class GuildMemberRemove {
236   mixin Event;
237 
238   Snowflake  guildID;
239   User       user;
240 }
241 
242 /**
243   Sent when a guild member is updated.
244 */
245 class GuildMemberUpdate {
246   mixin Event;
247 
248   @JSONFlat
249   GuildMember  member;
250 }
251 
252 /**
253   Sent when a guild role is created.
254 */
255 class GuildRoleCreate {
256   mixin Event;
257 
258   Snowflake  guildID;
259   Role       role;
260 }
261 
262 /**
263   Sent when a guild role is updated.
264 */
265 class GuildRoleUpdate {
266   mixin Event;
267 
268   Snowflake  guildID;
269   Role       role;
270 }
271 
272 /**
273   Sent when a guild role is deleted.
274 */
275 class GuildRoleDelete {
276   mixin Event;
277 
278   Snowflake  guildID;
279   Role       role;
280 }
281 
282 /**
283   Sent when a message is created.
284 */
285 class MessageCreate {
286   mixin Event;
287 
288   @JSONFlat
289   Message  message;
290 
291   // Reference to the command event
292   @JSONIgnore
293   CommandEvent commandEvent;
294 }
295 
296 /**
297   Sent when a message is updated.
298 */
299 class MessageUpdate {
300   mixin Event;
301 
302   @JSONFlat
303   Message  message;
304 }
305 
306 /**
307   Sent when a message is deleted.
308 */
309 class MessageDelete {
310   mixin Event;
311 
312   Snowflake  id;
313   Snowflake  channelID;
314 }
315 
316 /**
317   Sent when a user's presence is updated.
318 */
319 class PresenceUpdate {
320   mixin Event;
321 
322   @JSONFlat
323   Presence presence;
324 }
325 
326 /**
327   Sent when a user starts typing.
328 */
329 class TypingStart {
330   mixin Event;
331 
332   Snowflake  channelID;
333   Snowflake  userID;
334   ulong      timestamp;
335 }
336 
337 /**
338   Sent when this users settings are updated.
339 */
340 class UserSettingsUpdate {
341   mixin Event;
342 }
343 
344 /**
345   Sent when this user is updated.
346 */
347 class UserUpdate {
348   mixin Event;
349 }
350 
351 /**
352   Sent when a voice state is updated.
353 */
354 class VoiceStateUpdate {
355   mixin Event;
356 
357   @JSONFlat
358   VoiceState  state;
359 }
360 
361 /**
362   Sent when a voice server is updated.
363 */
364 class VoiceServerUpdate {
365   mixin Event;
366 
367   string     token;
368   string     endpoint;
369   Snowflake  guildID;
370 }
371 
372 /**
373   Sent when a channels pins are updated.
374 */
375 class ChannelPinsUpdate {
376   mixin Event;
377 
378   Snowflake  channelID;
379   string     lastPinTimestamp;
380 }
381 
382 /**
383   Sent when a bulk set of messages gets deleted from a channel.
384 */
385 class MessageDeleteBulk {
386   mixin Event;
387 
388   Snowflake channelID;
389   Snowflake[] ids;
390 }
391 
392 /**
393   Sent when a reaction is added.
394 */
395 class MessageReactionAdd {
396   mixin Event;
397 
398   Snowflake messageID;
399 }