1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-15 03:43:03 +01:00

Port to new group API

This commit is contained in:
Jfreegman 2015-07-13 22:12:13 -04:00
commit a846c38695
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
30 changed files with 1679 additions and 667 deletions

View File

@ -1,52 +1,23 @@
language: c env:
compiler: secure: m+RsGCgemJNMKbinD97PtjC1pUuFzDBrAol3tI6Z3xP1FE2qF0/efbcC5OyNwUWwcaqGRb83d0vWt4hzhxMwrwJC8O6EFLFHgJs0WpslP+++KRN30PUOqRFFqH404InF4pFNULlnwJYFZ8bGft4ThxppbEOeSYcXN4WSgb66RjM=
- gcc
- clang
before_script: before_script:
# Installing yasm (needed for compiling vpx) and openal - sudo apt-get install wget
- sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev libnotify-dev clang llvm-dev
# Installing libsodium, needed for toxcore
- git clone https://github.com/jedisct1/libsodium.git libsodium
- cd libsodium
- git checkout tags/1.0.3 > /dev/null
- ./autogen.sh > /dev/null
- ./configure > /dev/null
- make check -j2 || make check || exit 1 > /dev/null
- sudo make install > /dev/null
- cd ..
# Installing libopus, needed for audio encoding/decoding
- wget http://downloads.xiph.org/releases/opus/opus-1.1.tar.gz
- tar xzf opus-1.1.tar.gz > /dev/null
- cd opus-1.1
- ./configure > /dev/null
- make -j2 || make || exit 1 > /dev/null
- sudo make install > /dev/null
- cd ..
# Installing vpx
- git clone https://chromium.googlesource.com/webm/libvpx libvpx
- cd libvpx
- ./configure --enable-shared > /dev/null
- make -j2 || make || exit 1 > /dev/null
- sudo make install > /dev/null
- cd ..
# Creating libraries links and updating cache
- sudo ldconfig > /dev/null
# Installing toxcore
- git clone https://github.com/irungentoo/toxcore.git toxcore
- cd toxcore
- autoreconf -i
- ./configure --disable-tests --disable-ntox --disable-daemon --enable-av
- make -j2 || make || exit 1
- sudo make install
- cd ..
script: script:
- make -j2 || make || exit 1 - wget -O temp https://jenkins.libtoxcore.so/job/toxic_linux_beta/build?token=$TOKEN && cat temp
notifications: notifications:
email: false email: false
irc: irc:
channels: channels:
- "chat.freenode.net#tox-dev" - "chat.freenode.net#tox-groupchats"
on_success: always
on_failure: always
irc:
channels:
- "chat.freenode.net#tox-groupchats"
on_success: always on_success: always
on_failure: always on_failure: always

View File

@ -138,6 +138,11 @@ Indicator for alert messages\&.
Indicator for normal messages\&. Indicator for normal messages\&.
.RE .RE
.PP .PP
\fBline_special\fR
.RS 4
Indicator for special messages\&.
.RE
.PP
\fBmplex_away\fR \fBmplex_away\fR
.RS 4 .RS 4
Set user status when attaching and detaching from GNU screen or tmux\&. true or false Set user status when attaching and detaching from GNU screen or tmux\&. true or false

View File

@ -88,6 +88,9 @@ OPTIONS
*line_normal*;; *line_normal*;;
Indicator for normal messages. Indicator for normal messages.
*line_special*;;
Indicator for special messages.
*mplex_away*;; *mplex_away*;;
Set user status when attaching and detaching from GNU screen or tmux. Set user status when attaching and detaching from GNU screen or tmux.
true or false true or false

View File

@ -1,20 +1 @@
192.254.75.102 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F 192.254.75.104 33445 6058FF1DA1E013AD4F829CBE8E5DDFD30A4DE55901B0997832E3E8A64E19026C
144.76.60.215 33445 04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F
23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074
178.62.125.224 33445 10B20C49ACBD968D7C80F2E8438F92EA51F189F4E70CFBBB2C2C8C799E97F03E
178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057
195.154.119.113 33445 E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354
192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67
104.219.184.206 443 8CD087E31C67568103E8C2A28653337E90E6B8EDA0D765D57C6B5172B4F1F04C
76.191.23.96 33445 93574A3FAB7D612FEA29FD8D67D3DD10DFD07A075A5D62E8AF3DD9F5D0932E11
46.38.239.179 33445 F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A
178.62.250.138 33445 788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B
78.225.128.39 33445 7A2306BFBA665E5480AE59B31E116BE9C04DCEFE04D9FE25082316FA34B4DA0C
130.133.110.14 33445 461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F
104.167.101.29 33445 5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57
195.154.109.148 33445 391C96CB67AE893D4782B8E4495EB9D89CF1031F48460C06075AA8CE76D50A21
192.3.173.88 33445 3E1FFDEB667BFF549F619EC6737834762124F50A89C8D0DBF1DDF64A2DD6CD1B
205.185.116.116 33445 A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702
198.98.51.198 33445 1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F
80.232.246.79 33445 0B8DCEAA7BDDC44BB11173F987CAE3566A2D7057D8DD3CC642BD472B9391002A

View File

@ -44,6 +44,9 @@ ui = {
// Indicator for normal messages. // Indicator for normal messages.
line_normal="---"; line_normal="---";
// Indicator for special messages (currently only used for private group messages)
line_special=">>>";
// true to change status based on screen/tmux attach/detach, false to disable // true to change status based on screen/tmux attach/detach, false to disable
mplex_away=true; mplex_away=true;

View File

@ -63,9 +63,9 @@ static void kill_infobox(ToxWindow *self);
#endif /* AUDIO */ #endif /* AUDIO */
#ifdef AUDIO #ifdef AUDIO
#define AC_NUM_CHAT_COMMANDS 27 #define AC_NUM_CHAT_COMMANDS 28
#else #else
#define AC_NUM_CHAT_COMMANDS 20 #define AC_NUM_CHAT_COMMANDS 21
#endif /* AUDIO */ #endif /* AUDIO */
/* Array of chat command names used for tab completion. */ /* Array of chat command names used for tab completion. */
@ -78,6 +78,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/close" }, { "/close" },
{ "/connect" }, { "/connect" },
{ "/exit" }, { "/exit" },
{ "/gaccept" },
{ "/group" }, { "/group" },
{ "/help" }, { "/help" },
{ "/invite" }, { "/invite" },
@ -509,25 +510,18 @@ static void chat_onFileRecv(ToxWindow *self, Tox *m, uint32_t friendnum, uint32_
"Incoming file: %s", filename ); "Incoming file: %s", filename );
} }
static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, uint8_t type, const char *group_pub_key, static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, const char *invite_data,
uint16_t length) size_t length)
{ {
if (self->num != friendnumber) if (self->num != friendnumber)
return; return;
if (Friends.list[friendnumber].group_invite.key != NULL) if (Friends.list[friendnumber].group_invite.data)
free(Friends.list[friendnumber].group_invite.key); free(Friends.list[friendnumber].group_invite.data);
char *k = malloc(length); Friends.list[friendnumber].group_invite.data = malloc(length * sizeof(uint8_t));
memcpy(Friends.list[friendnumber].group_invite.data, invite_data, length);
if (k == NULL)
exit_toxic_err("Failed in chat_onGroupInvite", FATALERR_MEMORY);
memcpy(k, group_pub_key, length);
Friends.list[friendnumber].group_invite.key = k;
Friends.list[friendnumber].group_invite.pending = true;
Friends.list[friendnumber].group_invite.length = length; Friends.list[friendnumber].group_invite.length = length;
Friends.list[friendnumber].group_invite.type = type;
sound_notify(self, generic_message, NT_WNDALERT_2, NULL); sound_notify(self, generic_message, NT_WNDALERT_2, NULL);
@ -540,7 +534,7 @@ static void chat_onGroupInvite(ToxWindow *self, Tox *m, int32_t friendnumber, ui
box_silent_notify(self, NT_WNDALERT_2 | NT_NOFOCUS, &self->active_box, name, "invites you to join group chat"); 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, "%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."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Type \"/gaccept\" to join the chat.");
} }
/* Av Stuff */ /* Av Stuff */
@ -1104,7 +1098,6 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
ret.onMessage = &chat_onMessage; ret.onMessage = &chat_onMessage;
ret.onConnectionChange = &chat_onConnectionChange; ret.onConnectionChange = &chat_onConnectionChange;
ret.onTypingChange = & chat_onTypingChange; ret.onTypingChange = & chat_onTypingChange;
ret.onGroupInvite = &chat_onGroupInvite;
ret.onNickChange = &chat_onNickChange; ret.onNickChange = &chat_onNickChange;
ret.onStatusChange = &chat_onStatusChange; ret.onStatusChange = &chat_onStatusChange;
ret.onStatusMessageChange = &chat_onStatusMessageChange; ret.onStatusMessageChange = &chat_onStatusMessageChange;
@ -1113,6 +1106,7 @@ ToxWindow new_chat(Tox *m, uint32_t friendnum)
ret.onFileControl = &chat_onFileControl; ret.onFileControl = &chat_onFileControl;
ret.onFileRecv = &chat_onFileRecv; ret.onFileRecv = &chat_onFileRecv;
ret.onReadReceipt = &chat_onReadReceipt; ret.onReadReceipt = &chat_onReadReceipt;
ret.onGroupInvite = &chat_onGroupInvite;
#ifdef AUDIO #ifdef AUDIO
ret.onInvite = &chat_onInvite; ret.onInvite = &chat_onInvite;

