discordjson.c (4015B)
1 #include <cjson/cJSON.h> 2 #include <stdbool.h> 3 #include <string.h> 4 5 #include "discordjson.h" 6 7 static bool parse_message_create(cJSON *data, DiscordEvent *event); 8 static char * cpstr(char *dest, const char *src); 9 10 char * 11 build_identify_json(const char *token, const int intents) 12 { 13 cJSON *json = cJSON_CreateObject(); 14 cJSON *data = cJSON_CreateObject(); 15 cJSON *props = cJSON_CreateObject(); 16 char *json_string; 17 18 if (json == NULL || data == NULL || props == NULL) { 19 cJSON_Delete(json); 20 cJSON_Delete(data); 21 cJSON_Delete(props); 22 return NULL; 23 } 24 25 cJSON_AddNumberToObject(json, "op", 2); 26 cJSON_AddItemToObject(json, "d", data); 27 cJSON_AddStringToObject(data, "token", token); 28 cJSON_AddNumberToObject(data, "intents", intents); 29 cJSON_AddItemToObject(data, "properties", props); 30 cJSON_AddStringToObject(props, "os", "linux"); 31 cJSON_AddStringToObject(props, "browser", "discordc"); 32 cJSON_AddStringToObject(props, "device", "discordc"); 33 34 json_string = cJSON_PrintUnformatted(json); 35 cJSON_Delete(json); 36 37 return json_string; 38 } 39 40 char * 41 build_heartbeat_json(const long seq) 42 { 43 cJSON *json = cJSON_CreateObject(); 44 char *json_string; 45 46 if (json == NULL) 47 return NULL; 48 49 cJSON_AddNumberToObject(json, "op", 1); 50 if (seq >= 0) 51 cJSON_AddNumberToObject(json, "d", seq); 52 else 53 cJSON_AddNullToObject(json, "d"); 54 55 json_string = cJSON_PrintUnformatted(json); 56 cJSON_Delete(json); 57 58 return json_string; 59 } 60 61 char * 62 build_message_json(const char *content) 63 { 64 cJSON *json = cJSON_CreateObject(); 65 char *json_string; 66 67 if (json == NULL) 68 return NULL; 69 70 cJSON_AddStringToObject(json, "content", content); 71 json_string = cJSON_PrintUnformatted(json); 72 cJSON_Delete(json); 73 74 return json_string; 75 } 76 77 bool 78 parse_gateway_json(const char *payload, DiscordEvent *event) 79 { 80 cJSON *json = cJSON_Parse(payload); 81 cJSON *op, *seq, *type, *data, *interval; 82 83 memset(event, 0, sizeof(*event)); 84 event->op = -1; 85 event->seq = -1; 86 87 if (json == NULL) 88 return false; 89 90 op = cJSON_GetObjectItem(json, "op"); 91 seq = cJSON_GetObjectItem(json, "s"); 92 type = cJSON_GetObjectItem(json, "t"); 93 data = cJSON_GetObjectItem(json, "d"); 94 95 if (cJSON_IsNumber(op)) 96 event->op = op->valueint; 97 if (cJSON_IsNumber(seq)) 98 event->seq = (long) seq->valuedouble; 99 100 if (event->op == 10 && cJSON_IsObject(data)) { 101 interval = cJSON_GetObjectItem(data, "heartbeat_interval"); 102 if (cJSON_IsNumber(interval)) 103 event->heartbeat_ms = (long) interval->valuedouble; 104 } else if (event->op == 1) { 105 event->heartbeat_requested = true; 106 } else if (event->op == 0 && cJSON_IsString(type) 107 && type->valuestring != NULL 108 && strcmp(type->valuestring, "READY") == 0) { 109 event->ready = true; 110 } else if (event->op == 0 && cJSON_IsString(type) 111 && type->valuestring != NULL 112 && strcmp(type->valuestring, "MESSAGE_CREATE") == 0 113 && cJSON_IsObject(data)) { 114 parse_message_create(data, event); 115 } 116 117 cJSON_Delete(json); 118 119 return true; 120 } 121 122 bool 123 parse_message_create(cJSON *data, DiscordEvent *event) 124 { 125 cJSON *id = cJSON_GetObjectItem(data, "id"); 126 cJSON *channel_id = cJSON_GetObjectItem(data, "channel_id"); 127 cJSON *content = cJSON_GetObjectItem(data, "content"); 128 cJSON *timestamp = cJSON_GetObjectItem(data, "timestamp"); 129 cJSON *author = cJSON_GetObjectItem(data, "author"); 130 cJSON *bot = author ? cJSON_GetObjectItem(author, "bot") : NULL; 131 132 if (!cJSON_IsString(id) || id->valuestring == NULL 133 || !cJSON_IsString(channel_id) 134 || channel_id->valuestring == NULL 135 || !cJSON_IsString(content) 136 || content->valuestring == NULL) 137 return false; 138 if (cJSON_IsBool(bot) && cJSON_IsTrue(bot)) 139 return false; 140 141 cpstr(event->message_id, id->valuestring); 142 cpstr(event->channel_id, channel_id->valuestring); 143 cpstr(event->content, content->valuestring); 144 if (cJSON_IsString(timestamp) && timestamp->valuestring != NULL) 145 cpstr(event->timestamp, timestamp->valuestring); 146 event->has_message = true; 147 148 return true; 149 } 150 151 char * 152 cpstr(char *dest, const char *src) 153 { 154 size_t cplen = strlen(src); 155 156 memcpy(dest, src, cplen); 157 dest[cplen] = '\0'; 158 159 return dest; 160 }