/* 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-channels.h" #include "servers-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 notifylist_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 (notifylist_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_chatnet(*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->chatnet); rec = notify_nick_find(server, nick); if (notify != NULL && rec != NULL && notify->idle_check_time > 0 && rec->idle_time > notify->idle_check_time) { rec->idle_time = 0; 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->chatnet); 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 (!mask_match(SERVER(server), 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 = 0; 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(IRC_CHANNEL_REC *channel) { GSList *nicks, *tmp; nicks = nicklist_getnicks(CHANNEL(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 irc_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 irc_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(); }