View File

@ -78,6 +78,46 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent); close_file_transfer(self, m, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
} }
void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
return;
}
if (Friends.list[self->num].group_invite.length == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group invite");
return;
}
const char *passwd = NULL;
uint16_t passwd_len = 0;
if (argc > 0) {
passwd = argv[1];
passwd_len = strlen(passwd);
}
TOX_ERR_GROUP_INVITE_ACCEPT err;
uint32_t groupnumber = tox_group_invite_accept(m, Friends.list[self->num].group_invite.data,
Friends.list[self->num].group_invite.length,
(uint8_t *) passwd, passwd_len, &err);
if (err != TOX_ERR_GROUP_INVITE_ACCEPT_OK) {
if (err == TOX_ERR_GROUP_INVITE_ACCEPT_TOO_LONG)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group: Password too long.");
else
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to joing group (error %d).", err);
return;
}
if (init_groupchat_win(m, groupnumber, NULL, 0) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
tox_group_leave(m, groupnumber, NULL, 0, NULL);
return;
}
}
void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
if (argc < 1) { if (argc < 1) {
@ -92,53 +132,15 @@ void cmd_groupinvite(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*a
return; return;
} }
if (tox_invite_friend(m, self->num, groupnum) == -1) { TOX_ERR_GROUP_INVITE_FRIEND err;
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group."); if (!tox_group_invite_friend(m, groupnum, self->num, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to invite contact to group (error %d).", err);
return; return;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invited contact to Group %d.", groupnum);
} }
void cmd_join_group(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (get_num_active_windows() >= MAX_WINDOWS_NUM) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
return;
}
const char *groupkey = Friends.list[self->num].group_invite.key;
uint16_t length = Friends.list[self->num].group_invite.length;
uint8_t type = Friends.list[self->num].group_invite.type;
if (!Friends.list[self->num].group_invite.pending) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "No pending group chat invite.");
return;
}
int groupnum = -1;
if (type == TOX_GROUPCHAT_TYPE_TEXT)
groupnum = tox_join_groupchat(m, self->num, (uint8_t *) groupkey, length);
#ifdef AUDIO
else
groupnum = toxav_join_av_groupchat(m, self->num, (uint8_t *) groupkey, length,
NULL, NULL);
#endif
if (groupnum == -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, groupnum, type) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
tox_del_groupchat(m, groupnum);
return;
}
}
void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_savefile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
if (argc < 1) { if (argc < 1) {

View File

@ -26,9 +26,9 @@
#include "windows.h" #include "windows.h"
#include "toxic.h" #include "toxic.h"
void cmd_groupaccept(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
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_cancelfile(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_groupinvite(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_join_group(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_savefile(WINDOW *, ToxWindow *, Tox *, 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]); void cmd_sendfile(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);

View File

@ -34,6 +34,8 @@
#include "misc_tools.h" #include "misc_tools.h"
#include "notify.h" #include "notify.h"
#define MAX_NUM_ARGS 10 /* Includes command */
struct cmd_func { struct cmd_func {
const char *name; const char *name;
void (*func)(WINDOW *w, ToxWindow *, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void (*func)(WINDOW *w, ToxWindow *, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
@ -49,6 +51,7 @@ static struct cmd_func global_commands[] = {
{ "/exit", cmd_quit }, { "/exit", cmd_quit },
{ "/group", cmd_groupchat }, { "/group", cmd_groupchat },
{ "/help", cmd_prompt_help }, { "/help", cmd_prompt_help },
{ "/join", cmd_join },
{ "/log", cmd_log }, { "/log", cmd_log },
{ "/myid", cmd_myid }, { "/myid", cmd_myid },
{ "/nick", cmd_nick }, { "/nick", cmd_nick },
@ -66,8 +69,8 @@ static struct cmd_func global_commands[] = {
static struct cmd_func chat_commands[] = { static struct cmd_func chat_commands[] = {
{ "/cancel", cmd_cancelfile }, { "/cancel", cmd_cancelfile },
{ "/gaccept", cmd_groupaccept },
{ "/invite", cmd_groupinvite }, { "/invite", cmd_groupinvite },
{ "/join", cmd_join_group },
{ "/savefile", cmd_savefile }, { "/savefile", cmd_savefile },
{ "/sendfile", cmd_sendfile }, { "/sendfile", cmd_sendfile },
#ifdef AUDIO #ifdef AUDIO
@ -82,19 +85,96 @@ static struct cmd_func chat_commands[] = {
}; };
static struct cmd_func group_commands[] = { static struct cmd_func group_commands[] = {
{ "/title", cmd_set_title }, { "/ban", cmd_ban },
{ "/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 },
{ "/silence", cmd_silence },
{ "/topic", cmd_set_topic },
{ "/unban", cmd_unban },
{ "/unignore", cmd_unignore },
{ "/unmod", cmd_unmod },
{ "/unsilence", cmd_unsilence },
#ifdef AUDIO #ifdef AUDIO
{ "/mute", cmd_mute }, { "/mute", cmd_mute },
{ "/sense", cmd_sense }, { "/sense", cmd_sense },
#endif /* AUDIO */ #endif /* AUDIO */
{ NULL, NULL }, { NULL, NULL },
}; };
/* Parses input command and puts args into arg array. #define NUM_SPECIAL_COMMANDS 14
Returns number of arguments on success, -1 on failure. */ static const char special_commands[NUM_SPECIAL_COMMANDS][MAX_CMDNAME_SIZE] = {
"/ban",
"/gaccept",
"/group",
"/ignore",
"/kick",
"/mod",
"/nick",
"/note",
"/passwd",
"/silence",
"/topic",
"/unignore",
"/unmod",
"/unsilence",
};
/* return true if input command is in the special_commands array. False otherwise.*/
static bool is_special_command(const char *input)
{
int s = char_find(0, input, ' ');
if (s == strlen(input))
return false;
int i;
for (i = 0; i < NUM_SPECIAL_COMMANDS; ++i) {
if (strncmp(input, special_commands[i], s) == 0)
return true;
}
return false;
}
/* Parses commands in the special_commands array which take exactly one argument that may contain spaces.
* Unlike parse_command, this function does not split the input string at spaces.
*
* Returns number of arguments on success
* Returns -1 on failure
*/
static int parse_special_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
{
int len = strlen(input);
int s = char_find(0, input, ' ');
if (s + 1 >= len)
return -1;
memcpy(args[0], input, s);
args[0][s++] = '\0'; /* increment to remove space after /command */
memcpy(args[1], input + s, len - s);
args[1][len - s] = '\0';
return 2;
}
/* Parses input command and puts args (split by spaces) into args array.
*
* Returns number of arguments on success
* Returns -1 on failure.
*/
static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE]) static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*args)[MAX_STR_SIZE])
{ {
if (is_special_command(input))
return parse_special_command(w, self, input, args);
char *cmd = strdup(input); char *cmd = strdup(input);
if (cmd == NULL) if (cmd == NULL)
@ -132,11 +212,19 @@ static int parse_command(WINDOW *w, ToxWindow *self, const char *input, char (*a
strcpy(cmd, tmp); /* tmp will always fit inside cmd */ strcpy(cmd, tmp); /* tmp will always fit inside cmd */
} }
/* Ugly special case concatinates all args after arg1 for multi-word group passwords */
if (num_args > 2 && strcmp(args[0], "/join") == 0)
strcpy(args[2], input + strlen(args[0]) + 1 + strlen(args[1]) + 1);
free(cmd); free(cmd);
return num_args; return num_args;
} }
/* Matches command to respective function. Returns 0 on match, 1 on no match */ /* Matches command to respective function.
*
* Returns 0 on match,
* Returns -1 on no match
*/
static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands, static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct cmd_func *commands,
char (*args)[MAX_STR_SIZE]) char (*args)[MAX_STR_SIZE])
{ {
@ -149,7 +237,7 @@ static int do_command(WINDOW *w, ToxWindow *self, Tox *m, int num_args, struct c
} }
} }
return 1; return -1;
} }
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode) void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
@ -177,6 +265,7 @@ void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode)
case GROUPCHAT_COMMAND_MODE: case GROUPCHAT_COMMAND_MODE:
if (do_command(w, self, m, num_args, group_commands, args) == 0) if (do_command(w, self, m, num_args, group_commands, args) == 0)
return; return;
break; break;
} }

