diff options
Diffstat (limited to 'src/irc/bot/bot-events.c')
-rw-r--r-- | src/irc/bot/bot-events.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/irc/bot/bot-events.c b/src/irc/bot/bot-events.c new file mode 100644 index 00000000..ebbe0660 --- /dev/null +++ b/src/irc/bot/bot-events.c @@ -0,0 +1,199 @@ +/* + 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-server.h" +#include "channels.h" +#include "nicklist.h" +#include "modes.h" +#include "netsplit.h" + +#include "bot-users.h" + +static int get_flags(USER_REC *user, 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(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(CHANNEL_REC *channel, const char *mode, + const char *nick, const char *address) +{ + NICK_REC *nickrec, *splitnick; + 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(modestr != 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; + } + + 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(*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, 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(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) +{ + 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 = 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); +} |