1
0
mirror of https://github.com/irssi/irssi.git synced 2025-02-02 15:08:01 -05:00
irssi/src/irc/notifylist/notify-ison.c
Timo Sirainen bd6fe052bc Added time, size and level setting types. Breaks some settings - I'll add
automatic converter to these settings later. Meanwhile you CVS users can
fix your config files yourself :)

Time settings allow using "days", "hours", "minutes", "seconds" and
"milliseconds" or several of their abbreviations. For example "5d 4h
5msecs".

Size settings allow using "gbytes", "mbytes", "kbytes" and "bytes" or their
abbrevations. For example "5MB".

Level settings are currently handled pretty much the way they were before.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3080 dbcabf3a-b0e7-0310-adc4-f8d773084564
2002-12-28 17:54:13 +00:00

349 lines
8.3 KiB
C

/*
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-servers.h"
#include "servers-redirect.h"
#include "notifylist.h"
#define DEFAULT_NOTIFY_CHECK_TIME "1min"
#define DEFAULT_NOTIFY_WHOIS_TIME "5min"
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 void ison_send(IRC_SERVER_REC *server, GString *cmd)
{
MODULE_SERVER_REC *mserver;
mserver = MODULE_DATA(server);
mserver->ison_count++;
g_string_truncate(cmd, cmd->len-1);
g_string_prepend(cmd, "ISON :");
server_redirect_event(server, "ison", 1, NULL, -1, NULL,
"event 303", "notifylist event", NULL);
irc_send_cmd(server, cmd->str);
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)
{
MODULE_SERVER_REC *mserver;
GSList *tmp;
GString *cmd;
char *nick, *ptr;
int len;
g_return_if_fail(server != NULL);
if (!IS_IRC_SERVER(server))
return;
mserver = MODULE_DATA(server);
if (mserver->ison_count > 0) {
/* 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 (!notifylist_ircnets_match(rec, server->connrec->chatnet))
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, const char *nicks,
const char *whois_request)
{
char *p, *str;
/* "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, "whois", 1, str, TRUE,
"notifylist event whois end",
"event 318", "notifylist event whois end",
"event 311", "notifylist event whois",
"event 301", "notifylist event whois away",
"event 317", "notifylist event whois idle",
"", "event empty", NULL);
g_free(str);
irc_send_cmdv(server, "WHOIS %s", whois_request);
}
static void whois_send_server(IRC_SERVER_REC *server, char *nick)
{
char *str;
str = g_strdup_printf("%s %s", nick, nick);
whois_send(server, nick, 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, str->str);
count = 0;
}
}
if (str->len > 0) {
g_string_truncate(str, str->len-1);
whois_send(server, str->str, 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->chatnet);
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);
}
}
static void event_ison(IRC_SERVER_REC *server, const char *data)
{
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 (--mserver->ison_count > 0) {
/* 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(settings_get_time("notify_check_time"),
(GSourceFunc) notifylist_timeout_func, NULL);
notify_whois_time = settings_get_time("notify_whois_time")/1000;
}
void notifylist_ison_init(void)
{
settings_add_time("misc", "notify_check_time", DEFAULT_NOTIFY_CHECK_TIME);
settings_add_time("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);
}