// Commands.C -*- C++ -*-
// Copyright (c) 1998 Etienne BERNARD
-// Copyright (C) 2002 Clinton Ebadi
+// Copyright (C) 2002,2005 Clinton Ebadi
// 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
// 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.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301, USA.
+#include "Commands.H"
+
+#include <functional>
+
+#include "BanEntry.H"
+#include "Bot.H"
+#include "ChannelList.H"
#include "Macros.H"
#include "Message.H"
-#include "Commands.H"
+#include "Server.H"
+#include "ServerConnection.H"
+#include "ServerList.H"
+#include "ServerQueueItem.H"
+#include "ShitEntry.H"
+#include "ShitList.H"
+#include "StringTokenizer.H"
+#include "User.H"
+#include "UserList.H"
#include "Utils.H"
-#define Ok (Message(0, ""))
-#define NotOnChannel(c) (Message(-1, String("I am not on channel ") + (c)))
-#define NotChannelOp(c) (Message(-2, String("I am not channel op on ") + (c)))
-#define UserNotFound(w, c) (Message(-3, (w) + " is not on channel " + (c)))
-#define UserNotOp(w, c) (Message(-4, (w) + " is not channel op on " + (c)))
-#define UserProtected(w, c) (Message(-5, (w) + " is protected on " + (c)))
-#define InvalidNick(n) (Message(-6, (n) + " is not a valid nickname"))
-#define InvalidChannel(c) (Message(-7, (c) + " is not a valid channel name"))
-#define MassOpNotAllowed (Message(-8, "Mass op is not allowed."))
-#define UserOnShitList(w) (Message(-9, String("User ") + w + " is on my shitlist"))
-#define CanNotChangeTopic(c) (Message(-10, String("I can not change topic on ") + (c)))
-#define TopicLocked(c) (Message(-11, String("Topic is locked on ") + (c)))
-#define InvalidPort(p) (Message(-12, String((long)(p)) + " is an invalid port number"))
-#define InvalidTime(t) (Message(-13, String((long)(t)) + " is an invalid time"))
-#define CanNotChangeServer (Message(-14, "I cannot change server without loosing op on one of my channels"))
-#define EmptyServerList (Message(-15, "Server list is empty"))
-#define InvalidServerNumber(n) (Message(-16, String((long)(n)) + " is an invalid server number"))
-#define InvalidParameters (Message(-17, "Invalid parameters"))
-#define NotFound(w) (Message(-18, String("I can not find ") + (w)));
-#define NotInUserlist(w) (Message(-19, (w) + " is not in my userlist"))
-#define NotInShitlist(w) (Message(-20, (w) + " is not in my shitlist"))
-#define AlreadyInUserlist(m, mc) (Message(-21, (m) + " is already in userlist on channel(s) " + (mc)))
-#define AlreadyInShitlist(m, mc) (Message(-22, (m) + " is already in shitlist on channel(s) " + (mc)))
-#define EmptyMessage (Message(-23, "Can not send an empty message"))
-#define EmptyAddressee (Message(-24, "Can not send to nobody"))
-#define NotToChannel (Message(-25, "Can not send to a channel. Use \"say\" instead."))
-#define NotConnected (Message(-26, "Not connected."))
+#ifdef USESCRIPTS
+#include "BotInterp.H"
+#endif
+
#define CHECK_CONNECTION if (!bot->serverConnection) return NotConnected
if (message.length() == 0)
return InvalidParameters;
- QUEUE->sendPrivmsg(channel, String("\001ACTION ") +
- message + "\001");
+ Commands::CTCP (bot, channel, "ACTION", message);
return Ok;
}
String mask;
- if (!Utils::isWildcard(who))
+ if (!Utils::wildcard_p(who))
{
- mask = bot->getUserhost("", who);
- if (mask.length() == 0)
- return NotFound(who);
- }
+ mask = bot->getUserhost("", who);
+ if (mask.length() == 0)
+ {
+ return NotFound(who);
+ }
+ }
// Aha! This was before the brace...segfault gone
- mask = Utils::makeWildcard(mask);
+ mask = Utils::make_wildcard(mask);
if (bot->userList->isInUserList(mask, maskChannel))
- return AlreadyInUserlist(mask, maskChannel);
+ {
+ return AlreadyInUserlist(mask, maskChannel);
+ }
bot->userList->addUser(mask, maskChannel, level, prot, aop,
expire, password);
String who = mask;
- if (!Utils::isWildcard(mask)) {
+ if (!Utils::wildcard_p(mask)) {
mask = bot->getUserhost("", who);
if (mask.length() == 0)
return NotFound(who);
- mask = Utils::makeWildcard(mask);
+ mask = Utils::make_wildcard(mask);
if (bot->shitList->getShit(mask, maskChannel))
return AlreadyInShitlist(mask, maskChannel);
}
String dest;
- if (!Utils::isWildcard(who))
+ if (!Utils::wildcard_p(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
if (dest.length() == 0)
return NotFound(who);
- dest = Utils::makeWildcard(dest);
+ dest = Utils::make_wildcard(dest);
Mask m(dest);
for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
(*it)->channelMask.matches(channel) &&
(*it)->prot >= User::NO_BAN)
return UserProtected(who, channel);
-
- for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
- it != c->channelBanlist.end(); ++it)
- if (m.matches((*it)->banMask) && (*it)->banMask.getMask() != m.getMask())
- QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
- QUEUE->sendChannelMode(channel, "+b", dest);
+ c->delBan (m);
+ c->addBan (m, -1);
+
+ return Ok;
+}
+
+Message
+Commands::CTCP (Bot *bot, std::string target, std::string command,
+ std::string message)
+{
+ CHECK_CONNECTION;
+
+ if (target == "")
+ {
+ return EmptyAddressee;
+ }
+
+ if (command == "")
+ {
+ return InvalidParameters;
+ }
+
+ if (message == "")
+ {
+ return EmptyMessage;
+ }
+
+ if (Utils::channel_p (target) && !CHANNEL (target))
+ {
+ return NotOnChannel (target);
+ }
+
+
+ // Send multi-line messages as seperate privmsgs
+ StringTokenizer st_message (message);
+
+ while (st_message.more_tokens_p ('\n'))
+ {
+ QUEUE->sendCTCP (target, command, st_message.next_token ('\n'));
+ }
return Ok;
}
+Message
+Commands::CTCPReply (Bot *bot, std::string target, std::string command,
+ std::string message)
+{
+ CHECK_CONNECTION;
+
+ if (target == "")
+ {
+ return EmptyAddressee;
+ }
+
+ if (command == "")
+ {
+ return InvalidParameters;
+ }
+
+ if (message == "")
+ {
+ return EmptyMessage;
+ }
+
+ // CTCP-REPLY cannot go to a channel
+ if (Utils::channel_p (target))
+ {
+ return NotToChannel;
+ }
+
+
+ // Send multi-line messages as seperate privmsgs
+ StringTokenizer st_message (message);
+
+ while (st_message.more_tokens_p ('\n'))
+ {
+ QUEUE->sendCTCPReply (target, command, st_message.next_token ('\n'));
+ }
+
+ return Ok;
+}
+
+
Message
Commands::Cycle(Bot *bot, String channel)
{
String dest;
- if (!Utils::isWildcard(who))
+ if (!Utils::wildcard_p(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
if (dest.length() == 0)
return UserNotFound(who, channel);
- dest = Utils::makeWildcard(dest);
+ dest = Utils::make_wildcard(dest);
Mask m(dest);
+
+ BanList::MatchList matches = c->channelBanlist.find_matches (m);
- for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
- it != c->channelBanlist.end(); ++it)
- if (m.matches((*it)->getMask())) {
- // Let's see if the ban is in the shitlist
- ShitEntry *se = bot->shitList->getShit((*it)->getMask(), channel);
- if (!se || !se->isStillValid() ||
- se->getShitLevel() < ShitEntry::SHIT_NODEBAN)
- QUEUE->sendChannelMode(channel, "-b", (*it)->getMask());
- }
+ for (BanList::MatchList::iterator it = matches.begin ();
+ it != matches.end();
+ ++it)
+ if (m.matches(*it))
+ {
+ // Let's see if the ban is in the shitlist
+ ShitEntry *se = bot->shitList->getShit(it->getMask(), channel);
+ if (!se || !se->isStillValid() ||
+ se->getShitLevel() < ShitEntry::SHIT_NODEBAN)
+ c->delBan (m);
+ }
return Ok;
}
String dest;
- if (!Utils::isWildcard(who)) {
+ if (!Utils::wildcard_p(who)) {
dest = bot->getUserhost("", who);
if (dest.length() == 0)
return NotFound(who);
- dest = Utils::makeWildcard(who);
+ dest = Utils::make_wildcard(who);
}
if (!bot->userList->isInUserList(dest, maskChannel))
String dest;
- if (!Utils::isWildcard(who)) {
+ if (!Utils::wildcard_p(who)) {
dest = bot->getUserhost("", who);
if (dest.length() == 0)
return NotFound(who);
- dest = Utils::makeWildcard(who);
+ dest = Utils::make_wildcard(who);
}
if (!bot->shitList->getShit(dest, maskChannel))
return Ok;
}
+Commands::deop_wildcard::deop_wildcard
+(Bot *b, Mask &m, String &c)
+ : bot (b), mask (m), channel (c)
+{ }
+
+void
+Commands::deop_wildcard::operator() (const User &user)
+{
+ if (mask.matches(user.nick + "!" + user.userhost)
+ && user.getProt() < User::NO_DEOP
+ && (user.mode & User::OP_MODE))
+ QUEUE->sendChannelMode(channel, "-o", user.nick);
+}
+
Message
Commands::Deop(Bot *bot, String channel, String who)
{
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
- if (!Utils::isWildcard(who)) {
- User *u = c->getUser(who);
- if (!u)
- return UserNotFound(who, channel);
- if (!(u->mode & User::OP_MODE))
- return UserNotOp(who, channel);
- if (u->getProt() >= User::NO_DEOP)
- return UserProtected(who, channel);
- QUEUE->sendChannelMode(channel, "-o", who);
+ if (!Utils::wildcard_p(who)) {
+ try
+ {
+ User u = c->getUser(who);
+
+ if (!(u.mode & User::OP_MODE))
+ return UserNotOp(who, channel);
+ if (u.getProt() >= User::NO_DEOP)
+ return UserProtected(who, channel);
+ QUEUE->sendChannelMode(channel, "-o", who);
+ }
+ catch (const ChannelUserList::user_not_found &e)
+ {
+ return UserNotFound(e.name, channel);
+ }
} else {
- Mask m(who);
- for (std::map<String, User *, std::less<String> >::iterator
- it = c->channelMemory.begin();
- it != c->channelMemory.end(); ++it) {
- if (m.matches((*it).second->nick + "!" +
- (*it).second->userhost) &&
- (*it).second->getProt() < User::NO_DEOP &&
- ((*it).second->mode & User::OP_MODE))
- QUEUE->sendChannelMode(channel, "-o", (*it).second->nick);
- }
+ Mask m (who);
+ deop_wildcard f (bot, m, channel);
+ c->for_each_channel_users (f);
}
-
return Ok;
}
{
CHECK_CONNECTION;
- if (!Utils::isValidChannelName(channel))
+ if (!Utils::valid_channel_name_p(channel))
return InvalidChannel(channel);
// We change the key only if we are not on the channel.
// We don't trust the user...
if (!CHANNEL(channel)) {
if (bot->wantedChannels[channel])
- bot->wantedChannels[channel]->key = key;
+ bot->wantedChannels[channel]->key = static_cast<std::string> (key);
else {
bot->wantedChannels[channel] = new wantedChannel("", "", key);
}
return Ok;
}
+Commands::kick_wildcard::kick_wildcard
+(Bot *b, Mask &m, String &c, String &r)
+ : bot (b), mask (m), channel (c), reason (r)
+{ }
+
+void
+Commands::kick_wildcard::operator() (const User &user)
+{
+ if (mask.matches(user.nick + "!" + user.userhost) &&
+ user.getProt() < User::NO_KICK)
+ QUEUE->sendKick(channel, user.nick, reason);
+}
+
Message
Commands::Kick(Bot *bot, String channel, String who, String reason)
{
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
- if (Utils::isWildcard(who)) {
+ if (Utils::wildcard_p(who)) {
Mask m(who);
- for (std::map<String, User *, std::less<String> >::iterator it =
- c->channelMemory.begin();
- it != c->channelMemory.end();
- ++it)
- if (m.matches((*it).second->nick + "!" +
- (*it).second->userhost) &&
- (*it).second->getProt() < User::NO_KICK)
- QUEUE->sendKick(channel, (*it).second->nick, reason);
+ kick_wildcard f (bot, m, channel, reason);
+ c->for_each_channel_users (f);
} else {
- User * u = c->getUser(who);
- if (!u)
- return UserNotFound(who, channel);
- if (u->getProt() < User::NO_KICK)
- QUEUE->sendKick(channel, who, reason);
- else
- return UserProtected(who, channel);
+ try
+ {
+ User u = c->getUser(who);
+
+ if (u.getProt() < User::NO_KICK)
+ QUEUE->sendKick(channel, who, reason);
+ else
+ return UserProtected(who, channel);
+ }
+ catch (const ChannelUserList::user_not_found &e)
+ {
+ return UserNotFound(e.name, channel);
+ }
}
return Ok;
CHECK_CONNECTION;
if (who == "")
- return EmptyAddressee;
+ {
+ return EmptyAddressee;
+ }
- if (Utils::isChannel(who))
- return NotToChannel;
+ if (Utils::channel_p(who))
+ {
+ if (!CHANNEL(who))
+ {
+ return NotOnChannel (who);
+ }
+ }
if (message == "")
- return EmptyMessage;
+ {
+ return EmptyMessage;
+ }
- QUEUE->sendPrivmsg(who, message);
+ // Send multi-line messages as seperate privmsgs
+ StringTokenizer st_message (message);
+
+ while (st_message.more_tokens_p ('\n'))
+ {
+ QUEUE->sendPrivmsg(who, st_message.next_token ('\n'));
+ }
return Ok;
}
if (!bot->canChangeServer())
return CanNotChangeServer;
+
+#ifdef USESCRIPTS
+ // Run hooks/disconnect
+ bot->botInterp->RunHooks
+ (Hook::DISCONNECT,
+ bot->serverConnection->server->getHostName (),
+ scm_list_n
+ (Utils::str2scm (bot->serverConnection->server->getHostName ()),
+ SCM_BOOL_T));
+#endif
QUEUE->sendQuit("Changing server");
bot->nextServer();
{
CHECK_CONNECTION;
- if (nick == "" || !Utils::isValidNickName(nick))
+ if (nick == "" || !Utils::valid_nickname_p(bot, nick))
return InvalidNick(nick);
bot->wantedNickName = nick;
if (who == "")
return EmptyAddressee;
- if (Utils::isChannel(who))
- return NotToChannel;
+ // if (Utils::channel_p(who))
+ // return NotToChannel;
if (message == "")
return EmptyMessage;
- QUEUE->sendNotice(who, message);
+ // Send multiple lines as multiple notices
+ StringTokenizer st_message (message);
+
+ while (st_message.more_tokens_p ('\n'))
+ {
+ QUEUE->sendNotice(who, st_message.next_token ('\n'));
+ }
return Ok;
}
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
- if (Utils::isWildcard(who))
+ if (Utils::wildcard_p(who))
return MassOpNotAllowed;
+
+ try
+ {
+ User u = c->getUser(who);
- User *u = c->getUser(who);
- if (!u)
- return UserNotFound(who, channel);
-
- ShitEntry *se = bot->shitList->getShit(who, channel);
- if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP)
- return UserOnShitList(who);
-
- QUEUE->sendChannelMode(channel, "+o", who);
+ ShitEntry *se = bot->shitList->getShit(who, channel);
+ if (se && se->isStillValid() && se->getShitLevel() >= ShitEntry::SHIT_NOOP)
+ return UserOnShitList(who);
+
+ QUEUE->sendChannelMode(channel, "+o", who);
+ }
+ catch (const ChannelUserList::user_not_found &e)
+ {
+ return UserNotFound(e.name, channel);
+ }
return Ok;
}
Message
Commands::Say(Bot *bot, String channel, String message)
{
- CHECK_CONNECTION;
-
-// if (!CHANNEL(channel))
-// return NotOnChannel(channel);
-
- QUEUE->sendPrivmsg(channel, message);
-
- return Ok;
+ return Commands::Msg (bot, channel, message);
}
return Ok;
}
+Message
+Commands::SetFloodRate(Bot *bot, unsigned int num_messages)
+{
+ if (num_messages > 0)
+ {
+ bot->MAX_MESSAGES = num_messages;
+ return Ok;
+ }
+ return InvalidParameters;
+}
+
Message
Commands::SetVersion(Bot *bot, String str)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
+ String dest;
+ // Make sure all of the inputs are valid
if (!c)
return NotOnChannel(channel);
-
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
-
if (seconds <= 0)
return InvalidTime(seconds);
-
- String dest;
-
- if (!Utils::isWildcard(who))
+
+ // Look for user
+ if (!Utils::wildcard_p(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
-
+
if (dest.length() == 0)
return UserNotFound(who, channel);
- dest = Utils::makeWildcard(dest);
+ dest = Utils::make_wildcard(dest);
Mask m(dest);
+ // Make sure the user isn't protected from bans
for (std::list<UserListItem *>::iterator it = bot->userList->l.begin();
it != bot->userList->l.end();
it++)
- if (m.matches((*it)->mask) &&
- (*it)->channelMask.matches(channel) &&
- (*it)->prot >= User::NO_BAN)
- return UserProtected(who, channel);
+ {
+ if (m.matches((*it)->mask) &&
+ (*it)->channelMask.matches(channel) &&
+ (*it)->prot >= User::NO_BAN)
+ {
+ return UserProtected(who, channel);
+ }
+ }
+
- for (std::vector<BanEntry *>::iterator it = c->channelBanlist.begin();
- it != c->channelBanlist.end(); ++it)
- if (m.matches((*it)->banMask))
- QUEUE->sendChannelMode(channel, "-b", (*it)->banMask.getMask());
+ // c->delBan (dest);
+ c->addBan(dest, seconds);
- CHANNEL(channel)->addBan(dest, seconds);
- QUEUE->sendChannelMode(channel, "+b", dest);
- bot->todoList->addDeban(channel, dest, seconds);
+ return Ok;
}
return Ok;
}
+
+Message
+Commands::Who (Bot *bot, String target)
+{
+ CHECK_CONNECTION;
+
+ QUEUE->sendWho (target);
+
+ return Ok;
+}
+
+Message
+Commands::Whois (Bot *bot, String nick)
+{
+ CHECK_CONNECTION;
+
+ if (!Utils::valid_nickname_p (bot, nick))
+ {
+ return InvalidNick (nick);
+ }
+ else
+ {
+ QUEUE->sendWhois (nick);
+ return Ok;
+ }
+}
+
+