1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00
irssi/src/irc/notifylist/notifylist.c

357 lines
9.0 KiB
C
Raw Normal View History

/*
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 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_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 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();
}