discordc

discordc - C Discord ping bot.
git clone git://git.beep.wimdupont.com/discordc.git
Log | Files | Refs | README | LICENSE

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 }