..adding new files..

git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2000-04-26 08:03:38 +00:00 committed by cras
commit c95034c6de
206 changed files with 31247 additions and 0 deletions

View file

@ -0,0 +1,15 @@
noinst_LTLIBRARIES = libirc_notifylist.la
INCLUDES = $(GLIB_CFLAGS) \
-I$(top_srcdir)/src -I$(top_srcdir)/src/core/ -I$(top_srcdir)/src/irc/core/
libirc_notifylist_la_SOURCES = \
notifylist.c \
notify-commands.c \
notify-ison.c \
notify-setup.c \
notify-whois.c
noinst_HEADERS = \
notifylist.h \
notify-setup.h

View file

@ -0,0 +1,44 @@
#include "common.h"
#define MODULE_NAME "irc/notifylist"
#define ISON_EVENT "event 303"
typedef struct {
char *nick;
char *user, *host, *realname, *awaymsg;
time_t idle_time;
int host_ok:1; /* host matches the one in notifylist = this is the right person*/
int away_ok:1; /* not away, or we don't care about it */
int idle_ok:1; /* idle time is low enough, or we don't care about it */
int away:1; /* nick is away */
int join_announced:1; /* join to IRC has been announced */
int idle_changed:1; /* idle time is lower than in last check */
time_t last_whois;
} NOTIFY_NICK_REC;
typedef struct {
GSList *notify_users; /* NOTIFY_NICK_REC's of notifylist people who are in IRC */
GSList *ison_tempusers; /* Temporary list for saving /ISON events.. */
} MODULE_SERVER_REC;
#include "irc-server.h"
NOTIFY_NICK_REC *notify_nick_create(IRC_SERVER_REC *server, const char *nick);
void notify_nick_destroy(NOTIFY_NICK_REC *rec);
NOTIFY_NICK_REC *notify_nick_find(IRC_SERVER_REC *server, const char *nick);
void notifylist_left(IRC_SERVER_REC *server, NOTIFY_NICK_REC *rec);
void notifylist_destroy_all(void);
void notifylist_commands_init(void);
void notifylist_commands_deinit(void);
void notifylist_whois_init(void);
void notifylist_whois_deinit(void);
void notifylist_ison_init(void);
void notifylist_ison_deinit(void);

View file

