diff --git a/src/twc-chat.c b/src/twc-chat.c index ad9bef5..7d13fef 100644 --- a/src/twc-chat.c +++ b/src/twc-chat.c @@ -203,7 +203,7 @@ twc_chat_search_group(struct t_twc_profile *profile, } if (create_new) - return twc_chat_new_friend(profile, group_number); + return twc_chat_new_group(profile, group_number); return NULL; } diff --git a/src/twc-commands.c b/src/twc-commands.c index 4b443cd..cfda050 100644 --- a/src/twc-commands.c +++ b/src/twc-commands.c @@ -27,6 +27,7 @@ #include "twc-profile.h" #include "twc-chat.h" #include "twc-friend-request.h" +#include "twc-group-invite.h" #include "twc-bootstrap.h" #include "twc-sqlite.h" #include "twc-utils.h" @@ -370,6 +371,86 @@ twc_cmd_friend(void *data, struct t_gui_buffer *buffer, return WEECHAT_RC_ERROR; } +/** + * Command /group callback. + */ +int +twc_cmd_group(void *data, struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + struct t_twc_profile *profile = twc_profile_search_buffer(buffer); + TWC_CHECK_PROFILE(profile); + TWC_CHECK_PROFILE_LOADED(profile); + + // /group create + if (argc == 2 && weechat_strcasecmp(argv[1], "create") == 0) + { + weechat_printf(profile->buffer, + "%sNot implemented :|", + weechat_prefix("error")); + return WEECHAT_RC_OK; + } + + // /group join|decline + else if (argc == 3 && + (weechat_strcasecmp(argv[1], "join") == 0 + || weechat_strcasecmp(argv[1], "decline") == 0)) + { + bool join = weechat_strcasecmp(argv[1], "join") == 0; + + struct t_twc_group_chat_invite *invite; + + char *endptr; + unsigned long num = strtoul(argv[2], &endptr, 10); + if (endptr == argv[2] || (invite = twc_group_chat_invite_with_index(profile, num)) == NULL) + { + weechat_printf(profile->buffer, + "%sInvalid group chat invite ID.", + weechat_prefix("error")); + return WEECHAT_RC_OK; + } + + if (join) + { + int group_number = twc_group_chat_invite_join(invite); + + // create a buffer for the new group chat + if (group_number >= 0) + twc_chat_search_group(profile, group_number, true); + } + else + { + twc_group_chat_invite_remove(invite); + } + + return WEECHAT_RC_OK; + } + + // /group invites + else if (argc == 2 && weechat_strcasecmp(argv[1], "invites") == 0) + { + weechat_printf(profile->buffer, + "%sPending group chat invites:", + weechat_prefix("network")); + + size_t index; + struct t_twc_list_item *item; + twc_list_foreach(profile->group_chat_invites, index, item) + { + char *friend_name = + twc_get_name_nt(profile->tox, item->group_chat_invite->friend_number); + weechat_printf(profile->buffer, + "%s[%d] From: %s", + weechat_prefix("network"), + index, friend_name); + free(friend_name); + } + + return WEECHAT_RC_OK; + } + + return WEECHAT_RC_ERROR; +} /** * Command /me callback. */ @@ -726,6 +807,21 @@ twc_commands_init() " || decline", twc_cmd_friend, NULL); + weechat_hook_command("group", + "manage group chats", + "create" + " || invites" + " || join " + " || decline ", + " create: create a new group chat\n" + "invites: list group chat invites\n" + " join: join a group chat by its invite ID\n" + "decline: decline a group chat invite\n", + "create" + " || invites" + " || join", + twc_cmd_group, NULL); + weechat_hook_command("me", "send an action to the current chat", "", diff --git a/src/twc-friend-request.c b/src/twc-friend-request.c index 77627b1..499d882 100644 --- a/src/twc-friend-request.c +++ b/src/twc-friend-request.c @@ -31,9 +31,9 @@ #include "twc-friend-request.h" /** - * Add a new friend request to a profile. + * Add a new friend request to a profile. Return it's index for accepting. * - * Returns 0 on success, -1 on a full friend request list, -2 on other error. + * Returns ID on success, -1 on a full friend request list, -2 on other error. */ int twc_friend_request_add(struct t_twc_profile *profile, diff --git a/src/twc-group-invite.c b/src/twc-group-invite.c index f57f136..2d24b03 100644 --- a/src/twc-group-invite.c +++ b/src/twc-group-invite.c @@ -32,7 +32,7 @@ /** * Add a new group invite to a profile. * - * Returns 0 on success, -1 on error. + * Returns the index of the invite on success, -1 on error. */ int twc_group_chat_invite_add(struct t_twc_profile *profile, @@ -47,23 +47,29 @@ twc_group_chat_invite_add(struct t_twc_profile *profile, return -1; invite->profile = profile; + invite->friend_number = friend_number; invite->data = data; invite->data_size = size; - return 0; + twc_list_item_new_data_add(profile->group_chat_invites, invite); + + return profile->group_chat_invites->count - 1; } /** - * Accept a group chat invite. Remove and free the invite. + * Accept a group chat invite. Remove and free the invite. Returns group chat + * number. -1 on failure. */ -void -twc_group_chat_invite_accept(struct t_twc_group_chat_invite *invite) +int +twc_group_chat_invite_join(struct t_twc_group_chat_invite *invite) { - tox_join_groupchat(invite->profile->tox, - invite->friend_number, - invite->data, - invite->data_size); + int rc = tox_join_groupchat(invite->profile->tox, + invite->friend_number, + invite->data, + invite->data_size); twc_group_chat_invite_remove(invite); + + return rc; } /** diff --git a/src/twc-group-invite.h b/src/twc-group-invite.h index ba6d1b0..d1d7124 100644 --- a/src/twc-group-invite.h +++ b/src/twc-group-invite.h @@ -44,8 +44,8 @@ twc_group_chat_invite_add(struct t_twc_profile *profile, const uint8_t *data, size_t size); -void -twc_group_chat_invite_accept(struct t_twc_group_chat_invite *invite); +int +twc_group_chat_invite_join(struct t_twc_group_chat_invite *invite); void twc_group_chat_invite_remove(struct t_twc_group_chat_invite *invite); diff --git a/src/twc-profile.c b/src/twc-profile.c index 1c8859c..0228d90 100644 --- a/src/twc-profile.c +++ b/src/twc-profile.c @@ -270,6 +270,9 @@ twc_profile_load(struct t_twc_profile *profile) tox_callback_user_status(profile->tox, twc_user_status_callback, profile); tox_callback_status_message(profile->tox, twc_status_message_callback, profile); tox_callback_friend_request(profile->tox, twc_friend_request_callback, profile); + tox_callback_group_invite(profile->tox, twc_group_invite_callback, profile); + tox_callback_group_message(profile->tox, twc_group_message_callback, profile); + tox_callback_group_action(profile->tox, twc_group_action_callback, profile); } /** diff --git a/src/twc-sqlite.c b/src/twc-sqlite.c index 202f666..3db673b 100644 --- a/src/twc-sqlite.c +++ b/src/twc-sqlite.c @@ -206,7 +206,7 @@ twc_sqlite_delete_profile(struct t_twc_profile *profile) } /** - * Add a friend request. Return 0 on success, -1 on error. + * Add a friend request. Return ID on success, -1 on error. */ int twc_sqlite_add_friend_request(struct t_twc_profile *profile, @@ -236,7 +236,7 @@ twc_sqlite_add_friend_request(struct t_twc_profile *profile, if (rc != SQLITE_DONE) return -1; else - return 0; + return sqlite3_last_insert_rowid(twc_sqlite_db); } /** diff --git a/src/twc-tox-callbacks.c b/src/twc-tox-callbacks.c index 95424a3..b6ce17e 100644 --- a/src/twc-tox-callbacks.c +++ b/src/twc-tox-callbacks.c @@ -26,6 +26,7 @@ #include "twc-profile.h" #include "twc-chat.h" #include "twc-friend-request.h" +#include "twc-group-invite.h" #include "twc-message-queue.h" #include "twc-utils.h" @@ -50,11 +51,13 @@ twc_do_timer_cb(void *data, } void -twc_friend_message_callback(Tox *tox, - int32_t friend_number, - const uint8_t *message, - uint16_t length, - void *data) +twc_handle_friend_message(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data, + enum TWC_MESSAGE_TYPE message_type) + { struct t_twc_profile *profile = data; struct t_twc_chat *chat = twc_chat_search_friend(profile, @@ -65,12 +68,27 @@ twc_friend_message_callback(Tox *tox, char *message_nt = twc_null_terminate(message, length); twc_chat_print_message(chat, "", name, - message_nt, TWC_MESSAGE_TYPE_MESSAGE); + message_nt, message_type); free(name); free(message_nt); } +void +twc_friend_message_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + twc_handle_friend_message(tox, + friend_number, + message, + length, + data, + TWC_MESSAGE_TYPE_MESSAGE); +} + void twc_friend_action_callback(Tox *tox, int32_t friend_number, @@ -78,20 +96,12 @@ twc_friend_action_callback(Tox *tox, uint16_t length, void *data) { - struct t_twc_profile *profile = data; - - struct t_twc_chat *chat = twc_chat_search_friend(profile, - friend_number, - true); - - char *name = twc_get_name_nt(profile->tox, friend_number); - char *message_nt = twc_null_terminate(message, length); - - twc_chat_print_message(chat, "", name, - message_nt, TWC_MESSAGE_TYPE_ACTION); - - free(name); - free(message_nt); + twc_handle_friend_message(tox, + friend_number, + message, + length, + data, + TWC_MESSAGE_TYPE_ACTION); } void @@ -212,10 +222,12 @@ twc_friend_request_callback(Tox *tox, twc_bin2hex(public_key, TOX_CLIENT_ID_SIZE, hex_address); weechat_printf(profile->buffer, - "%sReceived a friend request with message \"%s\" from %s", + "%sReceived a friend request from %s with message \"%s\"; " + "accept it with \"/friend accept %d\"", weechat_prefix("network"), + hex_address, message_nt, - hex_address); + rc); if (rc == -2) { @@ -229,3 +241,84 @@ twc_friend_request_callback(Tox *tox, free(message_nt); } +void +twc_group_invite_callback(Tox *tox, + int32_t friend_number, + const uint8_t *invite_data, + uint16_t length, + void *data) +{ + struct t_twc_profile *profile = data; + + int64_t rc = twc_group_chat_invite_add(profile, friend_number, invite_data, length); + + char *friend_name = twc_get_name_nt(profile->tox, friend_number); + weechat_printf(profile->buffer, + "%sReceived a group chat invite from %s; " + "join with \"/group join %d\"", + weechat_prefix("network"), + friend_name, rc); + + + free(friend_name); +} + +void +twc_handle_group_message(Tox *tox, + int32_t group_number, + int32_t peer_number, + const uint8_t *message, + uint16_t length, + void *data, + enum TWC_MESSAGE_TYPE message_type) +{ + struct t_twc_profile *profile = data; + + struct t_twc_chat *chat = twc_chat_search_group(profile, + group_number, + true); + + char *name = twc_get_peer_name_nt(profile->tox, group_number, peer_number); + char *message_nt = twc_null_terminate(message, length); + + twc_chat_print_message(chat, "", name, + message_nt, message_type); + + free(name); + free(message_nt); +} + +void +twc_group_message_callback(Tox *tox, + int32_t group_number, + int32_t peer_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + twc_handle_group_message(tox, + group_number, + peer_number, + message, + length, + data, + TWC_MESSAGE_TYPE_MESSAGE); +} + +void +twc_group_action_callback(Tox *tox, + int32_t group_number, + int32_t peer_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + twc_handle_group_message(tox, + group_number, + peer_number, + message, + length, + data, + TWC_MESSAGE_TYPE_ACTION); +} + diff --git a/src/twc-tox-callbacks.h b/src/twc-tox-callbacks.h index 8727772..3156e2a 100644 --- a/src/twc-tox-callbacks.h +++ b/src/twc-tox-callbacks.h @@ -73,5 +73,28 @@ twc_friend_request_callback(Tox *tox, uint16_t length, void *data); +void +twc_group_invite_callback(Tox *tox, + int32_t friend_number, + const uint8_t *invite_data, + uint16_t length, + void *data); + +void +twc_group_message_callback(Tox *tox, + int32_t group_number, + int32_t peer_number, + const uint8_t *message, + uint16_t length, + void *data); + +void +twc_group_action_callback(Tox *tox, + int32_t group_number, + int32_t peer_number, + const uint8_t *message, + uint16_t length, + void *data); + #endif // TOX_WEECHAT_TOX_CALLBACKS_H diff --git a/src/twc-utils.c b/src/twc-utils.c index 269f431..1c4c1bd 100644 --- a/src/twc-utils.c +++ b/src/twc-utils.c @@ -102,6 +102,19 @@ twc_get_status_message_nt(Tox *tox, int32_t friend_number) return twc_null_terminate(message, length); } +/** + * Return the name of a group chat peer as a null terminated string. Must be + * freed. + */ +char * +twc_get_peer_name_nt(Tox *tox, int32_t group_number, int32_t peer_number) +{ + uint8_t name[TOX_MAX_NAME_LENGTH] = {0}; + + tox_group_peername(tox, group_number, peer_number, name); + return twc_null_terminate(name, strlen((char *)name)); +} + /** * Return the users own name, null-terminated. Must be freed. */ diff --git a/src/twc-utils.h b/src/twc-utils.h index 9195895..1c3ab90 100644 --- a/src/twc-utils.h +++ b/src/twc-utils.h @@ -39,6 +39,9 @@ twc_get_name_nt(Tox *tox, int32_t friend_number); char * twc_get_status_message_nt(Tox *tox, int32_t friend_number); +char * +twc_get_peer_name_nt(Tox *tox, int32_t group_number, int32_t peer_number); + char * twc_get_self_name_nt(Tox *tox);