mirror of
https://github.com/Tha14/toxic.git
synced 2025-04-08 01:32:45 +02:00
Compare commits
71 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
30d01127e7 | ||
|
85ab7592c9 | ||
|
6cdd01da25 | ||
|
69e4ed452d | ||
|
4c77e80a7f | ||
|
ff669be8d1 | ||
|
5d757e1230 | ||
|
70ab422acc | ||
|
2a052edb9e | ||
|
efbfa2c95c | ||
|
3f3e848b6f | ||
8d125d5e6b | |||
fbdc20dfa5 | |||
|
e8388bf20c | ||
|
398aecdd92 | ||
|
57a439c9b4 | ||
|
0aea5d7fbe | ||
|
e56edd556f | ||
|
7ed031b9bf | ||
6ef2c784c5 | |||
|
058057c64d | ||
146b00b8ca | |||
|
85024bfce8 | ||
129bb6ba68 | |||
|
68b4713ef7 | ||
|
46eb69412e | ||
|
f47b4c1c3c | ||
|
22eb6797b1 | ||
|
0edad7b862 | ||
|
cc80da00fc | ||
|
32efac931c | ||
|
4f936e5f9c | ||
|
529d905bd0 | ||
|
631b1d8b08 | ||
|
9ac8d517e9 | ||
|
90152f5e17 | ||
|
4d501aeb2a | ||
|
1b9f4f337a | ||
|
812f2d1ff9 | ||
|
2eeb1de20d | ||
|
ba896fd124 | ||
|
3ff3516e42 | ||
|
2ef3d68173 | ||
|
7a099f86c8 | ||
|
9a629072b3 | ||
|
27259ff23f | ||
|
f786b7ae6a | ||
|
cd4a5e5fde | ||
|
0b32b985f1 | ||
|
5851cb2dd8 | ||
|
1847025213 | ||
|
1a2320b035 | ||
|
1211899a40 | ||
|
5dabaac804 | ||
|
4f26171e3f | ||
|
fa075f1972 | ||
|
cbf3145aee | ||
|
06bdb0d167 | ||
|
0212391d7d | ||
|
535a8402d6 | ||
|
2c51afd9ef | ||
|
4aca8b6ecb | ||
|
28be56aad9 | ||
|
38004367a1 | ||
|
5499bb6645 | ||
|
ed8ba89cd8 | ||
|
812210d63f | ||
|
cec96e1ea3 | ||
|
eb7e6151a2 | ||
|
22ca3704d2 | ||
|
fdfaaf953f |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
libx11-dev
|
||||
python3-dev
|
||||
pkg-config &&
|
||||
git clone --depth=1 https://github.com/TokTok/c-toxcore &&
|
||||
git clone --depth=1 --recursive https://github.com/TokTok/c-toxcore &&
|
||||
cd c-toxcore &&
|
||||
cmake . -B_build -DBOOTSTRAP_DAEMON=OFF &&
|
||||
cd _build &&
|
||||
@ -85,7 +85,7 @@ jobs:
|
||||
make
|
||||
python3-dev
|
||||
pkg-config &&
|
||||
git clone --depth=1 https://github.com/TokTok/c-toxcore &&
|
||||
git clone --depth=1 --recursive https://github.com/TokTok/c-toxcore &&
|
||||
cd c-toxcore &&
|
||||
cmake . -B_build -DBOOTSTRAP_DAEMON=OFF &&
|
||||
cd _build &&
|
||||
|
@ -55,9 +55,9 @@ author = 'Jakob Kreuze'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.11.3'
|
||||
version = '0.12.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.11.3'
|
||||
release = '0.12.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Version
|
||||
TOXIC_VERSION = 0.11.3
|
||||
TOXIC_VERSION = 0.12.0
|
||||
REV = $(shell git rev-list HEAD --count 2>/dev/null || echo -n "error")
|
||||
ifneq (, $(findstring error, $(REV)))
|
||||
VERSION = $(TOXIC_VERSION)
|
||||
|
16
doc/toxic.1
16
doc/toxic.1
@ -1,13 +1,13 @@
|
||||
'\" t
|
||||
.\" Title: toxic
|
||||
.\" Author: [see the "AUTHORS" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
||||
.\" Date: 2021-05-24
|
||||
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
|
||||
.\" Date: 2021-12-05
|
||||
.\" Manual: Toxic Manual
|
||||
.\" Source: toxic __VERSION__
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "TOXIC" "1" "2021\-05\-24" "toxic __VERSION__" "Toxic Manual"
|
||||
.TH "TOXIC" "1" "2021\-12\-05" "toxic __VERSION__" "Toxic Manual"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@ -156,14 +156,14 @@ Configuration example\&.
|
||||
\-Screen flickering sometimes occurs on certain terminals\&.
|
||||
.sp
|
||||
\-Resizing the terminal window when a game window is open will break things\&.
|
||||
.SH "LINKS"
|
||||
.sp
|
||||
Project page: https://github\&.com/JFreegman/toxic
|
||||
.sp
|
||||
Tox development group public key: 360497DA684BCE2A500C1AF9B3A5CE949BBB9F6FB1F91589806FB04CA039E313
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
JFreegman <JFreegman@gmail\&.com>
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBtoxic\&.conf\fR(5)
|
||||
.SH "LINKS"
|
||||
.sp
|
||||
Project page: https://github\&.com/JFreegman/toxic
|
||||
.sp
|
||||
IRC channel: irc\&.libera\&.chat#tox
|
||||
|
@ -93,6 +93,12 @@ behaviour.
|
||||
|
||||
-Resizing the terminal window when a game window is open will break things.
|
||||
|
||||
LINKS
|
||||
-----
|
||||
Project page: <https://github.com/JFreegman/toxic>
|
||||
|
||||
Tox development group public key: 360497DA684BCE2A500C1AF9B3A5CE949BBB9F6FB1F91589806FB04CA039E313
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
JFreegman <JFreegman@gmail.com>
|
||||
@ -100,9 +106,3 @@ JFreegman <JFreegman@gmail.com>
|
||||
SEE ALSO
|
||||
--------
|
||||
*toxic.conf*(5)
|
||||
|
||||
LINKS
|
||||
-----
|
||||
Project page: <https://github.com/JFreegman/toxic>
|
||||
|
||||
IRC channel: irc.libera.chat#tox
|
||||
|
@ -1,13 +1,13 @@
|
||||
'\" t
|
||||
.\" Title: toxic.conf
|
||||
.\" Author: [see the "AUTHORS" section]
|
||||
.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
|
||||
.\" Date: 2021-05-24
|
||||
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
|
||||
.\" Date: 2022-06-27
|
||||
.\" Manual: Toxic Manual
|
||||
.\" Source: toxic __VERSION__
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "TOXIC\&.CONF" "5" "2021\-05\-24" "toxic __VERSION__" "Toxic Manual"
|
||||
.TH "TOXIC\&.CONF" "5" "2022\-06\-27" "toxic __VERSION__" "Toxic Manual"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Define some portability stuff
|
||||
.\" -----------------------------------------------------------------
|
||||
@ -138,6 +138,11 @@ Show welcome message on startup\&. true or false
|
||||
Enable friend connection change notifications\&. true or false
|
||||
.RE
|
||||
.PP
|
||||
\fBshow_group_connection_msg\fR
|
||||
.RS 4
|
||||
Enable group connection change notifications (does not include quit messages)\&. true or false
|
||||
.RE
|
||||
.PP
|
||||
\fBnodelist_update_freq\fR
|
||||
.RS 4
|
||||
How often in days to update the DHT nodes list\&. (integer; 0 to disable)
|
||||
@ -412,14 +417,14 @@ __DATADIR__/toxic\&.conf\&.example
|
||||
.RS 4
|
||||
Configuration example\&.
|
||||
.RE
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBtoxic\fR(1)
|
||||
.SH "RESOURCES"
|
||||
.sp
|
||||
Project page: https://github\&.com/JFreegman/toxic
|
||||
.sp
|
||||
IRC channel: irc\&.libera\&.chat#tox
|
||||
Tox development group public key: 360497DA684BCE2A500C1AF9B3A5CE949BBB9F6FB1F91589806FB04CA039E313
|
||||
.SH "AUTHORS"
|
||||
.sp
|
||||
JFreegman <JFreegman@gmail\&.com>
|
||||
.SH "SEE ALSO"
|
||||
.sp
|
||||
\fBtoxic\fR(1)
|
||||
|
@ -87,6 +87,9 @@ OPTIONS
|
||||
*show_connection_msg*;;
|
||||
Enable friend connection change notifications. true or false
|
||||
|
||||
*show_group_connection_msg*;;
|
||||
Enable group connection change notifications (does not include quit messages). true or false
|
||||
|
||||
*nodelist_update_freq*;;
|
||||
How often in days to update the DHT nodes list. (integer; 0 to disable)
|
||||
|
||||
@ -260,19 +263,19 @@ FILES
|
||||
{datadir}/toxic.conf.example::
|
||||
Configuration example.
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
Project page: <https://github.com/JFreegman/toxic>
|
||||
|
||||
Tox development group public key: 360497DA684BCE2A500C1AF9B3A5CE949BBB9F6FB1F91589806FB04CA039E313
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
JFreegman <JFreegman@gmail.com>
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*toxic*(1)
|
||||
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
Project page: <https://github.com/JFreegman/toxic>
|
||||
|
||||
IRC channel: irc.libera.chat#tox
|
||||
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
JFreegman <JFreegman@gmail.com>
|
||||
|
@ -1 +0,0 @@
|
||||
toxme.io 1A39E7A5D5FA9CF155C751570A32E625698A60A55F6D88028F949F66144F4F25
|
@ -56,6 +56,9 @@ ui = {
|
||||
// true to show friend connection change messages on the home screen
|
||||
show_connection_msg=true;
|
||||
|
||||
// true to show peer connection change messages in groups (setting to false does not include user quit messages)
|
||||
show_group_connection_msg=true;
|
||||
|
||||
// How often in days to update the DHT nodes list. (0 to disable updates)
|
||||
nodeslist_update_freq=7;
|
||||
|
||||
|
@ -114,7 +114,6 @@ apk add \
|
||||
libsodium-dev \
|
||||
libsodium-static \
|
||||
linux-headers \
|
||||
msgpack-c-dev \
|
||||
ncurses-dev \
|
||||
ncurses-static \
|
||||
ncurses-terminfo \
|
||||
@ -137,20 +136,32 @@ mkdir -p "$BUILD_DIR"
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
# The git hash of the c-toxcore version we're using
|
||||
TOXCORE_VERSION="v0.2.16"
|
||||
TOXCORE_VERSION="172f279dc0647a538b30e62c96bab8bb1b0c8960"
|
||||
|
||||
# The sha256sum of the c-toxcore tarball for TOXCORE_VERSION
|
||||
TOXCORE_HASH="653aa42654b607f0940cecfac873e9ce55605119a90d1dc454d1090ff6ca29c0"
|
||||
TOXCORE_HASH="9884d4ad9b80917e22495c2ebe7a76c509fb98c61031824562883225e66684ae"
|
||||
|
||||
TOXCORE_FILENAME="c-toxcore-$TOXCORE_VERSION.tar.gz"
|
||||
|
||||
wget --timeout=10 -O "$TOXCORE_FILENAME" "https://github.com/TokTok/c-toxcore/archive/$TOXCORE_VERSION.tar.gz"
|
||||
check_sha256 "$TOXCORE_HASH" "$TOXCORE_FILENAME"
|
||||
|
||||
tar -o -xf "$TOXCORE_FILENAME"
|
||||
rm "$TOXCORE_FILENAME"
|
||||
|
||||
cd c-toxcore*
|
||||
mkdir -p "third_party" && cd "third_party"
|
||||
|
||||
CMP_VERSION="074e0df43e8a61ea938c4f77f65d1fbccc0c3bf9"
|
||||
CMP_FILENAME="cmp-$CMP_VERSION.tar.gz"
|
||||
wget --timeout=10 -O "$CMP_FILENAME" "https://github.com/TokTok/cmp/archive/$CMP_VERSION.tar.gz"
|
||||
tar -o -xf "$CMP_FILENAME"
|
||||
|
||||
mv cmp-*/* 'cmp/'
|
||||
cd ..
|
||||
|
||||
cmake -B_build -H. \
|
||||
-DUSE_TEST_NETWORK=OFF \
|
||||
-DENABLE_STATIC=ON \
|
||||
-DENABLE_SHARED=OFF \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
@ -169,8 +180,8 @@ cmake --build _build --target install
|
||||
# location with SSL_CERT_FILE env variable.
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
CURL_VERSION="7.81.0"
|
||||
CURL_HASH="ac8e1087711084548d788ef18b9b732c8de887457b81f616fc681d1044b32f98"
|
||||
CURL_VERSION="7.88.1"
|
||||
CURL_HASH="cdb38b72e36bc5d33d5b8810f8018ece1baa29a8f215b4495e495ded82bbf3c7"
|
||||
CURL_FILENAME="curl-$CURL_VERSION.tar.gz"
|
||||
|
||||
wget --timeout=10 -O "$CURL_FILENAME" "https://curl.haxx.se/download/$CURL_FILENAME"
|
||||
|
@ -42,7 +42,7 @@
|
||||
extern struct user_settings *user_settings;
|
||||
|
||||
/* URL that we get the JSON encoded nodes list from. */
|
||||
#define NODES_LIST_URL 0 // This should be empty until NGC merges with mainnet
|
||||
#define NODES_LIST_URL "https://nodes.tox.chat/json"
|
||||
|
||||
#define DEFAULT_NODES_FILENAME "DHTnodes.json"
|
||||
|
||||
@ -79,29 +79,6 @@ extern struct user_settings *user_settings;
|
||||
/* Maximum allowable size of the nodes list */
|
||||
#define MAX_NODELIST_SIZE (MAX_RECV_CURL_DATA_SIZE)
|
||||
|
||||
// TODO(Jfreegman): Remove this before production
|
||||
static uint8_t const TESTNET_KEY[] = {
|
||||
0x79, 0xCA, 0xDA, 0x49, 0x74, 0xB0, 0x92, 0x6F,
|
||||
0x28, 0x6F, 0x02, 0x5C, 0xD5, 0xFF, 0xDF, 0x3E,
|
||||
0x65, 0x4A, 0x37, 0x58, 0xC5, 0x3E, 0x02, 0x73,
|
||||
0xEC, 0xFC, 0x4D, 0x12, 0xC2, 0x1D, 0xCA, 0x48,
|
||||
};
|
||||
|
||||
// TODO(Jfreegman): Remove this before production
|
||||
#define TESTNET_PORT 33445
|
||||
|
||||
#define TESTNET_IP "172.93.52.70"
|
||||
|
||||
static uint8_t const TESTNET_KEY2[] = {
|
||||
0x5E, 0x47, 0xBA, 0x1D, 0xC3, 0x91, 0x3E, 0xB2,
|
||||
0xCB, 0xF2, 0xD6, 0x4C, 0xE4, 0xF2, 0x3D, 0x8B,
|
||||
0xFE, 0x53, 0x91, 0xBF, 0xAB, 0xE5, 0xC4, 0x3C,
|
||||
0x5B, 0xAD, 0x13, 0xF0, 0xA4, 0x14, 0xCD, 0x77,
|
||||
};
|
||||
|
||||
#define TESTNET_PORT2 38445
|
||||
#define TESTNET_IP2 "tox.plastiras.org"
|
||||
|
||||
static struct Thread_Data {
|
||||
pthread_t tid;
|
||||
pthread_attr_t attr;
|
||||
@ -298,11 +275,6 @@ on_exit:
|
||||
*/
|
||||
static int update_DHT_nodeslist(const char *nodes_path)
|
||||
{
|
||||
if (NODES_LIST_URL == 0) { // TODO: Remove this when NGC merges with mainnet
|
||||
fprintf(stderr, "Skipping DHT Nodes list fetching (remove before production)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!nodeslist_needs_update(nodes_path)) {
|
||||
return 0;
|
||||
}
|
||||
@ -583,24 +555,6 @@ on_exit:
|
||||
*/
|
||||
int load_DHT_nodeslist(void)
|
||||
{
|
||||
// TODO(Jfreegman): Remove this before production
|
||||
fprintf(stderr, "Adding NGC testnet node - remove this before production\n");
|
||||
|
||||
struct Node *node = &Nodes.list[0];
|
||||
node->have_ip4 = true;
|
||||
node->port = TESTNET_PORT;
|
||||
memcpy(node->key, TESTNET_KEY, sizeof(TESTNET_KEY));
|
||||
memcpy(node->ip4, TESTNET_IP, sizeof(TESTNET_IP));
|
||||
|
||||
struct Node *node2 = &Nodes.list[1];
|
||||
node2->have_ip6 = true;
|
||||
node2->port = TESTNET_PORT2;
|
||||
memcpy(node2->key, TESTNET_KEY2, sizeof(TESTNET_KEY2));
|
||||
memcpy(node2->ip6, TESTNET_IP2, sizeof(TESTNET_IP2));
|
||||
|
||||
Nodes.count = 2;
|
||||
|
||||
#if 0
|
||||
if (thread_data.active) {
|
||||
return -1;
|
||||
}
|
||||
@ -623,7 +577,6 @@ int load_DHT_nodeslist(void)
|
||||
thread_data.active = false;
|
||||
return -5;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ static void set_self_typingstatus(ToxWindow *self, Tox *m, bool is_typing)
|
||||
|
||||
ChatContext *ctx = self->chatwin;
|
||||
|
||||
TOX_ERR_SET_TYPING err;
|
||||
Tox_Err_Set_Typing err;
|
||||
tox_self_set_typing(m, self->num, is_typing, &err);
|
||||
|
||||
if (err != TOX_ERR_SET_TYPING_OK) {
|
||||
|
@ -130,6 +130,7 @@ static struct cmd_func groupchat_commands[] = {
|
||||
{ "/list", cmd_list },
|
||||
{ "/locktopic", cmd_set_topic_lock },
|
||||
{ "/mod", cmd_mod },
|
||||
{ "/nick", cmd_group_nick },
|
||||
{ "/passwd", cmd_set_passwd },
|
||||
{ "/peerlimit", cmd_set_peerlimit },
|
||||
{ "/privacy", cmd_set_privacy },
|
||||
@ -141,10 +142,6 @@ static struct cmd_func groupchat_commands[] = {
|
||||
{ "/unsilence", cmd_unsilence },
|
||||
{ "/voice", cmd_set_voice },
|
||||
{ "/whois", cmd_whois },
|
||||
#ifdef AUDIO
|
||||
{ "/mute", cmd_mute },
|
||||
{ "/sense", cmd_sense },
|
||||
#endif /* AUDIO */
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
@ -1129,7 +1129,7 @@ int game_packet_send(const GameData *game, const uint8_t *data, size_t length, G
|
||||
memcpy(packet + 1 + GAME_PACKET_HEADER_SIZE, data, length);
|
||||
packet_length += length;
|
||||
|
||||
TOX_ERR_FRIEND_CUSTOM_PACKET err;
|
||||
Tox_Err_Friend_Custom_Packet err;
|
||||
|
||||
if (!tox_friend_send_lossless_packet(game->tox, game->friend_number, packet, packet_length, &err)) {
|
||||
fprintf(stderr, "failed to send game packet: error %d\n", err);
|
||||
|
@ -173,10 +173,16 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX
|
||||
|
||||
char id_bin[TOX_ADDRESS_SIZE] = {0};
|
||||
|
||||
const bool is_tox_id = (char_find(0, id, '@') == arg_length) && (arg_length >= TOX_ADDRESS_SIZE * 2);
|
||||
const bool is_domain = char_find(0, id, '@') != arg_length;
|
||||
const bool valid_id_size = arg_length >= TOX_ADDRESS_SIZE * 2; // arg_length may include invite message
|
||||
|
||||
if (!is_tox_id) {
|
||||
name_lookup(self, m, id_bin, id, msg);
|
||||
if (is_domain) {
|
||||
if (!name_lookup(self, m, id_bin, id, msg)) {
|
||||
return;
|
||||
}
|
||||
} else if (!valid_id_size) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid Tox ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
char xx[3];
|
||||
@ -777,7 +783,6 @@ void cmd_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA
|
||||
|
||||
tox_self_set_name(m, (uint8_t *) nick, len, NULL);
|
||||
prompt_update_nick(prompt, nick);
|
||||
set_nick_all_groups(m, nick, len);
|
||||
|
||||
store_data(m, DATA_FILE);
|
||||
}
|
||||
|
@ -76,6 +76,32 @@ void cmd_disconnect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*ar
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_group_nick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
UNUSED_VAR(window);
|
||||
|
||||
if (argc < 1) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Input required.");
|
||||
return;
|
||||
}
|
||||
|
||||
char nick[MAX_STR_SIZE];
|
||||
snprintf(nick, sizeof(nick), "%s", argv[1]);
|
||||
size_t len = strlen(nick);
|
||||
|
||||
if (!valid_nick(nick)) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid name.");
|
||||
return;
|
||||
}
|
||||
|
||||
len = MIN(len, TOXIC_MAX_NAME_LENGTH - 1);
|
||||
nick[len] = '\0';
|
||||
|
||||
set_nick_this_group(self, m, nick, len);
|
||||
|
||||
store_data(m, DATA_FILE);
|
||||
}
|
||||
|
||||
void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
{
|
||||
if (argc < 1) {
|
||||
@ -90,20 +116,20 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
return;
|
||||
}
|
||||
|
||||
Tox_Err_Group_Toggle_Ignore err;
|
||||
tox_group_toggle_ignore(m, self->num, peer_id, true, &err);
|
||||
Tox_Err_Group_Set_Ignore err;
|
||||
tox_group_set_ignore(m, self->num, peer_id, true, &err);
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_OK: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_OK: {
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_SELF: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_SELF: {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "You cannot ignore yourself.");
|
||||
return;
|
||||
}
|
||||
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND: {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "The specified nick or public key is invalid.");
|
||||
return;
|
||||
}
|
||||
@ -115,6 +141,8 @@ void cmd_ignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[
|
||||
}
|
||||
|
||||
line_info_add(self, true, NULL, NULL, SYS_MSG, 1, BLUE, "-!- Ignoring %s", nick);
|
||||
|
||||
group_toggle_peer_ignore(self->num, peer_id, true);
|
||||
}
|
||||
|
||||
void cmd_kick(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
@ -791,20 +819,20 @@ void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
return;
|
||||
}
|
||||
|
||||
Tox_Err_Group_Toggle_Ignore err;
|
||||
tox_group_toggle_ignore(m, self->num, peer_id, false, &err);
|
||||
Tox_Err_Group_Set_Ignore err;
|
||||
tox_group_set_ignore(m, self->num, peer_id, false, &err);
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_OK: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_OK: {
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_SELF: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_SELF: {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "You cannot unignore yourself.");
|
||||
return;
|
||||
}
|
||||
|
||||
case TOX_ERR_GROUP_TOGGLE_IGNORE_PEER_NOT_FOUND: {
|
||||
case TOX_ERR_GROUP_SET_IGNORE_PEER_NOT_FOUND: {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "The specified nick or public key is invalid.");
|
||||
return;
|
||||
}
|
||||
@ -816,6 +844,8 @@ void cmd_unignore(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv
|
||||
}
|
||||
|
||||
line_info_add(self, true, NULL, NULL, SYS_MSG, 1, BLUE, "-!- You are no longer ignoring %s", nick);
|
||||
|
||||
group_toggle_peer_ignore(self->num, peer_id, false);
|
||||
}
|
||||
|
||||
void cmd_whois(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE])
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
void cmd_chatid(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_disconnect(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
void cmd_group_nick(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_list(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]);
|
||||
|
327
src/groupchats.c
327
src/groupchats.c
@ -68,7 +68,7 @@ static int max_groupchat_index = 0;
|
||||
extern struct user_settings *user_settings;
|
||||
extern struct Winthread Winthread;
|
||||
|
||||
#define GROUP_SIDEBAR_OFFSET 2 /* Offset for the peer number box at the top of the statusbar */
|
||||
#define GROUP_SIDEBAR_OFFSET 3 /* Offset for the peer number box at the top of the statusbar */
|
||||
|
||||
/* groupchat command names used for tab completion. */
|
||||
static const char *group_cmd_list[] = {
|
||||
@ -117,12 +117,6 @@ static const char *group_cmd_list[] = {
|
||||
"/voice",
|
||||
"/whisper",
|
||||
"/whois",
|
||||
#ifdef AUDIO
|
||||
"/lsdev",
|
||||
"/sdev",
|
||||
"/mute",
|
||||
"/sense",
|
||||
#endif /* AUDIO */
|
||||
};
|
||||
|
||||
GroupChat groupchats[MAX_GROUPCHAT_NUM];
|
||||
@ -138,6 +132,7 @@ static void groupchat_onGroupStatusChange(ToxWindow *self, Tox *m, uint32_t grou
|
||||
TOX_USER_STATUS status);
|
||||
static void groupchat_onGroupSelfNickChange(ToxWindow *self, Tox *m, uint32_t groupnumber, const char *old_nick,
|
||||
size_t old_length, const char *new_nick, size_t length);
|
||||
static void ignore_list_cleanup(GroupChat *chat);
|
||||
|
||||
/*
|
||||
* Return a GroupChat pointer associated with groupnumber.
|
||||
@ -240,6 +235,8 @@ static void close_groupchat(ToxWindow *self, Tox *m, uint32_t groupnumber)
|
||||
return;
|
||||
}
|
||||
|
||||
ignore_list_cleanup(chat);
|
||||
|
||||
realloc_peer_list(groupnumber, 0);
|
||||
|
||||
free_ptr_array((void **) chat->name_list);
|
||||
@ -363,45 +360,75 @@ int init_groupchat_win(Tox *m, uint32_t groupnumber, const char *groupname, size
|
||||
return -1;
|
||||
}
|
||||
|
||||
void set_nick_all_groups(Tox *m, const char *new_nick, size_t length)
|
||||
void set_nick_this_group(ToxWindow *self, Tox *m, const char *new_nick, size_t length)
|
||||
{
|
||||
for (int i = 0; i < max_groupchat_index; ++i) {
|
||||
if (groupchats[i].active) {
|
||||
ToxWindow *self = get_window_ptr(groupchats[i].chatwin);
|
||||
if (self == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self) {
|
||||
continue;
|
||||
char old_nick[TOX_MAX_NAME_LENGTH + 1];
|
||||
size_t old_length = get_group_self_nick_truncate(m, old_nick, self->num);
|
||||
|
||||
Tox_Err_Group_Self_Name_Set err;
|
||||
tox_group_self_set_name(m, self->num, (uint8_t *) new_nick, length, &err);
|
||||
|
||||
GroupChat *chat = get_groupchat(self->num);
|
||||
|
||||
if (chat == NULL) {
|
||||
line_info_add(self, false, NULL, 0, SYS_MSG, 0, RED, "-!- Failed to set nick: invalid groupnumber");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_GROUP_SELF_NAME_SET_OK: {
|
||||
groupchat_onGroupSelfNickChange(self, m, self->num, old_nick, old_length, new_nick, length);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (chat->time_connected > 0) {
|
||||
line_info_add(self, false, NULL, 0, SYS_MSG, 0, RED, "-!- Failed to set nick (error %d).", err);
|
||||
}
|
||||
|
||||
char old_nick[TOX_MAX_NAME_LENGTH + 1];
|
||||
size_t old_length = get_group_self_nick_truncate(m, old_nick, self->num);
|
||||
|
||||
Tox_Err_Group_Self_Name_Set err;
|
||||
tox_group_self_set_name(m, groupchats[i].groupnumber, (uint8_t *) new_nick, length, &err);
|
||||
|
||||
switch (err) {
|
||||
case TOX_ERR_GROUP_SELF_NAME_SET_OK: {
|
||||
groupchat_onGroupSelfNickChange(self, m, self->num, old_nick, old_length, new_nick, length);
|
||||
break;
|
||||
}
|
||||
|
||||
case TOX_ERR_GROUP_SELF_NAME_SET_TAKEN: {
|
||||
line_info_add(self, false, NULL, 0, SYS_MSG, 0, RED, "-!- That nick is already in use.");
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (groupchats[i].time_connected > 0) {
|
||||
line_info_add(self, false, NULL, 0, SYS_MSG, 0, RED, "-!- Failed to set nick (error %d).", err);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* void set_nick_all_groups(Tox *m, const char *new_nick, size_t length) */
|
||||
/* { */
|
||||
/* for (int i = 0; i < max_groupchat_index; ++i) { */
|
||||
/* if (groupchats[i].active) { */
|
||||
/* ToxWindow *self = get_window_ptr(groupchats[i].chatwin); */
|
||||
|
||||
/* if (!self) { */
|
||||
/* continue; */
|
||||
/* } */
|
||||
|
||||
/* char old_nick[TOX_MAX_NAME_LENGTH + 1]; */
|
||||
/* size_t old_length = get_group_self_nick_truncate(m, old_nick, self->num); */
|
||||
|
||||
/* Tox_Err_Group_Self_Name_Set err; */
|
||||
/* tox_group_self_set_name(m, groupchats[i].groupnumber, (uint8_t *) new_nick, length, &err); */
|
||||
|
||||
/* switch (err) { */
|
||||
/* case TOX_ERR_GROUP_SELF_NAME_SET_OK: { */
|
||||
/* groupchat_onGroupSelfNickChange(self, m, self->num, old_nick, old_length, new_nick, length); */
|
||||
/* break; */
|
||||
/* } */
|
||||
|
||||
/* default: { */
|
||||
/* if (groupchats[i].time_connected > 0) { */
|
||||
/* line_info_add(self, false, NULL, 0, SYS_MSG, 0, RED, "-!- Failed to set nick (error %d).", err); */
|
||||
/* } */
|
||||
|
||||
/* break; */
|
||||
/* } */
|
||||
/* } */
|
||||
/* } */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
void set_status_all_groups(Tox *m, uint8_t status)
|
||||
{
|
||||
for (int i = 0; i < max_groupchat_index; ++i) {
|
||||
@ -480,6 +507,10 @@ static int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nick == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
|
||||
for (uint32_t i = 0; i < chat->max_idx; ++i) {
|
||||
@ -498,7 +529,7 @@ static int group_get_nick_peer_id(uint32_t groupnumber, const char *nick, uint32
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return count > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
/* Gets the peer_id associated with `public_key`.
|
||||
@ -514,9 +545,17 @@ int group_get_public_key_peer_id(uint32_t groupnumber, const char *public_key, u
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (public_key == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlen(public_key) < TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char key_bin[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
|
||||
|
||||
if (tox_pk_string_to_bytes(public_key, strlen(public_key), key_bin, sizeof(key_bin)) == -1) {
|
||||
if (tox_pk_string_to_bytes(public_key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2, key_bin, sizeof(key_bin)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -619,6 +658,131 @@ int get_peer_index(uint32_t groupnumber, uint32_t peer_id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if `key` is in the ignored list.
|
||||
*/
|
||||
static bool peer_is_ignored(const GroupChat *chat, const uint8_t *key)
|
||||
{
|
||||
for (uint16_t i = 0; i < chat->num_ignored; ++i) {
|
||||
if (memcmp(chat->ignored_list[i], key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool ignore_list_add_key(GroupChat *chat, const uint8_t *key)
|
||||
{
|
||||
uint8_t **tmp_list = (uint8_t **)realloc(chat->ignored_list, (chat->num_ignored + 1) * sizeof(uint8_t *));
|
||||
|
||||
if (tmp_list == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chat->ignored_list = tmp_list;
|
||||
|
||||
tmp_list[chat->num_ignored] = (uint8_t *)malloc(sizeof(uint8_t) * TOX_GROUP_PEER_PUBLIC_KEY_SIZE);
|
||||
|
||||
if (tmp_list[chat->num_ignored] == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(tmp_list[chat->num_ignored], key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE);
|
||||
++chat->num_ignored;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ignore_list_cleanup(GroupChat *chat)
|
||||
{
|
||||
for (uint16_t i = 0; i < chat->num_ignored; ++i) {
|
||||
if (chat->ignored_list[i] != NULL) {
|
||||
free(chat->ignored_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(chat->ignored_list);
|
||||
chat->ignored_list = NULL;
|
||||
chat->num_ignored = 0;
|
||||
}
|
||||
|
||||
static bool ignore_list_rm_key(GroupChat *chat, const uint8_t *key)
|
||||
{
|
||||
if (chat->num_ignored == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t idx = -1;
|
||||
|
||||
for (uint16_t i = 0; i < chat->num_ignored; ++i) {
|
||||
if (memcmp(chat->ignored_list[i], key, TOX_GROUP_PEER_PUBLIC_KEY_SIZE) == 0) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx == -1) {
|
||||
fprintf(stderr, "Key not found in ignore list\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((chat->num_ignored - 1) == 0) {
|
||||
ignore_list_cleanup(chat);
|
||||
return true;
|
||||
}
|
||||
|
||||
--chat->num_ignored;
|
||||
|
||||
if (idx != chat->num_ignored) {
|
||||
memcpy(chat->ignored_list[idx], chat->ignored_list[chat->num_ignored], TOX_GROUP_PEER_PUBLIC_KEY_SIZE);
|
||||
}
|
||||
|
||||
free(chat->ignored_list[chat->num_ignored]);
|
||||
|
||||
uint8_t **tmp_list = realloc(chat->ignored_list, chat->num_ignored * sizeof(uint8_t *));
|
||||
|
||||
if (tmp_list == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chat->ignored_list = tmp_list;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void group_toggle_peer_ignore(uint32_t groupnumber, int peer_id, bool ignore)
|
||||
{
|
||||
int peer_index = get_peer_index(groupnumber, peer_id);
|
||||
|
||||
if (peer_index < 0) {
|
||||
fprintf(stderr, "Failed to find peer index (group_toggle_peer_ignore())\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GroupChat *chat = get_groupchat(groupnumber);
|
||||
|
||||
if (!chat) {
|
||||
return;
|
||||
}
|
||||
|
||||
GroupPeer *peer = &chat->peer_list[peer_index];
|
||||
|
||||
peer->is_ignored = ignore;
|
||||
|
||||
bool ret;
|
||||
|
||||
if (ignore) {
|
||||
ret = ignore_list_add_key(chat, peer->public_key);
|
||||
} else {
|
||||
ret = ignore_list_rm_key(chat, peer->public_key);
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
fprintf(stderr, "Client failed to modify ignore list\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void group_update_name_list(uint32_t groupnumber)
|
||||
{
|
||||
GroupChat *chat = get_groupchat(groupnumber);
|
||||
@ -985,13 +1149,20 @@ static void groupchat_onGroupPeerJoin(ToxWindow *self, Tox *m, uint32_t groupnum
|
||||
peer->status = tox_group_peer_get_status(m, groupnumber, peer_id, NULL);
|
||||
peer->role = tox_group_peer_get_role(m, groupnumber, peer_id, NULL);
|
||||
peer->last_active = get_unix_time();
|
||||
tox_group_peer_get_public_key(m, groupnumber, peer_id, (uint8_t *) peer->public_key, NULL);
|
||||
tox_group_peer_get_public_key(m, groupnumber, peer_id, (uint8_t *)peer->public_key, NULL);
|
||||
peer->is_ignored = peer_is_ignored(chat, peer->public_key);
|
||||
|
||||
if (peer->is_ignored) {
|
||||
tox_group_set_ignore(m, groupnumber, peer_id, true, NULL);
|
||||
}
|
||||
|
||||
if (i == chat->max_idx) {
|
||||
++chat->max_idx;
|
||||
}
|
||||
|
||||
if (timed_out(chat->time_connected, 7)) { /* ignore join messages when we first connect to the group */
|
||||
if (timed_out(chat->time_connected, 60)
|
||||
&& user_settings->show_group_connection_msg ==
|
||||
SHOW_GROUP_CONNECTION_MSG_ON) { /* ignore join messages when we first connect to the group */
|
||||
line_info_add(self, true, peer->name, NULL, CONNECTION, 0, GREEN, "has joined the room");
|
||||
|
||||
write_to_log("has joined the room", peer->name, self->chatwin->log, true);
|
||||
@ -1027,14 +1198,16 @@ void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, uint32_t groupnumber, ui
|
||||
if (length > 0) {
|
||||
line_info_add(self, true, name, NULL, DISCONNECTION, 0, RED, "[Quit]: %s", part_message);
|
||||
snprintf(log_str, sizeof(log_str), "has left the room (%s)", part_message);
|
||||
} else {
|
||||
write_to_log(log_str, name, self->chatwin->log, true);
|
||||
sound_notify(self, silent, NT_WNDALERT_2, NULL);
|
||||
} else if (user_settings->show_group_connection_msg == SHOW_GROUP_CONNECTION_MSG_ON) {
|
||||
const char *exit_string = get_group_exit_string(exit_type);
|
||||
line_info_add(self, true, name, NULL, DISCONNECTION, 0, RED, "[%s]", exit_string);
|
||||
snprintf(log_str, sizeof(log_str), "[%s]", exit_string);
|
||||
write_to_log(log_str, name, self->chatwin->log, true);
|
||||
sound_notify(self, silent, NT_WNDALERT_2, NULL);
|
||||
}
|
||||
|
||||
write_to_log(log_str, name, self->chatwin->log, true);
|
||||
sound_notify(self, silent, NT_WNDALERT_2, NULL);
|
||||
}
|
||||
|
||||
int peer_index = get_peer_index(groupnumber, peer_id);
|
||||
@ -1372,7 +1545,7 @@ static void send_group_message(ToxWindow *self, Tox *m, uint32_t groupnumber, co
|
||||
|
||||
Tox_Err_Group_Send_Message err;
|
||||
|
||||
if (!tox_group_send_message(m, groupnumber, type, (uint8_t *) msg, strlen(msg), &err)) {
|
||||
if (!tox_group_send_message(m, groupnumber, type, (uint8_t *) msg, strlen(msg), NULL, &err)) {
|
||||
if (err == TOX_ERR_GROUP_SEND_MESSAGE_PERMISSIONS) {
|
||||
const Tox_Group_Role role = tox_group_self_get_role(m, groupnumber, NULL);
|
||||
|
||||
@ -1416,7 +1589,6 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, uint32_t groupnumbe
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t peer_id = 0;
|
||||
uint32_t name_length = 0;
|
||||
const char *nick = NULL;
|
||||
|
||||
@ -1434,13 +1606,23 @@ static void send_group_prvt_message(ToxWindow *self, Tox *m, uint32_t groupnumbe
|
||||
if (chat->peer_list[i].name_length > name_length) {
|
||||
name_length = chat->peer_list[i].name_length;
|
||||
nick = chat->peer_list[i].name;
|
||||
peer_id = chat->peer_list[i].peer_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nick == NULL) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid peer name.");
|
||||
if (data_len < TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Invalid nick.");
|
||||
return;
|
||||
}
|
||||
|
||||
nick = data;
|
||||
name_length = TOX_GROUP_PEER_PUBLIC_KEY_SIZE * 2;
|
||||
}
|
||||
|
||||
uint32_t peer_id;
|
||||
|
||||
if (group_get_peer_id_of_identifier(self, nick, &peer_id) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1659,7 +1841,15 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
wattron(ctx->sidebar, A_BOLD);
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
wprintw(ctx->sidebar, "Peers: %d\n", chat->num_peers);
|
||||
|
||||
if (chat->num_peers > 1) {
|
||||
wprintw(ctx->sidebar, "Peers: %d\n", chat->num_peers);
|
||||
} else if (tox_group_is_connected(m, self->num, NULL)) {
|
||||
wprintw(ctx->sidebar, "Connecting...\n");
|
||||
} else {
|
||||
wprintw(ctx->sidebar, "Disconnected\n");
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
wattroff(ctx->sidebar, A_BOLD);
|
||||
@ -1669,14 +1859,15 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
mvwhline(ctx->sidebar, 1, 1, ACS_HLINE, SIDEBAR_WIDTH - 1);
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(BLUE));
|
||||
|
||||
int maxlines = y2 - GROUP_SIDEBAR_OFFSET - CHATBOX_HEIGHT;
|
||||
uint32_t i, offset = 0;
|
||||
const int maxlines = y2 - GROUP_SIDEBAR_OFFSET - CHATBOX_HEIGHT;
|
||||
uint32_t offset = 0;
|
||||
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
uint32_t max_idx = chat->max_idx;
|
||||
const uint32_t max_idx = chat->max_idx;
|
||||
const uint32_t start = chat->side_pos;
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
for (i = 0; i < max_idx && i < maxlines; ++i) {
|
||||
for (uint32_t i = start; i < max_idx && offset < maxlines; ++i) {
|
||||
pthread_mutex_lock(&Winthread.lock);
|
||||
|
||||
if (!chat->peer_list[i].active) {
|
||||
@ -1686,22 +1877,26 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
|
||||
wmove(ctx->sidebar, offset + 2, 1);
|
||||
|
||||
int p = i + chat->side_pos;
|
||||
int maxlen_offset = chat->peer_list[p].role == TOX_GROUP_ROLE_USER ? 2 : 3;
|
||||
const bool is_ignored = chat->peer_list[i].is_ignored;
|
||||
uint16_t maxlen_offset = chat->peer_list[i].role == TOX_GROUP_ROLE_USER ? 2 : 3;
|
||||
|
||||
if (is_ignored) {
|
||||
++maxlen_offset;
|
||||
}
|
||||
|
||||
/* truncate nick to fit in side panel without modifying list */
|
||||
char tmpnck[TOX_MAX_NAME_LENGTH];
|
||||
int maxlen = SIDEBAR_WIDTH - maxlen_offset;
|
||||
const int maxlen = SIDEBAR_WIDTH - maxlen_offset;
|
||||
|
||||
memcpy(tmpnck, chat->peer_list[p].name, maxlen);
|
||||
memcpy(tmpnck, chat->peer_list[i].name, maxlen);
|
||||
|
||||
tmpnck[maxlen] = '\0';
|
||||
|
||||
int namecolour = WHITE;
|
||||
|
||||
if (chat->peer_list[p].status == TOX_USER_STATUS_AWAY) {
|
||||
if (chat->peer_list[i].status == TOX_USER_STATUS_AWAY) {
|
||||
namecolour = YELLOW;
|
||||
} else if (chat->peer_list[p].status == TOX_USER_STATUS_BUSY) {
|
||||
} else if (chat->peer_list[i].status == TOX_USER_STATUS_BUSY) {
|
||||
namecolour = RED;
|
||||
}
|
||||
|
||||
@ -1709,19 +1904,25 @@ static void groupchat_onDraw(ToxWindow *self, Tox *m)
|
||||
const char *rolesig = "";
|
||||
int rolecolour = WHITE;
|
||||
|
||||
if (chat->peer_list[p].role == TOX_GROUP_ROLE_FOUNDER) {
|
||||
if (chat->peer_list[i].role == TOX_GROUP_ROLE_FOUNDER) {
|
||||
rolesig = "&";
|
||||
rolecolour = BLUE;
|
||||
} else if (chat->peer_list[p].role == TOX_GROUP_ROLE_MODERATOR) {
|
||||
} else if (chat->peer_list[i].role == TOX_GROUP_ROLE_MODERATOR) {
|
||||
rolesig = "+";
|
||||
rolecolour = GREEN;
|
||||
} else if (chat->peer_list[p].role == TOX_GROUP_ROLE_OBSERVER) {
|
||||
} else if (chat->peer_list[i].role == TOX_GROUP_ROLE_OBSERVER) {
|
||||
rolesig = "-";
|
||||
rolecolour = MAGENTA;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&Winthread.lock);
|
||||
|
||||
if (is_ignored) {
|
||||
wattron(ctx->sidebar, COLOR_PAIR(RED) | A_BOLD);
|
||||
wprintw(ctx->sidebar, "#");
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(RED) | A_BOLD);
|
||||
}
|
||||
|
||||
wattron(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD);
|
||||
wprintw(ctx->sidebar, "%s", rolesig);
|
||||
wattroff(ctx->sidebar, COLOR_PAIR(rolecolour) | A_BOLD);
|
||||
|
@ -47,6 +47,7 @@ typedef struct GroupPeer {
|
||||
uint8_t public_key[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
|
||||
TOX_USER_STATUS status;
|
||||
Tox_Group_Role role;
|
||||
bool is_ignored;
|
||||
uint64_t last_active;
|
||||
} GroupPeer;
|
||||
|
||||
@ -56,6 +57,9 @@ typedef struct {
|
||||
uint32_t num_peers; /* Number of peers in the chat/name_list array */
|
||||
uint32_t max_idx; /* Maximum peer list index - 1 */
|
||||
|
||||
uint8_t **ignored_list; /* List of keys of peers that we're ignoring */
|
||||
uint16_t num_ignored;
|
||||
|
||||
char group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH + 1];
|
||||
size_t group_name_length;
|
||||
uint32_t groupnumber;
|
||||
@ -68,7 +72,7 @@ typedef struct {
|
||||
|
||||
void exit_groupchat(ToxWindow *self, Tox *m, uint32_t groupnumber, const char *partmessage, size_t length);
|
||||
int init_groupchat_win(Tox *m, uint32_t groupnumber, const char *groupname, size_t length, Group_Join_Type join_type);
|
||||
void set_nick_all_groups(Tox *m, const char *new_nick, size_t length);
|
||||
void set_nick_this_group(ToxWindow *self, Tox *m, const char *new_nick, size_t length);
|
||||
void set_status_all_groups(Tox *m, uint8_t status);
|
||||
int get_peer_index(uint32_t groupnumber, uint32_t peer_id);
|
||||
void groupchat_onGroupPeerExit(ToxWindow *self, Tox *m, uint32_t groupnumber, uint32_t peer_id,
|
||||
@ -108,4 +112,9 @@ void redraw_groupchat_win(ToxWindow *self);
|
||||
*/
|
||||
GroupChat *get_groupchat(uint32_t groupnumber);
|
||||
|
||||
/**
|
||||
* Toggles the ignore status of the peer associated with `peer_id`.
|
||||
*/
|
||||
void group_toggle_peer_ignore(uint32_t groupnumber, int peer_id, bool ignore);
|
||||
|
||||
#endif /* #define GROUPCHATS_H */
|
||||
|
26
src/help.c
26
src/help.c
@ -183,12 +183,12 @@ static void help_draw_global(ToxWindow *self)
|
||||
wprintw(win, " /requests : List pending friend requests\n");
|
||||
wprintw(win, " /status <type> : Set status (Online, Busy, Away)\n");
|
||||
wprintw(win, " /note <msg> : Set a personal note\n");
|
||||
wprintw(win, " /nick <nick> : Set your nickname\n");
|
||||
wprintw(win, " /nick <name> : Set your global name (doesn't affect groups)\n");
|
||||
wprintw(win, " /nospam <value> : Change part of your Tox ID to stop spam\n");
|
||||
wprintw(win, " /log <on> or <off> : Enable/disable logging\n");
|
||||
wprintw(win, " /conference <type> : Create a conference where type: text | audio\n");
|
||||
wprintw(win, " /myid : Print your Tox ID\n");
|
||||
wprintw(win, " /group <name> : Create a new group chat\n");
|
||||
wprintw(win, " /join <chatid> : Join a groupchat using a Chat ID\n");
|
||||
#ifdef GAMES
|
||||
wprintw(win, " /game : Play a game\n");
|
||||
#endif /* GAMES */
|
||||
@ -246,8 +246,10 @@ static void help_draw_chat(ToxWindow *self)
|
||||
wprintw(win, "Chat Commands:\n");
|
||||
wattroff(win, A_BOLD | COLOR_PAIR(RED));
|
||||
|
||||
wprintw(win, " /invite <n> : Invite contact to a conference \n");
|
||||
wprintw(win, " /join : Join a pending conference\n");
|
||||
wprintw(win, " /cinvite <n> : Invite contact to a conference \n");
|
||||
wprintw(win, " /cjoin : Join a pending conference\n");
|
||||
wprintw(win, " /invite <n> : Invite contact to a groupchat \n");
|
||||
wprintw(win, " /gaccept <password> : Accept a pending groupchat invite\n");
|
||||
wprintw(win, " /sendfile <path> : Send a file\n");
|
||||
wprintw(win, " /savefile <id> : Receive a file\n");
|
||||
wprintw(win, " /cancel <type> <id> : Cancel file transfer where type: in|out\n");
|
||||
@ -305,6 +307,7 @@ static void help_draw_groupchats(ToxWindow *self)
|
||||
wprintw(win, " /list : Print a list of peers currently in the group\n");
|
||||
wprintw(win, " /locktopic : Set the topic lock: on | off\n");
|
||||
wprintw(win, " /mod <name> : Promote a peer to moderator\n");
|
||||
wprintw(win, " /nick <name> : Set your name for this group only\n");
|
||||
wprintw(win, " /passwd <s> : Set a password needed to join the group\n");
|
||||
wprintw(win, " /peerlimit <n> : Set the maximum number of peers that can join\n");
|
||||
wprintw(win, " /privacy <state> : Set the privacy state: private | public\n");
|
||||
@ -431,18 +434,21 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
break;
|
||||
|
||||
case L'c':
|
||||
height = 12;
|
||||
#ifdef VIDEO
|
||||
help_init_window(self, 26, 80);
|
||||
height += 15;
|
||||
#elif AUDIO
|
||||
help_init_window(self, 21, 80);
|
||||
#else
|
||||
help_init_window(self, 11, 80);
|
||||
height += 5;
|
||||
#endif
|
||||
#ifdef GAMES
|
||||
height += 1;
|
||||
#endif
|
||||
help_init_window(self, height, 80);
|
||||
self->help->type = HELP_CHAT;
|
||||
break;
|
||||
|
||||
case L'g':
|
||||
height = 22;
|
||||
height = 24;
|
||||
#ifdef VIDEO
|
||||
height += 8;
|
||||
#elif AUDIO
|
||||
@ -491,7 +497,7 @@ void help_onKey(ToxWindow *self, wint_t key)
|
||||
break;
|
||||
|
||||
case L'r':
|
||||
help_init_window(self, 26, 80);
|
||||
help_init_window(self, 27, 80);
|
||||
self->help->type = HELP_GROUP;
|
||||
break;
|
||||
}
|
||||
|
@ -144,11 +144,14 @@ static struct line_info *line_info_ret_queue(struct history *hst)
|
||||
*/
|
||||
static int print_n_chars(WINDOW *win, const wchar_t *s, size_t n, int max_y)
|
||||
{
|
||||
// we use an array to represent a single wchar in order to get around an ncurses
|
||||
// bug with waddnwstr() that overreads the memory address by one byte when
|
||||
// supplied with a single wchar.
|
||||
wchar_t ch[2] = {0};
|
||||
bool newline = false;
|
||||
wchar_t ch;
|
||||
|
||||
for (size_t i = 0; i < n && (ch = s[i]); ++i) {
|
||||
if (ch == L'\n') {
|
||||
for (size_t i = 0; i < n && (ch[0] = s[i]); ++i) {
|
||||
if (ch[0] == L'\n') {
|
||||
newline = true;
|
||||
|
||||
int x;
|
||||
@ -165,11 +168,11 @@ static int print_n_chars(WINDOW *win, const wchar_t *s, size_t n, int max_y)
|
||||
|
||||
if (win) {
|
||||
#ifdef HAVE_WIDECHAR
|
||||
waddnwstr(win, &ch, 1);
|
||||
waddnwstr(win, ch, 1);
|
||||
#else
|
||||
char b;
|
||||
|
||||
if (wcstombs(&b, &ch, sizeof(char)) != 1) {
|
||||
if (wcstombs(&b, ch, sizeof(char)) != 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type,
|
||||
return;
|
||||
}
|
||||
|
||||
struct cqueue_msg *new_m = malloc(sizeof(struct cqueue_msg));
|
||||
struct cqueue_msg *new_m = calloc(1, sizeof(struct cqueue_msg));
|
||||
|
||||
if (new_m == NULL) {
|
||||
exit_toxic_err("failed in cqueue_message", FATALERR_MEMORY);
|
||||
@ -62,6 +62,7 @@ void cqueue_add(struct chat_queue *q, const char *msg, size_t len, uint8_t type,
|
||||
new_m->time_added = get_unix_time();
|
||||
new_m->receipt = -1;
|
||||
new_m->next = NULL;
|
||||
new_m->noread_flag = false;
|
||||
|
||||
if (q->root == NULL) {
|
||||
new_m->prev = NULL;
|
||||
@ -203,7 +204,7 @@ void cqueue_try_send(ToxWindow *self, Tox *m)
|
||||
return;
|
||||
}
|
||||
|
||||
TOX_ERR_FRIEND_SEND_MESSAGE err;
|
||||
Tox_Err_Friend_Send_Message err;
|
||||
Tox_Message_Type type = msg->type == OUT_MSG ? TOX_MESSAGE_TYPE_NORMAL : TOX_MESSAGE_TYPE_ACTION;
|
||||
uint32_t receipt = tox_friend_send_message(m, self->num, type, (uint8_t *) msg->message, msg->len, &err);
|
||||
|
||||
|
@ -362,16 +362,20 @@ on_exit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message)
|
||||
/* Attempts to do a tox name lookup.
|
||||
*
|
||||
* Returns true on success.
|
||||
*/
|
||||
bool name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message)
|
||||
{
|
||||
if (t_data.disabled) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled.");
|
||||
return;
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "nameservers list is empty or does not exist.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t_data.busy) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous name lookup to finish.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
snprintf(t_data.id_bin, sizeof(t_data.id_bin), "%s", id_bin);
|
||||
@ -384,22 +388,24 @@ void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr,
|
||||
if (pthread_attr_init(&lookup_thread.attr) != 0) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to init");
|
||||
clear_thread_data();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pthread_attr_setdetachstate(&lookup_thread.attr, PTHREAD_CREATE_DETACHED) != 0) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to set");
|
||||
pthread_attr_destroy(&lookup_thread.attr);
|
||||
clear_thread_data();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pthread_create(&lookup_thread.tid, &lookup_thread.attr, lookup_thread_func, NULL) != 0) {
|
||||
line_info_add(self, false, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread failed to init");
|
||||
pthread_attr_destroy(&lookup_thread.attr);
|
||||
clear_thread_data();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Initializes http based name lookups. Note: This function must be called only once before additional
|
||||
|
@ -23,14 +23,19 @@
|
||||
#ifndef NAME_LOOKUP
|
||||
#define NAME_LOOKUP
|
||||
|
||||
/* Initializes http based name lookups. Note: This function must be called only once before additional
|
||||
* threads are spawned.
|
||||
/* Initializes http based name lookups.
|
||||
*
|
||||
* Note: This function must be called only once before additional threads are spawned.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 on failure.
|
||||
*/
|
||||
int name_lookup_init(int curl_init_status);
|
||||
|
||||
int name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message);
|
||||
/* Attempts to do a tox name lookup.
|
||||
*
|
||||
* Returns true on success.
|
||||
*/
|
||||
bool name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message);
|
||||
|
||||
#endif /* NAME_LOOKUP */
|
||||
|
@ -20,9 +20,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "api.h"
|
||||
|
||||
#ifdef PYTHON
|
||||
#include <Python.h>
|
||||
#include "api.h"
|
||||
|
||||
#include "execute.h"
|
||||
|
||||
|
@ -63,6 +63,7 @@ static struct ui_strings {
|
||||
const char *show_typing_other;
|
||||
const char *show_welcome_msg;
|
||||
const char *show_connection_msg;
|
||||
const char *show_group_connection_msg;
|
||||
const char *nodeslist_update_freq;
|
||||
const char *autosave_freq;
|
||||
|
||||
@ -99,6 +100,7 @@ static struct ui_strings {
|
||||
"show_typing_other",
|
||||
"show_welcome_msg",
|
||||
"show_connection_msg",
|
||||
"show_group_connection_msg",
|
||||
"nodeslist_update_freq",
|
||||
"autosave_freq",
|
||||
"line_join",
|
||||
@ -136,6 +138,7 @@ static void ui_defaults(struct user_settings *settings)
|
||||
settings->show_typing_other = SHOW_TYPING_ON;
|
||||
settings->show_welcome_msg = SHOW_WELCOME_MSG_ON;
|
||||
settings->show_connection_msg = SHOW_CONNECTION_MSG_ON;
|
||||
settings->show_group_connection_msg = SHOW_GROUP_CONNECTION_MSG_ON;
|
||||
settings->nodeslist_update_freq = 1;
|
||||
settings->autosave_freq = 600;
|
||||
|
||||
@ -405,6 +408,7 @@ int settings_load(struct user_settings *s, const char *patharg)
|
||||
config_setting_lookup_bool(setting, ui_strings.show_typing_other, &s->show_typing_other);
|
||||
config_setting_lookup_bool(setting, ui_strings.show_welcome_msg, &s->show_welcome_msg);
|
||||
config_setting_lookup_bool(setting, ui_strings.show_connection_msg, &s->show_connection_msg);
|
||||
config_setting_lookup_bool(setting, ui_strings.show_group_connection_msg, &s->show_group_connection_msg);
|
||||
|
||||
config_setting_lookup_int(setting, ui_strings.history_size, &s->history_size);
|
||||
config_setting_lookup_int(setting, ui_strings.notification_timeout, &s->notification_timeout);
|
||||
|
@ -54,6 +54,7 @@ struct user_settings {
|
||||
int show_typing_other; /* boolean */
|
||||
int show_welcome_msg; /* boolean */
|
||||
int show_connection_msg; /* boolean */
|
||||
int show_group_connection_msg; /* boolean */
|
||||
int nodeslist_update_freq; /* int (<= 0 to disable updates) */
|
||||
int autosave_freq; /* int (<= 0 to disable autosave) */
|
||||
|
||||
@ -122,6 +123,9 @@ enum settings_values {
|
||||
SHOW_CONNECTION_MSG_OFF = 0,
|
||||
SHOW_CONNECTION_MSG_ON = 1,
|
||||
|
||||
SHOW_GROUP_CONNECTION_MSG_OFF = 0,
|
||||
SHOW_GROUP_CONNECTION_MSG_ON = 1,
|
||||
|
||||
DFLT_HST_SIZE = 700,
|
||||
|
||||
MPLEX_OFF = 0,
|
||||
|
24
src/toxic.c
24
src/toxic.c
@ -37,6 +37,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
@ -257,22 +258,27 @@ void cb_toxcore_logger(Tox *m, TOX_LOG_LEVEL level, const char *file, uint32_t l
|
||||
{
|
||||
UNUSED_VAR(m);
|
||||
|
||||
if (level == TOX_LOG_LEVEL_TRACE) {
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *fp = (FILE *)user_data;
|
||||
|
||||
if (!fp) {
|
||||
fp = stderr;
|
||||
}
|
||||
|
||||
const time_t t = time(NULL);
|
||||
struct tm *tmp = gmtime(&t);
|
||||
char timestamp[200];
|
||||
strftime(timestamp, sizeof(timestamp), "%F %T", tmp);
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
struct tm tmp;
|
||||
|
||||
gmtime_r(&tv.tv_sec, &tmp);
|
||||
|
||||
char timestamp[200];
|
||||
|
||||
strftime(timestamp, sizeof(timestamp), "%F %T", &tmp);
|
||||
|
||||
fprintf(fp, "%c %s.%06ld %s:%u(%s) - %s\n", tox_log_level_show(level)[0], timestamp, tv.tv_usec, file, line, func,
|
||||
message);
|
||||
|
||||
fprintf(fp, "[%c] %s %s:%u(%s) - %s\n", tox_log_level_show(level)[0], timestamp, file, line, func, message);
|
||||
fflush(fp);
|
||||
}
|
||||
|
||||
|
@ -114,8 +114,8 @@ void flag_interface_refresh(void);
|
||||
/* Sets ncurses refresh rate. Lower values make it refresh more often. */
|
||||
void set_window_refresh_rate(size_t refresh_rate);
|
||||
|
||||
void exit_toxic_success(Tox *m);
|
||||
void exit_toxic_err(const char *errmsg, int errcode);
|
||||
void exit_toxic_success(Tox *m) __attribute__((__noreturn__));
|
||||
void exit_toxic_err(const char *errmsg, int errcode) __attribute__((__noreturn__));
|
||||
|
||||
int store_data(Tox *m, const char *path);
|
||||
|
||||
@ -152,7 +152,7 @@ void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data,
|
||||
const uint8_t *group_name,
|
||||
size_t group_name_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);
|
||||
const uint8_t *message, size_t length, uint32_t message_id, void *userdata);
|
||||
void on_group_private_message(Tox *m, uint32_t groupnumber, uint32_t peernumber, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length,
|
||||
void *userdata);
|
||||
|
@ -395,8 +395,10 @@ void on_group_invite(Tox *m, uint32_t friendnumber, const uint8_t *invite_data,
|
||||
}
|
||||
|
||||
void on_group_message(Tox *m, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type,
|
||||
const uint8_t *message, size_t length, void *userdata)
|
||||
const uint8_t *message, size_t length, uint32_t message_id, void *userdata)
|
||||
{
|
||||
UNUSED_VAR(message_id);
|
||||
|
||||
char msg[MAX_STR_SIZE + 1];
|
||||
length = copy_tox_str(msg, sizeof(msg), (const char *) message, length);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user