View File

@ -26,13 +26,11 @@
#include "toxic.h" #include "toxic.h"
#include "windows.h" #include "windows.h"
#define MAX_NUM_ARGS 4 /* Includes command */
enum { enum {
GLOBAL_COMMAND_MODE, GLOBAL_COMMAND_MODE,
CHAT_COMMAND_MODE, CHAT_COMMAND_MODE,
GROUPCHAT_COMMAND_MODE, GROUPCHAT_COMMAND_MODE,
}; } COMMAND_MODE;
void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode); void execute(WINDOW *w, ToxWindow *self, Tox *m, const char *input, int mode);

View File

@ -112,11 +112,11 @@ static void realloc_blocklist(int n)
void kill_friendlist(void) void kill_friendlist(void)
{ {
int i; size_t i;
for (i = 0; i < Friends.max_idx; ++i) { for (i = 0; i < Friends.max_idx; ++i) {
if (Friends.list[i].active && Friends.list[i].group_invite.key != NULL) if (Friends.list[i].group_invite.data != NULL)
free(Friends.list[i].group_invite.key); free(Friends.list[i].group_invite.data);
} }
realloc_blocklist(0); realloc_blocklist(0);
@ -496,8 +496,7 @@ static void friendlist_onFileRecv(ToxWindow *self, Tox *m, uint32_t num, uint32_
sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL); sound_notify(prompt, notif_error, NT_WNDALERT_1, NULL);
} }
static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, uint8_t type, const char *group_pub_key, static void friendlist_onGroupInvite(ToxWindow *self, Tox *m, int32_t num, const char *data, size_t length)
uint16_t length)
{ {
if (num >= Friends.max_idx) if (num >= Friends.max_idx)
return; return;
@ -556,9 +555,6 @@ static void delete_friend(Tox *m, uint32_t f_num)
} }
} }
if (Friends.list[f_num].group_invite.key != NULL)
free(Friends.list[f_num].group_invite.key);
memset(&Friends.list[f_num], 0, sizeof(ToxicFriend)); memset(&Friends.list[f_num], 0, sizeof(ToxicFriend));
int i; int i;

View File

