1 /**
2   Implementations of Discord events.
3 */
4 
5 module dscord.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 dscord.types,
15        dscord.gateway,
16        dscord.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   User  user;
170 }
171 
172 /**
173   Sent when a guild ban is removed.
174 */
175 class GuildBanRemove {
176   mixin Event;
177 
178   User  user;
179 }
180 
181 /**
182   Sent when a guilds emojis are updated.
183 */
184 class GuildEmojisUpdate {
185   mixin Event;
186 }
187 
188 /**
189   Sent when a guilds integrations are updated.
190 */
191 class GuildIntegrationsUpdate {
192   mixin Event;
193 }
194 
195 /**
196   Sent in response to RequestGuildMembers.
197 */
198 
199 class GuildMembersChunk {
200   mixin Event;
201 
202   Snowflake guildID;
203   GuildMember[] members;
204 
205 /+
206   void load(JSONDecoder obj) {
207     obj.keySwitch!("guild_id", "members")(
208       { this.guildID = readSnowflake(obj); },
209       { loadMany!GuildMember(this.client, obj, (m) { this.members ~= m; }); },
210     );
211 
212     auto guild = this.client.state.guilds.get(this.guildID);
213     foreach (member; this.members) {
214       member.guild = guild;
215     }
216   }
217 +/
218 }
219 
220 /**
221   Sent when a member is added to a guild.
222 */
223 class GuildMemberAdd {
224   mixin Event;
225 
226   @JSONFlat
227   GuildMember  member;
228 }
229 
230 /**
231   Sent when a member is removed from a guild.
232 */
233 class GuildMemberRemove {
234   mixin Event;
235 
236   Snowflake  guildID;
237   User       user;
238 }
239 
240 /**
241   Sent when a guild member is updated.
242 */
243 class GuildMemberUpdate {
244   mixin Event;
245 
246   @JSONFlat
247   GuildMember  member;
248 }
249 
250 /**
251   Sent when a guild role is created.
252 */
253 class GuildRoleCreate {
254   mixin Event;
255 
256   Snowflake  guildID;
257   Role       role;
258 }
259 
260 /**
261   Sent when a guild role is updated.
262 */
263 class GuildRoleUpdate {
264   mixin Event;
265 
266   Snowflake  guildID;
267   Role       role;
268 }
269 
270 /**
271   Sent when a guild role is deleted.
272 */
273 class GuildRoleDelete {
274   mixin Event;
275 
276   Snowflake  guildID;
277   Role       role;
278 }
279 
280 /**
281   Sent when a message is created.
282 */
283 class MessageCreate {
284   mixin Event;
285 
286   @JSONFlat
287   Message  message;
288 
289   // Reference to the command event
290   @JSONIgnore
291   CommandEvent commandEvent;
292 }
293 
294 /**
295   Sent when a message is updated.
296 */
297 class MessageUpdate {
298   mixin Event;
299 
300   @JSONFlat
301   Message  message;
302 }
303 
304 /**
305   Sent when a message is deleted.
306 */
307 class MessageDelete {
308   mixin Event;
309 
310   Snowflake  id;
311   Snowflake  channelID;
312 }
313 
314 /**
315   Sent when a users presence is updated.
316 */
317 class PresenceUpdate {
318   mixin Event;
319 
320   @JSONFlat
321   Presence presence;
322 }
323 
324 /**
325   Sent when a user starts typing.
326 */
327 class TypingStart {
328   mixin Event;
329 
330   Snowflake  channelID;
331   Snowflake  userID;
332   ulong      timestamp;
333 }
334 
335 /**
336   Sent when this users settings are updated.
337 */
338 class UserSettingsUpdate {
339   mixin Event;
340 }
341 
342 /**
343   Sent when this user is updated.
344 */
345 class UserUpdate {
346   mixin Event;
347 }
348 
349 /**
350   Sent when a voice state is updated.
351 */
352 class VoiceStateUpdate {
353   mixin Event;
354 
355   @JSONFlat
356   VoiceState  state;
357 }
358 
359 /**
360   Sent when a voice server is updated.
361 */
362 class VoiceServerUpdate {
363   mixin Event;
364 
365   string     token;
366   string     endpoint;
367   Snowflake  guildID;
368 }
369 
370 /**
371   Sent when a channels pins are updated.
372 */
373 class ChannelPinsUpdate {
374   mixin Event;
375 
376   Snowflake  channelID;
377   string     lastPinTimestamp;
378 }
379 
380 /**
381   Sent when a bulk set of messages gets deleted from a channel.
382 */
383 class MessageDeleteBulk {
384   mixin Event;
385 
386   Snowflake channelID;
387   Snowflake[] ids;
388 }