summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Luka Šijanec <anton@sijanec.eu>2021-09-22 21:29:28 +0200
committerAnton Luka Šijanec <anton@sijanec.eu>2021-09-22 21:29:28 +0200
commitc9689f08269ddff5e41a16d035c060eef0348e4a (patch)
treeaee05abe21b99823401266538222f5ceb9321f39
parenttested json parsers until dm (diff)
downloaddiscord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar.gz
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar.bz2
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar.lz
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar.xz
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.tar.zst
discord.c-c9689f08269ddff5e41a16d035c060eef0348e4a.zip
-rw-r--r--src/api.c113
-rw-r--r--src/h.c47
2 files changed, 85 insertions, 75 deletions
diff --git a/src/api.c b/src/api.c
index c8b44bc..3e70684 100644
--- a/src/api.c
+++ b/src/api.c
@@ -73,8 +73,6 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn
}
}
if (reason & LEJP_FLAG_CB_IS_VALUE && (path == DC_JSON_ME_USERNAME || path == DC_JSON_ME_ID || path == DC_JSON_ME_DISCRIMINATOR) && (!client->user || !client->user->username || !client->user->id || client->user->status & DC_INCOMPLETE)) { /* if filled, then it's someone else */
- if (getenv("DC_R")) /* detect user parser */
- raise(SIGINT);
if (!client->user) { /* on first d.user this is our user, subsequent are someone else! */
DC_MR(program->users); /* don't need DC_IN_PROGRESS, we have ref in cl */
program->users[program->users_length++] = client->user = dc_user_init();
@@ -113,79 +111,57 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn
else /* if something goes wrong - if those handlers do not null user, IO_MEMB_GC will */
pass->api_io.user->status |= DC_EXPLICIT_NULL; /* but will not free. */
} /* user parsing end */
- if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_START) { /* client->guild[0] always */
- fprintf(stderr, "new DM start parsing object\n"); /* exists */
- /* dc_channel_free(pass->api_io.channel); */ /* parser branches must not leave */
- pass->api_io.channel = dc_channel_init(); /* behind any content in api_io */
+ if ((path == DC_JSON_DM || path == DC_JSON_GUILD_CHANNEL) && reason == LEJPCB_OBJECT_START) {
+ pass->api_io.channel = dc_channel_init();
pass->api_io.channel->status |= DC_IN_PROGRESS;
- pass->api_io.channel->guild = client->guilds[0];
}
if (path == DC_JSON_DM && reason == LEJPCB_OBJECT_END) {
struct dc_channel ** channel = &client->guilds[0]->channel; /* 1. guild = DMs */
while (*channel)
channel = &(*channel)->next;
- pass->api_io.channel->status &= ~(DC_IN_PROGRESS);
- free(pass->api_io.channel->name);
- pass->api_io.channel->name = strdup("");
+ pass->api_io.channel->guild = client->guilds[0]; /* client->guilds[0] always exists */
+ pass->api_io.channel->status &= ~DC_IN_PROGRESS;
+ free(pass->api_io.channel->topic);
+ pass->api_io.channel->topic = strdup("");
for (size_t i = 0; i < pass->api_io.channel->users_length; i++) {
- pass->api_io.channel->name = realloc(pass->api_io.channel->name, strlen(pass->api_io.channel->name)+strlen(pass->api_io.channel->users[i]->username)+1+2+1+4);
+ pass->api_io.channel->topic = realloc(pass->api_io.channel->topic, strlen(pass->api_io.channel->topic) + strlen(pass->api_io.channel->users[i]->username) + 1 + 2 + 1 + 4);
char buf[64];
- sprintf(buf, "#%d%s", pass->api_io.channel->users[i]->discriminator, i < pass->api_io.channel->users_length ? ", " : "");
- strcat(pass->api_io.channel->name, pass->api_io.channel->users[i]->username);
- strcat(pass->api_io.channel->name, buf);
+ snprintf(buf, 63, "#%04d%s", pass->api_io.channel->users[i]->discriminator, i+1 < pass->api_io.channel->users_length ? ", " : "");
+ strcat(pass->api_io.channel->topic, pass->api_io.channel->users[i]->username);
+ strcat(pass->api_io.channel->topic, buf);
}
+ if ((struct dc_channel * ch = dc_find_channel(program->channels, program->channels_length, pass->api_io.channel->id)))
+ DC_TRANSFER_CHANNEL(pass->api_io.channel->id, ch);
pass->api_io.channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE);
- fprintf(stderr, "new DM id=%llu (:\n", pass->api_io.channel->id);
- if ((*channel = dc_find_ll_channel(client->guilds[0]->channel, pass->api_io.channel->id))) {
- fprintf(stderr, "DM already in LL, id=%llu\n", pass->api_io.channel->id);
- if (*channel != pass->api_io.channel) {
- dc_channel_free(*channel, DC_REPLACE);
- memmove(*channel, pass->api_io.channel, sizeof(**channel));
- }
+ if (!dc_find_ll_channel(client->guilds[0]->channel, pass->api_io.channel->id)) {
+ fprintf(stderr, "new DM id=%llu (:\n", pass->api_io.channel->id);
+ *channel = pass->api_io.channel;
}
pass->api_io.channel->guild = client->guilds[0];
pass->api_io.channel = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
}
-#if 0
- if (startswith(ctx->path, dc_json_paths[DC_JSON_DM_USER])) { /* we don't DC_REPLACE here bcoz */
- if (path == DC_JSON_DM_USER && reason == LEJPCB_OBJECT_START) { /* users never update. */
- pass->api_io.user = dc_user_init();
- pass->api_io.user->status |= DC_IN_PROGRESS;
- }
- if (path == DC_JSON_DM_USER && reason == LEJPCB_OBJECT_END) {
- fprintf(stderr, "new DM participant (:\n");
- pass->api_io.user = dc_addr_user(program, DC_ISAE(program->users), pass->api_io.user, DC_MAY_FREE); /* add to program ISA or find existing */
- pass->api_io.user = dc_addr_user(program, DC_ISAE(pass->api_io.channel->users), pass->api_io.user, DC_UNSET); /* do not free, because it's already in program */
- pass->api_io.user->status &= ~(DC_IN_PROGRESS); /* somehow invalid 4 byte rw? */
- pass->api_io.user = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
- }
- if (reason & LEJP_FLAG_CB_IS_VALUE && pass->api_io.channel)
- switch (path) {
- case DC_JSON_DM_USER_ID:
- pass->api_io.user->id = strtoull(ctx->buf, NULL, 10);
- break;
- case DC_JSON_DM_USER_DISCRIMINATOR:
- pass->api_io.user->discriminator = atoi(ctx->buf);
- break;
- case DC_JSON_DM_USER_NAME:
- if (!pass->api_io.user->username)
- pass->api_io.user->username = strdup(ctx->buf);
- break;
- default:
- break;
- }
+ if (path == DC_JSON_GUILD_CHANNEL && reason == LEJPCB_OBJECT_END) {
+ struct dc_channel ** channel = &pass->api_io.guild->channel;
+ while (*channel)
+ channel = &(*channel)->next;
+ pass->api_io.channel = dc_addr_channel(program, DC_ISAN, pass->api_io.channel, DC_MAY_FREE | DC_REPLACE);
+ pass->api_io.channel = NULL;
}
- if (startswith(ctx->path, dc_json_paths[DC_JSON_GUILD])) {
- if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_START) {
- /* pass->api_io.guild = dc_guild_init();
- pass->api_io.guild->status |= DC_IN_PROGRESS; */
- }
- if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_END) {
- fprintf(stderr, "new guild");
- /* pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE); */
- }
+ if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_START) { /* guild parsing start */
+ pass->api_io.guild = dc_guild_init();
+ pass->api_io.guild->status |= DC_IN_PROGRESS;
}
-#endif
+ if (path == DC_JSON_GUILD && reason == LEJPCB_OBJECT_END) {
+ pass->api_io.guild->status &= ~DC_IN_PROGRESS;
+ pass->api_io.guild = dc_addr_guild(program, DC_ISAE(program->guilds), pass->api_io.guild, DC_MAY_FREE | DC_REPLACE); /* when we replace, the new guild's channels' ptrs */
+ struct dc_channel ** channel = &pass->api_io.guild->channel; /* to guild will be inv. */
+ while (*channel) {
+ *(channel)->guild = pass->api_io.guild;
+ channel = &(*channel)->next;
+ }
+ dc_add_guild(program, DC_ISAE(client->guilds), pass->api_io.guild, DC_UNSET);
+ pass->api_io.guild = NULL; /* we're done, NULL it or PROBLEMS WILL APPEAR!!! */
+ } /* guild parsing end */
if (reason & LEJP_FLAG_CB_IS_VALUE)
switch (path) {
case DC_JSON_FRIEND: /* we assume we get users[] before relationships[] */
@@ -214,13 +190,32 @@ signed char dc_json_cb (struct lejp_ctx * ctx, char reason) { /* to prevent warn
pass->api_io.user->discriminator = atoi(ctx->buf);
break; /* yeah, we don't care about nicknames */
case DC_JSON_DM_TYPE:
+ case DC_JSON_GUILD_CHANNEL_TYPE:
if (pass->api_io.channel)
pass->api_io.channel->type = atoi(ctx->buf);
break;
case DC_JSON_DM_ID:
+ case DC_JSON_GUILD_CHANNEL_ID:
if (pass->api_io.channel)
pass->api_io.channel->id = strtoull(ctx->buf, NULL, 10);
break;
+ case DC_JSON_DM_NAME:
+ case DC_JSON_GUILD_CHANNEL_NAME:
+ if (pass->api_io.channel)
+ pass->api_io.channel->name = strdup(ctx->buf);
+ break;
+ case DC_JSON_GUILD_NAME:
+ if (pass->api_io.guild)
+ pass->api_io.guild->name = strdup(ctx->buf);
+ break;
+ case DC_JSON_GUILD_ID:
+ if (pass->api_io.guild)
+ pass->api_io.guild->id = strtoull(ctx->buf, NULL, 10);
+ break;
+ case DC_JSON_GUILD_CHANNEL_TOPIC:
+ if (pass->api_io.channel)
+ pass->api_io.channel->topic = strdup(ctx->buf);
+ break;
default:
break;
}
diff --git a/src/h.c b/src/h.c
index 1a0988b..fd0d40a 100644
--- a/src/h.c
+++ b/src/h.c
@@ -17,6 +17,11 @@
#define DC_LWS_MAX_FD 64 /* max file descriptors LWS will have open. if unset, LWS acquires all unused */
#define DC_LWS_MAX_HEADER_LENGTH 64 /* _MAX_HEADER_LENGTH*_HEADERS_LENGTH is allocated for every reque */
#define DC_WS_PING_FORMAT "{\"op\":1,\"d\":%lld}"
+#ifdef DC_UI_GTK
+#define DC_IF_UI_GTK(...) __VA_ARGS__
+#else
+#define DC_IF_UI_GTK(...)
+#endif
/* it's strongly recommended to calloc structs during initialization. */
enum dc_status { /* theese are flags and should be and-checked */
DC_UNSET = 0, /* default value when enum is calloced */
@@ -48,12 +53,13 @@ enum dc_status { /* theese are flags and should be and-checked */
DC_INTERNAL = DC_FROM_LWS | DC_FROM_API, /* call originates from an internal function */
}; /* note: when checking status, first check for DC_OK, if it's set then disregard errors! */
enum dc_permissions { /* other permissions exist, but are not implemented/understood */
- DC_ALL_PERMISSIONS = 1 << 3, /* this is incredibly retarded, why is this SEPARATE?!? - admins */
+ DC_ADMIN = 1 << 3, /* this is incredibly retarded, why is this SEPARATE?!? - admins */
DC_CHANNEL_VIEW = 1 << 10, /* all enum fields here have values same as the server values */
DC_MESSAGE_SEND = 1 << 11,
DC_MESSAGE_READ = 1 << 16, /* na tistem vegova serverju sem lahko pošiljal ne pa bral sporočil */
DC_VOICE_LISTEN = 1 << 20,
- DC_VOICE_SPEAK = 1 << 21
+ DC_VOICE_SPEAK = 1 << 21,
+ DC_ALL_PERMISSIONS = DC_ADMIN | DC_CHANNEL_VIEW | DC_MESSAGE_SEND | DC_MESSAGE_READ | DC_VOICE_LISTEN | DC_VOICE_SPEAK /* admins get this@parsing, UI need not check admin separatly */
}; /* all enum fields here have values same as the values that the server sends */
enum dc_channel_type { /* other types exist, but are not implemented/understood */
DC_GC = 0, /* guild channel */
@@ -187,10 +193,15 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c
DC_JSON_DM,
DC_JSON_DM_TYPE,
DC_JSON_DM_ID,
+ DC_JSON_DM_NAME, /* yes, some do have names. */
DC_JSON_DM_USER, /* this is the ID */
DC_JSON_GUILD,
DC_JSON_GUILD_NAME,
DC_JSON_GUILD_ID,
+ DC_JSON_GUILD_ROLE,
+ DC_JSON_GUILD_ROLE_PERMISSION,
+ DC_JSON_GUILD_ROLE_NAME,
+ DC_JSON_GUILD_ROLE_ID,
DC_JSON_GUILD_CHANNEL,
DC_JSON_GUILD_CHANNEL_TYPE,
DC_JSON_GUILD_CHANNEL_NAME,
@@ -201,10 +212,6 @@ enum dc_json_paths { /* lws reduces the following char array to uint8_t, so we c
DC_JSON_GUILD_CHANNEL_PERMISSION_ID,
DC_JSON_GUILD_CHANNEL_PERMISSION_DENY,
DC_JSON_GUILD_CHANNEL_PERMISSION_ALLOW,
- DC_JSON_GUILD_ROLE,
- DC_JSON_GUILD_ROLE_PERMISSION,
- DC_JSON_GUILD_ROLE_NAME,
- DC_JSON_GUILD_ROLE_ID,
DC_JSON_MESSAGE,
DC_JSON_MESSAGE_ATTACHMENTS,
DC_JSON_MESSAGE_ID,
@@ -268,10 +275,15 @@ char * dc_json_paths[] = { /* array of paths we are interested in */
"d.private_channels[]",
"d.private_channels[].type",
"d.private_channels[].id",
- "d.private_channels[].recipients_ids[]",
+ "d.private_channels[].name",
+ "d.private_channels[].recipient_ids",
"d.guilds[]",
"d.guilds[].name",
"d.guilds[].id",
+ "d.guilds[].roles[]",
+ "d.guilds[].roles[].permissions",
+ "d.guilds[].roles[].name",
+ "d.guilds[].roles[].id",
"d.guilds[].channels[]",
"d.guilds[].channels[].type",
"d.guilds[].channels[].name",
@@ -282,10 +294,6 @@ char * dc_json_paths[] = { /* array of paths we are interested in */
"d.guilds[].channels[].permission_overwrites.id",
"d.guilds[].channels[].permission_overwrites.deny",
"d.guilds[].channels[].permission_overwrites.allow",
- "d.guilds[].roles[]",
- "d.guilds[].roles[].permissions",
- "d.guilds[].roles[].name",
- "d.guilds[].roles[].id",
"d",
"d.attachments[]",
"d.id",
@@ -396,8 +404,7 @@ struct dc_guild {
struct dc_client * client; /* nofree */
struct dc_channel * channel; /* nofree - first channel */
struct dc_role * role; /* nofree - first role. NOTE: role->id == guild->id => @everyone role */
- enum dc_permissions permissions;
- enum dc_status status;
+ enum dc_status status; /* /\ if NULL then assume all permissions - a DM guild */
#ifdef DC_UI_GTK
GtkTreeIter iter; /* NOTE: only works when GtkTreeModel has a flag GTK_TREE_MODEL_ITERS_PERSIST; see paragraph 8 of description of file:///usr/share/doc/libgtk-3-doc/gtk3/GtkTreeModel.html */
gboolean is_iter;
@@ -458,7 +465,7 @@ struct dc_channel {
unsigned long long int id;
enum dc_channel_type type;
struct dc_guild * guild; /* nofree */
- struct dc_channel * next; /* nofree - next channel (linked list of all guilds of dc_guild) */
+ struct dc_channel * next; /* nofree - next channel (linked list of all channel of dc_guild) */
struct dc_message * message; /* nofree - first message (ordered by time) */
struct dc_permission * permission; /* nofree - first permission */
enum dc_status status;
@@ -510,7 +517,7 @@ struct dc_role {
DC_STRUCT_PREFIX
char * name; /* yesfree */
unsigned long long int id;
- enum dc_permissions permissions;
+ enum dc_permissions permissions; /* this are guild permission */
struct dc_guild * guild; /* nofree - owner of the role */
struct dc_role * next; /* nofree - next role (linked list of all roles of dc_guild) */
struct dc_role_membership * role_membership; /* nofree - first role membership ll) */
@@ -563,7 +570,7 @@ void dc_user_free (struct dc_user * s, enum dc_status t) {
free(s);
}
struct dc_permission { /* permissions can be individual on a per-channel basis */
- DC_STRUCT_PREFIX
+ DC_STRUCT_PREFIX /* assume all permissions */
enum dc_permissions allow;
enum dc_permissions deny;
unsigned long long int id; /* to whom does this permission apply */
@@ -771,3 +778,11 @@ DC_FIND_LL_X(channel)
DC_GEN_X(guild, GUILD)
#define DC_ISAE(a) &a, &a##_sizeof, &a##_length /* ISA Expand */
#define DC_ISAN NULL, NULL, NULL /* ISA NULL */
+#define DC_TRANSFER_CHANNEL(n, o) do { /* n is going to DC_REPLACE o, transfer important data */ \
+ n->message = o->message; \
+ n->next = o->next; \
+ DC_IF_UI_GTK( \
+ memcpy(pass->api_io.channel->iter, ch->iter, sizeof(GtkTreeIter)); \
+ pass->api_io.channel->is_iter = ch->is_iter; \
+ ) \
+ } while(0)