@ -35,11 +35,9 @@ struct LastOnline {
char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */ char hour_min_str[TIME_STR_SIZE]; /* holds 12/24-hour time string e.g. "10:43 PM" */
}; };
struct GroupChatInvite { struct GroupInvite {
char *key; uint8_t *data;
uint16_t length; uint16_t length;
uint8_t type;
bool pending;
}; };
typedef struct { typedef struct {
@ -57,7 +55,7 @@ typedef struct {
uint8_t status; uint8_t status;
struct LastOnline last_online; struct LastOnline last_online;
struct GroupChatInvite group_invite; struct GroupInvite group_invite;
struct FileTransfer file_receiver[MAX_FILES]; struct FileTransfer file_receiver[MAX_FILES];
struct FileTransfer file_sender[MAX_FILES]; struct FileTransfer file_sender[MAX_FILES];

View File

@ -192,7 +192,7 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
} }
cmd_add_helper(self, m, id_bin, msg); cmd_add_helper(self, m, id_bin, msg);
} else { /* assume id is a username@domain address and do DNS lookup */ } else { /* assume id is a username@domain address */
dns3_lookup(self, m, id_bin, id, msg); dns3_lookup(self, m, id_bin, id, msg);
} }
} }
@ -320,42 +320,120 @@ void cmd_groupchat(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*arg
} }
if (argc < 1) { if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please specify group type: text | audio"); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name required");
return; return;
} }
uint8_t type; const char *tmp_name = argv[1];
int len = strlen(tmp_name);
if (!strcasecmp(argv[1], "audio")) if (len == 0 || len > TOX_GROUP_MAX_GROUP_NAME_LENGTH) {
type = TOX_GROUPCHAT_TYPE_AV; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid group name.");
else if (!strcasecmp(argv[1], "text"))
type = TOX_GROUPCHAT_TYPE_TEXT;
else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Valid group types are: text | audio");
return; return;
} }
int groupnum = -1; char name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
if (type == TOX_GROUPCHAT_TYPE_TEXT) if (argv[1][0] == '\"') { /* remove opening and closing quotes */
groupnum = tox_add_groupchat(m); snprintf(name, sizeof(name), "%s", &argv[1][1]);
#ifdef AUDIO len -= 2;
else name[len] = '\0';
groupnum = toxav_add_av_groupchat(m, NULL, NULL); } else {
#endif snprintf(name, sizeof(name), "%s", argv[1]);
}
TOX_ERR_GROUP_NEW err;
uint32_t groupnum = tox_group_new(m, TOX_GROUP_PRIVACY_STATE_PUBLIC, (uint8_t *) name, len, &err);
if (err != TOX_ERR_GROUP_NEW_OK) {
switch (err) {
case TOX_ERR_GROUP_NEW_TOO_LONG: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name length cannot exceed %d.", TOX_GROUP_MAX_GROUP_NAME_LENGTH);
break;
}
case TOX_ERR_GROUP_NEW_EMPTY: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group name cannot be empty.");
break;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize (error %d).", err);
break;
}
}
if (groupnum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat instance failed to initialize.");
return; return;
} }
if (init_groupchat_win(prompt, m, groupnum, type) == -1) { if (init_groupchat_win(m, groupnum, name, len) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
tox_del_groupchat(m, groupnum); tox_group_leave(m, groupnum, NULL, 0, NULL);
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) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, " * Warning: Too many windows are open.");
return; return;
} }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat [%d] created.", groupnum); if (argc < 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Chat ID is required.");
return;
}
const char *chat_id = argv[1];
if (strlen(chat_id) != TOX_GROUP_CHAT_ID_SIZE * 2) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID");
return;
}
char id_bin[TOX_GROUP_CHAT_ID_SIZE] = {0};
size_t i;
char xch[3];
uint32_t x;
for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
xch[0] = chat_id[2 * i];
xch[1] = chat_id[2 * i + 1];
xch[2] = '\0';
if (sscanf(xch, "%02x", &x) != 1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid chat ID.");
return;
}
id_bin[i] = x;
}
const char *passwd = NULL;
uint16_t passwd_len = 0;
if (argc > 1) {
passwd = argv[2];
passwd_len = strlen(passwd);
}
TOX_ERR_GROUP_JOIN err;
uint32_t groupnum = tox_group_join(m, (uint8_t *) id_bin, (uint8_t *) passwd, passwd_len, &err);
if (err != TOX_ERR_GROUP_JOIN_OK) {
if (err == TOX_ERR_GROUP_JOIN_TOO_LONG)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length cannot exceed %d.", TOX_GROUP_MAX_PASSWORD_SIZE);
else
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to join group (error %d).", err);
return;
}
if (init_groupchat_win(m, groupnum, NULL, 0) == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Group chat window failed to initialize.");
tox_group_leave(m, groupnum, NULL, 0, NULL);
return;
}
} }
void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -452,6 +530,7 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
tox_self_set_name(m, (uint8_t *) nick, len, NULL); tox_self_set_name(m, (uint8_t *) nick, len, NULL);
prompt_update_nick(prompt, nick); prompt_update_nick(prompt, nick);
set_nick_all_groups(m, nick, len);
store_data(m, DATA_FILE); store_data(m, DATA_FILE);
} }
@ -463,18 +542,7 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
return; return;
} }
if (argv[1][0] != '\"') { prompt_update_statusmessage(prompt, m, argv[1]);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Note must be enclosed in quotes.");
return;
}
/* remove opening and closing quotes */
char msg[MAX_STR_SIZE];
snprintf(msg, sizeof(msg), "%s", &argv[1][1]);
int len = strlen(msg) - 1;
msg[len] = '\0';
prompt_update_statusmessage(prompt, m, msg);
} }
void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
@ -549,6 +617,7 @@ void cmd_status(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
tox_self_set_status(m, status); tox_self_set_status(m, status);
prompt_update_status(prompt, status); prompt_update_status(prompt, status);
set_status_all_groups(m, status);
if (have_note) { if (have_note) {
if (argv[2][0] != '\"') { if (argv[2][0] != '\"') {

View File

@ -33,6 +33,7 @@ void cmd_clear(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE
void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_connect(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_decline(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_groupchat(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_join(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_nick(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_nick(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]);

View File

@ -21,59 +21,590 @@
*/ */
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "toxic.h" #include "toxic.h"
#include "windows.h" #include "windows.h"
#include "line_info.h" #include "line_info.h"
#include "misc_tools.h" #include "misc_tools.h"
#include "log.h" #include "log.h"
#include "groupchat.h"
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{ {
char title[MAX_STR_SIZE]; char chatid[TOX_GROUP_CHAT_ID_SIZE * 2 + 1] = {0};
char chat_public_key[TOX_GROUP_CHAT_ID_SIZE];
TOX_ERR_GROUP_STATE_QUERIES err;
if (!tox_group_get_chat_id(m, self->num, (uint8_t *) chat_public_key, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve the Chat ID (error %d).", err);
return;
}
size_t i;
for (i = 0; i < TOX_GROUP_CHAT_ID_SIZE; ++i) {
char xx[3];
snprintf(xx, sizeof(xx), "%02X", chat_public_key[i] & 0xff);
strcat(chatid, xx);
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s", chatid);
}
void cmd_ignore(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 peernum = group_get_nick_peernumber(self->num, nick);
if (peernum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
return;
}
TOX_ERR_GROUP_TOGGLE_IGNORE err;
if (!tox_group_toggle_ignore(m, self->num, peernum, true, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to ignore %s (error %d).", nick, err);
return;
}
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick);
}
static void cmd_kickban_helper(ToxWindow *self, Tox *m, const char *nick, bool set_ban)
{
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 '%s'.", nick);
return;
}
const char *type_str = set_ban ? "ban" : "kick";
TOX_ERR_GROUP_MOD_REMOVE_PEER err;
tox_group_mod_remove_peer(m, self->num, (uint32_t) peernumber, set_ban, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_REMOVE_PEER_OK: {
type_str = set_ban ? "banned" : "kicked";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, RED, "You have %s %s from the group.", type_str, nick);
return;
}
case TOX_ERR_GROUP_MOD_REMOVE_PEER_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to %s %s.", type_str, nick);
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to %s %s from the group (error %d).", type_str, nick, err);
return;
}
}
}
void cmd_kick(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;
}
cmd_kickban_helper(self, m, argv[1], false);
}
void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
TOX_ERR_GROUP_BAN_QUERY err;
if (argc < 1) { if (argc < 1) {
int tlen = tox_group_get_title(m, self->num, (uint8_t *) title, TOX_MAX_NAME_LENGTH); size_t num_banned = tox_group_ban_get_list_size(m, self->num, &err);
if (tlen != -1) { if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
title[tlen] = '\0'; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list size (error %d).", err);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is set to: %s", title); return;
} else { }
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title is not set");
if (num_banned == 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list is empty.");
return;
}
uint16_t ban_list[num_banned];
if (!tox_group_ban_get_list(m, self->num, ban_list, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to get the ban list (error %d).", err);
return;
}
uint16_t i;
for (i = 0; i < num_banned; ++i) {
uint16_t id = ban_list[i];
size_t len = tox_group_ban_get_name_size(m, self->num, id, &err);
if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name length for ban %d (error %d).", id, err);
continue;
}
char tmp_nick[len];
if (!tox_group_ban_get_name(m, self->num, id, (uint8_t *) tmp_nick, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve name for ban %d (error %d).", id, err);
continue;
}
char nick[len + 1];
copy_tox_str(nick, sizeof(nick), tmp_nick, len);
uint64_t time_set = tox_group_ban_get_time_set(m, self->num, id, &err);
if (err != TOX_ERR_GROUP_BAN_QUERY_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve timestamp for ban %d (error %d).", id, err);
continue;
}
struct tm tm_set = *localtime((const time_t *) &time_set);
char time_str[64];
strftime(time_str, sizeof(time_str), "%e %b %Y %H:%M:%S%p", &tm_set);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "ID %d : %s [Set:%s]", id, nick, time_str);
} }
return; return;
} }
if (argv[1][0] != '\"') { cmd_kickban_helper(self, m, argv[1], true);
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Title must be enclosed in quotes."); }
void cmd_unban(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, "Ban ID must be specified.");
return; return;
} }
/* remove opening and closing quotes */ int ban_id = atoi(argv[1]);
snprintf(title, sizeof(title), "%s", &argv[1][1]);
int len = strlen(title) - 1;
title[len] = '\0';
if (tox_group_set_title(m, self->num, (uint8_t *) title, len) != 0) { if (ban_id == 0 && strcmp(argv[1], "0")) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set title."); line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID must be a non-negative interger.");
return; return;
} }
set_window_title(self, title, len); TOX_ERR_GROUP_MOD_REMOVE_BAN err;
tox_group_mod_remove_ban(m, self->num, ban_id, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_REMOVE_BAN_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban list entry with id %d has been removed.", ban_id);
return;
}
case TOX_ERR_GROUP_MOD_REMOVE_BAN_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unban peers.");
return;
}
case TOX_ERR_GROUP_MOD_REMOVE_BAN_FAIL_ACTION: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Ban ID does not exist.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to remove ban list entry (error %d).", err);
return;
}
}
}
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 '%s'.", nick);
return;
}
TOX_ERR_GROUP_MOD_SET_ROLE err;
tox_group_mod_set_role(m, self->num, peernumber, TOX_GROUP_ROLE_MODERATOR, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have promoted %s to moderator.", nick);
return;
}
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to promote moderators.");
return;
}
case TOX_ERR_GROUP_MOD_SET_ROLE_ASSIGNMENT: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "This peer is already a moderator.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to promote peer to moderator (error %d).", err);
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 '%s'.", nick);
return;
}
if (tox_group_peer_get_role(m, self->num, peernumber, NULL) != TOX_GROUP_ROLE_MODERATOR) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not a moderator", nick);
return;
}
TOX_ERR_GROUP_MOD_SET_ROLE err;
tox_group_mod_set_role(m, self->num, peernumber, TOX_GROUP_ROLE_USER, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have revoked moderator powers from %s.", nick);
return;
}
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Nice try.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to revoke moderator powers from %s (error %d).", nick, err);
return;
}
}
}
void cmd_set_passwd(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
const char *passwd = NULL;
size_t len = 0;
if (argc > 0) {
passwd = argv[1];
len = strlen(passwd);
}
TOX_ERR_GROUP_FOUNDER_SET_PASSWORD err;
tox_group_founder_set_password(m, self->num, (uint8_t *) passwd, len, &err);
switch (err) {
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK: {
if (len > 0)
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been set to %s.", passwd);
else
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password has been unset.");
return;
}
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_TOO_LONG: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Password length must not exceed %d.", TOX_GROUP_MAX_PASSWORD_SIZE);
return;
}
case TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the password.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set password (error %d).", err);
return;
}
}
}
void cmd_set_peerlimit(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
int maxpeers = 0;
if (argc < 1) {
TOX_ERR_GROUP_STATE_QUERIES err;
uint32_t maxpeers = tox_group_get_peer_limit(m, self->num, &err);
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve peer limit (error %d).", err);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit is set to %d", maxpeers);
return;
}
maxpeers = atoi(argv[1]);
if (maxpeers <= 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit must be a value greater than 0.");
return;
}
TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT err;
tox_group_founder_set_peer_limit(m, self->num, maxpeers, &err);
switch (err) {
case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Peer limit has been set to %d.", maxpeers);
return;
}
case TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the peer limit.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the peer limit (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;
TOX_GROUP_PRIVACY_STATE privacy_state;
if (argc < 1) {
TOX_ERR_GROUP_STATE_QUERIES err;
privacy_state = tox_group_get_privacy_state(m, self->num, &err);
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve privacy state (error %d).", err);
return;
}
pstate_str = privacy_state == TOX_GROUP_PRIVACY_STATE_PRIVATE ? "private" : "public";
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state is set to %s.", pstate_str);
return;
}
pstate_str = argv[1];
if (strcasecmp(pstate_str, "private") != 0 && strcasecmp(pstate_str, "public") != 0) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state must be \"private\" or \"public\".");
return;
}
privacy_state = strcasecmp(pstate_str, "private") == 0 ? TOX_GROUP_PRIVACY_STATE_PRIVATE : TOX_GROUP_PRIVACY_STATE_PUBLIC;
TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE err;
tox_group_founder_set_privacy_state(m, self->num, privacy_state, &err);
switch (err) {
case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Privacy state has been set to %s.", pstate_str);
return;
}
case TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the privacy state.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Error setting privacy state (error %d).", err);
return;
}
}
}
void cmd_silence(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 '%s'.", nick);
return;
}
TOX_ERR_GROUP_MOD_SET_ROLE err;
tox_group_mod_set_role(m, self->num, peernumber, TOX_GROUP_ROLE_OBSERVER, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have silenced %s", nick);
return;
}
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to silence %s.", nick);
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to silence %s (error %d).", nick, err);
return;
}
}
}
void cmd_unsilence(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 '%s'.", nick);
return;
}
if (tox_group_peer_get_role(m, self->num, peernumber, NULL) != TOX_GROUP_ROLE_OBSERVER) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "%s is not silenced.", nick);
return;
}
TOX_ERR_GROUP_MOD_SET_ROLE err;
tox_group_mod_set_role(m, self->num, peernumber, TOX_GROUP_ROLE_USER, &err);
switch (err) {
case TOX_ERR_GROUP_MOD_SET_ROLE_OK: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 1, BLUE, "You have unsilenced %s.", nick);
return;
}
case TOX_ERR_GROUP_MOD_SET_ROLE_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to unsilence %s.", nick);
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unsilence %s (error %d).", nick, err);
return;
}
}
}
void cmd_rejoin(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
TOX_ERR_GROUP_RECONNECT err;
if (!tox_group_reconnect(m, self->num, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to rejoin group (error %d).", err);
return;
}
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Reconnecting to group...");
}
void cmd_set_topic(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
{
if (argc < 1) {
TOX_ERR_GROUP_STATE_QUERIES err;
size_t tlen = tox_group_get_topic_size(m, self->num, &err);
if (err != TOX_ERR_GROUP_STATE_QUERIES_OK) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic length (error %d).", err);
return;
}
if (tlen > 0) {
char cur_topic[tlen];
if (!tox_group_get_topic(m, self->num, (uint8_t *) cur_topic, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve topic (error %d).", err);
return;
}
cur_topic[tlen] = '\0';
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is set to: %s", cur_topic);
} else {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic is not set.");
}
return;
}
const char *topic = argv[1];
TOX_ERR_GROUP_TOPIC_SET err;
tox_group_set_topic(m, self->num, (uint8_t *) topic, strlen(topic), &err);
switch (err) {
case TOX_ERR_GROUP_TOPIC_SET_OK: {
/* handled below switch */
break;
}
case TOX_ERR_GROUP_TOPIC_SET_TOO_LONG: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Topic length must not exceed %d.", TOX_GROUP_MAX_TOPIC_LENGTH);
return;
}
case TOX_ERR_GROUP_TOPIC_SET_PERMISSIONS: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "You do not have permission to set the topic.");
return;
}
default: {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to set the topic (error %d).", err);
return;
}
}
char timefrmt[TIME_STR_SIZE]; char timefrmt[TIME_STR_SIZE];
char selfnick[TOX_MAX_NAME_LENGTH];
get_time_str(timefrmt, sizeof(timefrmt)); get_time_str(timefrmt, sizeof(timefrmt));
tox_self_get_name(m, (uint8_t *) selfnick); TOX_ERR_GROUP_SELF_QUERY sn_err;
size_t sn_len = tox_self_get_name_size(m); size_t sn_len = tox_group_self_get_name_size(m, self->num, &sn_err);
char selfnick[sn_len];
if (!tox_group_self_get_name(m, self->num, (uint8_t *) selfnick, &sn_err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to retrieve your own name (error %d).", sn_err);
return;
}
selfnick[sn_len] = '\0'; selfnick[sn_len] = '\0';
line_info_add(self, timefrmt, selfnick, NULL, NAME_CHANGE, 0, 0, " set the group title to: %s", title); line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, MAGENTA, "-!- You set the topic to: %s.", topic);
char tmp_event[MAX_STR_SIZE]; char tmp_event[MAX_STR_SIZE];
snprintf(tmp_event, sizeof(tmp_event), "set title to %s", title); snprintf(tmp_event, sizeof(tmp_event), "set topic to %s", topic);
write_to_log(tmp_event, selfnick, self->chatwin->log, true); write_to_log(tmp_event, selfnick, self->chatwin->log, true);
} }
void cmd_unignore(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 must be specified.");
return;
}
const char *nick = argv[1];
int peernum = group_get_nick_peernumber(self->num, nick);
if (peernum == -1) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name '%s'.", nick);
return;
}
TOX_ERR_GROUP_TOGGLE_IGNORE err;
if (!tox_group_toggle_ignore(m, self->num, peernum, false, &err)) {
line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Failed to unignore %s (error %d).", nick, err);
return;
}
char timefrmt[TIME_STR_SIZE];
get_time_str(timefrmt, sizeof(timefrmt));
line_info_add(self, timefrmt, NULL, NULL, SYS_MSG, 1, BLUE, "-!- You are no longer ignoring %s", nick);
}

