2000-04-26 04:03:38 -04:00
|
|
|
/*
|
|
|
|
massjoin.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"
|
2000-05-04 06:32:42 -04:00
|
|
|
#include "settings.h"
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-08-26 11:39:44 -04:00
|
|
|
#include "irc-servers.h"
|
|
|
|
#include "irc-channels.h"
|
2001-02-02 17:10:20 -05:00
|
|
|
#include "irc-nicklist.h"
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
static int massjoin_tag;
|
2000-05-04 06:32:42 -04:00
|
|
|
static int massjoin_max_joins;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
/* Massjoin support - really useful when trying to do things (like op/deop)
|
|
|
|
to people after netjoins. It sends
|
|
|
|
"massjoin #channel nick!user@host nick2!user@host ..." signals */
|
2000-12-05 16:12:52 -05:00
|
|
|
static void event_join(IRC_SERVER_REC *server, const char *data,
|
2000-08-26 11:39:44 -04:00
|
|
|
const char *nick, const char *address)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
char *params, *channel, *ptr;
|
2000-08-26 11:39:44 -04:00
|
|
|
IRC_CHANNEL_REC *chanrec;
|
2000-04-26 04:03:38 -04:00
|
|
|
NICK_REC *nickrec;
|
|
|
|
GSList *nicks, *tmp;
|
|
|
|
|
|
|
|
g_return_if_fail(data != NULL);
|
|
|
|
|
|
|
|
if (g_strcasecmp(nick, server->nick) == 0) {
|
|
|
|
/* You joined, no need to do anything here */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
params = event_get_params(data, 1, &channel);
|
|
|
|
ptr = strchr(channel, 7); /* ^G does something weird.. */
|
|
|
|
if (ptr != NULL) *ptr = '\0';
|
|
|
|
|
|
|
|
/* find channel */
|
2000-08-26 11:39:44 -04:00
|
|
|
chanrec = irc_channel_find(server, channel);
|
2000-04-26 04:03:38 -04:00
|
|
|
g_free(params);
|
|
|
|
if (chanrec == NULL) return;
|
|
|
|
|
2001-12-21 21:28:22 -05:00
|
|
|
/* check that the nick isn't already in nicklist. seems to happen
|
|
|
|
sometimes (server desyncs or something?) */
|
|
|
|
nickrec = nicklist_find(CHANNEL(chanrec), nick);
|
|
|
|
if (nickrec != NULL) {
|
|
|
|
/* destroy the old record */
|
|
|
|
nicklist_remove(CHANNEL(chanrec), nickrec);
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
/* add user to nicklist */
|
2001-12-09 12:13:48 -05:00
|
|
|
nickrec = irc_nicklist_insert(chanrec, nick, FALSE, FALSE, FALSE, TRUE);
|
2001-01-20 19:49:52 -05:00
|
|
|
nicklist_set_host(CHANNEL(chanrec), nickrec, address);
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
if (chanrec->massjoins == 0) {
|
|
|
|
/* no nicks waiting in massjoin queue */
|
|
|
|
chanrec->massjoin_start = time(NULL);
|
|
|
|
chanrec->last_massjoins = 0;
|
|
|
|
}
|
|
|
|
|
2000-07-02 12:24:28 -04:00
|
|
|
if (nickrec->realname == NULL) {
|
|
|
|
/* Check if user is already in some other channel,
|
|
|
|
get the realname and other stuff from there */
|
2000-08-26 11:39:44 -04:00
|
|
|
nicks = nicklist_get_same(SERVER(server), nick);
|
2000-07-02 12:24:28 -04:00
|
|
|
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
|
|
|
|
NICK_REC *rec = tmp->next->data;
|
|
|
|
|
|
|
|
if (rec->realname != NULL) {
|
|
|
|
nickrec->last_check = rec->last_check;
|
|
|
|
nickrec->realname = g_strdup(rec->realname);
|
|
|
|
nickrec->gone = rec->gone;
|
|
|
|
break;
|
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
2000-07-02 12:24:28 -04:00
|
|
|
g_slist_free(nicks);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
chanrec->massjoins++;
|
|
|
|
}
|
|
|
|
|
2000-12-05 16:12:52 -05:00
|
|
|
static void event_part(IRC_SERVER_REC *server, const char *data,
|
2000-08-26 11:39:44 -04:00
|
|
|
const char *nick, const char *addr)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
char *params, *channel, *reason;
|
2000-08-26 11:39:44 -04:00
|
|
|
IRC_CHANNEL_REC *chanrec;
|
2000-04-26 04:03:38 -04:00
|
|
|
NICK_REC *nickrec;
|
|
|
|
|
|
|
|
g_return_if_fail(data != NULL);
|
|
|
|
|
|
|
|
if (g_strcasecmp(nick, server->nick) == 0) {
|
|
|
|
/* you left channel, no need to do anything here */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
params = event_get_params(data, 2, &channel, &reason);
|
|
|
|
|
|
|
|
/* find channel */
|
2000-08-26 11:39:44 -04:00
|
|
|
chanrec = irc_channel_find(server, channel);
|
2000-04-26 04:03:38 -04:00
|
|
|
if (chanrec == NULL) {
|
|
|
|
g_free(params);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* remove user from nicklist */
|
2000-08-26 11:39:44 -04:00
|
|
|
nickrec = nicklist_find(CHANNEL(chanrec), nick);
|
2000-04-26 04:03:38 -04:00
|
|
|
if (nickrec != NULL) {
|
|
|
|
if (nickrec->send_massjoin) {
|
|
|
|
/* quick join/part after which it's useless to send
|
|
|
|
nick in massjoin */
|
|
|
|
chanrec->massjoins--;
|
|
|
|
}
|
2000-08-26 11:39:44 -04:00
|
|
|
nicklist_remove(CHANNEL(chanrec), nickrec);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
g_free(params);
|
|
|
|
}
|
|
|
|
|
2000-12-05 16:12:52 -05:00
|
|
|
static void event_quit(IRC_SERVER_REC *server, const char *data,
|
2000-08-26 11:39:44 -04:00
|
|
|
const char *nick)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-08-26 11:39:44 -04:00
|
|
|
IRC_CHANNEL_REC *channel;
|
2000-04-26 04:03:38 -04:00
|
|
|
NICK_REC *nickrec;
|
|
|
|
GSList *nicks, *tmp;
|
|
|
|
|
|
|
|
g_return_if_fail(data != NULL);
|
|
|
|
|
|
|
|
if (g_strcasecmp(nick, server->nick) == 0) {
|
|
|
|
/* you quit, don't do anything here */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove nick from all channels */
|
2000-08-26 11:39:44 -04:00
|
|
|
nicks = nicklist_get_same(SERVER(server), nick);
|
2000-04-26 04:03:38 -04:00
|
|
|
for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) {
|
|
|
|
channel = tmp->data;
|
|
|
|
nickrec = tmp->next->data;
|
|
|
|
|
|
|
|
if (nickrec->send_massjoin) {
|
|
|
|
/* quick join/quit after which it's useless to
|
|
|
|
send nick in massjoin */
|
|
|
|
channel->massjoins--;
|
|
|
|
}
|
2000-08-26 11:39:44 -04:00
|
|
|
nicklist_remove(CHANNEL(channel), nickrec);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
g_slist_free(nicks);
|
|
|
|
}
|
|
|
|
|
2000-12-05 16:12:52 -05:00
|
|
|
static void event_kick(IRC_SERVER_REC *server, const char *data)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
char *params, *channel, *nick, *reason;
|
2000-08-26 11:39:44 -04:00
|
|
|
IRC_CHANNEL_REC *chanrec;
|
2000-04-26 04:03:38 -04:00
|
|
|
NICK_REC *nickrec;
|
|
|
|
|
|
|
|
g_return_if_fail(data != NULL);
|
|
|
|
|
|
|
|
params = event_get_params(data, 3, &channel, &nick, &reason);
|
|
|
|
|
|
|
|
if (g_strcasecmp(nick, server->nick) == 0) {
|
|
|
|
/* you were kicked, no need to do anything */
|
|
|
|
g_free(params);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove user from nicklist */
|
2000-08-26 11:39:44 -04:00
|
|
|
chanrec = irc_channel_find(server, channel);
|
|
|
|
nickrec = chanrec == NULL ? NULL :
|
|
|
|
nicklist_find(CHANNEL(chanrec), nick);
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
if (chanrec != NULL && nickrec != NULL) {
|
|
|
|
if (nickrec->send_massjoin) {
|
|
|
|
/* quick join/kick after which it's useless to
|
|
|
|
send nick in massjoin */
|
|
|
|
chanrec->massjoins--;
|
|
|
|
}
|
2000-08-26 11:39:44 -04:00
|
|
|
nicklist_remove(CHANNEL(chanrec), nickrec);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free(params);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void massjoin_send_hash(gpointer key, NICK_REC *nick, GSList **list)
|
|
|
|
{
|
|
|
|
if (nick->send_massjoin) {
|
|
|
|
nick->send_massjoin = FALSE;
|
|
|
|
*list = g_slist_append(*list, nick);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send channel's massjoin list signal */
|
2000-08-26 11:39:44 -04:00
|
|
|
static void massjoin_send(IRC_CHANNEL_REC *channel)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
list = NULL;
|
|
|
|
g_hash_table_foreach(channel->nicks, (GHFunc) massjoin_send_hash, &list);
|
|
|
|
|
|
|
|
channel->massjoins = 0;
|
|
|
|
signal_emit("massjoin", 2, channel, list);
|
|
|
|
g_slist_free(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void server_check_massjoins(IRC_SERVER_REC *server, time_t max)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
|
|
|
|
/* Scan all channels through for massjoins */
|
|
|
|
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
|
2000-08-26 11:39:44 -04:00
|
|
|
IRC_CHANNEL_REC *rec = tmp->data;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-08-26 11:39:44 -04:00
|
|
|
if (!IS_IRC_CHANNEL(rec) || rec->massjoins <= 0)
|
2000-04-26 04:03:38 -04:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (rec->massjoin_start < max || /* We've waited long enough */
|
2000-05-04 06:32:42 -04:00
|
|
|
rec->massjoins-massjoin_max_joins < rec->last_massjoins) { /* Less than x joins since last check */
|
2000-04-26 04:03:38 -04:00
|
|
|
/* send them */
|
|
|
|
massjoin_send(rec);
|
|
|
|
} else {
|
|
|
|
/* Wait for some more.. */
|
|
|
|
rec->last_massjoins = rec->massjoins;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sig_massjoin_timeout(void)
|
|
|
|
{
|
|
|
|
GSList *tmp;
|
|
|
|
time_t max;
|
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
max = time(NULL)-settings_get_int("massjoin_max_wait");
|
2000-07-15 09:08:39 -04:00
|
|
|
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
|
|
|
|
IRC_SERVER_REC *server = tmp->data;
|
|
|
|
|
2000-08-26 11:39:44 -04:00
|
|
|
if (IS_IRC_SERVER(server))
|
2000-07-15 09:08:39 -04:00
|
|
|
server_check_massjoins(server, max);
|
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
static void read_settings(void)
|
|
|
|
{
|
|
|
|
massjoin_max_joins = settings_get_int("massjoin_max_joins");
|
|
|
|
}
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
void massjoin_init(void)
|
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
settings_add_int("misc", "massjoin_max_wait", 5000);
|
|
|
|
settings_add_int("misc", "massjoin_max_joins", 3);
|
2000-04-26 04:03:38 -04:00
|
|
|
massjoin_tag = g_timeout_add(1000, (GSourceFunc) sig_massjoin_timeout, NULL);
|
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
read_settings();
|
2000-04-26 04:03:38 -04:00
|
|
|
signal_add("event join", (SIGNAL_FUNC) event_join);
|
|
|
|
signal_add("event part", (SIGNAL_FUNC) event_part);
|
|
|
|
signal_add("event kick", (SIGNAL_FUNC) event_kick);
|
|
|
|
signal_add("event quit", (SIGNAL_FUNC) event_quit);
|
2000-05-04 06:32:42 -04:00
|
|
|
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void massjoin_deinit(void)
|
|
|
|
{
|
|
|
|
g_source_remove(massjoin_tag);
|
|
|
|
|
|
|
|
signal_remove("event join", (SIGNAL_FUNC) event_join);
|
|
|
|
signal_remove("event part", (SIGNAL_FUNC) event_part);
|
|
|
|
signal_remove("event kick", (SIGNAL_FUNC) event_kick);
|
|
|
|
signal_remove("event quit", (SIGNAL_FUNC) event_quit);
|
2000-05-04 06:32:42 -04:00
|
|
|
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|