From c9689f08269ddff5e41a16d035c060eef0348e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20Luka=20=C5=A0ijanec?= Date: Wed, 22 Sep 2021 21:29:28 +0200 Subject: grem spat. se ne kompajla. bom popravil ju3. zrihtal DM --- src/api.c | 113 ++++++++++++++++++++++++++++++-------------------------------- src/h.c | 47 +++++++++++++++++--------- 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) -- cgit v1.2.3