View File

@ -26,6 +26,21 @@
#include "windows.h" #include "windows.h"
#include "toxic.h" #include "toxic.h"
void cmd_set_title(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_ban(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
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_prune(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_silence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_unsilence(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_unban(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 */ #endif /* GROUP_COMMANDS_H */

File diff suppressed because it is too large Load Diff

View File

@ -59,28 +59,26 @@ struct GAudio {
#endif /* AUDIO */ #endif /* AUDIO */
typedef struct { typedef struct {
uint32_t groupnumber;
int chatwin; int chatwin;
bool active; bool active;
uint8_t type; bool is_connected;
int num_peers;
int side_pos; /* current position of the sidebar - used for scrolling up and down */ int side_pos; /* current position of the sidebar - used for scrolling up and down */
uint64_t start_time; uint32_t num_peers;
uint8_t *peer_names; uint8_t *peer_names;
uint8_t *oldpeer_names;
uint16_t *peer_name_lengths; uint16_t *peer_name_lengths;
uint16_t *oldpeer_name_lengths;
#ifdef AUDIO #ifdef AUDIO
struct GAudio audio; struct GAudio audio;
#endif #endif
} GroupChat; } GroupChat;
void close_groupchat(ToxWindow *self, Tox *m, int groupnum); void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnum);
int init_groupchat_win(ToxWindow *prompt, Tox *m, int groupnum, uint8_t type); int init_groupchat_win(Tox *m, uint32_t groupnum, const char *groupname, size_t length);
void set_nick_all_groups(Tox *m, const char *nick, size_t length);
void set_status_all_groups(Tox *m, uint8_t status);
int group_get_nick_peernumber(uint32_t groupnum, const char *nick);
/* destroys and re-creates groupchat window with or without the peerlist */ /* destroys and re-creates groupchat window with or without the peerlist */
void redraw_groupchat_win(ToxWindow *self); void redraw_groupchat_win(ToxWindow *self);
ToxWindow new_group_chat(Tox *m, int groupnum);
#endif /* #define GROUPCHAT_H */ #endif /* #define GROUPCHAT_H */

View File

@ -150,9 +150,10 @@ static void help_draw_global(ToxWindow *self)
wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n"); wprintw(win, " /connect <ip> <port> <key> : Manually connect to a DHT node\n");
wprintw(win, " /status <type> <msg> : Set status with optional note\n"); wprintw(win, " /status <type> <msg> : Set status with optional note\n");
wprintw(win, " /note <msg> : Set a personal note\n"); wprintw(win, " /note <msg> : Set a personal note\n");
wprintw(win, " /group : Create a group chat\n");
wprintw(win, " /join <chat id> <passwd> : Join a group chat with optional password\n");
wprintw(win, " /nick <nick> : Set your nickname\n"); wprintw(win, " /nick <nick> : Set your nickname\n");
wprintw(win, " /log <on> or <off> : Enable/disable logging\n"); wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
wprintw(win, " /group <type> : Create a group chat where type: text | audio\n");
wprintw(win, " /myid : Print your Tox ID\n"); wprintw(win, " /myid : Print your Tox ID\n");
wprintw(win, " /clear : Clear window history\n"); wprintw(win, " /clear : Clear window history\n");
wprintw(win, " /close : Close the current chat window\n"); wprintw(win, " /close : Close the current chat window\n");
@ -183,8 +184,7 @@ static void help_draw_chat(ToxWindow *self)
wprintw(win, "Chat Commands:\n"); wprintw(win, "Chat Commands:\n");
wattroff(win, A_BOLD | COLOR_PAIR(RED)); wattroff(win, A_BOLD | COLOR_PAIR(RED));
wprintw(win, " /invite <n> : Invite contact to a group chat\n"); wprintw(win, " /gaccept <password> : Accept a group invite with optional password\n");
wprintw(win, " /join : Join a pending group chat\n");
wprintw(win, " /sendfile <path> : Send a file\n"); wprintw(win, " /sendfile <path> : Send a file\n");
wprintw(win, " /savefile <id> : Receive a file\n"); wprintw(win, " /savefile <id> : Receive a file\n");
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n"); wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
@ -243,7 +243,30 @@ static void help_draw_group(ToxWindow *self)
wprintw(win, "Group commands:\n"); wprintw(win, "Group commands:\n");
wattroff(win, A_BOLD | COLOR_PAIR(RED)); wattroff(win, A_BOLD | COLOR_PAIR(RED));
wprintw(win, " /title <msg> : Set group title (show current title if no msg)\n\n"); wprintw(win, " /chatid : Print the group chat id to share with others\n");
wprintw(win, " /ignore <nick> : Ignore peer\n");
wprintw(win, " /unignore <nick> : Unignore peer \n");
wprintw(win, " /rejoin : Rejoin the group\n");
wprintw(win, " /topic <msg> : Set group topic (show current topic if no msg)\n");
wprintw(win, " /whisper <nick> <msg> : Send private message to nick\n");
wattron(win, A_BOLD);
wprintw(win, " Moderator commands:\n");
wattroff(win, A_BOLD);
wprintw(win, " /kick <nick> : Kick peer\n");
wprintw(win, " /ban <nick> : Ban peer (leave nick blank to see ban list)\n");
wprintw(win, " /unban <Ban ID> : Unban entry\n");
wprintw(win, " /silence <nick> : Silences peer for the entire group\n");
wprintw(win, " /unsilence <nick> : Unsilences peer\n");
wattron(win, A_BOLD);
wprintw(win, " Founder commands:\n");
wattroff(win, A_BOLD);
wprintw(win, " /mod <nick> : Promote peer to moderator\n");
wprintw(win, " /unmod <nick> : Demote moderator to normal user\n");
wprintw(win, " /passwd <password> : Set group password (leave blank to unset)\n");
wprintw(win, " /peerlimit <num> : Set group peer limit\n");
wprintw(win, " /privacy <state> : Set group privacy state: private|public\n");
help_draw_bottom_menu(win); help_draw_bottom_menu(win);
@ -283,24 +306,24 @@ void help_onKey(ToxWindow *self, wint_t key)
case 'c': case 'c':
#ifdef AUDIO #ifdef AUDIO
help_init_window(self, 19, 80); help_init_window(self, 18, 80);
#else #else
help_init_window(self, 9, 80); help_init_window(self, 8, 80);
#endif #endif
self->help->type = HELP_CHAT; self->help->type = HELP_CHAT;
break; break;
case 'g': case 'g':
#ifdef AUDIO #ifdef AUDIO
help_init_window(self, 24, 80); help_init_window(self, 25, 80);
#else #else
help_init_window(self, 20, 80); help_init_window(self, 21, 80);
#endif #endif
self->help->type = HELP_GLOBAL; self->help->type = HELP_GLOBAL;
break; break;
case 'r': case 'r':
help_init_window(self, 6, 80); help_init_window(self, 23, 80);
self->help->type = HELP_GROUP; self->help->type = HELP_GROUP;
break; break;

View File

@ -166,6 +166,11 @@ void line_info_add(ToxWindow *self, const char *timestr, const char *name1, cons
len += strlen(user_settings->line_normal) + 3; len += strlen(user_settings->line_normal) + 3;
break; break;
case IN_PRVT_MSG:
case OUT_PRVT_MSG:
len += strlen(user_settings->line_special) + 3;
break;
case CONNECTION: case CONNECTION:
len += strlen(user_settings->line_join) + 2; len += strlen(user_settings->line_join) + 2;
break; break;
@ -305,6 +310,8 @@ void line_info_print(ToxWindow *self)
case OUT_MSG_READ: case OUT_MSG_READ:
/* fallthrough */ /* fallthrough */
case IN_MSG: case IN_MSG:
case IN_PRVT_MSG:
case OUT_PRVT_MSG:
wattron(win, COLOR_PAIR(BLUE)); wattron(win, COLOR_PAIR(BLUE));
wprintw(win, "%s ", line->timestr); wprintw(win, "%s ", line->timestr);
wattroff(win, COLOR_PAIR(BLUE)); wattroff(win, COLOR_PAIR(BLUE));
@ -317,7 +324,10 @@ void line_info_print(ToxWindow *self)
nameclr = CYAN; nameclr = CYAN;
wattron(win, COLOR_PAIR(nameclr)); wattron(win, COLOR_PAIR(nameclr));
wprintw(win, "%s %s: ", user_settings->line_normal, line->name1); wprintw(win, "%s %s: ",(type != OUT_PRVT_MSG && type != IN_PRVT_MSG) ?
user_settings->line_normal :
user_settings->line_special,
line->name1);
wattroff(win, COLOR_PAIR(nameclr)); wattroff(win, COLOR_PAIR(nameclr));
if (line->msg[0] == '>') if (line->msg[0] == '>')

View File

@ -35,10 +35,12 @@ enum {
SYS_MSG, SYS_MSG,
IN_MSG, IN_MSG,
OUT_MSG, OUT_MSG,
OUT_MSG_READ, /* for sent messages that have received a read reply. don't set this with line_info_add */ OUT_MSG_READ, /* for sent messages that have received a read reply. */
IN_ACTION, IN_ACTION,
OUT_ACTION, OUT_ACTION,
OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */ OUT_ACTION_READ, /* same as OUT_MSG_READ but for actions */
IN_PRVT_MSG, /* PRVT should only be used for groups */
OUT_PRVT_MSG,
PROMPT, PROMPT,
CONNECTION, CONNECTION,
DISCONNECTION, DISCONNECTION,

View File

@ -287,11 +287,19 @@ size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum)
/* same as get_nick_truncate but for groupchats */ /* same as get_nick_truncate but for groupchats */
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum) int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
{ {
int len = tox_group_peername(m, groupnum, peernum, (uint8_t *) buf); TOX_ERR_GROUP_PEER_QUERY err;
size_t len = tox_group_peer_get_name_size(m, groupnum, peernum, &err);
if (len == -1) { if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
strcpy(buf, UNKNOWN_NAME); strcpy(buf, UNKNOWN_NAME);
len = strlen(UNKNOWN_NAME); len = strlen(UNKNOWN_NAME);
} else {
tox_group_peer_get_name(m, groupnum, peernum, (uint8_t *) buf, &err);
if (err != TOX_ERR_GROUP_PEER_QUERY_OK) {
strcpy(buf, UNKNOWN_NAME);
len = strlen(UNKNOWN_NAME);
}
} }
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1); len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
@ -301,13 +309,18 @@ int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum)
} }
/* copies data to msg buffer. /* copies data to msg buffer.
returns length of msg, which will be no larger than size-1 */ returns length of msg.
returns 0 and nulls msg if length is too big for buffer size */
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length) size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
{ {
size_t len = MIN(length, size - 1); if (length > size - 1) {
memcpy(msg, data, len); msg[0] = '\0';
msg[len] = '\0'; return 0;
return len; }
memcpy(msg, data, length);
msg[length] = '\0';
return length;
} }
/* returns index of the first instance of ch in s starting at idx. /* returns index of the first instance of ch in s starting at idx.

View File

@ -108,7 +108,8 @@ size_t get_nick_truncate(Tox *m, char *buf, uint32_t friendnum);
int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum); int get_group_nick_truncate(Tox *m, char *buf, int peernum, int groupnum);
/* copies data to msg buffer. /* copies data to msg buffer.
returns length of msg, which will be no larger than size-1 */ returns length of msg.
returns 0 and nulls msg if length is too big for buffer size */
size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length); size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length);
/* returns index of the first instance of ch in s starting at idx. /* returns index of the first instance of ch in s starting at idx.

View File

@ -51,9 +51,9 @@ extern FriendsList Friends;
FriendRequests FrndRequests; FriendRequests FrndRequests;
#ifdef AUDIO #ifdef AUDIO
#define AC_NUM_GLOB_COMMANDS 18 #define AC_NUM_GLOB_COMMANDS 19
#else #else
#define AC_NUM_GLOB_COMMANDS 16 #define AC_NUM_GLOB_COMMANDS 17
#endif /* AUDIO */ #endif /* AUDIO */
/* Array of global command names used for tab completion. */ /* Array of global command names used for tab completion. */
@ -67,6 +67,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = {
{ "/exit" }, { "/exit" },
{ "/group" }, { "/group" },
{ "/help" }, { "/help" },
{ "/join" },
{ "/log" }, { "/log" },
{ "/myid" }, { "/myid" },
{ "/nick" }, { "/nick" },

View File

@ -62,6 +62,7 @@ static struct ui_strings {
const char* line_quit; const char* line_quit;
const char* line_alert; const char* line_alert;
const char* line_normal; const char* line_normal;
const char* line_special;
const char* mplex_away; const char* mplex_away;
const char* mplex_away_note; const char* mplex_away_note;
@ -82,6 +83,7 @@ static struct ui_strings {
"line_quit", "line_quit",
"line_alert", "line_alert",
"line_normal", "line_normal",
"line_special",
"mplex_away", "mplex_away",
"mplex_away_note", "mplex_away_note",
}; };
@ -104,6 +106,7 @@ static void ui_defaults(struct user_settings* settings)
snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT); snprintf(settings->line_quit, LINE_HINT_MAX + 1, "%s", LINE_QUIT);
snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT); snprintf(settings->line_alert, LINE_HINT_MAX + 1, "%s", LINE_ALERT);
snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL); snprintf(settings->line_normal, LINE_HINT_MAX + 1, "%s", LINE_NORMAL);
snprintf(settings->line_special, LINE_HINT_MAX + 1, "%s", LINE_SPECIAL);
settings->mplex_away = MPLEX_ON; settings->mplex_away = MPLEX_ON;
snprintf (settings->mplex_away_note, snprintf (settings->mplex_away_note,
@ -321,6 +324,9 @@ int settings_load(struct user_settings *s, const char *patharg)
if ( config_setting_lookup_string(setting, ui_strings.line_normal, &str) ) { if ( config_setting_lookup_string(setting, ui_strings.line_normal, &str) ) {
snprintf(s->line_normal, sizeof(s->line_normal), "%s", str); snprintf(s->line_normal, sizeof(s->line_normal), "%s", str);
} }
if ( config_setting_lookup_string(setting, ui_strings.line_special, &str) ) {
snprintf(s->line_special, sizeof(s->line_special), "%s", str);
}
config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away); config_setting_lookup_bool (setting, ui_strings.mplex_away, &s->mplex_away);

View File

@ -49,6 +49,7 @@ struct user_settings {
char line_quit[LINE_HINT_MAX + 1]; char line_quit[LINE_HINT_MAX + 1];
char line_alert[LINE_HINT_MAX + 1]; char line_alert[LINE_HINT_MAX + 1];
char line_normal[LINE_HINT_MAX + 1]; char line_normal[LINE_HINT_MAX + 1];
char line_special[LINE_HINT_MAX + 1];
char download_path[PATH_MAX]; char download_path[PATH_MAX];
char chatlogs_path[PATH_MAX]; char chatlogs_path[PATH_MAX];
@ -104,6 +105,7 @@ enum {
#define LINE_QUIT "<--" #define LINE_QUIT "<--"
#define LINE_ALERT "-!-" #define LINE_ALERT "-!-"
#define LINE_NORMAL "---" #define LINE_NORMAL "---"
#define LINE_SPECIAL ">>>"
#define TIMESTAMP_DEFAULT "%H:%M:%S" #define TIMESTAMP_DEFAULT "%H:%M:%S"
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]" #define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
#define MPLEX_AWAY_NOTE "Detached from screen" #define MPLEX_AWAY_NOTE "Detached from screen"

View File

@ -47,6 +47,7 @@
#include "toxic.h" #include "toxic.h"
#include "windows.h" #include "windows.h"
#include "friendlist.h" #include "friendlist.h"
#include "groupchat.h"
#include "prompt.h" #include "prompt.h"
#include "misc_tools.h" #include "misc_tools.h"
#include "file_transfers.h" #include "file_transfers.h"
@ -251,7 +252,7 @@ static void print_init_messages(ToxWindow *toxwin)
line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]); line_info_add(toxwin, NULL, NULL, NULL, SYS_MSG, 0, 0, init_messages.msgs[i]);
} }
#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */ #define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.chat = 8) */
#define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */ #define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */
#define MAXNODES 50 #define MAXNODES 50
#define NODELEN (MAX_NODE_LINE - TOX_PUBLIC_KEY_SIZE - 7) #define NODELEN (MAX_NODE_LINE - TOX_PUBLIC_KEY_SIZE - 7)
@ -381,6 +382,17 @@ int init_connection(Tox *m)
return 4; return 4;
} }
static void load_groups(Tox *m)
{
size_t i;
size_t numgroups = tox_group_get_number_groups(m);
for (i = 0; i < numgroups; ++i) {
if (init_groupchat_win(m, i, NULL, 0) == -1)
tox_group_leave(m, i, NULL, 0, NULL);
}
}
static void load_friendlist(Tox *m) static void load_friendlist(Tox *m)
{ {
size_t i; size_t i;
@ -551,15 +563,26 @@ static void init_tox_callbacks(Tox *m)
tox_callback_friend_status(m, on_statuschange, NULL); tox_callback_friend_status(m, on_statuschange, NULL);
tox_callback_friend_status_message(m, on_statusmessagechange, NULL); tox_callback_friend_status_message(m, on_statusmessagechange, NULL);
tox_callback_friend_read_receipt(m, on_read_receipt, NULL); tox_callback_friend_read_receipt(m, on_read_receipt, NULL);
tox_callback_group_invite(m, on_groupinvite, NULL);
tox_callback_group_message(m, on_groupmessage, NULL);
tox_callback_group_action(m, on_groupaction, NULL);
tox_callback_group_namelist_change(m, on_group_namelistchange, NULL);
tox_callback_group_title(m, on_group_titlechange, NULL);
tox_callback_file_recv(m, on_file_recv, NULL); tox_callback_file_recv(m, on_file_recv, NULL);
tox_callback_file_chunk_request(m, on_file_chunk_request, NULL); tox_callback_file_chunk_request(m, on_file_chunk_request, NULL);
tox_callback_file_recv_control(m, on_file_control, NULL); tox_callback_file_recv_control(m, on_file_control, NULL);
tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL); tox_callback_file_recv_chunk(m, on_file_recv_chunk, NULL);
tox_callback_group_invite(m, on_group_invite, NULL);
tox_callback_group_message(m, on_group_message, NULL);
tox_callback_group_private_message(m, on_group_private_message, NULL);
tox_callback_group_peerlist_update(m, on_group_namelistchange, NULL);
tox_callback_group_peer_join(m, on_group_peer_join, NULL);
tox_callback_group_peer_exit(m, on_group_peer_exit, NULL);
tox_callback_group_peer_name(m, on_group_nick_change, NULL);
tox_callback_group_topic(m, on_group_topic_change, NULL);
// tox_callback_group_peer_limit(m, on_group_peer_limit, NULL);
// tox_callback_group_privacy_state(m, on_group_privacy_state, NULL);
// tox_callback_group_password(m, on_group_password, NULL);
tox_callback_group_self_join(m, on_group_self_join, NULL);
tox_callback_group_join_fail(m, on_group_rejected, NULL);
tox_callback_group_moderation(m, on_group_moderation, NULL);
} }
static void init_tox_options(struct Tox_Options *tox_opts) static void init_tox_options(struct Tox_Options *tox_opts)
@ -1171,6 +1194,7 @@ int main(int argc, char *argv[])
if (init_mplex_away_timer(m) == -1) if (init_mplex_away_timer(m) == -1)
queue_init_message("Failed to init mplex auto-away."); queue_init_message("Failed to init mplex auto-away.");
load_groups(m);
print_init_messages(prompt); print_init_messages(prompt);
cleanup_init_messages(); cleanup_init_messages();