@ -0,0 +1,81 @@
/*
notify-commands.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "signals.h"
#include "commands.h"
#include "misc.h"
#include "settings.h"
#include "notifylist.h"
#define DEFAULT_NOTIFY_IDLE_TIME 60
static void cmd_notify(gchar *data)
{
char *params, *mask, *ircnets, *args, *idletime;
int away_check, idle_check_time;
g_return_if_fail(data != NULL);
args = "@idle";
params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, &args, &idletime, &mask, &ircnets);
if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
if (stristr(args, "-idle") == NULL)
idle_check_time = 0;
else {
idle_check_time = is_numeric(idletime, 0) ? (atol(idletime)*60) :
(settings_get_int("notify_idle_time")*60);
}
away_check = stristr(args, "-away") != NULL;
notifylist_remove(mask);
notifylist_add(mask, ircnets, away_check, idle_check_time);
g_free(params);
}
static void cmd_unnotify(const char *data)
{
char *params, *mask;
g_return_if_fail(data != NULL);
params = cmd_get_params(data, 1, &mask);
if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
notifylist_remove(mask);
g_free(params);
}
void notifylist_commands_init(void)
{
settings_add_int("misc", "notify_idle_time", DEFAULT_NOTIFY_IDLE_TIME);
command_bind("notify", NULL, (SIGNAL_FUNC) cmd_notify);
command_bind("unnotify", NULL, (SIGNAL_FUNC) cmd_unnotify);
}
void notifylist_commands_deinit(void)
{
command_unbind("notify", (SIGNAL_FUNC) cmd_notify);
command_unbind("unnotify", (SIGNAL_FUNC) cmd_unnotify);
}

View file

@ -0,0 +1,354 @@
/*
notify-ison.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "signals.h"
#include "misc.h"
#include "settings.h"
#include "irc.h"
#include "irc-server.h"
#include "server-redirect.h"
#include "notifylist.h"
#define DEFAULT_NOTIFY_CHECK_TIME 60
#define DEFAULT_NOTIFY_WHOIS_TIME (60*5)
typedef struct {
char *nick;
int hostok;
} ISON_REC;
static int notify_tag;
static int notify_whois_time;
NOTIFY_NICK_REC *notify_nick_create(IRC_SERVER_REC *server, const char *nick)
{
MODULE_SERVER_REC *mserver;
NOTIFY_NICK_REC *rec;
mserver = MODULE_DATA(server);
rec = g_new0(NOTIFY_NICK_REC, 1);
rec->nick = g_strdup(nick);
mserver->notify_users = g_slist_append(mserver->notify_users, rec);
return rec;
}
void notify_nick_destroy(NOTIFY_NICK_REC *rec)
{
g_free(rec->nick);
g_free_not_null(rec->user);
g_free_not_null(rec->host);
g_free_not_null(rec->realname);
g_free_not_null(rec->awaymsg);
g_free(rec);
}
NOTIFY_NICK_REC *notify_nick_find(IRC_SERVER_REC *server, const char *nick)
{
MODULE_SERVER_REC *mserver;
NOTIFY_NICK_REC *rec;
GSList *tmp;
mserver = MODULE_DATA(server);
for (tmp = mserver->notify_users; tmp != NULL; tmp = tmp->next) {
rec = tmp->data;
if (g_strcasecmp(rec->nick, nick) == 0)
return rec;
}
return NULL;
}
static int is_ison_queue_empty(IRC_SERVER_REC *server)
{
GSList *tmp;
tmp = server_redirect_getqueue((SERVER_REC *) server, ISON_EVENT, NULL);
for (; tmp != NULL; tmp = tmp->next) {
REDIRECT_REC *rec = tmp->data;
if (strcmp(rec->name, "notifylist event") == 0)
return FALSE;
}
return TRUE;
}
static void ison_send(IRC_SERVER_REC *server, GString *cmd)
{
g_string_truncate(cmd, cmd->len-1);
g_string_prepend(cmd, "ISON :");
irc_send_cmd(server, cmd->str);
server_redirect_event((SERVER_REC *) server, NULL, 1, ISON_EVENT, "notifylist event", -1, NULL);
g_string_truncate(cmd, 0);
}
/* timeout function: send /ISON commands to server to check if someone in
notify list is in IRC */
static void notifylist_timeout_server(IRC_SERVER_REC *server)
{
GSList *tmp;
GString *cmd;
char *nick, *ptr;
int len;
g_return_if_fail(server != NULL);
if (!is_ison_queue_empty(server)) {
/* still not received all replies to previous /ISON commands.. */
return;
}
cmd = g_string_new(NULL);
for (tmp = notifies; tmp != NULL; tmp = tmp->next) {
NOTIFYLIST_REC *rec = tmp->data;
if (!notify_ircnets_match(rec, server->connrec->ircnet))
continue;
nick = g_strdup(rec->mask);
ptr = strchr(nick, '!');
if (ptr != NULL) *ptr = '\0';
len = strlen(nick);
if (cmd->len+len+1 > 510)
ison_send(server, cmd);
g_string_sprintfa(cmd, "%s ", nick);
g_free(nick);
}
if (cmd->len > 0)
ison_send(server, cmd);
g_string_free(cmd, TRUE);
}
static int notifylist_timeout_func(void)
{
g_slist_foreach(servers, (GFunc) notifylist_timeout_server, NULL);
return 1;
}
static void ison_save_users(MODULE_SERVER_REC *mserver, char *online)
{
char *ptr;
while (online != NULL && *online != '\0') {
ptr = strchr(online, ' ');
if (ptr != NULL) *ptr++ = '\0';
mserver->ison_tempusers =
g_slist_append(mserver->ison_tempusers, g_strdup(online));
online = ptr;
}
}
static void whois_send(IRC_SERVER_REC *server, char *nicks)
{
char *p, *str;
irc_send_cmdv(server, "WHOIS %s", nicks);
/* "nick1,nick2" -> "nick1,nick2 nick1 nick2" because
End of WHOIS give nick1,nick2 while other whois events give
nick1 or nick2 */
str = g_strconcat(nicks, " ", nicks, NULL);
for (p = str+strlen(nicks)+1; *p != '\0'; p++)
if (*p == ',') *p = ' ';
server_redirect_event((SERVER_REC *) server, str, 2,
"event 318", "notifylist event whois end", 1,
"event 402", "event empty", -1,
"event 401", "event empty", 1,
"event 311", "notifylist event whois", 1,
"event 301", "notifylist event whois away", 1,
"event 312", "event empty", 1,
"event 313", "event empty", 1,
"event 317", "notifylist event whois idle", 1,
"event 319", "event empty", 1, NULL);
g_free(str);
}
static void whois_send_server(IRC_SERVER_REC *server, char *nick)
{
char *str;
str = g_strdup_printf("%s %s", nick, nick);
whois_send(server, str);
g_free(str);
}
/* try to send as many nicks in one WHOIS as possible */
static void whois_list_send(IRC_SERVER_REC *server, GSList *nicks)
{
GSList *tmp;
GString *str;
char *nick;
int count;
str = g_string_new(NULL);
count = 0;
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
nick = tmp->data;
count++;
g_string_sprintfa(str, "%s,", nick);
if (count >= server->max_whois_in_cmd) {
g_string_truncate(str, str->len-1);
whois_send(server, str->str);
count = 0;
}
}
if (str->len > 0) {
g_string_truncate(str, str->len-1);
whois_send(server, str->str);
}
g_string_free(str, TRUE);
}
static void ison_check_joins(IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
NOTIFYLIST_REC *notify;
NOTIFY_NICK_REC *rec;
GSList *tmp, *newnicks;
int send_whois;
time_t now;
mserver = MODULE_DATA(server);
now = time(NULL);
newnicks = NULL;
for (tmp = mserver->ison_tempusers; tmp != NULL; tmp = tmp->next) {
char *nick = tmp->data;
notify = notifylist_find(nick, server->connrec->ircnet);
send_whois = notify != NULL &&
(notify->away_check || notify->idle_check_time > 0);
rec = notify_nick_find(server, nick);
if (rec != NULL) {
/* check if we want to send WHOIS yet.. */
if (now-rec->last_whois < notify_whois_time)
continue;
} else {
rec = notify_nick_create(server, nick);
if (!send_whois) newnicks = g_slist_append(newnicks, nick);
}
if (send_whois) {
/* we need away message or idle time -
send the WHOIS reply to the nick's server */
rec->last_whois = now;
whois_send_server(server, nick);
}
}
whois_list_send(server, newnicks);
g_slist_free(newnicks);
}
static void ison_check_parts(IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
GSList *tmp, *next;
mserver = MODULE_DATA(server);
for (tmp = mserver->notify_users; tmp != NULL; tmp = next) {
NOTIFY_NICK_REC *rec = tmp->data;
next = tmp->next;
if (gslist_find_icase_string(mserver->ison_tempusers, rec->nick) != NULL)
continue;
notifylist_left(server, rec);
notify_nick_destroy(rec);
}
}
static void event_ison(const char *data, IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
char *params, *online;
g_return_if_fail(data != NULL);
g_return_if_fail(server != NULL);
params = event_get_params(data, 2, NULL, &online);
mserver = MODULE_DATA(server);
ison_save_users(mserver, online);
if (!is_ison_queue_empty(server)) {
/* wait for the rest of the /ISON replies */
g_free(params);
return;
}
ison_check_joins(server);
ison_check_parts(server);
/* free memory used by temp list */
g_slist_foreach(mserver->ison_tempusers, (GFunc) g_free, NULL);
g_slist_free(mserver->ison_tempusers);
mserver->ison_tempusers = NULL;
g_free(params);
}
static void read_settings(void)
{
if (notify_tag != -1) g_source_remove(notify_tag);
notify_tag = g_timeout_add(1000*settings_get_int("notify_check_time"), (GSourceFunc) notifylist_timeout_func, NULL);
notify_whois_time = settings_get_int("notify_whois_time");
}
void notifylist_ison_init(void)
{
settings_add_int("misc", "notify_check_time", DEFAULT_NOTIFY_CHECK_TIME);
settings_add_int("misc", "notify_whois_time", DEFAULT_NOTIFY_WHOIS_TIME);
notify_tag = -1;
read_settings();
signal_add("notifylist event", (SIGNAL_FUNC) event_ison);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
}
void notifylist_ison_deinit(void)
{
g_source_remove(notify_tag);
signal_remove("notifylist event", (SIGNAL_FUNC) event_ison);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}

