summaryrefslogtreecommitdiff
path: root/src/core/bs_bot.cpp
diff options
context:
space:
mode:
authorAdam <Adam@Anope.org>2010-05-25 00:57:25 -0500
committerAdam <Adam@anope.org>2010-06-18 21:04:07 -0400
commit4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch)
treee4af4e59fd29352138db0fb0ff614d50233850b8 /src/core/bs_bot.cpp
parent2fba686904e6f78ebab35df171c5757afeebf05d (diff)
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/core/bs_bot.cpp')
-rw-r--r--src/core/bs_bot.cpp432
1 files changed, 432 insertions, 0 deletions
diff --git a/src/core/bs_bot.cpp b/src/core/bs_bot.cpp
new file mode 100644
index 000000000..2c5888554
--- /dev/null
+++ b/src/core/bs_bot.cpp
@@ -0,0 +1,432 @@
+/* BotServ core functions
+ *
+ * (C) 2003-2010 Anope Team
+ * Contact us at team@anope.org
+ *
+ * Please read COPYING and README for further details.
+ *
+ * Based on the original code of Epona by Lara.
+ * Based on the original code of Services by Andy Church.
+ *
+ *
+ */
+/*************************************************************************/
+
+#include "module.h"
+
+class CommandBSBot : public Command
+{
+ private:
+ CommandReturn DoAdd(User *u, const std::vector<ci::string> &params)
+ {
+ const char *nick = params[1].c_str();
+ const char *user = params[2].c_str();
+ const char *host = params[3].c_str();
+ const char *real = params[4].c_str();
+ const char *ch = NULL;
+ BotInfo *bi;
+
+ if (findbot(nick))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick);
+ return MOD_CONT;
+ }
+
+ if (strlen(nick) > Config.NickLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ if (strlen(user) > Config.UserLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_LONG_IDENT, Config.UserLen);
+ return MOD_CONT;
+ }
+
+ if (strlen(user) > Config.HostLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_LONG_HOST, Config.HostLen);
+ return MOD_CONT;
+ }
+
+ /* Check the nick is valid re RFC 2812 */
+ if (isdigit(nick[0]) || nick[0] == '-')
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ for (ch = nick; *ch && (ch - nick) < Config.NickLen; ch++)
+ {
+ if (!isvalidnick(*ch))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+ }
+
+ /* check for hardcored ircd forbidden nicks */
+ if (!ircdproto->IsNickValid(nick))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ /* Check the host is valid re RFC 2812 */
+ if (!isValidHost(host, 3))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_HOST);
+ return MOD_CONT;
+ }
+
+ for (ch = user; *ch && (ch - user) < Config.UserLen; ch++)
+ {
+ if (!isalnum(*ch))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_IDENT, Config.UserLen);
+ return MOD_CONT;
+ }
+ }
+
+
+ /* We check whether the nick is registered, and inform the user
+ * if so. You need to drop the nick manually before you can use
+ * it as a bot nick from now on -GD
+ */
+ if (findnick(nick))
+ {
+ notice_lang(Config.s_BotServ, u, NICK_ALREADY_REGISTERED, nick);
+ return MOD_CONT;
+ }
+
+ if (!(bi = new BotInfo(nick, user, host, real)))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BOT_CREATION_FAILED);
+ return MOD_CONT;
+ }
+
+ /* We check whether user with this nick is online, and kill it if so */
+ EnforceQlinedNick(nick, Config.s_BotServ);
+
+ notice_lang(Config.s_BotServ, u, BOT_BOT_ADDED, bi->nick.c_str(), bi->user.c_str(), bi->host.c_str(), bi->real.c_str());
+
+ FOREACH_MOD(I_OnBotCreate, OnBotCreate(bi));
+ return MOD_CONT;
+ }
+
+ CommandReturn DoChange(User *u, const std::vector<ci::string> &params)
+ {
+ const char *oldnick = params[1].c_str();
+ const char *nick = params.size() > 2 ? params[2].c_str() : NULL;
+ const char *user = params.size() > 3 ? params[3].c_str() : NULL;
+ const char *host = params.size() > 4 ? params[4].c_str() : NULL;
+ const char *real = params.size() > 5 ? params[5].c_str() : NULL;
+ const char *ch = NULL;
+ BotInfo *bi;
+
+ if (!oldnick || !nick)
+ {
+ this->OnSyntaxError(u, "CHANGE");
+ return MOD_CONT;
+ }
+
+ if (!(bi = findbot(oldnick)))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick);
+ return MOD_CONT;
+ }
+
+ if (stricmp(oldnick, nick) && nickIsServices(oldnick, 0))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick);
+ return MOD_CONT;
+ }
+
+ if (strlen(nick) > Config.NickLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ if (user && strlen(user) > Config.UserLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_LONG_IDENT, Config.UserLen);
+ return MOD_CONT;
+ }
+
+ if (host && strlen(host) > Config.HostLen)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_LONG_HOST, Config.HostLen);
+ return MOD_CONT;
+ }
+
+ if (stricmp(oldnick, nick) && nickIsServices(nick, 0))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick);
+ return MOD_CONT;
+ }
+
+ /* Checks whether there *are* changes.
+ * Case sensitive because we may want to change just the case.
+ * And we must finally check that the nick is not already
+ * taken by another bot.
+ */
+ if (bi->nick == nick && (user ? bi->user == user : 1) && (host ? bi->host == host : 1) && (real ? bi->real == real : 1))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BOT_ANY_CHANGES);
+ return MOD_CONT;
+ }
+
+ /* Check the nick is valid re RFC 2812 */
+ if (isdigit(nick[0]) || nick[0] == '-')
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ for (ch = nick; *ch && (ch - nick) < Config.NickLen; ch++)
+ {
+ if (!isvalidnick(*ch))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+ }
+
+ /* check for hardcored ircd forbidden nicks */
+ if (!ircdproto->IsNickValid(nick))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_NICK);
+ return MOD_CONT;
+ }
+
+ if (host && !isValidHost(host, 3))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_HOST);
+ return MOD_CONT;
+ }
+
+ if (user)
+ {
+ for (ch = user; *ch && (ch - user) < Config.UserLen; ch++)
+ {
+ if (!isalnum(*ch))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BAD_IDENT, Config.UserLen);
+ return MOD_CONT;
+ }
+ }
+ }
+
+ ci::string ci_bi_nick(bi->nick.c_str());
+ if (ci_bi_nick != nick && findbot(nick))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick);
+ return MOD_CONT;
+ }
+
+ if (ci_bi_nick != nick)
+ {
+ /* We check whether the nick is registered, and inform the user
+ * if so. You need to drop the nick manually before you can use
+ * it as a bot nick from now on -GD
+ */
+ if (findnick(nick))
+ {
+ notice_lang(Config.s_BotServ, u, NICK_ALREADY_REGISTERED, nick);
+ return MOD_CONT;
+ }
+
+ /* The new nick is really different, so we remove the Q line for
+ the old nick. */
+ if (ircd->sqline)
+ {
+ XLine x(bi->nick.c_str());
+ ircdproto->SendSQLineDel(&x);
+ }
+
+ /* We check whether user with this nick is online, and kill it if so */
+ EnforceQlinedNick(nick, Config.s_BotServ);
+ }
+
+ if (user)
+ ircdproto->SendQuit(bi, "Quit: Be right back");
+ else
+ {
+ ircdproto->SendChangeBotNick(bi, nick);
+ XLine x(bi->nick.c_str(), "Reserved for services");
+ ircdproto->SendSQLine(&x);
+ }
+
+ if (bi->nick != nick)
+ bi->ChangeNick(nick);
+
+ if (user && bi->user != user)
+ bi->user = user;
+ if (host && bi->host != host)
+ bi->host = host;
+ if (real && bi->real != real)
+ bi->real = real;
+
+ if (user)
+ {
+ if (ircd->ts6) {
+ // This isn't the nicest way to do this, unfortunately.
+ bi->uid = ts6_uid_retrieve();
+ }
+ ircdproto->SendClientIntroduction(bi->nick, bi->user, bi->host, bi->real, ircd->pseudoclient_mode, bi->uid);
+ XLine x(bi->nick.c_str(), "Reserved for services");
+ ircdproto->SendSQLine(&x);
+ bi->RejoinAll();
+ }
+
+ notice_lang(Config.s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick.c_str(), bi->user.c_str(), bi->host.c_str(), bi->real.c_str());
+
+ FOREACH_MOD(I_OnBotChange, OnBotChange(bi));
+ return MOD_CONT;
+ }
+
+ CommandReturn DoDel(User *u, const std::vector<ci::string> &params)
+ {
+ const char *nick = params[1].c_str();
+ BotInfo *bi;
+
+ if (!nick)
+ {
+ this->OnSyntaxError(u, "DEL");
+ return MOD_CONT;
+ }
+
+ if (!(bi = findbot(nick)))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, nick);
+ return MOD_CONT;
+ }
+
+ if (nickIsServices(nick, 0))
+ {
+ notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, nick);
+ return MOD_CONT;
+ }
+
+ FOREACH_MOD(I_OnBotDelete, OnBotDelete(bi));
+
+ ircdproto->SendQuit(bi, "Quit: Help! I'm being deleted by %s!", u->nick.c_str());
+ XLine x(bi->nick.c_str());
+ ircdproto->SendSQLineDel(&x);
+
+ delete bi;
+ notice_lang(Config.s_BotServ, u, BOT_BOT_DELETED, nick);
+ return MOD_CONT;
+ }
+ public:
+ CommandBSBot() : Command("BOT", 1, 6)
+ {
+ this->SetFlag(CFLAG_STRIP_CHANNEL);
+ }
+
+ CommandReturn Execute(User *u, const std::vector<ci::string> &params)
+ {
+ ci::string cmd = params[0];
+
+ if (readonly)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_BOT_READONLY);
+ return MOD_CONT;
+ }
+
+ if (cmd == "ADD")
+ {
+ // ADD nick user host real - 5
+ if (!u->Account()->HasCommand("botserv/bot/add"))
+ {
+ notice_lang(Config.s_BotServ, u, ACCESS_DENIED);
+ return MOD_CONT;
+ }
+
+ if (params.size() < 5)
+ {
+ this->OnSyntaxError(u, "ADD");
+ return MOD_CONT;
+ }
+
+ std::vector<ci::string> tempparams = params;
+ // ADD takes less params than CHANGE, so we need to take 6 if given and append it with a space to 5.
+ if (tempparams.size() >= 6)
+ tempparams[4] = tempparams[4] + " " + tempparams[5];
+
+ return this->DoAdd(u, tempparams);
+ }
+ else if (cmd == "CHANGE")
+ {
+ // CHANGE oldn newn user host real - 6
+ // but only oldn and newn are required
+ if (!u->Account()->HasCommand("botserv/bot/change"))
+ {
+ notice_lang(Config.s_BotServ, u, ACCESS_DENIED);
+ return MOD_CONT;
+ }
+
+ if (params.size() < 3)
+ {
+ this->OnSyntaxError(u, "CHANGE");
+ return MOD_CONT;
+ }
+
+ return this->DoChange(u, params);
+ }
+ else if (cmd == "DEL")
+ {
+ // DEL nick
+ if (!u->Account()->HasCommand("botserv/bot/del"))
+ {
+ notice_lang(Config.s_BotServ, u, ACCESS_DENIED);
+ return MOD_CONT;
+ }
+
+ if (params.size() < 1)
+ {
+ this->OnSyntaxError(u, "DEL");
+ return MOD_CONT;
+ }
+
+ return this->DoDel(u, params);
+ }
+ else
+ this->OnSyntaxError(u, "");
+
+ return MOD_CONT;
+ }
+
+ bool OnHelp(User *u, const ci::string &subcommand)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_SERVADMIN_HELP_BOT);
+ return true;
+ }
+
+ void OnSyntaxError(User *u, const ci::string &subcommand)
+ {
+ syntax_error(Config.s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
+ }
+};
+
+class BSBot : public Module
+{
+ public:
+ BSBot(const std::string &modname, const std::string &creator) : Module(modname, creator)
+ {
+ this->SetAuthor("Anope");
+ this->SetVersion(VERSION_STRING);
+ this->SetType(CORE);
+ this->AddCommand(BotServ, new CommandBSBot());
+
+ ModuleManager::Attach(I_OnBotServHelp, this);
+ }
+ void OnBotServHelp(User *u)
+ {
+ notice_lang(Config.s_BotServ, u, BOT_HELP_CMD_BOT);
+ }
+};
+
+MODULE_INIT(BSBot)