diff --git a/src/execute.c b/src/execute.c index b24dfef..f7dfd3c 100644 --- a/src/execute.c +++ b/src/execute.c @@ -139,6 +139,7 @@ static struct cmd_func groupchat_commands[] = { { "/unignore", cmd_unignore }, { "/unmod", cmd_unmod }, { "/unsilence", cmd_unsilence }, + { "/voice", cmd_set_voice }, { "/whois", cmd_whois }, #ifdef AUDIO { "/mute", cmd_mute }, diff --git a/src/groupchat_commands.c b/src/groupchat_commands.c index ab03118..7d42e5d 100644 --- a/src/groupchat_commands.c +++ b/src/groupchat_commands.c @@ -400,6 +400,78 @@ void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char ( } } +void cmd_set_voice(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + Tox_Group_Voice_State voice_state; + + if (argc < 1) { + Tox_Err_Group_State_Queries err; + voice_state = tox_group_get_voice_state(m, self->num, &err); + + if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve voice state (error %d).", err); + return; + } + + switch (voice_state) { + case TOX_GROUP_VOICE_STATE_ALL: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Voice state is set to ALL"); + break; + } + + case TOX_GROUP_VOICE_STATE_MODERATOR: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Voice state is set to MODERATOR"); + break; + } + + case TOX_GROUP_VOICE_STATE_FOUNDER: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Voice state is set to FOUNDER"); + break; + } + + default: + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Error: Unknown voice state: %d", voice_state); + return; + } + + return; + } + + const char *vstate_str = argv[1]; + + if (strcasecmp(vstate_str, "mod") == 0) { + voice_state = TOX_GROUP_VOICE_STATE_MODERATOR; + } else if (strcasecmp(vstate_str, "founder") == 0) { + voice_state = TOX_GROUP_VOICE_STATE_FOUNDER; + } else if (strcasecmp(vstate_str, "all") == 0) { + voice_state = TOX_GROUP_VOICE_STATE_ALL; + } else { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, + "voice state must be \"all\", \"mod\", or \"founder\"."); + return; + } + + Tox_Err_Group_Founder_Set_Voice_State err; + tox_group_founder_set_voice_state(m, self->num, voice_state, &err); + + switch (err) { + case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Voice state has been set to %s.", vstate_str); + return; + } + + case TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_PERMISSIONS: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the voice state."); + return; + } + + default: { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Error setting voice state (error %d).", err); + return; + } + } +} + void cmd_set_privacy(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { const char *pstate_str = NULL; diff --git a/src/groupchat_commands.h b/src/groupchat_commands.h index 8c6cc42..e308a0d 100644 --- a/src/groupchat_commands.h +++ b/src/groupchat_commands.h @@ -36,6 +36,7 @@ void cmd_prune(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[M 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_set_voice(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_set_topic_lock(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]); diff --git a/src/groupchats.c b/src/groupchats.c index dd44200..f9c3d1c 100644 --- a/src/groupchats.c +++ b/src/groupchats.c @@ -114,6 +114,7 @@ static const char *group_cmd_list[] = { "/unignore", "/unmod", "/unsilence", + "/voice", "/whisper", "/whois", #ifdef AUDIO @@ -841,6 +842,43 @@ static void groupchat_onGroupPrivacyState(ToxWindow *self, Tox *m, uint32_t grou write_to_log(tmp_event, "The founder", ctx->log, true); } +void groupchat_onGroupVoiceState(ToxWindow *self, Tox *m, uint32_t groupnumber, Tox_Group_Voice_State voice_state) +{ + ChatContext *ctx = self->chatwin; + + if (self->num != groupnumber || !get_groupchat(groupnumber)) { + return; + } + + char tmp_event[MAX_STR_SIZE]; + + switch (voice_state) { + case TOX_GROUP_VOICE_STATE_ALL: { + line_info_add(self, true, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Voice: Everyone may speak"); + snprintf(tmp_event, sizeof(tmp_event), " set the voice state to ALL."); + break; + } + + case TOX_GROUP_VOICE_STATE_MODERATOR: { + line_info_add(self, true, NULL, NULL, SYS_MSG, 1, BLUE, + "-!- Voice: Only moderators and the founder may speak"); + snprintf(tmp_event, sizeof(tmp_event), " set the voice state to MODERATOR."); + break; + } + + case TOX_GROUP_VOICE_STATE_FOUNDER: { + line_info_add(self, true, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Voice: Only the founder may speak."); + snprintf(tmp_event, sizeof(tmp_event), " set the voice state to FOUNDER."); + break; + } + + default: + return; + } + + write_to_log(tmp_event, "The founder", ctx->log, true); +} + static void groupchat_onGroupTopicLock(ToxWindow *self, Tox *m, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock) { ChatContext *ctx = self->chatwin; @@ -1336,7 +1374,13 @@ static void send_group_message(ToxWindow *self, Tox *m, uint32_t groupnumber, co if (!tox_group_send_message(m, groupnumber, type, (uint8_t *) msg, strlen(msg), &err)) { if (err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS) { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * You are silenced."); + const Tox_Group_Role role = tox_group_self_get_role(m, groupnumber, NULL); + + if (role == TOX_GROUP_ROLE_OBSERVER) { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * You are silenced."); + } else { + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * You do not have voice."); + } } else { line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send message (Error %d).", err); } @@ -1411,11 +1455,12 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, uint32_t groupnumbe Tox_Err_Group_Send_Private_Message err; - if (!tox_group_send_private_message(m, groupnumber, peer_id, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) msg, msg_len, &err)) { + if (!tox_group_send_private_message(m, groupnumber, peer_id, TOX_MESSAGE_TYPE_NORMAL, + (uint8_t *) msg, msg_len, &err)) { if (err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_PERMISSIONS) { line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * You are silenced."); } else { - line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send private message."); + line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, " * Failed to send private message (%d)", err); } return; @@ -1762,6 +1807,7 @@ static ToxWindow *new_group_chat(Tox *m, uint32_t groupnumber, const char *group ret->onGroupSelfJoin = &groupchat_onGroupSelfJoin; ret->onGroupRejected = &groupchat_onGroupRejected; ret->onGroupModeration = &groupchat_onGroupModeration; + ret->onGroupVoiceState = &groupchat_onGroupVoiceState; ChatContext *chatwin = calloc(1, sizeof(ChatContext)); Help *help = calloc(1, sizeof(Help)); diff --git a/src/help.c b/src/help.c index cd80448..fdb0840 100644 --- a/src/help.c +++ b/src/help.c @@ -307,13 +307,14 @@ static void help_draw_groupchats(ToxWindow *self) wprintw(win, " /mod : Promote a peer to moderator\n"); wprintw(win, " /passwd : Set a password needed to join the group\n"); wprintw(win, " /peerlimit : Set the maximum number of peers that can join\n"); - wprintw(win, " /privacy : Set the group privacy state: private | public\n"); + wprintw(win, " /privacy : Set the privacy state: private | public\n"); wprintw(win, " /rejoin : Reconnect to the groupchat\n"); wprintw(win, " /silence : Silence a peer for the entire group\n"); wprintw(win, " /unsilence : Unsilence a silenced peer\n"); wprintw(win, " /status : Set your status\n"); wprintw(win, " /topic : Set the group topic\n"); wprintw(win, " /unmod : Demote a moderator\n"); + wprintw(win, " /voice : Set the voice state: all | mod | founder\n"); wprintw(win, " /whisper : Send a private message to a peer\n"); wprintw(win, " /whois : Print whois info for a peer\n"); @@ -490,7 +491,7 @@ void help_onKey(ToxWindow *self, wint_t key) break; case L'r': - help_init_window(self, 25, 80); + help_init_window(self, 26, 80); self->help->type = HELP_GROUP; break; } diff --git a/src/toxic.c b/src/toxic.c index 51761c9..09d65c0 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -842,6 +842,7 @@ static void init_tox_callbacks(Tox *m) tox_callback_group_self_join(m, on_group_self_join); tox_callback_group_join_fail(m, on_group_rejected); tox_callback_group_moderation(m, on_group_moderation); + tox_callback_group_voice_state(m, on_group_voice_state); } static void init_tox_options(struct Tox_Options *tox_opts) diff --git a/src/toxic.h b/src/toxic.h index b4a719c..a7def1a 100644 --- a/src/toxic.h +++ b/src/toxic.h @@ -173,6 +173,7 @@ void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata); void on_group_rejected(Tox *m, uint32_t groupnumber, Tox_Group_Join_Fail type, void *userdata); void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peernum, uint32_t target_peernum, Tox_Group_Mod_Event type, void *userdata); +void on_group_voice_state(Tox *m, uint32_t groupnumber, Tox_Group_Voice_State voice_state, void *userdata); extern char *DATA_FILE; extern char *BLOCK_FILE; diff --git a/src/windows.c b/src/windows.c index 8d25d9e..98edfc2 100644 --- a/src/windows.c +++ b/src/windows.c @@ -555,6 +555,15 @@ void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peer_id, } } +void on_group_voice_state(Tox *m, uint32_t groupnumber, Tox_Group_Voice_State voice_state, void *userdata) +{ + for (size_t i = 0; i < MAX_WINDOWS_NUM; ++i) { + if (windows[i] != NULL && windows[i]->onGroupVoiceState != NULL) { + windows[i]->onGroupVoiceState(windows[i], m, groupnumber, voice_state); + } + } +} + /* CALLBACKS END */ int add_window(Tox *m, ToxWindow *w) diff --git a/src/windows.h b/src/windows.h index 79f47d1..cb6e3f0 100644 --- a/src/windows.h +++ b/src/windows.h @@ -209,6 +209,7 @@ struct ToxWindow { void(*onGroupSelfJoin)(ToxWindow *, Tox *, uint32_t); void(*onGroupRejected)(ToxWindow *, Tox *, uint32_t, Tox_Group_Join_Fail); void(*onGroupModeration)(ToxWindow *, Tox *, uint32_t, uint32_t, uint32_t, Tox_Group_Mod_Event); + void(*onGroupVoiceState)(ToxWindow *, Tox *, uint32_t, Tox_Group_Voice_State); #ifdef AUDIO