diff --git a/source/chansrv.c b/source/chansrv.c index d8c1af1..425cc81 100644 --- a/source/chansrv.c +++ b/source/chansrv.c @@ -1,2559 +1,2559 @@ /* * Copyright (C) 1996 Darkbot Project. * This program is free software, you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2. 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 COPYING file for details. */ #include "defines.h" #include "vars.h" #include "prototypes.h" // FIXME: When the command is invoked in a channel, target is the channel name, otherwise target is the bots name? // Due to the original nature of this code, some of these routines assume the in channel case, others assume the /msg case. // Also check the commands that can have a channel argument work the same in and out of channel. enum chanserv_command_type { INFO_COMMAND = 0, SAFE_COMMAND = 1, NORMAL_COMMAND = 2, DANGER_COMMAND = 3, PASSWORD_COMMAND = 4 }; struct chanserv_command { enum chanserv_command_type type; int access; int arg_count; int too_many; /* Check for too many args */ struct chanserv_output *(*func) (char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost); char *command[5]; char *syntax; char *summary; }; static void show_output(char *source, char *target, struct chanserv_output *result, enum chanserv_invoke_type input_type, int question); struct chanserv_output *chanserv_show_help(char *cmd, long user_level); struct chanserv_output *chanserv_asprintf(struct chanserv_output *output, const char *format, ...) { struct chanserv_output *result = NULL; static char temp[BUFSIZ]; /* a temp buffer (8KB) */ va_list list; int r; va_start(list, format); r = vsprintf(temp, format, list); va_end(list); if (r >= 0) { char *ptr; ptr = malloc(r + 1); if (ptr) { result = malloc(sizeof(struct chanserv_output)); if (result) { strncpy(ptr, temp, r); /* copy at most n */ ptr[r] = '\0'; /* ensure \0 at end */ result->output = ptr; result->next = NULL; if (output) { struct chanserv_output *next = output; while (next->next) next = next->next; next->next = result; result = output; } } else free(ptr); } } if (result == NULL) { ;// FIXME: Should bitch about lack of ram. } return result; } void chanserv_output_free(struct chanserv_output *output) { while (output) { struct chanserv_output *next = output->next; free(output->output); free(output); output = next; } } struct chanserv_output *chanserv_add(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char str [STRING_LONG] = { 0 }, topic [STRING_LONG] = {0}; if (!args || !args[0]) return chanserv_asprintf(NULL, "Add what?"); /* Save topic since we're chopping args[0] off later. */ strncpy (topic, args[0], sizeof (topic)); /* Check to make sure the topic doesn't exist first. */ if (check_existing_url(source, topic, target) == 1) { return chanserv_asprintf(result, "%s \37%s\37\n", EXISTING_ENTRY, topic); } /* Cut off the first argument (the topic) */ args++; if ((db_argstostr (str, args, 0, ' ')) < 1) return chanserv_asprintf(result, "What info is to be added for %s?", topic); // Fix for some segmentation fault problems // concerning topics consisting entirely of // wildcard characters. if (strspn(topic, "*?") == strlen(topic)) return chanserv_asprintf(NULL, "Sorry, but support for that topic has been removed."); /* FIXME: If both things happen, result is overwritten with * the second event, and the first truncation isn't displayed */ if (strlen(topic) > MAX_TOPIC_SIZE) { topic[MAX_TOPIC_SIZE] = '\0'; result = chanserv_asprintf(NULL, "Topic is over the limit, and has had characters truncated."); } if (strlen(str) > MAX_DATA_SIZE) { str[MAX_DATA_SIZE] = '\0'; result = chanserv_asprintf(NULL, "Data is over the limit, and has had characters truncated."); } strlwr(topic); /* Don't allow the topic to be an rdb file name. */ if (*topic == '~') return chanserv_asprintf(result, "Rdb files can only be called from the data of a topic, they cannot be used in the topic itself."); if (LOG_ADD_DELETES) db_log(ADD_DELETES, "[%s] %s!%s ADD %s %s\n", date(), source, userhost, topic, str); ADDITIONS++; if ((strspn (topic, "ilc")) == 3 || (strspn (topic, "iln")) == 3) { db_log(URL2, "%s ([%s] %s!%s): %s\n", topic, date(), source, userhost, str); } else { db_log(URL2, "%s %s\n", topic, str); } return chanserv_asprintf(result, "Okay."); } struct chanserv_output *chanserv_add_user(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char temp[1024] = { 0 }; long level = 0; if (!args || !args[0] || !args[1] || !args[2] || !args[3]) return result; level = atoi(args[2]); if (level > 10 || level <= 0) return result; if (strlen(args[1]) < 7) return result; snprintf(temp, sizeof (temp), "I haven't used \2%cSETINFO\2 yet!", *CMDCHAR); add_helper(args[0], mask_from_nick(args[1], target), level, 0, temp, args[3], 0); save_changes(); return chanserv_asprintf(NULL, "Added user: %s - level %d.", mask_from_nick(args[1], target), level); } struct chanserv_output *chanserv_alarm(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char temp[1024] = { 0 }; time_t seconds = 0, unixtime = 0; long i = 0; if (!args || !args[0] || !args[1] || (strlen(args[0]) < 2)) return chanserv_asprintf(NULL, "Syntax: <time type: \2d/h/m/s\2><time> <text to say>"); if (tolower(*args[0]) == 'd') { /* Days. */ seconds = 86400; args[0]++; } else if (tolower(*args[0]) == 'h') { /* Hours */ seconds = 3600; args[0]++; } else if (tolower(*args[0]) == 'm') { /* Minutes */ seconds = 60; args[0]++; } else if (tolower(*args[0]) == 's') { /* Seconds */ seconds = 1; args[0]++; } else { return chanserv_asprintf(NULL, "Syntax: <time type: \2d/h/m/s\2><time> <text to say>"); } snprintf(temp, sizeof (temp), "%s/%ld", DBTIMERS_PATH, (atoi (args[0]) * seconds) + time (NULL)); db_log(temp, "PRIVMSG %s :\2ALARMCLOCK\2 by %s!%s: %s", source, source, userhost, args[1]); unixtime = atoi (args[0]) * seconds; if (unixtime > 86400) result = chanserv_asprintf(NULL, "alarmclock set to go off in %d day%s, %02d:%02d.", unixtime / 86400, plural((unixtime / 86400)), (unixtime / 3600) % 24, (unixtime / 60) % 60); else if (unixtime > 3600) result = chanserv_asprintf(NULL, "alarmclock set to go off in %d hour%s, %d min%s.", unixtime / 3600, plural ((unixtime / 3600)), (unixtime / 60) % 60, plural (((unixtime / 60) % 60))); else result = chanserv_asprintf(NULL, "alarm clock set to go off in %d minute%s, %d sec%s.", unixtime / 60, unixtime / 60 == 1 ? "" : "s", unixtime % 60, unixtime % 60 == 1 ? "" : "s"); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_autotopic(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char topic [STRING_LONG] = {0}; if (!args || !args[0]) return result; if (db_argstostr(topic, args, 0, ' ') < 1) return result; set_autotopic (source, target, topic); return result; } #endif //#ifndef WIN32 struct chanserv_output *chanserv_backup(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { char temp[1024] = { 0 }; int ret; snprintf(temp, sizeof (temp), "/bin/cp -f %s %s_`date +%%F_%%R.bak`\n", URL2, URL2); ret = system(temp); return chanserv_asprintf(NULL, "Backed up database."); } //#endif #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_ban_list(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return show_banlist(source); } #endif #ifdef ENABLE_MATH struct chanserv_output *chanserv_calc(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; if (strlen(args[0]) > 200) args[0][200] = '\0'; return do_math(source, target, args[0]); } #endif struct chanserv_output *chanserv_chan_info(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; else /* If args[0] is not a valid channel name, just use the current channel */ result = show_chaninfo (source, ((*args[0] == '#' || *args[0] == '&' || *args[0] == '+') ? args[0] : target), target); return result; } struct chanserv_output *chanserv_chan_users(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) result = show_chanusers (source, target); else /* If args[0] is not a valid channel name, just use the current channel. */ result = show_chanusers (source, ((*args[0] == '#' || *args[0] == '&' || *args[0] == '+') ? args[0] : target)); return result; } struct chanserv_output *chanserv_char(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; return chanserv_asprintf(NULL, "%c -> %d.", args[0][0], args[0][0]); } struct chanserv_output *chanserv_char_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "My command char is: %c.", *CMDCHAR); } struct chanserv_output *chanserv_cpu_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { getrusage(RUSAGE_SELF, &r_usage); return chanserv_asprintf(NULL, "CPU usage: %ld.%06ld, System = %ld.%06ld.", r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec, r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec); } struct chanserv_output *chanserv_cycle(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; /* Check for channel list parameter being specified. */ if (!args | !args[0]) { S ("PART %s\n", target); S ("JOIN %s\n", target); } else { result = chanserv_asprintf(NULL, "Cycling %s.", args[0]); S("PART %s\n", args[0]); S("JOIN %s\n", args[0]); } return result; } struct chanserv_output *chanserv_data_search(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "What should I be %sing for?", cmd); printf ("args[0] = %s\n", args[0]); datasearch (source, args[0], target); return result; } struct chanserv_output *chanserv_date(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "%s.", date()); } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_delban(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Enter the user@host to purge!"); if (del_permban(source, args[0]) == 1) S("MODE %s -b %s\n", target, args[0]); else result = chanserv_asprintf(NULL, "No such ban."); return result; } #endif struct chanserv_output *chanserv_delete(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "%s what?", cmd); if (strlen (args[0]) > MAX_TOPIC_SIZE) args[0][MAX_TOPIC_SIZE] = '\0'; if (LOG_ADD_DELETES) db_log (ADD_DELETES, "[%s] %s!%s DEL %s\n", date (), source, userhost, args[0]); if (*args[0] == '~') { /* need level 2 to delete .rdb files */ if (invoked == MSG_INVOKE) { if (check_access (userhost, "#*", 0, source) >= 2) delete_url (source, args[0], source); } else { if (check_access (userhost, target, 0, source) >= 2) delete_url (source, args[0], target); } return result; } if (invoked == MSG_INVOKE) delete_url (source, args[0], source); else delete_url (source, args[0], target); return result; } struct chanserv_output *chanserv_deluser(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Enter the user@host to delete!"); delete_user_ram (source, args[0]); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_deop(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char users_to_deop [STRING_LONG] = {0}, chan[STRING_LONG] = {0}; /* Make sure first arg, which should be target chan, is there. */ if (!args || !args[0]) return result; strncpy (chan, args[0], sizeof (chan)); /* Chop of first arg, since we have a copy as chan. */ args++; db_argstostr (users_to_deop, args, 0, ' '); if ((invoked == MSG_INVOKE) || (*chan == '#')) { if (check_access (userhost, chan, 0, source) >= 3) { if (users_to_deop[0] == '\0') return result; S ("MODE %s -oooooo %s\n", chan, users_to_deop); } } else { if (users_to_deop[0] == '\0') S ("MODE %s -oooooo %s\n", target, chan); else S ("MODE %s -oooooo %s %s\n", target, chan, users_to_deop); } return result; } struct chanserv_output *chanserv_devoice(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char chan [STRING_LONG] = {0}, users_to_devoice [STRING_LONG] = {0}; if (!args || !args[0]) return result; strncpy (chan, args[0], sizeof (chan)); args++; db_argstostr (users_to_devoice, args, 0, ' '); if ((invoked == MSG_INVOKE) || (*chan == '#')) { if (check_access (userhost, chan, 0, source) >= 3) { if (users_to_devoice[0] == '\0') return result; S ("MODE %s -vvvvvv %s\n", chan, users_to_devoice); } } else { if (users_to_devoice[0] == '\0') S ("MODE %s -vvvvvvv %s\n", target, chan); else S ("MODE %s -vvvvvvv %s %s\n", target, chan, users_to_devoice); } return result; } #endif struct chanserv_output *chanserv_die(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char quit_message [STRING_LONG] = {0}; long unixtime = 0; if (!args || !args[0]) Snow("QUIT :K\2\2illed (%s (cause I say so!))\n", source); else { if ((db_argstostr (quit_message, args, 0, ' ')) < 1) return result; Snow("QUIT :K\2\2illed (%s (%s))\n", source, quit_message); } db_sleep (1); printf ("\n\nGood-bye! %s (c) Jason Hamilton\n\n", dbVersion); uptime = time (NULL) - uptime; printf("Time elapsed: %ld hour%s, %ld min%s\n\n", uptime / 3600, uptime / 3600 == 1 ? "" : "s", (uptime / 60) % 60, (uptime / 60) % 60 == 1 ? "" : "s"); db_sleep (5); exit (0); return result; } struct chanserv_output *chanserv_display(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; result = display_url(target, source, args[0]); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_down(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; S ("MODE %s -o %s\n", target, source); return result; } #endif struct chanserv_output *chanserv_darkbot(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (Sleep_Toggle == 1) return result; if (cf (userhost, source, target)) return result; return chanserv_asprintf(NULL, "%s reporting! My cmdchar is %c.", dbVersion, *CMDCHAR); } struct chanserv_output *chanserv_help(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char command [STRING_LONG] = {0}; char *chan = NULL; long user_level; if (!args || !args[0]) { result = chanserv_asprintf(result, "I can be triggered by various forms of speech, all which must be addressed to me, in one of the following formats: %s %s %s or even %s . In my database, you can find a topic by saying my nick, <topic> . eg; \37%s nuke\37 . To do a search on a word, or partial text, just type: search <text> or dsearch <text> , eg; \37search nuke\37.", NICK_COMMA, COLON_NICK, BCOLON_NICK, Mynick, NICK_COMMA); if (cf (userhost, source, target)) return result; result = chanserv_asprintf(result, "I can also be triggered with even more human formats: \37%s who is bill gates?\37 . You can also phrase it as a question: \37%s where is msie?\37 . For a list of commands use \37help commands\37 . For a list of setup parameters use \37help parameters\37 . For more info about me, visit http://darkbot.sourceforge.net .", NICK_COMMA, NICK_COMMA, NICK_COMMA); return (result); } if ((db_argstostr (command, args, 0, ' ')) < 1) return NULL; chan = (invoked == MSG_INVOKE) ? "#*" : target; user_level = check_access(userhost, chan, 0, source); result = chanserv_show_help(command, user_level); return result; } struct chanserv_output *chanserv_idle(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; long unixtime = 0; if (!args || !args[0]) return result; if (strcasecmp (args[0], source) == 0) return chanserv_asprintf(NULL, "Don't be lame."); unixtime = return_useridle (target, args[0], 0); if (unixtime == 0) return chanserv_asprintf(NULL, "I do not see %s in %s.", args[0], target); unixtime = time (NULL) - unixtime; if (unixtime > 86400) result = chanserv_asprintf(result, " %s has been idle %d day%s, %02d:%02d.", args[0], unixtime / 86400, (unixtime / 86400 == 1) ? "" : "s", (unixtime / 3600) % 24, (unixtime / 60) % 60); else if (unixtime > 3600) result = chanserv_asprintf(result, "%s has been idle %d hour%s, %d min%s.", args[0], unixtime / 3600, unixtime / 3600 == 1 ? "" : "s", (unixtime / 60) % 60, (unixtime / 60) % 60 == 1 ? "" : "s"); else result = chanserv_asprintf(result, " %s has been idle %d minute%s, %d sec%s.", args[0], unixtime / 60, unixtime / 60 == 1 ? "" : "s", unixtime % 60, unixtime % 60 == 1 ? "" : "s"); return result; } struct chanserv_output *chanserv_ignore(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Ignore who?"); if ( add_ignore_user_ram(args[0]) > 0 ) result = chanserv_asprintf(result, "Ignoring %s.", args[0]); else result = chanserv_asprintf(result, "Unable to ignore %s.", args[0]); return result; } struct chanserv_output *chanserv_info(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; info (source, (invoked == MSG_INVOKE) ? source : target); return result; } struct chanserv_output *chanserv_info_2(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return show_info2((invoked == MSG_INVOKE) ? source : target, source, invoked); } struct chanserv_output *chanserv_info_size(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; struct stat statbuf; if (stat (URL2, &statbuf) == 0) result = chanserv_asprintf(NULL, "My database file is presently %ld byte%s in size.", statbuf.st_size, ((statbuf.st_size == 1) ? "" : "s")); return result; } struct chanserv_output *chanserv_isop(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; result = chanserv_asprintf(NULL, "%s is %san op in channel %s.", args[0], is_op(args[0], target) ? "" : "not ", target); return result; } struct chanserv_output *chanserv_join(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) S ("JOIN %s\n", target); else { S ("JOIN %s\n", args[0]); result = chanserv_asprintf(NULL, "Joining %s.", args[0]); } return result; } struct chanserv_output *chanserv_joins_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "I have seen %d joins thus far.", JOINs); } struct chanserv_output *chanserv_jump(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char server [STRING_LONG] = {0}, port_argument [STRING_LONG] = {0}; long port = 0; if (!args || !args[0]) return result; strncpy (server, args[0], sizeof (server)); args++; if ((db_argstostr (port_argument, args, 0, ' ')) < 1) port = 6667; else port = atoi(port_argument); S ("QUIT :Jumping to %s:%d\n", server, port); db_sleep (1); strncpy (BS, server, sizeof (BS)); BP = port; prepare_bot (); register_bot (); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_kick(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char chan[STRING_LONG] = {0}, nick[STRING_LONG] = {0}, reason [STRING_LONG] = {0}; if (!args || !args[0]) return chanserv_asprintf(NULL, "Specify a nick/channel!"); if (invoked == MSG_INVOKE) { /* Copy channel variable and chuck it. */ strncpy (chan, args[0], sizeof (chan)); args++; /* Make sure first parameter is a channel name. */ if ((*chan != '#') && (*chan != '&')) return chanserv_asprintf (NULL, "You must specify a channel name first."); if (check_access (userhost, chan, 0, source) >= 3) { if (!args[0]) return chanserv_asprintf(NULL, "You must specity a nickname to kick!"); strncpy (nick, args[0], sizeof (nick)); args++; /* Remaining args are fed into reason. */ if ((db_argstostr (reason, args, 0, ' ')) < 1) S ("KICK %s %s %s\n", chan, nick, DEFAULT_KICK); else S ("KICK %s %s :%s\n", chan, nick, reason); return result; } } else { if (*args[0] != '#' && *args[0] != '&') { strncpy (nick, args[0], sizeof (nick)); args++; if (strcasecmp (nick, Mynick) == 0) S ("KICK %s %s :hah! As *IF*\n", target, source); if ((db_argstostr (reason, args, 0, ' ')) < 1) S ("KICK %s %s :\2%s\2'ed: %s\n", target, nick, cmd, DEFAULT_KICK); else S ("KICK %s %s :\2%s\2'ed: %s\n", target, nick, cmd, reason); } else { if (!args[0] || !args[1]) return chanserv_asprintf(result, "You must specify a nickname to kick!"); strncpy (chan, args[0], sizeof chan); args++; strncpy (nick, args[0], sizeof nick); args++; if (strcasecmp (nick, Mynick) == 0) S ("KICK %s %s :hah! As *IF*\n", target, nick); if ((db_argstostr (reason, args, 0, ' ')) < 1) S ("KICK %s %s :\2%s\2ed: %s\n", chan, nick, cmd, DEFAULT_KICK); else S ("KICK %s %s :\2%s\2ed: %s\n", chan, nick, cmd, reason); } } return result; } #endif struct chanserv_output *chanserv_language(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { - return chanserv_asprintf(NULL, "I speak English."); + return chanserv_asprintf(NULL, I_SPEAK); } struct chanserv_output *chanserv_leave(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char chan [STRING_LONG] = {0}, reason [STRING_LONG] = {0}; if (!args || !args[0]) S ("PART %s\n", target); else { strncpy (chan, args[0], sizeof chan); args++; /* Don't bother telling the channel we left about it. */ if ((strcasecmp (target, chan)) != 0) result = chanserv_asprintf(result, "Leaving %s.", chan); if ((db_argstostr (reason, args, 0, ' ')) < 1) S ("PART %s :Requested!\n", chan); else S ("PART %s :%s\n", chan, reason); } return (result); } struct chanserv_output *chanserv_length(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char str [STRING_LONG] = {0}; if (!args || !args[0]) return result; if ((db_argstostr (str, args, 0, ' ')) == 0) strcpy(str, args[0]); return chanserv_asprintf(NULL, "It was %d characters long.", strlen (str)); } struct chanserv_output *chanserv_level(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char *uh; if (!args || !args[0]) return result; uh = uh_from_nick(args[0], target); if (uh) result = chanserv_asprintf(result, "%s is level %ld in channel %s.", args[0], check_access(uh, target, 0, args[0]), target); return result; } struct chanserv_output *chanserv_location_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "There %s %d server%s in my server list. I am currently on server #%d.", (snr == 1) ? "is" : "are", snr, (snr == 1) ? "" : "s", spr); } struct chanserv_output *chanserv_login(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; do_login (source, args[0]); return result; } struct chanserv_output *chanserv_mask(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if(!args || !args[0]) return result; return chanserv_asprintf(NULL, " %s", (invoked == MSG_INVOKE) ? mask_from_nick(args[0], "#*") : mask_from_nick(args[0], target)); } //#ifndef WIN32 struct chanserv_output *chanserv_memory(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { char command[1024] = { 0 }; snprintf(command, sizeof (command), "ps u -p %d\n", getpid()); const char *ptr = run_program (command); if (ptr == NULL) return chanserv_asprintf(NULL, "Unable to gather data for mem output.\n"); else return chanserv_asprintf(NULL, "ps: %s", ptr); } //#endif #ifdef ENABLE_METAR struct chanserv_output *chanserv_metar(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if(!args || !args[0]) return chanserv_asprintf(NULL, "Metar what?"); result = web_post_query (cmd, source, userhost, target, args[0], strlen(args[0])); return result; } #endif struct chanserv_output *chanserv_nick(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; // If no nick was specified... if(!args || !args[0]) return chanserv_asprintf(NULL, "Specify a nick!"); // If the nick specified contains illegal characters... if(strspn(args[0], LEGAL_NICK_TEXT) != strlen(args[0])) return chanserv_asprintf(NULL, "The nickname %s contains illegal characters.", args[0]); if (isdigit(args[0][0])) return chanserv_asprintf(NULL, "The nickname %s should not start with a digit.", args[0]); S("NICK %s\n", args[0]); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_op(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char nicks [STRING_LONG] = {0}, chan [STRING_LONG] = {0}; int ischan = 0; if (!args[0]) return chanserv_asprintf (NULL, "You must specify a nickname/channel!."); /* Check for channel name specified, set up args accordingly. */ if ((*args[0] == '#') || (*args[0] == '&')) { ischan = 1; /* channel specified */ strncpy (chan, args[0], sizeof chan); args++; } if ((db_argstostr (nicks, args, 0, ' ')) < 1) return chanserv_asprintf (NULL, "You must specify a nickname to op."); if ((invoked == MSG_INVOKE) || (ischan == 1)) { /* If MSG_INVOKE, make sure chan == 1. This seems weird, but * we could have MSG_INVOKE without channel specified. */ if (ischan != 1) return chanserv_asprintf (NULL, "You must specify a channel to deop people on."); if (check_access (userhost, chan, 0, source) >= 3) { S ("MODE %s +oooooo %s\n", chan, nicks); return result; } } else S ("MODE %s +oooooo %s\n", target, nicks); return result; } #endif struct chanserv_output *chanserv_os_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char command[1024] = { 0 }; char *reply = NULL; #ifdef WIN32 snprintf (command, sizeof (command), "cmd /c ver\n"); #else snprintf (command, sizeof (command), "uname\n"); #endif return chanserv_asprintf(NULL, "I am running %s.", run_program(command)); } struct chanserv_output *chanserv_password(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (args[0] == NULL || args[1] == NULL) return result; if (strlen(args[1]) > 25) args[1][25] = '\0'; set_pass(source, userhost, args[0], args[1]); return result; } struct chanserv_output *chanserv_performs(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { /* Set the default umodes */ S ("MODE %s %s\n", Mynick, DEFAULT_UMODE); run_perform (); return chanserv_asprintf(NULL, "Performs have been executed."); } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_perm_ban(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char reason [STRING_LONG] = {0}, host [STRING_LONG] = {0}; if (!args || !args[0]) return result = chanserv_asprintf(result, "Type !help permbans"); strncpy (host, args[0], sizeof host); args++; if ((db_argstostr (reason, args, 0, ' ')) < 1) strncpy (reason, "Permbanned!", sizeof reason); add_permban(host, 0, reason); result = chanserv_asprintf(result, "Added in permban #%d, %s; reason: %s.", PERMBAN_counter, host, reason); save_permbans(); S("MODE %s +b %s\n", target, host); /* FIXME: Scan for user in room and kick them with reason. */ return result; } struct chanserv_output *chanserv_perm_bans_list(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "There %s %d permban%s loaded into ram.", (PERMBAN_counter == 1) ? "is" : "are", PERMBAN_counter, (PERMBAN_counter == 1) ? "" : "s"); } #endif #ifdef ENABLE_CTCP struct chanserv_output *chanserv_ping(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (cf(userhost, source, target)) return result; if (cf(userhost, source, target)) return result; if (args[0] != NULL) { if (strlen (args[0]) > 21) args[0][21] = '\0'; S ("NOTICE %s :\1PING %s\n", source, args[0]); } return result; } #endif struct chanserv_output *chanserv_ping2(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "PONG!"); } struct chanserv_output *chanserv_queue_show(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "There is currently %d item%s in queue.", get_sendq_count(2), (get_sendq_count(2) == 1) ? "" : "s"); } #ifdef ENABLE_QUIZ struct chanserv_output *chanserv_quiz(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (quiz_halt == 0) result = run_quiz_question (target); return result; } #endif #ifdef ENABLE_RANDQ struct chanserv_output *chanserv_quote(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return do_randq(args[0], RANDQ_RAND, target, source); } struct chanserv_output *chanserv_random_quote(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { if (!args || !args[0]) return chanserv_asprintf (NULL, "You must specify a search string."); // RANDQ_NORMAL return do_randq(args[0], RANDQ_NORMAL, target, source); } struct chanserv_output *chanserv_random_quote_2(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { if (!args || !args[0]) return chanserv_asprintf (NULL, "You must specify a search string."); // RANDQ_CASE return do_randq(args[0], RANDQ_CASE, target, source); } #endif #ifdef ENABLE_RANDOM struct chanserv_output *chanserv_random_stuff(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char text_to_add [STRING_LONG] = {0}; /* Fill argument buffer, if it's empty we return a message to * the user asking for input. */ if (!args || !args[0]) return chanserv_asprintf(NULL, "What do you want to add?"); if ((db_argstostr (text_to_add, args, 0, ' ')) < 1) return result; if (invoked == MSG_INVOKE) { if (check_access (userhost, "#*", 0, source) >= RAND_LEVEL) { if ((db_argstostr (text_to_add, args, 0, ' ')) < 1) return chanserv_asprintf(NULL, "What do you want to add?"); add_randomstuff(source, source, text_to_add); } } else add_randomstuff(source, target, text_to_add); return result; } struct chanserv_output *chanserv_random_stuff_list(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "%d seconds left till randstuff.", Rand_Stuff); } #endif struct chanserv_output *chanserv_raw(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char rawdata [STRING_LONG] = {0}; if (!args || !args[0]) return result; if ((db_argstostr (rawdata, args, 0, ' ')) < 1) return result; Snow("%s\n", rawdata); return result; } //#ifndef WIN32 struct chanserv_output *chanserv_rdb(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char command[1024] = { 0 }; char str [STRING_LONG] = {0}; /* Check for arguments */ if (!args || !args[0]) { snprintf(command, sizeof (command), "ls %s/*.rdb | wc\n", RDB_DIR); result = chanserv_asprintf(result, "RDB: %s.", run_program(command)); } else { if ((db_argstostr (str, args, 0, ' ')) < 1) return result; if (strspn(str, SAFE_LIST) != strlen(str)) return chanserv_asprintf(NULL, "Rdb files are made up of letters and or numbers, no other text is accepted."); snprintf(command, sizeof (command), "cat %s/%s.rdb | wc -l\n", RDB_DIR, str); result = chanserv_asprintf(result, "%s", run_program(command)); } return result; } //#endif struct chanserv_output *chanserv_repeat(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; long delay = 0, count = 0; char rawdata [STRING_LONG] = {0}; if (!args || !args[0] || !args[1] || !args[2]) return result; count = atoi (args[0]); delay = atoi (args[1]); if ((db_argstostr (rawdata, args, 2, ' ')) < 1) return result; while (count > 0) { S ("%s\n", rawdata); db_sleep (delay); count--; } return result; } struct chanserv_output *chanserv_replace(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char topic [STRING_LONG] = {0}, text [STRING_LONG] = {0}; if (!args || !args[0]) return chanserv_asprintf(NULL, "Replace what?"); if (strlen(args[0]) > MAX_TOPIC_SIZE) args[0][MAX_TOPIC_SIZE] = '\0'; /* Copy topic, and traverse args for data to be replaced. */ strncpy (topic, args[0], sizeof topic); args++; /* Make sure there's information to be replaced. */ if ((db_argstostr (text, args, 0, ' ')) < 1) return chanserv_asprintf(NULL, "What info should replace %s?", topic); /* Don't let str go over MAX_DATA_SIZE characters. */ if (strlen(text) > MAX_DATA_SIZE) text[MAX_DATA_SIZE] = '\0'; strlwr(topic); if (check_existing_url(source, topic, target) != 1) return chanserv_asprintf(NULL, "%s \37%s\37", NO_ENTRY, topic); /* Replace the data. */ delete_url (source, topic, target); if (LOG_ADD_DELETES) db_log (ADD_DELETES, "[%s] %s!%s REPLACE %s %s\n", date (), source, userhost, topic, text); ADDITIONS++; db_log (URL2, "%s %s\n", topic, text); return chanserv_asprintf(NULL, "%s has been updated.", topic); } struct chanserv_output *chanserv_reserved_1(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; call_reserved_1(source, target, args[0]); return result; } struct chanserv_output *chanserv_reserved_2(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result; call_reserved_2(source, target, args[0]); return result; } struct chanserv_output *chanserv_restart(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char command[1024] = { 0 }; int ret; S("QUIT :Restarting %s ...\n", dbVersion); db_sleep(2); snprintf(command, sizeof (command), "%s", DARKBOT_BIN); ret = system(command); db_sleep(1); exit(0); return result; } struct chanserv_output *chanserv_search(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) { if (strcasecmp(cmd, "FIND") == 0) result = chanserv_asprintf(NULL, "%s?", TRY_FIND); else result = chanserv_asprintf(NULL, "What should I be %sing for?", cmd); return result; } find_url(source, args[0], target); return result; } struct chanserv_output *chanserv_seen(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) { count_seen(source, target); return result; } if (return_useridle (target, args[0], 1) == 1) return chanserv_asprintf(NULL, "%s is right here in the channel!", args[0]); result = show_seen(args[0], source, target); return result; } struct chanserv_output *chanserv_set(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; struct setup_parameter *param = NULL; if (!args || !args[0]) return result; param = set_parameter(args[0]); if (param) { switch (param->type) { case ST_BOOLEAN : { bool *variable = param->value; result = chanserv_asprintf(result, "Setting %s = %s", param->summary, (*variable) ? "true" : "false"); break; } case ST_INTEGER : { long *variable = param->value; result = chanserv_asprintf(result, "Setting %s = %ld", param->summary, *variable); break; } case ST_STRING : { char *variable = param->value; result = chanserv_asprintf(result, "Setting %s = %s", param->summary, variable); break; } } save_setup(); } else result = chanserv_asprintf(result, "Unknown parameter."); return result; } struct chanserv_output *chanserv_setinfo(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char greeting [STRING_LONG] = {0}; if (!args) return chanserv_asprintf (NULL, "My %s variables are: ^ nick, %% number of joins, & Channel, $ user@host. Example: !setinfo ^ has joined & %% times (also, if you make the first char of your %s a \"+\", the %s will be shown as an ACTION).", cmd, cmd, cmd); if ((db_argstostr (greeting, args, 0, ' ')) < 1) return NULL; update_setinfo (userhost, greeting, source); return (result); } struct chanserv_output *chanserv_sleep(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char period [STRING_LONG] = {0}; Sleep_Toggle = 1; /* Copy arguments to buffer, if there is one convert to long * and use it as the sleep time in seconds. */ if ((db_argstostr (period, args, 0, '\0')) < 1) Sleep_Time = SLEEP_TIME; else if ((Sleep_Time = strtol (period, (char **) NULL, 10)) < 1) Sleep_Time = SLEEP_TIME; strncpy (sleep_chan, target, sizeof (sleep_chan)); /* If the user has specified a custom length of time to sleep for, send * a notice reminding the user how long the bot will be asleep, in a * more readable format. */ if (Sleep_Time != SLEEP_TIME) { if (Sleep_Time > 86400) result = chanserv_asprintf(result, "Sleeping for %ld day%s, %02ld:%02ld.", Sleep_Time / 86400, (Sleep_Time / 86400 == 1) ? "" : "s", (Sleep_Time / 3600) % 24, (Sleep_Time / 60) % 60); else if (Sleep_Time > 3600) result = chanserv_asprintf(result, "Sleeping for %ld hour%s, %ld min%s.", Sleep_Time / 3600, Sleep_Time / 3600 == 1 ? "" : "s", (Sleep_Time / 60) % 60, (Sleep_Time/ 60) % 60 == 1 ? "" : "s"); else result = chanserv_asprintf(result, "Sleeping for %ld minute%s, %ld sec%s.", Sleep_Time / 60, Sleep_Time / 60 == 1 ? "" : "s", Sleep_Time % 60, Sleep_Time % 60 == 1 ? "" : "s"); } else S ("PRIVMSG %s :%s\n", target, GOSLEEP_ACTION); return result; } #ifdef ENABLE_STATS struct chanserv_output *chanserv_stats(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return result = chanserv_asprintf (NULL, "Syntax: %s <nick>", cmd); result = get_stats(target, args[0]); return result; } #endif #ifdef ENABLE_TAF struct chanserv_output *chanserv_taf(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if(!args || !args[0]) return chanserv_asprintf(NULL, "Taf what?"); result = web_post_query(cmd, source, userhost, target, args[0], strlen(args[0])); return result; } #endif #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_teaseop(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Specify a nick!"); if (strcasecmp (args[0], Mynick) == 0) result = chanserv_asprintf(result, "How about I not do that?"); else S ("MODE %s +o-o+o-o+o-o %s %s %s %s %s %s\n", target, args[0], args[0], args[0], args[0], args[0], args[0]); return result; } #endif struct chanserv_output *chanserv_tell(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char topic [STRING_LONG] = {0}; if (!args || !args[0]) return chanserv_asprintf(NULL, "Tell who?"); if (!args[1]) return chanserv_asprintf(NULL, "What do you want me to tell %s?", args[0]); if (strcasecmp (args[1], Mynick) == 0) return result; /* don't bother telling myself about stuff */ if (strcasecmp (args[1], "ABOUT") == 0) { if ((db_argstostr (topic, args, 2, '+')) < 1) return chanserv_asprintf(NULL, "Tell %s about what?", args[0]); strlwr(topic); if (invoked == MSG_INVOKE) result = show_url (source, get_multiword_topic (topic), args[0], 1, 0, userhost, 1); else result = show_url (args[0], get_multiword_topic (topic), target, 1, 0, userhost, 1); } else { if ((db_argstostr (topic, args, 1, '+')) < 1) return chanserv_asprintf (NULL, "Tell %s about what?", args[0]); strlwr(topic); if (invoked == MSG_INVOKE) result = show_url (source, get_multiword_topic (topic), args[0], 1, 0, userhost, 1); else result = show_url (args[0], get_multiword_topic (topic), target, 1, 0, userhost, 1); } return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_topic(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char str [STRING_LONG] = {0}; if ((db_argstostr (str, args, 0, ' ')) < 1) return chanserv_asprintf (NULL, "What do you want the topic changed to?"); else S ("TOPIC %s :%s\n", target, str); return result; } #endif struct chanserv_output *chanserv_unignore(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Unignore who?"); if ( delete_ignore_user_ram (args[0]) > 0 ) result = chanserv_asprintf(result, "Unignoring %s.", args[0]); else result = chanserv_asprintf(result, "Unable to unignore %s. :(", args[0]); return result; } struct chanserv_output *chanserv_unixtime(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; time_t delta_t = 0, input_t = 0, cur_t = 0; char *things = NULL; int errno; /* Make sure current time is available while acquiring it. */ if ((cur_t = time (NULL)) < 0) { result = chanserv_asprintf (result, "Unable to produce results because current system time is unavailable."); return (result); } /* Print current time when no argument is given */ if (!args || !args[0]) { result = chanserv_asprintf (result, "%ld", cur_t); return result; } /* Convert input value to time_t. We check if the return value is * 0 here, but our main concern is if things is NULL, because that * would mean the function converted a string value "0", instead * of returning a failing code. Set errno to 0 first as for a * precautionary measure. */ errno = 0; if ((input_t = (time_t) strtol (args[0], &things, 10)) == 0) { if (things == NULL) { result = chanserv_asprintf (result, "%s (things = %s)", strerror (errno), things); return (result); } /* things was not NULL, this is "0" converted to long. * So we continue as if nothing happened. */ } /* Check for out of range values, tell the user which range * was exceeded, perhaps for debugging purposes. */ if (errno == ERANGE) { result = chanserv_asprintf (result, "Your implementation does not support numeric ranges beyond %ld for this function.", input_t); return (result); } delta_t = input_t - cur_t; if (delta_t > 86400) result = chanserv_asprintf(result, "%d day%s, %02d:%02d.", delta_t / 86400, plural (delta_t / 86400), (delta_t / 3600) % 24, (delta_t / 60) % 60); else if (delta_t > 3600) result = chanserv_asprintf(result, "%d hour%s, %d min%s.", delta_t / 3600, plural(delta_t / 3600), (delta_t / 60) % 60, plural(delta_t / 60)); else result = chanserv_asprintf(result, "%d minute%s, %d sec%s.", delta_t / 60, plural(delta_t / 60), delta_t % 60, plural(delta_t % 60)); return result; } #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_up(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; S ("MODE %s +o %s\n", target, source); return result; } #endif //#ifndef WIN32 struct chanserv_output *chanserv_uptime(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { char command[1024] = { 0 }; snprintf(command, sizeof (command), "uptime\n"); return chanserv_asprintf(NULL, "Uptime: %s.", run_program(command)); } //#endif struct chanserv_output *chanserv_user_list(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; int i = 0; if (!args) { result = show_helper_list(result, source, 0); } else { int level = 0; for (i = 0; args[i]; i++) result = show_helper_list(result, source, atoi (args[i])); } return result; } #ifdef ENABLE_STATUS struct chanserv_output *chanserv_users_list(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; S ("LUSERS\n"); return result; } #endif struct chanserv_output *chanserv_variables(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { return chanserv_asprintf(NULL, "Data variables are: N~ (Nick), C~ (Chan), T~ (Time/date) B~ (Botnick), Q~ (Question asked), R~ (random nick), !~ (command char), S~ (current Server), P~ (current port) V~ (botVer), W~ (db WWW site), H~ (u@h), t~ (unixtime), BAN (sets a ban), TEMPBAN (bans for 60 sec)."); } #ifdef ENABLE_CTCP struct chanserv_output *chanserv_version(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (cf (userhost, source, target)) return result; if (cf (userhost, source, target)) return result; return chanserv_asprintf(NULL, "\1VERSION Hi, I'm a Darkbot. Download me from http://darkbot.sourceforge.net\1."); } #endif #ifdef ENABLE_CHANNEL struct chanserv_output *chanserv_voice(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char nicks [STRING_LONG] = {0}, chan [STRING_LONG] = {0}, str [STRING_LONG] = {0}; int ischan = 0; if (!args[0]) return result; db_argstostr (str, args, 0, ' '); /* Check for channel name specified, set up args accordingly. */ if ((*args[0] == '#') || (*args[0] == '&')) { ischan = 1; /* channel specified */ strncpy (chan, args[0], sizeof chan); args++; } if ((db_argstostr (nicks, args, 0, ' ')) < 1) return chanserv_asprintf (NULL, "You must specify a nickname to voice."); if ((invoked == MSG_INVOKE) || (ischan == 1)) { /* If MSG_INVOke, make sure chan ==1. This seems weird, * but we could have MSG_INVOKE without a channel given, * and this is an error. */ if (ischan != 1) return chanserv_asprintf (NULL, "You must specify a channel to give voice on."); if (check_access (userhost, chan, 0, source) >= 3) { S ("MODE %s +vvvvvv %s\n", chan, nicks); return result; } } else S ("MODE %s +vvvvvv %s\n", target, nicks); return result; } #endif struct chanserv_output *chanserv_wakeup(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (Sleep_Toggle == 0) return result; Sleep_Toggle = 0; AIL4 = 0; S ("PRIVMSG %s :%s\n", target, WAKEUP_ACTION); if (strcasecmp (sleep_chan, target) != 0) S ("PRIVMSG %s :%s\n", sleep_chan, WAKEUP_ACTION); return result; } #ifdef ENABLE_WEATHER struct chanserv_output *chanserv_weather(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "Show weather from where?"); result = web_post_query(cmd, source, userhost, target, args[0], strlen(args[0])); return result; } #endif #ifdef ENABLE_WEBSEARCH struct chanserv_output *chanserv_websearch(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; if(!args || !args[0]) return chanserv_asprintf(NULL, "Web search for what?"); result = web_post_query(cmd, source, userhost, target, args[0], strlen(args[0])); return result; } #endif struct chanserv_output *chanserv_where(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char topic [STRING_LONG] = {0}; char *ptr3 = NULL; if (!args || !args[0]) return chanserv_asprintf(NULL, "You were asking?"); if (args[1] == NULL) return result; strlwr (args[1]); ptr3 = strchr (args[1], '?'); if (ptr3 != NULL) memmove (ptr3, ptr3 + 1, strlen (ptr3 + 1) + 1); ptr3 = strchr (args[1], '!'); if (ptr3 != NULL) memmove (ptr3, ptr3 + 1, strlen (ptr3 + 1) + 1); if (strcasecmp (args[1], "A") == 0 || strcasecmp (args[1], "AN") == 0) { if ((db_argstostr (topic, args, 2, ' ')) < 1) return chanserv_asprintf(NULL, "%s %s %s? Mind rephrasing that? (Type %cHELP for syntax hints).", cmd, args[0], args[1], *CMDCHAR); result = show_url (source, get_multiword_topic (topic), (invoked == MSG_INVOKE) ? source : target, 1, 0, userhost, 0); } else result = show_url (source, get_multiword_topic (args[1]), (invoked == MSG_INVOKE) ? source : target, 1, 0, userhost, 0); return result; } struct chanserv_output *chanserv_whisper(char *source, char *target, char *cmd, char **args, enum chanserv_invoke_type invoked, char *userhost) { struct chanserv_output *result = NULL; char topic [STRING_LONG] = {0}; if (!args || !args[0]) return chanserv_asprintf(NULL, "Whisper to who?"); if (args[1] == NULL) return chanserv_asprintf(NULL, "What do you want me to whisper to %s?", args[0]); if (strcasecmp (args[1], Mynick) == 0) return result; /* don't bother telling myself about stuff */ if (strcasecmp (args[1], "ABOUT") == 0) { if ((db_argstostr (topic, args, 2, ' ')) < 1) return chanserv_asprintf(NULL, "Whisper to %s about what?", args[0]); strlwr(topic); result = show_url(source, get_multiword_topic(topic), args[0], 1, 0, userhost, 1); } else { strlwr (args[1]); result = show_url(source, get_multiword_topic(args[1]), args[0], 1, 0, userhost, 1); } return result; } /* The help system uses the first alias for each command for the list of commands. * So make the first alias the most meaningful, and keep the list sorted by that first alias. */ struct chanserv_command chanserv_commands[] = { {NORMAL_COMMAND, ADD_LEVEL, 1, 0, chanserv_add, {"ADD", "REMEMBER", "SAVE", "STORE", NULL}, "<topic> <text>", "Add a topic and it's text."}, {PASSWORD_COMMAND, 3, 4, 0, chanserv_add_user, {"ADDUSER", NULL, NULL, NULL, NULL}, "<#channel|#*> <user@host> <level> [password]", "Add a user to the access list."}, {SAFE_COMMAND, 2, 2, 0, chanserv_alarm, {"ALARM", "ALARMCLOCK", NULL, NULL, NULL}, "<time type: d/h/m><time> <text to say>", "Set some text to be said by the bot at a later time."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_autotopic, {"AUTOTOPIC", NULL, NULL, NULL, NULL}, "<channel topic>", "Refreshes the channel topic every thirty minutes (set to \"0\" to turn off)."}, #endif //#ifndef WIN32 {DANGER_COMMAND, 3, 0, 0, chanserv_backup, {"BACKUP", NULL, NULL, NULL, NULL}, NULL, "Create a backup of the database."}, //#endif #ifdef ENABLE_CHANNEL {INFO_COMMAND, 1, 0, 0, chanserv_ban_list, {"BANLIST", NULL, NULL, NULL, NULL}, NULL, "Displays permanent bans."}, #endif #ifdef ENABLE_MATH {INFO_COMMAND, 0, 1, 0, chanserv_calc, {"CALC", "MATH", NULL, NULL, NULL}, "<expression>", "Very basic calculator."}, #endif {INFO_COMMAND, 0, 1, 0, chanserv_chan_info, {"CHANINFO", NULL, NULL, NULL, NULL}, "<#channel>", "Displays number of users in channel and in ram."}, {INFO_COMMAND, 0, 1, 0, chanserv_chan_users, {"CHANUSERS", NULL, NULL, NULL, NULL}, "<#channel>", "Displays names of users in channel."}, {INFO_COMMAND, 0, 1, 0, chanserv_char, {"CHAR", NULL, NULL, NULL, NULL}, "<character>", "Show the ascii code of the character."}, {INFO_COMMAND, 0, 0, 1, chanserv_char_show, {"CMDCHAR?", NULL, NULL, NULL, NULL}, NULL, "Show command character."}, {INFO_COMMAND, 0, 0, 1, chanserv_cpu_show, {"CPU?", NULL, NULL, NULL, NULL}, NULL, "Show the cpu usage of the bot."}, {DANGER_COMMAND, 2, 0, 0, chanserv_cycle, {"CYCLE", "CYC", NULL, NULL, NULL}, "[#channel]", "Leave and rejoin the channel."}, {INFO_COMMAND, 0, 1, 0, chanserv_data_search, {"DATASEARCH", "DSEARCH", "DFIND", NULL, NULL}, "<topic>", "Search in the replies."}, {INFO_COMMAND, 0, 0, 0, chanserv_date, {"DATE", "TIME", NULL, NULL, NULL}, NULL, "Show the current date and time."}, {DANGER_COMMAND, 0, 1, 0, chanserv_reserved_2, {RESERVED2, NULL, NULL, NULL, NULL}, "<>", ""}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_delban, {"DELBAN", NULL, NULL, NULL, NULL}, "<user@host>", "Delete a user from the permanent ban list."}, #endif {NORMAL_COMMAND, DEL_LEVEL, 1, 0, chanserv_delete, {"DELETE", "DEL", "REMOVE", "FORGET", NULL}, "<topic>", "Delete a topic."}, {DANGER_COMMAND, 3, 1, 0, chanserv_deluser, {"DELUSER", NULL, NULL, NULL, NULL}, "<user@host>", "Delete a user from the access list."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_deop, {"DEOP", NULL, NULL, NULL, NULL}, "[#channel] <nicks>", "Remove channel operator status from users."}, {NORMAL_COMMAND, 3, 1, 0, chanserv_devoice, {"DEVOICE", "DV", "DEV", "DVOICE", NULL}, "[#channel] <nicks>", "Remove channel voice status from users."}, #endif {DANGER_COMMAND, 3, 0, 0, chanserv_die, {"DIE", "QUIT", NULL, NULL, NULL}, NULL, "Stop bot from running."}, {INFO_COMMAND, 0, 1, 0, chanserv_display, {"DISPLAY", NULL, NULL, NULL, NULL}, "<topic>", "Display the text for a topic."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 2, 0, 0, chanserv_down, {"DOWN", NULL, NULL, NULL, NULL}, NULL, "Remove channel operator status from yourself."}, #endif {INFO_COMMAND, 0, 0, 0, chanserv_darkbot, {"\2\2DARKBOT", NULL, NULL, NULL, NULL}, NULL, ""}, {DANGER_COMMAND, 0, 1, 0, chanserv_reserved_1, {RESERVED1, NULL, NULL, NULL, NULL}, "<>", ""}, {INFO_COMMAND, 0, 0, 0, chanserv_help, {"HELP", NULL, NULL, NULL, NULL}, "[command]", "Show some help text to the user."}, {INFO_COMMAND, 0, 1, 0, chanserv_idle, {"IDLE", NULL, NULL, NULL, NULL}, "<nick>", "Shows how long the user has been idle."}, {DANGER_COMMAND, 1, 1, 0, chanserv_ignore, {"IGNORE", NULL, NULL, NULL, NULL}, "<nick>", "Get bot to ignore a user."}, {INFO_COMMAND, 0, 0, 1, chanserv_info, {"INFO", NULL, NULL, NULL, NULL}, NULL, "Shows some information about bot and it's activity."}, {INFO_COMMAND, 0, 0, 1, chanserv_info_2, {"INFO2", NULL, NULL, NULL, NULL}, NULL, "Shows when the bot was compiled, and lines processed since startup."}, {INFO_COMMAND, 2, 0, 1, chanserv_info_size, {"INFOSIZE", "DBSIZE", NULL, NULL, NULL}, NULL, "Show size of the database."}, {INFO_COMMAND, 0, 1, 0, chanserv_isop, {"ISOP", NULL, NULL, NULL, NULL}, "<nick>", "Is user a channel op?"}, {DANGER_COMMAND, 2, 1, 0, chanserv_join, {"JOIN", "J", NULL, NULL, NULL}, "<#channel>", "Get bot to join a channel."}, {INFO_COMMAND, 0, 0, 1, chanserv_joins_show, {"JOINS?", NULL, NULL, NULL, NULL}, NULL, "Shows the number of user joins bot has seen in this channel since startup."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_kick, {"KICK", "WHACK", "K", "NAIL", NULL}, "[#channel] <nick> [reason]", "Kick a user off the channel."}, #endif {INFO_COMMAND, 0, 0, 0, chanserv_language, {"LANGUAGE", "LANG", NULL, NULL, NULL}, NULL, "Shows the language that bot is currently speaking."}, {DANGER_COMMAND, 2, 0, 0, chanserv_leave, {"LEAVE", "PART", "L", "P", NULL}, "[#channel]", "Get bot to leave the channel."}, {INFO_COMMAND, 0, 1, 0, chanserv_length, {"LENGTH", NULL, NULL, NULL, NULL}, "<text>", "Show the length of the text."}, {INFO_COMMAND, 0, 1, 0, chanserv_level, {"LEVEL", NULL, NULL, NULL, NULL}, "<nick>", "Show users level."}, {INFO_COMMAND, 0, 0, 0, chanserv_location_show, {"LOCATION?", NULL, NULL, NULL, NULL}, NULL, "Shows what servers are available and in use."}, {PASSWORD_COMMAND, 0, 1, 0, chanserv_login, {"LOGIN", NULL, NULL, NULL, NULL}, "<password>", "Gives you access to high level bot commands if you are on the access list."}, #ifdef ENABLE_STATUS {INFO_COMMAND, 1, 0, 0, chanserv_users_list, {"LUSERS", NULL, NULL, NULL, NULL}, NULL, ""}, #endif {INFO_COMMAND, 0, 1, 0, chanserv_mask, {"MASK", NULL, NULL, NULL, NULL}, "<nick>", "Show the users user@host mask."}, //#ifndef WIN32 {INFO_COMMAND, 3, 0, 1, chanserv_memory, {"MEM", "RAM", NULL, NULL, NULL}, NULL, "Shows some memory usage and process statistics."}, //#endif #ifdef ENABLE_METAR {NORMAL_COMMAND, 0, 1, 0, chanserv_metar, {"METAR", NULL, NULL, NULL, NULL}, "<city or code>", "Get raw METAR weather data."}, #endif {DANGER_COMMAND, 3, 1, 0, chanserv_nick, {"NICK", "N", NULL, NULL, NULL}, "<newnick>", "Change bot's nickname, but not the default."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_op, {"OP", NULL, NULL, NULL, NULL}, "[#channel] <nicks>", "Add channel operator status to users."}, #endif {INFO_COMMAND, 0, 0, 1, chanserv_os_show, {"OS", NULL, NULL, NULL, NULL}, NULL, "Show the operating system that bot is running on."}, {PASSWORD_COMMAND, 0, 2, 0, chanserv_password, {"PASSWORD", "PASS", "PASSWD", NULL, NULL}, "<old password> <new password>", "Change your bot access list password."}, {DANGER_COMMAND, 3, 0, 0, chanserv_performs, {"PERFORMS", NULL, NULL, NULL, NULL}, NULL, "Perform the tasks in the perform.ini startup script."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 3, 1, 0, chanserv_perm_ban, {"PERMBAN", "SHITLIST", NULL, NULL, NULL}, "<user@host> [reason]", "Adds a user to the permanent ban list."}, {INFO_COMMAND, 0, 0, 0, chanserv_perm_bans_list, {"PERMBANS?", NULL, NULL, NULL, NULL}, NULL, "Shows how many permanent bans there are."}, #endif #ifdef ENABLE_CTCP {INFO_COMMAND, 0, 1, 0, chanserv_ping, {"\1PING", NULL, NULL, NULL, NULL}, "<>", ""}, #endif {INFO_COMMAND, 0, 0, 0, chanserv_ping2, {"PING", NULL, NULL, NULL, NULL}, NULL, "Replies with \"PONG\" to see how lagged the bot is.."}, {INFO_COMMAND, 0, 0, 0, chanserv_queue_show, {"SENDQ?", "QUE?", NULL, NULL, NULL}, NULL, "Shows how many items are ready to be displayed."}, #ifdef ENABLE_QUIZ {SAFE_COMMAND, 0, 0, 0, chanserv_quiz, {"QUIZ", NULL, NULL, NULL, NULL}, NULL, ""}, #endif #ifdef ENABLE_RANDQ {NORMAL_COMMAND, 0, 1, 0, chanserv_quote, {"QUOTE", NULL, NULL, NULL, NULL}, "[text]", "Shows a random quote."}, {NORMAL_COMMAND, 0, 1, 0, chanserv_random_quote, {"RANDQUOTE", "RANDQ", NULL, NULL, NULL}, "[text]", "Shows a random quote."}, {NORMAL_COMMAND, 0, 1, 0, chanserv_random_quote_2, {"RANDQUOTE2", "RANDQ2", NULL, NULL, NULL}, "[text]", "Shows a random quote."}, #endif #ifdef ENABLE_RANDOM {NORMAL_COMMAND, RAND_LEVEL, 1, 0, chanserv_random_stuff, {"RANDOMSTUFF", "RANDSTUFF", "RS", "ZADD", NULL}, "<text>", "Add random stuff to say."}, {INFO_COMMAND, 0, 0, 0, chanserv_random_stuff_list, {"RANDOMSTUFF?", "RANDSTUFF?", NULL, NULL, NULL}, NULL, "Shows time until next random thing is said."}, #endif {DANGER_COMMAND, 3, 1, 0, chanserv_raw, {"RAW", NULL, NULL, NULL, NULL}, "<raw data>", "Get bot to send raw IRC data."}, //#ifndef WIN32 {INFO_COMMAND, 0, 0, 0, chanserv_rdb, {"RDB", NULL, NULL, NULL, NULL}, "[topic]", "Display information about the random databases."}, //#endif {DANGER_COMMAND, 3, 3, 0, chanserv_repeat, {"REPEAT", "TIMER", NULL, NULL, NULL}, "<number> <delay> <raw data>", "Get bot to send raw IRC data a number of times."}, {NORMAL_COMMAND, 1, 1, 0, chanserv_replace, {"REPLACE", NULL, NULL, NULL, NULL}, "<topic> <text>", "Replace the text of a topic."}, {DANGER_COMMAND, 3, 0, 0, chanserv_restart, {"RESTART", "REHASH", NULL, NULL, NULL}, NULL, "Restart the bot."}, {INFO_COMMAND, 0, 1, 0, chanserv_search, {"SEARCH", "LOOK", "FIND", NULL, NULL}, "<text>", "Search in the topics."}, {INFO_COMMAND, 0, 1, 0, chanserv_seen, {"SEEN", NULL, NULL, NULL, NULL}, "<nick>", "Show the last time a user was seen."}, {DANGER_COMMAND, 3, 1, 0, chanserv_jump, {"SERVER", "JUMP", NULL, NULL, NULL}, "<server> [port]", "Switch bot to a different server."}, {DANGER_COMMAND, 3, 1, 0, chanserv_set, {"SET", NULL, NULL, NULL, NULL}, "<parameter>[=<new value>]", "Set or show the value of a setup.ini parameter. Usually requires a restart."}, {DANGER_COMMAND, 1, 1, 0, chanserv_setinfo, {"SETINFO", NULL, NULL, NULL, NULL}, "<new user greeting|0>", "Set your greeting from the bot when you join a channel."}, {SAFE_COMMAND, SLEEP_LEVEL, 1, 1, chanserv_sleep, {"SLEEP", "HUSH", NULL, NULL, NULL}, "[period]", "Deactivate bot for a period."}, #ifdef ENABLE_STATS {INFO_COMMAND, 0, 0, 0, chanserv_stats, {"STATS", NULL, NULL, NULL, NULL}, "[nick]", "Shows statistics about questions answered."}, #endif #ifdef ENABLE_TAF {NORMAL_COMMAND, 0, 1, 0, chanserv_taf, {"TAF", NULL, NULL, NULL, NULL}, "<city or code>", "Get raw TAF weather data."}, #endif #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 2, 1, 0, chanserv_teaseop, {"TEASEOP", "TO", NULL, NULL, NULL}, "<nick>", "Tease a user with channel operator status."}, #endif {INFO_COMMAND, 0, 2, 0, chanserv_tell, {"TELL", NULL, NULL, NULL, NULL}, "<nick> [ABOUT] <topic>", "Get bot to recall a topic to a user."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 2, 0, 0, chanserv_topic, {"TOPIC", "T", NULL, NULL, NULL}, "<channel topic>", "Change the channels topic."}, #endif {DANGER_COMMAND, 1, 1, 0, chanserv_unignore, {"UNIGNORE", NULL, NULL, NULL, NULL}, "<nick>", "Get bot to stop ignoring a user."}, {INFO_COMMAND, 0, 1, 0, chanserv_unixtime, {"UNIXTIME", NULL, NULL, NULL, NULL}, "<time>", "Shows unixtime."}, #ifdef ENABLE_CHANNEL {DANGER_COMMAND, 2, 0, 0, chanserv_up, {"UP", NULL, NULL, NULL, NULL}, NULL, "Add channel operator status to yourself."}, #endif //#ifndef WIN32 {INFO_COMMAND, 0, 0, 0, chanserv_uptime, {"UPTIME", NULL, NULL, NULL, NULL}, NULL, "Shows the uptime statistics for the computer the bot is running on."}, //#endif {INFO_COMMAND, 1, 0, 0, chanserv_user_list, {"USERLIST", "HLIST", "ACCESS", NULL, NULL}, NULL, "Show the bot's access list."}, {INFO_COMMAND, 0, 0, 0, chanserv_variables, {"VARIABLES", NULL, NULL, NULL, NULL}, NULL, "Displays variables you can use."}, #ifdef ENABLE_CTCP {INFO_COMMAND, 0, 0, 0, chanserv_version, {"\1VERSION\1", NULL, NULL, NULL, NULL}, NULL, ""}, #endif #ifdef ENABLE_CHANNEL {NORMAL_COMMAND, 3, 1, 0, chanserv_voice, {"VOICE", "V", NULL, NULL, NULL}, "[#channel] <nicks>", "Add channel voice status to users."}, #endif {SAFE_COMMAND, SLEEP_LEVEL, 0, 0, chanserv_wakeup, {"WAKEUP", NULL, NULL, NULL, NULL}, NULL, "Reactivates bot from sleep mode."}, #ifdef ENABLE_WEATHER {NORMAL_COMMAND, 0, 1, 0, chanserv_weather, {"WEATHER", NULL, NULL, NULL, NULL}, "<city or code>", "Get decoded weather data."}, #endif #ifdef ENABLE_WEBSEARCH {NORMAL_COMMAND, 0, 1, 0, chanserv_websearch, {"WEBSEARCH", NULL, NULL, NULL, NULL}, "<text>", "Look up the text on the web using duckduckgo.com."}, #endif {SAFE_COMMAND, 0, 2, 0, chanserv_where, {"WHAT", "WHO", "WHERE", NULL, NULL}, "<IS> [A|AN] <topic>", "Recall a topic."}, {SAFE_COMMAND, 0, 2, 0, chanserv_whisper, {"WHISPER", NULL, NULL, NULL, NULL}, "<nick> [ABOUT] <topic>", "Get bot to recall a topic to a user privately."}, {INFO_COMMAND, 4, 0, 0, NULL, {NULL, NULL, NULL, NULL, NULL}, NULL, NULL} }; void chanserv(char *source, char *target, char *buf) { struct chanserv_output *result = NULL; char *cmd = NULL, *userhost = NULL, oldbuf[BUFSIZ] = {"NULL"}, *ptr = NULL, *chan = NULL; int i = 0, j = 0, found = -1, command = 0, wakeup = 0, exempt = 0, more_needed = 0, too_many = 0, check_too_many = 0, arg_count = 0, command_access = 0; enum chanserv_invoke_type input_type = DIRECT_INVOKE; enum chanserv_command_type command_type = NORMAL_COMMAND; #ifdef ENABLE_RANDOM if (strcasecmp (target, CHAN) == 0) Rand_Idle = 0; #endif stripline (buf); stripline (source); if (buf == NULL || target == NULL || source == NULL) return; /* Make a copy of the original buffer in a safe location for * later use. Strip the : if there is one. */ strncpy (oldbuf, buf, sizeof (oldbuf)); /* Pointer to oldbuf */ ptr = oldbuf; if (*ptr == ':') ptr++; cmd = strtok (buf, " "); if (!cmd) return; if (*cmd == ':') cmd++; if ((userhost = strchr (source, '!')) != NULL) *userhost++ = '\0'; if (check_ignore_user_ram(source) > 0) return; if (*target != '#' && *target != '&' && *target != '+') { input_type = MSG_INVOKE; } else if (strcasecmp (cmd, NICK_COMMA) == 0 || strcasecmp (cmd, COLON_NICK) == 0 || strcasecmp (cmd, BCOLON_NICK) == 0 || strcasecmp (cmd, Mynick) == 0) { input_type = ADDRESS_INVOKE; cmd = strtok (NULL, " "); } if (cmd) { if (*cmd == *CMDCHAR) { cmd++; command = 1; input_type = CHAR_INVOKE; } strupr (cmd); for (i = 0; chanserv_commands[i].func != NULL; i++) { for (j = 0; chanserv_commands[i].command[j] != NULL; j++) { if (strcmp(cmd, chanserv_commands[i].command[j]) == 0) { found = i; command_type = chanserv_commands[found].type; check_too_many = chanserv_commands[found].too_many; if (strcmp(cmd, "WAKEUP") == 0) wakeup = 1; break; } } if (found != -1) break; } } if (input_type != MSG_INVOKE) { if (((Sleep_Toggle == 1) && (wakeup != 1)) || (cf(userhost, source, target))) return; add_user(target, source, userhost, 0); /* Unidle */ } if (found != -1) { /* * password related commands can ONLY be done privately. * Every command can be done by /msg bot !command. * Every command can be done by /query bot !command. * Every command can be done by /msg bot !command. * Every danger command can be done by bot: !command. * Every danger command can be done by !command. * Every normal command can be done by /query bot command. * Every normal command can be done by /msg bot command. * Every safe command can be done by bot: command. * Every information command can be done by command. */ switch (command_type) { case INFO_COMMAND : break; case SAFE_COMMAND : { if (input_type == DIRECT_INVOKE) return; break; } case NORMAL_COMMAND : { if (input_type == DIRECT_INVOKE) return; break; } case DANGER_COMMAND : { if (command != 1) return; break; } case PASSWORD_COMMAND : { if (input_type != MSG_INVOKE) return; break; } } chan = (input_type == MSG_INVOKE) ? "#*" : target; command_access = chanserv_commands[found].access; if (check_access(userhost, chan, 0, source) >= (long)command_access) { char **args = NULL; int k = 0; /* Use the char count of spaces in our oldbuf ptr. Since * it has the cmd tacked on the beginning, the number of * spaces gives us an accurate early number of arguments * supplied by the user, because the count of spaces will * return one more than the actual number of args supplied. * The first word is the cmd, so we don't want this counted. * This is sort of a lazy way of counting arguments before * they're actually read into a buffer and dealt with. * * This allows us to "break out" of the command routine if * we've entered accidentally by user input. Such instances * may be if the user says "info things stuff", the bot * realizes this is not a command, but normal conversation, * and will respond if the topic is in it's database. If it's * not found, the bot either ignores it or responds with a * whut reply if addressed directly. This code is only * intended for commands which have no arguments. */ if (*ptr == '!') ptr++; /* Actual number of arguments supplied. */ k = count_char (ptr, ' '); /* Number of arguments expected. */ arg_count = chanserv_commands[found].arg_count; if (k > 0) { args = calloc(k + 1, sizeof(char *)); if (args) { for (i = 0; i < k; i++) { args[i] = strtok(NULL, " "); } args[i++] = NULL; /* Check for more arguments needed, but don't * bail out, we'll take care of it later. */ if (i < arg_count) more_needed = 1; } else return; /* Check for too many args on special cases. */ if (check_too_many == 1) { if ((input_type == ADDRESS_INVOKE) && (k > (arg_count+1))) too_many = 1; if ((k > arg_count) && (input_type == DIRECT_INVOKE)) too_many = 1; if ((k > arg_count) && (input_type == MSG_INVOKE)) too_many = 1; if ((k > arg_count) && (input_type == CHAR_INVOKE)) return; } } else { args = calloc(1, sizeof(char *)); if (args) { args[0] = NULL; if (0 < arg_count) more_needed = 1; } else return; } if (too_many == 1) { int i = 0; char *ptr2 = NULL; strlwr (ptr); for (i = 0; i < strlen (ptr); i++) { if (ptr[i] == ' ') ptr[i] = '+'; } /* Strip the bot's nickname if ADDRESS_INVOKE */ if (input_type == ADDRESS_INVOKE) { ptr2 = strtok (ptr, "+"); ptr = strtok (NULL, ""); } /* Output only if the topic exists. If the bot was * addressed by nickname (ADDRESS_INVOKE), output * anyway because show_url will supply a DUNNO * response. * If the input_type was MSG_INVOKE, we use the * source as a target, because the target ends up * being set to the bot's own nickname due to the * parsing under certain conditions. */ if (check_existing_url(source, ptr, target) == 1) // || (input_type == ADDRESS_INVOKE) // || (input_type == MSG_INVOKE)) { result = show_url(source, ptr, ((input_type == MSG_INVOKE) ? source : target), 1, 0, userhost, 0); } else /* No matching database entry. */ return; } else if ((more_needed == 1) && chanserv_commands[found].syntax) { chan = (input_type == MSG_INVOKE) ? "#*" : target; result = chanserv_show_help(cmd, check_access(userhost, chan, 0, source)); } else { /* We call this to give the command a chance to supply * a custom error msg if there are not enough * arguments. Because it fell through the loop * this far, we assume it's a normal command with * arguments to be parsed. */ result = chanserv_commands[found].func(source, target, cmd, args, input_type, userhost); } if (result) { i = 1; show_output(source, target, result, input_type, 0); result = NULL; } free(args); } } else if (input_type != CHAR_INVOKE) { if ((input_type == ADDRESS_INVOKE) && (cmd == NULL)) { if (RANDOM_WHUT == true) do_randomtopic(WHUTR, target, WHUT_FILE, source, cmd); else { if (input_type == MSG_INVOKE) S("NOTICE %s :%s\n", source, WHUT); else S("PRIVMSG %s :%s: %s\n", target, source, WHUT); } } else if ((GENERAL_QUESTIONS) && (cmd)) { result = show_url(source, get_multiword_topic(cmd), (input_type == MSG_INVOKE) ? source : target, (! (input_type == DIRECT_INVOKE)), (input_type == DIRECT_INVOKE), userhost, 0); if (result) { show_output(source, (input_type == MSG_INVOKE) ? source : target, result, input_type, 1); result = NULL; } } } } static void show_output(char *source, char *target, struct chanserv_output *result, enum chanserv_invoke_type input_type, int question) { struct chanserv_output *output = result; // TODO - This is not working for actions. while (output) { char *s, *s2, c; int length, len; /* RFC2812 says max packet length is 512, including CR-LF at end. * Also a colon and a space at the beginning. */ //#define MAX_IRC_LEN 507 // This doesn't work. #define MAX_IRC_LEN 475 // This works. s = output->output; length = strlen(s); if (input_type == MSG_INVOKE) { len = 12 + strlen(source); while ((len + length) > MAX_IRC_LEN) { c = s[MAX_IRC_LEN - len]; s[MAX_IRC_LEN - len] = '\0'; s2 = strrchr(s, ' '); *s2 = '\0'; S("NOTICE %s :%s\n", source, s); db_sleep(2); *s2 = ' '; s[MAX_IRC_LEN - len] = c; s = s2 + 1; length = strlen(s); } S("NOTICE %s :%s\n", source, s); } else { len = 16 + strlen(target) + strlen(source); while ((len + length) > MAX_IRC_LEN) { c = s[MAX_IRC_LEN - len]; s[MAX_IRC_LEN - len] = '\0'; s2 = strrchr(s, ' '); *s2 = '\0'; if ((('#' == target[0]) && (ADDRESS_INVOKE != input_type)) || (question)) S("PRIVMSG %s :%s\n", target, s); else S("PRIVMSG %s :%s: %s\n", target, source, s); db_sleep(2); *s2 = ' '; s[MAX_IRC_LEN - len] = c; s = s2 + 1; length = strlen(s); } if ((('#' == target[0]) && (ADDRESS_INVOKE != input_type)) || (question)) S("PRIVMSG %s :%s\n", target, s); else S("PRIVMSG %s :%s: %s\n", target, source, s); } output = output->next; } chanserv_output_free(result); } struct chanserv_output *chanserv_show_help(char *cmd, long user_level) { struct chanserv_output *result = NULL; char temp[10 * 1024] = { 0 }, cmdchar[2] = "\0\0"; int i, j, found = -1; if (*cmd == *CMDCHAR) cmd++; strupr(cmd); for (i = 0; chanserv_commands[i].func != NULL; i++) { for (j = 0; chanserv_commands[i].command[j] != NULL; j++) { if (strcmp(cmd, chanserv_commands[i].command[j]) == 0) { found = i; break; } } if (found != -1) break; } if (found != -1) { if (chanserv_commands[found].type == DANGER_COMMAND) cmdchar[0] = *CMDCHAR; else cmdchar[0] = '\0'; for (j = 0; chanserv_commands[found].command[j] != NULL; j++) { if (j) strcat(temp, " | "); if (chanserv_commands[i].type == DANGER_COMMAND) strcat(temp, cmdchar); strcat(temp, chanserv_commands[found].command[j]); } result = chanserv_asprintf(result, "%s [level %d] - %s SYNTAX - %s%s %s", temp, chanserv_commands[found].access, chanserv_commands[found].summary, cmdchar, cmd, (chanserv_commands[found].syntax != NULL) ? chanserv_commands[found].syntax : ""); } else if (strcmp(cmd, "COMMANDS") == 0) { cmdchar[0] = *CMDCHAR; for (i = 0; chanserv_commands[i].func != NULL; i++) { if (chanserv_commands[i].access <= user_level) { if (chanserv_commands[i].command[0][0] > 10) { if (i) strcat(temp, " "); if (chanserv_commands[i].type == DANGER_COMMAND) strcat(temp, cmdchar); strcat(temp, chanserv_commands[i].command[0]); } } } result = chanserv_asprintf(result, "%s", temp); } else if (strcmp(cmd, "PARAMETERS") == 0) { for (i = 0; parameters[i].parameter[0] != NULL; i++) { if (parameters[i].access <= user_level) { if (i) strcat(temp, " "); strcat(temp, parameters[i].parameter[0]); } } result = chanserv_asprintf(result, "%s", temp); } else { for (i = 0; parameters[i].parameter[0] != NULL; i++) { for (j = 0; parameters[i].parameter[j] != NULL; j++) { if (strcmp(cmd, parameters[i].parameter[j]) == 0) { found = i; break; } } if (found != -1) break; } if (found != -1) { for (j = 0; parameters[found].parameter[j] != NULL; j++) { if (j) strcat(temp, " | "); strcat(temp, parameters[found].parameter[j]); } switch (parameters[found].type) { case ST_BOOLEAN : { bool *variable = parameters[found].value; result = chanserv_asprintf(result, "%s [level %d] - %s VALUE - %s = %s", temp, parameters[found].access, parameters[found].summary, cmd, (*variable) ? "true" : "false"); break; } case ST_INTEGER : { long *variable = parameters[found].value; result = chanserv_asprintf(result, "%s [level %d] - %s VALUE - %s = %ld", temp, parameters[found].access, parameters[found].summary, cmd, *variable); break; } case ST_STRING : { char *variable = parameters[found].value; result = chanserv_asprintf(result, "%s [level %d] - %s VALUE - %s = %s", temp, parameters[found].access, parameters[found].summary, cmd, variable); break; } } } } return result; } int check_exempt (char *cmd) { int i = 0; int j = 0; int k = 0; char *exempt_items[] = { "CYCLE", "HELP", #ifdef ENABLE_STATS "STATS", #endif NULL }; strupr(cmd); for (i = 0; chanserv_commands[i].func != NULL; i++) { for (j = 0; chanserv_commands[i].command[j] != NULL; j++) { if (strcmp (cmd, chanserv_commands[i].command[j]) == 0) { for (k = 0; exempt_items[k] != NULL; k++) { if (strcmp (chanserv_commands[i].command[j], exempt_items[k]) == 0) { strlwr(cmd); return 1; } } } } } strlwr(cmd); return 0; }