bs_bot.c

Go to the documentation of this file.
00001 /* BotServ core functions
00002  *
00003  * (C) 2003-2008 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  * $Id: bs_bot.c 1352 2008-01-24 14:08:36Z drstein $
00012  *
00013  */
00014 /*************************************************************************/
00015 
00016 #include "module.h"
00017 
00018 int do_bot(User * u);
00019 int delbot(BotInfo * bi);
00020 void myBotServHelp(User * u);
00021 void change_bot_nick(BotInfo * bi, char *newnick);
00022 
00029 int AnopeInit(int argc, char **argv)
00030 {
00031     Command *c;
00032 
00033     moduleAddAuthor("Anope");
00034     moduleAddVersion("$Id: bs_bot.c 1352 2008-01-24 14:08:36Z drstein $");
00035     moduleSetType(CORE);
00036 
00037     c = createCommand("BOT", do_bot, is_services_admin, -1, -1, -1,
00038                       BOT_SERVADMIN_HELP_BOT, BOT_SERVADMIN_HELP_BOT);
00039     moduleAddCommand(BOTSERV, c, MOD_UNIQUE);
00040 
00041     moduleSetBotHelp(myBotServHelp);
00042 
00043     return MOD_CONT;
00044 }
00045 
00049 void AnopeFini(void)
00050 {
00051 
00052 }
00053 
00054 
00055 
00060 void myBotServHelp(User * u)
00061 {
00062     if (is_services_admin(u)) {
00063         notice_lang(s_BotServ, u, BOT_HELP_CMD_BOT);
00064     }
00065 }
00066 
00072 int do_bot(User * u)
00073 {
00074     BotInfo *bi;
00075     char *cmd = strtok(NULL, " ");
00076     char *ch = NULL;
00077 
00078     if (!cmd)
00079         syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
00080     else if (!stricmp(cmd, "ADD")) {
00081         char *nick = strtok(NULL, " ");
00082         char *user = strtok(NULL, " ");
00083         char *host = strtok(NULL, " ");
00084         char *real = strtok(NULL, "");
00085 
00086         if (!nick || !user || !host || !real)
00087             syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
00088         else if (readonly)
00089             notice_lang(s_BotServ, u, BOT_BOT_READONLY);
00090         else if (findbot(nick))
00091             notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick);
00092         else if (strlen(nick) > NickLen)
00093             notice_lang(s_BotServ, u, BOT_BAD_NICK);
00094         else if (strlen(user) >= USERMAX)
00095             notice_lang(s_BotServ, u, BOT_LONG_IDENT, USERMAX - 1);
00096         else if (strlen(user) > HOSTMAX)
00097             notice_lang(s_BotServ, u, BOT_LONG_HOST, HOSTMAX);
00098         else {
00099             NickAlias *na;
00100 
00104             if (isdigit(nick[0]) || nick[0] == '-') {
00105                 notice_lang(s_BotServ, u, BOT_BAD_NICK);
00106                 return MOD_CONT;
00107             }
00108             for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) {
00109                 if (!isvalidnick(*ch)) {
00110                     notice_lang(s_BotServ, u, BOT_BAD_NICK);
00111                     return MOD_CONT;
00112                 }
00113             }
00114 
00115             /* check for hardcored ircd forbidden nicks */
00116             if (!anope_valid_nick(nick)) {
00117                 notice_lang(s_BotServ, u, BOT_BAD_NICK);
00118                 return MOD_CONT;
00119             }
00120 
00121             if (!isValidHost(host, 3)) {
00122                 notice_lang(s_BotServ, u, BOT_BAD_HOST);
00123                 return MOD_CONT;
00124             }
00125             for (ch = user; *ch && (ch - user) < USERMAX; ch++) {
00126                 if (!isalnum(*ch)) {
00127                     notice_lang(s_BotServ, u, BOT_LONG_IDENT, USERMAX - 1);
00128                     return MOD_CONT;
00129                 }
00130             }
00131 
00136             /* Check whether it's a services client's nick and return if so - Certus */
00137             /* use nickIsServices reduce the total number lines of code  - TSL */
00138 
00139             if (nickIsServices(nick, 0)) {
00140                 notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED);
00141                 return MOD_CONT;
00142             }
00143 
00144             /* We check whether the nick is registered, and inform the user
00145              * if so. You need to drop the nick manually before you can use
00146              * it as a bot nick from now on -GD
00147              */
00148             if ((na = findnick(nick))) {
00149                 notice_lang(s_BotServ, u, NICK_ALREADY_REGISTERED, nick);
00150                 return MOD_CONT;
00151             }
00152 
00153             bi = makebot(nick);
00154             if (!bi) {
00155                 notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED);
00156                 return MOD_CONT;
00157             }
00158 
00159             bi->user = sstrdup(user);
00160             bi->host = sstrdup(host);
00161             bi->real = sstrdup(real);
00162             bi->created = time(NULL);
00163             bi->chancount = 0;
00164 
00165             /* We check whether user with this nick is online, and kill it if so */
00166             EnforceQlinedNick(nick, s_BotServ);
00167 
00168             /* We make the bot online, ready to serve */
00169             anope_cmd_bot_nick(bi->nick, bi->user, bi->host, bi->real,
00170                                ircd->botserv_bot_mode);
00171 
00172             notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user,
00173                         bi->host, bi->real);
00174 
00175             send_event(EVENT_BOT_CREATE, 1, bi->nick);
00176         }
00177     } else if (!stricmp(cmd, "CHANGE")) {
00178         char *oldnick = strtok(NULL, " ");
00179         char *nick = strtok(NULL, " ");
00180         char *user = strtok(NULL, " ");
00181         char *host = strtok(NULL, " ");
00182         char *real = strtok(NULL, "");
00183 
00184         if (!oldnick || !nick)
00185             syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
00186         else if (readonly)
00187             notice_lang(s_BotServ, u, BOT_BOT_READONLY);
00188         else if (!(bi = findbot(oldnick)))
00189             notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick);
00190         else if (strlen(nick) > NickLen)
00191             notice_lang(s_BotServ, u, BOT_BAD_NICK);
00192         else if (user && strlen(user) >= USERMAX)
00193             notice_lang(s_BotServ, u, BOT_LONG_IDENT, USERMAX - 1);
00194         else if (host && strlen(host) > HOSTMAX)
00195             notice_lang(s_BotServ, u, BOT_LONG_HOST, HOSTMAX);
00196         else {
00197             NickAlias *na;
00198 
00199             /* Checks whether there *are* changes.
00200              * Case sensitive because we may want to change just the case.
00201              * And we must finally check that the nick is not already
00202              * taken by another bot.
00203              */
00204             if (!strcmp(bi->nick, nick)
00205                 && ((user) ? !strcmp(bi->user, user) : 1)
00206                 && ((host) ? !strcmp(bi->host, host) : 1)
00207                 && ((real) ? !strcmp(bi->real, real) : 1)) {
00208                 notice_lang(s_BotServ, u, BOT_BOT_ANY_CHANGES);
00209                 return MOD_CONT;
00210             }
00211 
00212             /* Check whether it's a services client's nick and return if so - Certus */
00213             /* use nickIsServices() to reduce the number of lines of code  - TSL */
00214             if (nickIsServices(nick, 0)) {
00215                 notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED);
00216                 return MOD_CONT;
00217             }
00218 
00222             if (isdigit(nick[0]) || nick[0] == '-') {
00223                 notice_lang(s_BotServ, u, BOT_BAD_NICK);
00224                 return MOD_CONT;
00225             }
00226             for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) {
00227                 if (!isvalidnick(*ch)) {
00228                     notice_lang(s_BotServ, u, BOT_BAD_NICK);
00229                     return MOD_CONT;
00230                 }
00231             }
00232 
00233             /* check for hardcored ircd forbidden nicks */
00234             if (!anope_valid_nick(nick)) {
00235                 notice_lang(s_BotServ, u, BOT_BAD_NICK);
00236                 return MOD_CONT;
00237             }
00238 
00239             if (host && !isValidHost(host, 3)) {
00240                 notice_lang(s_BotServ, u, BOT_BAD_HOST);
00241                 return MOD_CONT;
00242             }
00243 
00244             if (user) {
00245                 for (ch = user; *ch && (ch - user) < USERMAX; ch++) {
00246                     if (!isalnum(*ch)) {
00247                         notice_lang(s_BotServ, u, BOT_LONG_IDENT, USERMAX - 1);
00248                         return MOD_CONT;
00249                     }
00250                 }
00251             }
00252 
00253             if (stricmp(bi->nick, nick) && findbot(nick)) {
00254                 notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick);
00255                 return MOD_CONT;
00256             }
00257 
00258             if (stricmp(bi->nick, nick)) {
00259                 /* We check whether the nick is registered, and inform the user
00260                  * if so. You need to drop the nick manually before you can use
00261                  * it as a bot nick from now on -GD
00262                  */
00263                 if ((na = findnick(nick))) {
00264                     notice_lang(s_BotServ, u, NICK_ALREADY_REGISTERED,
00265                                 nick);
00266                     return MOD_CONT;
00267                 }
00268 
00269                 /* The new nick is really different, so we remove the Q line for
00270                    the old nick. */
00271                 if (ircd->sqline) {
00272                     anope_cmd_unsqline(bi->nick);
00273                 }
00274 
00275                 /* We check whether user with this nick is online, and kill it if so */
00276                 EnforceQlinedNick(nick, s_BotServ);
00277             }
00278 
00279             if (strcmp(nick, bi->nick))
00280                 change_bot_nick(bi, nick);
00281 
00282             if (user && strcmp(user, bi->user)) {
00283                 free(bi->user);
00284                 bi->user = sstrdup(user);
00285             }
00286             if (host && strcmp(host, bi->host)) {
00287                 free(bi->host);
00288                 bi->host = sstrdup(host);
00289             }
00290             if (real && strcmp(real, bi->real)) {
00291                 free(bi->real);
00292                 bi->real = sstrdup(real);
00293             }
00294 
00295             /* If only the nick changes, we just make the bot change his nick,
00296                else we must make it quit and rejoin. We must not forget to set
00297                            the Q:Line either (it's otherwise set in anope_cmd_bot_nick) */
00298             if (!user) {
00299                 anope_cmd_chg_nick(oldnick, bi->nick);
00300                                 anope_cmd_sqline(bi->nick, "Reserved for services");
00301             } else {
00302                 anope_cmd_quit(oldnick, "Quit: Be right back");
00303 
00304                 anope_cmd_bot_nick(bi->nick, bi->user, bi->host, bi->real,
00305                                    ircd->botserv_bot_mode);
00306                 bot_rejoin_all(bi);
00307             }
00308 
00309             notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick,
00310                         bi->user, bi->host, bi->real);
00311 
00312             send_event(EVENT_BOT_CHANGE, 1, bi->nick);
00313         }
00314     } else if (!stricmp(cmd, "DEL")) {
00315         char *nick = strtok(NULL, " ");
00316 
00317         if (!nick)
00318             syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
00319         else if (readonly)
00320             notice_lang(s_BotServ, u, BOT_BOT_READONLY);
00321         else if (!(bi = findbot(nick)))
00322             notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick);
00323         else {
00324             send_event(EVENT_BOT_DEL, 1, bi->nick);
00325             anope_cmd_quit(bi->nick,
00326                            "Quit: Help! I'm being deleted by %s!",
00327                            u->nick);
00328             if (ircd->sqline) {
00329                 anope_cmd_unsqline(bi->nick);
00330             }
00331             delbot(bi);
00332 
00333             notice_lang(s_BotServ, u, BOT_BOT_DELETED, nick);
00334         }
00335     } else
00336         syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX);
00337 
00338     return MOD_CONT;
00339 }
00340 
00341 int delbot(BotInfo * bi)
00342 {
00343     cs_remove_bot(bi);
00344 
00345     if (bi->next)
00346         bi->next->prev = bi->prev;
00347     if (bi->prev)
00348         bi->prev->next = bi->next;
00349     else
00350         botlists[tolower(*bi->nick)] = bi->next;
00351 
00352     nbots--;
00353 
00354     free(bi->nick);
00355     free(bi->user);
00356     free(bi->host);
00357     free(bi->real);
00358 
00359     free(bi);
00360 
00361     return 1;
00362 }
00363 
00364 void change_bot_nick(BotInfo * bi, char *newnick)
00365 {
00366     if (bi->next)
00367         bi->next->prev = bi->prev;
00368     if (bi->prev)
00369         bi->prev->next = bi->next;
00370     else
00371         botlists[tolower(*bi->nick)] = bi->next;
00372 
00373     if (bi->nick)
00374         free(bi->nick);
00375     bi->nick = sstrdup(newnick);
00376 
00377     insert_bot(bi);
00378 }

Generated on Sun Oct 5 09:06:54 2008 for Anope by  doxygen 1.5.7.1