View File

@ -107,11 +107,6 @@ void on_nickchange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t
void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata); void on_statuschange(Tox *m, uint32_t friendnumber, TOX_USER_STATUS status, void *userdata);
void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata); void on_statusmessagechange(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata);
void on_friendadded(Tox *m, uint32_t friendnumber, bool sort); void on_friendadded(Tox *m, uint32_t friendnumber, bool sort);
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void *userdata);
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void *userdata);
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length, void *userdata);
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata);
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, void *userdata);
void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata); void on_file_chunk_request(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, size_t length, void *userdata);
void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, void on_file_recv_chunk(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
size_t length, void *userdata); size_t length, void *userdata);
@ -120,5 +115,18 @@ void on_file_recv(Tox *m, uint32_t friendnumber, uint32_t filenumber, uint32_t k
const uint8_t *filename, size_t filename_length, void *userdata); const uint8_t *filename, size_t filename_length, void *userdata);
void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata); void on_typing_change(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata);
void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata); void on_read_receipt(Tox *m, uint32_t friendnumber, uint32_t receipt, void *userdata);
void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata);
void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
const uint8_t *message, size_t length, void *userdata);
void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *message, size_t length, void *userdata);
void on_group_namelistchange(Tox *m, uint32_t groupnumber, void *userdata);
void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peernumber, void *userdata);
void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *partmsg, size_t length, void *userdata);
void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *topic, size_t length, void *userdata);
void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *newname, size_t length, void *userdata);
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);
#endif /* #define TOXIC_H */ #endif /* #define TOXIC_H */

