1
0
mirror of https://github.com/Tha14/toxic.git synced 2025-04-08 01:32:45 +02:00

Compare commits

..

71 Commits
ngc ... master

Author SHA1 Message Date
jfreegman
30d01127e7
Remove invalid groupchat commands
These commands only work in audio conferences
2023-10-05 13:37:54 -04:00
jfreegman
85ab7592c9
Fix group ignore functionality
Ignoring a peer now persists if they leave/disconnect and rejoin the group.
In addition, ignore status is now displayed in the peer list sidebar
as a red # symbol.
2023-10-03 20:33:37 -04:00
jfreegman
6cdd01da25
Fix syntax error in static build script 2023-09-03 08:16:42 -04:00
jfreegman
69e4ed452d
tell compiler that exit_toxic funcs don't return 2023-08-26 08:05:43 -04:00
jfreegman
4c77e80a7f
Fix ID lookup error messages
We now properly distinguish between ID lookups and domain name lookups
and print the appropriate error message for each given case
2023-08-09 10:39:27 -04:00
jfreegman
ff669be8d1
detach group names from global name
Group names are now set on a per-group basis and are not affected
by the global /nick command.
2023-04-04 16:16:57 -04:00
Pigpog
5d757e1230
Update help dialog height to fit the new commands
Made the "global" and "chat" help pages fit properly in the dialog again.
I also made the logic for deciding height for the chat page consistent with the other pages.
2023-03-04 17:07:15 -05:00
jfreegman
70ab422acc
Update static build script 2023-03-04 10:11:37 -05:00
jfreegman
2a052edb9e
Bump version to 0.12.0 & Update man pages
We no longer use libera as they were found to be spying on their
users' private conversations, so we've replaced it with a
public tox group via the new groupchat implementation
2023-03-04 09:52:15 -05:00
jfreegman
efbfa2c95c
Remove toxme.io from nameservers list as it no longer exists 2023-01-11 13:16:13 -05:00
jfreegman
3f3e848b6f
Show connection status in groupchat peerlist 2023-01-05 12:33:04 -05:00
8d125d5e6b
Change conference invite, accept, Add NGC join, invite, accept 2023-01-05 19:12:00 +02:00
fbdc20dfa5
fix: git clone toxcore recursive 2022-11-30 12:36:05 +01:00
jfreegman
e8388bf20c
Show toxcore TRACE logging messages
I'm not sure why this was disabled. It shouldn't be.
2022-10-13 23:27:31 -04:00
jfreegman
398aecdd92
Fix group whispering for duplicate nicks
If a group has numerous peers with the same nick we now require
their public key in order to send a private message. Previously
we would greedily send the message to the first peer
in the list.
2022-10-06 14:16:16 -04:00
jfreegman
57a439c9b4
Remove testnet specific code
Preparing for ngc merge
2022-09-22 14:05:23 -04:00
jfreegman
0aea5d7fbe
Remove testnet specific code
Preparing for ngc merge
2022-09-22 13:51:00 -04:00
jfreegman
e56edd556f
Remove error code that no longer exists 2022-07-14 00:17:39 -04:00
jfreegman
7ed031b9bf
Fix static build script 2022-06-28 10:54:19 -04:00
6ef2c784c5
Fix tab alert bug on peer exit 2022-06-28 17:31:27 +03:00
jfreegman
058057c64d
Fix style issues 2022-06-27 19:42:38 -04:00
146b00b8ca
Fix chatlog saving with new hide connection msg pr 2022-06-28 01:58:32 +03:00
jfreegman
85024bfce8
Update config man page 2022-06-27 10:40:03 -04:00
129bb6ba68
New option: Hide peer connection status in groups 2022-06-27 17:31:05 +03:00
jfreegman
68b4713ef7
Update group API 2022-06-02 10:20:38 -04:00
jfreegman
46eb69412e
Update group API 2022-04-23 13:14:44 -04:00
jfreegman
f47b4c1c3c
Remove duplicate help menu entry 2022-03-18 12:24:07 -04:00
jfreegman
22eb6797b1
Fix another group peerlist scrolling bug 2022-03-18 12:24:06 -04:00
jfreegman
0edad7b862
Fix group peerlist scrolling bug 2022-03-18 12:24:06 -04:00
jfreegman
cc80da00fc
Increase how long we wait after joining a group before showing peer join messages 2022-03-18 12:24:06 -04:00
jfreegman
32efac931c
Connect second testnet bootstrap node to ipv4 instead of 6 2022-03-18 12:24:05 -04:00
jfreegman
4f936e5f9c
Add higher precision for logging timestamps 2022-03-18 12:24:05 -04:00
jfreegman
529d905bd0
Add timestamps to logger and enable widechar for bazel build 2022-03-18 12:24:05 -04:00
jfreegman
631b1d8b08
Fix second bootstrap node info 2022-03-18 12:24:04 -04:00
jfreegman
9ac8d517e9
Add second testnet bootstrap node 2022-03-18 12:24:04 -04:00
jfreegman
90152f5e17
some logging code cleanup 2022-03-18 12:24:04 -04:00
jfreegman
4d501aeb2a
Add support for new voice state feature 2022-03-18 12:24:03 -04:00
jfreegman
1b9f4f337a
Fix name change notifications
Due to recent core changes we now need to store a peer's
previous name instead of relying on API lookups via the
peer_id in the name change callback in order to display
the correct info
2022-03-18 12:24:03 -04:00
jfreegman
812f2d1ff9
Fix some weird/incorrect code for printing private messages 2022-03-18 12:24:03 -04:00
jfreegman
2eeb1de20d
Remove usage of deprecated API typedefs 2022-03-18 12:24:02 -04:00
jfreegman
ba896fd124
Hardcode testnet bootstrap node 2022-03-18 12:24:02 -04:00
jfreegman
3ff3516e42
Add more descriptive errors to some moderation commands 2022-03-18 12:24:02 -04:00
jfreegman
2ef3d68173
Properly handle group mod event
We now update all peer roles if we get a moderation event
in which the peer ID is invalid, per recent API changes
2022-03-18 12:24:01 -04:00
jfreegman
7a099f86c8
Fix duplicate config example line 2022-03-18 12:24:01 -04:00
jfreegman
9a629072b3
Fix possible null deref 2022-03-18 12:24:00 -04:00
jfreegman
27259ff23f
Update function name (merge conflict) 2022-03-18 12:24:00 -04:00
jfreegman
f786b7ae6a
Refactor peer-specific commands
This takes into account the possibility of multiple peers in
the group using the same nick. The /whois command now lists
all peers associated with the input name, and all commands
that target a peer with a non-unique nick will require the
public key to be used.
2022-03-18 12:24:00 -04:00
jfreegman
cd4a5e5fde
Fix rebase mistakes 2022-03-18 12:23:59 -04:00
jfreegman
0b32b985f1
Add topic lock command and callbacks 2022-03-18 12:23:59 -04:00
jfreegman
5851cb2dd8
Don't announce/alert on self group join 2022-03-18 12:23:59 -04:00
jfreegman
1847025213
Make /whois show both public key and name 2022-03-18 12:23:58 -04:00
jfreegman
1a2320b035
Add the ability to make peer-specific commands using public keys
This allows us to use commands on peers who may be using nicks with strange
or unsupported unicode characters
2022-03-18 12:23:58 -04:00
jfreegman
1211899a40
Add /list command that lists all group peers w/ public keys 2022-03-18 12:23:58 -04:00
jfreegman
5dabaac804
Remove some unnecessary code 2022-03-18 12:23:57 -04:00
jfreegman
4f26171e3f
Re-add /group command
Another one lost in a rebase
2022-03-18 12:23:57 -04:00
jfreegman
fa075f1972
Add connection type to whois group peer queries 2022-03-18 12:23:57 -04:00
jfreegman
cbf3145aee
Remove redundant command /mykey
You can get your own key with the /whois command
2022-03-18 12:23:56 -04:00
jfreegman
06bdb0d167
Add groupchat help menu
It seems to have disappeared after a recent rebase
2022-03-18 12:23:56 -04:00
jfreegman
0212391d7d
Disable DHT nodeslist fetching temporarily
We don't want to fetch the mainnet nodes list when we're on
the NGC testnet. This should be fixed before the NGC merge
2022-03-18 12:23:56 -04:00
jfreegman
535a8402d6
Merge with master (V0.11.1) 2022-03-18 12:23:55 -04:00
jfreegman
2c51afd9ef
Sync with master branch 2022-03-18 12:23:55 -04:00
jfreegman
4aca8b6ecb
Fix/update groupchat UI 2022-03-18 12:23:55 -04:00
jfreegman
28be56aad9
Fix bug causing group PM's to increment window notifications by 2 instead of 1 2022-03-18 12:23:54 -04:00
jfreegman
38004367a1
Port fix for invalid error handling of widechar conversions from master 2022-03-18 12:23:54 -04:00
jfreegman
5499bb6645
Fix/update group logging implementation 2022-03-18 12:23:53 -04:00
jfreegman
ed8ba89cd8
Fix merge conflicts with master 2022-03-18 12:23:53 -04:00
jfreegman
812210d63f
Implement new groupchats 2022-03-18 12:23:53 -04:00
jfreegman
cec96e1ea3
Use calloc instead of malloc for new message queue items
This prevents us from accidentally using uninitialized memory
2022-03-18 12:17:50 -04:00
iphydf
eb7e6151a2
cleanup: Ensure python_api.c is never completely empty.
C doesn't allow this, there must be at least some declarations in it,
even if no code.
2022-03-17 17:52:37 +00:00
jfreegman
22ca3704d2
Use a small hack to get around an ncurses buffer overread
Patch by iphydf
2022-03-16 16:31:41 -04:00
iphydf
fdfaaf953f
cleanup: Remove all uses of deprecated enum names.
All-caps enum names have been deprecated for a while now and will go
away in 0.3.0.
2022-03-07 19:20:35 +00:00
30 changed files with 469 additions and 214 deletions

View File

@ -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 &&

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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>

View File

@ -1 +0,0 @@
toxme.io 1A39E7A5D5FA9CF155C751570A32E625698A60A55F6D88028F949F66144F4F25

View File

@ -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;

View File

@ -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"

View File

@ -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;
}

View File

@ -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) {

View File

@ -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 },
};

View File

@ -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);

View File

@ -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);
}

View 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])

View File

@ -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]);

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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 */

View File

@ -20,9 +20,10 @@
*
*/
#include "api.h"
#ifdef PYTHON
#include <Python.h>
#include "api.h"
#include "execute.h"

View File

@ -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);

View File

@ -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,

View File

@ -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);
}

View File

@ -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);

View File

@ -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);