X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/1d9574827a360322e344883a477c8f52f35ede2e..e42487a5d0733c361fce6607ed7f01025f650aa1:/src/chanserv.c diff --git a/src/chanserv.c b/src/chanserv.c index b664ac3..ec6aa80 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -129,9 +129,11 @@ static const struct message_entry msgtab[] = { { "CSMSG_REG_SUCCESS", "You now have ownership of $b%s$b." }, { "CSMSG_PROXY_SUCCESS", "%s now has ownership of $b%s$b." }, { "CSMSG_ALREADY_REGGED", "$b%s$b is registered to someone else." }, - { "CSMSG_MUST_BE_OPPED", "You must be a channel operator in $b%s$b to register it." }, + { "CSMSG_MUST_BE_OPPED", "You must be a channel operator (+o) in $b%s$b to register it." }, { "CSMSG_PROXY_FORBIDDEN", "You may not register a channel for someone else." }, - { "CSMSG_OWN_TOO_MANY", "%s already owns enough channels (at least %d); use FORCE to override." }, + { "CSMSG_OWN_TOO_MANY", "%s already owns more than the limit of %d channels. Use FORCE to override." }, + { "CSMSG_YOU_OWN_TOO_MANY", "You already own more than the limit of %d channels. Ask a staff member for help." }, + { "CSMSG_ANOTHER_SERVICE", "Another service bot is in that channel already. Ask a staff member for help." }, /* Do-not-register channels */ { "CSMSG_NOT_DNR", "$b%s$b is not a valid channel name or *account." }, @@ -150,7 +152,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_UNREG_SUCCESS", "$b%s$b has been unregistered." }, { "CSMSG_UNREG_NODELETE", "$b%s$b is protected from unregistration." }, { "CSMSG_CHAN_SUSPENDED", "$b$C$b access to $b%s$b has been temporarily suspended (%s)." }, - { "CSMSG_CONFIRM_UNREG", "To confirm this unregistration, you must use 'unregister %s'." }, + { "CSMSG_CONFIRM_UNREG", "To confirm this unregistration, you must use 'unregister %s %s'." }, /* Channel moving */ { "CSMSG_MOVE_SUCCESS", "Channel registration has been moved to $b%s$b." }, @@ -195,13 +197,13 @@ static const struct message_entry msgtab[] = { { "CSMSG_TRIMMED_USERS", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s." }, { "CSMSG_INCORRECT_ACCESS", "%s has access $b%s$b, not %s." }, { "CSMSG_USER_EXISTS", "%s is already on the $b%s$b user list (with %s access)." }, - { "CSMSG_ADDUSER_PENDING", "I have sent him/her a message letting them know, and if they auth or register soon, i will finish adding them automatically." }, + { "CSMSG_ADDUSER_PENDING", "I have sent him/her a message letting them know, and if they auth or register soon, I will finish adding them automatically." }, { "CSMSG_ADDUSER_PENDING_ALREADY", "He or she is already pending addition to %s once he/she auths with $b$N$b." }, { "CSMSG_ADDUSER_PENDING_HEADER", "Users to add to channels pending logins:" }, /* Remove after testing? */ { "CSMSG_ADDUSER_PENDING_LIST", "Channel %s user %s" }, /* Remove after testing? */ - { "CSMSG_ADDUSER_PENDING_HEADER", "--------- End of pending list ----------" }, /* Remove after testing? */ + { "CSMSG_ADDUSER_PENDING_FOOTER", "--------- End of pending list ----------" }, /* Remove after testing? */ /*{ "CSMSG_ADDUSER_PENDING_NOTINCHAN", "That user is not in %s, and is not auth'd." }, */ - { "CSMSG_ADDUSER_PENDING_TARGET", "Channel Services bot here, %s would like to add you to my userlist in channel %s, but you are not auth'd to $b$N$b. Please auth now, and you will be added. If you do not have an accont, type /msg $N help register" }, + { "CSMSG_ADDUSER_PENDING_TARGET", "Channel Services bot here: %s would like to add you to my userlist in channel %s, but you are not authenticated to $b$N$b. Please authenticate now and you will be added. If you do not have an account, type /msg $N help register" }, { "CSMSG_CANNOT_TRIM", "You must include a minimum inactivity duration of at least 60 seconds to trim." }, { "CSMSG_NO_SELF_CLVL", "You cannot change your own access." }, @@ -268,25 +270,25 @@ static const struct message_entry msgtab[] = { { "CSMSG_SET_USERGREETING", "$bUserGreeting$b %s" }, { "CSMSG_SET_MODES", "$bModes $b %s" }, { "CSMSG_SET_NODELETE", "$bNoDelete $b %s" }, - { "CSMSG_SET_DYNLIMIT", "$bDynLimit $b %s" }, + { "CSMSG_SET_DYNLIMIT", "$bDynLimit $b %s - +l joinflood protection." }, { "CSMSG_SET_OFFCHANNEL", "$bOffChannel $b %s" }, - { "CSMSG_SET_USERINFO", "$bUserInfo $b %d" }, + { "CSMSG_SET_USERINFO", "$bUserInfo $b %d - and above userinfos are shown." }, /* { "CSMSG_SET_GIVE_VOICE", "$bGiveVoice $b %d" }, { "CSMSG_SET_GIVE_HALFOPS", "$bGiveHalfOps $b %d" }, */ { "CSMSG_SET_TOPICSNARF", "$bTopicSnarf $b %d" }, - { "CSMSG_SET_INVITEME", "$bInviteMe $b %d" }, - { "CSMSG_SET_ENFOPS", "$bEnfOps $b %d" }, - { "CSMSG_SET_ENFHALFOPS", "$bEnfHalfOps $b %d" }, + { "CSMSG_SET_INVITEME", "$bInviteMe $b %d - Userlevel required to invite self." }, + { "CSMSG_SET_ENFOPS", "$bEnfOps $b %d - level and above can op unknown users." }, + { "CSMSG_SET_ENFHALFOPS", "$bEnfHalfOps $b %d - level and above can hop unknown users." }, /* { "CSMSG_SET_GIVE_OPS", "$bGiveOps $b %d" }, */ - { "CSMSG_SET_ENFMODES", "$bEnfModes $b %d" }, - { "CSMSG_SET_ENFTOPIC", "$bEnfTopic $b %d" }, - { "CSMSG_SET_PUBCMD", "$bPubCmd $b %d" }, - { "CSMSG_SET_SETTERS", "$bSetters $b %d" }, - { "CSMSG_SET_CTCPUSERS", "$bCTCPUsers $b %d" }, + { "CSMSG_SET_ENFMODES", "$bEnfModes $b %d - and above can change channel modes." }, + { "CSMSG_SET_ENFTOPIC", "$bEnfTopic $b %d - and above can set the topic." }, + { "CSMSG_SET_PUBCMD", "$bPubCmd $b %d - and above can use public commands." }, + { "CSMSG_SET_SETTERS", "$bSetters $b %d - and above can change these settings." }, +/* { "CSMSG_SET_CTCPUSERS", "$bCTCPUsers $b %d - and above can use ctcps." }, */ { "CSMSG_SET_VOICE", "$bvoice $b %d - %s" }, { "CSMSG_SET_PROTECT", "$bProtect $b %d - %s" }, { "CSMSG_SET_TOYS", "$bToys $b %d - %s" }, @@ -322,6 +324,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_TOPICREFRESH_6_HOURS", "Refresh every 6 hours." }, { "CSMSG_TOPICREFRESH_12_HOURS", "Refresh every 12 hours." }, { "CSMSG_TOPICREFRESH_24_HOURS", "Refresh every 24 hours." }, + { "CSMSG_CTCPREACTION_NONE", "CTCPs are allowed" }, { "CSMSG_CTCPREACTION_KICK", "Kick on disallowed CTCPs" }, { "CSMSG_CTCPREACTION_KICKBAN", "Kickban on disallowed CTCPs" }, { "CSMSG_CTCPREACTION_SHORTBAN", "Short timed ban on disallowed CTCPs" }, @@ -459,7 +462,7 @@ static const struct message_entry msgtab[] = { /* User settings */ { "CSMSG_USER_OPTIONS", "User Options:" }, - { "CSMSG_USER_PROTECTED", "That user is protected." }, +// { "CSMSG_USER_PROTECTED", "That user is protected." }, /* Toys */ { "CSMSG_UNF_RESPONSE", "I don't want to be part of your sick fantasies!" }, @@ -475,6 +478,7 @@ static const struct message_entry msgtab[] = { /* Other things */ { "CSMSG_EVENT_SEARCH_RESULTS", "$bChannel Events for %s$b" }, + { "CSMSG_LAST_INVALID", "Invalid argument. must be 1-200" }, { NULL, NULL } }; @@ -614,6 +618,7 @@ static const struct { { "helper", "BUG:", UL_HELPER, 'X' } }; +/* If you change this, change the enum in chanserv.h also, or stack smashing will commence. */ static const struct { char *format_name; char *db_name; @@ -622,16 +627,16 @@ static const struct { unsigned int old_flag; unsigned short flag_value; } levelOptions[] = { - { "CSMSG_SET_GIVE_VOICE", "givevoice", 100, ~0, CHANNEL_VOICE_ALL, 0 }, - { "CSMSG_SET_GIVE_HALFOPS", "givehalfops", 150, ~0, CHANNEL_HOP_ALL, 0 }, - { "CSMSG_SET_GIVE_OPS", "giveops", 200, 2, 0, 0 }, +// { "CSMSG_SET_GIVE_VOICE", "givevoice", 100, ~0, CHANNEL_VOICE_ALL, 0 }, +// { "CSMSG_SET_GIVE_HALFOPS", "givehalfops", 150, ~0, CHANNEL_HOP_ALL, 0 }, +// { "CSMSG_SET_GIVE_OPS", "giveops", 200, 2, 0, 0 }, // these 3 need removed, but causes segs if its still in the db.. { "CSMSG_SET_ENFOPS", "enfops", 300, 1, 0, 0 }, { "CSMSG_SET_ENFHALFOPS", "enfhalfops", 300, 1, 0, 0 }, { "CSMSG_SET_ENFMODES", "enfmodes", 200, 3, 0, 0 }, { "CSMSG_SET_ENFTOPIC", "enftopic", 200, 4, 0, 0 }, { "CSMSG_SET_PUBCMD", "pubcmd", 0, 5, 0, 0 }, { "CSMSG_SET_SETTERS", "setters", 400, 7, 0, 0 }, - { "CSMSG_SET_CTCPUSERS", "ctcpusers", 0, 9, 0, 0 }, +// { "CSMSG_SET_CTCPUSERS", "ctcpusers", 0, 9, 0, 0 }, { "CSMSG_SET_USERINFO", "userinfo", 1, ~0, CHANNEL_INFO_LINES, 1 }, { "CSMSG_SET_INVITEME", "inviteme", 1, ~0, CHANNEL_PEON_INVITE, 200 }, { "CSMSG_SET_TOPICSNARF", "topicsnarf", 501, ~0, CHANNEL_TOPIC_SNARF, 1 } @@ -660,6 +665,7 @@ struct charOptionValues { { '3', "CSMSG_TOPICREFRESH_12_HOURS" }, { '4', "CSMSG_TOPICREFRESH_24_HOURS" } }, ctcpReactionValues[] = { + { 'n', "CSMSG_CTCPREACTION_NONE" }, { 'k', "CSMSG_CTCPREACTION_KICK" }, { 'b', "CSMSG_CTCPREACTION_KICKBAN" }, { 't', "CSMSG_CTCPREACTION_SHORTBAN" }, @@ -678,7 +684,7 @@ static const struct { { "CSMSG_SET_PROTECT", "protect", 'l', 0, ArrayLength(protectValues), protectValues }, { "CSMSG_SET_TOYS", "toys", 'p', 6, ArrayLength(toysValues), toysValues }, { "CSMSG_SET_TOPICREFRESH", "topicrefresh", 'n', 8, ArrayLength(topicRefreshValues), topicRefreshValues }, - { "CSMSG_SET_CTCPREACTION", "ctcpreaction", 't', 10, ArrayLength(ctcpReactionValues), ctcpReactionValues } + { "CSMSG_SET_CTCPREACTION", "ctcpreaction", 'n', 10, ArrayLength(ctcpReactionValues), ctcpReactionValues } }; struct userData *helperList; @@ -861,9 +867,15 @@ chanserv_ctcp_check(struct userNode *user, struct chanNode *channel, char *text, || IsService(user) || !ircncasecmp(text, "ACTION ", 7)) return; - /* Figure out the minimum level needed to CTCP the channel */ - if(check_user_level(channel, user, lvlCTCPUsers, 1, 0)) - return; + /* We dont punish people we know -Rubin + * * Figure out the minimum level needed to CTCP the channel * + * + * if(check_user_level(channel, user, lvlCTCPUsers, 1, 0)) + * return; + */ + /* If they are a user of the channel, they are exempt */ + if(_GetChannelUser(channel->channel_info, user->handle_info, 0, 0)) + return; /* We need to enforce against them; do so. */ eflags = 0; argv[0] = text; @@ -872,7 +884,10 @@ chanserv_ctcp_check(struct userNode *user, struct chanNode *channel, char *text, if(GetUserMode(channel, user)) eflags |= ACTION_KICK; switch(channel->channel_info->chOpts[chCTCPReaction]) { - default: case 'k': /* just do the kick */ break; + default: case 'n': return; + case 'k': + eflags |= ACTION_KICK; + break; case 'b': eflags |= ACTION_BAN; break; @@ -1311,8 +1326,15 @@ process_adduser_pending(struct userNode *user) while((ap = find_adduser_pending(NULL, user))) { struct userData *actee; - actee = add_channel_user(ap->channel->channel_info, ap->user->handle_info, ap->level, 0, NULL); - scan_user_presence(actee, NULL); + if(GetTrueChannelAccess(ap->channel->channel_info, ap->user->handle_info)) + { + /* Already on the userlist. do nothing*/ + } + else + { + actee = add_channel_user(ap->channel->channel_info, ap->user->handle_info, ap->level, 0, NULL); + scan_user_presence(actee, NULL); + } del_adduser_pending(ap); } } @@ -1880,6 +1902,8 @@ static CHANSERV_FUNC(cmd_register) char *chan_name; unsigned int new_channel, force=0; struct do_not_register *dnr; + unsigned int n; + if(channel) { @@ -1895,8 +1919,7 @@ static CHANSERV_FUNC(cmd_register) return 0; } - if(!IsHelping(user) - && (!(mn = GetUserMode(channel, user)) || !(mn->modes & MODE_CHANOP))) + if(!IsHelping(user) && (!(mn = GetUserMode(channel, user)) || !(mn->modes & MODE_CHANOP))) { reply("CSMSG_MUST_BE_OPPED", channel->name); return 0; @@ -1941,11 +1964,36 @@ static CHANSERV_FUNC(cmd_register) return 0; force = (argc > (new_channel+2)) && !irccasecmp(argv[new_channel+2], "force"); dnr = chanserv_is_dnr(chan_name, handle); + + /* Check if they are over the limit.. */ + if((chanserv_get_owned_count(handle) >= chanserv_conf.max_owned) && !force) + { + reply("CSMSG_OWN_TOO_MANY", handle->handle, chanserv_conf.max_owned); + return 0; + } + } else { - handle = user->handle_info; + handle = user->handle_info; dnr = chanserv_is_dnr(chan_name, handle); + /* Check if they are over the limit.. */ + if((chanserv_get_owned_count(handle) >= chanserv_conf.max_owned) && !force) + { + reply("CSMSG_YOU_OWN_TOO_MANY", chanserv_conf.max_owned); + return 0; + } + /* Check if another service is in the channel */ + if(channel) + for(n = 0; n < channel->members.used; n++) + { + mn = channel->members.list[n]; + if((mn && mn->user && (mn->user->modes & FLAGS_SERVICE)) || IsLocal(mn->user)) + { + reply("CSMSG_ANOTHER_SERVICE"); + return 0; + } + } } if(dnr && !force) { @@ -1956,11 +2004,13 @@ static CHANSERV_FUNC(cmd_register) return 0; } + /* now handled above for message specilization * if((chanserv_get_owned_count(handle) >= chanserv_conf.max_owned) && !force) { reply("CSMSG_OWN_TOO_MANY", handle->handle, chanserv_conf.max_owned); return 0; } + */ if(new_channel) channel = AddChannel(argv[1], now, NULL, NULL, NULL); @@ -2052,7 +2102,7 @@ static CHANSERV_FUNC(cmd_unregister) confirm_string = make_confirmation_string(uData); if((argc < 2) || strcmp(argv[1], confirm_string)) { - reply("CSMSG_CONFIRM_UNREG", confirm_string); + reply("CSMSG_CONFIRM_UNREG", channel->name, confirm_string); return 0; } } @@ -3000,19 +3050,24 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c if(IsService(victim)) { - reply("MSG_SERVICE_IMMUNE", victim->nick); + if(cmd) + reply("MSG_SERVICE_IMMUNE", victim->nick); return 0; } if((action == ACTION_KICK) && !victimCount) { - reply("MSG_CHANNEL_USER_ABSENT", victim->nick, channel->name); + if(cmd) + reply("MSG_CHANNEL_USER_ABSENT", victim->nick, channel->name); return 0; } if(protect_user(victim, user, channel->channel_info)) { - reply("CSMSG_USER_PROTECTED", victim->nick); + // This translates to send_message(user, cmd->parent->bot, ...) + // if user is x3 (ctcp action) cmd is null and segfault. + if(cmd) + reply("CSMSG_USER_PROTECTED", victim->nick); return 0; } @@ -3023,7 +3078,8 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c { if(!is_ircmask(argv[1])) { - reply("MSG_NICK_UNKNOWN", argv[1]); + if(cmd) + reply("MSG_NICK_UNKNOWN", argv[1]); return 0; } @@ -3031,7 +3087,8 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c if(bad_channel_ban(channel, user, argv[1], &victimCount, victims)) { - reply("CSMSG_MASK_PROTECTED", argv[1]); + if(cmd) + reply("CSMSG_MASK_PROTECTED", argv[1]); return 0; } /* We dont actually want a victem count if were banning a mask manually, IMO -Rubin*/ @@ -3041,14 +3098,16 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c #ifdef entropy_lameness if((victimCount > 4) && ((victimCount * 3) > channel->members.used) && !IsOper(user)) { - reply("CSMSG_LAME_MASK", argv[1]); + if(cmd) + reply("CSMSG_LAME_MASK", argv[1]); return 0; } #endif if((action == ACTION_KICK) && (victimCount == 0)) { - reply("CSMSG_NO_MATCHING_USERS", channel->name, argv[1]); + if(cmd) + reply("CSMSG_NO_MATCHING_USERS", channel->name, argv[1]); return 0; } @@ -3065,7 +3124,8 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c if(channel->channel_info->banCount >= chanserv_conf.max_chan_bans) /* ..lamers.. */ { - reply("CSMSG_MAXIMUM_LAMERS", chanserv_conf.max_chan_bans); /* ..lamers.. */ + if(cmd) + reply("CSMSG_MAXIMUM_LAMERS", chanserv_conf.max_chan_bans); /* ..lamers.. */ free(ban); return 0; } @@ -3076,13 +3136,15 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c if(duration < 15) { - reply("CSMSG_DURATION_TOO_LOW"); + if(cmd) + reply("CSMSG_DURATION_TOO_LOW"); free(ban); return 0; } else if(duration > (86400 * 365 * 2)) { - reply("CSMSG_DURATION_TOO_HIGH"); + if(cmd) + reply("CSMSG_DURATION_TOO_HIGH"); free(ban); return 0; } @@ -3137,7 +3199,7 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c if(!cmd) { - /* automated kickban */ + /* automated kickban, dont reply */ } else if(duration) reply("CSMSG_LAMER_EXTENDED", ban, intervalString(interval, duration, user->handle_info)); @@ -3651,7 +3713,7 @@ static CHANSERV_FUNC(cmd_access) return 1; } -/* This is never used... */ +/* This is never used... static void zoot_list(struct listData *list) { @@ -3701,6 +3763,7 @@ zoot_list(struct listData *list) } } } +*/ static void def_list(struct listData *list) @@ -3710,12 +3773,13 @@ def_list(struct listData *list) send_message(list->user, list->bot, "CSMSG_ACCESS_SEARCH_HEADER", list->channel->name, user_level_name_from_level(list->lowest), user_level_name_from_level(list->highest), list->search); else send_message(list->user, list->bot, "CSMSG_ACCESS_ALL_HEADER", list->channel->name, user_level_name_from_level(list->lowest), user_level_name_from_level(list->highest)); - table_send(list->bot, list->user->nick, 0, NULL, list->table); if(list->table.length == 1) { msg = user_find_message(list->user, "MSG_NONE"); send_message_type(4, list->user, list->bot, " %s", msg); } + else + table_send(list->bot, list->user->nick, 0, NULL, list->table); } static int @@ -3748,7 +3812,7 @@ cmd_list_users(struct userNode *user, struct chanNode *channel, unsigned int arg lData.search = (argc > 1) ? argv[1] : NULL; send_list = def_list; /* What does the following line do exactly?? */ - (void)zoot_list; /* since it doesn't show user levels */ + /*(void)zoot_list; ** since it doesn't show user levels */ /* this does nothing!! -rubin if(user->handle_info) @@ -4469,32 +4533,34 @@ static CHANSERV_FUNC(cmd_resync) } else if(uData && uData->access >= UL_HALFOP /*cData->lvlOpts[lvlGiveHalfOps]*/) { - if(!(mn->modes & MODE_HALFOP)) + if(mn->modes & MODE_CHANOP) { - changes->args[used].mode = MODE_HALFOP; + changes->args[used].mode = MODE_REMOVE | MODE_CHANOP; changes->args[used++].u.member = mn; } - if(mn->modes & MODE_CHANOP) + if(!(mn->modes & MODE_HALFOP)) { - changes->args[used].mode = MODE_REMOVE | (mn->modes & ~MODE_CHANOP); + changes->args[used].mode = MODE_HALFOP; changes->args[used++].u.member = mn; } + /* why cant halfops keep voice if(mn->modes & MODE_VOICE) { changes->args[used].mode = MODE_REMOVE | (mn->modes & ~MODE_VOICE); changes->args[used++].u.member = mn; } + */ } else if(uData && uData->access >= UL_PEON /* cData->lvlOpts[lvlGiveVoice]*/) { if(mn->modes & MODE_CHANOP) { - changes->args[used].mode = MODE_REMOVE | (mn->modes & ~MODE_VOICE); + changes->args[used].mode = MODE_REMOVE | MODE_CHANOP; changes->args[used++].u.member = mn; } if(mn->modes & MODE_HALFOP) { - changes->args[used].mode = MODE_REMOVE | (mn->modes & ~MODE_VOICE); + changes->args[used].mode = MODE_REMOVE | MODE_HALFOP; changes->args[used++].u.member = mn; } if(!(mn->modes & MODE_VOICE)) @@ -4723,6 +4789,23 @@ static CHANSERV_FUNC(cmd_delnote) return 1; } +static CHANSERV_FUNC(cmd_last) +{ + int numoflines; + + REQUIRE_PARAMS(1); + + numoflines = (argc > 1) ? atoi(argv[1]) : 10; + + if(numoflines < 1 || numoflines > 200) + { + reply("CSMSG_LAST_INVALID"); + return 0; + } + ShowLog(user, channel, "*", "*", "*", "*", numoflines); + return 1; +} + static CHANSERV_FUNC(cmd_events) { struct logSearch discrim; @@ -5528,10 +5611,12 @@ static MODCMD_FUNC(chan_opt_setters) return channel_level_option(lvlSetters, CSFUNC_ARGS); } +/* static MODCMD_FUNC(chan_opt_ctcpusers) { return channel_level_option(lvlCTCPUsers, CSFUNC_ARGS); } +*/ static MODCMD_FUNC(chan_opt_userinfo) { @@ -6087,6 +6172,7 @@ static CHANSERV_FUNC(cmd_wut) return 1; } +#ifdef lame8ball static CHANSERV_FUNC(cmd_8ball) { unsigned int i, j, accum; @@ -6109,6 +6195,169 @@ static CHANSERV_FUNC(cmd_8ball) return 1; } +#else /* Use cool 8ball instead */ + +void eightball(char *outcome, int method, unsigned int seed) +{ + int answer = 0; + +#define NUMOFCOLORS 18 + char ballcolors[50][50] = {"blue", "red", "green", "yellow", + "white", "black", "grey", "brown", + "yellow", "pink", "purple", "orange", "teal", "burgandy", + "fuchsia","turquoise","magenta", "cyan"}; +#define NUMOFLOCATIONS 50 + char balllocations[50][55] = { + "Locke's house", "Oregon", "California", "Indiana", "Canada", + "Russia", "Japan", "Florida", "the Bahamas", "Hiroshima", + "the Caribbean", "the Everglades", "your head", "your pants", "your school", + "the Statue of Liberty", "Mt. Fugi", "your mother's house", "IRC", "OSU", + "Locke's cat", "the closet", "the washroom", "the lake", "Spain", + "the bathtub", "the toilet", "the sewer", "a horse", "Jupiter", + "Uranus", "Pluto", "a dark place", "your undies", "your shirt", + "your bra", "your hair", "your bed", "the couch", "the wall", + "Reed", "here --> [X]", "your brain", "Italy", "the Netherlands", + "Mars", "my hardware", "the bar", "Neverland Ranch", "Germany" }; +#define NUMOFPREPS 15 + char ballpreps[50][50] = { + "Near", "Somewhere near", "In", "In", "In", + "In", "Hiding in", "Under", "Next to", "Over", + "Crying in", "Right beside", "Nowhere near", "North of", "Trying to find"}; +#define NUMOFNUMS 34 + char ballnums[50][50] = { + "A hundred", "A thousand", "A few", "42", + "About 1", "About 2", "About 3", "About 4", "About 5", "About 6", "About 7", "About 8", "About 9", "About 10", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ten", + "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ten", + }; +#define NUMOFMULTS 8 + char ballmults[50][50] = { " million", " or so", " thousand", "", " or less", " or more", "", ""}; + + /* Method: + * 0: normal (Not used in x3) + * 1: color + * 2: where is + * 3: how many + */ + + srand(seed); + if (method == 1) /* A Color */ + { + char tmp[MAXLEN]; + + answer = (rand() % 12); /* Make sure this is the # of entries */ + switch(answer) + { + case 0: strcpy(tmp, "Very bright %s, I'd say."); + break; + case 1: strcpy(tmp, "Sort of a light %s color."); + break; + case 2: strcpy(tmp, "Dark and dreary %s."); + break; + case 3: strcpy(tmp, "Quite a pale shade of %s."); + break; + case 4: strcpy(tmp, "A gross kind of mucky %s."); + break; + case 5: strcpy(tmp, "Brilliant whiteish %s."); + break; + case 6: case 7: case 8: case 9: strcpy(tmp, "%s."); + break; + case 10: strcpy(tmp, "Solid %s."); + break; + case 11: strcpy(tmp, "Transparent %s."); + break; + default: strcpy(outcome, "An invalid random number was generated."); + return; + } + sprintf(outcome, tmp, ballcolors[rand() % NUMOFCOLORS]); + return; + } + else if (method == 2) /* Location */ + { + sprintf(outcome, "%s %s.", ballpreps[rand() % NUMOFPREPS], balllocations[rand() % NUMOFLOCATIONS]); + } + else if (method == 3) /* Number of ___ */ + { + sprintf(outcome, "%s%s.", ballnums[rand() % NUMOFNUMS], ballmults[rand() % NUMOFMULTS]); + } + else + { + //Debug(DBGWARNING, "Error in 8ball."); + } + return; +} + +static CHANSERV_FUNC(cmd_8ball) +{ + char *word1, *word2, *word3; + static char eb[MAXLEN]; + unsigned int accum, i, j; + + REQUIRE_PARAMS(1); + accum = 0; + for(i=1; i2?argv[2]:""; + word3 = argc>3?argv[3]:""; + +/*** COLOR *****/ + if((word2) && strcasecmp(word1, "what") == 0 && strcasecmp(word2, "color") == 0) + eightball(eb, 1, accum); + else if((word3) && strcasecmp(word1, "what's") == 0 && strcasecmp(word2, "the") == 0 && strcasecmp(word3, "color") == 0) + eightball(eb, 1, accum); + else if((word3) && strcasecmp(word1, "whats") == 0 && strcasecmp(word2, "the") == 0 && strcasecmp(word3, "color") == 0) + eightball(eb, 1, accum); +/*** LOCATION *****/ + else if( + ( + word2 && + ( + (strcasecmp(word1, "where") == 0) && + (strcasecmp(word2, "is") == 0) + ) + ) || + ( + strcasecmp(word1, "where's") == 0 + ) + ) + eightball(eb, 2, accum); +/*** NUMBER *****/ + else if((word2) && strcasecmp(word1, "how") == 0 && strcasecmp(word2, "many") == 0) + eightball(eb, 3, accum); +/*** GENERIC *****/ + else + { + /* Generic 8ball question.. so pull from x3.conf srvx style */ + const char *resp; + + resp = chanserv_conf.eightball->list[accum % chanserv_conf.eightball->used]; + if(channel) + { + char response[MAXLEN]; + sprintf(response, "\002%s\002: %s", user->nick, resp); + irc_privmsg(cmd->parent->bot, channel->name, response); + } + else + send_message_type(4, user, cmd->parent->bot, "%s", resp); + return 1; + } + + if(channel) + { + char response[MAXLEN]; + sprintf(response, "\002%s\002: %s", user->nick, eb); + irc_privmsg(cmd->parent->bot, channel->name, response); + } + else + send_message_type(4, user, cmd->parent->bot, "%s", eb); + return 1; +} +#endif + static CHANSERV_FUNC(cmd_d) { unsigned long sides, count, modifier, ii, total; @@ -6887,7 +7136,7 @@ chanserv_conf_read(void) "DefaultTopic", "TopicMask", "Greeting", "UserGreeting", "Modes", /* options based on user level */ "PubCmd", "InviteMe", "UserInfo",/* "GiveVoice", "GiveHalfOps", "GiveOps", */ "EnfOps", - "EnfHalfOps", "EnfModes", "EnfTopic", "TopicSnarf", "Setters", "CtcpUsers", + "EnfHalfOps", "EnfModes", "EnfTopic", "TopicSnarf", "Setters", /*"CtcpUsers", */ /* multiple choice options */ "CtcpReaction", "Protect", "Toys", "TopicRefresh", /* binary options */ @@ -7697,6 +7946,7 @@ init_chanserv(const char *nick) DEFINE_COMMAND(resync, 1, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); DEFINE_COMMAND(events, 1, MODCMD_REQUIRE_REGCHAN, "flags", "+nolog", "access", "manager", NULL); + DEFINE_COMMAND(last, 1, MODCMD_REQUIRE_REGCHAN, "flags", "+nolog", "access", "manager", NULL); DEFINE_COMMAND(addlamer, 2, MODCMD_REQUIRE_REGCHAN, "access", "manager", NULL); DEFINE_COMMAND(addtimedlamer, 3, MODCMD_REQUIRE_REGCHAN, "access", "manager", NULL); @@ -7769,7 +8019,7 @@ init_chanserv(const char *nick) DEFINE_CHANNEL_OPTION(toys); DEFINE_CHANNEL_OPTION(setters); DEFINE_CHANNEL_OPTION(topicrefresh); - DEFINE_CHANNEL_OPTION(ctcpusers); +// DEFINE_CHANNEL_OPTION(ctcpusers); DEFINE_CHANNEL_OPTION(ctcpreaction); DEFINE_CHANNEL_OPTION(inviteme); if(off_channel > 1)