View file

@ -0,0 +1,84 @@
/*
notify-setup.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "lib-config/iconfig.h"
#include "settings.h"
#include "irc-server.h"
#include "notifylist.h"
void notifylist_add_config(NOTIFYLIST_REC *rec)
{
CONFIG_NODE *node;
node = iconfig_node_traverse("notifies", TRUE);
node = config_node_section(node, rec->mask, NODE_TYPE_BLOCK);
if (rec->away_check)
config_node_set_bool(node, "away_check", TRUE);
else
config_node_set_str(node, "away_check", NULL);
if (rec->idle_check_time > 0)
config_node_set_int(node, "idle_check_time", rec->idle_check_time/60);
else
config_node_set_str(node, "idle_check_time", NULL);
config_node_set_str(node, "ircnets", NULL);
if (rec->ircnets != NULL && *rec->ircnets != NULL) {
node = config_node_section(node, "ircnets", NODE_TYPE_LIST);
config_node_add_list(node, rec->ircnets);
}
}
void notifylist_remove_config(NOTIFYLIST_REC *rec)
{
iconfig_set_str("notifies", rec->mask, NULL);
}
void notifylist_read_config(void)
{
CONFIG_NODE *node;
NOTIFYLIST_REC *rec;
GSList *tmp;
notifylist_destroy_all();
node = iconfig_node_traverse("notifies", FALSE);
if (node == NULL) return;
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
node = tmp->data;
if (node->type != NODE_TYPE_BLOCK)
continue;
rec = g_new0(NOTIFYLIST_REC, 1);
notifies = g_slist_append(notifies, rec);
rec->mask = g_strdup(node->key);
rec->away_check = config_node_get_bool(node, "away_check", FALSE);
rec->idle_check_time = config_node_get_int(node, "idle_check_time", 0)*60;
node = config_node_section(node, "ircnets", -1);
if (node != NULL) rec->ircnets = config_node_get_list(node);
}
}

View file

@ -0,0 +1,9 @@
#ifndef __NOTIFY_SETUP_H
#define __NOTIFY_SETUP_H
void notifylist_add_config(NOTIFYLIST_REC *rec);
void notifylist_remove_config(NOTIFYLIST_REC *rec);
void notifylist_read_config(void);
#endif

View file

@ -0,0 +1,186 @@
/*
notify-whois.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "signals.h"
#include "special-vars.h"
#include "irc.h"
#include "irc-server.h"
#include "masks.h"
#include "notifylist.h"
static char *last_notify_nick;
static void event_whois(const char *data, IRC_SERVER_REC *server)
{
char *params, *nick, *user, *host, *realname;
NOTIFY_NICK_REC *nickrec;
NOTIFYLIST_REC *notify;
g_return_if_fail(data != NULL);
g_return_if_fail(server != NULL);
params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname);
notify = notifylist_find(nick, server->connrec->ircnet);
if (notify != NULL && !irc_mask_match(notify->mask, nick, user, host)) {
/* user or host didn't match */
g_free(params);
return;
}
nickrec = notify_nick_find(server, nick);
if (nickrec != NULL) {
g_free_not_null(last_notify_nick);
last_notify_nick = g_strdup(nick);
g_free_not_null(nickrec->user);
g_free_not_null(nickrec->host);
g_free_not_null(nickrec->realname);
g_free_and_null(nickrec->awaymsg);
nickrec->user = g_strdup(user);
nickrec->host = g_strdup(host);
nickrec->realname = g_strdup(realname);
nickrec->away = FALSE;
nickrec->host_ok = TRUE;
nickrec->idle_ok = TRUE;
}
g_free(params);
}
static void event_whois_idle(const char *data, IRC_SERVER_REC *server)
{
NOTIFY_NICK_REC *nickrec;
NOTIFYLIST_REC *notify;
char *params, *nick, *secstr;
long secs;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &secstr);
secs = atol(secstr);
notify = notifylist_find(nick, server->connrec->ircnet);
nickrec = notify_nick_find(server, nick);
if (notify != NULL && nickrec != NULL) {
time_t now = time(NULL);
nickrec->idle_changed = secs < now-nickrec->idle_time &&
now-nickrec->idle_time > notify->idle_check_time;
nickrec->idle_time = now-secs;
}
g_free(params);
}
static void event_whois_away(const char *data, IRC_SERVER_REC *server)
{
NOTIFY_NICK_REC *nickrec;
char *params, *nick, *awaymsg;
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &awaymsg);
nickrec = notify_nick_find(server, nick);
if (nickrec != NULL) {
nickrec->awaymsg = g_strdup(awaymsg);
nickrec->away = TRUE;
}
g_free(params);
}
/* All WHOIS replies got, now announce all the changes at once. */
static void event_whois_end(const char *data, IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
NOTIFYLIST_REC *notify;
NOTIFY_NICK_REC *rec;
GSList *tmp;
const char *event;
int away_ok;
time_t now;
now = time(NULL);
mserver = MODULE_DATA(server);
for (tmp = mserver->notify_users; tmp != NULL; tmp = tmp->next) {
rec = tmp->data;
if (rec->realname == NULL)
continue;
notify = notifylist_find(rec->nick, server->connrec->ircnet);
if (notify == NULL) continue;
away_ok = !notify->away_check || !rec->away;
event = NULL;
if (!rec->join_announced) {
rec->join_announced = TRUE;
rec->idle_time = now;
if (away_ok) event = "notifylist joined";
} else if (notify->away_check && rec->away_ok == rec->away)
event = "notifylist away changed";
else if (notify->idle_check_time > 0 && rec->idle_changed)
event = "notifylist unidle";
if (event != NULL) {
signal_emit(event, 6, server, rec->nick,
rec->user, rec->host,
rec->realname, rec->awaymsg);
}
rec->idle_ok = notify->idle_check_time <= 0 ||
now-rec->idle_time <= notify->idle_check_time;
rec->idle_changed = FALSE;
rec->away_ok = away_ok;
}
}
/* last person that NOTIFY detected a signon for */
static char *expando_lastnotify(void *server, void *item, int *free_ret)
{
return last_notify_nick;
}
void notifylist_whois_init(void)
{
last_notify_nick = NULL;
signal_add("notifylist event whois", (SIGNAL_FUNC) event_whois);
signal_add("notifylist event whois away", (SIGNAL_FUNC) event_whois_away);
signal_add("notifylist event whois idle", (SIGNAL_FUNC) event_whois_idle);
signal_add("notifylist event whois end", (SIGNAL_FUNC) event_whois_end);
expando_create("D", expando_lastnotify);
}
void notifylist_whois_deinit(void)
{
g_free_not_null(last_notify_nick);
signal_remove("notifylist event whois", (SIGNAL_FUNC) event_whois);
signal_remove("notifylist event whois away", (SIGNAL_FUNC) event_whois_away);
signal_remove("notifylist event whois idle", (SIGNAL_FUNC) event_whois_idle);
signal_remove("notifylist event whois end", (SIGNAL_FUNC) event_whois_end);
expando_destroy("D", expando_lastnotify);
}

