X-Git-Url: https://jfr.im/git/irc/evilnet/x3.git/blobdiff_plain/ff3b058ac51e9caf5cf1fd310b8a401a97a85582..4cb36ef05734bc040784d67794a3376b0e3a5ec2:/src/chanserv.c diff --git a/src/chanserv.c b/src/chanserv.c index 74f9898..b39dd9b 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -21,9 +21,12 @@ #include "chanserv.h" #include "conf.h" #include "global.h" +#include "gline.h" +#include "ioset.h" #include "modcmd.h" #include "opserv.h" /* for opserv_bad_channel() */ #include "saxdb.h" +#include "shun.h" #include "spamserv.h" #include "timeq.h" @@ -39,7 +42,6 @@ #define KEY_ADJUST_DELAY "adjust_delay" #define KEY_CHAN_EXPIRE_FREQ "chan_expire_freq" #define KEY_CHAN_EXPIRE_DELAY "chan_expire_delay" -#define KEY_DNR_EXPIRE_FREQ "dnr_expire_freq" #define KEY_BAN_TIMEOUT_FREQ "ban_timeout_freq" #define KEY_MAX_CHAN_USERS "max_chan_users" #define KEY_MAX_CHAN_BANS "max_chan_bans" @@ -112,6 +114,7 @@ #define KEY_NOTES "notes" #define KEY_TOPIC_MASK "topic_mask" #define KEY_OWNER_TRANSFER "owner_transfer" +#define KEY_MAXSETINFO "maxsetinfo" /* User data */ #define KEY_LEVEL "level" @@ -131,8 +134,7 @@ #define KEY_GOD_TIMEOUT "god_timeout" -#define CHANNEL_DEFAULT_FLAGS (CHANNEL_OFFCHANNEL | CHANNEL_UNREVIEWED) -#define CHANNEL_PRESERVED_FLAGS (CHANNEL_UNREVIEWED) +#define CHANNEL_DEFAULT_FLAGS (CHANNEL_OFFCHANNEL) #define CHANNEL_DEFAULT_OPTIONS "lmoooanpcnat" /* Administrative messages */ @@ -154,7 +156,6 @@ static const struct message_entry msgtab[] = { { "CSMSG_DNR_SEARCH_RESULTS", "$bDo-Not-Register Channels$b" }, { "CSMSG_DNR_INFO", "$b%s$b (set by $b%s$b): %s" }, { "CSMSG_DNR_INFO_SET", "$b%s$b (set %s ago by $b%s$b): %s" }, - { "CSMSG_DNR_INFO_SET_EXPIRES", "$b%s$b is do-not-register (set %s by $b%s$b; expires %s): %s" }, { "CSMSG_MORE_DNRS", "%d more do-not-register entries skipped." }, { "CSMSG_DNR_CHANNEL", "Only network staff may register $b%s$b." }, { "CSMSG_DNR_CHANNEL_MOVE", "Only network staff may move $b%s$b." }, @@ -162,8 +163,6 @@ static const struct message_entry msgtab[] = { { "CSMSG_NOREGISTER_CHANNEL", "$b%s$b has been added to the do-not-register list." }, { "CSMSG_NO_SUCH_DNR", "$b%s$b is not in the do-not-register list." }, { "CSMSG_DNR_REMOVED", "$b%s$b has been removed from the do-not-register list." }, - { "CSMSG_DNR_BAD_ACTION", "$b%s$b is not a recognized do-not-register action." }, - { "CSMSG_DNR_SEARCH_RESULTS", "The following do-not-registers were found:" }, /* Channel unregistration */ { "CSMSG_UNREG_SUCCESS", "$b%s$b has been unregistered." }, @@ -200,6 +199,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_ALREADY_DOWN", "You are not opped, halfopped, or voiced in $b%s$b." }, { "CSMSG_ALREADY_OPCHANNED", "There has been no net.join since the last opchan in $b%s$b." }, { "CSMSG_OPCHAN_DONE", "I have (re-)opped myself in $b%s$b." }, + { "CSMSG_NOT_IN_CHANNEL", "I am not in %s." }, /* Removing yourself from a channel. */ { "CSMSG_NO_OWNER_DELETEME", "You cannot delete your owner access in $b%s$b." }, @@ -231,7 +231,6 @@ static const struct message_entry msgtab[] = { { "CSMSG_MULTIPLE_OWNERS", "There is more than one owner in %s; please use $bCLVL$b, $bDELOWNER$b and/or $bADDOWNER$b instead." }, { "CSMSG_NO_OWNER", "There is no owner for %s; please use $bCLVL$b and/or $bADDOWNER$b instead." }, { "CSMSG_TRANSFER_WAIT", "You must wait %s before you can give ownership of $b%s$b to someone else." }, - { "CSMSG_CONFIRM_GIVEOWNERSHIP", "To really give ownership to $b%1$s$b, you must use 'giveownership *%1$s %2$s'." }, { "CSMSG_NO_TRANSFER_SELF", "You cannot give ownership to your own account." }, { "CSMSG_OWNERSHIP_GIVEN", "Ownership of $b%s$b has been transferred to account $b%s$b." }, @@ -280,7 +279,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_BAD_SETLEVEL", "You cannot change any setting to above your level." }, { "CSMSG_BAD_SETTERS", "You cannot change Setters to above your level." }, { "CSMSG_INVALID_MODE_LOCK", "$b%s$b is an invalid mode lock." }, - { "CSMSG_INVALID_NUMERIC", "$b%d$b is not a valid choice. Choose one:" }, + { "CSMSG_INVALID_NUMERIC", "$b%s$b is not a valid choice. Choose one:" }, { "CSMSG_SET_DEFAULT_TOPIC", "$bDefaultTopic$b %s" }, { "CSMSG_SET_TOPICMASK", "$bTopicMask $b %s" }, { "CSMSG_SET_GREETING", "$bGreeting $b %s" }, @@ -303,9 +302,9 @@ static const struct message_entry msgtab[] = { { "CSMSG_SET_TOYS", "$bToys $b %d - %s" }, { "CSMSG_SET_CTCPREACTION", "$bCTCPReaction$b %d - %s" }, { "CSMSG_SET_TOPICREFRESH", "$bTopicRefresh$b %d - %s" }, - { "CSMSG_SET_UNREVIEWED", "$bUnreviewed $b %s" }, { "CSMSG_SET_RESYNC", "$bResync $b %d - %s" }, { "CSMSG_SET_BANTIMEOUT", "$bBanTimeout $b %d - %s" }, + { "CSMSG_SET_MAXSETINFO", "$bMaxSetInfo $b %d - maximum characters in a setinfo line." }, { "CSMSG_USET_AUTOOP", "$bAutoOp $b %s" }, { "CSMSG_USET_AUTOVOICE", "$bAutoVoice $b %s" }, @@ -326,7 +325,7 @@ static const struct message_entry msgtab[] = { { "CSMSG_DEVOICED_USERS", "Devoiced users in $b%s$b." }, { "CSMSG_AUTOMODE_NONE", "Noone will be automatically oped, half-oped, or voiced." }, - { "CSMSG_AUTOMODE_NORMAL", "Give voice to peons, half-op to halfops, and op to ops." }, + { "CSMSG_AUTOMODE_NORMAL", "Give voice to pals, half-op to halfops, and op to ops." }, { "CSMSG_AUTOMODE_VOICE", "#1 plus give voice to everyone." }, { "CSMSG_AUTOMODE_HOP", "#1 plus give halfops to everyone." }, { "CSMSG_AUTOMODE_OP", "#1 plus give ops to everyone (not advised)" }, @@ -432,9 +431,6 @@ static const struct message_entry msgtab[] = { { "CSMSG_HELPER_HAS_ACCESS", "%s has $b%s$b access (%d) in %s and has $bsecurity override$b enabled." }, { "CSMSG_LAZY_SMURF_TARGET", "%s is %s ($bIRCOp$b; not logged in)." }, { "CSMSG_SMURF_TARGET", "%s is %s ($b%s$b)." }, - { "CSMSG_OPERATOR_TITLE", "IRC operator" }, - { "CSMSG_UC_H_TITLE", "network helper" }, - { "CSMSG_LC_H_TITLE", "support helper" }, { "CSMSG_LAME_SMURF_TARGET", "%s is an IRC operator." }, /* Seen information */ @@ -509,7 +505,6 @@ static const struct message_entry msgtab[] = { /* Channel configuration */ { "CSMSG_INVALID_OPTION", "$b%s$b is not a valid %s option." }, - { "CSMSG_INVALID_CFLAG", "$b%s$b is not a recognized channel flag." }, { "CSMSG_CHANNEL_OPTIONS", "$bChannel Options for %s$b" }, { "CSMSG_CHANNEL_OPTIONS_END", "-------------End of Options-------------" }, { "CSMSG_GREETING_TOO_LONG", "Your greeting ($b%d$b characters) must be shorter than $b%d$b characters." }, @@ -529,6 +524,30 @@ static const struct message_entry msgtab[] = { { "CSMSG_DIE_ROLL", "A $b%lu$b shows on the %lu-sided die." }, { "CSMSG_HUGGLES_HIM", "\001ACTION huggles %s\001" }, { "CSMSG_HUGGLES_YOU", "\001ACTION huggles you\001" }, + { "CSMSG_ROULETTE_LOADS", "\001ACTION loads the gun and sets it on the table\001" }, + { "CSMSG_ROULETTE_NEW", "Please type %croulette to start a new round" } , + { "CSMSG_ROULETTE_BETTER_LUCK", "Better luck next time, %s" }, + { "CSMSG_ROULETTE_BANG", "Bang!!!" } , + { "CSMSG_ROULETTE_CLICK", "Click" } , + + { "CSMSG_SPIN_WHEEL1", "\001ACTION spins the wheel of misfortune for: %s\001" } , + { "CSMSG_SPIN_WHEEL2", "Round and round she goes, where she stops, nobody knows...!" } , + { "CSMSG_SPIN_WHEEL3", "The wheel of misfortune has stopped on..." } , + + { "CSMSG_SPIN_PEER", "Peer: Peer's gonna eat you!!!!" } , + { "CSMSG_SPIN_PARTALL", "Part all: Part all channels" } , + { "CSMSG_SPIN_Gline", "Gline: /gline for random amount of time" } , + { "CSMSG_SPIN_SHUN", "Shun: /shun for random amount of time" } , + { "CSMSG_SPIN_NOTHING", "Nothing: Absolutely nothing" } , + { "CSMSG_SPIN_RANDJOIN", "Random join: Join a bunch of random channels, then /part all of 'em several times" } , + { "CSMSG_SPIN_ABUSEWHOIS", "Abuse whois: Abuse line added to /whois info" } , + { "CSMSG_SPIN_KICKALL", "Kick all: /kick from each channel you're in" } , + { "CSMSG_SPIN_NICKCHANGE", "Nick change: Random Nick Change" } , + { "CSMSG_SPIN_KILL", "Kill: /kill" } , + { "CSMSG_SPIN_SVSIGNORE", "Ignore: Services ignore for random amount of time" } , + { "CSMSG_SPIN_SVSIGNORE_OPER", "Ignore: I'm trying REALLY hard to ignore you, but your IRCOp smell is overwhelming!" } , + { "CSMSG_SPIN_KICKBANALL", "Kickban all: /kick and ban from each channel your're in" } , + { "CSMSG_SPIN_UNKNOWN", "Error: I don't know how to '%s' you, so you live for now..." }, /* Other things */ { "CSMSG_EVENT_SEARCH_RESULTS", "$bChannel Events for %s$b" }, @@ -582,7 +601,6 @@ static struct unsigned long db_backup_frequency; unsigned long channel_expire_frequency; - unsigned long dnr_expire_frequency; unsigned long ban_timeout_frequency; long info_delay; @@ -605,6 +623,7 @@ static struct struct string_list *set_shows; struct string_list *eightball; struct string_list *old_ban_names; + struct string_list *wheel; const char *ctcp_short_ban_duration; const char *ctcp_long_ban_duration; @@ -640,6 +659,9 @@ enum note_visible_type NOTE_VIS_PRIVILEGED }; +struct io_fd *socket_io_fd; +extern struct cManagerNode cManager; + struct note_type { enum note_access_type set_access_type; @@ -669,6 +691,7 @@ static const struct { unsigned short level; char ch; } accessLevels[] = { /* MUST be orderd less to most! */ + { "pal", "Pal", UL_PEON, '+' }, { "peon", "Peon", UL_PEON, '+' }, { "halfop", "HalfOp", UL_HALFOP, '%' }, { "op", "Op", UL_OP, '@' }, @@ -774,6 +797,28 @@ unsigned int chanserv_read_version = 0; /* db version control */ #define GetChannelAccess(channel, handle) _GetChannelUser(channel, handle, 0, 0) #define GetTrueChannelAccess(channel, handle) _GetChannelUser(channel, handle, 0, 1) +void sputsock(const char *text, ...) PRINTF_LIKE(1, 2); + +void +sputsock(const char *text, ...) +{ + va_list arg_list; + char buffer[MAXLEN]; + int pos; + + if (!cManager.uplink || cManager.uplink->state == DISCONNECTED) return; + buffer[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(buffer, MAXLEN - 2, text, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; + buffer[pos] = 0; + log_replay(MAIN_LOG, true, buffer); + buffer[pos++] = '\n'; + buffer[pos] = 0; + ioset_write(socket_io_fd, buffer, pos); +} + unsigned short user_level_from_name(const char *name, unsigned short clamp_level) { @@ -796,7 +841,7 @@ user_level_name_from_level(int level) highest = "None"; if(level >= 1) - highest = "Peon"; + highest = "Pal"; for(ii = 0; (ii < ArrayLength(accessLevels)); ii++) if(level >= accessLevels[ii].level) highest = accessLevels[ii].title; @@ -930,7 +975,7 @@ scan_user_presence(struct userData *uData, struct userNode *user) } static void -chanserv_ctcp_check(struct userNode *user, struct chanNode *channel, const char *text, UNUSED_ARG(struct userNode *bot)) +chanserv_ctcp_check(struct userNode *user, struct chanNode *channel, char *text, UNUSED_ARG(struct userNode *bot)) { unsigned int eflags, argc; char *argv[4]; @@ -953,7 +998,7 @@ chanserv_ctcp_check(struct userNode *user, struct chanNode *channel, const char return; /* We need to enforce against them; do so. */ eflags = 0; - argv[0] = (char*)text; + argv[0] = text; argv[1] = user->nick; argc = 2; if(GetUserMode(channel, user)) @@ -1765,38 +1810,6 @@ expire_channels(UNUSED_ARG(void *data)) timeq_add(now + chanserv_conf.channel_expire_frequency, expire_channels, NULL); } -static void -expire_dnrs(UNUSED_ARG(void *data)) -{ - dict_iterator_t it; - struct do_not_register *dnr; - - for(it = dict_first(handle_dnrs); it; it = iter_next(it)) - { - dnr = iter_data(it); - if(!dnr->expires || dnr->expires > now) - continue; - dict_remove(handle_dnrs, dnr->chan_name + 1); - } - for(it = dict_first(plain_dnrs); it; it = iter_next(it)) - { - dnr = iter_data(it); - if(!dnr->expires || dnr->expires > now) - continue; - dict_remove(plain_dnrs, dnr->chan_name); - } - for(it = dict_first(mask_dnrs); it; it = iter_next(it)) - { - dnr = iter_data(it); - if(!dnr->expires || dnr->expires > now) - continue; - dict_remove(mask_dnrs, dnr->chan_name); - } - - if(chanserv_conf.dnr_expire_frequency) - timeq_add(now + chanserv_conf.dnr_expire_frequency, expire_dnrs, NULL); -} - static int protect_user(const struct userNode *victim, const struct userNode *aggressor, struct chanData *channel, int protect_invitables) { @@ -1934,14 +1947,13 @@ validate_dehop(struct svccmd *cmd, struct userNode *user, struct chanNode *chann } static struct do_not_register * -chanserv_add_dnr(const char *chan_name, const char *setter, time_t expires, const char *reason) +chanserv_add_dnr(const char *chan_name, const char *setter, const char *reason) { struct do_not_register *dnr = calloc(1, sizeof(*dnr)+strlen(reason)); safestrncpy(dnr->chan_name, chan_name, sizeof(dnr->chan_name)); safestrncpy(dnr->setter, setter, sizeof(dnr->setter)); strcpy(dnr->reason, reason); dnr->set = now; - dnr->expires = expires; if(dnr->chan_name[0] == '*') dict_insert(handle_dnrs, dnr->chan_name+1, dnr); else if(strpbrk(dnr->chan_name, "*?")) @@ -1952,81 +1964,44 @@ chanserv_add_dnr(const char *chan_name, const char *setter, time_t expires, cons } static struct dnrList -chanserv_find_dnrs(const char *chan_name, const char *handle, unsigned int max) +chanserv_find_dnrs(const char *chan_name, const char *handle) { struct dnrList list; - dict_iterator_t it, next; + dict_iterator_t it; struct do_not_register *dnr; dnrList_init(&list); - if(handle && (dnr = dict_find(handle_dnrs, handle, NULL))) - { - if(dnr->expires && dnr->expires <= now) - dict_remove(handle_dnrs, handle); - else if(list.used < max) dnrList_append(&list, dnr); - } - if(chan_name && (dnr = dict_find(plain_dnrs, chan_name, NULL))) - { - if(dnr->expires && dnr->expires <= now) - dict_remove(plain_dnrs, chan_name); - else if(list.used < max) dnrList_append(&list, dnr); - } - if(chan_name) - { - for(it = dict_first(mask_dnrs); it && list.used < max; it = next) - { - next = iter_next(it); - if(!match_ircglob(chan_name, iter_key(it))) - continue; - dnr = iter_data(it); - if(dnr->expires && dnr->expires <= now) - dict_remove(mask_dnrs, iter_key(it)); - else - dnrList_append(&list, dnr); - } - } - + for(it = dict_first(mask_dnrs); it; it = iter_next(it)) + if(match_ircglob(chan_name, iter_key(it))) + dnrList_append(&list, iter_data(it)); return list; } -static int dnr_print_func(struct do_not_register *dnr, void *extra) -{ - struct userNode *user; - char buf1[INTERVALLEN]; - char buf2[INTERVALLEN]; - - user = extra; - if(dnr->set) - strftime(buf1, sizeof(buf1), "%d %b %Y", localtime(&dnr->set)); - if(dnr->expires) - { - strftime(buf2, sizeof(buf2), "%d %b %Y", localtime(&dnr->expires)); - send_message(user, chanserv, "CSMSG_DNR_INFO_SET_EXPIRES", dnr->chan_name, buf1, dnr->setter, buf2, dnr->reason); - } - else if(dnr->set) - { - send_message(user, chanserv, "CSMSG_DNR_INFO_SET", dnr->chan_name, buf1, dnr->setter, dnr->reason); - } - else - send_message(user, chanserv, "CSMSG_DNR_INFO", dnr->chan_name, dnr->setter, dnr->reason); - return 0; -} - static unsigned int chanserv_show_dnrs(struct userNode *user, struct svccmd *cmd, const char *chan_name, const char *handle) { struct dnrList list; + struct do_not_register *dnr; unsigned int ii; + char buf[INTERVALLEN]; - list = chanserv_find_dnrs(chan_name, handle, UINT_MAX); + list = chanserv_find_dnrs(chan_name, handle); for(ii = 0; (ii < list.used) && (ii < 10); ++ii) - dnr_print_func(list.list[ii], user); - + { + dnr = list.list[ii]; + if(dnr->set) + { + strftime(buf, sizeof(buf), "%Y %b %d", localtime(&dnr->set)); + reply("CSMSG_DNR_INFO_SET", dnr->chan_name, buf, dnr->setter, dnr->reason); + } + else + reply("CSMSG_DNR_INFO", dnr->chan_name, dnr->setter, dnr->reason); + } if(ii < list.used) reply("CSMSG_MORE_DNRS", list.used - ii); free(list.list); @@ -2035,51 +2010,66 @@ chanserv_show_dnrs(struct userNode *user, struct svccmd *cmd, const char *chan_n struct do_not_register * chanserv_is_dnr(const char *chan_name, struct handle_info *handle) -{ - struct dnrList list; - struct do_not_register *dnr; - - list = chanserv_find_dnrs(chan_name, handle ? handle->handle : NULL, 1); - dnr = list.used ? list.list[0] : NULL; - free(list.list); - - return dnr; -} - -static unsigned int send_dnrs(struct userNode *user, dict_t dict) { struct do_not_register *dnr; - dict_iterator_t it, next; - unsigned int matches = 0; + dict_iterator_t it; - for(it = dict_first(dict); it; it = next) + if(handle && (dnr = dict_find(handle_dnrs, handle->handle, NULL))) + return dnr; + if(chan_name) { - dnr = iter_data(it); - next = iter_next(it); - if(dnr->expires && dnr->expires <= now) - { - dict_remove(dict, iter_key(it)); - continue; - } - dnr_print_func(dnr, user); - matches++; + if((dnr = dict_find(plain_dnrs, chan_name, NULL))) + return dnr; + for(it = dict_first(mask_dnrs); it; it = iter_next(it)) + if(match_ircglob(chan_name, iter_key(it))) + return iter_data(it); } - - return matches; + return NULL; } static CHANSERV_FUNC(cmd_noregister) { const char *target; - time_t expiry, duration; + struct do_not_register *dnr; + char buf[INTERVALLEN]; unsigned int matches; if(argc < 2) { + dict_iterator_t it; + reply("CSMSG_DNR_SEARCH_RESULTS"); - matches = send_dnrs(user, handle_dnrs); - matches += send_dnrs(user, plain_dnrs); - matches += send_dnrs(user, mask_dnrs); + if(user->handle_info && user->handle_info->userlist_style != HI_STYLE_CLEAN) + reply("CSMSG_BAR"); + matches = 0; + for(it = dict_first(handle_dnrs); it; it = iter_next(it)) + { + dnr = iter_data(it); + if(dnr->set) + reply("CSMSG_DNR_INFO_SET", dnr->chan_name, intervalString(buf, now - dnr->set, user->handle_info), dnr->setter, dnr->reason); + else + reply("CSMSG_DNR_INFO", dnr->chan_name, dnr->setter, dnr->reason); + matches++; + } + for(it = dict_first(plain_dnrs); it; it = iter_next(it)) + { + dnr = iter_data(it); + if(dnr->set) + reply("CSMSG_DNR_INFO_SET", dnr->chan_name, intervalString(buf, now - dnr->set, user->handle_info), dnr->setter, dnr->reason); + else + reply("CSMSG_DNR_INFO", dnr->chan_name, dnr->setter, dnr->reason); + matches++; + } + for(it = dict_first(mask_dnrs); it; it = iter_next(it)) + { + dnr = iter_data(it); + if(dnr->set) + reply("CSMSG_DNR_INFO_SET", dnr->chan_name, intervalString(buf, now - dnr->set, user->handle_info), dnr->setter, dnr->reason); + else + reply("CSMSG_DNR_INFO", dnr->chan_name, dnr->setter, dnr->reason); + matches++; + } + if(matches) reply("MSG_MATCH_COUNT", matches); else @@ -2097,34 +2087,20 @@ static CHANSERV_FUNC(cmd_noregister) if(argc > 2) { - if(argc == 3) - { - reply("MSG_INVALID_DURATION", argv[2]); - return 0; - } - - if(!strcmp(argv[2], "0")) - expiry = 0; - else if((duration = ParseInterval(argv[2]))) - expiry = now + duration; - else - { - reply("MSG_INVALID_DURATION", argv[2]); - return 0; - } - - const char *reason = unsplit_string(argv + 3, argc - 3, NULL); + const char *reason = unsplit_string(argv + 2, argc - 2, NULL); if((*target == '*') && !get_handle_info(target + 1)) { reply("MSG_HANDLE_UNKNOWN", target + 1); return 0; } - chanserv_add_dnr(target, user->handle_info->handle, expiry, reason); + chanserv_add_dnr(target, user->handle_info->handle, reason); reply("CSMSG_NOREGISTER_CHANNEL", target); return 1; } reply("CSMSG_DNR_SEARCH_RESULTS"); + if(user->handle_info && user->handle_info->userlist_style != HI_STYLE_CLEAN) + reply("CSMSG_BAR"); if(*target == '*') matches = chanserv_show_dnrs(user, cmd, NULL, target + 1); else @@ -2138,262 +2114,26 @@ static CHANSERV_FUNC(cmd_allowregister) { const char *chan_name = argv[1]; - if(((chan_name[0] == '*') && dict_remove(handle_dnrs, chan_name+1)) - || dict_remove(plain_dnrs, chan_name) - || dict_remove(mask_dnrs, chan_name)) + if((chan_name[0] == '*') && dict_find(handle_dnrs, chan_name+1, NULL)) { + dict_remove(handle_dnrs, chan_name+1); reply("CSMSG_DNR_REMOVED", chan_name); - return 1; } - reply("CSMSG_NO_SUCH_DNR", chan_name); - return 0; -} - -struct dnr_search { - struct userNode *source; - char *chan_mask; - char *setter_mask; - char *reason_mask; - time_t min_set, max_set; - time_t min_expires, max_expires; - unsigned int limit; -}; - -static int -dnr_search_matches(const struct do_not_register *dnr, const struct dnr_search *search) -{ - return !((dnr->set < search->min_set) - || (dnr->set > search->max_set) - || (dnr->expires && ((dnr->expires < search->min_expires) - || (dnr->expires > search->max_expires))) - || (search->chan_mask - && !match_ircglob(dnr->chan_name, search->chan_mask)) - || (search->setter_mask - && !match_ircglob(dnr->setter, search->setter_mask)) - || (search->reason_mask - && !match_ircglob(dnr->reason, search->reason_mask))); -} - -static struct dnr_search * -dnr_search_create(struct userNode *user, struct svccmd *cmd, unsigned int argc, char *argv[]) -{ - struct dnr_search *discrim; - unsigned int ii; - - discrim = calloc(1, sizeof(*discrim)); - discrim->source = user; - discrim->chan_mask = NULL; - discrim->setter_mask = NULL; - discrim->reason_mask = NULL; - discrim->max_set = INT_MAX; - discrim->max_expires = INT_MAX; - discrim->limit = 50; - - for(ii=0; iichan_mask = argv[++ii]; - } - else if(0 == irccasecmp(argv[ii], "setter")) - { - discrim->setter_mask = argv[++ii]; - } - else if(0 == irccasecmp(argv[ii], "reason")) - { - discrim->reason_mask = argv[++ii]; - } - else if(0 == irccasecmp(argv[ii], "limit")) - { - discrim->limit = strtoul(argv[++ii], NULL, 0); - } - else if(0 == irccasecmp(argv[ii], "set")) - { - const char *cmp = argv[++ii]; - if(cmp[0] == '<') { - if(cmp[1] == '=') - discrim->min_set = now - ParseInterval(cmp + 2); - else - discrim->min_set = now - (ParseInterval(cmp + 1) - 1); - } else if(cmp[0] == '=') { - discrim->min_set = discrim->max_set = now - ParseInterval(cmp + 1); - } else if(cmp[0] == '>') { - if(cmp[1] == '=') - discrim->max_set = now - ParseInterval(cmp + 2); - else - discrim->max_set = now - (ParseInterval(cmp + 1) - 1); - } else { - discrim->max_set = now - (ParseInterval(cmp) - 1); - } - } - else if(0 == irccasecmp(argv[ii], "expires")) - { - const char *cmp = argv[++ii]; - if(cmp[0] == '<') { - if(cmp[1] == '=') - discrim->max_expires = now + ParseInterval(cmp + 2); - else - discrim->max_expires = now + (ParseInterval(cmp + 1) - 1); - } else if(cmp[0] == '=') { - discrim->min_expires = discrim->max_expires = now + ParseInterval(cmp + 1); - } else if(cmp[0] == '>') { - if(cmp[1] == '=') - discrim->min_expires = now + ParseInterval(cmp + 2); - else - discrim->min_expires = now + (ParseInterval(cmp + 1) - 1); - } else { - discrim->min_expires = now + (ParseInterval(cmp) - 1); - } - } - else - { - reply("MSG_INVALID_CRITERIA", argv[ii]); - goto fail; - } - } - return discrim; - - fail: - free(discrim); - return NULL; -} - -typedef int (*dnr_search_func)(struct do_not_register *match, void *extra); - -static unsigned int -dnr_search(struct dnr_search *discrim, dnr_search_func dsf, void *data) -{ - struct do_not_register *dnr; - dict_iterator_t next; - dict_iterator_t it; - unsigned int count; - int target_fixed; - - /* Initialize local variables. */ - count = 0; - target_fixed = 0; - if(discrim->chan_mask) + else if(dict_find(plain_dnrs, chan_name, NULL)) { - int shift = (discrim->chan_mask[0] == '\\' && discrim->chan_mask[1] == '*') ? 2 : 0; - if('\0' == discrim->chan_mask[shift + strcspn(discrim->chan_mask+shift, "*?")]) - target_fixed = 1; - } - - if(target_fixed && discrim->chan_mask[0] == '\\' && discrim->chan_mask[1] == '*') - { - /* Check against account-based DNRs. */ - dnr = dict_find(handle_dnrs, discrim->chan_mask + 2, NULL); - if(dnr && dnr_search_matches(dnr, discrim) && (count++ < discrim->limit)) - dsf(dnr, data); - } - else if(target_fixed) - { - /* Check against channel-based DNRs. */ - dnr = dict_find(plain_dnrs, discrim->chan_mask, NULL); - if(dnr && dnr_search_matches(dnr, discrim) && (count++ < discrim->limit)) - dsf(dnr, data); - } - else - { - /* Exhaustively search account DNRs. */ - for(it = dict_first(handle_dnrs); it; it = next) - { - next = iter_next(it); - dnr = iter_data(it); - if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data)) - break; - } - /* Do the same for channel DNRs. */ - for(it = dict_first(plain_dnrs); it; it = next) - { - next = iter_next(it); - dnr = iter_data(it); - if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data)) - break; - } - - /* Do the same for wildcarded channel DNRs. */ - for(it = dict_first(mask_dnrs); it; it = next) - { - next = iter_next(it); - dnr = iter_data(it); - if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data)) - break; - } - } - return count; -} - -static int -dnr_remove_func(struct do_not_register *match, void *extra) -{ - struct userNode *user; - char *chan_name; - - chan_name = alloca(strlen(match->chan_name) + 1); - strcpy(chan_name, match->chan_name); - user = extra; - if(((chan_name[0] == '*') && dict_remove(handle_dnrs, chan_name+1)) - || dict_remove(plain_dnrs, chan_name) - || dict_remove(mask_dnrs, chan_name)) - { - send_message(user, chanserv, "CSMSG_DNR_REMOVED", chan_name); + dict_remove(plain_dnrs, chan_name); + reply("CSMSG_DNR_REMOVED", chan_name); } - return 0; -} - -static int -dnr_count_func(struct do_not_register *match, void *extra) -{ - return 0; (void)match; (void)extra; -} - -static MODCMD_FUNC(cmd_dnrsearch) -{ - struct dnr_search *discrim; - dnr_search_func action; - struct svccmd *subcmd; - unsigned int matches; - char buf[MAXLEN]; - - sprintf(buf, "dnrsearch %s", argv[1]); - subcmd = dict_find(cmd->parent->commands, buf, NULL); - if(!subcmd) + else if(dict_find(mask_dnrs, chan_name, NULL)) { - reply("CSMSG_DNR_BAD_ACTION", argv[1]); - return 0; + dict_remove(mask_dnrs, chan_name); + reply("CSMSG_DNR_REMOVED", chan_name); } - if(!svccmd_can_invoke(user, cmd->parent->bot, subcmd, channel, SVCCMD_NOISY)) - return 0; - if(!irccasecmp(argv[1], "print")) - action = dnr_print_func; - else if(!irccasecmp(argv[1], "remove")) - action = dnr_remove_func; - else if(!irccasecmp(argv[1], "count")) - action = dnr_count_func; else { - reply("CSMSG_DNR_BAD_ACTION", argv[1]); + reply("CSMSG_NO_SUCH_DNR", chan_name); return 0; } - - discrim = dnr_search_create(user, cmd, argc-2, argv+2); - if(!discrim) - return 0; - - if(action == dnr_print_func) - reply("CSMSG_DNR_SEARCH_RESULTS"); - matches = dnr_search(discrim, action, user); - if(matches) - reply("MSG_MATCH_COUNT", matches); - else - reply("MSG_NO_MATCHES"); - free(discrim); return 1; } @@ -2556,6 +2296,7 @@ static CHANSERV_FUNC(cmd_register) /* Initialize the channel's max user record. */ cData->max = channel->members.used; + cData->maxsetinfo = chanserv_conf.max_userinfo_length; if(handle != user->handle_info) reply("CSMSG_PROXY_SUCCESS", handle->handle, channel->name); @@ -3012,6 +2753,10 @@ static CHANSERV_FUNC(cmd_opchan) reply("CSMSG_ALREADY_OPCHANNED", channel->name); return 0; } + if(!IsInChannel(channel,chanserv)) { + reply("CSMSG_NOT_IN_CHANNEL", channel->name); + return 0; + } channel->channel_info->may_opchan = 0; mod_chanmode_init(&change); change.argc = 1; @@ -3025,9 +2770,9 @@ static CHANSERV_FUNC(cmd_opchan) static CHANSERV_FUNC(cmd_adduser) { struct userData *actee; - struct userData *actor, *real_actor;; + struct userData *actor; struct handle_info *handle; - unsigned short access, override = 0; + unsigned short access; REQUIRE_PARAMS(3); @@ -3045,18 +2790,12 @@ static CHANSERV_FUNC(cmd_adduser) } actor = GetChannelUser(channel->channel_info, user->handle_info); - real_actor = GetChannelAccess(channel->channel_info, user->handle_info); - if(actor->access <= access) { reply("CSMSG_NO_BUMP_ACCESS"); return 0; } - /* Trying to add someone with equal/more access? */ - if (!real_actor || real_actor->access <= access) - override = CMD_LOG_OVERRIDE; - if(!(handle = modcmd_get_handle_info(user, argv[1]))) { // 'kevin must first authenticate with AuthServ.' is sent to user @@ -3103,21 +2842,20 @@ static CHANSERV_FUNC(cmd_adduser) timeq_add(accessexpiry, chanserv_expire_tempuser, actee); reply("CSMSG_ADDED_USER", handle->handle, channel->name, user_level_name_from_level(access), access); - return 1 | override; + return 1; } static CHANSERV_FUNC(cmd_clvl) { struct handle_info *handle; struct userData *victim; - struct userData *actor, *real_actor; - unsigned short new_access, override = 0; + struct userData *actor; + unsigned short new_access; int privileged = IsHelping(user) && ((user->handle_info->opserv_level >= chanserv_conf.nodelete_level) || !IsProtected(channel->channel_info)); REQUIRE_PARAMS(3); actor = GetChannelUser(channel->channel_info, user->handle_info); - real_actor = GetChannelAccess(channel->channel_info, user->handle_info); if(!(handle = modcmd_get_handle_info(user, argv[1]))) return 0; @@ -3172,34 +2910,22 @@ static CHANSERV_FUNC(cmd_clvl) timeq_add(clvlexpiry, chanserv_expire_tempclvl, victim); } - /* Trying to clvl a equal/higher user? */ - if(!real_actor || (real_actor->access <= victim->access && handle != user->handle_info)) - override = CMD_LOG_OVERRIDE; - /* Trying to clvl someone to equal/higher access? */ - if(!real_actor || new_access >= real_actor->access) - override = CMD_LOG_OVERRIDE; - /* Helpers clvling themselves get caught by the "clvl someone to equal/higher access" check. - * If they lower their own access it's not a big problem. - */ - victim->access = new_access; reply("CSMSG_CHANGED_ACCESS", handle->handle, user_level_name_from_level(new_access), new_access, channel->name); - - return 1 | override; + return 1; } static CHANSERV_FUNC(cmd_deluser) { struct handle_info *handle; struct userData *victim; - struct userData *actor, *real_actor; - unsigned short access, override = 0; + struct userData *actor; + unsigned short access; char *chan_name; REQUIRE_PARAMS(2); actor = GetChannelUser(channel->channel_info, user->handle_info); - real_actor = GetChannelAccess(channel->channel_info, user->handle_info); if(!(handle = modcmd_get_handle_info(user, argv[argc-1]))) return 0; @@ -3236,28 +2962,19 @@ static CHANSERV_FUNC(cmd_deluser) return 0; } - /* If people delete themselves it is an override, but they - * could've used deleteme so we don't log it as an override - */ - if(!real_actor || (real_actor->access <= victim->access && real_actor != victim)) - override = CMD_LOG_OVERRIDE; - chan_name = strdup(channel->name); del_channel_user(victim, 1); reply("CSMSG_DELETED_USER", handle->handle, access, chan_name); free(chan_name); - - return 1 | override; + return 1; } static int cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short min_access, unsigned short max_access, char *mask, struct svccmd *cmd) { - struct userData *actor, *real_actor, *uData, *next; - unsigned int override = 0; + struct userData *actor, *uData, *next; actor = GetChannelUser(channel->channel_info, user->handle_info); - real_actor = GetChannelAccess(channel->channel_info, user->handle_info); if(min_access > max_access) { @@ -3271,9 +2988,6 @@ cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short mi return 0; } - if(!real_actor || real_actor->access <= max_access) - override = CMD_LOG_OVERRIDE; - for(uData = channel->channel_info->users; uData; uData = next) { next = uData->next; @@ -3285,8 +2999,7 @@ cmd_mdel_user(struct userNode *user, struct chanNode *channel, unsigned short mi } reply("CSMSG_DELETED_USERS", mask, min_access, max_access, channel->name); - - return 1 | override; + return 1; } static CHANSERV_FUNC(cmd_mdelowner) @@ -3319,6 +3032,10 @@ static CHANSERV_FUNC(cmd_mdelpeon) return cmd_mdel_user(user, channel, UL_PEON, UL_HALFOP-1, argv[1], cmd); } +static CHANSERV_FUNC(cmd_mdelpal) +{ + return cmd_mdel_user(user, channel, UL_PEON, UL_HALFOP-1, argv[1], cmd); +} static CHANSERV_FUNC(cmd_levels) { @@ -3422,15 +3139,13 @@ cmd_trim_users(struct svccmd *cmd, struct userNode *user, struct chanNode *chann time_t limit; actor = GetChannelUser(channel->channel_info, user->handle_info); - actor = GetChannelAccess(channel->channel_info, user->handle_info); - if(min_access > max_access) { reply("CSMSG_BAD_RANGE", min_access, max_access); return 0; } - if(!actor || actor->access <= max_access) + if((actor->access <= max_access) && !IsHelping(user)) { reply("CSMSG_NO_ACCESS"); return 0; @@ -3770,35 +3485,6 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c ban = generate_hostmask(victim, GENMASK_STRICT_HOST|GENMASK_ANY_IDENT); name = victim->nick; } - else if(!is_ircmask(argv[1]) && (*argv[1] == '*')) - { - struct handle_info *hi; - char banmask[NICKLEN + USERLEN + HOSTLEN + 3]; - const char *accountname = argv[1] + 1; - - if(!(hi = get_handle_info(accountname))) - { - reply("MSG_HANDLE_UNKNOWN", accountname); - return 0; - } - - snprintf(banmask, sizeof(banmask), "*!*@%s.*", hi->handle); - victims = alloca(sizeof(victims[0]) * channel->members.used); - - if(bad_channel_ban(channel, user, banmask, &victimCount, victims)) - { - reply("CSMSG_MASK_PROTECTED", banmask); - return 0; - } - - if((action == ACTION_KICK) && (victimCount == 0)) - { - reply("CSMSG_NO_MATCHING_USERS", channel->name, banmask); - return 0; - } - - name = ban = strdup(banmask); - } else { if(!is_ircmask(argv[1])) @@ -4202,23 +3888,13 @@ unban_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c /* may want to allow a comma delimited list of users... */ if(!(actee = GetUserH(argv[1]))) { - if(!is_ircmask(argv[1]) && *argv[1] == '*') - { - char banmask[NICKLEN + USERLEN + HOSTLEN + 3]; - const char *accountname = argv[1] + 1; - - snprintf(banmask, sizeof(banmask), "*!*@%s.*", accountname); - mask = strdup(banmask); - } - else if(!is_ircmask(argv[1])) - { - reply("MSG_NICK_UNKNOWN", argv[1]); - return 0; + if(!is_ircmask(argv[1])) + { + reply("MSG_NICK_UNKNOWN", argv[1]); + return 0; } - else - { - mask = strdup(argv[1]); - } + + mask = strdup(argv[1]); } /* We don't sanitize the mask here because ircu @@ -4463,17 +4139,17 @@ static CHANSERV_FUNC(cmd_access) if(IsOper(target)) { epithet = chanserv_conf.irc_operator_epithet; - type = user_find_message(user, "CSMSG_OPERATOR_TITLE"); + type = "IRCOp"; } else if(IsNetworkHelper(target)) { epithet = chanserv_conf.network_helper_epithet; - type = user_find_message(user, "CSMSG_UC_H_TITLE"); + type = "network helper"; } else if(IsSupportHelper(target)) { epithet = chanserv_conf.support_helper_epithet; - type = user_find_message(user, "CSMSG_LC_H_TITLE"); + type = "support helper"; } if(epithet) { @@ -4875,22 +4551,16 @@ static CHANSERV_FUNC(cmd_plist) static CHANSERV_FUNC(cmd_lamers) { - struct userNode *search_u = NULL; struct helpfile_table tbl; - unsigned int matches = 0, timed = 0, search_wilds = 0, ii; + unsigned int matches = 0, timed = 0, ii; char t_buffer[INTERVALLEN], e_buffer[INTERVALLEN], *search; const char *msg_never, *triggered, *expires; struct banData *ban, **bans; /* lamers */ - if(argc < 2) + if(argc > 1) + search = argv[1]; + else search = NULL; - else if(strchr(search = argv[1], '!')) - { - search = argv[1]; - search_wilds = search[strcspn(search, "?*")]; - } - else if(!(search_u = GetUserH(search))) - reply("MSG_NICK_UNKNOWN", search); reply("CSMSG_LAMERS_HEADER", channel->name); bans = alloca(channel->channel_info->banCount * sizeof(struct banData *)); /* lamers */ @@ -4898,16 +4568,8 @@ static CHANSERV_FUNC(cmd_lamers) /* lamers */ for(ban = channel->channel_info->bans; ban; ban = ban->next) { - if(search_u) - { - if(!user_matches_glob(search_u, ban->mask, MATCH_USENICK | MATCH_VISIBLE)) + if(search && !match_ircglobs(search, ban->mask)) continue; - } - else if(search) - { - if(search_wilds ? !match_ircglobs(search, ban->mask) : !match_ircglob(search, ban->mask)) - continue; - } bans[matches++] = ban; if(ban->expires) timed = 1; @@ -5509,12 +5171,10 @@ static CHANSERV_FUNC(cmd_peek) static MODCMD_FUNC(cmd_wipeinfo) { struct handle_info *victim; - struct userData *ud, *actor, *real_actor; - unsigned int override = 0; + struct userData *ud, *actor; REQUIRE_PARAMS(2); actor = GetChannelUser(channel->channel_info, user->handle_info); - real_actor = GetChannelAccess(channel->channel_info, user->handle_info); if(!(victim = modcmd_get_handle_info(user, argv[1]))) return 0; if(!(ud = GetTrueChannelAccess(channel->channel_info, victim))) @@ -5527,13 +5187,11 @@ static MODCMD_FUNC(cmd_wipeinfo) reply("MSG_USER_OUTRANKED", victim->handle); return 0; } - if((ud != real_actor) && (!real_actor || (ud->access >= real_actor->access))) - override = CMD_LOG_OVERRIDE; if(ud->info) free(ud->info); ud->info = NULL; reply("CSMSG_WIPED_INFO_LINE", argv[1], channel->name); - return 1 | override; + return 1; } static void @@ -6170,8 +5828,6 @@ chanserv_search_create(struct svccmd *cmd, struct userNode *user, unsigned int a search->flags |= CHANNEL_NODELETE; else if(!irccasecmp(argv[i], "suspended")) search->flags |= CHANNEL_SUSPENDED; - else if(!irccasecmp(argv[i], "unreviewed")) - search->flags |= CHANNEL_UNREVIEWED; else { reply("CSMSG_INVALID_CFLAG", argv[i]); @@ -6314,60 +5970,6 @@ static CHANSERV_FUNC(cmd_unvisited) return 1; } -static MODCMD_FUNC(chan_opt_unreviewed) -{ - struct chanData *cData = channel->channel_info; - int value = (cData->flags & CHANNEL_UNREVIEWED) ? 1 : 0; - - if(argc > 1) - { - int new_value; - - /* The two directions can have different ACLs. */ - if(enabled_string(argv[1])) - new_value = 1; - else if(disabled_string(argv[1])) - new_value = 0; - else - { - reply("MSG_INVALID_BINARY", argv[1]); - return 0; - } - - if (new_value != value) - { - struct svccmd *subcmd; - char subcmd_name[32]; - - snprintf(subcmd_name, sizeof(subcmd_name), "%s %s", argv[0], (new_value ? "on" : "off")); - subcmd = dict_find(cmd->parent->commands, subcmd_name, NULL); - if(!subcmd) - { - reply("MSG_COMMAND_DISABLED", subcmd_name); - return 0; - } - else if(!svccmd_can_invoke(user, cmd->parent->bot, subcmd, channel, SVCCMD_NOISY)) - return 0; - - if (new_value) - cData->flags |= CHANNEL_UNREVIEWED; - else - { - free(cData->registrar); - cData->registrar = strdup(user->handle_info->handle); - cData->flags &= ~CHANNEL_UNREVIEWED; - } - value = new_value; - } - } - - if(value) - reply("CSMSG_SET_UNREVIEWED", user_find_message(user, "MSG_ON")); - else - reply("CSMSG_SET_UNREVIEWED", user_find_message(user, "MSG_OFF")); - return 1; -} - static MODCMD_FUNC(chan_opt_defaulttopic) { if(argc > 1) @@ -6483,6 +6085,20 @@ static MODCMD_FUNC(chan_opt_usergreeting) return opt_greeting_common(user, cmd, argc, argv, "CSMSG_SET_USERGREETING", &channel->channel_info->user_greeting); } +static MODCMD_FUNC(chan_opt_maxsetinfo) +{ + unsigned int charmax; + + if(argc > 1) { + charmax = atoi(argv[1]); + if ((charmax > 0) && (charmax < chanserv_conf.max_userinfo_length)) + channel->channel_info->maxsetinfo = charmax; + } + + reply("CSMSG_SET_MAXSETINFO", channel->channel_info->maxsetinfo); + return 1; +} + static MODCMD_FUNC(chan_opt_modes) { struct mod_chanmode *new_modes; @@ -6583,6 +6199,16 @@ static MODCMD_FUNC(chan_opt_nodelete) static MODCMD_FUNC(chan_opt_dynlimit) { + struct mod_chanmode change; + + if (argc > 1) { + if (disabled_string(argv[1])) { + mod_chanmode_init(&change); + change.modes_clear |= MODE_LIMIT; + mod_chanmode_announce(chanserv, channel, &change); + } + } + CHANNEL_BINARY_OPTION("CSMSG_SET_DYNLIMIT", CHANNEL_DYNAMIC_LIMIT); } @@ -6655,8 +6281,7 @@ static MODCMD_FUNC(chan_opt_defaults) reply("CSMSG_CONFIRM_DEFAULTS", channel->name, confirm); return 0; } - cData->flags = (CHANNEL_DEFAULT_FLAGS & ~CHANNEL_PRESERVED_FLAGS) - | (cData->flags & CHANNEL_PRESERVED_FLAGS); + cData->flags = CHANNEL_DEFAULT_FLAGS; cData->modes = chanserv_conf.default_modes; for(lvlOpt = 0; lvlOpt < NUM_LEVEL_OPTIONS; ++lvlOpt) cData->lvlOpts[lvlOpt] = levelOptions[lvlOpt].default_value; @@ -6783,7 +6408,7 @@ channel_multiple_option(enum charOption option, struct userNode *user, struct ch if(!isdigit(argv[1][0]) || (index < 0) || (index >= count)) { - reply("CSMSG_INVALID_NUMERIC", index); + reply("CSMSG_INVALID_NUMERIC", argv[1]); /* Show possible values. */ for(index = 0; index < count; index++) reply(charOptions[option].format_name, index, user_find_message(user, charOptions[option].values[index].format_name)); @@ -6911,9 +6536,6 @@ static CHANSERV_FUNC(cmd_set) return 0; } - argv[0] = ""; - argv[1] = buf; - return subcmd->command->func(user, channel, argc - 1, argv + 1, subcmd); } @@ -6997,9 +6619,9 @@ static MODCMD_FUNC(user_opt_info) { size_t bp; infoline = unsplit_string(argv + 1, argc - 1, NULL); - if(strlen(infoline) > chanserv_conf.max_userinfo_length) + if(strlen(infoline) > channel->channel_info->maxsetinfo) { - reply("CSMSG_INFOLINE_TOO_LONG", chanserv_conf.max_userinfo_length); + reply("CSMSG_INFOLINE_TOO_LONG", channel->channel_info->maxsetinfo); return 0; } bp = strcspn(infoline, "\001"); @@ -7080,12 +6702,9 @@ static CHANSERV_FUNC(cmd_uset) static CHANSERV_FUNC(cmd_giveownership) { struct handle_info *new_owner_hi; - struct userData *new_owner; - struct userData *curr_user; - struct userData *invoker; + struct userData *new_owner, *curr_user; struct chanData *cData = channel->channel_info; struct do_not_register *dnr; - const char *confirm; struct giveownership *giveownership; unsigned int force, override; unsigned short co_access, new_owner_old_access; @@ -7120,7 +6739,7 @@ static CHANSERV_FUNC(cmd_giveownership) } curr_user = owner; } - else if(!force && (now < (time_t)(cData->ownerTransfer + chanserv_conf.giveownership_period))) + else if (!force && (now < (time_t)(cData->ownerTransfer + chanserv_conf.giveownership_period))) { char delay[INTERVALLEN]; intervalString(delay, cData->ownerTransfer + chanserv_conf.giveownership_period - now, user->handle_info); @@ -7143,7 +6762,7 @@ static CHANSERV_FUNC(cmd_giveownership) { if(force) { - new_owner = add_channel_user(cData, new_owner_hi, UL_OWNER - 1, 0, NULL, 0); + new_owner = add_channel_user(cData, new_owner_hi, UL_COOWNER, 0, NULL, 0); } else { @@ -7164,17 +6783,6 @@ static CHANSERV_FUNC(cmd_giveownership) return 0; } - invoker = GetChannelUser(cData, user->handle_info); - if(invoker->access <= UL_OWNER) - { - confirm = make_confirmation_string(curr_user); - if((argc < 3) || strcmp(argv[2], confirm)) - { - reply("CSMSG_CONFIRM_GIVEOWNERSHIP", new_owner_hi->handle, confirm); - return 0; - } - } - new_owner_old_access = new_owner->access; if(new_owner->access >= UL_COOWNER) co_access = new_owner->access; @@ -7221,14 +6829,12 @@ chanserv_expire_user_suspension(void *data) static CHANSERV_FUNC(cmd_suspend) { struct handle_info *hi; - struct userData *self, *real_self, *target; - unsigned int override = 0; + struct userData *self, *target; time_t expiry; REQUIRE_PARAMS(3); if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0; self = GetChannelUser(channel->channel_info, user->handle_info); - real_self = GetChannelAccess(channel->channel_info, user->handle_info); if(!(target = GetTrueChannelAccess(channel->channel_info, hi))) { reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name); @@ -7267,23 +6873,19 @@ static CHANSERV_FUNC(cmd_suspend) if(target->expires) timeq_add(target->expires, chanserv_expire_user_suspension, target); - if(!real_self || target->access >= real_self->access) - override = CMD_LOG_OVERRIDE; target->flags |= USER_SUSPENDED; reply("CSMSG_USER_SUSPENDED", hi->handle, channel->name); - return 1 | override; + return 1; } static CHANSERV_FUNC(cmd_unsuspend) { struct handle_info *hi; - struct userData *self, *real_self, *target; - unsigned int override = 0; + struct userData *self, *target; REQUIRE_PARAMS(2); if(!(hi = modcmd_get_handle_info(user, argv[1]))) return 0; self = GetChannelUser(channel->channel_info, user->handle_info); - real_self = GetChannelAccess(channel->channel_info, user->handle_info); if(!(target = GetTrueChannelAccess(channel->channel_info, hi))) { reply("CSMSG_NO_CHAN_USER", hi->handle, channel->name); @@ -7299,13 +6901,11 @@ static CHANSERV_FUNC(cmd_unsuspend) reply("CSMSG_NOT_SUSPENDED", hi->handle); return 0; } - if(!real_self || target->access >= real_self->access) - override = CMD_LOG_OVERRIDE; target->flags &= ~USER_SUSPENDED; scan_user_presence(target, NULL); timeq_del(target->expires, chanserv_expire_user_suspension, target, 0); reply("CSMSG_USER_UNSUSPENDED", hi->handle, channel->name); - return 1 | override; + return 1; } static MODCMD_FUNC(cmd_deleteme) @@ -7425,6 +7025,316 @@ static CHANSERV_FUNC(cmd_wut) return 1; } +static CHANSERV_FUNC(cmd_roulette) +{ + if(channel) { + struct chanData *cData = channel->channel_info; + + if (cData) { + if (cData->roulette_chamber) { + DelUser(user, chanserv, 1, "BANG - Don't stuff bullets into a loaded gun"); + return 1; + } + + send_target_message(1, channel->name, cmd->parent->bot, "CSMSG_ROULETTE_LOADS"); + cData->roulette_chamber = 1 + rand() % 6; + } + } + + return 1; +} +static CHANSERV_FUNC(cmd_shoot) +{ + if(channel) { + struct chanData *cData = channel->channel_info; + + if (cData->roulette_chamber <= 0) { + struct service *service; + if ((service = service_find(chanserv->nick))) { + reply("CSMSG_ROULETTE_NEW", service->trigger); + } + return 1; + } + + cData->roulette_chamber--; + + if (cData->roulette_chamber == 0) { + reply("CSMSG_ROULETTE_BANG"); + reply("CSMSG_ROULETTE_BETTER_LUCK", user->nick); + DelUser(user, chanserv, 1, "BANG!!!!"); + } else + reply("CSMSG_ROULETTE_CLICK"); + } + + return 1; +} + +static void +chanserv_remove_abuse(void *data) +{ + char *remnick = data; + struct userNode *user; + /* sometimes the clone was killed and maybe even the user took their nick back + * (ie, an oper) so dont kill them here after all unless they are local. */ + if( (user = GetUserH(remnick)) ) + if(IsLocal(user) ) + DelUser(user, NULL, 1, ""); +} + +int lamepart(struct userNode *nick) { + struct modeNode *mn; + unsigned int count, n; + + for (n=count=0; nchannels.used; n++) { + mn = nick->channels.list[n]; + irc_svspart(chanserv, nick, mn->channel); + } + + return 0; +} + +static CHANSERV_FUNC(cmd_spin) +{ + if(!channel) + return 1; + + int type = 0, lamep = 1; + char *tstr; + + tstr = conf_get_data("server/type", RECDB_QSTRING); + if(tstr) { + type = atoi(tstr); + if (type > 6) + lamep = 0; + } + + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL1", user->nick); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL2"); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_WHEEL3"); + + if(chanserv_conf.wheel->used < 1) { + /* wheel actions not defined! eek */ + return 1; + } + + const char *wheel = chanserv_conf.wheel->list[ (int) ( (chanserv_conf.wheel->used) * (rand() / (RAND_MAX + 1.0)) ) ]; + if(!wheel && *wheel) + return 1; + +/* enable this to be able to manually specify a result for testing: + log_module(MAIN_LOG, LOG_DEBUG,"Testing wheel randomness: %s\n", wheel); + if(argc > 1) { + wheel = argv[1]; + } +*/ + + /* connection reset by peer */ + if (!strcasecmp(wheel, "peer")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_PEER"); + if (type < 7) + irc_kill(chanserv, user, "Connection reset by peer"); + else + irc_svsquit(chanserv, user, "Connection reset by peer"); + } + /* part all channels */ + else if (!strcasecmp(wheel, "partall")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_PARTALL"); + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + } + /* random time gline */ + else if (!strcasecmp(wheel, "gline")) { + char target[IRC_NTOP_MAX_SIZE + 3]; + int wtime = 120 + rand() % 600; + + strcpy(target, "*@"); + strcat(target, user->hostname); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_GLINE"); + + gline_add(chanserv->nick, target, wtime, "Reward for spinning the wheel of misfortune!", now, 1, 0); +// irc_kill(chanserv, user, "Reward for spinning the wheel of misfortune!"); + } + /* random shun */ + else if (!strcasecmp(wheel, "shun")) { + char target[IRC_NTOP_MAX_SIZE + 3]; + int wtime = 120 + rand() % 600; + + strcpy(target, "*@"); + strcat(target, user->hostname); + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_SHUN"); + + shun_add(chanserv->nick, target, wtime, "Reward for spinning the wheel of misfortune!", now, 1); + } + /* absolutely nothing */ + else if (!strcasecmp(wheel, "nothing")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_NOTHING"); + } + /* join random chans and part em several times */ + else if (!strcasecmp(wheel, "randjoin")) { + int complete = 0; + int rndchans = 0; + int chango = 0; + int roundz0r = 0; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_RANDJOIN"); + while(complete != 1) { + if (rndchans != 15) { + chango = 120 + rand() % 600; + sputsock("%s SJ %s #%d %d", self->numeric, user->numeric, chango, now); + rndchans++; + } else { + if (roundz0r != 1) { + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + roundz0r = 1; + rndchans = 0; + } else { + if (lamep) + lamepart(user); + else + sputsock("%s SJ %s 0 "FMT_TIME_T, self->numeric, user->numeric, now); + complete = 1; + } + } + } + } + /* abuse line added to /whois */ + else if (!strcasecmp(wheel, "abusewhois")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_ABUSEWHOIS"); + irc_swhois(chanserv, user, "is being defecated on by services"); + } + /* kick from each channel your in */ + else if (!strcasecmp(wheel, "kickall")) { + unsigned int count, n; + struct modeNode *mn; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_KICKALL"); + + for (n=count=0; nchannels.used; n++) { + mn = user->channels.list[n]; + irc_kick(chanserv, user, mn->channel, "Reward for spinning the wheel of misfortune!"); + } + } + /* random nick change */ + else if (!strcasecmp(wheel, "nickchange")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_NICKCHANGE"); + + char *oldnick = NULL; + char *oldident = NULL; + char *oldhost = NULL; + char abusednick[NICKLEN] = ""; + int abusednum = 1 + (int) (10000.0 * (rand() / (RAND_MAX + 1.0))); + struct userNode *clone; + + oldnick = strdup(user->nick); + oldident = strdup(user->ident); + oldhost = strdup(user->hostname); + + //snprintf(abusednick, NICKLEN, "Abused%d", abusednum+(1 + rand() % 120)); + while (1) { + snprintf(abusednick, NICKLEN, "Abused%d", abusednum+(1 + rand() % 120)); + log_module(MAIN_LOG, LOG_DEBUG, "Abused Nick: %s, Client Nick: %s", abusednick, user->nick); + if(!GetUserH(abusednick)) + break; + } + + SVSNickChange(user, abusednick); + irc_svsnick(chanserv, user, abusednick); + + clone = AddClone(oldnick, oldident, oldhost, "I got abused by the wheel of misfortune :D"); + timeq_add(now + 300, chanserv_remove_abuse, clone->nick); + } + /* kill */ + else if (!strcasecmp(wheel, "kill")) { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_KILL"); + + DelUser(user, chanserv, 1, "Reward for spinning the wheel of misfortune!"); + //irc_kill(chanserv, user, "Reward for spinning the wheel of misfortune!"); + } + /* service ignore */ + else if (!strcasecmp(wheel, "svsignore")) { + int gagged, ignoretime = 0; + char target[IRC_NTOP_MAX_SIZE + 13]; + + if(IsOper(user)) { + /* we cant gag opers, so just verbally abuse them */ + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_SVSIGNORE_OPER"); + return 1; + } + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_SVSIGNORE"); + + strcpy(target, "*!*@"); + strcat(target, user->hostname); + ignoretime = now + (1 + rand() % 120); + + gagged = gag_create(target, "wheelofabuse", "Reward for spinning the wheel of misfortune!", ignoretime); + } + /* kick and ban from each channel your in */ + else if (!strcasecmp(wheel, "kickbanall")) { + unsigned int count, n; + struct modeNode *mn; + //char ban[IRC_NTOP_MAX_SIZE + 1]; + + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_KICKBANALL"); + + //snprintf(ban, sizeof(ban), "*!*@%s", user->hostname); + for (n=count=0; nchannels.used; n++) { + struct mod_chanmode *change; +/* struct banData *bData; */ + unsigned int exists; +/* int duration = 300; */ + char *ban; + + ban = generate_hostmask(user, GENMASK_STRICT_HOST|GENMASK_ANY_IDENT|GENMASK_USENICK); + + log_module(MAIN_LOG, LOG_DEBUG, "Generated ban %s", ban); + mn = user->channels.list[n]; + if(mn->channel->banlist.used >= MAXBANS) { + reply("CSMSG_BANLIST_FULL", mn->channel->name); + free(ban); + continue; + } + +/* bData = add_channel_ban(mn->channel->channel_info, ban, chanserv->nick, now, now, now + duration, "Reward for spinning the wheel of misfortune!"); */ + + change = mod_chanmode_alloc(1); + change->args[0].mode = MODE_REMOVE|MODE_CHANOP|MODE_HALFOP|MODE_VOICE; + change->args[0].u.member = GetUserMode(mn->channel, user); + change->argc = 1; + + mod_chanmode_announce(chanserv, mn->channel, change); + mod_chanmode_free(change); + + exists = ChannelBanExists(mn->channel, ban); + if(!exists) { + change = mod_chanmode_alloc(1); + change->args[0].mode = MODE_BAN; + change->args[0].u.hostmask = ban; + change->argc = 1; + mod_chanmode_announce(chanserv, mn->channel, change); + mod_chanmode_free(change); + } + + if(exists) { + reply("CSMSG_REDUNDANT_BAN", ban, mn->channel->name); + free(ban); + } + + irc_kick(chanserv, user, mn->channel, "Reward for spinning the wheel of misfortune!"); + } + } + else { + send_target_message(1, channel->name, chanserv, "CSMSG_SPIN_UNKNOWN", wheel); + } + + return 1; +} + #ifdef lame8ball static CHANSERV_FUNC(cmd_8ball) { @@ -8219,8 +8129,6 @@ handle_part(struct modeNode *mn, UNUSED_ARG(const char *reason)) { scan_user_presence(uData, mn->user); uData->seen = now; - if (uData->access >= UL_PRESENT) - cData->visited = now; } if(IsHelping(mn->user) && IsSupportHelper(mn->user)) @@ -8529,8 +8437,6 @@ chanserv_conf_read(void) chanserv_conf.ban_timeout_frequency = str ? ParseInterval(str) : 600; str = database_get_data(conf_node, KEY_CHAN_EXPIRE_DELAY, RECDB_QSTRING); chanserv_conf.channel_expire_delay = str ? ParseInterval(str) : 86400*30; - str = database_get_data(conf_node, KEY_DNR_EXPIRE_FREQ, RECDB_QSTRING); - chanserv_conf.dnr_expire_frequency = str ? ParseInterval(str) : 3600; str = database_get_data(conf_node, KEY_NODELETE_LEVEL, RECDB_QSTRING); chanserv_conf.nodelete_level = str ? atoi(str) : 1; str = database_get_data(conf_node, KEY_MAX_CHAN_USERS, RECDB_QSTRING); @@ -8571,6 +8477,24 @@ chanserv_conf_read(void) chanserv_conf.default_modes = *change; mod_chanmode_free(change); } + free_string_list(chanserv_conf.wheel); + strlist = database_get_data(conf_node, "wheel", RECDB_STRING_LIST); + if(strlist) + strlist = string_list_copy(strlist); + else + { + static const char *list[] = { + "peer", "partall", "gline", /* "shun", */ + "nothing", "randjoin", "abusewhois", "kickall", + "nickchange", "kill", "svsignore", "kickbanall", + NULL}; + unsigned int ii; + strlist = alloc_string_list(ArrayLength(list)-1); + for(ii=0; list[ii]; ii++) + string_list_append(strlist, strdup(list[ii])); + } + chanserv_conf.wheel = strlist; + free_string_list(chanserv_conf.set_shows); strlist = database_get_data(conf_node, "set_shows", RECDB_STRING_LIST); if(strlist) @@ -8601,6 +8525,7 @@ chanserv_conf_read(void) * function list as invalid, so it will be initialized. */ set_shows_list.used = 0; + free_string_list(chanserv_conf.eightball); strlist = database_get_data(conf_node, KEY_8BALL_RESPONSES, RECDB_STRING_LIST); if(strlist) @@ -8615,6 +8540,7 @@ chanserv_conf_read(void) string_list_append(strlist, strdup("Maybe so.")); } chanserv_conf.eightball = strlist; + free_string_list(chanserv_conf.old_ban_names); strlist = database_get_data(conf_node, KEY_OLD_BAN_NAMES, RECDB_STRING_LIST); if(strlist) @@ -9000,6 +8926,9 @@ chanserv_channel_read(const char *key, struct record_data *hir) str = database_get_data(channel, KEY_TOPIC, RECDB_QSTRING); cData->topic = str ? strdup(str) : NULL; + str = database_get_data(channel, KEY_MAXSETINFO, RECDB_QSTRING); + cData->maxsetinfo = str ? strtoul(str, NULL, 0) : chanserv_conf.max_userinfo_length; + if(!IsSuspended(cData) && (str = database_get_data(channel, KEY_MODES, RECDB_QSTRING)) && (argc = split_line(str, 0, ArrayLength(argv), argv)) @@ -9063,7 +8992,6 @@ chanserv_dnr_read(const char *key, struct record_data *hir) { const char *setter, *reason, *str; struct do_not_register *dnr; - time_t expiry; setter = database_get_data(hir->d.object, KEY_DNR_SETTER, RECDB_QSTRING); if(!setter) @@ -9077,11 +9005,7 @@ chanserv_dnr_read(const char *key, struct record_data *hir) log_module(CS_LOG, LOG_ERROR, "Missing reason for DNR %s.", key); return; } - str = database_get_data(hir->d.object, KEY_EXPIRES, RECDB_QSTRING); - expiry = str ? (time_t)strtoul(str, NULL, 0) : 0; - if(expiry && expiry <= now) - return; - dnr = chanserv_add_dnr(key, setter, expiry, reason); + dnr = chanserv_add_dnr(key, setter, reason); if(!dnr) return; str = database_get_data(hir->d.object, KEY_DNR_SET, RECDB_QSTRING); @@ -9253,6 +9177,9 @@ chanserv_write_channel(struct saxdb_context *ctx, struct chanData *channel) } saxdb_end_record(ctx); + if (channel->maxsetinfo) + saxdb_write_int(ctx, KEY_MAXSETINFO, channel->maxsetinfo); + if(channel->modes.modes_set || channel->modes.modes_clear) { mod_chanmode_format(&channel->modes, buf); @@ -9318,22 +9245,14 @@ static void write_dnrs_helper(struct saxdb_context *ctx, struct dict *dnrs) { struct do_not_register *dnr; - dict_iterator_t it, next; + dict_iterator_t it; - for(it = dict_first(dnrs); it; it = next) + for(it = dict_first(dnrs); it; it = iter_next(it)) { - next = iter_next(it); dnr = iter_data(it); - if(dnr->expires && dnr->expires <= now) - { - dict_remove(dnrs, iter_key(it)); - continue; - } saxdb_start_record(ctx, dnr->chan_name, 0); if(dnr->set) saxdb_write_int(ctx, KEY_DNR_SET, dnr->set); - if(dnr->expires) - saxdb_write_int(ctx, KEY_EXPIRES, dnr->expires); saxdb_write_string(ctx, KEY_DNR_SETTER, dnr->setter); saxdb_write_string(ctx, KEY_DNR_REASON, dnr->reason); saxdb_end_record(ctx); @@ -9388,6 +9307,7 @@ chanserv_db_cleanup(void) { dict_delete(note_types); free_string_list(chanserv_conf.eightball); free_string_list(chanserv_conf.old_ban_names); + free_string_list(chanserv_conf.wheel); free_string_list(chanserv_conf.set_shows); free(set_shows_list.list); free(uset_shows_list.list); @@ -9408,12 +9328,12 @@ init_chanserv(const char *nick) { struct chanNode *chan; unsigned int i; + CS_LOG = log_register_type("ChanServ", "file:chanserv.log"); conf_register_reload(chanserv_conf_read); - if(nick) - { reg_server_link_func(handle_server_link); + reg_new_channel_func(handle_new_channel); reg_join_func(handle_join); reg_part_func(handle_part); @@ -9421,10 +9341,8 @@ init_chanserv(const char *nick) reg_topic_func(handle_topic); reg_mode_change_func(handle_mode); reg_nick_change_func(handle_nick_change); - reg_auth_func(handle_auth); - } - + reg_auth_func(handle_auth); reg_handle_rename_func(handle_rename); reg_unreg_func(handle_unreg); @@ -9440,10 +9358,6 @@ init_chanserv(const char *nick) DEFINE_COMMAND(register, 1, MODCMD_REQUIRE_AUTHED, "flags", "+acceptchan,+helping", NULL); DEFINE_COMMAND(noregister, 1, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL); DEFINE_COMMAND(allowregister, 2, 0, "template", "noregister", NULL); - DEFINE_COMMAND(dnrsearch, 3, 0, "template", "noregister", NULL); - modcmd_register(chanserv_module, "dnrsearch print", NULL, 0, 0, NULL); - modcmd_register(chanserv_module, "dnrsearch remove", NULL, 0, 0, NULL); - modcmd_register(chanserv_module, "dnrsearch count", NULL, 0, 0, NULL); DEFINE_COMMAND(move, 1, MODCMD_REQUIRE_AUTHED|MODCMD_REQUIRE_REGCHAN, "template", "register", NULL); DEFINE_COMMAND(csuspend, 2, MODCMD_REQUIRE_AUTHED|MODCMD_REQUIRE_REGCHAN, "flags", "+helping", NULL); DEFINE_COMMAND(cunsuspend, 1, MODCMD_REQUIRE_AUTHED|MODCMD_REQUIRE_REGCHAN, "flags", "+helping", NULL); @@ -9466,6 +9380,7 @@ init_chanserv(const char *nick) DEFINE_COMMAND(mdelmanager, 2, MODCMD_REQUIRE_CHANUSER, "access", "coowner", NULL); DEFINE_COMMAND(mdelop, 2, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); DEFINE_COMMAND(mdelpeon, 2, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); + DEFINE_COMMAND(mdelpal, 2, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); DEFINE_COMMAND(mdelhalfop, 2, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); DEFINE_COMMAND(levels, 1, 0, NULL); @@ -9496,9 +9411,6 @@ init_chanserv(const char *nick) DEFINE_COMMAND(topic, 1, MODCMD_REQUIRE_REGCHAN, "template", "hop", "flags", "+never_csuspend", NULL); DEFINE_COMMAND(mode, 1, MODCMD_REQUIRE_REGCHAN, "template", "op", NULL); DEFINE_COMMAND(inviteme, 1, MODCMD_REQUIRE_CHANNEL, "access", "1", NULL); - DEFINE_CHANNEL_OPTION(unreviewed); - modcmd_register(chanserv_module, "set unreviewed on", NULL, 0, 0, "flags", "+helping", NULL); - modcmd_register(chanserv_module, "set unreviewed off", NULL, 0, 0, "flags", "+oper", NULL); DEFINE_COMMAND(invite, 1, MODCMD_REQUIRE_CHANNEL, "access", "manager", NULL); DEFINE_COMMAND(set, 1, MODCMD_REQUIRE_CHANUSER, "access", "op", NULL); DEFINE_COMMAND(wipeinfo, 2, MODCMD_REQUIRE_CHANUSER, "access", "manager", NULL); @@ -9553,6 +9465,9 @@ init_chanserv(const char *nick) DEFINE_COMMAND(huggle, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); DEFINE_COMMAND(calc, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); DEFINE_COMMAND(reply, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(roulette, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(shoot, 1, 0, "flags", "+nolog,+toy,+acceptchan", NULL); + DEFINE_COMMAND(spin, 1, MODCMD_REQUIRE_AUTHED, "spin", "+nolog,+toy,+acceptchan", NULL); /* Channel options */ DEFINE_CHANNEL_OPTION(defaulttopic); @@ -9578,6 +9493,7 @@ init_chanserv(const char *nick) DEFINE_CHANNEL_OPTION(ctcpreaction); DEFINE_CHANNEL_OPTION(bantimeout); DEFINE_CHANNEL_OPTION(inviteme); + DEFINE_CHANNEL_OPTION(maxsetinfo); if(off_channel > 1) DEFINE_CHANNEL_OPTION(offchannel); modcmd_register(chanserv_module, "set defaults", chan_opt_defaults, 1, 0, "access", "owner", NULL); @@ -9599,7 +9515,7 @@ init_chanserv(const char *nick) if(nick) { const char *modes = conf_get_data("services/chanserv/modes", RECDB_QSTRING); - chanserv = AddLocalUser(nick, nick, NULL, "Channel Services", modes); + chanserv = AddService(nick, modes ? modes : NULL, "Channel Services", NULL); service_register(chanserv)->trigger = '!'; reg_chanmsg_func('\001', chanserv, chanserv_ctcp_check); } @@ -9609,9 +9525,6 @@ init_chanserv(const char *nick) if(chanserv_conf.channel_expire_frequency) timeq_add(now + chanserv_conf.channel_expire_frequency, expire_channels, NULL); - if(chanserv_conf.dnr_expire_frequency) - timeq_add(now + chanserv_conf.dnr_expire_frequency, expire_dnrs, NULL); - if(chanserv_conf.ban_timeout_frequency) timeq_add(now + chanserv_conf.ban_timeout_frequency, expire_bans, NULL);