/* bot-events.c : IRC bot plugin for irssi Copyright (C) 1999 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 "irc.h" #include "irc-servers.h" #include "irc-channels.h" #include "nicklist.h" #include "modes.h" #include "netsplit.h" #include "bot-users.h" static int get_flags(USER_REC *user, IRC_CHANNEL_REC *channel) { USER_CHAN_REC *userchan; g_return_val_if_fail(user != NULL, 0); g_return_val_if_fail(channel != NULL, 0); userchan = g_hash_table_lookup(user->channels, channel->name); return (user->flags | (userchan == NULL ? 0 : userchan->flags)) & (~user->not_flags); } static void event_massjoin(IRC_CHANNEL_REC *channel, GSList *users) { USER_REC *user; USER_CHAN_REC *userchan; NICK_REC *nick; GString *modestr, *nickstr; int flags; g_return_if_fail(channel != NULL); g_return_if_fail(users != NULL); modestr = g_string_new(NULL); nickstr = g_string_new(NULL); for (; users != NULL; users = users->next) { user = users->data; userchan = g_hash_table_lookup(user->channels, channel->name); nick = userchan->nickrec; flags = get_flags(user, channel); if (!nick->op && (flags & USER_AUTO_OP)) { g_string_sprintfa(modestr, "+o"); g_string_sprintfa(nickstr, "%s,", nick->nick); } if (!nick->voice && !nick->op && (flags & USER_AUTO_VOICE)) { g_string_sprintfa(modestr, "+v"); g_string_sprintfa(nickstr, "%s,", nick->nick); } } if (nickstr->len > 0) { g_string_truncate(nickstr, nickstr->len-1); g_string_sprintfa(modestr, " %s", nickstr->str); channel_set_mode(channel->server, channel->name, modestr->str); } g_string_free(modestr, TRUE); g_string_free(nickstr, TRUE); } /* Parse channel mode string */ static void parse_channel_mode(IRC_CHANNEL_REC *channel, const char *mode, const char *nick, const char *address) { NETSPLIT_CHAN_REC *splitnick; NICK_REC *nickrec; USER_REC *user; GString *str; char *ptr, *curmode, type, *dup, *modestr; int flags; g_return_if_fail(channel != NULL); g_return_if_fail(nick != NULL); g_return_if_fail(mode != NULL); user = botuser_find(nick, address); flags = user == NULL ? 0 : get_flags(user, channel); if (!channel->chanop || (flags & USER_MASTER) || g_strcasecmp(nick, channel->server->nick) == 0) { /* can't do anything or we/master did mode change, don't bother checking what */ return; } /* check if unwanted people got ops */ str = g_string_new(NULL); dup = modestr = g_strdup(mode); type = '+'; curmode = cmd_get_param(&modestr); for (; *curmode != '\0'; curmode++) { if (*curmode == '+' || *curmode == '-') { type = *curmode; continue; } if (!HAS_MODE_ARG(type, *curmode)) ptr = NULL; else { ptr = cmd_get_param(&modestr); if (*ptr == '\0') continue; } if (*curmode != 'o') continue; if (type == '-' && strcmp(channel->server->nick, ptr) == 0) { /* we aren't chanop anymore .. */ g_string_truncate(str, 0); break; } if (type != '+') continue; /* check that op is valid */ nickrec = nicklist_find(CHANNEL(channel), ptr); if (nickrec == NULL || nickrec->host == NULL) continue; user = botuser_find(ptr, nickrec->host); flags = user == NULL ? 0 : get_flags(user, channel); if (flags & USER_OP) continue; if (address == NULL) { /* server opped, check if user was opped before netsplit. */ splitnick = netsplit_find_channel(channel->server, nickrec->nick, nickrec->host, channel->name); if (splitnick != NULL && splitnick->op) continue; } /* this one isn't supposed to get ops! */ g_string_sprintfa(str, "%s ", ptr); } g_free(dup); if (str->len != 0) signal_emit("command deop", 3, str->str, channel->server, channel); g_string_free(str, TRUE); } static void event_mode(IRC_SERVER_REC *server, const char *data, const char *nick, const char *address) { IRC_CHANNEL_REC *chanrec; char *params, *channel, *mode; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode); if (ischannel(*channel)) { /* channel mode change */ chanrec = irc_channel_find(server, channel); if (chanrec != NULL) parse_channel_mode(chanrec, mode, nick, address); } g_free(params); } void bot_events_init(void) { signal_add_last("bot massjoin", (SIGNAL_FUNC) event_massjoin); signal_add("event mode", (SIGNAL_FUNC) event_mode); } void bot_events_deinit(void) { signal_remove("bot massjoin", (SIGNAL_FUNC) event_massjoin); signal_remove("event mode", (SIGNAL_FUNC) event_mode); }