summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2014-01-23 11:31:57 +0100
committerSebastien Helleu <flashcode@flashtux.org>2014-01-23 11:31:57 +0100
commit3acdcee0d94feaf2845c3e74d323f8c5dd01d70a (patch)
tree1aca3f34fb571b74b4190ef8d188c4b140ca2640 /src/plugins
parent6d4bc94536e162f40a0e5ec5d9db21f6cde85863 (diff)
downloadweechat-3acdcee0d94feaf2845c3e74d323f8c5dd01d70a.zip
irc: use MONITOR instead of ISON for /notify when it is available on server (task #11477) (patch from Nils Görs)
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/irc/irc-command.c26
-rw-r--r--src/plugins/irc/irc-message.c43
-rw-r--r--src/plugins/irc/irc-notify.c249
-rw-r--r--src/plugins/irc/irc-notify.h5
-rw-r--r--src/plugins/irc/irc-protocol.c189
-rw-r--r--src/plugins/irc/irc-redirect.c11
-rw-r--r--src/plugins/irc/irc-server.c228
-rw-r--r--src/plugins/irc/irc-server.h3
-rw-r--r--src/plugins/irc/irc-upgrade.c18
9 files changed, 589 insertions, 183 deletions
diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c
index 092c54859..ae6dbedfa 100644
--- a/src/plugins/irc/irc-command.c
+++ b/src/plugins/irc/irc-command.c
@@ -3428,17 +3428,27 @@ irc_command_notify (void *data, struct t_gui_buffer *buffer, int argc,
return WEECHAT_RC_OK;
}
+ if ((ptr_server->monitor > 0)
+ && (ptr_server->notify_count >= ptr_server->monitor))
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%sMonitor list is full (%d)"),
+ weechat_prefix ("error"), ptr_server->monitor);
+ return WEECHAT_RC_OK;
+ }
+
ptr_notify = irc_notify_new (ptr_server, argv[2], check_away);
if (ptr_notify)
{
irc_notify_set_server_option (ptr_server);
weechat_printf (ptr_server->buffer,
- _("%s: notification added for %s%s"),
+ _("%s: notification added for %s%s%s"),
IRC_PLUGIN_NAME,
irc_nick_color_for_server_message (ptr_server,
NULL,
ptr_notify->nick),
- ptr_notify->nick);
+ ptr_notify->nick,
+ weechat_color ("reset"));
irc_notify_check_now (ptr_notify);
}
else
@@ -3505,10 +3515,16 @@ irc_command_notify (void *data, struct t_gui_buffer *buffer, int argc,
ptr_notify = irc_notify_search (ptr_server, argv[2]);
if (ptr_notify)
{
- irc_notify_free (ptr_server, ptr_notify);
+ weechat_printf (ptr_server->buffer,
+ _("%s: notification deleted for %s%s%s"),
+ IRC_PLUGIN_NAME,
+ irc_nick_color_for_server_message (ptr_server,
+ NULL,
+ ptr_notify->nick),
+ ptr_notify->nick,
+ weechat_color ("reset"));
+ irc_notify_free (ptr_server, ptr_notify, 1);
irc_notify_set_server_option (ptr_server);
- weechat_printf (NULL, _("%s: notification deleted"),
- IRC_PLUGIN_NAME);
}
else
{
diff --git a/src/plugins/irc/irc-message.c b/src/plugins/irc/irc-message.c
index 1e1e5cb45..1b0fc76bd 100644
--- a/src/plugins/irc/irc-message.c
+++ b/src/plugins/irc/irc-message.c
@@ -798,7 +798,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
{
struct t_hashtable *hashtable;
char **argv, **argv_eol, *tags, *host, *command, *arguments, target[512];
- char *pos;
+ char *pos, monitor_action[3];
int split_ok, argc, index_args, max_length_nick, max_length_host;
split_ok = 0;
@@ -868,17 +868,47 @@ irc_message_split (struct t_irc_server *server, const char *message)
if ((weechat_strcasecmp (command, "ison") == 0)
|| (weechat_strcasecmp (command, "wallops") == 0))
{
+ /*
+ * ISON :nick1 nick2 nick3
+ * WALLOPS :some text here
+ */
split_ok = irc_message_split_string (hashtable, tags, host, command,
NULL, ":",
(argv_eol[index_args][0] == ':') ?
argv_eol[index_args] + 1 : argv_eol[index_args],
NULL, ' ', max_length_host);
}
+ else if (weechat_strcasecmp (command, "monitor") == 0)
+ {
+ /*
+ * MONITOR + nick1,nick2,nick3
+ * MONITOR - nick1,nick2,nick3
+ */
+ if (((argv_eol[index_args][0] == '+') || (argv_eol[index_args][0] == '-'))
+ && (argv_eol[index_args][1] == ' '))
+ {
+ snprintf (monitor_action, sizeof (monitor_action),
+ "%c ", argv_eol[index_args][0]);
+ split_ok = irc_message_split_string (hashtable, tags, host, command,
+ NULL, monitor_action,
+ argv_eol[index_args] + 2,
+ NULL, ',', max_length_host);
+ }
+ else
+ {
+ split_ok = irc_message_split_string (hashtable, tags, host, command,
+ NULL, ":",
+ (argv_eol[index_args][0] == ':') ?
+ argv_eol[index_args] + 1 : argv_eol[index_args],
+ NULL, ',', max_length_host);
+ }
+ }
else if (weechat_strcasecmp (command, "join") == 0)
{
- /* split join (if it's more than 510 bytes) */
+ /* JOIN #channel1,#channel2,#channel3 key1,key2 */
if (strlen (message) > 510)
{
+ /* split join if it's more than 510 bytes */
split_ok = irc_message_split_join (hashtable, tags, host,
arguments);
}
@@ -886,7 +916,10 @@ irc_message_split (struct t_irc_server *server, const char *message)
else if ((weechat_strcasecmp (command, "privmsg") == 0)
|| (weechat_strcasecmp (command, "notice") == 0))
{
- /* split privmsg/notice */
+ /*
+ * PRIVMSG target :some text here
+ * NOTICE target :some text here
+ */
if (index_args + 1 <= argc - 1)
{
split_ok = irc_message_split_privmsg_notice (hashtable, tags, host,
@@ -899,7 +932,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
}
else if (weechat_strcasecmp (command, "005") == 0)
{
- /* split 005 (isupport) */
+ /* :server 005 nick MODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 ... */
if (index_args + 1 <= argc - 1)
{
split_ok = irc_message_split_005 (hashtable, tags, host, command,
@@ -911,7 +944,7 @@ irc_message_split (struct t_irc_server *server, const char *message)
else if (weechat_strcasecmp (command, "353") == 0)
{
/*
- * split 353 (list of users on channel):
+ * list of users on channel:
* :server 353 mynick = #channel :mynick nick1 @nick2 +nick3
*/
if (index_args + 2 <= argc - 1)
diff --git a/src/plugins/irc/irc-notify.c b/src/plugins/irc/irc-notify.c
index 823c52dff..503a34cbe 100644
--- a/src/plugins/irc/irc-notify.c
+++ b/src/plugins/irc/irc-notify.c
@@ -189,8 +189,12 @@ irc_notify_new (struct t_irc_server *server, const char *nick, int check_away)
{
struct t_irc_notify *new_notify;
- if (!server || !nick || !nick[0])
+ if (!server || !nick || !nick[0]
+ || ((server->monitor > 0)
+ && ((server->notify_count >= server->monitor))))
+ {
return NULL;
+ }
new_notify = malloc (sizeof (*new_notify));
if (new_notify)
@@ -210,37 +214,146 @@ irc_notify_new (struct t_irc_server *server, const char *nick, int check_away)
server->notify_list = new_notify;
server->last_notify = new_notify;
new_notify->next_notify = NULL;
+
+ server->notify_count++;
}
return new_notify;
}
/*
- * Checks now ison/whois for a notify (called when a notify is added).
+ * Checks now if a nick is connected with ison/monitor + whois (if away checking
+ * is enabled).
+ *
+ * It is called when a notify is added.
*/
void
irc_notify_check_now (struct t_irc_notify *notify)
{
- if (notify->server->is_connected)
+ /* don't send anything if we are not connected to the server */
+ if (!notify->server->is_connected)
+ return;
+
+ if (notify->server->monitor > 0)
{
- /* send the ISON for nick */
- irc_redirect_new (notify->server, "ison", "notify", 1,
- NULL, 0, NULL);
- irc_server_sendf (notify->server,
- IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
+ /* send MONITOR for nick */
+ irc_server_sendf (notify->server, IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
+ "MONITOR + %s", notify->nick);
+ }
+ else
+ {
+ /* send ISON for nick (MONITOR not supported on server) */
+ irc_redirect_new (notify->server, "ison", "notify", 1, NULL, 0, NULL);
+ irc_server_sendf (notify->server, IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
"ISON :%s", notify->nick);
+ }
+
+ if (notify->check_away)
+ {
+ /* send WHOIS for nick */
+ irc_redirect_new (notify->server, "whois", "notify", 1, notify->nick, 0,
+ "301,401");
+ irc_server_sendf (notify->server, IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
+ "WHOIS :%s", notify->nick);
+ }
+}
+
+/*
+ * Builds a message with nicks (ISON or MONITOR).
+ *
+ * Argument "message" must be "ISON :" or "MONITOR + " or "MONITOR - ".
+ * Argument "separator" must be " " for ISON and "," for MONITOR.
+ * Argument "num_nicks" is set with the number of nicks added in message.
+ *
+ * Note: result must be freed after use.
+ */
+
+char *
+irc_notify_build_message_with_nicks (struct t_irc_server *server,
+ const char *irc_message,
+ const char *separator,
+ int *num_nicks)
+{
+ char *message, *message2;
+ int length, total_length, length_separator;
+ struct t_irc_notify *ptr_notify;
+
+ *num_nicks = 0;
+
+ length = strlen (irc_message) + 1;
+ total_length = length;
+ length_separator = strlen (separator);
- if (notify->check_away)
+ message = malloc (length);
+ if (!message)
+ return NULL;
+ snprintf (message, length, "%s", irc_message);
+
+ for (ptr_notify = server->notify_list; ptr_notify;
+ ptr_notify = ptr_notify->next_notify)
+ {
+ length = strlen (ptr_notify->nick);
+ total_length += length + length_separator;
+ message2 = realloc (message, total_length);
+ if (!message2)
{
- /* send the WHOIS for nick */
- irc_redirect_new (notify->server, "whois", "notify", 1,
- notify->nick, 0, "301,401");
- irc_server_sendf (notify->server,
- IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
- "WHOIS :%s", notify->nick);
+ if (message)
+ free (message);
+ message = NULL;
+ break;
}
+ message = message2;
+ if (*num_nicks > 0)
+ strcat (message, separator);
+ strcat (message, ptr_notify->nick);
+
+ (*num_nicks)++;
}
+
+ return message;
+}
+
+/*
+ * Sends the MONITOR message (after server connection or if the option
+ * "irc.server.xxx.notify" is changed).
+ */
+
+void
+irc_notify_send_monitor (struct t_irc_server *server)
+{
+ struct t_hashtable *hashtable;
+ char *message, hash_key[32];
+ const char *str_message;
+ int num_nicks, number;
+
+ message = irc_notify_build_message_with_nicks (server,
+ "MONITOR + ",
+ ",",
+ &num_nicks);
+ if (message && (num_nicks > 0))
+ {
+ hashtable = irc_message_split (server, message);
+ if (hashtable)
+ {
+ number = 1;
+ while (1)
+ {
+ snprintf (hash_key, sizeof (hash_key), "msg%d", number);
+ str_message = weechat_hashtable_get (hashtable,
+ hash_key);
+ if (!str_message)
+ break;
+ irc_server_sendf (server,
+ IRC_SERVER_SEND_OUTQ_PRIO_LOW,
+ NULL, "%s", str_message);
+ number++;
+ }
+ weechat_hashtable_free (hashtable);
+ }
+ }
+ if (message)
+ free (message);
}
/*
@@ -257,12 +370,10 @@ irc_notify_new_for_server (struct t_irc_server *server)
irc_notify_free_all (server);
notify = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_NOTIFY);
-
if (!notify || !notify[0])
return;
items = weechat_string_split (notify, ",", 0, 0, &num_items);
-
if (items)
{
for (i = 0; i < num_items; i++)
@@ -293,6 +404,10 @@ irc_notify_new_for_server (struct t_irc_server *server)
}
weechat_string_free_split (items);
}
+
+ /* if we are using MONITOR, send it now with new nicks monitored */
+ if (server->is_connected && (server->monitor > 0))
+ irc_notify_send_monitor (server);
}
/*
@@ -316,14 +431,25 @@ irc_notify_new_for_all_servers ()
*/
void
-irc_notify_free (struct t_irc_server *server, struct t_irc_notify *notify)
+irc_notify_free (struct t_irc_server *server, struct t_irc_notify *notify,
+ int remove_monitor)
{
weechat_hook_signal_send ("irc_notify_removing",
WEECHAT_HOOK_SIGNAL_POINTER, notify);
/* free data */
if (notify->nick)
+ {
+ if ((server->monitor > 0) && remove_monitor
+ && (server->is_connected) && !irc_signal_upgrade_received)
+ {
+ /* remove one monitored nick */
+ irc_server_sendf (notify->server,
+ IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
+ "MONITOR - %s", notify->nick);
+ }
free (notify->nick);
+ }
if (notify->away_message)
free (notify->away_message);
@@ -339,6 +465,9 @@ irc_notify_free (struct t_irc_server *server, struct t_irc_notify *notify)
free (notify);
+ if (server->notify_count > 0)
+ server->notify_count--;
+
weechat_hook_signal_send ("irc_notify_removed",
WEECHAT_HOOK_SIGNAL_STRING, NULL);
}
@@ -350,9 +479,18 @@ irc_notify_free (struct t_irc_server *server, struct t_irc_notify *notify)
void
irc_notify_free_all (struct t_irc_server *server)
{
+ /* remove all monitored nicks */
+ if ((server->monitor > 0) && (server->is_connected)
+ && !irc_signal_upgrade_received)
+ {
+ irc_server_sendf (server, IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL,
+ "MONITOR C");
+ }
+
+ /* free notify list */
while (server->notify_list)
{
- irc_notify_free (server, server->notify_list);
+ irc_notify_free (server, server->notify_list, 0);
}
}
@@ -524,7 +662,7 @@ irc_notify_send_signal (struct t_irc_notify *notify,
*/
void
-irc_notify_set_is_on_server (struct t_irc_notify *notify,
+irc_notify_set_is_on_server (struct t_irc_notify *notify, const char *host,
int is_on_server)
{
if (!notify)
@@ -540,18 +678,23 @@ irc_notify_set_is_on_server (struct t_irc_notify *notify,
notify->nick),
(notify->is_on_server < 0) ?
((is_on_server) ?
- _("%snotify: %s%s%s is connected") :
- _("%snotify: %s%s%s is offline")) :
+ _("%snotify: %s%s%s%s%s%s%s%s%s is connected") :
+ _("%snotify: %s%s%s%s%s%s%s%s%s is offline")) :
((is_on_server) ?
- _("%snotify: %s%s%s has joined") :
- _("%snotify: %s%s%s has quit")),
+ _("%snotify: %s%s%s%s%s%s%s%s%s has joined") :
+ _("%snotify: %s%s%s%s%s%s%s%s%s has quit")),
weechat_prefix ("network"),
irc_nick_color_for_server_message (notify->server,
NULL,
notify->nick),
notify->nick,
- (is_on_server) ?
- IRC_COLOR_MESSAGE_JOIN : IRC_COLOR_MESSAGE_QUIT);
+ (host && host[0]) ? IRC_COLOR_CHAT_DELIMITERS : "",
+ (host && host[0]) ? " (" : "",
+ (host && host[0]) ? IRC_COLOR_CHAT_HOST : "",
+ (host && host[0]) ? host : "",
+ (host && host[0]) ? IRC_COLOR_CHAT_DELIMITERS : "",
+ (host && host[0]) ? ")" : "",
+ (is_on_server) ? IRC_COLOR_MESSAGE_JOIN : IRC_COLOR_MESSAGE_QUIT);
irc_notify_send_signal (notify, (is_on_server) ? "join" : "quit", NULL);
notify->is_on_server = is_on_server;
@@ -726,7 +869,9 @@ irc_notify_hsignal_cb (void *data, const char *signal,
ptr_notify->nick,
nicks_recv[j]) == 0)
{
- irc_notify_set_is_on_server (ptr_notify, 1);
+ irc_notify_set_is_on_server (ptr_notify,
+ NULL,
+ 1);
ptr_notify->ison_received = 1;
}
}
@@ -757,7 +902,7 @@ irc_notify_hsignal_cb (void *data, const char *signal,
}
if (nick_was_sent)
{
- irc_notify_set_is_on_server (ptr_notify, 0);
+ irc_notify_set_is_on_server (ptr_notify, NULL, 0);
}
}
@@ -824,11 +969,10 @@ irc_notify_hsignal_cb (void *data, const char *signal,
int
irc_notify_timer_ison_cb (void *data, int remaining_calls)
{
- char *message, *message2, hash_key[32];
+ char *message, hash_key[32];
const char *str_message;
- int total_length, length, nicks_added, number;
+ int num_nicks, number;
struct t_irc_server *ptr_server;
- struct t_irc_notify *ptr_notify, *ptr_next_notify;
struct t_hashtable *hashtable;
/* make C compiler happy */
@@ -838,41 +982,15 @@ irc_notify_timer_ison_cb (void *data, int remaining_calls)
for (ptr_server = irc_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
- if (ptr_server->is_connected && ptr_server->notify_list)
+ if (ptr_server->is_connected
+ && ptr_server->notify_list
+ && (ptr_server->monitor == 0))
{
- message = malloc (7);
- if (!message)
- continue;
-
- snprintf (message, 7, "ISON :");
- total_length = 7;
- nicks_added = 0;
-
- ptr_notify = ptr_server->notify_list;
- while (ptr_notify)
- {
- ptr_next_notify = ptr_notify->next_notify;
-
- length = strlen (ptr_notify->nick);
- total_length += length + 1;
- message2 = realloc (message, total_length);
- if (!message2)
- {
- if (message)
- free (message);
- message = NULL;
- break;
- }
- message = message2;
- if (nicks_added > 0)
- strcat (message, " ");
- strcat (message, ptr_notify->nick);
- nicks_added++;
-
- ptr_notify = ptr_next_notify;
- }
-
- if (message && (nicks_added > 0))
+ message = irc_notify_build_message_with_nicks (ptr_server,
+ "ISON :",
+ " ",
+ &num_nicks);
+ if (message && (num_nicks > 0))
{
hashtable = irc_message_split (ptr_server, message);
if (hashtable)
@@ -895,7 +1013,6 @@ irc_notify_timer_ison_cb (void *data, int remaining_calls)
weechat_hashtable_free (hashtable);
}
}
-
if (message)
free (message);
}
diff --git a/src/plugins/irc/irc-notify.h b/src/plugins/irc/irc-notify.h
index 9453a4f76..8590c6f6d 100644
--- a/src/plugins/irc/irc-notify.h
+++ b/src/plugins/irc/irc-notify.h
@@ -54,9 +54,12 @@ extern void irc_notify_check_now (struct t_irc_notify *notify);
extern void irc_notify_new_for_server (struct t_irc_server *server);
extern void irc_notify_new_for_all_servers ();
extern void irc_notify_free (struct t_irc_server *server,
- struct t_irc_notify *notify);
+ struct t_irc_notify *notify, int remove_monitor);
+extern void irc_notify_set_is_on_server (struct t_irc_notify *notify,
+ const char *host, int is_on_server);
extern void irc_notify_free_all (struct t_irc_server *server);
extern void irc_notify_display_list (struct t_irc_server *server);
+extern void irc_notify_send_monitor (struct t_irc_server *server);
extern int irc_notify_timer_ison_cb (void *data, int remaining_calls);
extern int irc_notify_timer_whois_cb (void *data, int remaining_calls);
extern struct t_hdata *irc_notify_hdata_notify_cb (void *data,
diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c
index 8622bbc7f..4283f58ee 100644
--- a/src/plugins/irc/irc-protocol.c
+++ b/src/plugins/irc/irc-protocol.c
@@ -52,6 +52,7 @@
#include "irc-nick.h"
#include "irc-sasl.h"
#include "irc-server.h"
+#include "irc-notify.h"
/*
@@ -2159,6 +2160,8 @@ IRC_PROTOCOL_CALLBACK(001)
/* connection to IRC server is OK! */
server->is_connected = 1;
server->reconnect_delay = 0;
+ server->monitor_time = time (NULL) + 5;
+
if (server->hook_timer_connection)
{
weechat_unhook (server->hook_timer_connection);
@@ -2232,7 +2235,8 @@ IRC_PROTOCOL_CALLBACK(001)
IRC_PROTOCOL_CALLBACK(005)
{
char *pos, *pos2, *pos_start, *error, *isupport2;
- int length_isupport, length, nick_max_length, casemapping;
+ int length_isupport, length, casemapping;
+ long value;
IRC_PROTOCOL_MIN_ARGS(4);
@@ -2262,9 +2266,9 @@ IRC_PROTOCOL_CALLBACK(005)
if (pos2)
pos2[0] = '\0';
error = NULL;
- nick_max_length = (int)strtol (pos, &error, 10);
- if (error && !error[0] && (nick_max_length > 0))
- server->nick_max_length = nick_max_length;
+ value = strtol (pos, &error, 10);
+ if (error && !error[0] && (value > 0))
+ server->nick_max_length = (int)value;
if (pos2)
pos2[0] = ' ';
}
@@ -2314,6 +2318,22 @@ IRC_PROTOCOL_CALLBACK(005)
pos2[0] = ' ';
}
+ /* save monitor (limit) */
+ pos = strstr (argv_eol[3], "MONITOR=");
+ if (pos)
+ {
+ pos += 8;
+ pos2 = strchr (pos, ' ');
+ if (pos2)
+ pos2[0] = '\0';
+ error = NULL;
+ value = strtol (pos, &error, 10);
+ if (error && !error[0] && (value > 0))
+ server->monitor = (int)value;
+ if (pos2)
+ pos2[0] = ' ';
+ }
+
/* save whole message (concatenate to existing isupport, if any) */
pos_start = NULL;
pos = strstr (argv_eol[3], " :");
@@ -4667,6 +4687,162 @@ IRC_PROTOCOL_CALLBACK(729)
}
/*
+ * Callback for the IRC message "730": monitored nicks are online
+ * (RPL_MONONLINE).
+ *
+ * Message looks like:
+ * :server 730 mynick :nick1!user1@host1,nick2!user2@host2
+ */
+
+IRC_PROTOCOL_CALLBACK(730)
+{
+ struct t_irc_notify *ptr_notify;
+ const char *monitor_nick, *monitor_host;
+ char **nicks;
+ int i, num_nicks;
+
+ IRC_PROTOCOL_MIN_ARGS(4);
+
+ nicks = weechat_string_split ((argv_eol[3][0] == ':') ?
+ argv_eol[3] + 1 : argv_eol[3],
+ ",", 0, 0, &num_nicks);
+ if (nicks)
+ {
+ for (i = 0; i < num_nicks; i++)
+ {
+ monitor_nick = irc_message_get_nick_from_host (nicks[i]);
+ monitor_host = strchr (nicks[i], '!');
+ if (monitor_host)
+ monitor_host++;
+ ptr_notify = irc_notify_search (server, monitor_nick);
+ if (ptr_notify)
+ irc_notify_set_is_on_server (ptr_notify, monitor_host, 1);
+ }
+ weechat_string_free_split (nicks);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for the IRC message "731": monitored nicks are offline
+ * (RPL_MONOFFLINE).
+ *
+ * Message looks like:
+ * :server 731 mynick :nick1!user1@host1,nick2!user2@host2
+ */
+
+IRC_PROTOCOL_CALLBACK(731)
+{
+ struct t_irc_notify *ptr_notify;
+ const char *monitor_nick, *monitor_host;
+ char **nicks;
+ int i, num_nicks;
+
+ IRC_PROTOCOL_MIN_ARGS(4);
+
+ nicks = weechat_string_split ((argv_eol[3][0] == ':') ?
+ argv_eol[3] + 1 : argv_eol[3],
+ ",", 0, 0, &num_nicks);
+ if (nicks)
+ {
+ for (i = 0; i < num_nicks; i++)
+ {
+ monitor_nick = irc_message_get_nick_from_host (nicks[i]);
+ monitor_host = strchr (nicks[i], '!');
+ if (monitor_host)
+ monitor_host++;
+ ptr_notify = irc_notify_search (server, monitor_nick);
+ if (ptr_notify)
+ irc_notify_set_is_on_server (ptr_notify, monitor_host, 0);
+ }
+ weechat_string_free_split (nicks);
+ }
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for the IRC message "732": list of monitored nicks (RPL_MONLIST).
+ *
+ * Message looks like:
+ * :server 732 mynick :nick1!user1@host1,nick2!user2@host2
+ */
+
+IRC_PROTOCOL_CALLBACK(732)
+{
+ char *pos_args;
+
+ IRC_PROTOCOL_MIN_ARGS(3);
+
+ pos_args = (argc > 3) ?
+ ((argv_eol[3][0] == ':') ? argv_eol[3] + 1 : argv_eol[3]) : NULL;
+
+ weechat_printf_date_tags (irc_msgbuffer_get_target_buffer (server, NULL,
+ command, "monitor",
+ NULL),
+ date,
+ irc_protocol_tags (command, "irc_numeric", NULL),
+ "%s%s",
+ weechat_prefix ("network"),
+ (pos_args && pos_args[0]) ? pos_args : "");
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for the IRC message "733": end of a monitor list (RPL_ENDOFMONLIST).
+ *
+ * Message looks like:
+ * :server 733 mynick :End of MONITOR list
+ */
+
+IRC_PROTOCOL_CALLBACK(733)
+{
+ char *pos_args;
+
+ IRC_PROTOCOL_MIN_ARGS(3);
+
+ pos_args = (argc > 3) ?
+ ((argv_eol[3][0] == ':') ? argv_eol[3] + 1 : argv_eol[3]) : NULL;
+
+ weechat_printf_date_tags (irc_msgbuffer_get_target_buffer (server, NULL,
+ command, "monitor",
+ NULL),
+ date,
+ irc_protocol_tags (command, "irc_numeric", NULL),
+ "%s%s",
+ weechat_prefix ("network"),
+ (pos_args && pos_args[0]) ? pos_args : "");
+
+ return WEECHAT_RC_OK;
+}
+
+/*
+ * Callback for the IRC message "734": monitor list is full (ERR_MONLISTFULL)
+ *
+ * Message looks like:
+ * :server 734 mynick limit nick1,nick2 :Monitor list is full.
+ */
+
+IRC_PROTOCOL_CALLBACK(734)
+{
+ IRC_PROTOCOL_MIN_ARGS(5);
+
+ weechat_printf_date_tags (irc_msgbuffer_get_target_buffer (server, NULL,
+ command, "monitor",
+ NULL),
+ date,
+ irc_protocol_tags (command, "irc_numeric", NULL),
+ "%s%s (%s)",
+ weechat_prefix ("error"),
+ (argv_eol[5][0] == ':') ? argv_eol[5] + 1 : argv_eol[5],
+ argv[3]);
+
+ return WEECHAT_RC_OK;
+}
+
+/*
* Callback for the IRC message "900": logged in as (SASL).
*
* Message looks like:
@@ -5005,6 +5181,11 @@ irc_protocol_recv_command (struct t_irc_server *server,
{ "671", /* whois (secure connection) */ 1, 0, &irc_protocol_cb_whois_nick_msg },
{ "728", /* quietlist */ 1, 0, &irc_protocol_cb_728 },
{ "729", /* end of quietlist */ 1, 0, &irc_protocol_cb_729 },
+ { "730", /* monitored nicks online */ 1, 0, &irc_protocol_cb_730 },
+ { "731", /* monitored nicks offline */ 1, 0, &irc_protocol_cb_731 },
+ { "732", /* list of monitored nicks */ 1, 0, &irc_protocol_cb_732 },
+ { "733", /* end of monitor list */ 1, 0, &irc_protocol_cb_733 },
+ { "734", /* monitor list is full */ 1, 0, &irc_protocol_cb_734 },
{ "900", /* logged in as (SASL) */ 1, 0, &irc_protocol_cb_900 },
{ "901", /* you are now logged in */ 1, 0, &irc_protocol_cb_901 },
{ "903", /* SASL authentication successful */ 1, 0, &irc_protocol_cb_sasl_end },
diff --git a/src/plugins/irc/irc-redirect.c b/src/plugins/irc/irc-redirect.c
index 30da704bf..9d3194711 100644
--- a/src/plugins/irc/irc-redirect.c
+++ b/src/plugins/irc/irc-redirect.c
@@ -135,6 +135,17 @@ struct t_irc_redirect_pattern irc_redirect_patterns_default[] =
NULL,
NULL, NULL,
},
+ { "monitor", 0, 0,
+ /*
+ * monitor: start: 732: list of monitored nicks
+ * stop: 733: end of a monitor list
+ * extra; -
+ */
+ "732:2",
+ "733:1",
+ NULL,
+ NULL, NULL,
+ },
{ "names", 0, 0,
/*
* names: start: 353: list of nicks on channel
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index 2e51a06c2..d7b391401 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -980,6 +980,8 @@ irc_server_alloc (const char *name)
new_server->casemapping = IRC_SERVER_CASEMAPPING_RFC1459;
new_server->chantypes = NULL;
new_server->chanmodes = NULL;
+ new_server->monitor = 0;
+ new_server->monitor_time = 0;
new_server->reconnect_delay = 0;
new_server->reconnect_start = 0;
new_server->command_time = 0;
@@ -1007,6 +1009,7 @@ irc_server_alloc (const char *name)
new_server->last_redirect = NULL;
new_server->notify_list = NULL;
new_server->last_notify = NULL;
+ new_server->notify_count = 0;
new_server->join_manual = weechat_hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_TIME,
@@ -2826,129 +2829,138 @@ irc_server_timer_cb (void *data, int remaining_calls)
}
else
{
- if (ptr_server->is_connected)
- {
- /* send queued messages */
- irc_server_outqueue_send (ptr_server);
+ if (!ptr_server->is_connected)
+ continue;
- /* check for lag */
- if ((weechat_config_integer (irc_config_network_lag_check) > 0)
- && (ptr_server->lag_check_time.tv_sec == 0)
- && (current_time >= ptr_server->lag_next_check))
- {
- irc_server_sendf (ptr_server, 0, NULL, "PING %s",
- (ptr_server->current_address) ?
- ptr_server->current_address : "weechat");
- gettimeofday (&(ptr_server->lag_check_time), NULL);
- ptr_server->lag = 0;
- ptr_server->lag_last_refresh = 0;
- }
- else
+ /* send queued messages */
+ irc_server_outqueue_send (ptr_server);
+
+ /* check for lag */
+ if ((weechat_config_integer (irc_config_network_lag_check) > 0)
+ && (ptr_server->lag_check_time.tv_sec == 0)
+ && (current_time >= ptr_server->lag_next_check))
+ {
+ irc_server_sendf (ptr_server, 0, NULL, "PING %s",
+ (ptr_server->current_address) ?
+ ptr_server->current_address : "weechat");
+ gettimeofday (&(ptr_server->lag_check_time), NULL);
+ ptr_server->lag = 0;
+ ptr_server->lag_last_refresh = 0;
+ }
+ else
+ {
+ /* check away (only if lag check was not done) */
+ away_check = IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_AWAY_CHECK);
+ if (away_check > 0)
{
- /* check away (only if lag check was not done) */
- away_check = IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_AWAY_CHECK);
- if (away_check > 0)
+ if ((ptr_server->last_away_check == 0)
+ || (current_time >= ptr_server->last_away_check + (away_check * 60)))
{
- if ((ptr_server->last_away_check == 0)
- || (current_time >= ptr_server->last_away_check + (away_check * 60)))
- {
- irc_server_check_away (ptr_server);
- }
+ irc_server_check_away (ptr_server);
}
}
+ }
- /* check if it's time to autojoin channels (after command delay) */
- if ((ptr_server->command_time != 0)
- && (current_time >= ptr_server->command_time +
- IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_COMMAND_DELAY)))
+ /* check if it's time to autojoin channels (after command delay) */
+ if ((ptr_server->command_time != 0)
+ && (current_time >= ptr_server->command_time +
+ IRC_SERVER_OPTION_INTEGER(ptr_server, IRC_SERVER_OPTION_COMMAND_DELAY)))
+ {
+ irc_server_autojoin_channels (ptr_server);
+ ptr_server->command_time = 0;
+ }
+
+ /* check if it's time to send MONITOR command */
+ if ((ptr_server->monitor_time != 0)
+ && (current_time >= ptr_server->monitor_time))
+ {
+ if (ptr_server->monitor > 0)
+ irc_notify_send_monitor (ptr_server);
+ ptr_server->monitor_time = 0;
+ }
+
+ /* compute lag */
+ if (ptr_server->lag_check_time.tv_sec != 0)
+ {
+ gettimeofday (&tv, NULL);
+ ptr_server->lag = (int) weechat_util_timeval_diff (&(ptr_server->lag_check_time),
+ &tv);
+ /* refresh lag item if needed */
+ if (((ptr_server->lag_last_refresh == 0)
+ || (current_time >= ptr_server->lag_last_refresh + weechat_config_integer (irc_config_network_lag_refresh_interval)))
+ && (ptr_server->lag >= weechat_config_integer (irc_config_network_lag_min_show)))
{
- irc_server_autojoin_channels (ptr_server);
- ptr_server->command_time = 0;
+ ptr_server->lag_last_refresh = current_time;
+ weechat_bar_item_update ("lag");
}
-
- /* compute lag */
- if (ptr_server->lag_check_time.tv_sec != 0)
+ /* lag timeout? => disconnect */
+ if ((weechat_config_integer (irc_config_network_lag_reconnect) > 0)
+ && (ptr_server->lag >= weechat_config_integer (irc_config_network_lag_reconnect) * 1000))
+ {
+ weechat_printf (ptr_server->buffer,
+ _("%s%s: lag is high, reconnecting to "
+ "server %s%s%s"),
+ weechat_prefix ("network"),
+ IRC_PLUGIN_NAME,
+ IRC_COLOR_CHAT_SERVER,
+ ptr_server->name,
+ IRC_COLOR_RESET);
+ irc_server_disconnect (ptr_server, 0, 1);
+ }
+ else
{
- gettimeofday (&tv, NULL);
- ptr_server->lag = (int) weechat_util_timeval_diff (&(ptr_server->lag_check_time),
- &tv);
- /* refresh lag item if needed */
- if (((ptr_server->lag_last_refresh == 0)
- || (current_time >= ptr_server->lag_last_refresh + weechat_config_integer (irc_config_network_lag_refresh_interval)))
- && (ptr_server->lag >= weechat_config_integer (irc_config_network_lag_min_show)))
+ /* stop lag counting if max lag is reached */
+ if ((weechat_config_integer (irc_config_network_lag_max) > 0)
+ && (ptr_server->lag >= (weechat_config_integer (irc_config_network_lag_max) * 1000)))
{
+ /* refresh lag item */
ptr_server->lag_last_refresh = current_time;
weechat_bar_item_update ("lag");
- }
- /* lag timeout? => disconnect */
- if ((weechat_config_integer (irc_config_network_lag_reconnect) > 0)
- && (ptr_server->lag >= weechat_config_integer (irc_config_network_lag_reconnect) * 1000))
- {
- weechat_printf (ptr_server->buffer,
- _("%s%s: lag is high, reconnecting to "
- "server %s%s%s"),
- weechat_prefix ("network"),
- IRC_PLUGIN_NAME,
- IRC_COLOR_CHAT_SERVER,
- ptr_server->name,
- IRC_COLOR_RESET);
- irc_server_disconnect (ptr_server, 0, 1);
- }
- else
- {
- /* stop lag counting if max lag is reached */
- if ((weechat_config_integer (irc_config_network_lag_max) > 0)
- && (ptr_server->lag >= (weechat_config_integer (irc_config_network_lag_max) * 1000)))
- {
- /* refresh lag item */
- ptr_server->lag_last_refresh = current_time;
- weechat_bar_item_update ("lag");
-
- /* schedule next lag check in 5 seconds */
- ptr_server->lag_check_time.tv_sec = 0;
- ptr_server->lag_check_time.tv_usec = 0;
- ptr_server->lag_next_check = time (NULL) +
- weechat_config_integer (irc_config_network_lag_check);
- }
+
+ /* schedule next lag check in 5 seconds */
+ ptr_server->lag_check_time.tv_sec = 0;
+ ptr_server->lag_check_time.tv_usec = 0;
+ ptr_server->lag_next_check = time (NULL) +
+ weechat_config_integer (irc_config_network_lag_check);
}
}
+ }
- /* remove redirects if timeout occurs */
- ptr_redirect = ptr_server->redirects;
- while (ptr_redirect)
- {
- ptr_next_redirect = ptr_redirect->next_redirect;
-
- if ((ptr_redirect->start_time > 0)
- && (ptr_redirect->start_time + ptr_redirect->timeout < current_time))
- {
- irc_redirect_stop (ptr_redirect, "timeout");
- }
+ /* remove redirects if timeout occurs */
+ ptr_redirect = ptr_server->redirects;
+ while (ptr_redirect)
+ {
+ ptr_next_redirect = ptr_redirect->next_redirect;
- ptr_redirect = ptr_next_redirect;
+ if ((ptr_redirect->start_time > 0)
+ && (ptr_redirect->start_time + ptr_redirect->timeout < current_time))
+ {
+ irc_redirect_stop (ptr_redirect, "timeout");
}
- /* purge some data (every 10 minutes) */
- if (current_time > ptr_server->last_data_purge + (60 * 10))
+ ptr_redirect = ptr_next_redirect;
+ }
+
+ /* purge some data (every 10 minutes) */
+ if (current_time > ptr_server->last_data_purge + (60 * 10))
+ {
+ weechat_hashtable_map (ptr_server->join_manual,
+ &irc_server_check_join_manual_cb,
+ NULL);
+ weechat_hashtable_map (ptr_server->join_noswitch,
+ &irc_server_check_join_noswitch_cb,
+ NULL);
+ for (ptr_channel = ptr_server->channels; ptr_channel;
+ ptr_channel = ptr_channel->next_channel)
{
- weechat_hashtable_map (ptr_server->join_manual,
- &irc_server_check_join_manual_cb,
- NULL);
- weechat_hashtable_map (ptr_server->join_noswitch,
- &irc_server_check_join_noswitch_cb,
- NULL);
- for (ptr_channel = ptr_server->channels; ptr_channel;
- ptr_channel = ptr_channel->next_channel)
+ if (ptr_channel->join_smart_filtered)
{
- if (ptr_channel->join_smart_filtered)
- {
- weechat_hashtable_map (ptr_channel->join_smart_filtered,
- &irc_server_check_join_smart_filtered_cb,
- NULL);
- }
+ weechat_hashtable_map (ptr_channel->join_smart_filtered,
+ &irc_server_check_join_smart_filtered_cb,
+ NULL);
}
- ptr_server->last_data_purge = current_time;
}
+ ptr_server->last_data_purge = current_time;
}
}
}
@@ -4251,7 +4263,7 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address,
if (switch_address)
irc_server_switch_address (server, 0);
else
- irc_server_set_index_current_address(server, 0);
+ irc_server_set_index_current_address (server, 0);
if (server->nick_modes)
{
@@ -4267,6 +4279,8 @@ irc_server_disconnect (struct t_irc_server *server, int switch_address,
server->lag_next_check = time (NULL) +
weechat_config_integer (irc_config_network_lag_check);
server->lag_last_refresh = 0;
+ server->monitor = 0;
+ server->monitor_time = 0;
if (reconnect
&& IRC_SERVER_OPTION_BOOLEAN(server, IRC_SERVER_OPTION_AUTORECONNECT))
@@ -4789,6 +4803,8 @@ irc_server_hdata_server_cb (void *data, const char *hdata_name)
WEECHAT_HDATA_VAR(struct t_irc_server, casemapping, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, chantypes, STRING, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, chanmodes, STRING, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, monitor, INTEGER, 0, NULL, NULL);
+ WEECHAT_HDATA_VAR(struct t_irc_server, monitor_time, TIME, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, reconnect_delay, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, reconnect_start, TIME, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, command_time, TIME, 0, NULL, NULL);
@@ -4811,6 +4827,7 @@ irc_server_hdata_server_cb (void *data, const char *hdata_name)
WEECHAT_HDATA_VAR(struct t_irc_server, last_redirect, POINTER, 0, NULL, "irc_redirect");
WEECHAT_HDATA_VAR(struct t_irc_server, notify_list, POINTER, 0, NULL, "irc_notify");
WEECHAT_HDATA_VAR(struct t_irc_server, last_notify, POINTER, 0, NULL, "irc_notify");
+ WEECHAT_HDATA_VAR(struct t_irc_server, notify_count, INTEGER, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, join_manual, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, join_channel_key, HASHTABLE, 0, NULL, NULL);
WEECHAT_HDATA_VAR(struct t_irc_server, join_noswitch, HASHTABLE, 0, NULL, NULL);
@@ -5003,6 +5020,10 @@ irc_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "chanmodes", server->chanmodes))
return 0;
+ if (!weechat_infolist_new_var_integer (ptr_item, "monitor", server->monitor))
+ return 0;
+ if (!weechat_infolist_new_var_time (ptr_item, "monitor_time", server->monitor_time))
+ return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "reconnect_delay", server->reconnect_delay))
return 0;
if (!weechat_infolist_new_var_time (ptr_item, "reconnect_start", server->reconnect_start))
@@ -5337,6 +5358,8 @@ irc_server_print_log ()
irc_server_casemapping_string[ptr_server->casemapping]);
weechat_log_printf (" chantypes. . . . . . : '%s'", ptr_server->chantypes);
weechat_log_printf (" chanmodes. . . . . . : '%s'", ptr_server->chanmodes);
+ weechat_log_printf (" monitor. . . . . . . : %d", ptr_server->monitor);
+ weechat_log_printf (" monitor_time . . . . : %ld", ptr_server->monitor_time);
weechat_log_printf (" reconnect_delay. . . : %d", ptr_server->reconnect_delay);
weechat_log_printf (" reconnect_start. . . : %ld", ptr_server->reconnect_start);
weechat_log_printf (" command_time . . . . : %ld", ptr_server->command_time);
@@ -5364,6 +5387,7 @@ irc_server_print_log ()
weechat_log_printf (" last_redirect. . . . : 0x%lx", ptr_server->last_redirect);
weechat_log_printf (" notify_list. . . . . : 0x%lx", ptr_server->notify_list);
weechat_log_printf (" last_notify. . . . . : 0x%lx", ptr_server->last_notify);
+ weechat_log_printf (" notify_count . . . . : %d", ptr_server->notify_count);
weechat_log_printf (" join_manual. . . . . : 0x%lx (hashtable: '%s')",
ptr_server->join_manual,
weechat_hashtable_get_string (ptr_server->join_manual, "keys_values"));
diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h
index efcf094c6..6b4a9d9fb 100644
--- a/src/plugins/irc/irc-server.h
+++ b/src/plugins/irc/irc-server.h
@@ -181,6 +181,8 @@ struct t_irc_server
char *chantypes; /* chantypes from msg 005 (eg "&#") */
char *chanmodes; /* chanmodes from msg 005 */
/* (eg "beI,k,l,imnpstaqr") */
+ int monitor; /* monitor limit from msg 005 (eg 100) */
+ time_t monitor_time; /* time for monitoring nicks (on connect)*/
int reconnect_delay; /* current reconnect delay (growing) */
time_t reconnect_start; /* this time + delay = reconnect time */
time_t command_time; /* this time + command_delay = time to */
@@ -205,6 +207,7 @@ struct t_irc_server
struct t_irc_redirect *last_redirect; /* last command redirection */
struct t_irc_notify *notify_list; /* list of notify */
struct t_irc_notify *last_notify; /* last notify */
+ int notify_count; /* number of notify in list */
struct t_hashtable *join_manual; /* manual joins pending */
struct t_hashtable *join_channel_key; /* keys pending for joins */
struct t_hashtable *join_noswitch; /* joins w/o switch to buffer */
diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c
index f56fd7d5e..dfc76d718 100644
--- a/src/plugins/irc/irc-upgrade.c
+++ b/src/plugins/irc/irc-upgrade.c
@@ -403,6 +403,24 @@ irc_upgrade_read_cb (void *data,
if (str)
irc_upgrade_current_server->chanmodes = strdup (str);
}
+ /* "monitor" is new in WeeChat 0.4.3 */
+ if (weechat_infolist_search_var (infolist, "monitor"))
+ {
+ irc_upgrade_current_server->monitor = weechat_infolist_integer (infolist, "monitor");
+ }
+ else
+ {
+ /* WeeChat <= 0.4.2 */
+ str = irc_server_get_isupport_value (irc_upgrade_current_server,
+ "MONITOR");
+ if (str)
+ {
+ error = NULL;
+ number = strtol (str, &error, 10);
+ if (error && !error[0])
+ irc_upgrade_current_server->monitor = (int)number;
+ }
+ }
irc_upgrade_current_server->reconnect_delay = weechat_infolist_integer (infolist, "reconnect_delay");
irc_upgrade_current_server->reconnect_start = weechat_infolist_time (infolist, "reconnect_start");
irc_upgrade_current_server->command_time = weechat_infolist_time (infolist, "command_time");