Skip to content

Commit

Permalink
feat: Allow friend invites from group and conference windows
Browse files Browse the repository at this point in the history
Friends from the friend list can now be invited to groups and
conferences with the /invite and /cinvite commands respectively.
  • Loading branch information
JFreegman committed Dec 23, 2024
1 parent 76d6b1e commit 441dc89
Show file tree
Hide file tree
Showing 12 changed files with 242 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/chat_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ void cmd_cancelfile(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, cha
close_file_transfer(self, toxic, ft, TOX_FILE_CONTROL_CANCEL, msg, silent);
}

void cmd_conference_invite(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
void cmd_invite_to_conference(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
{
UNUSED_VAR(window);

Expand Down Expand Up @@ -275,7 +275,7 @@ void cmd_group_accept(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, c
}
}

void cmd_group_invite(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
void cmd_invite_to_group(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
{
if (toxic == NULL || self == NULL) {
return;
Expand Down
4 changes: 2 additions & 2 deletions src/chat_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@

void cmd_autoaccept_files(WINDOW *window, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_cancelfile(WINDOW *window, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_conference_invite(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_invite_to_conference(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_conference_join(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_group_accept(WINDOW *window, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_group_invite(WINDOW *window, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_invite_to_group(WINDOW *window, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_game_join(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_savefile(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_sendfile(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
Expand Down
19 changes: 18 additions & 1 deletion src/conference.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "autocomplete.h"
#include "conference.h"
#include "execute.h"
#include "friendlist.h"
#include "help.h"
#include "input.h"
#include "line_info.h"
Expand Down Expand Up @@ -67,14 +68,15 @@ static const char *const conference_cmd_list[] = {
#endif
"/avatar",
"/chatid",
"/cinvite",
"/clear",
"/close",
"/color",
"/conference",
"/connect",
"/decline",
"/exit",
"/group",
"/conference",
#ifdef GAMES
"/game",
#endif
Expand Down Expand Up @@ -662,6 +664,7 @@ static void set_peer_audio_position(Tox *tox, uint32_t conferencenum, uint32_t p
const float angle = asinf(peer_posn - (float)(num_posns - 1) / 2);
set_source_position(peer->audio_out_idx, sinf(angle), cosf(angle), 0);
}

#endif // AUDIO


Expand Down Expand Up @@ -965,6 +968,19 @@ static bool conference_onKey(ToxWindow *self, Toxic *toxic, wint_t key, bool ltr
}
} else if (wcsncmp(ctx->line, L"/avatar ", wcslen(L"/avatar ")) == 0) {
diff = dir_match(self, toxic, ctx->line, L"/avatar");
} else if (wcsncmp(ctx->line, L"/cinvite ", wcslen(L"/cinvite ")) == 0) {
size_t num_friends = friendlist_get_count();
char **friend_names = (char **) malloc_ptr_array(num_friends, TOX_MAX_NAME_LENGTH);

if (friend_names != NULL) {
friendlist_get_names(friend_names, num_friends, TOX_MAX_NAME_LENGTH);
diff = complete_line(self, toxic, (const char *const *) friend_names, num_friends);
free_ptr_array((void **) friend_names);
} else {
diff = -1;
num_friends = 0;
fprintf(stderr, "Failed to allocate memory for friends name list\n");
}
}

#ifdef PYTHON
Expand Down Expand Up @@ -1602,4 +1618,5 @@ float conference_get_VAD_threshold(uint32_t conferencenum)

return device_get_VAD_threshold(chat->audio_in_idx);
}

#endif // AUDIO
59 changes: 59 additions & 0 deletions src/conference_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <string.h>

#include "conference.h"
#include "friendlist.h"
#include "line_info.h"
#include "log.h"
#include "misc_tools.h"
Expand Down Expand Up @@ -51,6 +52,63 @@ void cmd_conference_chatid(WINDOW *window, ToxWindow *self, Toxic *toxic, int ar
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "%s", id_string);
}

void cmd_conference_invite(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
{
UNUSED_VAR(window);

if (toxic == NULL || self == NULL) {
return;
}

Tox *tox = toxic->tox;
const Client_Config *c_config = toxic->c_config;

if (argc != 1) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Friend name required.");
return;
}

const char *nick = argv[1];
const int64_t friend_number = get_friend_number_name(nick, strlen(nick));

if (friend_number == -1) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0,
"Friend '%s' not found (names are case-sensitive)", nick);
return;
}

if (friend_number == -2) {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0,
"There are multiple friends in your friend list with this name. To invite this friend, navigate to their chat window and try again");
return;
}

const long int conferencenum = self->num;

Tox_Err_Conference_Invite err;

if (!tox_conference_invite(tox, (uint32_t)friend_number, conferencenum, &err)) {
switch (err) {
case TOX_ERR_GROUP_INVITE_FRIEND_FRIEND_NOT_FOUND: {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "%s is not in your friends list.", nick);
return;
}

case TOX_ERR_GROUP_INVITE_FRIEND_INVITE_FAIL: {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Friend is offline.");
return;
}

default: {
line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Invite failed (error %d)", err);
return;
}
}
}

line_info_add(self, c_config, false, NULL, NULL, SYS_MSG, 0, 0, "Invited %s to the conference.", nick);
}

void cmd_conference_set_title(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE])
{
UNUSED_VAR(window);
Expand Down Expand Up @@ -248,4 +306,5 @@ void cmd_conference_push_to_talk(WINDOW *window, ToxWindow *self, Toxic *toxic,

print_err(self, c_config, enable ? "Push-To-Talk is enabled. Push F2 to activate" : "Push-To-Talk is disabled");
}

#endif /* AUDIO */
1 change: 1 addition & 0 deletions src/conference_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "windows.h"

void cmd_conference_chatid(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_conference_invite(WINDOW *window, ToxWindow *self, Toxic *toxic, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_conference_set_title(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_enable_audio(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
void cmd_conference_mute(WINDOW *, ToxWindow *, Toxic *, int argc, char (*argv)[MAX_STR_SIZE]);
Expand Down
10 changes: 7 additions & 3 deletions src/execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ static struct cmd_func global_commands[] = {
static struct cmd_func chat_commands[] = {
{ "/autoaccept", cmd_autoaccept_files },
{ "/cancel", cmd_cancelfile },
{ "/cinvite", cmd_conference_invite },
{ "/cinvite", cmd_invite_to_conference },
{ "/cjoin", cmd_conference_join },
{ "/gaccept", cmd_group_accept },
{ "/invite", cmd_group_invite },
{ "/invite", cmd_invite_to_group },
#ifdef GAMES
{ "/play", cmd_game_join },
#endif
Expand All @@ -99,6 +99,7 @@ static struct cmd_func chat_commands[] = {

static struct cmd_func conference_commands[] = {
{ "/chatid", cmd_conference_chatid },
{ "/cinvite", cmd_conference_invite },
{ "/title", cmd_conference_set_title },

#ifdef AUDIO
Expand All @@ -112,8 +113,9 @@ static struct cmd_func conference_commands[] = {

static struct cmd_func groupchat_commands[] = {
{ "/chatid", cmd_chatid },
{ "/disconnect", cmd_disconnect },
{ "/disconnect", cmd_disconnect },
{ "/ignore", cmd_ignore },
{ "/invite", cmd_group_invite },
{ "/kick", cmd_kick },
{ "/list", cmd_list },
{ "/locktopic", cmd_set_topic_lock },
Expand All @@ -137,9 +139,11 @@ static struct cmd_func groupchat_commands[] = {
static const char special_commands[][MAX_CMDNAME_SIZE] = {
"/add",
"/avatar",
"/cinvite",
"/gaccept",
"/group",
"/ignore",
"/invite",
"/kick",
"/mod",
"/nick",
Expand Down
42 changes: 42 additions & 0 deletions src/friendlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,24 @@ void disable_friend_window(uint32_t f_num)
Friends.list[f_num].window_id = -1;
}

size_t friendlist_get_count(void)
{
return Friends.num_friends;
}

void friendlist_get_names(char **names, size_t max_names, size_t max_name_size)
{
if (Friends.num_friends == 0) {
return;
}

const size_t bytes_to_copy = MIN(sizeof(Friends.list[0].name), max_name_size);

for (size_t i = 0; i < max_names && i < Friends.num_friends; ++i) {
snprintf(names[i], bytes_to_copy, "%s", Friends.list[i].name);
}
}

#ifdef AUDIO
static void friendlist_onAV(ToxWindow *self, Toxic *toxic, uint32_t friend_number, int state)
{
Expand Down Expand Up @@ -1455,6 +1473,7 @@ static void friendlist_onAV(ToxWindow *self, Toxic *toxic, uint32_t friend_numbe
set_active_window_by_id(toxic->windows, window_id);
}
}

#endif /* AUDIO */

/* Returns a friend's status */
Expand All @@ -1477,6 +1496,29 @@ Tox_Connection get_friend_connection_status(uint32_t friendnumber)
return Friends.list[friendnumber].connection_status;
}

int64_t get_friend_number_name(const char *name, uint16_t length)
{
int64_t num = -1;
bool match_found = false;

for (size_t i = 0; i < Friends.max_idx; ++i) {
if (length != Friends.list[i].namelength) {
continue;
}

if (memcmp(name, Friends.list[i].name, length) == 0) {
if (match_found) {
return -2;
}

num = Friends.list[i].num;
match_found = true;
}
}

return num;
}

/*
* Returns true if friend associated with `public_key` is in the block list.
*
Expand Down
23 changes: 23 additions & 0 deletions src/friendlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ void friendlist_onFriendAdded(ToxWindow *self, Toxic *toxic, uint32_t num, bool
Tox_User_Status get_friend_status(uint32_t friendnumber);
Tox_Connection get_friend_connection_status(uint32_t friendnumber);

/*
* Returns the number of friends in the friend list.
*/
size_t friendlist_get_count(void);

/*
* Copies names from the friends list into the `names` array.
*
* @max_names The maximum number of names to copy.
* @max_name_size The maximum number of bytes to copy per name.
*/
void friendlist_get_names(char **names, size_t max_names, size_t max_name_size);

/*
* Loads the list of blocked peers from `path`.
*
Expand Down Expand Up @@ -162,6 +175,16 @@ bool friend_get_auto_accept_files(uint32_t friendnumber);
*/
uint16_t get_friend_name(char *buf, size_t buf_size, uint32_t friendnumber);

/*
* Returns the friend number associated with `name`.
*
* @length The length of the name.
*
* Returns -1 if `name` does not designate a friend in the friend list.
* Returns -2 if `name` matches more than one friend in the friend list.
*/
int64_t get_friend_number_name(const char *name, uint16_t length);

/*
* Puts a friend's public key in `pk`, which must have room for at least
* TOX_PUBLIC_KEY_SIZE bytes.
Expand Down
Loading

0 comments on commit 441dc89

Please sign in to comment.