diff --git a/src/execute.c b/src/execute.c index 5a505f1..9ff54c3 100644 --- a/src/execute.c +++ b/src/execute.c @@ -88,12 +88,14 @@ static struct cmd_func group_commands[] = { { "/chatid", cmd_chatid }, { "/ignore", cmd_ignore }, { "/kick", cmd_kick }, + { "/mod", cmd_mod }, { "/passwd", cmd_set_passwd }, { "/peerlimit", cmd_set_peerlimit }, { "/privacy", cmd_set_privacy }, { "/rejoin", cmd_rejoin }, { "/topic", cmd_set_topic }, { "/unignore", cmd_unignore }, + { "/unmod", cmd_unmod }, #ifdef AUDIO { "/mute", cmd_mute }, { "/sense", cmd_sense }, @@ -101,17 +103,19 @@ static struct cmd_func group_commands[] = { { NULL, NULL }, }; -#define NUM_SPECIAL_COMMANDS 9 +#define NUM_SPECIAL_COMMANDS 11 static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = { "/gaccept", "/group", "/ignore", "/kick", + "/mod", "/nick", "/note", "/passwd", "/topic", - "/unignore" + "/unignore", + "/unmod", }; /* return true if input command is in the special_commands array. False otherwise.*/ diff --git a/src/group_commands.c b/src/group_commands.c index b020b57..d6a1f38 100644 --- a/src/group_commands.c +++ b/src/group_commands.c @@ -96,7 +96,7 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA switch (ret) { case 0: { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You have kicked %s from the group.", nick); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, RED, "You have kicked %s from the group.", nick); return; } case -1: { @@ -110,6 +110,72 @@ void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA } } +void cmd_mod(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, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_MODERATOR); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have promoted %s to moderator.", nick); + return; + } + case -1: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator"); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators."); + return; + } + } +} + +void cmd_unmod(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, "Peer name must be specified."); + return; + } + + const char *nick = argv[1]; + int peernumber = group_get_nick_peernumber(self->num, nick); + + if (peernumber == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name."); + return; + } + + int ret = tox_group_set_peer_role(m, self->num, peernumber, TOX_GR_USER); + + switch (ret) { + case 0: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have revoked moderator powers from %s.", nick); + return; + } + case -1: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to revoke moderator powers from %s.", nick); + return; + } + case -2: { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Nice try."); + return; + } + } +} + void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *passwd = NULL; @@ -234,8 +300,10 @@ void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { - if (tox_group_reconnect(m, self->num) == -1) + if (tox_group_reconnect(m, self->num) == -1) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to rejoin group."); return; + } line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group..."); } diff --git a/src/group_commands.h b/src/group_commands.h index 0a43291..477bf0e 100644 --- a/src/group_commands.h +++ b/src/group_commands.h @@ -29,11 +29,13 @@ void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_mod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_unmod(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); #endif /* GROUP_COMMANDS_H */ diff --git a/src/groupchat.c b/src/groupchat.c index 4a0f242..8d338cf 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -70,9 +70,9 @@ extern struct user_settings *user_settings; extern struct Winthread Winthread; #ifdef AUDIO -#define AC_NUM_GROUP_COMMANDS 32 +#define AC_NUM_GROUP_COMMANDS 34 #else -#define AC_NUM_GROUP_COMMANDS 28 +#define AC_NUM_GROUP_COMMANDS 30 #endif /* AUDIO */ /* groupchat command names used for tab completion. */ @@ -92,6 +92,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/join" }, { "/kick" }, { "/log" }, + { "/mod" }, { "/myid" }, { "/nick" }, { "/note" }, @@ -104,6 +105,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/status" }, { "/topic" }, { "/unignore" }, + { "/unmod" }, { "/whisper" }, #ifdef AUDIO @@ -573,7 +575,7 @@ static void groupchat_onGroupRejected(ToxWindow *self, Tox *m, int groupnum, uin } static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, uint32_t src_peernum, - uint32_t tgt_peernum, TOX_GROUP_MOD_TYPE type) + uint32_t tgt_peernum, TOX_GROUP_MOD_EVENT type) { if (groupnum != self->num) return; @@ -587,26 +589,28 @@ static void groupchat_onGroupModeration(ToxWindow *self, Tox *m, int groupnum, u if (get_group_nick_truncate(m, tgt_name, tgt_peernum, groupnum) == -1) return; - const char *eventstr = NULL; - int colour = RED; + char timefrmt[TIME_STR_SIZE]; + get_time_str(timefrmt, sizeof(timefrmt)); switch (type) { - case TOX_MOD_KICK: - eventstr = "kicked"; + case TOX_GROUP_MOD_EVENT_KICK: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, RED, "-!- %s has been kicked by %s", tgt_name, src_name); break; - case TOX_MOD_BAN: - eventstr = "banned"; + case TOX_GROUP_MOD_EVENT_BAN: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, RED, "-!- %s has been banned by %s", tgt_name, src_name); break; - case TOX_MOD_SILENCE: - eventstr = "silenced"; + case TOX_GROUP_MOD_EVENT_OBSERVER: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been silenced by %s", tgt_name, src_name); + break; + case TOX_GROUP_MOD_EVENT_USER: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been user'd by %s", tgt_name, src_name); + break; + case TOX_GROUP_MOD_EVENT_MODERATOR: + line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- %s has been promoted to moderator by %s", tgt_name, src_name); break; default: return; } - - char timefrmt[TIME_STR_SIZE]; - get_time_str(timefrmt, sizeof(timefrmt)); - line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, colour, "-!- %s has been %s by %s", tgt_name, eventstr, src_name); } static void groupchat_onGroupNickChange(ToxWindow *self, Tox *m, int groupnum, uint32_t peernum, @@ -867,29 +871,48 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m) wmove(ctx->sidebar, i + 2, 1); int peer = i + groupchats[self->num].side_pos; + /* TODO: Make this not poll */ + pthread_mutex_lock(&Winthread.lock); + uint8_t status = tox_group_get_status(m, self->num, i); + TOX_GROUP_ROLE role = tox_group_get_role(m, self->num, i); + pthread_mutex_unlock(&Winthread.lock); + + int maxlen_offset = role == TOX_GR_USER ? 2 : 3; + /* truncate nick to fit in side panel without modifying list */ char tmpnck[TOX_MAX_NAME_LENGTH]; - int maxlen = SIDEBAR_WIDTH - 2; + int maxlen = SIDEBAR_WIDTH - maxlen_offset; pthread_mutex_lock(&Winthread.lock); memcpy(tmpnck, &groupchats[self->num].peer_names[peer * TOX_MAX_NAME_LENGTH], maxlen); pthread_mutex_unlock(&Winthread.lock); tmpnck[maxlen] = '\0'; - /* TODO: Make this not poll */ - pthread_mutex_lock(&Winthread.lock); - uint8_t status = tox_group_get_status(m, self->num, i); - pthread_mutex_unlock(&Winthread.lock); - - int colour = WHITE; + int namecolour = WHITE; if (status == TOX_GS_AWAY) - colour = YELLOW; + namecolour = YELLOW; else if (status == TOX_GS_BUSY) - colour = RED; + namecolour = RED; - wattron(ctx->sidebar, COLOR_PAIR(colour)); + /* Signify roles (e.g. founder, moderator) */ + const char *rolesig = ""; + int rolecolour = WHITE; + + if (role == TOX_GR_FOUNDER) { + rolesig = "&"; + rolecolour = BLUE; + } else if (role == TOX_GR_MODERATOR) { + rolesig = "+"; + rolecolour = GREEN; + } + + wattron(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD); + wprintw(ctx->sidebar, "%s", rolesig); + wattroff(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD); + + wattron(ctx->sidebar, COLOR_PAIR(namecolour)); wprintw(ctx->sidebar, "%s\n", tmpnck); - wattroff(ctx->sidebar, COLOR_PAIR(colour)); + wattroff(ctx->sidebar, COLOR_PAIR(namecolour)); } } diff --git a/src/toxic.h b/src/toxic.h index de02c0b..da92087 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -128,6 +128,6 @@ void on_group_nick_change(Tox *m, int groupnumber, uint32_t peernumber, const ui void on_group_self_join(Tox *m, int groupnumber, void *userdata); void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata); void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, - TOX_GROUP_MOD_TYPE type, void *userdata); + TOX_GROUP_MOD_EVENT type, void *userdata); #endif /* #define TOXIC_H */ diff --git a/src/windows.c b/src/windows.c index d7e1e95..e59e81b 100644 --- a/src/windows.c +++ b/src/windows.c @@ -293,7 +293,7 @@ void on_group_rejected(Tox *m, int groupnumber, uint8_t type, void *userdata) } void on_group_moderation(Tox *m, int groupnumber, uint32_t source_peernum, uint32_t target_peernum, - TOX_GROUP_MOD_TYPE type, void *userdata) + TOX_GROUP_MOD_EVENT type, void *userdata) { size_t i; diff --git a/src/windows.h b/src/windows.h index 1df5ee2..c9b0291 100644 --- a/src/windows.h +++ b/src/windows.h @@ -137,7 +137,7 @@ struct ToxWindow { void(*onGroupTopicChange)(ToxWindow *, Tox *, int, uint32_t, const char *, uint16_t); void(*onGroupSelfJoin)(ToxWindow *, Tox *, int); void(*onGroupRejected)(ToxWindow *, Tox *, int, uint8_t); - void(*onGroupModeration)(ToxWindow *, Tox *, int, uint32_t, uint32_t, TOX_GROUP_MOD_TYPE); + void(*onGroupModeration)(ToxWindow *, Tox *, int, uint32_t, uint32_t, TOX_GROUP_MOD_EVENT); #ifdef AUDIO