View File

@ -151,8 +151,18 @@ void on_friendadded(Tox *m, uint32_t friendnumber, bool sort)
store_data(m, DATA_FILE); store_data(m, DATA_FILE);
} }
void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *message, uint16_t length, void on_group_invite(Tox *m, int32_t friendnumber, const uint8_t *invite_data, size_t length, void *userdata)
void *userdata) {
size_t 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, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
const uint8_t *message, size_t length, void *userdata)
{ {
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length); length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
@ -161,56 +171,121 @@ void on_groupmessage(Tox *m, int groupnumber, int peernumber, const uint8_t *mes
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupMessage != NULL) if (windows[i].onGroupMessage != NULL)
windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, msg, length); windows[i].onGroupMessage(&windows[i], m, groupnumber, peernumber, type, msg, length);
} }
} }
void on_groupaction(Tox *m, int groupnumber, int peernumber, const uint8_t *action, uint16_t length, void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *message,
void *userdata) size_t length, void *userdata)
{ {
char msg[MAX_STR_SIZE + 1]; char msg[MAX_STR_SIZE + 1];
length = copy_tox_str(msg, sizeof(msg), (const char *) action, length); length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
size_t i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupAction != NULL) if (windows[i].onGroupPrivateMessage != NULL)
windows[i].onGroupAction(&windows[i], m, groupnumber, peernumber, msg, length); windows[i].onGroupPrivateMessage(&windows[i], m, groupnumber, peernumber, msg, length);
} }
} }
void on_groupinvite(Tox *m, int32_t friendnumber, uint8_t type, const uint8_t *group_pub_key, uint16_t length, void on_group_namelistchange(Tox *m, uint32_t groupnumber, void *userdata)
void *userdata)
{
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupInvite != NULL)
windows[i].onGroupInvite(&windows[i], m, friendnumber, type, (char *) group_pub_key, length);
}
}
void on_group_namelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata)
{ {
size_t i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupNamelistChange != NULL) if (windows[i].onGroupNamelistChange != NULL)
windows[i].onGroupNamelistChange(&windows[i], m, groupnumber, peernumber, change); windows[i].onGroupNamelistChange(&windows[i], m, groupnumber);
} }
} }
void on_group_titlechange(Tox *m, int groupnumber, int peernumber, const uint8_t *title, uint8_t length, void on_group_peer_join(Tox *m, uint32_t groupnumber, uint32_t peernumber, void *userdata)
void *userdata)
{ {
char data[MAX_STR_SIZE + 1]; size_t i;
length = copy_tox_str(data, sizeof(data), (const char *) title, length);
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupPeerJoin != NULL)
windows[i].onGroupPeerJoin(&windows[i], m, groupnumber, peernumber);
}
}
void on_group_peer_exit(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *partmsg, size_t length,
void *userdata)
{
char msg[MAX_STR_SIZE + 1];
if (length == 0 || !partmsg) {
strcpy(msg, "Quit");
length = strlen(msg);
} else {
length = copy_tox_str(msg, sizeof(msg), (const char *) partmsg, length);
}
size_t i; size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) { for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupTitleChange != NULL) if (windows[i].onGroupPeerExit != NULL)
windows[i].onGroupTitleChange(&windows[i], m, groupnumber, peernumber, data, length); windows[i].onGroupPeerExit(&windows[i], m, groupnumber, peernumber, msg, length);
}
}
void on_group_topic_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *topic, size_t length,
void *userdata)
{
char data[MAX_STR_SIZE + 1];
length = copy_tox_str(data, sizeof(data), (const char *) topic, length);
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupTopicChange != NULL)
windows[i].onGroupTopicChange(&windows[i], m, groupnumber, peernumber, data, length);
}
}
void on_group_nick_change(Tox *m, uint32_t groupnumber, uint32_t peernumber, const uint8_t *newname, size_t length,
void *userdata)
{
char name[TOXIC_MAX_NAME_LENGTH + 1];
length = copy_tox_str(name, sizeof(name), (const char *) newname, length);
filter_str(name, length);
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupNickChange != NULL)
windows[i].onGroupNickChange(&windows[i], m, groupnumber, peernumber, name, length);
}
}
void on_group_self_join(Tox *m, uint32_t groupnumber, void *userdata)
{
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupSelfJoin != NULL)
windows[i].onGroupSelfJoin(&windows[i], m, groupnumber);
}
}
void on_group_rejected(Tox *m, uint32_t groupnumber, TOX_GROUP_JOIN_FAIL type, void *userdata)
{
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupRejected != NULL)
windows[i].onGroupRejected(&windows[i], m, groupnumber, type);
}
}
void on_group_moderation(Tox *m, uint32_t groupnumber, uint32_t source_peernum, uint32_t target_peernum,
TOX_GROUP_MOD_EVENT type, void *userdata)
{
size_t i;
for (i = 0; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i].onGroupModeration != NULL)
windows[i].onGroupModeration(&windows[i], m, groupnumber, source_peernum, target_peernum, type);
} }
} }
@ -595,7 +670,7 @@ void kill_all_windows(Tox *m)
if (windows[i].is_chat) if (windows[i].is_chat)
kill_chat_window(&windows[i], m); kill_chat_window(&windows[i], m);
else if (windows[i].is_groupchat) else if (windows[i].is_groupchat)
close_groupchat(&windows[i], m, i); close_groupchat(&windows[i], m, windows[i].num);
} }
kill_prompt_window(prompt); kill_prompt_window(prompt);

