summaryrefslogtreecommitdiff
path: root/src/plugins/irc
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2010-11-06 11:38:48 +0100
committerSebastien Helleu <flashcode@flashtux.org>2010-11-06 11:38:48 +0100
commite001c057108a573d9e67cc37c0c5f8462e1fbdf6 (patch)
treed5e153942e4c8b08a870ee49325e3d953f887770 /src/plugins/irc
parenta56dc00b2f7a01ee3c52fcb49bea2638c877d1ff (diff)
downloadweechat-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.txt1
-rw-r--r--src/plugins/irc/Makefile.am2
-rw-r--r--src/plugins/irc/irc-command.c232
-rw-r--r--src/plugins/irc/irc-completion.c52
-rw-r--r--src/plugins/irc/irc-config.c154
-rw-r--r--src/plugins/irc/irc-config.h8
-rw-r--r--src/plugins/irc/irc-ignore.c10
-rw-r--r--src/plugins/irc/irc-ignore.h4
-rw-r--r--src/plugins/irc/irc-info.c50
-rw-r--r--src/plugins/irc/irc-notify.c927
-rw-r--r--src/plugins/irc/irc-notify.h66
-rw-r--r--src/plugins/irc/irc-redirect.h7
-rw-r--r--src/plugins/irc/irc-server.c10
-rw-r--r--src/plugins/irc/irc-server.h6
-rw-r--r--src/plugins/irc/irc-upgrade.c42
-rw-r--r--src/plugins/irc/irc-upgrade.h1
-rw-r--r--src/plugins/irc/irc.c9
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;