1 // Commands.C -*- C++ -*-
2 // Copyright (c) 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005 Clinton Ebadi
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "StringTokenizer.H"
26 #define CHECK_CONNECTION if (!bot->serverConnection) return NotConnected
29 Commands::Action(Bot *bot, String channel, String message)
33 if (!CHANNEL(channel))
34 return NotOnChannel(channel);
36 if (message.length() == 0)
37 return InvalidParameters;
39 QUEUE->sendCTCP (channel, "ACTION", message);
45 Commands::AddUser(Bot *bot, String who, String maskChannel, int level,
46 int prot, bool aop, std::time_t expire, String password)
48 // Gah, fix this (makes bot segfault)
49 if (who.length() == 0 ||
50 maskChannel.length() == 0 ||
52 level > User::FRIEND ||
55 return InvalidParameters;
59 if (!Utils::wildcard_p(who))
61 mask = bot->getUserhost("", who);
62 if (mask.length() == 0)
67 // Aha! This was before the brace...segfault gone
68 mask = Utils::make_wildcard(mask);
70 if (bot->userList->isInUserList(mask, maskChannel))
72 return AlreadyInUserlist(mask, maskChannel);
75 bot->userList->addUser(mask, maskChannel, level, prot, aop,
84 Commands::AddServer(Bot *bot, String servername, int port)
87 return InvalidPort(port);
89 bot->serverList->addServer(new class Server(servername, port));
96 Commands::AddShit(Bot *bot, String mask, String maskChannel,
97 int level, time_t expiration, String reason)
99 if (mask.length() == 0 || maskChannel.length() == 0 ||
100 level < 0 || level > ShitEntry::SHIT_NODEBAN)
101 return InvalidParameters;
104 reason = "You're on my shitlist, lamer";
108 if (!Utils::wildcard_p(mask)) {
109 mask = bot->getUserhost("", who);
110 if (mask.length() == 0)
111 return NotFound(who);
112 mask = Utils::make_wildcard(mask);
113 if (bot->shitList->getShit(mask, maskChannel))
114 return AlreadyInShitlist(mask, maskChannel);
117 if (bot->userList->getMaxProt(mask, maskChannel) > 0)
118 return UserProtected(who, maskChannel);
120 bot->shitList->addShit(mask, maskChannel, level, expiration, reason);
127 Commands::Ban(Bot *bot, String channel, String who)
131 Channel *c = CHANNEL(channel);
134 return NotOnChannel(channel);
136 if (!bot->iAmOp(channel))
137 return NotChannelOp(channel);
141 if (!Utils::wildcard_p(who))
142 dest = bot->getUserhost(channel, who);
146 if (dest.length() == 0)
147 return NotFound(who);
149 dest = Utils::make_wildcard(dest);
152 for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
153 it != bot->userList->l.end();
155 if (m.matches((*it)->mask) &&
156 (*it)->channelMask.matches(channel) &&
157 (*it)->prot >= User::NO_BAN)
158 return UserProtected(who, channel);
160 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
161 it != c->channelBanlist.end(); ++it)
162 if (m.matches((*it)->banMask) && (*it)->banMask.getMask() != m.getMask())
163 QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
165 QUEUE->sendChannelMode(channel, "+b", dest);
171 Commands::Cycle(Bot *bot, String channel)
175 if (!CHANNEL(channel))
176 return NotOnChannel(channel);
178 QUEUE->sendPart(channel);
179 QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
185 Commands::Deban(Bot *bot, String channel, String who)
189 Channel *c = CHANNEL(channel);
192 return NotOnChannel(channel);
194 if (!bot->iAmOp(channel))
195 return NotChannelOp(channel);
199 if (!Utils::wildcard_p(who))
200 dest = bot->getUserhost(channel, who);
204 if (dest.length() == 0)
205 return UserNotFound(who, channel);
207 dest = Utils::make_wildcard(dest);
210 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
211 it != c->channelBanlist.end(); ++it)
212 if (m.matches((*it)->getMask())) {
213 // Let's see if the ban is in the shitlist
214 ShitEntry *se = bot->shitList->getShit((*it)->getMask(), channel);
215 if (!se || !se->isStillValid() ||
216 se->getShitLevel() < ShitEntry::SHIT_NODEBAN)
217 QUEUE->sendChannelMode(channel, "-b", (*it)->getMask());
224 Commands::DelServer(Bot *bot, int number)
226 if (number < 0 || number >= bot->serverList->size())
227 return InvalidServerNumber(number);
229 bot->serverList->delServer(number);
235 Commands::DelUser(Bot *bot, String who, String maskChannel)
237 if (who.length() == 0 || maskChannel.length() == 0)
238 return InvalidParameters;
242 if (!Utils::wildcard_p(who)) {
243 dest = bot->getUserhost("", who);
244 if (dest.length() == 0)
245 return NotFound(who);
246 dest = Utils::make_wildcard(who);
249 if (!bot->userList->isInUserList(dest, maskChannel))
250 return NotInUserlist(who);
252 bot->userList->removeUser(dest, maskChannel);
259 Commands::DelShit(Bot *bot, String who, String maskChannel)
261 if (who.length() == 0 || maskChannel.length() == 0)
262 return InvalidParameters;
266 if (!Utils::wildcard_p(who)) {
267 dest = bot->getUserhost("", who);
268 if (dest.length() == 0)
269 return NotFound(who);
270 dest = Utils::make_wildcard(who);
273 if (!bot->shitList->getShit(dest, maskChannel))
274 return NotInShitlist(who);
276 bot->shitList->delShit(dest, maskChannel);
282 Commands::Deop(Bot *bot, String channel, String who)
286 Channel *c = CHANNEL(channel);
289 return NotOnChannel(channel);
291 if (!bot->iAmOp(channel))
292 return NotChannelOp(channel);
294 if (!Utils::wildcard_p(who)) {
295 User *u = c->getUser(who);
297 return UserNotFound(who, channel);
298 if (!(u->mode & User::OP_MODE))
299 return UserNotOp(who, channel);
300 if (u->getProt() >= User::NO_DEOP)
301 return UserProtected(who, channel);
302 QUEUE->sendChannelMode(channel, "-o", who);
305 for (std::map<String, User *, std::less<String> >::iterator
306 it = c->channelMemory.begin();
307 it != c->channelMemory.end(); ++it) {
308 if (m.matches((*it).second->nick + "!" +
309 (*it).second->userhost) &&
310 (*it).second->getProt() < User::NO_DEOP &&
311 ((*it).second->mode & User::OP_MODE))
312 QUEUE->sendChannelMode(channel, "-o", (*it).second->nick);
320 Commands::Die(Bot *bot, String reason)
324 QUEUE->sendQuit(reason);
331 Commands::Do(Bot *bot, String command)
335 QUEUE->addLine(command, 0, 0, ServerQueueItem::OTHER);
340 Commands::Invite(Bot *bot, String channel, String who)
344 if (!bot->iAmOp(channel))
345 return NotChannelOp(channel);
347 QUEUE->sendInvite(channel, who);
353 Commands::Join(Bot *bot, String channel, String key)
357 if (!Utils::valid_channel_name_p(channel))
358 return InvalidChannel(channel);
360 // We change the key only if we are not on the channel.
361 // We don't trust the user...
362 if (!CHANNEL(channel)) {
363 if (bot->wantedChannels[channel])
364 bot->wantedChannels[channel]->key = key;
366 bot->wantedChannels[channel] = new wantedChannel("", "", key);
369 QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
375 Commands::Keep(Bot *bot, String channel, String modes)
379 Channel *c = CHANNEL(channel);
382 return NotOnChannel(channel);
384 c->keepModes = modes;
390 Commands::Kick(Bot *bot, String channel, String who, String reason)
394 Channel *c = CHANNEL(channel);
397 return NotOnChannel(channel);
399 if (!bot->iAmOp(channel))
400 return NotChannelOp(channel);
402 if (Utils::wildcard_p(who)) {
404 for (std::map<String, User *, std::less<String> >::iterator it =
405 c->channelMemory.begin();
406 it != c->channelMemory.end();
408 if (m.matches((*it).second->nick + "!" +
409 (*it).second->userhost) &&
410 (*it).second->getProt() < User::NO_KICK)
411 QUEUE->sendKick(channel, (*it).second->nick, reason);
413 User * u = c->getUser(who);
415 return UserNotFound(who, channel);
416 if (u->getProt() < User::NO_KICK)
417 QUEUE->sendKick(channel, who, reason);
419 return UserProtected(who, channel);
426 Commands::KickBan(Bot *bot, String channel, String who, String reason)
430 Message m = Commands::Ban(bot, channel, who);
432 if (m.getCode() == 0)
433 m = Commands::Kick(bot, channel, who, reason);
439 Commands::Lock(Bot *bot, String channel)
443 Channel *c = CHANNEL(channel);
446 return NotOnChannel(channel);
448 c->lockedTopic = true;
454 Commands::Mode(Bot *bot, String channel, String mode)
458 if (!CHANNEL(channel))
459 return NotOnChannel(channel);
461 if (!bot->iAmOp(channel))
462 return NotChannelOp(channel);
464 QUEUE->sendChannelMode(String("MODE ") + channel + " " + mode);
470 Commands::Msg(Bot *bot, String who, String message)
476 return EmptyAddressee;
479 if (Utils::channel_p(who))
483 return NotOnChannel (who);
492 // Send multi-line messages as seperate privmsgs
493 StringTokenizer st_message (message);
495 while (st_message.more_tokens_p ('\n'))
497 QUEUE->sendPrivmsg(who, st_message.next_token ('\n'));
504 Commands::NextServer(Bot *bot)
508 if (bot->serverList->size() == 0)
509 return EmptyServerList;
511 if (!bot->canChangeServer())
512 return CanNotChangeServer;
514 QUEUE->sendQuit("Changing server");
521 Commands::Nick(Bot *bot, String nick)
525 if (nick == "" || !Utils::valid_nickname_p(bot, nick))
526 return InvalidNick(nick);
528 bot->wantedNickName = nick;
529 QUEUE->sendNick(nick);
535 Commands::Notice(Bot *bot, String who, String message)
540 return EmptyAddressee;
542 // if (Utils::channel_p(who))
543 // return NotToChannel;
548 // Send multiple lines as multiple notices
549 StringTokenizer st_message (message);
551 while (st_message.more_tokens_p ('\n'))
553 QUEUE->sendNotice(who, st_message.next_token ('\n'));
560 Commands::Op(Bot *bot, String channel, String who)
564 Channel *c = CHANNEL(channel);
567 return NotOnChannel(channel);
569 if (!bot->iAmOp(channel))
570 return NotChannelOp(channel);
572 if (Utils::wildcard_p(who))
573 return MassOpNotAllowed;
575 User *u = c->getUser(who);
577 return UserNotFound(who, channel);
579 ShitEntry *se = bot->shitList->getShit(who, channel);
580 if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP)
581 return UserOnShitList(who);
583 QUEUE->sendChannelMode(channel, "+o", who);
590 Commands::Part(Bot *bot, String channel)
594 if (!CHANNEL(channel))
595 return NotOnChannel(channel);
597 wantedChannel *w = bot->wantedChannels[channel];
598 bot->wantedChannels.erase(channel);
600 QUEUE->sendPart(channel);
606 Commands::Reconnect(Bot *bot)
610 if (!bot->canChangeServer())
611 return CanNotChangeServer;
613 QUEUE->sendQuit("Reconnecting");
620 Commands::Say(Bot *bot, String channel, String message)
622 return Commands::Msg (bot, channel, message);
627 Commands::Server(Bot *bot, int number)
631 if (number < 0 || number >= bot->serverList->size())
632 return InvalidServerNumber(number);
634 if (!bot->canChangeServer())
635 return CanNotChangeServer;
637 QUEUE->sendQuit("Changing server");
639 bot->connect(number);
645 Commands::SetFloodRate(Bot *bot, unsigned int num_messages)
647 if (num_messages > 0)
649 bot->MAX_MESSAGES = num_messages;
652 return InvalidParameters;
656 Commands::SetVersion(Bot *bot, String str)
658 if (str.length() == 0)
659 return InvalidParameters;
661 bot->versionString = str;
666 Commands::TBan(Bot *bot, String channel, String who, int seconds)
670 Channel *c = CHANNEL(channel);
673 // Make sure all of the inputs are valid
676 return NotOnChannel(channel);
679 if (!bot->iAmOp(channel))
681 return NotChannelOp(channel);
686 return InvalidTime(seconds);
690 if (!Utils::wildcard_p(who))
692 dest = bot->getUserhost(channel, who);
699 if (dest.length() == 0)
701 return UserNotFound(who, channel);
705 dest = Utils::make_wildcard(dest);
708 // Make sure the user isn't protected from bans
709 for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
710 it != bot->userList->l.end();
713 if (m.matches((*it)->mask) &&
714 (*it)->channelMask.matches(channel) &&
715 (*it)->prot >= User::NO_BAN)
717 return UserProtected(who, channel);
721 // Clear existing bans on the user
722 for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
723 it != c->channelBanlist.end(); ++it)
725 if (m.matches((*it)->banMask))
727 QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
732 CHANNEL(channel)->addBan(dest, seconds);
733 QUEUE->sendChannelMode(channel, "+b", dest);
734 bot->todoList->addDeban(channel, dest, seconds);
741 Commands::TKBan(Bot *bot, String channel, String who, int seconds, String reason)
745 Message m = Commands::TBan(bot, channel, who, seconds);
747 if (m.getCode() == 0)
748 m = Commands::Kick(bot, channel, who, reason);
755 Commands::Topic(Bot *bot, String channel, String topic)
759 Channel *c = CHANNEL(channel);
762 return NotOnChannel(channel);
764 if (!bot->iAmOp(channel) && !(c->channelMode & Channel::TOPIC_RESTRICTED))
765 return CanNotChangeTopic(channel);
768 return TopicLocked(channel);
770 QUEUE->sendTopic(channel, topic);
777 Commands::Unlock(Bot *bot, String channel)
781 Channel *c = CHANNEL(channel);
784 return NotOnChannel(channel);
786 c->lockedTopic = false;