View File

@ -121,11 +121,6 @@ struct ToxWindow {
void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t); void(*onNickChange)(ToxWindow *, Tox *, uint32_t, const char *, size_t);
void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS); void(*onStatusChange)(ToxWindow *, Tox *, uint32_t, TOX_USER_STATUS);
void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t); void(*onStatusMessageChange)(ToxWindow *, uint32_t, const char *, size_t);
void(*onGroupMessage)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupAction)(ToxWindow *, Tox *, int, int, const char *, uint16_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, uint8_t, const char *, uint16_t);
void(*onGroupNamelistChange)(ToxWindow *, Tox *, int, int, uint8_t);
void(*onGroupTitleChange)(ToxWindow *, Tox *, int, int, const char *, uint8_t);
void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t); void(*onFileChunkRequest)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, size_t);
void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t); void(*onFileRecvChunk)(ToxWindow *, Tox *, uint32_t, uint32_t, uint64_t, const char *, size_t);
void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL); void(*onFileControl)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_FILE_CONTROL);
@ -133,6 +128,18 @@ struct ToxWindow {
void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool); void(*onTypingChange)(ToxWindow *, Tox *, uint32_t, bool);
void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t); void(*onReadReceipt)(ToxWindow *, Tox *, uint32_t, uint32_t);
void(*onGroupInvite)(ToxWindow *, Tox *, int32_t, const char *, size_t);
void(*onGroupMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, TOX_MESSAGE_TYPE, const char *, size_t);
void(*onGroupPrivateMessage)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
void(*onGroupNamelistChange)(ToxWindow *, Tox *, uint32_t);
void(*onGroupPeerJoin)(ToxWindow *, Tox *, uint32_t, uint32_t);
void(*onGroupPeerExit)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
void(*onGroupNickChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
void(*onGroupTopicChange)(ToxWindow *, Tox *, uint32_t, uint32_t, const char *, size_t);
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);
#ifdef AUDIO #ifdef AUDIO
void(*onInvite)(ToxWindow *, ToxAv *, int); void(*onInvite)(ToxWindow *, ToxAv *, int);
@ -146,7 +153,6 @@ struct ToxWindow {
void(*onEnd)(ToxWindow *, ToxAv *, int); void(*onEnd)(ToxWindow *, ToxAv *, int);
void(*onRequestTimeout)(ToxWindow *, ToxAv *, int); void(*onRequestTimeout)(ToxWindow *, ToxAv *, int);
void(*onPeerTimeout)(ToxWindow *, ToxAv *, int); void(*onPeerTimeout)(ToxWindow *, ToxAv *, int);
void(*onWriteDevice)(ToxWindow *, Tox *, int, int, const int16_t *, unsigned int, uint8_t, unsigned int);
int call_idx; /* If in a call will have this index set, otherwise it's -1. int call_idx; /* If in a call will have this index set, otherwise it's -1.
* Don't modify outside av callbacks. */ * Don't modify outside av callbacks. */