From ff69cdd2537348316b167cebd3f4a8ed52dc6ec6 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 23 Jan 2015 00:52:09 -0500 Subject: [PATCH] add friend group invites --- src/chat.c | 32 ++++++++++++++++++++++++++++++-- src/chat_commands.c | 23 +++++++++++++++++++++++ src/chat_commands.h | 1 + src/execute.c | 1 + src/friendlist.c | 20 ++++++++++++++++++++ src/friendlist.h | 6 ++++++ src/global_commands.c | 29 ++++++++++++++++++++++++++--- src/groupchat.c | 12 ++++++------ src/misc_tools.c | 6 +++++- src/toxic.c | 1 + src/toxic.h | 1 + src/windows.c | 10 ++++++++++ src/windows.h | 1 + 13 files changed, 131 insertions(+), 12 deletions(-) diff --git a/src/chat.c b/src/chat.c index a47aefc..4d3481a 100644 --- a/src/chat.c +++ b/src/chat.c @@ -64,9 +64,9 @@ static void kill_infobox(ToxWindow *self); #endif /* AUDIO */ #ifdef AUDIO -#define AC_NUM_CHAT_COMMANDS 26 +#define AC_NUM_CHAT_COMMANDS 27 #else -#define AC_NUM_CHAT_COMMANDS 19 +#define AC_NUM_CHAT_COMMANDS 20 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -81,6 +81,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/exit" }, { "/group" }, { "/help" }, + { "/invite" }, { "/join" }, { "/log" }, { "/myid" }, @@ -560,6 +561,32 @@ static void chat_onFileData(ToxWindow *self, Tox *m, int32_t num, uint8_t filenu Friends.list[num].file_receiver[filenum].bytes_recv += length; } +static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data, + uint16_t length) +{ + if (self->num != friendnumber) + return; + + if (length != TOX_GROUP_INVITE_DATA_SIZE) + return; + + memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length); + Friends.list[friendnumber].group_invite.length = length; + + sound_notify(self, generic_message, NT_WNDALERT_2, NULL); + + char name[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, name, friendnumber); + + if (self->active_box != -1) + box_silent_notify2(self, NT_WNDALERT_2 | NT_NOFOCUS, self->active_box, "invites you to join group chat"); + else + box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat"); + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s has invited you to a group chat.", name); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/join\" to join the chat."); +} + /* Av Stuff */ #ifdef AUDIO @@ -1113,6 +1140,7 @@ ToxWindow new_chat(Tox *m, int32_t friendnum) ret.onFileControl = &chat_onFileControl; ret.onFileData = &chat_onFileData; ret.onReadReceipt = &chat_onReadReceipt; + ret.onGroupInvite = &chat_onGroupInvite; #ifdef AUDIO ret.onInvite = &chat_onInvite; diff --git a/src/chat_commands.c b/src/chat_commands.c index 48de478..9ca5109 100644 --- a/src/chat_commands.c +++ b/src/chat_commands.c @@ -66,6 +66,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar get_file_name(name, sizeof(name), filepath); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "File transfer for '%s' canceled.", name); chat_close_file_receiver(m, filenum, self->num, TOX_FILECONTROL_KILL); + return; } else if (strcasecmp(inoutstr, "out") == 0) { /* cancel an outgoing file transfer */ int i; @@ -94,6 +95,28 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar } } +void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + if (argc < 1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group number required."); + return; + } + + int groupnum = atoi(argv[1]); + + if (groupnum == 0 && strcmp(argv[1], "0")) { /* atoi returns 0 value on invalid input */ + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group number."); + return; + } + + if (tox_group_invite_friend(m, groupnum, self->num) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group."); + return; + } + + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum); +} + void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (argc < 1) { diff --git a/src/chat_commands.h b/src/chat_commands.h index 9c87ede..afe314e 100644 --- a/src/chat_commands.h +++ b/src/chat_commands.h @@ -26,6 +26,7 @@ #include "windows.h" #include "toxic.h" +void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_savefile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/execute.c b/src/execute.c index c2c2803..d53767b 100644 --- a/src/execute.c +++ b/src/execute.c @@ -67,6 +67,7 @@ static struct cmd_func global_commands[] = { static struct cmd_func chat_commands[] = { { "/cancel", cmd_cancelfile }, + { "/invite", cmd_groupinvite }, { "/savefile", cmd_savefile }, { "/sendfile", cmd_sendfile }, #ifdef AUDIO diff --git a/src/friendlist.c b/src/friendlist.c index ba925f0..1e95a0e 100644 --- a/src/friendlist.c +++ b/src/friendlist.c @@ -476,6 +476,25 @@ static void friendlist_onFileSendRequest(ToxWindow *self, Tox *m, int32_t num, u } } +static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data, + uint16_t length) +{ + if (num >= Friends.max_idx) + return; + + if (Friends.list[num].chatwin == -1) { + if (get_num_active_windows() < MAX_WINDOWS_NUM) { + Friends.list[num].chatwin = add_window(m, new_chat(m, Friends.list[num].num)); + } else { + char nick[TOX_MAX_NAME_LENGTH]; + get_nick_truncate(m, nick, num); + line_info_add(prompt, NULL, NULL, NULL, SYS_MSG, 0, RED, + "* Group chat invite from %s failed: too many windows are open.", nick); + sound_notify(prompt, error, NT_WNDALERT_1, NULL); + } + } +} + /* move friendlist/blocklist cursor up and down */ static void select_friend(ToxWindow *self, wint_t key, int *selected, int num) { @@ -1046,6 +1065,7 @@ ToxWindow new_friendlist(void) ret.onStatusChange = &friendlist_onStatusChange; ret.onStatusMessageChange = &friendlist_onStatusMessageChange; ret.onFileSendRequest = &friendlist_onFileSendRequest; + ret.onGroupInvite = &friendlist_onGroupInvite; #ifdef AUDIO ret.onInvite = &friendlist_onAv; diff --git a/src/friendlist.h b/src/friendlist.h index 599d4a7..ae4e965 100644 --- a/src/friendlist.h +++ b/src/friendlist.h @@ -48,6 +48,11 @@ struct LastOnline { char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */ }; +struct GroupInvite { + uint8_t data[TOX_GROUP_INVITE_DATA_SIZE]; + uint16_t length; +}; + typedef struct { char name[TOXIC_MAX_NAME_LENGTH + 1]; int namelength; @@ -61,6 +66,7 @@ typedef struct { uint8_t is_typing; bool logging_on; /* saves preference for friend irrespective of global settings */ uint8_t status; + struct GroupInvite group_invite; struct LastOnline last_online; struct FileReceiver file_receiver[MAX_FILES]; uint8_t active_file_receivers; diff --git a/src/global_commands.c b/src/global_commands.c index d812649..d38c351 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -362,6 +362,23 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg } } +static void join_invite(ToxWindow *self, Tox *m) +{ + int groupnumber = tox_group_accept_invite(m, Friends.list[self->num].group_invite.data, + Friends.list[self->num].group_invite.length); + + if (groupnumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize."); + return; + } + + if (init_groupchat_win(prompt, m, groupnumber, NULL, 0) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); + tox_group_delete(m, groupnumber, NULL, 0); + return; + } +} + void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { if (get_num_active_windows() >= MAX_WINDOWS_NUM) { @@ -369,9 +386,15 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA return; } + /* If no input check for a group invite */ if (argc < 1) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat ID is required."); - return; + if (!self->is_chat || Friends.list[self->num].group_invite.length == 0) { + const char *msg = "You must either be invited to a group or input the group ID of the group you wish to join."; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", msg); + return; + } + + return join_invite(self, m); } const char *chat_id = argv[1]; @@ -409,7 +432,7 @@ void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA if (init_groupchat_win(prompt, m, groupnum, NULL, 0) == -1) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); - tox_group_delete(m, self->num, NULL, 0); + tox_group_delete(m, groupnum, NULL, 0); return; } } diff --git a/src/groupchat.c b/src/groupchat.c index 47785ee..cdaf18c 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -189,7 +189,7 @@ void set_nick_all_groups(Tox *m, const char *nick, uint16_t length) for (i = 0; i < max_groupchat_index; ++i) { if (groupchats[i].active) { ToxWindow *self = get_window_ptr(groupchats[i].chatwin); - int ret = tox_group_set_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); + int ret = tox_group_set_self_name(m, groupchats[i].groupnumber, (uint8_t *) nick, length); if (ret == -1 && groupchats[i].is_connected) line_info_add(self, timefrmt, NULL, 0, SYS_MSG, 0, 0, "Invalid nick"); @@ -875,11 +875,6 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.onGroupSelfTimeout = &groupchat_onGroupSelfTimeout; ret.onGroupRejected = &groupchat_onGroupRejected; - if (groupname && length) - set_window_title(&ret, groupname, length); - else - snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); - ChatContext *chatwin = calloc(1, sizeof(ChatContext)); Help *help = calloc(1, sizeof(Help)); @@ -893,5 +888,10 @@ ToxWindow new_group_chat(Tox *m, int groupnum, const char *groupname, int length ret.show_peerlist = true; ret.active_box = -1; + if (groupname && length) + set_window_title(&ret, groupname, length); + else + snprintf(ret.name, sizeof(ret.name), "Group %d", groupnum); + return ret; } diff --git a/src/misc_tools.c b/src/misc_tools.c index 4d8373e..ee9ca0f 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -400,7 +400,11 @@ int check_file_signature(const char *signature, size_t size, FILE *fp) void set_window_title(ToxWindow *self, const char *title, int len) { char cpy[TOXIC_MAX_NAME_LENGTH + 1]; - snprintf(cpy, sizeof(cpy), "%s", title); + + if (self->is_groupchat) /* keep groupnumber in title */ + snprintf(cpy, sizeof(cpy), "%d %s", self->num, title); + else + snprintf(cpy, sizeof(cpy), "%s", title); if (len > MAX_WINDOW_NAME_LENGTH) { strcpy(&cpy[MAX_WINDOW_NAME_LENGTH - 3], "..."); diff --git a/src/toxic.c b/src/toxic.c index edeea94..b2a6291 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -310,6 +310,7 @@ static Tox *init_tox(void) tox_callback_file_control(m, on_file_control, NULL); tox_callback_file_data(m, on_file_data, NULL); tox_callback_read_receipt(m, on_read_receipt, NULL); + tox_callback_group_invite(m, on_group_invite, NULL); tox_callback_group_message(m, on_group_message, NULL); tox_callback_group_action(m, on_group_action, NULL); tox_callback_group_private_message(m, on_group_private_message, NULL); diff --git a/src/toxic.h b/src/toxic.h index eaed4e3..551ef29 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -111,6 +111,7 @@ void on_file_data(Tox *m, int32_t friendnumber, uint8_t filenumber, const uint8_ void on_typing_change(Tox *m, int32_t friendnumber, uint8_t is_typing, void *userdata); void on_read_receipt(Tox *m, int32_t, uint32_t, void *userdata); +void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata); void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); void on_group_action(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *action, uint16_t length, void *userdata); void on_group_private_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata); diff --git a/src/windows.c b/src/windows.c index f6c809e..fe5b135 100644 --- a/src/windows.c +++ b/src/windows.c @@ -161,6 +161,16 @@ void on_friendadded(Tox *m, int32_t friendnumber, bool sort) store_data(m, DATA_FILE); } +void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, uint16_t length, void *userdata) +{ + int i; + + for (i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i].onGroupInvite != NULL) + windows[i].onGroupInvite(&windows[i], m, friendnumber, (char *) invite_data, length); + } +} + void on_group_message(Tox *m, int groupnumber, uint32_t peernumber, const uint8_t *message, uint16_t length, void *userdata) { diff --git a/src/windows.h b/src/windows.h index fbaa84d..2e1394b 100644 --- a/src/windows.h +++ b/src/windows.h @@ -123,6 +123,7 @@ struct ToxWindow { void(*onTypingChange)(ToxWindow *, Tox *, int32_t, uint8_t); void(*onReadReceipt)(ToxWindow *, Tox *, int32_t, uint32_t); + void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, uint16_t); void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t); void(*onGroupPrivateMessage)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t);