View file

@ -0,0 +1,356 @@
/*
notifylist.c : irssi
Copyright (C) 1999-2000 Timo Sirainen
This program 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 2 of the License, or
(at your option) any later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "module.h"
#include "modules.h"
#include "signals.h"
#include "irc.h"
#include "irc-server.h"
#include "server-redirect.h"
#include "masks.h"
#include "nicklist.h"
#include "notifylist.h"
#include "notify-setup.h"
GSList *notifies;
NOTIFYLIST_REC *notifylist_add(const char *mask, const char *ircnets,
int away_check, int idle_check_time)
{
NOTIFYLIST_REC *rec;
g_return_val_if_fail(mask != NULL, NULL);
rec = g_new0(NOTIFYLIST_REC, 1);
rec->mask = g_strdup(mask);
rec->ircnets = ircnets == NULL || *ircnets == '\0' ? NULL :
g_strsplit(ircnets, " ", -1);
rec->away_check = away_check;
rec->idle_check_time = idle_check_time;
notifylist_add_config(rec);
notifies = g_slist_append(notifies, rec);
signal_emit("notifylist new", 1, rec);
return rec;
}
static void notify_destroy(NOTIFYLIST_REC *rec)
{
if (rec->ircnets != NULL) g_strfreev(rec->ircnets);
g_free(rec->mask);
g_free(rec);
}
void notifylist_destroy_all(void)
{
g_slist_foreach(notifies, (GFunc) notify_destroy, NULL);
g_slist_free(notifies);
notifies = NULL;
}
void notifylist_remove(const char *mask)
{
NOTIFYLIST_REC *rec;
g_return_if_fail(mask != NULL);
rec = notifylist_find(mask, "*");
if (rec == NULL) return;
notifylist_remove_config(rec);
notifies = g_slist_remove(notifies, rec);
signal_emit("notifylist remove", 1, rec);
notify_destroy(rec);
}
int notify_ircnets_match(NOTIFYLIST_REC *rec, const char *ircnet)
{
char **tmp;
if (rec->ircnets == NULL) return TRUE;
if (ircnet == NULL) return FALSE;
if (strcmp(ircnet, "*") == 0) return TRUE;
for (tmp = rec->ircnets; *tmp != NULL; tmp++) {
if (g_strcasecmp(*tmp, ircnet) == 0)
return TRUE;
}
return FALSE;
}
NOTIFYLIST_REC *notifylist_find(const char *mask, const char *ircnet)
{
NOTIFYLIST_REC *best;
GSList *tmp;
int len;
best = NULL;
len = strlen(mask);
for (tmp = notifies; tmp != NULL; tmp = tmp->next) {
NOTIFYLIST_REC *rec = tmp->data;
/* check mask */
if (g_strncasecmp(rec->mask, mask, len) != 0 ||
(rec->mask[len] != '\0' && rec->mask[len] != '!')) continue;
/* check ircnet */
if (rec->ircnets == NULL) {
best = rec;
continue;
}
if (notify_ircnets_match(rec, ircnet))
return rec;
}
return best;
}
int notifylist_ison_server(IRC_SERVER_REC *server, const char *nick)
{
NOTIFY_NICK_REC *rec;
g_return_val_if_fail(nick != NULL, FALSE);
g_return_val_if_fail(server != NULL, FALSE);
rec = notify_nick_find(server, nick);
return rec != NULL && rec->host_ok && rec->away_ok && rec->idle_ok;
}
static IRC_SERVER_REC *notifylist_ison_serverlist(const char *nick, const char *taglist)
{
IRC_SERVER_REC *server;
char **list, **tmp;
list = g_strsplit(taglist, " ", -1);
server = NULL;
for (tmp = list; *tmp != NULL; tmp++) {
server = (IRC_SERVER_REC *) server_find_ircnet(*tmp);
if (server != NULL && notifylist_ison_server(server, nick))
break;
}
g_strfreev(list);
return tmp == NULL ? NULL : server;
}
IRC_SERVER_REC *notifylist_ison(const char *nick, const char *serverlist)
{
GSList *tmp;
g_return_val_if_fail(nick != NULL, FALSE);
g_return_val_if_fail(serverlist != NULL, FALSE);
if (*serverlist != '\0')
return notifylist_ison_serverlist(nick, serverlist);
/* any server.. */
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
if (notifylist_ison_server(tmp->data, nick))
return tmp->data;
}
return NULL;
}
static void notifylist_init_server(IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *rec;
g_return_if_fail(server != NULL);
rec = g_new0(MODULE_SERVER_REC,1 );
MODULE_DATA_SET(server, rec);
server_redirect_init((SERVER_REC *) server, "command ison", 1, ISON_EVENT, NULL);
}
static void notifylist_deinit_server(IRC_SERVER_REC *server)
{
MODULE_SERVER_REC *mserver;
NOTIFY_NICK_REC *rec;
g_return_if_fail(server != NULL);
mserver = MODULE_DATA(server);
while (mserver->notify_users != NULL) {
rec = mserver->notify_users->data;
mserver->notify_users = g_slist_remove(mserver->notify_users, rec);
notify_nick_destroy(rec);
}
g_free(mserver);
}
void notifylist_left(IRC_SERVER_REC *server, NOTIFY_NICK_REC *rec)
{
MODULE_SERVER_REC *mserver;
mserver = MODULE_DATA(server);
mserver->notify_users = g_slist_remove(mserver->notify_users, rec);
if (rec->host_ok && rec->away_ok) {
signal_emit("notifylist left", 6,
server, rec->nick,
rec->user, rec->host,
rec->realname, rec->awaymsg);
}
}
static void notifylist_idle_reset(IRC_SERVER_REC *server, const char *nick)
{
NOTIFY_NICK_REC *rec;
NOTIFYLIST_REC *notify;
notify = notifylist_find(nick, server->connrec->ircnet);
rec = notify_nick_find(server, nick);
if (notify != NULL && rec != NULL && notify->idle_check_time > 0 &&
time(NULL)-rec->idle_time > notify->idle_check_time) {
rec->idle_time = time(NULL);
signal_emit("notifylist unidle", 6,
server, rec->nick,
rec->user, rec->host,
rec->realname, rec->awaymsg);
}
}
static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nick)
{
NOTIFY_NICK_REC *rec;
if (*data == ':') data++; /* quit message */
rec = notify_nick_find(server, nick);
if (rec != NULL) notifylist_left(server, rec);
}
static void notifylist_check_join(IRC_SERVER_REC *server, const char *nick,
const char *userhost, const char *realname, int away)
{
NOTIFYLIST_REC *notify;
NOTIFY_NICK_REC *rec;
char *user, *host;
notify = notifylist_find(nick, server->connrec->ircnet);
if (notify == NULL) return;
rec = notify_nick_find(server, nick);
if (rec != NULL && rec->join_announced) return;
if (rec == NULL) rec = notify_nick_create(server, nick);
user = g_strdup(userhost);
host = strchr(user, '@');
if (host != NULL) *host++ = '\0'; else host = "";
if (!irc_mask_match(notify->mask, nick, user, host)) {
g_free(user);
return;
}
if (notify->away_check && away == -1) {
/* we need to know if the nick is away */
g_free(user);
return;
}
g_free_not_null(rec->user);
g_free_not_null(rec->host);
g_free_not_null(rec->realname);
rec->user = g_strdup(user);
rec->host = g_strdup(host);
rec->realname = *realname == '\0' ? NULL : g_strdup(realname);
if (away != -1) rec->away = away;
rec->host_ok = TRUE;
rec->join_announced = TRUE;
rec->idle_time = time(NULL);
signal_emit("notifylist joined", 6,
server, rec->nick, rec->user, rec->host, realname, NULL);
g_free(user);
}
static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
{
if (nick != NULL) {
notifylist_check_join(server, nick, address, "", -1);
notifylist_idle_reset(server, nick);
}
}
static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address)
{
notifylist_check_join(server, nick, address, "", -1);
}
static void sig_channel_wholist(CHANNEL_REC *channel)
{
GSList *nicks, *tmp;
nicks = nicklist_getnicks(channel);
for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
NICK_REC *rec = tmp->data;
notifylist_check_join(channel->server, rec->nick, rec->host, rec->realname, rec->gone);
}
g_slist_free(nicks);
}
void notifylist_init(void)
{
notifylist_read_config();
notifylist_commands_init();
notifylist_ison_init();
notifylist_whois_init();
signal_add("server connected", (SIGNAL_FUNC) notifylist_init_server);
signal_add("server disconnected", (SIGNAL_FUNC) notifylist_deinit_server);
signal_add("event quit", (SIGNAL_FUNC) event_quit);
signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_add("event join", (SIGNAL_FUNC) event_join);
signal_add("channel wholist", (SIGNAL_FUNC) sig_channel_wholist);
signal_add("setup reread", (SIGNAL_FUNC) notifylist_read_config);
}
void notifylist_deinit(void)
{
notifylist_commands_deinit();
notifylist_ison_deinit();
notifylist_whois_deinit();
signal_remove("server connected", (SIGNAL_FUNC) notifylist_init_server);
signal_remove("server disconnected", (SIGNAL_FUNC) notifylist_deinit_server);
signal_remove("event quit", (SIGNAL_FUNC) event_quit);
signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg);
signal_remove("event join", (SIGNAL_FUNC) event_join);
signal_remove("channel wholist", (SIGNAL_FUNC) sig_channel_wholist);
signal_remove("setup reread", (SIGNAL_FUNC) notifylist_read_config);
notifylist_destroy_all();
}

View file

@ -0,0 +1,32 @@
#ifndef __NOTIFYLIST_H
#define __NOTIFYLIST_H
typedef struct {
char *mask; /* nick part must not contain wildcards */
char **ircnets; /* if non-NULL, check only from these irc networks */
/* notify when AWAY status changes (uses /USERHOST) */
int away_check:1;
/* notify when idle time is reset and it was bigger than this
(uses /WHOIS and PRIVMSG events) */
int idle_check_time;
} NOTIFYLIST_REC;
extern GSList *notifies;
void notifylist_init(void);
void notifylist_deinit(void);
NOTIFYLIST_REC *notifylist_add(const char *mask, const char *ircnets,
int away_check, int idle_check_time);
void notifylist_remove(const char *mask);
IRC_SERVER_REC *notifylist_ison(const char *nick, const char *serverlist);
int notifylist_ison_server(IRC_SERVER_REC *server, const char *nick);
/* If `ircnet' is "*", it doesn't matter at all. */
NOTIFYLIST_REC *notifylist_find(const char *mask, const char *ircnet);
int notify_ircnets_match(NOTIFYLIST_REC *rec, const char *ircnet);
#endif