1 #include "serialization.h"
2 #include "connection.h"
3 #include "discord_rpc.h"
4
5 template <typename T>
NumberToString(char * dest,T number)6 void NumberToString(char* dest, T number)
7 {
8 if (!number) {
9 *dest++ = '0';
10 *dest++ = 0;
11 return;
12 }
13 if (number < 0) {
14 *dest++ = '-';
15 number = -number;
16 }
17 char temp[32];
18 int place = 0;
19 while (number) {
20 auto digit = number % 10;
21 number = number / 10;
22 temp[place++] = '0' + (char)digit;
23 }
24 for (--place; place >= 0; --place) {
25 *dest++ = temp[place];
26 }
27 *dest = 0;
28 }
29
30 // it's ever so slightly faster to not have to strlen the key
31 template <typename T>
WriteKey(JsonWriter & w,T & k)32 void WriteKey(JsonWriter& w, T& k)
33 {
34 w.Key(k, sizeof(T) - 1);
35 }
36
37 struct WriteObject {
38 JsonWriter& writer;
WriteObjectWriteObject39 WriteObject(JsonWriter& w)
40 : writer(w)
41 {
42 writer.StartObject();
43 }
44 template <typename T>
WriteObjectWriteObject45 WriteObject(JsonWriter& w, T& name)
46 : writer(w)
47 {
48 WriteKey(writer, name);
49 writer.StartObject();
50 }
~WriteObjectWriteObject51 ~WriteObject() { writer.EndObject(); }
52 };
53
54 struct WriteArray {
55 JsonWriter& writer;
56 template <typename T>
WriteArrayWriteArray57 WriteArray(JsonWriter& w, T& name)
58 : writer(w)
59 {
60 WriteKey(writer, name);
61 writer.StartArray();
62 }
~WriteArrayWriteArray63 ~WriteArray() { writer.EndArray(); }
64 };
65
66 template <typename T>
WriteOptionalString(JsonWriter & w,T & k,const char * value)67 void WriteOptionalString(JsonWriter& w, T& k, const char* value)
68 {
69 if (value && value[0]) {
70 w.Key(k, sizeof(T) - 1);
71 w.String(value);
72 }
73 }
74
JsonWriteNonce(JsonWriter & writer,int nonce)75 static void JsonWriteNonce(JsonWriter& writer, int nonce)
76 {
77 WriteKey(writer, "nonce");
78 char nonceBuffer[32];
79 NumberToString(nonceBuffer, nonce);
80 writer.String(nonceBuffer);
81 }
82
JsonWriteRichPresenceObj(char * dest,size_t maxLen,int nonce,int pid,const DiscordRichPresence * presence)83 size_t JsonWriteRichPresenceObj(char* dest,
84 size_t maxLen,
85 int nonce,
86 int pid,
87 const DiscordRichPresence* presence)
88 {
89 JsonWriter writer(dest, maxLen);
90
91 {
92 WriteObject top(writer);
93
94 JsonWriteNonce(writer, nonce);
95
96 WriteKey(writer, "cmd");
97 writer.String("SET_ACTIVITY");
98
99 {
100 WriteObject args(writer, "args");
101
102 WriteKey(writer, "pid");
103 writer.Int(pid);
104
105 if (presence != nullptr) {
106 WriteObject activity(writer, "activity");
107
108 WriteOptionalString(writer, "state", presence->state);
109 WriteOptionalString(writer, "details", presence->details);
110
111 if (presence->startTimestamp || presence->endTimestamp) {
112 WriteObject timestamps(writer, "timestamps");
113
114 if (presence->startTimestamp) {
115 WriteKey(writer, "start");
116 writer.Int64(presence->startTimestamp);
117 }
118
119 if (presence->endTimestamp) {
120 WriteKey(writer, "end");
121 writer.Int64(presence->endTimestamp);
122 }
123 }
124
125 if ((presence->largeImageKey && presence->largeImageKey[0]) ||
126 (presence->largeImageText && presence->largeImageText[0]) ||
127 (presence->smallImageKey && presence->smallImageKey[0]) ||
128 (presence->smallImageText && presence->smallImageText[0])) {
129 WriteObject assets(writer, "assets");
130 WriteOptionalString(writer, "large_image", presence->largeImageKey);
131 WriteOptionalString(writer, "large_text", presence->largeImageText);
132 WriteOptionalString(writer, "small_image", presence->smallImageKey);
133 WriteOptionalString(writer, "small_text", presence->smallImageText);
134 }
135
136 if ((presence->partyId && presence->partyId[0]) || presence->partySize ||
137 presence->partyMax) {
138 WriteObject party(writer, "party");
139 WriteOptionalString(writer, "id", presence->partyId);
140 if (presence->partySize && presence->partyMax) {
141 WriteArray size(writer, "size");
142 writer.Int(presence->partySize);
143 writer.Int(presence->partyMax);
144 }
145 }
146
147 if ((presence->matchSecret && presence->matchSecret[0]) ||
148 (presence->joinSecret && presence->joinSecret[0]) ||
149 (presence->spectateSecret && presence->spectateSecret[0])) {
150 WriteObject secrets(writer, "secrets");
151 WriteOptionalString(writer, "match", presence->matchSecret);
152 WriteOptionalString(writer, "join", presence->joinSecret);
153 WriteOptionalString(writer, "spectate", presence->spectateSecret);
154 }
155
156 writer.Key("instance");
157 writer.Bool(presence->instance != 0);
158 }
159 }
160 }
161
162 return writer.Size();
163 }
164
JsonWriteHandshakeObj(char * dest,size_t maxLen,int version,const char * applicationId)165 size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
166 {
167 JsonWriter writer(dest, maxLen);
168
169 {
170 WriteObject obj(writer);
171 WriteKey(writer, "v");
172 writer.Int(version);
173 WriteKey(writer, "client_id");
174 writer.String(applicationId);
175 }
176
177 return writer.Size();
178 }
179
JsonWriteSubscribeCommand(char * dest,size_t maxLen,int nonce,const char * evtName)180 size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
181 {
182 JsonWriter writer(dest, maxLen);
183
184 {
185 WriteObject obj(writer);
186
187 JsonWriteNonce(writer, nonce);
188
189 WriteKey(writer, "cmd");
190 writer.String("SUBSCRIBE");
191
192 WriteKey(writer, "evt");
193 writer.String(evtName);
194 }
195
196 return writer.Size();
197 }
198
JsonWriteUnsubscribeCommand(char * dest,size_t maxLen,int nonce,const char * evtName)199 size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
200 {
201 JsonWriter writer(dest, maxLen);
202
203 {
204 WriteObject obj(writer);
205
206 JsonWriteNonce(writer, nonce);
207
208 WriteKey(writer, "cmd");
209 writer.String("UNSUBSCRIBE");
210
211 WriteKey(writer, "evt");
212 writer.String(evtName);
213 }
214
215 return writer.Size();
216 }
217
JsonWriteJoinReply(char * dest,size_t maxLen,const char * userId,int reply,int nonce)218 size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce)
219 {
220 JsonWriter writer(dest, maxLen);
221
222 {
223 WriteObject obj(writer);
224
225 WriteKey(writer, "cmd");
226 if (reply == DISCORD_REPLY_YES) {
227 writer.String("SEND_ACTIVITY_JOIN_INVITE");
228 }
229 else {
230 writer.String("CLOSE_ACTIVITY_JOIN_REQUEST");
231 }
232
233 WriteKey(writer, "args");
234 {
235 WriteObject args(writer);
236
237 WriteKey(writer, "user_id");
238 writer.String(userId);
239 }
240
241 JsonWriteNonce(writer, nonce);
242 }
243
244 return writer.Size();
245 }
246