1 module dscord.gateway.packets;
2 
3 import std.stdio;
4 
5 import dscord.types.all;
6 
7 enum OPCode : ushort {
8   DISPATCH = 0,
9   HEARTBEAT = 1,
10   IDENTIFY = 2,
11   STATUS_UPDATE = 3,
12   VOICE_STATE_UPDATE = 4,
13   VOICE_SERVER_PING = 5,
14   RESUME = 6,
15   RECONNECT = 7,
16   REQUEST_GUILD_MEMBERS = 8,
17   INVALID_SESSION = 9,
18 };
19 
20 interface Serializable {
21   JSONValue serialize();
22 }
23 
24 class BasePacket {
25   OPCode      op;
26   JSONValue  data;
27   JSONValue  raw;
28 
29   JSONValue serialize(ushort op, JSONValue data) {
30     JSONValue res;
31     res["op"] = JSONValue(op);
32     res["d"] = data;
33     return res;
34   }
35 }
36 
37 class HeartbeatPacket : BasePacket, Serializable {
38   uint seq;
39 
40   this(uint seq) {
41     this.seq = seq;
42   }
43 
44   override JSONValue serialize() {
45     return super.serialize(OPCode.HEARTBEAT, JSONValue(this.seq));
46   }
47 }
48 
49 class ResumePacket : BasePacket, Serializable {
50   string  token;
51   string  session_id;
52   uint    seq;
53 
54   this(string token, string session_id, uint seq) {
55     this.token = token;
56     this.session_id = session_id;
57     this.seq = seq;
58   }
59 
60   override JSONValue serialize() {
61     JSONValue obj;
62     obj["token"] = JSONValue(token);
63     obj["session_id"] = JSONValue(session_id);
64     obj["seq"] = JSONValue(seq);
65     return super.serialize(OPCode.RESUME, obj);
66   }
67 }
68 
69 /* class StatusUpdate : BasePacket, Deserializable {} */
70 /* class VoiceServerPing : BasePacket, Deserializable {} */
71 /* class Resume : BasePacket, Deserializable {} */
72 /* class Reconnect : BasePacket, Deserializable {} */
73 /* class RequestGuildMembers : BasePacket, Deserializable {} */
74 /* class InvalidSession : BasePacket, Deserializable {} */
75 
76 class VoiceStateUpdatePacket : BasePacket, Serializable {
77   Snowflake  guildID;
78   Snowflake  channelID;
79   bool       self_mute;
80   bool       self_deaf;
81 
82   this(Snowflake guild_id, Snowflake channel_id, bool self_mute, bool self_deaf) {
83     this.guildID = guild_id;
84     this.channelID = channel_id;
85     this.self_mute = self_mute;
86     this.self_deaf = self_deaf;
87   }
88 
89   override JSONValue serialize() {
90     JSONValue res;
91     res["self_mute"] = JSONValue(this.self_mute);
92     res["self_deaf"] = JSONValue(this.self_deaf);
93     res["guild_id"] = this.guildID ? JSONValue(this.guildID) : JSONValue(null);
94     res["channel_id"] = this.channelID ? JSONValue(this.channelID) : JSONValue(null);
95     return super.serialize(OPCode.VOICE_STATE_UPDATE, res);
96   }
97 }
98 
99 class IdentifyPacket : BasePacket, Serializable {
100   string token;
101   bool compress = true;
102   ushort large_threshold = 250;
103 
104   this(string token) {
105     this.token = token;
106   }
107 
108   @property JSONValue properties() {
109     JSONValue prop;
110     prop["$os"] = "linux";
111     prop["$browser"] = "dscord";
112     prop["$device"] = "dscord";
113     prop["$referrer"] = "";
114     prop["$browser"] = "";
115     return prop;
116   }
117 
118   override JSONValue serialize() {
119     JSONValue res;
120     res["token"] = JSONValue(this.token);
121     res["properties"] = this.properties;
122     res["compress"] = JSONValue(this.compress);
123     res["large_threshold"] = JSONValue(this.large_threshold);
124     return super.serialize(OPCode.IDENTIFY, res);
125   }
126 }
127