1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-30 23:06:38 +02:00

irc: add server option "autojoin_record"

This commit is contained in:
Sébastien Helleu
2022-03-06 16:34:32 +01:00
parent f81a0dc4d9
commit c1e65e8edd
26 changed files with 1028 additions and 10 deletions
+1
View File
@@ -31,6 +31,7 @@ add_library(irc MODULE
irc-ignore.c irc-ignore.h
irc-info.c irc-info.h
irc-input.c irc-input.h
irc-join.c irc-join.h
irc-message.c irc-message.h
irc-mode.c irc-mode.h
irc-modelist.c irc-modelist.h
+2
View File
@@ -49,6 +49,8 @@ irc_la_SOURCES = irc.c \
irc-info.h \
irc-input.c \
irc-input.h \
irc-join.c \
irc-join.h \
irc-message.c \
irc-message.h \
irc-mode.c \
+53 -10
View File
@@ -41,6 +41,7 @@
#include "irc-config.h"
#include "irc-ignore.h"
#include "irc-input.h"
#include "irc-join.h"
#include "irc-message.h"
#include "irc-mode.h"
#include "irc-modelist.h"
@@ -2632,8 +2633,8 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments,
int manual_join, int noswitch)
{
char *new_args, **channels, **keys, *pos_space, *pos_keys, *pos_channel;
char *channel_name;
int i, num_channels, num_keys, length;
char *channel_name, *ptr_key;
int i, num_channels, num_keys, length, record;
time_t time_now;
struct t_irc_channel *ptr_channel;
@@ -2646,6 +2647,8 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments,
return;
}
record = IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOJOIN_RECORD);
/* split channels and keys */
channels = NULL;
num_channels = 0;
@@ -2733,8 +2736,10 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments,
free (channel_name);
}
}
ptr_key = NULL;
if (keys && (i < num_keys))
{
ptr_key = keys[i];
ptr_channel = irc_channel_search (server, pos_channel);
if (ptr_channel)
{
@@ -2749,16 +2754,24 @@ irc_command_join_server (struct t_irc_server *server, const char *arguments,
}
}
if (manual_join
&& weechat_config_boolean (irc_config_look_buffer_open_before_join)
&& !irc_channel_search (server, pos_channel)
&& (strcmp (pos_channel, "0") != 0))
{
/*
* open the channel buffer immediately (do not wait for the
* JOIN sent by server)
*/
irc_channel_create_buffer (
server, IRC_CHANNEL_TYPE_CHANNEL, pos_channel, 1, 1);
if (weechat_config_boolean (irc_config_look_buffer_open_before_join))
{
/*
* open the channel buffer immediately (do not wait
* for the JOIN sent by server)
*/
irc_channel_create_buffer (
server, IRC_CHANNEL_TYPE_CHANNEL, pos_channel,
1, 1);
}
if (record)
{
irc_join_add_channel_to_autojoin (server, pos_channel,
ptr_key);
}
}
}
if (pos_space)
@@ -4070,7 +4083,8 @@ irc_command_part_channel (struct t_irc_server *server, const char *channel_name,
IRC_COMMAND_CALLBACK(part)
{
char *channel_name, *pos_args;
char *channel_name, *pos_args, **channels;
int i, num_channels;
IRC_BUFFER_GET_SERVER_CHANNEL(buffer);
IRC_COMMAND_CHECK_SERVER("part", 1, 1);
@@ -4129,6 +4143,23 @@ IRC_COMMAND_CALLBACK(part)
irc_command_part_channel (ptr_server, channel_name, pos_args);
if (IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOJOIN_RECORD))
{
channels = weechat_string_split (channel_name, ",", NULL,
WEECHAT_STRING_SPLIT_STRIP_LEFT
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0, &num_channels);
if (channels)
{
for (i = 0; i < num_channels; i++)
{
irc_join_remove_channel_from_autojoin (ptr_server, channels[i]);
}
weechat_string_free_split (channels);
}
}
return WEECHAT_RC_OK;
}
@@ -5104,6 +5135,18 @@ irc_command_display_server (struct t_irc_server *server, int with_detail)
weechat_printf (NULL, " autojoin . . . . . . : %s'%s'",
IRC_COLOR_CHAT_VALUE,
weechat_config_string (server->options[IRC_SERVER_OPTION_AUTOJOIN]));
/* autojoin_record */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOJOIN_RECORD]))
weechat_printf (NULL, " autojoin_record. . . : (%s)",
(IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOJOIN_RECORD)) ?
_("on") : _("off"));
else
weechat_printf (NULL, " autojoin_record. . . : %s%s",
IRC_COLOR_CHAT_VALUE,
(weechat_config_boolean (server->options[IRC_SERVER_OPTION_AUTOJOIN_RECORD])) ?
_("on") : _("off"));
/* autorejoin */
if (weechat_config_option_is_null (server->options[IRC_SERVER_OPTION_AUTOREJOIN]))
weechat_printf (NULL, " autorejoin . . . . . : (%s)",
+18
View File
@@ -2217,6 +2217,24 @@ irc_config_server_new_option (struct t_config_file *config_file,
callback_change_data,
NULL, NULL, NULL);
break;
case IRC_SERVER_OPTION_AUTOJOIN_RECORD:
new_option = weechat_config_new_option (
config_file, section,
option_name, "boolean",
N_("set automatically the \"autojoin\" option according to "
"the channels you manually join and part with commands "
"/join and /part"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case IRC_SERVER_OPTION_AUTOREJOIN:
new_option = weechat_config_new_option (
config_file, section,
+377
View File
@@ -0,0 +1,377 @@
/*
* irc-join.c - functions for list of channels to join
*
* Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "irc.h"
#include "irc-join.h"
#include "irc-config.h"
#include "irc-server.h"
/*
* Compares two join channels.
*/
int
irc_join_compare_cb (void *data, struct t_arraylist *arraylist,
void *pointer1, void *pointer2)
{
struct t_irc_server *server;
struct t_irc_join_channel *channel1, *channel2;
int rc;
/* make C compiler happy */
(void) arraylist;
server = (struct t_irc_server *)data;
channel1 = (struct t_irc_join_channel *)pointer1;
channel2 = (struct t_irc_join_channel *)pointer2;
/*
* if channel is the same, always consider it's the same, even if the key
* is different
*/
rc = irc_server_strcasecmp (server, channel1->name, channel2->name);
if (rc == 0)
return 0;
/* channels with a key are first in list */
if (channel1->key && !channel2->key)
return -1;
if (!channel1->key && channel2->key)
return 1;
return 1;
}
/*
* Frees a join channel.
*/
void
irc_join_free_cb (void *data, struct t_arraylist *arraylist, void *pointer)
{
struct t_irc_join_channel *channel;
/* make C compiler happy */
(void) data;
(void) arraylist;
channel = (struct t_irc_join_channel *)pointer;
if (channel->name)
free (channel->name);
if (channel->key)
free (channel->key);
free (channel);
}
/*
* Splits join string and returns an array list with a list of
* channels/keys.
*
* The format of channels/keys is the one specified by RFC 1459 for the JOIN
* command (channels with key first in list), for example:
*
* #channel1,#channel2,#channel3 key1,key2
*/
struct t_arraylist *
irc_join_split (struct t_irc_server *server, const char *join)
{
struct t_arraylist *arraylist;
char **items, **channels, **keys;
int count_items, count_channels, count_keys, i;
const char *ptr_channels, *ptr_keys;
struct t_irc_join_channel *new_channel;
arraylist = NULL;
items = NULL;
count_items = 0;
ptr_channels = NULL;
ptr_keys = NULL;
channels = NULL;
count_channels = 0;
keys = NULL;
count_keys = 0;
items = weechat_string_split ((join) ? join : "",
" ", NULL,
WEECHAT_STRING_SPLIT_STRIP_LEFT |
WEECHAT_STRING_SPLIT_STRIP_RIGHT |
WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0, &count_items);
if (count_items >= 1)
ptr_channels = items[0];
if (count_items >= 2)
ptr_keys = items[1];
if (ptr_channels)
{
channels = weechat_string_split (ptr_channels, ",", NULL,
WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0, &count_channels);
}
if (ptr_keys)
{
keys = weechat_string_split (ptr_keys, ",", NULL,
WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
0, &count_keys);
}
arraylist = weechat_arraylist_new (
16, 1, 0,
&irc_join_compare_cb, server,
&irc_join_free_cb, NULL);
if (!arraylist)
goto end;
for (i = 0; i < count_channels; i++)
{
new_channel = (struct t_irc_join_channel *)malloc (sizeof (*new_channel));
new_channel->name = strdup (channels[i]);
new_channel->key = (i < count_keys) ? strdup (keys[i]) : NULL;
weechat_arraylist_add (arraylist, new_channel);
}
end:
if (items)
weechat_string_free_split (items);
if (channels)
weechat_string_free_split (channels);
if (keys)
weechat_string_free_split (keys);
return arraylist;
}
/*
* Builds string with a list of channels/keys.
*
* Note: result must be freed after use.
*/
char *
irc_join_build_string (struct t_arraylist *arraylist)
{
struct t_irc_join_channel *channel;
char **channels, **keys, *result;
int size, i;
if (!arraylist)
return strdup ("");
channels = NULL;
keys = NULL;
result = NULL;
channels = weechat_string_dyn_alloc (1024);
if (!channels)
goto end;
keys = weechat_string_dyn_alloc (1024);
if (!keys)
goto end;
size = weechat_arraylist_size (arraylist);
for (i = 0; i < size; i++)
{
channel = (struct t_irc_join_channel *)weechat_arraylist_get (
arraylist, i);
if (*channels[0])
weechat_string_dyn_concat (channels, ",", -1);
weechat_string_dyn_concat (channels, channel->name, -1);
if (channel->key)
{
if (*keys[0])
weechat_string_dyn_concat (keys, ",", -1);
weechat_string_dyn_concat (keys, channel->key, -1);
}
}
if (*keys[0])
{
weechat_string_dyn_concat (channels, " ", -1);
weechat_string_dyn_concat (channels, *keys, -1);
}
end:
if (channels)
{
result = *channels;
weechat_string_dyn_free (channels, 0);
}
if (keys)
weechat_string_dyn_free (keys, 1);
return (result) ? result : strdup ("");
}
/*
* Adds a channel with optional key to the join string.
*
* Channels with a key are first in list, so for example:
*
* join = "#abc,#def,#ghi key_abc,key_def"
* channel_name = "#xyz"
* key = "key_xyz"
*
* => returned value: "#abc,#def,#xyz,#ghi key_abc,key_def,key_xyz"
*
* Note: result must be freed after use.
*/
char *
irc_join_add_channel (struct t_irc_server *server,
const char *join,
const char *channel_name, const char *key)
{
struct t_arraylist *arraylist;
struct t_irc_join_channel *channel;
char *new_join;
if (!channel_name)
return NULL;
arraylist = irc_join_split (server, join);
if (!arraylist)
return NULL;
channel = (struct t_irc_join_channel *)malloc (sizeof (*channel));
channel->name = strdup (channel_name);
channel->key = (key && key[0]) ? strdup (key) : NULL;
weechat_arraylist_add (arraylist, channel);
new_join = irc_join_build_string (arraylist);
weechat_arraylist_free (arraylist);
return new_join;
}
/*
* Adds a channel with optional key to the autojoin option of a server.
*/
void
irc_join_add_channel_to_autojoin (struct t_irc_server *server,
const char *channel_name, const char *key)
{
char *new_autojoin;
if (!channel_name)
return;
new_autojoin = irc_join_add_channel (
server,
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN),
channel_name,
key);
if (new_autojoin)
{
weechat_config_option_set (
server->options[IRC_SERVER_OPTION_AUTOJOIN],
new_autojoin,
1);
free (new_autojoin);
}
}
/*
* Removes a channel from a join string.
*
* Channels with a key are first in list, so for example:
*
* join = "#abc,#def,#ghi key_abc,key_def"
* channel_name = "#def"
*
* => returned value: "#abc,#ghi key_abc"
*
* Note: result must be freed after use.
*/
char *
irc_join_remove_channel (struct t_irc_server *server,
const char *join, const char *channel_name)
{
struct t_arraylist *arraylist;
struct t_irc_join_channel *channel;
char *new_join;
int i;
if (!channel_name)
return NULL;
arraylist = irc_join_split (server, join);
if (!arraylist)
return NULL;
i = 0;
while (i < weechat_arraylist_size (arraylist))
{
channel = (struct t_irc_join_channel *)weechat_arraylist_get (
arraylist, i);
if (irc_server_strcasecmp (server, channel->name, channel_name) == 0)
weechat_arraylist_remove (arraylist, i);
else
i++;
}
new_join = irc_join_build_string (arraylist);
weechat_arraylist_free (arraylist);
return new_join;
}
/*
* Removes a channel from server autojoin option.
*/
void
irc_join_remove_channel_from_autojoin (struct t_irc_server *server,
const char *channel_name)
{
char *new_autojoin;
if (!channel_name)
return;
new_autojoin = irc_join_remove_channel (
server,
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN),
channel_name);
if (new_autojoin)
{
weechat_config_option_set (
server->options[IRC_SERVER_OPTION_AUTOJOIN],
new_autojoin,
1);
free (new_autojoin);
}
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 Sébastien Helleu <flashcode@flashtux.org>
*
* This file is part of WeeChat, the extensible chat client.
*
* WeeChat is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* WeeChat is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef WEECHAT_PLUGIN_IRC_JOIN_H
#define WEECHAT_PLUGIN_IRC_JOIN_H
struct t_irc_server;
struct t_irc_join_channel
{
char *name; /* channel name */
char *key; /* channel key */
};
extern struct t_arraylist *irc_join_split (struct t_irc_server *server,
const char *join);
extern char *irc_join_build_string (struct t_arraylist *arraylist);
extern char *irc_join_add_channel (struct t_irc_server *server,
const char *join, const char *channel_name,
const char *key);
void irc_join_add_channel_to_autojoin (struct t_irc_server *server,
const char *channel_name,
const char *key);
extern char *irc_join_remove_channel (struct t_irc_server *server,
const char *join,
const char *channel_name);
void irc_join_remove_channel_from_autojoin (struct t_irc_server *server,
const char *channel_name);
#endif /* WEECHAT_PLUGIN_IRC_JOIN_H */
+13
View File
@@ -107,6 +107,7 @@ char *irc_server_options[IRC_SERVER_NUM_OPTIONS][2] =
{ "command", "" },
{ "command_delay", "0" },
{ "autojoin", "" },
{ "autojoin_record", "off" },
{ "autorejoin", "off" },
{ "autorejoin_delay", "30" },
{ "connection_timeout", "60" },
@@ -6289,6 +6290,9 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
if (!weechat_infolist_new_var_string (ptr_item, "autojoin",
IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "autojoin_record",
IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOJOIN_RECORD)))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "autorejoin",
IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTOREJOIN)))
return 0;
@@ -6648,6 +6652,15 @@ irc_server_print_log ()
else
weechat_log_printf (" autojoin. . . . . . . . . : '%s'",
weechat_config_string (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN]));
/* autojoin_record */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN_RECORD]))
weechat_log_printf (" autojoin_record . . . . . : null (%s)",
(IRC_SERVER_OPTION_BOOLEAN(ptr_server, IRC_SERVER_OPTION_AUTOJOIN_RECORD)) ?
"on" : "off");
else
weechat_log_printf (" autojoin_record . . . . . : %s",
(weechat_config_boolean (ptr_server->options[IRC_SERVER_OPTION_AUTOJOIN_RECORD])) ?
"on" : "off");
/* autorejoin */
if (weechat_config_option_is_null (ptr_server->options[IRC_SERVER_OPTION_AUTOREJOIN]))
weechat_log_printf (" autorejoin. . . . . . . . : null (%s)",
+1
View File
@@ -79,6 +79,7 @@ enum t_irc_server_option
IRC_SERVER_OPTION_COMMAND, /* command to run once connected */
IRC_SERVER_OPTION_COMMAND_DELAY, /* delay after execution of command */
IRC_SERVER_OPTION_AUTOJOIN, /* channels to automatically join */
IRC_SERVER_OPTION_AUTOJOIN_RECORD, /* auto set autojoin option */
IRC_SERVER_OPTION_AUTOREJOIN, /* auto rejoin channels when kicked */
IRC_SERVER_OPTION_AUTOREJOIN_DELAY, /* delay before auto rejoin */
IRC_SERVER_OPTION_CONNECTION_TIMEOUT, /* timeout for connection */