From d86a386edd35764aa50e871add208cb8e5be93b7 Mon Sep 17 00:00:00 2001 From: Florian Stinglmayr Date: Sat, 20 Jul 2019 12:51:07 +0200 Subject: [PATCH] introduce a /join command for guild text channels --- libdc/include/dc/guild.h | 1 + libdc/include/dc/session.h | 1 + libdc/src/guild.c | 17 +++++++++- libdc/src/session.c | 18 ++++++++++ ncdc/CMakeLists.txt | 1 + ncdc/include/ncdc/cmds.h | 1 + ncdc/include/ncdc/mainwindow.h | 8 ++++- ncdc/src/cmds.c | 1 + ncdc/src/join.c | 62 ++++++++++++++++++++++++++++++++++ ncdc/src/mainwindow.c | 53 +++++++++++++++++++++++++++++ ncdc/src/msg.c | 31 ++--------------- ncdc/src/util.c | 2 +- 12 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 ncdc/src/join.c diff --git a/libdc/include/dc/guild.h b/libdc/include/dc/guild.h index ab3b13a..8a6a498 100644 --- a/libdc/include/dc/guild.h +++ b/libdc/include/dc/guild.h @@ -16,6 +16,7 @@ dc_guild_t dc_guild_from_json(json_t *j); size_t dc_guild_channels(dc_guild_t d); dc_channel_t dc_guild_nth_channel(dc_guild_t d, size_t idx); +dc_channel_t dc_guild_channel_by_name(dc_guild_t g, char const *name); char const *dc_guild_name(dc_guild_t d); void dc_guild_set_name(dc_guild_t d, char const *val); diff --git a/libdc/include/dc/session.h b/libdc/include/dc/session.h index 00cba59..479ee8c 100644 --- a/libdc/include/dc/session.h +++ b/libdc/include/dc/session.h @@ -98,6 +98,7 @@ dc_channel_t dc_session_channel_recipients(dc_session_t s, */ void dc_session_add_guild(dc_session_t s, dc_guild_t g); GHashTable *dc_session_guilds(dc_session_t s); +dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name); /** * comparision functions for sorting, and finding diff --git a/libdc/src/guild.c b/libdc/src/guild.c index f6fd739..1eb58de 100644 --- a/libdc/src/guild.c +++ b/libdc/src/guild.c @@ -58,7 +58,7 @@ dc_guild_t dc_guild_from_json(json_t *j) g->id = strdup(json_string_value(val)); /* there is a ton of more information here, that we should look - * add, including "member_count", "owner_id", but for channels + * to add, including "member_count", "owner_id", but for now "channels" * will do nicely */ val = json_object_get(j, "channels"); @@ -91,6 +91,21 @@ dc_channel_t dc_guild_nth_channel(dc_guild_t d, size_t idx) return g_ptr_array_index(d->channels, idx); } +dc_channel_t dc_guild_channel_by_name(dc_guild_t g, char const *name) +{ + return_if_true(g == NULL || name == NULL, NULL); + size_t i = 0; + + for (i = 0; i < g->channels->len; i++) { + dc_channel_t c = g_ptr_array_index(g->channels, i); + if (strcmp(dc_channel_name(c), name) == 0) { + return c; + } + } + + return NULL; +} + char const *dc_guild_name(dc_guild_t d) { return_if_true(d == NULL, NULL); diff --git a/libdc/src/session.c b/libdc/src/session.c index 3e507d5..ad57418 100644 --- a/libdc/src/session.c +++ b/libdc/src/session.c @@ -450,3 +450,21 @@ void dc_session_add_guild(dc_session_t s, dc_guild_t g) */ } } + +dc_guild_t dc_session_guild_by_name(dc_session_t s, char const *name) +{ + return_if_true(s == NULL || s->guilds == NULL || name == NULL, NULL); + + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, s->guilds); + while (g_hash_table_iter_next(&iter, &key, &value)) { + dc_guild_t g = (dc_guild_t)value; + if (strcmp(dc_guild_name(g), name) == 0) { + return g; + } + } + + return NULL; +} diff --git a/ncdc/CMakeLists.txt b/ncdc/CMakeLists.txt index 7b01352..889d1bc 100644 --- a/ncdc/CMakeLists.txt +++ b/ncdc/CMakeLists.txt @@ -19,6 +19,7 @@ SET(SOURCES "src/config.c" "src/friends.c" "src/input.c" + "src/join.c" "src/keycodes.c" "src/login.c" "src/logout.c" diff --git a/ncdc/include/ncdc/cmds.h b/ncdc/include/ncdc/cmds.h index 01b265f..86430a1 100644 --- a/ncdc/include/ncdc/cmds.h +++ b/ncdc/include/ncdc/cmds.h @@ -32,6 +32,7 @@ ncdc_commands_t *ncdc_find_cmd(ncdc_commands_t *cmds, wchar_t const *name); bool ncdc_cmd_ack(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); bool ncdc_cmd_friends(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); +bool ncdc_cmd_join(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); bool ncdc_cmd_login(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); bool ncdc_cmd_logout(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f); diff --git a/ncdc/include/ncdc/mainwindow.h b/ncdc/include/ncdc/mainwindow.h index 7cfb2fb..59509ee 100644 --- a/ncdc/include/ncdc/mainwindow.h +++ b/ncdc/include/ncdc/mainwindow.h @@ -2,6 +2,7 @@ #define NCDC_MAINWINDOW_H #include +#include #include struct ncdc_mainwindow_; @@ -16,7 +17,12 @@ void ncdc_mainwindow_log(ncdc_mainwindow_t w, wchar_t const *fmt, ...); GPtrArray *ncdc_mainwindow_views(ncdc_mainwindow_t n); dc_channel_t ncdc_mainwindow_current_channel(ncdc_mainwindow_t n); -void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx); +//void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx); +void ncdc_mainwindow_switch_view(ncdc_mainwindow_t n, ncdc_textview_t v); +ncdc_textview_t ncdc_mainwindow_channel_view(ncdc_mainwindow_t n, + dc_channel_t c); +ncdc_textview_t ncdc_mainwindow_switch_or_add(ncdc_mainwindow_t n, + dc_channel_t c); void ncdc_mainwindow_refresh(ncdc_mainwindow_t n); void ncdc_mainwindow_input_ready(ncdc_mainwindow_t n); diff --git a/ncdc/src/cmds.c b/ncdc/src/cmds.c index 7256f5a..515c110 100644 --- a/ncdc/src/cmds.c +++ b/ncdc/src/cmds.c @@ -5,6 +5,7 @@ ncdc_commands_t cmds[] = { { L"/connect", ncdc_cmd_login }, { L"/friend", ncdc_cmd_friends }, { L"/friends", ncdc_cmd_friends }, + { L"/join", ncdc_cmd_join }, { L"/login", ncdc_cmd_login }, { L"/logout", ncdc_cmd_logout }, { L"/markread", ncdc_cmd_ack }, diff --git a/ncdc/src/join.c b/ncdc/src/join.c new file mode 100644 index 0000000..089080a --- /dev/null +++ b/ncdc/src/join.c @@ -0,0 +1,62 @@ +#include +#include + +bool +ncdc_cmd_join(ncdc_mainwindow_t n, size_t ac, wchar_t **av, wchar_t const *f) +{ + char *guild = NULL; + char *channel = NULL; + bool ret = true; + dc_guild_t g = NULL; + dc_channel_t c = NULL; + + if (ac <= 2) { + LOG(n, L"join: not enough arguments given"); + return false; + } + + if (!is_logged_in()) { + return false; + } + + guild = w_convert(av[1]); + channel = w_convert(av[2]); + + g = dc_session_guild_by_name(current_session, guild); + if (g == NULL) { + LOG(n, L"join: no such guild: %s", guild); + goto cleanup; + } + + c = dc_guild_channel_by_name(g, channel); + if (c == NULL) { + LOG(n, L"join: no such channel %s in guild %s", channel, guild); + goto cleanup; + } + + if (dc_channel_messages(c) == 0) { + bool ret = false; + + ret = dc_api_get_messages(dc_session_api(current_session), + dc_session_me(current_session), + c + ); + if (!ret) { + LOG(n, L"join: failed to fetch messages for channel %s", channel); + goto cleanup; + } + } + + /* this adds a channel, or switches to the channel if a view already exists + */ + ncdc_mainwindow_switch_or_add(n, c); + + ret = true; + +cleanup: + + free(guild); + free(channel); + + return ret; +} diff --git a/ncdc/src/mainwindow.c b/ncdc/src/mainwindow.c index 386a476..1f8d2f1 100644 --- a/ncdc/src/mainwindow.c +++ b/ncdc/src/mainwindow.c @@ -418,6 +418,16 @@ void ncdc_mainwindow_switchview(ncdc_mainwindow_t n, int idx) n->curview = idx; } +void ncdc_mainwindow_switch_view(ncdc_mainwindow_t n, ncdc_textview_t v) +{ + return_if_true(n == NULL || n->views == NULL || v == NULL,); + guint idx = 0; + + if (g_ptr_array_find(n->views, v, &idx)) { + n->curview = idx; + } +} + void ncdc_mainwindow_refresh(ncdc_mainwindow_t n) { ncdc_textview_t v = 0; @@ -458,6 +468,49 @@ void ncdc_mainwindow_log(ncdc_mainwindow_t w, wchar_t const *fmt, ...) ncdc_textview_append(w->log, buf); } +ncdc_textview_t +ncdc_mainwindow_switch_or_add(ncdc_mainwindow_t n, dc_channel_t c) +{ + ncdc_textview_t v = NULL; + + return_if_true(n == NULL || c == NULL, NULL); + return_if_true(!is_logged_in(), NULL); + + v = ncdc_mainwindow_channel_view(n, c); + if (v == NULL) { + v = ncdc_textview_new(); + if (v == NULL) { + return NULL; + } + + ncdc_textview_set_account(v, dc_session_me(current_session)); + ncdc_textview_set_channel(v, c); + + g_ptr_array_add(n->views, v); + ncdc_mainwindow_switch_view(n, v); + } + + ncdc_mainwindow_switch_view(n, v); + return v; +} + +ncdc_textview_t +ncdc_mainwindow_channel_view(ncdc_mainwindow_t n, dc_channel_t c) +{ + size_t i = 0; + + for (i = 0; i < n->views->len; i++) { + ncdc_textview_t v = g_ptr_array_index(n->views, i); + dc_channel_t vc = ncdc_textview_channel(v); + + if (dc_channel_compare(vc, c)) { + return v; + } + } + + return NULL; +} + static void ncdc_mainwindow_ack_view(ncdc_mainwindow_t n) { #if 0 diff --git a/ncdc/src/msg.c b/ncdc/src/msg.c index 8a7947b..b8acda3 100644 --- a/ncdc/src/msg.c +++ b/ncdc/src/msg.c @@ -13,9 +13,6 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, dc_message_t m = NULL; bool ret = false; dc_channel_t c = NULL; - ncdc_textview_t v = NULL; - dc_account_t current_account = NULL; - size_t i = 0; if (!is_logged_in()) { LOG(n, L"msg: not logged in"); @@ -25,8 +22,6 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, target = w_convert(av[1]); goto_if_true(target == NULL, cleanup); - current_account = dc_session_me(current_session); - /* find out if the target is a friend we can contact */ dc_account_t f = dc_session_account_fullname(current_session, target); @@ -41,30 +36,9 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, goto cleanup; } - /* see if we have a channel already, that services that user - * if so we set v to something non-NIL and it should be good + /* this adds a channel, or switches to the channel if a view already exists */ - for (i = 0; i < ncdc_mainwindow_views(n)->len; i++) { - ncdc_textview_t view = g_ptr_array_index(ncdc_mainwindow_views(n), i); - dc_channel_t chan = ncdc_textview_channel(view); - - if (dc_channel_compare(chan, c)) { - ncdc_mainwindow_switchview(n, i); - v = view; - break; - } - } - - if (v == NULL) { - v = ncdc_textview_new(); - goto_if_true(v == NULL, cleanup); - - ncdc_textview_set_account(v, current_account); - ncdc_textview_set_channel(v, c); - - g_ptr_array_add(ncdc_mainwindow_views(n), dc_ref(v)); - ncdc_mainwindow_switchview(n, ncdc_mainwindow_views(n)->len-1); - } + ncdc_mainwindow_switch_or_add(n, c); if (ac > 2) { /* also post the rest of the content as a message to the channel @@ -90,7 +64,6 @@ bool ncdc_cmd_msg(ncdc_mainwindow_t n, size_t ac, cleanup: dc_unref(c); - dc_unref(v); dc_unref(m); free(target); diff --git a/ncdc/src/util.c b/ncdc/src/util.c index 2b5e830..a357997 100644 --- a/ncdc/src/util.c +++ b/ncdc/src/util.c @@ -122,7 +122,7 @@ wchar_t **w_tokenise(wchar_t const *str) case IN_STRING: { if (c == '"') { - size_t len = (p - 2 - start_of_word); + size_t len = (p - start_of_word); wchar_t *s = wcsndup(start_of_word, len); g_ptr_array_add(array, s); state = DULL;