summaryrefslogtreecommitdiffstats
path: root/src/api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/api.c')
-rw-r--r--src/api.c152
1 files changed, 106 insertions, 46 deletions
diff --git a/src/api.c b/src/api.c
index fbd9495..32a2058 100644
--- a/src/api.c
+++ b/src/api.c
@@ -24,6 +24,17 @@
cJSON_GetObjectItem(cJSON_GetObjectItem3(ro, na1, na2, na3), na4) : NULL)
#define cJSON_GetObjectItem5(r, n1, n2, n3, n4, n5) (cJSON_GetObjectItem4(r, n1, n2, n3, n4) ? \
cJSON_GetObjectItem(cJSON_GetObjectItem4(r, n1, n2, n3, n4), n5) : NULL)
+#define cJSON_GSV cJSON_GetStringValue
+#define cJSON_GNV cJSON_GetNumberValue
+#define cJSON_GAS cJSON_GetArraySize
+#define cJSON_GOI cJSON_GetObjectItem
+#define cJSON_GOI2 cJSON_GetObjectItem2
+#define cJSON_GOI3 cJSON_GetObjectItem3
+#define cJSON_GOI4 cJSON_GetObjectItem4
+#define cJSON_GOI5 cJSON_GetObjectItem5
+#define cJSON_GSV cJSON_GetStringValue
+#define cJSON_IN cJSON_IsNumber
+#define cJSON_AFE cJSON_ArrayForEach
unsigned char dc_api_identify_u[] = {
#include <identify.xxd>
};
@@ -37,19 +48,26 @@ void dc_api_stack (struct dc_api_io i) { /* stack output struct to be delivered
}
unsigned long long int dc_calculate_permissions (struct dc_user * u, struct dc_channel * c) {
unsigned long long int p = 0; /* note: this is NOT according to server's implementation of */
- struct dc_role ** role = &c->guild->role; /* permission parsing, but should suffice for most */
- while (*role) { /* cases. */
- if ((*role)->status & DC_EVERYONE || dc_find_user((*role)->users, (*role)->users_length, u->id))
+ struct dc_role ** role = &c->guild->role; /* perm parsing, but should suffice 4 most cases */
+ if (!*role) /* see struct dc_guild: if NULL then assume all permissions - a DM guild */
+ return DC_ALL_PERMISSIONS;
+ while (*role) {
+ if (DC_ROLE_EVERYONE(*role)
+ || dc_find_user((*role)->users, (*role)->users_length, u->id))
p |= (*role)->permissions;
role = &(*role)->next;
}
if (p & DC_ADMIN)
return DC_ALL_PERMISSIONS;
for (size_t i = 0; i < c->permissions_length; i++)
- if (c->permissions[i]->user == u || dc_find_user(c->permissions[i]->role->users, c->permissions[i]->role->users_length, u->id) || c->permissions[i]->role->status & DC_EVERYONE) {
+ if (c->permissions[i]->user
+ ? c->permissions[i]->user == u
+ : dc_find_user(c->permissions[i]->role->users,
+ c->permissions[i]->role->users_length, u->id)
+ || DC_ROLE_EVERYONE(c->permissions[i]->role)) {
p &= ~c->permissions[i]->deny;
p |= c->permissions[i]->allow;
- if ((*role)->permissions & DC_ADMIN)
+ if (p & DC_ADMIN)
return DC_ALL_PERMISSIONS;
}
return p;
@@ -57,15 +75,17 @@ unsigned long long int dc_calculate_permissions (struct dc_user * u, struct dc_c
struct dc_user * dc_parse_user (struct dc_user * dst, const cJSON * src) {
char * cp;
if (!dst)
- dst = dc_user_init();
- if ((cp = cJSON_GetStringValue(cJSON_GetObjectItem(src, "username"))))
+ dst = dc_user_init();
+ if ((cp = cJSON_GSV(cJSON_GOI(src, "username"))))
dst->username = strdup(cp);
- if ((cp = cJSON_GetStringValue(cJSON_GetObjectItem(src, "discriminator"))))
+ if ((cp = cJSON_GSV(cJSON_GOI(src, "discriminator"))))
dst->discriminator = atoi(cp);
- else
- dst->discriminator = -1;
- if ((cp = cJSON_GetStringValue(cJSON_GetObjectItem(src, "id"))))
+ if ((cp = cJSON_GSV(cJSON_GOI(src, "id"))))
dst->id = strtoull(cp, NULL, 10);
+ if (!dst->username || dst->discriminator == -1) { /* it's quite useless to store only ids */
+ dc_user_free(dst, DC_UNSET);
+ return NULL;
+ }
return dst;
}
static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us, void * in, size_t len) {
@@ -207,60 +227,100 @@ static int dc_lws_cb (struct lws * wsi, enum lws_callback_reasons rs, void * us,
fprintf(stdout, "%.*s", len, (const unsigned char *) in);
char * serialized = dc_json(pass->json, in, len);
while (serialized) {
- cJSON * json = cJSON_Parse(serialized);
- cJSON * obj;
+ cJSON * obj, * obje, * json = cJSON_Parse(serialized);
char * st;
if (getenv("DC_J")) {
st = cJSON_Print(json);
- if (st) {
- printf("%s\n", st);
- cJSON_free(st);
- } else
- fprintf(stderr, "_RECEIVE: _Print NULL: %s\n", serialized);
+ printf("%s\n", st);
+ cJSON_free(st);
+ }
+#define DC_PTYP(t) ((st = cJSON_GSV(cJSON_GOI(json, "t"))) && !strcmp(st, t))
+ if (DC_PTYP("READY") && getenv("DC_R")) {
+ printf("%s\n", (st = cJSON_Print(json)));
+ cJSON_free(st);
}
- pass->api_io.client->last_packet
- = cJSON_GetNumberValue(cJSON_GetObjectItem(json, "s"));
- if (cJSON_GetNumberValue(cJSON_GetObjectItem(json, "op"))
- == DC_PING) {
+ if ((st = cJSON_GSV(cJSON_GOI(json, "t"))))
+ fprintf(stderr, "t: %s\n", st);
+ pass->api_io.client->last_packet = cJSON_GNV(cJSON_GOI(json, "s"));
+ if (cJSON_GNV(cJSON_GOI(json, "op")) == DC_PING) {
pass->api_io.client->last_ping = 0;
dc_handle_ping(pass->api_io, NULL);
}
- if (cJSON_IsNumber((obj
- = cJSON_GetObjectItem2(json, "d", "heartbeat_interval")))) {
- pass->api_io.client->ping_interval
- = cJSON_GetNumberValue(obj)/1000-1;
+ if (cJSON_IN((obj = cJSON_GOI2(json, "d", "heartbeat_interval")))) {
+ pass->api_io.client->ping_interval = cJSON_GNV(obj)/1000-1;
pass->api_io.client->last_ping = 1;
}
#define DC_PARSEOBJ(w, object, also) if ((obj = object)) { \
struct dc_##w * w; \
- w = dc_parse_##w(NULL, obj); \
- w = dc_addr_##w(pass->api_io.program, \
+ if ((w = dc_parse_##w(NULL, obj))) \
+ w = dc_addr_##w(pass->api_io.program, \
DC_ISAE(pass->api_io.program->w##s), w, \
- DC_MAY_FREE | DC_REPLACE);\
+ DC_MAY_FREE | DC_REPLACE | DC_INCOMPLETE);\
also \
}
- DC_PARSEOBJ(user, cJSON_GetObjectItem2(json, "d", "user"),
- if (!pass->api_io.client->user) pass->api_io.client->user = user;)
- DC_PARSEOBJ(user, cJSON_GetObjectItem3(json, "d", "member", "user"),)
- DC_PARSEOBJ(user, cJSON_GetObjectItem2(json, "d", "author"), )
- DC_PARSEOBJ(user, cJSON_GetObjectItem3(json, "d",
- "referenced_message", "author"), )
-#define DC_PARSEARR(what, arr) cJSON_ArrayForEach(obj, arr) { \
+ DC_PARSEOBJ(user, cJSON_GOI2(json, "d", "user"),
+ if (!pass->api_io.client->user)
+ pass->api_io.client->user = user;
+ )
+ DC_PARSEOBJ(user, cJSON_GOI3(json, "d", "member", "user"),)
+ DC_PARSEOBJ(user, cJSON_GOI2(json, "d", "author"),)
+ DC_PARSEOBJ(user, cJSON_GOI3(json,
+ "d", "referenced_message", "author"),)
+#define DC_PARSEARR(what, arr, also) cJSON_AFE(obj, arr) { \
struct dc_##what * what = dc_parse_##what(NULL, obj); \
if (!what) \
continue; \
dc_addr_##what(pass->api_io.program, \
DC_ISAE(pass->api_io.program->what##s), \
- what, DC_MAY_FREE | DC_REPLACE); \
+ what, DC_MAY_FREE|DC_REPLACE|DC_INCOMPLETE);\
+ also \
}
- DC_PARSEARR(user, cJSON_GetObjectItem2(json, "d", "users"));
- DC_PARSEARR(user, cJSON_GetObjectItem2(json, "d", "mentions"));
- DC_PARSEARR(user, cJSON_GetObjectItem3(json, "d",
- "referenced_message", "mentions"));
-#define DC_PTYP(t) ((st = cJSON_GetStringValue(cJSON_GetObjectItem(json, "t"))) && !strcmp(st, t))
- if (DC_PTYP("MESSAGE_CREATE")) {
-
+ DC_PARSEARR(user, cJSON_GOI2(json, "d", "users"),)
+ DC_PARSEARR(user, cJSON_GOI2(json, "d", "mentions"),)
+ DC_PARSEARR(user, cJSON_GOI3(json,
+ "d", "referenced_message", "mentions"),)
+ cJSON_AFE(obj, cJSON_GOI2(json, "d", "private_channels")) {
+ if (/* !cJSON_GAS(cJSON_GOI(obj, "recipient_ids")) || */
+ /* commented. DMs with 0 members're shown /\ */ !cJSON_GSV(cJSON_GOI(obj, "id")) ||
+ !DC_CHANNEL_SUPPORTED(
+ /* cJSON is called many times here but I don't care */ cJSON_GNV(cJSON_GOI(obj, "type"))))
+ continue;
+ struct dc_channel * ch = dc_channel_init();
+ if ((st = cJSON_GSV(cJSON_GOI(obj, "name"))))
+ ch->name = strdup(st);
+ ch->type = cJSON_GNV(cJSON_GOI(obj, "type"));
+ ch->id = strtoull(cJSON_GSV(cJSON_GOI(obj, "id")), NULL, 10);
+ cJSON_AFE(obje, cJSON_GOI(obj, "recipient_ids")) {
+ struct dc_user * part = dc_user_init();
+ part->username = strdup("Private channel recipient");
+ part = dc_add_user(
+ DC_ISAE(pass->api_io.program->users),
+ /* no replace here. stored user can be better. */ part, DC_MAY_FREE);
+ DC_MR(ch->users); /* needn't dc_add here coz start */
+ ch->users[ch->users_length++] = part; /* empty ch. */
+ }
+ ch = dc_addr_channel(pass->api_io.program,
+ DC_ISAE(pass->api_io.program->channels), ch,
+ /* replace here. ours is better - fresher. */ DC_MAY_FREE | DC_REPLACE | DC_INCOMPLETE);
+ ch->guild = pass->api_io.client->guilds[0];
}
+ cJSON_AFE(obj, cJSON_GOI2(json, "d", "merged_members"))
+ cJSON_AFE(obje, cJSON_GOI(obj, "roles")) {
+ if (!(st = cJSON_GSV(obje)))
+ continue;
+ struct dc_role * role = dc_role_init();
+ role->id = strtoull(st, NULL, 10);
+ role = dc_add_role(
+ DC_ISAE(pass->api_io.program->roles),
+ role, DC_MAY_FREE);
+ struct dc_user * user = dc_user_init();
+ user->id = strtoull(cJSON_GSV(cJSON_GOI(
+ obj, "user_id")), NULL, 10);
+ user = dc_add_user(
+ DC_ISAE(pass->api_io.program->users),
+ /* again, no replace here, because we only have ID */ user, DC_MAY_FREE);
+ /* role may have users */ dc_add_user(DC_ISAE(role->users), user, DC_UNSET);
+ }
cJSON_Delete(json);
json = NULL;
serialized = dc_json(pass->json, NULL, 0);
@@ -292,7 +352,7 @@ void dc_api_i (struct dc_api_io i) { /* this function does not call attached fun
struct dc_lws_pass * pass;
assert(i.program);
if (i.program->lws_context && !(i.status & DC_FROM_LWS))
- lws_service(i.program->lws_context, 0); /* DO NOT CALL THIS FROM _cb! */
+ lws_service(i.program->lws_context, -1); /* DO NOT CALL THIS FROM _cb! */
switch (i.type) {
case DC_API_MESSAGE:
break;
@@ -440,7 +500,7 @@ struct dc_api_io dc_api_o (struct dc_api_io i /* for ->program */) {
return i;
}
if (i.program->lws_context)
- lws_service(i.program->lws_context, 0);
+ lws_service(i.program->lws_context, -1); /* with -1 this takes ~0 time */
for (size_t x = 0; x < i.program->clients_length; x++) {
if (i.program->clients[x]->status & DC_WS_ACTIVE && !i.program->clients[x]->pass
&& i.program->clients[x]->disconnect_time+DC_RECONNECT_DELAY<time(NULL)) {