diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2010-11-06 11:38:48 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2010-11-06 11:38:48 +0100 |
commit | e001c057108a573d9e67cc37c0c5f8462e1fbdf6 (patch) | |
tree | d5e153942e4c8b08a870ee49325e3d953f887770 /src/plugins/irc | |
parent | a56dc00b2f7a01ee3c52fcb49bea2638c877d1ff (diff) | |
download | weechat-e001c057108a573d9e67cc37c0c5f8462e1fbdf6.zip |
Add IRC command /notify, new options for notify and infolist "irc_notify" (task #5441)
This commit provides:
- new IRC command /notify
- new options: irc.look.notify_tags_ison, irc.look.notify_tags_whois,
irc.network.notify_check_ison, irc.network.notify_check_whois
- new option "notify" in servers (but should not be changed, only /notify
command should be used)
- infolist "irc_notify" to get notify list (by server or for all servers).
Diffstat (limited to 'src/plugins/irc')
-rw-r--r-- | src/plugins/irc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/irc/Makefile.am | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc-command.c | 232 | ||||
-rw-r--r-- | src/plugins/irc/irc-completion.c | 52 | ||||
-rw-r--r-- | src/plugins/irc/irc-config.c | 154 | ||||
-rw-r--r-- | src/plugins/irc/irc-config.h | 8 | ||||
-rw-r--r-- | src/plugins/irc/irc-ignore.c | 10 | ||||
-rw-r--r-- | src/plugins/irc/irc-ignore.h | 4 | ||||
-rw-r--r-- | src/plugins/irc/irc-info.c | 50 | ||||
-rw-r--r-- | src/plugins/irc/irc-notify.c | 927 | ||||
-rw-r--r-- | src/plugins/irc/irc-notify.h | 66 | ||||
-rw-r--r-- | src/plugins/irc/irc-redirect.h | 7 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 10 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 6 | ||||
-rw-r--r-- | src/plugins/irc/irc-upgrade.c | 42 | ||||
-rw-r--r-- | src/plugins/irc/irc-upgrade.h | 1 | ||||
-rw-r--r-- | src/plugins/irc/irc.c | 9 |
17 files changed, 1536 insertions, 45 deletions
diff --git a/src/plugins/irc/CMakeLists.txt b/src/plugins/irc/CMakeLists.txt index 93ccf9cca..98e21d45d 100644 --- a/src/plugins/irc/CMakeLists.txt +++ b/src/plugins/irc/CMakeLists.txt @@ -35,6 +35,7 @@ irc-input.c irc-input.h irc-mode.c irc-mode.h irc-msgbuffer.c irc-msgbuffer.h irc-nick.c irc-nick.h +irc-notify.c irc-notify.h irc-protocol.c irc-protocol.h irc-raw.c irc-raw.h irc-redirect.c irc-redirect.h diff --git a/src/plugins/irc/Makefile.am b/src/plugins/irc/Makefile.am index 105c7eeb8..bd287713c 100644 --- a/src/plugins/irc/Makefile.am +++ b/src/plugins/irc/Makefile.am @@ -57,6 +57,8 @@ irc_la_SOURCES = irc.c \ irc-msgbuffer.h \ irc-nick.c \ irc-nick.h \ + irc-notify.c \ + irc-notify.h \ irc-protocol.c \ irc-protocol.h \ irc-raw.c \ diff --git a/src/plugins/irc/irc-command.c b/src/plugins/irc/irc-command.c index fa021f3b8..b982d55dc 100644 --- a/src/plugins/irc/irc-command.c +++ b/src/plugins/irc/irc-command.c @@ -36,16 +36,17 @@ #include "irc.h" #include "irc-command.h" #include "irc-buffer.h" +#include "irc-channel.h" #include "irc-color.h" #include "irc-config.h" -#include "irc-input.h" -#include "irc-server.h" -#include "irc-channel.h" -#include "irc-nick.h" #include "irc-display.h" #include "irc-ignore.h" +#include "irc-input.h" +#include "irc-nick.h" +#include "irc-notify.h" #include "irc-protocol.h" #include "irc-raw.h" +#include "irc-server.h" /* @@ -1436,7 +1437,7 @@ irc_command_halfop (void *data, struct t_gui_buffer *buffer, int argc, } /* - * irc_command_ignore_display: display a ignore + * irc_command_ignore_display: display an ignore */ void @@ -1454,10 +1455,8 @@ irc_command_ignore_display (struct t_irc_ignore *ignore) IRC_COLOR_CHAT_DELIMITERS, IRC_COLOR_CHAT, (mask) ? mask : ignore->mask, - (ignore->server) ? - ignore->server : "*", - (ignore->channel) ? - ignore->channel : "*"); + (ignore->server) ? ignore->server : "*", + (ignore->channel) ? ignore->channel : "*"); if (mask) free (mask); @@ -1483,7 +1482,7 @@ irc_command_ignore (void *data, struct t_gui_buffer *buffer, int argc, if ((argc == 1) || ((argc == 2) && (weechat_strcasecmp (argv[1], "list") == 0))) { - /* display all key bindings */ + /* display all ignores */ if (irc_ignore_list) { weechat_printf (NULL, ""); @@ -2623,6 +2622,184 @@ irc_command_notice (void *data, struct t_gui_buffer *buffer, int argc, } /* + * irc_command_notify: add or remove notify + */ + +int +irc_command_notify (void *data, struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + struct t_irc_notify *ptr_notify; + int i, check_away; + + IRC_BUFFER_GET_SERVER(buffer); + + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) argv_eol; + + /* display notify status for users on server */ + if (argc == 1) + { + irc_notify_display_list (ptr_server); + return WEECHAT_RC_OK; + } + + /* add notify */ + if (weechat_strcasecmp (argv[1], "add") == 0) + { + if (argc < 3) + { + weechat_printf (NULL, + _("%s%s: missing arguments for \"%s\" " + "command"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + "notify add"); + return WEECHAT_RC_OK; + } + + check_away = 0; + + if (argc > 3) + { + ptr_server = irc_server_search (argv[3]); + if (!ptr_server) + { + weechat_printf (NULL, + _("%s%s: server \"%s\" not found"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + argv[3]); + return WEECHAT_RC_OK; + } + } + + if (!ptr_server) + { + weechat_printf (NULL, + _("%s%s: server must be specified because you are " + "not on an irc server or channel"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (argc > 4) + { + for (i = 4; i < argc; i++) + { + if (weechat_strcasecmp (argv[i], "-away") == 0) + check_away = 1; + } + } + + ptr_notify = irc_notify_search (ptr_server, argv[2]); + if (ptr_notify) + { + weechat_printf (NULL, + _("%s%s: notify already exists"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + 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"), + IRC_PLUGIN_NAME, + IRC_COLOR_CHAT_NICK, + ptr_notify->nick); + } + else + { + weechat_printf (NULL, _("%s%s: error adding notification"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + } + + return WEECHAT_RC_OK; + } + + /* delete notify */ + if (weechat_strcasecmp (argv[1], "del") == 0) + { + if (argc < 3) + { + weechat_printf (NULL, + _("%s%s: missing arguments for \"%s\" " + "command"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + "notify del"); + return WEECHAT_RC_OK; + } + + if (argc > 3) + { + ptr_server = irc_server_search (argv[3]); + if (!ptr_server) + { + weechat_printf (NULL, + _("%s%s: server \"%s\" not found"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, + argv[3]); + return WEECHAT_RC_OK; + } + } + + if (!ptr_server) + { + weechat_printf (NULL, + _("%s%s: server must be specified because you are " + "not on an irc server or channel"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[2], "-all") == 0) + { + if (ptr_server->notify_list) + { + irc_notify_free_all (ptr_server); + irc_notify_set_server_option (ptr_server); + weechat_printf (NULL, _("%s: all notifications deleted"), + IRC_PLUGIN_NAME); + } + else + { + weechat_printf (NULL, _("%s: no notification in list"), + IRC_PLUGIN_NAME); + } + } + else + { + ptr_notify = irc_notify_search (ptr_server, argv[2]); + if (ptr_notify) + { + irc_notify_free (ptr_server, ptr_notify); + irc_notify_set_server_option (ptr_server); + weechat_printf (NULL, _("%s: notification deleted"), + IRC_PLUGIN_NAME); + } + else + { + weechat_printf (NULL, + _("%s%s: notification not found"), + weechat_prefix ("error"), IRC_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + } + + return WEECHAT_RC_OK; + } + + weechat_printf (NULL, + _("%s%s: unknown option for \"%s\" " + "command"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, "notify"); + return WEECHAT_RC_OK; +} + +/* * irc_command_op: give operator privileges to nickname(s) */ @@ -4502,8 +4679,8 @@ irc_command_init () N_("[list] | [add [re:]nick/host [server [channel]]] | " "[del number|-all]"), N_(" list: list all ignores\n" - " add: add a ignore\n" - " del: del a ignore\n" + " add: add an ignore\n" + " del: delete an ignore\n" " number: number of ignore to delete (look at " "list to find it)\n" " -all: delete all ignores\n" @@ -4686,6 +4863,37 @@ irc_command_init () "nickname: user to send notice to\n" " text: text to send"), "%(nicks) %-", &irc_command_notice, NULL); + weechat_hook_command ("notify", + N_("add a notification for presence or away status " + "of nicks on servers"), + N_("[add nick [server [-away]]] | " + "[del nick|-all [server]]"), + N_(" add: add a notification\n" + " nick: nickname\n" + "server: internal server name (by default " + "current server)\n" + " -away: notify when away message is changed " + "(by doing whois on nick)\n" + " del: delete a notification\n" + " -all: delete all notifications\n\n" + "Without argument, this command displays " + "notifications for current server (or all servers " + "if command is issued on core buffer).\n\n" + "Examples:\n" + " notify when \"toto\" joins/quits current " + "server:\n" + " /notify add toto\n" + " notify when \"toto\" joins/quits freenode " + "server:\n" + " /notify add toto freenode\n" + " notify when \"toto\" is away or back on " + "freenode server:\n" + " /notify add toto freenode -away"), + "list" + " || add %(irc_channel_nicks) %(irc_servers) " + "-away %-" + " || del -all|%(irc_notify_nicks) %(irc_servers) %-", + &irc_command_notify, NULL); weechat_hook_command ("op", N_("give channel operator status to nickname(s)"), N_("nickname [nickname]"), diff --git a/src/plugins/irc/irc-completion.c b/src/plugins/irc/irc-completion.c index 393d9f7e9..5699afc3c 100644 --- a/src/plugins/irc/irc-completion.c +++ b/src/plugins/irc/irc-completion.c @@ -28,13 +28,14 @@ #include "../weechat-plugin.h" #include "irc.h" #include "irc-buffer.h" +#include "irc-channel.h" #include "irc-color.h" #include "irc-completion.h" #include "irc-config.h" #include "irc-ignore.h" -#include "irc-server.h" -#include "irc-channel.h" #include "irc-nick.h" +#include "irc-notify.h" +#include "irc-server.h" /* @@ -566,6 +567,50 @@ irc_completion_ignores_numbers_cb (void *data, const char *completion_item, } /* + * irc_completion_notify_nicks_cb: callback for completion with nicks in notify + * list + */ + +int +irc_completion_notify_nicks_cb (void *data, const char *completion_item, + struct t_gui_buffer *buffer, + struct t_gui_completion *completion) +{ + struct t_irc_notify *ptr_notify; + + IRC_BUFFER_GET_SERVER(buffer); + + /* make C compiler happy */ + (void) data; + (void) completion_item; + + if (ptr_server) + { + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + weechat_hook_completion_list_add (completion, ptr_notify->nick, + 0, WEECHAT_LIST_POS_SORT); + } + } + else + { + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + weechat_hook_completion_list_add (completion, ptr_notify->nick, + 0, WEECHAT_LIST_POS_SORT); + } + } + } + + return WEECHAT_RC_OK; +} + +/* * irc_completion_init: init completion for IRC plugin */ @@ -614,4 +659,7 @@ irc_completion_init () weechat_hook_completion ("irc_ignores_numbers", N_("numbers for defined ignores"), &irc_completion_ignores_numbers_cb, NULL); + weechat_hook_completion ("irc_notify_nicks", + N_("nicks in notify list"), + &irc_completion_notify_nicks_cb, NULL); } diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 00b5f9b12..d1ab51552 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -32,13 +32,14 @@ #include "../weechat-plugin.h" #include "irc.h" #include "irc-config.h" -#include "irc-ctcp.h" #include "irc-buffer.h" +#include "irc-channel.h" +#include "irc-ctcp.h" #include "irc-ignore.h" #include "irc-msgbuffer.h" #include "irc-nick.h" +#include "irc-notify.h" #include "irc-server.h" -#include "irc-channel.h" struct t_config_file *irc_config_file = NULL; @@ -79,6 +80,8 @@ struct t_config_option *irc_config_look_highlight_tags; struct t_config_option *irc_config_look_item_display_server; struct t_config_option *irc_config_look_msgbuffer_fallback; struct t_config_option *irc_config_look_notice_as_pv; +struct t_config_option *irc_config_look_notify_tags_ison; +struct t_config_option *irc_config_look_notify_tags_whois; struct t_config_option *irc_config_look_part_closes_buffer; struct t_config_option *irc_config_look_raw_messages; struct t_config_option *irc_config_look_smart_filter; @@ -109,12 +112,14 @@ struct t_config_option *irc_config_color_reason_quit; struct t_config_option *irc_config_network_autoreconnect_delay_growing; struct t_config_option *irc_config_network_autoreconnect_delay_max; +struct t_config_option *irc_config_network_colors_receive; +struct t_config_option *irc_config_network_colors_send; struct t_config_option *irc_config_network_lag_check; struct t_config_option *irc_config_network_lag_min_show; struct t_config_option *irc_config_network_lag_disconnect; struct t_config_option *irc_config_network_lag_refresh_interval; -struct t_config_option *irc_config_network_colors_receive; -struct t_config_option *irc_config_network_colors_send; +struct t_config_option *irc_config_network_notify_check_ison; +struct t_config_option *irc_config_network_notify_check_whois; struct t_config_option *irc_config_network_send_unknown_commands; /* IRC config, server section */ @@ -587,6 +592,38 @@ irc_config_change_network_lag_min_show (void *data, } /* + * irc_config_change_network_notify_check_ison: called when notify check ison + * is changed + */ + +void +irc_config_change_network_notify_check_ison (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + irc_notify_hook_timer_ison (); +} + +/* + * irc_config_change_network_notify_check_whois: called when notify check whois + * is changed + */ + +void +irc_config_change_network_notify_check_whois (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + irc_notify_hook_timer_whois (); +} + +/* * irc_config_change_network_send_unknown_commands: called when "send_unknown_commands" * is changed */ @@ -715,12 +752,39 @@ irc_config_server_change_cb (void *data, struct t_config_option *option) irc_server_check_away (ptr_server); else irc_server_remove_away (ptr_server); + break; + case IRC_SERVER_OPTION_NOTIFY: + irc_notify_new_for_server (ptr_server); + break; } } } } /* + * irc_config_server_default_check_notify: calback called when "notify" option + * from "server_default" section is + * changed: return 0 if a value is set + * This option is not used, only values + * in servers are used for notify. + */ + +int +irc_config_server_default_check_notify (void *data, + struct t_config_option *option, + const char *value) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (value && value[0]) + return 0; + + return 1; +} + +/* * irc_config_reload: reload IRC configuration file */ @@ -1436,6 +1500,21 @@ irc_config_server_new_option (struct t_config_file *config_file, callback_change, callback_change_data, NULL, NULL); break; + case IRC_SERVER_OPTION_NOTIFY: + new_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + N_("notify list for server (you should not change this option " + "but use /notify command instead)"), + NULL, 0, 0, + default_value, value, + null_value_allowed, + (section == irc_config_section_server_default) ? + &irc_config_server_default_check_notify : NULL, + NULL, + callback_change, callback_change_data, + NULL, NULL); + break; case IRC_SERVER_NUM_OPTIONS: break; } @@ -1855,6 +1934,24 @@ irc_config_init () N_("display notices as private messages (if auto, use private buffer " "if found)"), "auto|never|always", 0, 0, "auto", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + irc_config_look_notify_tags_ison = weechat_config_new_option ( + irc_config_file, ptr_section, + "notify_tags_ison", "string", + N_("comma separated list of tags used in messages printed by notify " + "when a nick joins or quits server (result of command ison), " + "for example: \"notify_highglight\", \"notify_message\" or " + "\"notify_private\""), + NULL, 0, 0, "notify_message", NULL, 0, NULL, NULL, + NULL, NULL, NULL, NULL); + irc_config_look_notify_tags_whois = weechat_config_new_option ( + irc_config_file, ptr_section, + "notify_tags_whois", "string", + N_("comma separated list of tags used in messages printed by notify " + "when a nick away status changes (result of command whois), " + "for example: \"notify_highglight\", \"notify_message\" or " + "\"notify_private\""), + NULL, 0, 0, "notify_message", NULL, 0, NULL, NULL, + NULL, NULL, NULL, NULL); irc_config_look_part_closes_buffer = weechat_config_new_option ( irc_config_file, ptr_section, "part_closes_buffer", "boolean", @@ -2026,6 +2123,18 @@ irc_config_init () N_("maximum autoreconnect delay to server (in seconds, 0 = no maximum)"), NULL, 0, 3600 * 24, "1800", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + irc_config_network_colors_receive = weechat_config_new_option ( + irc_config_file, ptr_section, + "colors_receive", "boolean", + N_("when off, colors codes are ignored in incoming messages"), + NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + irc_config_network_colors_send = weechat_config_new_option ( + irc_config_file, ptr_section, + "colors_send", "boolean", + N_("allow user to send colors with special codes (ctrl-c + a code and " + "optional color: b=bold, cxx=color, cxx,yy=color+background, " + "u=underline, r=reverse)"), + NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); irc_config_network_lag_check = weechat_config_new_option ( irc_config_file, ptr_section, "lag_check", "integer", @@ -2051,24 +2160,26 @@ irc_config_init () N_("interval between two refreshs of lag item, when lag is increasing " "(in seconds)"), NULL, 1, 3600, "1", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); - irc_config_network_colors_receive = weechat_config_new_option ( - irc_config_file, ptr_section, - "colors_receive", "boolean", - N_("when off, colors codes are ignored in incoming messages"), - NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); - irc_config_network_colors_send = weechat_config_new_option ( - irc_config_file, ptr_section, - "colors_send", "boolean", - N_("allow user to send colors with special codes (ctrl-c + a code and " - "optional color: b=bold, cxx=color, cxx,yy=color+background, " - "u=underline, r=reverse)"), - NULL, 0, 0, "on", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); irc_config_network_send_unknown_commands = weechat_config_new_option ( irc_config_file, ptr_section, "send_unknown_commands", "boolean", N_("send unknown commands to server"), NULL, 0, 0, "off", NULL, 0, NULL, NULL, &irc_config_change_network_send_unknown_commands, NULL, NULL, NULL); + irc_config_network_notify_check_ison = weechat_config_new_option ( + irc_config_file, ptr_section, + "notify_check_ison", "integer", + N_("interval between two checks for notify with IRC command \"ison\" " + "(in minutes)"), + NULL, 1, 60 * 24 * 7, "1", NULL, 0, NULL, NULL, + &irc_config_change_network_notify_check_ison, NULL, NULL, NULL); + irc_config_network_notify_check_whois = weechat_config_new_option ( + irc_config_file, ptr_section, + "notify_check_whois", "integer", + N_("interval between two checks for notify with IRC command \"whois\" " + "(in minutes)"), + NULL, 1, 60 * 24 * 7, "5", NULL, 0, NULL, NULL, + &irc_config_change_network_notify_check_whois, NULL, NULL, NULL); /* msgbuffer */ ptr_section = weechat_config_new_section (irc_config_file, "msgbuffer", @@ -2154,7 +2265,16 @@ irc_config_init () int irc_config_read () { - return weechat_config_read (irc_config_file); + int rc; + + rc = weechat_config_read (irc_config_file); + if (rc == WEECHAT_CONFIG_READ_OK) + { + irc_notify_new_for_all_servers (); + irc_config_change_network_notify_check_ison (NULL, NULL); + irc_config_change_network_notify_check_whois (NULL, NULL); + } + return rc; } /* diff --git a/src/plugins/irc/irc-config.h b/src/plugins/irc/irc-config.h index 043a56129..aed25367e 100644 --- a/src/plugins/irc/irc-config.h +++ b/src/plugins/irc/irc-config.h @@ -105,6 +105,8 @@ extern struct t_config_option *irc_config_look_highlight_tags; extern struct t_config_option *irc_config_look_item_display_server; extern struct t_config_option *irc_config_look_msgbuffer_fallback; extern struct t_config_option *irc_config_look_notice_as_pv; +extern struct t_config_option *irc_config_look_notify_tags_ison; +extern struct t_config_option *irc_config_look_notify_tags_whois; extern struct t_config_option *irc_config_look_part_closes_buffer; extern struct t_config_option *irc_config_look_raw_messages; extern struct t_config_option *irc_config_look_smart_filter; @@ -131,12 +133,14 @@ extern struct t_config_option *irc_config_color_reason_quit; extern struct t_config_option *irc_config_network_autoreconnect_delay_growing; extern struct t_config_option *irc_config_network_autoreconnect_delay_max; +extern struct t_config_option *irc_config_network_colors_receive; +extern struct t_config_option *irc_config_network_colors_send; extern struct t_config_option *irc_config_network_lag_check; extern struct t_config_option *irc_config_network_lag_min_show; extern struct t_config_option *irc_config_network_lag_disconnect; extern struct t_config_option *irc_config_network_lag_refresh_interval; -extern struct t_config_option *irc_config_network_colors_receive; -extern struct t_config_option *irc_config_network_colors_send; +extern struct t_config_option *irc_config_network_notify_check_ison; +extern struct t_config_option *irc_config_network_notify_check_whois; extern struct t_config_option *irc_config_network_send_unknown_commands; extern struct t_config_option *irc_config_server_default[]; diff --git a/src/plugins/irc/irc-ignore.c b/src/plugins/irc/irc-ignore.c index aaba11509..c67fd68a2 100644 --- a/src/plugins/irc/irc-ignore.c +++ b/src/plugins/irc/irc-ignore.c @@ -36,7 +36,7 @@ struct t_irc_ignore *last_irc_ignore = NULL; /* last ignore in list */ /* - * irc_ignore_valid: check if a ignore pointer exists + * irc_ignore_valid: check if an ignore pointer exists * return 1 if ignore exists * 0 if ignore is not found */ @@ -61,7 +61,7 @@ irc_ignore_valid (struct t_irc_ignore *ignore) } /* - * irc_ignore_search: search a ignore + * irc_ignore_search: search an ignore */ struct t_irc_ignore * @@ -91,7 +91,7 @@ irc_ignore_search (const char *mask, const char *server, const char *channel) } /* - * irc_ignore_search_by_number: search a ignore by number (first is #1) + * irc_ignore_search_by_number: search an ignore by number (first is #1) */ struct t_irc_ignore * @@ -241,7 +241,7 @@ irc_ignore_check (struct t_irc_server *server, const char *channel, } /* - * irc_ignore_free: remove a ignore + * irc_ignore_free: remove an ignore */ void @@ -302,7 +302,7 @@ irc_ignore_free_all () } /* - * irc_ignore_add_to_infolist: add a ignore in an infolist + * irc_ignore_add_to_infolist: add an ignore in an infolist * return 1 if ok, 0 if error */ diff --git a/src/plugins/irc/irc-ignore.h b/src/plugins/irc/irc-ignore.h index 71b1a6cb5..e3c4b9c8a 100644 --- a/src/plugins/irc/irc-ignore.h +++ b/src/plugins/irc/irc-ignore.h @@ -30,8 +30,8 @@ struct t_irc_ignore int number; /* ignore number */ char *mask; /* nick / host mask */ regex_t *regex_mask; /* regex for mask */ - char *server; /* server name */ - char *channel; /* channel name */ + char *server; /* server name ("*" == any server) */ + char *channel; /* channel name ("*" == any channel) */ struct t_irc_ignore *prev_ignore; /* link to previous ignore */ struct t_irc_ignore *next_ignore; /* link to next ignore */ }; diff --git a/src/plugins/irc/irc-info.c b/src/plugins/irc/irc-info.c index 5d9562f34..8fb518b4b 100644 --- a/src/plugins/irc/irc-info.c +++ b/src/plugins/irc/irc-info.c @@ -31,6 +31,7 @@ #include "irc-config.h" #include "irc-ignore.h" #include "irc-nick.h" +#include "irc-notify.h" #include "irc-protocol.h" #include "irc-server.h" @@ -273,6 +274,7 @@ irc_info_get_infolist_cb (void *data, const char *infolist_name, struct t_irc_channel *ptr_channel; struct t_irc_nick *ptr_nick; struct t_irc_ignore *ptr_ignore; + struct t_irc_notify *ptr_notify; char **argv; int argc; @@ -495,6 +497,49 @@ irc_info_get_infolist_cb (void *data, const char *infolist_name, } } } + else if (weechat_strcasecmp (infolist_name, "irc_notify") == 0) + { + if (pointer && !irc_notify_valid (NULL, pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (ptr_infolist) + { + if (pointer) + { + /* build list with only one notify */ + if (!irc_notify_add_to_infolist (ptr_infolist, pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with notify list of all servers matchin arguments */ + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + if (!arguments || !arguments[0] + || weechat_string_match (ptr_server->name, arguments, 0)) + { + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (!irc_notify_add_to_infolist (ptr_infolist, + ptr_notify)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + } + } + return ptr_infolist; + } + } + } return NULL; } @@ -575,4 +620,9 @@ irc_info_init () N_("ignore pointer (optional)"), NULL, &irc_info_get_infolist_cb, NULL); + weechat_hook_infolist ("irc_notify", + N_("list of notify"), + N_("notify pointer (optional)"), + N_("server name (can start or end with \"*\" as wildcard) (optional)"), + &irc_info_get_infolist_cb, NULL); } diff --git a/src/plugins/irc/irc-notify.c b/src/plugins/irc/irc-notify.c new file mode 100644 index 000000000..97947bfed --- /dev/null +++ b/src/plugins/irc/irc-notify.c @@ -0,0 +1,927 @@ +/* + * Copyright (C) 2010 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +/* + * irc-notify.c: notify lists for IRC plugin + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../weechat-plugin.h" +#include "irc.h" +#include "irc-notify.h" +#include "irc-color.h" +#include "irc-config.h" +#include "irc-redirect.h" +#include "irc-server.h" + + +/* timers to run "ison" and "whois" commands */ +struct t_hook *irc_notify_timer_ison = NULL; /* timer for "ison" */ +struct t_hook *irc_notify_timer_whois = NULL; /* timer for "whois" */ + +/* hsignal for redirected commands */ +struct t_hook *irc_notify_hsignal = NULL; + + +/* + * irc_notify_valid: check if a notify pointer exists for a server + * if server is NULL, search in all servers + * return 1 if notify exists + * 0 if notify is not found + */ + +int +irc_notify_valid (struct t_irc_server *server, struct t_irc_notify *notify) +{ + struct t_irc_server *ptr_server; + struct t_irc_notify *ptr_notify; + + if (!notify) + return 0; + + if (server) + { + for (ptr_notify = server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (ptr_notify == notify) + return 1; + } + } + else + { + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (ptr_notify == notify) + return 1; + } + } + } + + /* notify not found */ + return 0; +} + +/* + * irc_notify_search: search a notify + */ + +struct t_irc_notify * +irc_notify_search (struct t_irc_server *server, const char *nick) +{ + struct t_irc_notify *ptr_notify; + + if (!server || !nick) + return NULL; + + for (ptr_notify = server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (strcmp (ptr_notify->nick, nick) == 0) + return ptr_notify; + } + + /* notify not found */ + return NULL; +} + +/* + * irc_notify_set_server_option: set server option "notify" with notify + * list on server + */ + +void +irc_notify_set_server_option (struct t_irc_server *server) +{ + char *str; + struct t_irc_notify *ptr_notify; + int total_length, length; + + if (!server) + return; + + if (server->notify_list) + { + str = NULL; + total_length = 0; + for (ptr_notify = server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + length = strlen (ptr_notify->nick) + 32; + if (!str) + { + total_length += length + 1; + str = malloc (total_length); + if (str) + str[0] = '\0'; + } + else + { + total_length += length; + str = realloc (str, total_length); + } + if (str) + { + if (str[0]) + strcat (str, ","); + strcat (str, ptr_notify->nick); + if (ptr_notify->check_away) + strcat (str, " away"); + } + } + if (str) + { + weechat_config_option_set (server->options[IRC_SERVER_OPTION_NOTIFY], + str, 0); + free (str); + } + } + else + { + weechat_config_option_set (server->options[IRC_SERVER_OPTION_NOTIFY], + "", 0); + } +} + +/* + * irc_notify_new: add new notify + */ + +struct t_irc_notify * +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]) + return NULL; + + new_notify = malloc (sizeof (*new_notify)); + if (new_notify) + { + new_notify->server = server; + new_notify->nick = strdup (nick); + new_notify->check_away = check_away; + new_notify->is_on_server = 0; + new_notify->away_message = NULL; + new_notify->ison_received = 0; + + /* add notify to notify list on server */ + new_notify->prev_notify = server->last_notify; + if (server->notify_list) + server->last_notify->next_notify = new_notify; + else + server->notify_list = new_notify; + server->last_notify = new_notify; + new_notify->next_notify = NULL; + } + + return new_notify; +} + +/* + * irc_notify_new_for_server: create notify list for server with option + * "irc.server.xxx.notify" + */ + +void +irc_notify_new_for_server (struct t_irc_server *server) +{ + const char *notify; + char **items, *pos_params, **params; + int i, j, num_items, num_params, check_away; + + 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++) + { + check_away = 0; + pos_params = strchr (items[i], ' '); + if (pos_params) + { + pos_params[0] = '\0'; + pos_params++; + while (pos_params[0] == ' ') + { + pos_params++; + } + params = weechat_string_split (pos_params, "/", 0, 0, + &num_params); + if (params) + { + for (j = 0; j < num_params; j++) + { + if (weechat_strcasecmp (params[j], "away") == 0) + check_away = 1; + } + weechat_string_free_split (params); + } + } + irc_notify_new (server, items[i], check_away); + } + weechat_string_free_split (items); + } +} + +/* + * irc_notify_new_for_all_servers: create notify list for all servers with + * option "irc.server.xxx.notify" + */ + +void +irc_notify_new_for_all_servers () +{ + struct t_irc_server *ptr_server; + + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + irc_notify_new_for_server (ptr_server); + } +} + +/* + * irc_notify_free: remove a notify on a server + */ + +void +irc_notify_free (struct t_irc_server *server, struct t_irc_notify *notify) +{ + weechat_hook_signal_send ("irc_notify_removing", + WEECHAT_HOOK_SIGNAL_POINTER, notify); + + /* free data */ + if (notify->nick) + free (notify->nick); + if (notify->away_message) + free (notify->away_message); + + /* remove notify from list */ + if (notify->prev_notify) + (notify->prev_notify)->next_notify = notify->next_notify; + if (notify->next_notify) + (notify->next_notify)->prev_notify = notify->prev_notify; + if (server->notify_list == notify) + server->notify_list = notify->next_notify; + if (server->last_notify == notify) + server->last_notify = notify->prev_notify; + + free (notify); + + weechat_hook_signal_send ("irc_notify_removed", + WEECHAT_HOOK_SIGNAL_STRING, NULL); +} + +/* + * irc_notify_free_all: remove all notify on a server + */ + +void +irc_notify_free_all (struct t_irc_server *server) +{ + while (server->notify_list) + { + irc_notify_free (server, server->notify_list); + } +} + +/* + * irc_notify_display: display a notify + */ + +void +irc_notify_display (struct t_gui_buffer *buffer, struct t_irc_notify *notify) +{ + if (!notify->is_on_server && !notify->away_message) + { + weechat_printf (buffer, + " %s%s%s @ %s%s%s: %s%s", + IRC_COLOR_CHAT_NICK, + notify->nick, + IRC_COLOR_CHAT, + IRC_COLOR_CHAT_SERVER, + notify->server->name, + IRC_COLOR_CHAT, + IRC_COLOR_MESSAGE_QUIT, + _("offline")); + } + else + { + weechat_printf (buffer, + " %s%s%s @ %s%s%s: %s%s %s%s%s%s%s%s", + IRC_COLOR_CHAT_NICK, + notify->nick, + IRC_COLOR_CHAT, + IRC_COLOR_CHAT_SERVER, + notify->server->name, + IRC_COLOR_CHAT, + IRC_COLOR_MESSAGE_JOIN, + _("online"), + IRC_COLOR_CHAT, + (notify->away_message) ? " (" : "", + (notify->away_message) ? _("away") : "", + (notify->away_message) ? ": \"" : "", + (notify->away_message) ? notify->away_message : "", + (notify->away_message) ? "\")" : ""); + } +} + +/* + * irc_notify_display_list: display notify list for a server + * (or all servers if server is NULL) + */ + +void +irc_notify_display_list (struct t_irc_server *server) +{ + struct t_irc_notify *ptr_notify; + struct t_irc_server *ptr_server; + int count; + + if (server) + { + if (server->notify_list) + { + weechat_printf (server->buffer, ""); + weechat_printf (server->buffer, + _("Notify list for %s%s%s:"), + IRC_COLOR_CHAT_SERVER, + server->name, + IRC_COLOR_CHAT); + for (ptr_notify = server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + irc_notify_display (server->buffer, ptr_notify); + } + } + else + { + weechat_printf (server->buffer, + _("Notify list is empty on this server")); + } + } + else + { + count = 0; + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (count == 0) + { + weechat_printf (NULL, ""); + weechat_printf (NULL, _("Notify list for all servers:")); + } + irc_notify_display (NULL, ptr_notify); + count++; + } + } + if (count == 0) + { + weechat_printf (NULL, + _("Notify list is empty on all servers")); + } + } +} + +/* + * irc_notify_get_tags: get tags for message displayed + * (concatenation of "irc_notify" and tags from option) + */ + +const char * +irc_notify_get_tags (struct t_config_option *option) +{ + static char string[1024]; + const char *tags; + + tags = weechat_config_string (option); + + snprintf (string, sizeof (string), "irc_notify%s%s", + (tags && tags[0]) ? "," : "", + (tags && tags[0]) ? tags : ""); + + return string; +} + +/* + * irc_notify_set_is_on_server: set flag "is_on_server" for a notify + * and display message if user was not on server + */ + +void +irc_notify_set_is_on_server (struct t_irc_notify *notify, + int is_on_server) +{ + if (!notify) + return; + + /* same status, then do nothing */ + if (notify->is_on_server == is_on_server) + return; + + notify->is_on_server = is_on_server; + + weechat_printf_tags (notify->server->buffer, + irc_notify_get_tags (irc_config_look_notify_tags_ison), + (notify->is_on_server) ? + _("%snotify: %s%s%s has joined %s%s") : + _("%snotify: %s%s%s has quit %s%s"), + weechat_prefix ("network"), + IRC_COLOR_CHAT_NICK, + notify->nick, + (notify->is_on_server) ? + IRC_COLOR_MESSAGE_JOIN : IRC_COLOR_MESSAGE_QUIT, + IRC_COLOR_CHAT_SERVER, + notify->server->name); +} + +/* + * irc_notify_set_away_message: set away message for a notify + * and display message if away status has changed + */ + +void +irc_notify_set_away_message (struct t_irc_notify *notify, + const char *away_message) +{ + if (!notify) + return; + + /* same away message, then do nothing */ + if ((!notify->away_message && !away_message) + || (notify->away_message && away_message + && (strcmp (notify->away_message, away_message) == 0))) + return; + + if (!notify->away_message && away_message) + { + weechat_printf_tags (notify->server->buffer, + irc_notify_get_tags (irc_config_look_notify_tags_whois), + _("%snotify: %s%s%s is now away: \"%s\""), + weechat_prefix ("network"), + IRC_COLOR_CHAT_NICK, + notify->nick, + IRC_COLOR_CHAT, + away_message); + } + else if (notify->away_message && !away_message) + { + weechat_printf_tags (notify->server->buffer, + irc_notify_get_tags (irc_config_look_notify_tags_whois), + _("%snotify: %s%s%s is back"), + weechat_prefix ("network"), + IRC_COLOR_CHAT_NICK, + notify->nick, + IRC_COLOR_CHAT); + } + else if (notify->away_message && away_message) + { + weechat_printf_tags (notify->server->buffer, + irc_notify_get_tags (irc_config_look_notify_tags_whois), + _("%snotify: %s%s%s is still away: \"%s\""), + weechat_prefix ("network"), + IRC_COLOR_CHAT_NICK, + notify->nick, + IRC_COLOR_CHAT, + away_message); + } + + if (notify->away_message) + free (notify->away_message); + notify->away_message = (away_message) ? strdup (away_message) : NULL; +} + +/* + * irc_notify_hsignal_cb: callback for hsignal on redirected commands + * "ison" and "whois" + */ + +int +irc_notify_hsignal_cb (void *data, const char *signal, + struct t_hashtable *hashtable) +{ + const char *error, *server, *pattern, *command, *output; + char **messages, **nicks_sent, **nicks_recv, *irc_cmd, *arguments; + char *ptr_args, *pos; + int i, j, num_messages, num_nicks_sent, num_nicks_recv, nick_was_sent; + int away_message_updated, no_such_nick; + struct t_irc_server *ptr_server; + struct t_irc_notify *ptr_notify; + + /* make C compiler happy */ + (void) data; + (void) signal; + + error = weechat_hashtable_get (hashtable, "error"); + server = weechat_hashtable_get (hashtable, "server"); + pattern = weechat_hashtable_get (hashtable, "pattern"); + command = weechat_hashtable_get (hashtable, "command"); + output = weechat_hashtable_get (hashtable, "output"); + + /* if there is an error on redirection, just ignore result */ + if (error && error[0]) + return WEECHAT_RC_OK; + + /* missing things in redirection */ + if (!server || !pattern || !command || !output) + return WEECHAT_RC_OK; + + /* search server */ + ptr_server = irc_server_search (server); + if (!ptr_server) + return WEECHAT_RC_OK; + + /* search for start of arguments in command sent to server */ + ptr_args = strchr (command, ' '); + if (!ptr_args) + return WEECHAT_RC_OK; + ptr_args++; + while ((ptr_args[0] == ' ') || (ptr_args[0] == ':')) + { + ptr_args++; + } + if (!ptr_args[0]) + return WEECHAT_RC_OK; + + /* read output of command */ + if (strcmp (pattern, "ison") == 0) + { + /* redirection of command "ison" */ + messages = weechat_string_split (output, "\n", 0, 0, &num_messages); + if (messages) + { + nicks_sent = weechat_string_split (ptr_args, " ", 0, 0, + &num_nicks_sent); + if (!nicks_sent) + return WEECHAT_RC_OK; + for (ptr_notify = ptr_server->notify_list; + ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + ptr_notify->ison_received = 0; + } + for (i = 0; i < num_messages; i++) + { + irc_server_parse_message (messages[i], NULL, NULL, NULL, NULL, + &arguments); + if (arguments) + { + pos = strchr (arguments, ' '); + if (pos) + { + pos++; + while ((pos[0] == ' ') || (pos[0] == ':')) + { + pos++; + } + if (pos[0]) + { + nicks_recv = weechat_string_split (pos, " ", 0, 0, + &num_nicks_recv); + if (nicks_recv) + { + for (j = 0; j < num_nicks_recv; j++) + { + for (ptr_notify = ptr_server->notify_list; + ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (strcmp (ptr_notify->nick, nicks_recv[j]) == 0) + { + irc_notify_set_is_on_server (ptr_notify, 1); + ptr_notify->ison_received = 1; + } + } + } + weechat_string_free_split (nicks_recv); + } + } + } + free (arguments); + } + } + for (ptr_notify = ptr_server->notify_list; + ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + if (!ptr_notify->ison_received) + { + nick_was_sent = 0; + for (j = 0; j < num_nicks_sent; j++) + { + if (strcmp (nicks_sent[j], ptr_notify->nick) == 0) + { + nick_was_sent = 1; + break; + } + } + if (nick_was_sent) + { + irc_notify_set_is_on_server (ptr_notify, 0); + } + } + + } + weechat_string_free_split (messages); + } + } + else if (strcmp (pattern, "whois") == 0) + { + /* redirection of command "whois" */ + ptr_notify = irc_notify_search (ptr_server, ptr_args); + if (ptr_notify) + { + away_message_updated = 0; + no_such_nick = 0; + messages = weechat_string_split (output, "\n", 0, 0, &num_messages); + if (messages) + { + for (i = 0; i < num_messages; i++) + { + irc_server_parse_message (messages[0], NULL, NULL, + &irc_cmd, NULL, &arguments); + if (irc_cmd && arguments) + { + if (strcmp (irc_cmd, "401") == 0) + { + /* no such nick/channel */ + no_such_nick = 1; + } + else if (strcmp (irc_cmd, "301") == 0) + { + /* away message */ + pos = strchr (arguments, ':'); + if (pos) + { + pos++; + /* nick is away */ + irc_notify_set_away_message (ptr_notify, pos); + away_message_updated = 1; + } + } + } + if (irc_cmd) + free (irc_cmd); + if (arguments) + free (arguments); + } + } + if (!away_message_updated && !no_such_nick) + { + /* nick is back */ + irc_notify_set_away_message (ptr_notify, NULL); + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * irc_notify_timer_ison_cb: timer called to send "ison" command to servers + */ + +int +irc_notify_timer_ison_cb (void *data, int remaining_calls) +{ + char ison_list[1024]; + int total_length, length; + struct t_irc_server *ptr_server; + struct t_irc_notify *ptr_notify, *ptr_next_notify; + + /* make C compiler happy */ + (void) data; + (void) remaining_calls; + + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + if (ptr_server->is_connected && ptr_server->notify_list) + { + ison_list[0] = '\0'; + total_length = 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; + if (ison_list[0]) + strcat (ison_list, " "); + strcat (ison_list, ptr_notify->nick); + + ptr_notify = ptr_next_notify; + } + if (ison_list[0]) + { + irc_redirect_new (ptr_server, "ison", "notify", 1, + NULL, 0, NULL); + irc_server_sendf (ptr_server, IRC_SERVER_SEND_OUTQ_PRIO_LOW, + NULL, "ISON :%s", ison_list); + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * irc_notify_timer_whois_cb: timer called to send "whois" command to servers + */ + +int +irc_notify_timer_whois_cb (void *data, int remaining_calls) +{ + struct t_irc_server *ptr_server; + struct t_irc_notify *ptr_notify, *ptr_next_notify; + + /* make C compiler happy */ + (void) data; + (void) remaining_calls; + + for (ptr_server = irc_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + if (ptr_server->is_connected && ptr_server->notify_list) + { + ptr_notify = ptr_server->notify_list; + while (ptr_notify) + { + ptr_next_notify = ptr_notify->next_notify; + + if (ptr_notify->check_away) + { + /* + * redirect whois, and get only 2 messages: + * 301: away message + * 401: no such nick/channel + */ + irc_redirect_new (ptr_server, "whois", "notify", 1, + ptr_notify->nick, 0, "301,401"); + irc_server_sendf (ptr_server, + IRC_SERVER_SEND_OUTQ_PRIO_LOW, NULL, + "WHOIS :%s", ptr_notify->nick); + } + + ptr_notify = ptr_next_notify; + } + } + } + + return WEECHAT_RC_OK; +} + +/* + * irc_notify_add_to_infolist: add a notify in an infolist + * return 1 if ok, 0 if error + */ + +int +irc_notify_add_to_infolist (struct t_infolist *infolist, + struct t_irc_notify *notify) +{ + struct t_infolist_item *ptr_item; + + if (!infolist || !notify) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_pointer (ptr_item, "server", notify->server)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "server_name", notify->server->name)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "nick", notify->nick)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "check_away", notify->check_away)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "is_on_server", notify->is_on_server)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "away_message", notify->away_message)) + return 0; + + return 1; +} + +/* + * irc_notify_print_log: print notify infos in log (usually for crash dump) + */ + +void +irc_notify_print_log (struct t_irc_server *server) +{ + struct t_irc_notify *ptr_notify; + + for (ptr_notify = server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + weechat_log_printf (""); + weechat_log_printf (" => notify (addr:0x%lx):", ptr_notify); + weechat_log_printf (" server. . . . . . . : 0x%lx", ptr_notify->server); + weechat_log_printf (" nick. . . . . . . . : '%s'", ptr_notify->nick); + weechat_log_printf (" check_away. . . . . : %d", ptr_notify->check_away); + weechat_log_printf (" is_on_server. . . . : %d", ptr_notify->is_on_server); + weechat_log_printf (" away_message. . . . : '%s'", ptr_notify->away_message); + weechat_log_printf (" ison_received . . . : %d", ptr_notify->ison_received); + weechat_log_printf (" prev_notify . . . . : 0x%lx", ptr_notify->prev_notify); + weechat_log_printf (" next_notify . . . . : 0x%lx", ptr_notify->next_notify); + } +} + +/* + * irc_notify_hook_timer_ison: hook timer to send "ison" command + */ + +void +irc_notify_hook_timer_ison () +{ + if (irc_notify_timer_ison) + weechat_unhook (irc_notify_timer_ison); + + irc_notify_timer_ison = weechat_hook_timer ( + 60 * 1000 * weechat_config_integer (irc_config_network_notify_check_ison), + 0, 0, &irc_notify_timer_ison_cb, NULL); +} + +/* + * irc_notify_hook_timer_whois: hook timer to send "whois" command + */ + +void +irc_notify_hook_timer_whois () +{ + if (irc_notify_timer_whois) + weechat_unhook (irc_notify_timer_whois); + + irc_notify_timer_whois = weechat_hook_timer ( + 60 * 1000 * weechat_config_integer (irc_config_network_notify_check_whois), + 0, 0, &irc_notify_timer_whois_cb, NULL); +} + +/* + * irc_notify_init: hook timers and hsignals + */ + +void +irc_notify_init () +{ + irc_notify_hook_timer_ison (); + irc_notify_hook_timer_whois (); + + irc_notify_hsignal = weechat_hook_hsignal ("irc_redirection_notify_*", + &irc_notify_hsignal_cb, + NULL); +} + +/* + * irc_notify_end: remove timers and hsignals + */ + +void +irc_notify_end () +{ + if (irc_notify_timer_ison) + weechat_unhook (irc_notify_timer_ison); + if (irc_notify_timer_whois) + weechat_unhook (irc_notify_timer_whois); + if (irc_notify_hsignal) + weechat_unhook (irc_notify_hsignal); +} diff --git a/src/plugins/irc/irc-notify.h b/src/plugins/irc/irc-notify.h new file mode 100644 index 000000000..b069d258d --- /dev/null +++ b/src/plugins/irc/irc-notify.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2010 Sebastien 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef __WEECHAT_IRC_NOTIFY_H +#define __WEECHAT_IRC_NOTIFY_H 1 + +struct t_irc_server; + +struct t_irc_notify +{ + struct t_irc_server *server; /* server */ + char *nick; /* nick */ + int check_away; /* check away status (with whois) */ + /* current state of nick */ + int is_on_server; /* 1 if nick is currently on server */ + /* (using answer of ison command) */ + char *away_message; /* current away message, NULL if */ + /* nick is not away (using answer of */ + /* whois command) */ + /* internal stuff */ + int ison_received; /* used when receiving ison answer */ + struct t_irc_notify *prev_notify; /* link to previous notify */ + struct t_irc_notify *next_notify; /* link to next notify */ +}; + +extern int irc_notify_valid (struct t_irc_server *server, + struct t_irc_notify *notify); +extern struct t_irc_notify *irc_notify_search (struct t_irc_server *server, + const char *nick); +extern void irc_notify_set_server_option (struct t_irc_server *server); +extern struct t_irc_notify *irc_notify_new (struct t_irc_server *server, + const char *nick, + int check_away); +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); +extern void irc_notify_free_all (struct t_irc_server *server); +extern void irc_notify_display_list (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 int irc_notify_add_to_infolist (struct t_infolist *infolist, + struct t_irc_notify *notify); +extern void irc_notify_print_log (struct t_irc_server *server); +extern void irc_notify_hook_timer_ison (); +extern void irc_notify_hook_timer_whois (); +extern void irc_notify_init (); +extern void irc_notify_end (); + +#endif /* __WEECHAT_IRC_NOTIFY_H */ diff --git a/src/plugins/irc/irc-redirect.h b/src/plugins/irc/irc-redirect.h index 44f802068..3186c9186 100644 --- a/src/plugins/irc/irc-redirect.h +++ b/src/plugins/irc/irc-redirect.h @@ -91,6 +91,13 @@ extern struct t_irc_redirect *irc_redirect_new_with_commands (struct t_irc_serve const char *cmd_stop, const char *cmd_extra, const char *cmd_filter); +extern struct t_irc_redirect *irc_redirect_new (struct t_irc_server *server, + const char *pattern, + const char *signal, + int count, + const char *string, + int timeout, + const char *cmd_filter); extern struct t_irc_redirect *irc_redirect_search_available (struct t_irc_server *server); extern void irc_redirect_init_command (struct t_irc_redirect *redirect, const char *command); diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index de005d823..09fd5de2d 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -50,6 +50,7 @@ #include "irc-config.h" #include "irc-input.h" #include "irc-nick.h" +#include "irc-notify.h" #include "irc-protocol.h" #include "irc-raw.h" #include "irc-redirect.h" @@ -73,6 +74,7 @@ char *irc_server_option_string[IRC_SERVER_NUM_OPTIONS] = "anti_flood_prio_high", "anti_flood_prio_low", "away_check", "away_check_max_nicks", "default_msg_part", "default_msg_quit", + "notify", }; char *irc_server_option_default[IRC_SERVER_NUM_OPTIONS] = @@ -86,6 +88,7 @@ char *irc_server_option_default[IRC_SERVER_NUM_OPTIONS] = "2", "2", "0", "25", "WeeChat %v", "WeeChat %v", + "", }; char *irc_server_prefix_modes_default = "qaohvu"; @@ -650,6 +653,8 @@ irc_server_alloc (const char *name) } new_server->redirects = NULL; new_server->last_redirect = NULL; + new_server->notify_list = NULL; + new_server->last_notify = NULL; new_server->buffer = NULL; new_server->buffer_as_string = NULL; new_server->channels = NULL; @@ -1088,6 +1093,7 @@ irc_server_free_data (struct t_irc_server *server) { irc_server_outqueue_free_all (server, i); } + irc_notify_free_all (server); irc_redirect_free_all (server); if (server->channels) irc_channel_free_all (server); @@ -4480,6 +4486,8 @@ irc_server_print_log () } weechat_log_printf (" redirects. . . . . . : 0x%lx", ptr_server->redirects); 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 (" buffer . . . . . . . : 0x%lx", ptr_server->buffer); weechat_log_printf (" buffer_as_string . . : 0x%lx", ptr_server->buffer_as_string); weechat_log_printf (" channels . . . . . . : 0x%lx", ptr_server->channels); @@ -4489,6 +4497,8 @@ irc_server_print_log () irc_redirect_print_log (ptr_server); + irc_notify_print_log (ptr_server); + for (ptr_channel = ptr_server->channels; ptr_channel; ptr_channel = ptr_channel->next_channel) { diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index b8e728d3c..23140ed85 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -64,6 +64,7 @@ enum t_irc_server_option IRC_SERVER_OPTION_AWAY_CHECK_MAX_NICKS, /* max nicks for away check */ IRC_SERVER_OPTION_DEFAULT_MSG_PART, /* default part message */ IRC_SERVER_OPTION_DEFAULT_MSG_QUIT, /* default quit message */ + IRC_SERVER_OPTION_NOTIFY, /* notify list */ /* number of server options */ IRC_SERVER_NUM_OPTIONS, }; @@ -173,6 +174,8 @@ struct t_irc_server struct t_irc_outqueue *last_outqueue[2]; /* last outgoing message */ struct t_irc_redirect *redirects; /* command redirections */ 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 */ struct t_gui_buffer *buffer; /* GUI buffer allocated for server */ char *buffer_as_string; /* used to return buffer info */ struct t_irc_channel *channels; /* opened channels on server */ @@ -234,6 +237,9 @@ extern void irc_server_send_signal (struct t_irc_server *server, const char *signal, const char *command, const char *full_message, const char *tags); +extern void irc_server_parse_message (const char *message, char **nick, + char **host, char **command, + char **channel, char **arguments); extern struct t_hashtable *irc_server_parse_message_to_hashtable (const char *message); extern void irc_server_set_send_default_tags (const char *tags); extern void irc_server_sendf (struct t_irc_server *server, int flags, diff --git a/src/plugins/irc/irc-upgrade.c b/src/plugins/irc/irc-upgrade.c index d4c5d0522..a167960b6 100644 --- a/src/plugins/irc/irc-upgrade.c +++ b/src/plugins/irc/irc-upgrade.c @@ -29,13 +29,14 @@ #include "irc.h" #include "irc-upgrade.h" #include "irc-buffer.h" +#include "irc-channel.h" #include "irc-config.h" #include "irc-input.h" -#include "irc-server.h" -#include "irc-channel.h" #include "irc-nick.h" +#include "irc-notify.h" #include "irc-raw.h" #include "irc-redirect.h" +#include "irc-server.h" struct t_irc_server *irc_upgrade_current_server = NULL; @@ -55,6 +56,7 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) struct t_irc_nick *ptr_nick; struct t_irc_redirect *ptr_redirect; struct t_irc_redirect_pattern *ptr_redirect_pattern; + struct t_irc_notify *ptr_notify; struct t_irc_raw_message *ptr_raw_message; int rc; @@ -122,7 +124,6 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) for (ptr_redirect = ptr_server->redirects; ptr_redirect; ptr_redirect = ptr_redirect->next_redirect) { - /* save channel */ infolist = weechat_infolist_new (); if (!infolist) return 0; @@ -138,6 +139,26 @@ irc_upgrade_save_all_data (struct t_upgrade_file *upgrade_file) if (!rc) return 0; } + + /* save server notify list */ + for (ptr_notify = ptr_server->notify_list; ptr_notify; + ptr_notify = ptr_notify->next_notify) + { + infolist = weechat_infolist_new (); + if (!infolist) + return 0; + if (!irc_notify_add_to_infolist (infolist, ptr_notify)) + { + weechat_infolist_free (infolist); + return 0; + } + rc = weechat_upgrade_write_object (upgrade_file, + IRC_UPGRADE_TYPE_NOTIFY, + infolist); + weechat_infolist_free (infolist); + if (!rc) + return 0; + } } /* save raw messages */ @@ -255,6 +276,7 @@ irc_upgrade_read_cb (void *data, const char *buffer_name, *str, *nick; struct t_irc_nick *ptr_nick; struct t_irc_redirect *ptr_redirect; + struct t_irc_notify *ptr_notify; struct t_gui_buffer *ptr_buffer; /* make C compiler happy */ @@ -558,6 +580,20 @@ irc_upgrade_read_cb (void *data, weechat_infolist_string (infolist, "cmd_stop"), weechat_infolist_string (infolist, "cmd_extra")); break; + case IRC_UPGRADE_TYPE_NOTIFY: + if (irc_upgrade_current_server) + { + ptr_notify = irc_notify_search (irc_upgrade_current_server, + weechat_infolist_string (infolist, "nick")); + if (ptr_notify) + { + ptr_notify->is_on_server = weechat_infolist_integer (infolist, "is_on_server"); + str = weechat_infolist_string (infolist, "away_message"); + if (str) + ptr_notify->away_message = strdup (str); + } + } + break; case IRC_UPGRADE_TYPE_RAW_MESSAGE: irc_raw_message_add_to_list (weechat_infolist_time (infolist, "date"), weechat_infolist_string (infolist, "prefix"), diff --git a/src/plugins/irc/irc-upgrade.h b/src/plugins/irc/irc-upgrade.h index 724fd15c9..175376c2f 100644 --- a/src/plugins/irc/irc-upgrade.h +++ b/src/plugins/irc/irc-upgrade.h @@ -32,6 +32,7 @@ enum t_irc_upgrade_type IRC_UPGRADE_TYPE_RAW_MESSAGE, IRC_UPGRADE_TYPE_REDIRECT_PATTERN, IRC_UPGRADE_TYPE_REDIRECT, + IRC_UPGRADE_TYPE_NOTIFY, }; extern int irc_upgrade_save (); diff --git a/src/plugins/irc/irc.c b/src/plugins/irc/irc.c index 68e3abb3c..df356daf6 100644 --- a/src/plugins/irc/irc.c +++ b/src/plugins/irc/irc.c @@ -29,6 +29,7 @@ #include "irc.h" #include "irc-bar-item.h" #include "irc-buffer.h" +#include "irc-channel.h" #include "irc-color.h" #include "irc-command.h" #include "irc-completion.h" @@ -36,11 +37,11 @@ #include "irc-debug.h" #include "irc-info.h" #include "irc-input.h" -#include "irc-server.h" -#include "irc-channel.h" #include "irc-nick.h" +#include "irc-notify.h" #include "irc-raw.h" #include "irc-redirect.h" +#include "irc-server.h" #include "irc-upgrade.h" @@ -167,6 +168,8 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) irc_redirect_init (); + irc_notify_init (); + /* hook some signals */ irc_debug_init (); weechat_hook_signal ("quit", &irc_signal_quit_cb, NULL); @@ -269,6 +272,8 @@ weechat_plugin_end (struct t_weechat_plugin *plugin) irc_config_free (); + irc_notify_end (); + irc_redirect_end (); return WEECHAT_RC_OK; |