Compare commits

...

2 Commits

Author SHA1 Message Date
Artem Savkov 1b9870a0ea Per-channel sync
Discord no longer seems to support per-guild sync, but per-channel sync
was added. Switch to that syncing user lists on channel join.

Fixes: #201

Signed-off-by: Artem Savkov <artem.savkov@gmail.com>
2020-02-06 13:32:26 +01:00
Artem Savkov 6500934bba Remove pending sync var
Since we are no longer syncing on connect - remove unused pending sync
variable.

Signed-off-by: Artem Savkov <artem.savkov@gmail.com>
2020-02-06 11:21:21 +01:00
5 changed files with 64 additions and 10 deletions

View File

@ -521,9 +521,6 @@ static void discord_handle_server(struct im_connection *ic, json_value *sinfo,
discord_handle_voice_state(ic, vsinfo, sdata->id);
}
}
discord_ws_sync_server(dd, sdata->id);
dd->pending_sync++;
} else {
server_info *sdata = get_server_by_id(dd, id);
if (sdata == NULL) {
@ -742,7 +739,7 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
if (cinfo == NULL) {
return;
}
time_t tstamp = use_tstamp ? parse_iso_8601(json_o_str(minfo, "timestamp")) : 0;
if (action == ACTION_CREATE) {
@ -803,6 +800,28 @@ void discord_handle_message(struct im_connection *ic, json_value *minfo,
}
}
static void parse_list_update_item(struct im_connection *ic,
const char *guild_id, const char *op,
json_value *item)
{
discord_data *dd = ic->proto_data;
json_value *member = json_o_get(item, "member");
json_value *uinfo = json_o_get(member, "user");
json_value *pinfo = json_o_get(member, "presence");
if (g_strcmp0(op, "DELETE") == 0) {
discord_handle_user(ic, uinfo, guild_id, ACTION_DELETE);
} else {
user_info *user = get_user(dd, json_o_str(uinfo, "id"), guild_id,
SEARCH_ID);
if (user == NULL) {
discord_handle_user(ic, uinfo, guild_id, ACTION_CREATE);
}
discord_handle_presence(ic, pinfo, guild_id);
}
}
gboolean discord_parse_message(struct im_connection *ic, gchar *buf, guint64 size)
{
discord_data *dd = ic->proto_data;
@ -947,11 +966,32 @@ gboolean discord_parse_message(struct im_connection *ic, gchar *buf, guint64 siz
discord_handle_presence(ic, pinfo, id);
}
}
} else if (g_strcmp0(event, "GUILD_MEMBER_LIST_UPDATE") == 0) {
json_value *data = json_o_get(js, "d");
json_value *ops = json_o_get(data, "ops");
const char *guild_id = json_o_str(data, "guild_id");
dd->pending_sync--;
if (dd->pending_sync < 1 && dd->state == WS_ALMOST_READY) {
dd->state = WS_READY;
imcb_connected(ic);
if (ops != NULL && ops->type == json_array) {
for (int oidx = 0; oidx < ops->u.array.length; oidx++) {
const char *op = json_o_str(ops->u.array.values[oidx], "op");
if (g_strcmp0(op, "SYNC") == 0) {
json_value *items = json_o_get(ops->u.array.values[oidx], "items");
if (items != NULL && items->type == json_array) {
for (int iidx = 0; iidx < items->u.array.length; iidx++) {
json_value *item = items->u.array.values[iidx];
if (item != NULL && json_o_get(item, "member") != NULL) {
parse_list_update_item(ic, guild_id, op, item);
}
}
}
} else {
json_value *item = json_o_get(ops->u.array.values[oidx], "item");
if (item != NULL && json_o_get(item, "member") != NULL) {
parse_list_update_item(ic, guild_id, op, item);
}
}
}
}
} else if (g_strcmp0(event, "VOICE_STATE_UPDATE") == 0) {
json_value *vsinfo = json_o_get(js, "d");

View File

@ -98,6 +98,16 @@ void discord_ws_sync_server(discord_data *dd, const char *id)
g_string_free(buf, TRUE);
}
void discord_ws_sync_channel(discord_data *dd, const char *guild_id,
const char *channel_id, unsigned int members)
{
GString *buf = g_string_new("");
g_string_printf(buf, "{\"op\":%d,\"d\":{\"guild_id\":\"%s\",\"typing\":true,\"activities\":true,\"channels\":{\"%s\":[[0,%u]]}}}",
OPCODE_REQUEST_SYNC_CHANNEL, guild_id, channel_id, members);
discord_ws_send_payload(dd, buf->str, buf->len);
g_string_free(buf, TRUE);
}
static gboolean discord_ws_heartbeat_timeout(gpointer data, gint fd,
b_input_condition cond)
{

View File

@ -29,7 +29,9 @@ typedef enum {
OPCODE_INVALID_SESSION,
OPCODE_HELLO,
OPCODE_HEARTBEAT_ACK,
OPCODE_REQUEST_SYNC
OPCODE_REQUEST_SYNC,
OPCODE_UNKNOWN,
OPCODE_REQUEST_SYNC_CHANNEL
} discord_opcode;
gboolean discord_ws_keepalive_loop(gpointer data, gint fd,
@ -40,3 +42,5 @@ void discord_ws_cleanup(discord_data *dd);
void discord_ws_set_status(struct im_connection *ic, gchar *status,
gchar *message);
void discord_ws_sync_server(discord_data *dd, const char *id);
void discord_ws_sync_channel(discord_data *dd, const char *guild_id,
const char *channel_id, unsigned int members);

View File

@ -195,6 +195,7 @@ struct groupchat *discord_chat_do_join(struct im_connection *ic,
if (cinfo != NULL && cinfo->type == CHANNEL_TEXT) {
sinfo = cinfo->to.channel.sinfo;
gc = imcb_chat_new(ic, cinfo->to.channel.name);
discord_ws_sync_channel(dd, sinfo->id, cinfo->id, 0);
if (is_auto_join) {
imcb_chat_name_hint(gc, room);

View File

@ -73,7 +73,6 @@ typedef struct _discord_data {
gint inpa;
gint wsid;
guint64 seq;
guint pending_sync;
GSList *pending_reqs;
GSList *pending_events;
gboolean reconnecting;