diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2014-01-23 11:31:57 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2014-01-23 11:31:57 +0100 |
commit | 3acdcee0d94feaf2845c3e74d323f8c5dd01d70a (patch) | |
tree | 1aca3f34fb571b74b4190ef8d188c4b140ca2640 /src/plugins | |
parent | 6d4bc94536e162f40a0e5ec5d9db21f6cde85863 (diff) | |
download | weechat-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.c | 26 | ||||
-rw-r--r-- | src/plugins/irc/irc-message.c | 43 | ||||
-rw-r--r-- | src/plugins/irc/irc-notify.c | 249 | ||||
-rw-r--r-- | src/plugins/irc/irc-notify.h | 5 | ||||
-rw-r--r-- | src/plugins/irc/irc-protocol.c | 189 | ||||
-rw-r--r-- | src/plugins/irc/irc-redirect.c | 11 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 228 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 3 | ||||
-rw-r--r-- | src/plugins/irc/irc-upgrade.c | 18 |
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"); |