// Commands.C -*- C++ -*-
// Copyright (c) 1998 Etienne BERNARD
// Copyright (C) 2002 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
// the Free Software Foundation; either version 2 of the License, or
// 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 "Macros.H"
#include "Message.H"
#include "Commands.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."))
#define CHECK_CONNECTION if (!bot->serverConnection) return NotConnected
Message
Commands::Action(Bot *bot, String channel, String message)
{
CHECK_CONNECTION;
if (!CHANNEL(channel))
return NotOnChannel(channel);
if (message.length() == 0)
return InvalidParameters;
QUEUE->sendPrivmsg(channel, String("\001ACTION ") +
message + "\001");
return Ok;
}
Message
Commands::AddUser(Bot *bot, String who, String maskChannel, int level,
int prot, bool aop, std::time_t expire, String password)
{
// Gah, fix this (makes bot segfault)
if (who.length() == 0 ||
maskChannel.length() == 0 ||
level < 0 ||
level > User::FRIEND ||
prot < 0 ||
prot > User::NO_DEOP)
return InvalidParameters;
String mask;
if (!Utils::isWildcard(who))
{
mask = bot->getUserhost("", who);
if (mask.length() == 0)
return NotFound(who);
}
// Aha! This was before the brace...segfault gone
mask = Utils::makeWildcard(mask);
if (bot->userList->isInUserList(mask, maskChannel))
return AlreadyInUserlist(mask, maskChannel);
bot->userList->addUser(mask, maskChannel, level, prot, aop,
expire, password);
bot->rehash();
return Ok;
}
Message
Commands::AddServer(Bot *bot, String servername, int port)
{
if (port <= 0)
return InvalidPort(port);
bot->serverList->addServer(new class Server(servername, port));
return Ok;
}
Message
Commands::AddShit(Bot *bot, String mask, String maskChannel,
int level, time_t expiration, String reason)
{
if (mask.length() == 0 || maskChannel.length() == 0 ||
level < 0 || level > ShitEntry::SHIT_NODEBAN)
return InvalidParameters;
if (reason == "")
reason = "You're on my shitlist, lamer";
String who = mask;
if (!Utils::isWildcard(mask)) {
mask = bot->getUserhost("", who);
if (mask.length() == 0)
return NotFound(who);
mask = Utils::makeWildcard(mask);
if (bot->shitList->getShit(mask, maskChannel))
return AlreadyInShitlist(mask, maskChannel);
}
if (bot->userList->getMaxProt(mask, maskChannel) > 0)
return UserProtected(who, maskChannel);
bot->shitList->addShit(mask, maskChannel, level, expiration, reason);
return Ok;
}
Message
Commands::Ban(Bot *bot, String channel, String who)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
String dest;
if (!Utils::isWildcard(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
if (dest.length() == 0)
return NotFound(who);
dest = Utils::makeWildcard(dest);
Mask m(dest);
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);
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);
return Ok;
}
Message
Commands::Cycle(Bot *bot, String channel)
{
CHECK_CONNECTION;
if (!CHANNEL(channel))
return NotOnChannel(channel);
QUEUE->sendPart(channel);
QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
return Ok;
}
Message
Commands::Deban(Bot *bot, String channel, String who)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
String dest;
if (!Utils::isWildcard(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
if (dest.length() == 0)
return UserNotFound(who, channel);
dest = Utils::makeWildcard(dest);
Mask m(dest);
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());
}
return Ok;
}
Message
Commands::DelServer(Bot *bot, int number)
{
if (number < 0 || number >= bot->serverList->size())
return InvalidServerNumber(number);
bot->serverList->delServer(number);
return Ok;
}
Message
Commands::DelUser(Bot *bot, String who, String maskChannel)
{
if (who.length() == 0 || maskChannel.length() == 0)
return InvalidParameters;
String dest;
if (!Utils::isWildcard(who)) {
dest = bot->getUserhost("", who);
if (dest.length() == 0)
return NotFound(who);
dest = Utils::makeWildcard(who);
}
if (!bot->userList->isInUserList(dest, maskChannel))
return NotInUserlist(who);
bot->userList->removeUser(dest, maskChannel);
bot->rehash();
return Ok;
}
Message
Commands::DelShit(Bot *bot, String who, String maskChannel)
{
if (who.length() == 0 || maskChannel.length() == 0)
return InvalidParameters;
String dest;
if (!Utils::isWildcard(who)) {
dest = bot->getUserhost("", who);
if (dest.length() == 0)
return NotFound(who);
dest = Utils::makeWildcard(who);
}
if (!bot->shitList->getShit(dest, maskChannel))
return NotInShitlist(who);
bot->shitList->delShit(dest, maskChannel);
return Ok;
}
Message
Commands::Deop(Bot *bot, String channel, String who)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
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);
} 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);
}
}
return Ok;
}
Message
Commands::Die(Bot *bot, String reason)
{
CHECK_CONNECTION;
QUEUE->sendQuit(reason);
bot->stop = true;
return Ok;
}
Message
Commands::Do(Bot *bot, String command)
{
CHECK_CONNECTION;
QUEUE->addLine(command, 0, 0, ServerQueueItem::OTHER);
return Ok;
}
Message
Commands::Invite(Bot *bot, String channel, String who)
{
CHECK_CONNECTION;
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
QUEUE->sendInvite(channel, who);
return Ok;
}
Message
Commands::Join(Bot *bot, String channel, String key)
{
CHECK_CONNECTION;
if (!Utils::isValidChannelName(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;
else {
bot->wantedChannels[channel] = new wantedChannel("", "", key);
}
}
QUEUE->sendJoin(channel, bot->wantedChannels[channel]->key);
return Ok;
}
Message
Commands::Keep(Bot *bot, String channel, String modes)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
c->keepModes = modes;
return Ok;
}
Message
Commands::Kick(Bot *bot, String channel, String who, String reason)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
if (Utils::isWildcard(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);
} 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);
}
return Ok;
}
Message
Commands::KickBan(Bot *bot, String channel, String who, String reason)
{
CHECK_CONNECTION;
Message m = Commands::Ban(bot, channel, who);
if (m.getCode() == 0)
m = Commands::Kick(bot, channel, who, reason);
return m;
}
Message
Commands::Lock(Bot *bot, String channel)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
c->lockedTopic = true;
return Ok;
}
Message
Commands::Mode(Bot *bot, String channel, String mode)
{
CHECK_CONNECTION;
if (!CHANNEL(channel))
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
QUEUE->sendChannelMode(String("MODE ") + channel + " " + mode);
return Ok;
}
Message
Commands::Msg(Bot *bot, String who, String message)
{
CHECK_CONNECTION;
if (who == "")
return EmptyAddressee;
if (Utils::isChannel(who))
return NotToChannel;
if (message == "")
return EmptyMessage;
QUEUE->sendPrivmsg(who, message);
return Ok;
}
Message
Commands::NextServer(Bot *bot)
{
CHECK_CONNECTION;
if (bot->serverList->size() == 0)
return EmptyServerList;
if (!bot->canChangeServer())
return CanNotChangeServer;
QUEUE->sendQuit("Changing server");
bot->nextServer();
return Ok;
}
Message
Commands::Nick(Bot *bot, String nick)
{
CHECK_CONNECTION;
if (nick == "" || !Utils::isValidNickName(nick))
return InvalidNick(nick);
bot->wantedNickName = nick;
QUEUE->sendNick(nick);
return Ok;
}
Message
Commands::Notice(Bot *bot, String who, String message)
{
CHECK_CONNECTION;
if (who == "")
return EmptyAddressee;
if (Utils::isChannel(who))
return NotToChannel;
if (message == "")
return EmptyMessage;
QUEUE->sendNotice(who, message);
return Ok;
}
Message
Commands::Op(Bot *bot, String channel, String who)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
if (Utils::isWildcard(who))
return MassOpNotAllowed;
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);
return Ok;
}
Message
Commands::Part(Bot *bot, String channel)
{
CHECK_CONNECTION;
if (!CHANNEL(channel))
return NotOnChannel(channel);
wantedChannel *w = bot->wantedChannels[channel];
bot->wantedChannels.erase(channel);
delete w;
QUEUE->sendPart(channel);
return Ok;
}
Message
Commands::Reconnect(Bot *bot)
{
CHECK_CONNECTION;
if (!bot->canChangeServer())
return CanNotChangeServer;
QUEUE->sendQuit("Reconnecting");
bot->reconnect();
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;
}
Message
Commands::Server(Bot *bot, int number)
{
CHECK_CONNECTION;
if (number < 0 || number >= bot->serverList->size())
return InvalidServerNumber(number);
if (!bot->canChangeServer())
return CanNotChangeServer;
QUEUE->sendQuit("Changing server");
QUEUE->flush();
bot->connect(number);
return Ok;
}
Message
Commands::SetVersion(Bot *bot, String str)
{
if (str.length() == 0)
return InvalidParameters;
bot->versionString = str;
return Ok;
}
Message
Commands::TBan(Bot *bot, String channel, String who, int seconds)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel))
return NotChannelOp(channel);
if (seconds <= 0)
return InvalidTime(seconds);
String dest;
if (!Utils::isWildcard(who))
dest = bot->getUserhost(channel, who);
else
dest = who;
if (dest.length() == 0)
return UserNotFound(who, channel);
dest = Utils::makeWildcard(dest);
Mask m(dest);
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);
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());
CHANNEL(channel)->addBan(dest, seconds);
QUEUE->sendChannelMode(channel, "+b", dest);
bot->todoList->addDeban(channel, dest, seconds);
return Ok;
}
Message
Commands::TKBan(Bot *bot, String channel, String who, int seconds, String reason)
{
CHECK_CONNECTION;
Message m = Commands::TBan(bot, channel, who, seconds);
if (m.getCode() == 0)
m = Commands::Kick(bot, channel, who, reason);
return m;
}
Message
Commands::Topic(Bot *bot, String channel, String topic)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
if (!bot->iAmOp(channel) && !(c->channelMode & Channel::TOPIC_RESTRICTED))
return CanNotChangeTopic(channel);
if (c->lockedTopic)
return TopicLocked(channel);
QUEUE->sendTopic(channel, topic);
return Ok;
}
Message
Commands::Unlock(Bot *bot, String channel)
{
CHECK_CONNECTION;
Channel *c = CHANNEL(channel);
if (!c)
return NotOnChannel(channel);
c->lockedTopic = false;
return Ok;
}
syntax highlighted by Code2HTML, v. 0.9.1