From f742f29fcc58084cb6026d3ec89f109396905701 Mon Sep 17 00:00:00 2001 From: Florian Stinglmayr Date: Thu, 11 Jul 2019 20:06:51 +0200 Subject: [PATCH] handle incoming messages through MESSAGE_CREATE --- libdc/include/dc/channel.h | 3 ++- libdc/include/dc/event.h | 2 ++ libdc/src/channel.c | 25 +++++++++++++++++ libdc/src/event.c | 10 +++---- libdc/src/session.c | 55 +++++++++++++++++++++++++++++--------- 5 files changed, 77 insertions(+), 18 deletions(-) diff --git a/libdc/include/dc/channel.h b/libdc/include/dc/channel.h index 9450249..a65d157 100644 --- a/libdc/include/dc/channel.h +++ b/libdc/include/dc/channel.h @@ -21,7 +21,7 @@ typedef enum { /* A direct message channel for 1:1 communication */ - CHANNEL_TYPE_DM_TEXT, + CHANNEL_TYPE_DM, /* A guild voice channel */ @@ -53,6 +53,7 @@ dc_channel_t dc_channel_from_json(json_t *j); char const *dc_channel_id(dc_channel_t c); dc_channel_type_t dc_channel_type(dc_channel_t c); +bool dc_channel_is_dm(dc_channel_t c); void dc_channel_set_type(dc_channel_t c, dc_channel_type_t t); size_t dc_channel_recipients(dc_channel_t c); diff --git a/libdc/include/dc/event.h b/libdc/include/dc/event.h index 1a5bdd6..d1da560 100644 --- a/libdc/include/dc/event.h +++ b/libdc/include/dc/event.h @@ -10,7 +10,9 @@ typedef struct dc_event_ *dc_event_t; typedef enum { DC_EVENT_TYPE_UNKNOWN = 0, DC_EVENT_TYPE_READY, + DC_EVENT_TYPE_MESSAGE_CREATE, + /* ^^^^^^ Make sure events are up there ^^^^^^^ */ DC_EVENT_TYPE_LAST, } dc_event_type_t; diff --git a/libdc/src/channel.c b/libdc/src/channel.c index 65b8cd6..1eac160 100644 --- a/libdc/src/channel.c +++ b/libdc/src/channel.c @@ -44,6 +44,7 @@ struct dc_channel_ */ char *application_id; + GHashTable *messages_byid; GPtrArray *messages; }; @@ -69,6 +70,11 @@ static void dc_channel_free(dc_channel_t c) c->messages = NULL; } + if (c->messages_byid != NULL) { + g_hash_table_unref(c->messages_byid); + c->messages_byid = NULL; + } + free(c); } @@ -87,6 +93,11 @@ dc_channel_t dc_channel_new(void) (GDestroyNotify)dc_unref ); + c->messages_byid = g_hash_table_new_full( + g_str_hash, g_str_equal, + free, dc_unref + ); + return dc_ref(c); } @@ -237,6 +248,14 @@ dc_channel_type_t dc_channel_type(dc_channel_t c) return c->type; } +bool dc_channel_is_dm(dc_channel_t c) +{ + return_if_true(c == NULL, false); + return (c->type == CHANNEL_TYPE_GROUP_DM || + c->type == CHANNEL_TYPE_DM + ); +} + void dc_channel_set_type(dc_channel_t c, dc_channel_type_t t) { return_if_true(c == NULL,); @@ -292,6 +311,12 @@ void dc_channel_add_messages(dc_channel_t c, dc_message_t *m, size_t s) size_t i = 0; for (i = 0; i < s; i++) { + char const *id = dc_message_id(m[i]); + if (g_hash_table_contains(c->messages_byid, id)) { + continue; + } + + g_hash_table_insert(c->messages_byid, strdup(id), dc_ref(m[i])); g_ptr_array_add(c->messages, dc_ref(m[i])); } diff --git a/libdc/src/event.c b/libdc/src/event.c index 7328b0e..6dac19f 100644 --- a/libdc/src/event.c +++ b/libdc/src/event.c @@ -60,15 +60,15 @@ json_t *dc_event_payload(dc_event_t e) dc_event_type_t dc_event_type_code(dc_event_t e) { - static char const *types[] = { - "UNKNOWN", - "READY", - NULL + static char const *types[DC_EVENT_TYPE_LAST] = { + [DC_EVENT_TYPE_UNKNOWN] = "UNKNOWN", + [DC_EVENT_TYPE_READY] = "READY", + [DC_EVENT_TYPE_MESSAGE_CREATE] = "MESSAGE_CREATE", }; int i = 0; - for (i = 0; types[i] != NULL; i++) { + for (i = 0; i < DC_EVENT_TYPE_LAST; i++) { if (strcmp(types[i], e->type) == 0) { return (dc_event_type_t)i; } diff --git a/libdc/src/session.c b/libdc/src/session.c index 3456844..b4d74cc 100644 --- a/libdc/src/session.c +++ b/libdc/src/session.c @@ -18,10 +18,12 @@ struct dc_session_ */ typedef void (*dc_session_handler_t)(dc_session_t s, dc_event_t e); static void dc_session_handle_ready(dc_session_t s, dc_event_t e); +static void dc_session_handle_message_create(dc_session_t s, dc_event_t e); static dc_session_handler_t handlers[DC_EVENT_TYPE_LAST] = { [DC_EVENT_TYPE_UNKNOWN] = NULL, [DC_EVENT_TYPE_READY] = dc_session_handle_ready, + [DC_EVENT_TYPE_MESSAGE_CREATE] = dc_session_handle_message_create, }; static void dc_session_free(dc_session_t s) @@ -46,6 +48,28 @@ static void dc_session_free(dc_session_t s) free(s); } +static void dc_session_handle_message_create(dc_session_t s, dc_event_t e) +{ + dc_message_t m = NULL; + json_t *r = dc_event_payload(e); + char const *id = NULL; + + m = dc_message_from_json(r); + goto_if_true(m == NULL, cleanup); + + id = dc_message_channel_id(m); + goto_if_true(m == NULL, cleanup); + + if (g_hash_table_contains(s->channels, id)) { + dc_channel_t c = g_hash_table_lookup(s->channels, id); + dc_channel_add_messages(c, &m, 1); + } + +cleanup: + + dc_unref(m); +} + static void dc_session_handle_ready(dc_session_t s, dc_event_t e) { json_t *r = dc_event_payload(e); @@ -276,21 +300,28 @@ dc_channel_t dc_session_make_channel(dc_session_t s, dc_account_t *r, /* check if we have the channel already with those recipients */ c = dc_session_channel_recipients(s, r, n); - return_if_true(c != NULL, c); - /* no? create new one - */ - if (!dc_api_create_channel(s->api, s->login, r, n, &c)) { - return NULL; + if (c == NULL) { + /* no? create new one + */ + if (!dc_api_create_channel(s->api, s->login, r, n, &c)) { + return NULL; + } + + return_if_true(c == NULL, NULL); + dc_session_add_channel(s, c); + /* unref once to match the proper ref count after + * dc_session_add_channel() + * BUG: if dc_session_add_channel() fails this is bad + */ + dc_unref(c); } - return_if_true(c == NULL, NULL); - dc_session_add_channel(s, c); - - /* unref once to match the proper ref count after dc_session_add_channel() - * BUG: if dc_session_add_channel() fails this is bad - */ - dc_unref(c); + if (dc_channel_messages(c) <= 0 && dc_channel_is_dm(c)) { + /* fetch some messages for it + */ + dc_api_get_messages(s->api, s->login, c); + } return c; }