diff options
227 files changed, 8593 insertions, 12137 deletions
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 461ea287a..b0d99e11e 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,6 +1,6 @@ # Only install example.chk and example.conf from this directory # NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file) -set(DATA example.chk example.conf mysql/tables.sql) +set(DATA example.chk commands.example.conf example.conf modules.example.conf mysql/tables.sql) install(FILES ${DATA} DESTINATION data ) diff --git a/data/commands.example.conf b/data/commands.example.conf new file mode 100644 index 000000000..a3481bc11 --- /dev/null +++ b/data/commands.example.conf @@ -0,0 +1,336 @@ + +/* + * [RECOMMENDED] Core modules and command configuration + * + * In Anope modules can provide (multiple) commands, each of which has a unique command name. Once these modules + * are loaded you can then configure the commands to be added to any client you like with any name you like. + * + * Sane defaults are below. + */ + +module { name = "help" } +command { service = "BotServ"; name = "HELP"; command = "generic/help"; } +command { service = "ChanServ"; name = "HELP"; command = "generic/help"; } +command { service = "Global"; name = "HELP"; command = "generic/help"; } +command { service = "HostServ"; name = "HELP"; command = "generic/help"; } +command { service = "MemoServ"; name = "HELP"; command = "generic/help"; } +command { service = "NickServ"; name = "HELP"; command = "generic/help"; } +command { service = "OperServ"; name = "HELP"; command = "generic/help"; } + +module { name = "bs_assign" } +command { service = "BotServ"; name = "ASSIGN"; command = "botserv/assign"; } +command { service = "BotServ"; name = "UNASSIGN"; command = "botserv/unassign"; } +module { name = "bs_badwords" } +command { service = "BotServ"; name = "BADWORDS"; command = "botserv/badwords"; } +module { name = "bs_bot" } +command { service = "BotServ"; name = "BOT"; command = "botserv/bot"; } +module { name = "bs_botlist" } +command { service = "BotServ"; name = "BOTLIST"; command = "botserv/botlist"; } +module { name = "bs_control" } +command { service = "BotServ"; name = "ACT"; command = "botserv/act"; } +command { service = "BotServ"; name = "SAY"; command = "botserv/say"; } +module { name = "bs_info" } +command { service = "BotServ"; name = "INFO"; command = "botserv/info"; } +module { name = "bs_kick" } +command { service = "BotServ"; name = "KICK"; command = "botserv/kick"; } +module { name = "bs_set" } +command { service = "BotServ"; name = "SET"; command = "botserv/set"; } + +module { name = "cs_access" } +command { service = "ChanServ"; name = "ACCESS"; command = "chanserv/access"; } +command { service = "ChanServ"; name = "LEVELS"; command = "chanserv/levels"; } +module { name = "cs_akick" } +command { service = "ChanServ"; name = "AKICK"; command = "chanserv/akick"; } +module { name = "cs_ban" } +command { service = "ChanServ"; name = "BAN"; command = "chanserv/ban"; } +command { service = "ChanServ"; name = "KB"; command = "chanserv/ban"; } +module { name = "cs_clearusers" } +command { service = "ChanServ"; name = "CLEARUSERS"; command = "chanserv/clearusers"; } +module { name = "cs_clone" } +command { service = "ChanServ"; name = "CLONE"; command = "chanserv/clone"; } +module { name = "cs_drop" } +command { service = "ChanServ"; name = "DROP"; command = "chanserv/drop"; } +module { name = "cs_getkey" } +command { service = "ChanServ"; name = "GETKEY"; command = "chanserv/getkey"; } +module { name = "cs_info" } +command { service = "ChanServ"; name = "INFO"; command = "chanserv/info"; } +module { name = "cs_invite" } +command { service = "ChanServ"; name = "INVITE"; command = "chanserv/invite"; } +module { name = "cs_kick" } +command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; } +command { service = "ChanServ"; name = "K"; command = "chanserv/kick"; } +module { name = "cs_list" } +command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; } +module { name = "cs_mode" } +command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; } +module { name = "cs_modes" } +command { service = "ChanServ"; name = "OP"; command = "chanserv/op"; } +command { service = "ChanServ"; name = "DEOP"; command = "chanserv/deop"; } +command { service = "ChanServ"; name = "HALFOP"; command = "chanserv/halfop"; } +command { service = "ChanServ"; name = "DEHALFOP"; command = "chanserv/dehalfop"; } +command { service = "ChanServ"; name = "VOICE"; command = "chanserv/voice"; } +command { service = "ChanServ"; name = "DEVOICE"; command = "chanserv/devoice"; } +command { service = "ChanServ"; name = "PROTECT"; command = "chanserv/protect"; } +command { service = "ChanServ"; name = "DEPROTECT"; command = "chanserv/deprotect"; } +command { service = "ChanServ"; name = "OWNER"; command = "chanserv/owner"; } +command { service = "ChanServ"; name = "DEOWNER"; command = "chanserv/deowner"; } +module { name = "cs_register" } +command { service = "ChanServ"; name = "REGISTER"; command = "chanserv/register"; } +module { name = "cs_set" } +command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; } +module { name = "cs_saset" } +command { service = "ChanServ"; name = "SASET"; command = "chanserv/saset"; } +module { name = "cs_set_bantype" } +command { service = "ChanServ"; name = "SET BANTYPE"; command = "chanserv/set/bantype"; } +command { service = "ChanServ"; name = "SASET BANTYPE"; command = "chanserv/saset/bantype"; } +module { name = "cs_set_description" } +command { service = "ChanServ"; name = "SET DESCRIPTION"; command = "chanserv/set/description"; } +command { service = "ChanServ"; name = "SASET DESCRIPTION"; command = "chanserv/saset/description"; } +module { name = "cs_set_founder" } +command { service = "ChanServ"; name = "SET FOUNDER"; command = "chanserv/set/founder"; } +command { service = "ChanServ"; name = "SASET FOUNDER"; command = "chanserv/saset/founder"; } +module { name = "cs_set_keeptopic" } +command { service = "ChanServ"; name = "SET KEEPTOPIC"; command = "chanserv/set/keeptopic"; } +command { service = "ChanServ"; name = "SASET KEEPTOPIC"; command = "chanserv/saset/keeptopic"; } +module { name = "cs_set_opnotice" } +command { service = "ChanServ"; name = "SET OPNOTICE"; command = "chanserv/set/opnotice"; } +command { service = "ChanServ"; name = "SASET OPNOTICE"; command = "chanserv/saset/opnotice"; } +module { name = "cs_set_peace" } +command { service = "ChanServ"; name = "SET PEACE"; command = "chanserv/set/peace"; } +command { service = "ChanServ"; name = "SASET PEACE"; command = "chanserv/saset/peace"; } +module { name = "cs_set_persist" } +command { service = "ChanServ"; name = "SET PERSIST"; command = "chanserv/set/persist"; } +command { service = "ChanServ"; name = "SASET PERSIST"; command = "chanserv/saset/persist"; } +module { name = "cs_set_private" } +command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; } +command { service = "ChanServ"; name = "SASET PRIVATE"; command = "chanserv/saset/private"; } +module { name = "cs_set_restricted" } +command { service = "ChanServ"; name = "SET RESITRCTED"; command = "chanserv/set/restricted"; } +command { service = "ChanServ"; name = "SASET RESITRCTED"; command = "chanserv/saset/restricted"; } +module { name = "cs_set_secure" } +command { service = "ChanServ"; name = "SET SECURE"; command = "chanserv/set/secure"; } +command { service = "ChanServ"; name = "SASET SECURE"; command = "chanserv/saset/secure"; } +module { name = "cs_set_securefounder" } +command { service = "ChanServ"; name = "SET SECUREFOUNDER"; command = "chanserv/set/securefounder"; } +command { service = "ChanServ"; name = "SASET SECUREFOUNDER"; command = "chanserv/saset/securefounder"; } +module { name = "cs_set_secureops" } +command { service = "ChanServ"; name = "SET SECUREOPS"; command = "chanserv/set/secureops"; } +command { service = "ChanServ"; name = "SASET SECUREOPS"; command = "chanserv/saset/secureops"; } +module { name = "cs_set_signkick" } +command { service = "ChanServ"; name = "SET SIGNKICK"; command = "chanserv/set/signkick"; } +command { service = "ChanServ"; name = "SASET SIGNKICK"; command = "chanserv/saset/signkick"; } +module { name = "cs_set_successor" } +command { service = "ChanServ"; name = "SET SUCCESSOR"; command = "chanserv/set/successor"; } +command { service = "ChanServ"; name = "SASET SUCCESSOR"; command = "chanserv/saset/successor"; } +module { name = "cs_set_topiclock" } +command { service = "ChanServ"; name = "SET TOPICLOCK"; command = "chanserv/set/topiclock"; } +command { service = "ChanServ"; name = "SASET TOPICLOCK"; command = "chanserv/saset/topiclock"; } +module { name = "cs_set_xop" } +command { service = "ChanServ"; name = "SET XOP"; command = "chanserv/set/xop"; } +command { service = "ChanServ"; name = "SASET XOP"; command = "chanserv/saset/xop"; } +module { name = "cs_saset_noexpire" } +command { service = "ChanServ"; name = "SET NOEXPIRE"; command = "chanserv/set/noexpire"; } +module { name = "cs_status" } +command { service = "ChanServ"; name = "STATUS"; command = "chanserv/status"; } +module { name = "cs_suspend" } +command { service = "ChanServ"; name = "SUSPEND"; command = "chanserv/suspend"; } +command { service = "ChanServ"; name = "UNSUSPEND"; command = "chanserv/unsuspend"; } +module { name = "cs_topic" } +command { service = "ChanServ"; name = "TOPIC"; command = "chanserv/topic"; } +module { name = "cs_unban" } +command { service = "ChanServ"; name = "UNBAN"; command = "chanserv/unban"; } +module { name = "cs_xop" } +command { service = "ChanServ"; name = "QOP"; command = "chanserv/qop"; } +command { service = "ChanServ"; name = "SOP"; command = "chanserv/sop"; } +command { service = "ChanServ"; name = "AOP"; command = "chanserv/aop"; } +command { service = "ChanServ"; name = "HOP"; command = "chanserv/hop"; } +command { service = "ChanServ"; name = "VOP"; command = "chanserv/vop"; } + +module { name = "gl_global" } +command { service = "Global"; name = "GLOBAL"; command = "global/global"; } + +module { name = "hs_del" } +command { service = "HostServ"; name = "DEL"; command = "hostserv/del"; } +command { service = "HostServ"; name = "DELALL"; command = "hostserv/delall"; } +module { name = "hs_group" } +command { service = "HostServ"; name = "GROUP"; command = "hostserv/group"; } +module { name = "hs_list" } +command { service = "HostServ"; name = "LIST"; command = "hostserv/list"; } +module { name = "hs_off" } +command { service = "HostServ"; name = "OFF"; command = "hostserv/off"; } +module { name = "hs_on" } +command { service = "HostServ"; name = "ON"; command = "hostserv/on"; } +module { name = "hs_set" } +command { service = "HostServ"; name = "SET"; command = "hostserv/set"; } +command { service = "HostServ"; name = "SETALL"; command = "hostserv/setall"; } + +module { name = "ms_cancel" } +command { service = "MemoServ"; name = "CANCEL"; command = "memoserv/cancel"; } +module { name = "ms_check" } +command { service = "MemoServ"; name = "CHECK"; command = "memoserv/check"; } +module { name = "ms_del" } +command { service = "MemoServ"; name = "DEL"; command = "memoserv/del"; } +module { name = "ms_ignore" } +command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; } +module { name = "ms_info" } +command { service = "MemoServ"; name = "INFO"; command = "memoserv/info"; } +module { name = "ms_list" } +command { service = "MemoServ"; name = "LIST"; command = "memoserv/list"; } +module { name = "ms_read" } +command { service = "MemoServ"; name = "READ"; command = "memoserv/read"; } +module { name = "ms_rsend" } +command { service = "MemoServ"; name = "RSEND"; command = "memoserv/rsend"; } +module { name = "ms_send" } +command { service = "MemoServ"; name = "SEND"; command = "memoserv/send"; } +module { name = "ms_sendall" } +command { service = "MemoServ"; name = "SENDALL"; command = "memoserv/sendall"; } +module { name = "ms_set" } +command { service = "MemoServ"; name = "SET"; command = "memoserv/set"; } +module { name = "ms_staff" } +command { service = "MemoServ"; name = "STAFF"; command = "memoserv/staff"; } + +module { name = "ns_access" } +command { service = "NickServ"; name = "ACCESS"; command = "nickserv/access"; } +module { name = "ns_ajoin" } +command { service = "NickServ"; name = "AJOIN"; command = "nickserv/ajoin"; } +module { name = "ns_alist" } +command { service = "NickServ"; name = "ALIST"; command = "nickserv/alist"; } +module { name = "ns_cert" } +command { service = "NickServ"; name = "CERT"; command = "nickserv/cert"; } +module { name = "ns_drop" } +command { service = "NickServ"; name = "DROP"; command = "nickserv/drop"; } +module { name = "ns_getemail" } +command { service = "NickServ"; name = "GETEMAIL"; command = "nickserv/getemail"; } +module { name = "ns_getpass" } +command { service = "NickServ"; name = "GETPASS"; command = "nickserv/getpass"; } +module { name = "ns_ghost" } +command { service = "NickServ"; name = "GHOST"; command = "nickserv/ghost"; } +module { name = "ns_group" } +command { service = "NickServ"; name = "GLIST"; command = "nickserv/glist"; } +command { service = "NickServ"; name = "GROUP"; command = "nickserv/group"; } +command { service = "NickServ"; name = "UNGROUP"; command = "nickserv/ungroup"; } +module { name = "ns_identify" } +command { service = "NickServ"; name = "IDENTIFY"; command = "nickserv/identify"; } +module { name = "ns_info" } +command { service = "NickServ"; name = "INFO"; command = "nickserv/info"; } +module { name = "ns_list" } +command { service = "NickServ"; name = "LIST"; command = "nickserv/list"; } +module { name = "ns_logout" } +command { service = "NickServ"; name = "LOGOUT"; command = "nickserv/logout"; } +module { name = "ns_recover" } +command { service = "NickServ"; name = "RECOVER"; command = "nickserv/recover"; } +module { name = "ns_register" } +command { service = "NickServ"; name = "CONFIRM"; command = "nickserv/confirm"; } +command { service = "NickServ"; name = "REGISTER"; command = "nickserv/register"; } +command { service = "NickServ"; name = "RESEND"; command = "nickserv/resend"; } +module { name = "ns_release" } +command { service = "NickServ"; name = "RELEASE"; command = "nickserv/release"; } +module { name = "ns_resetpass" } +command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; } +module { name = "ns_saset" } +command { service = "NickServ"; name = "SASET"; command = "nickserv/saset"; } +command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/saset/display"; } +command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; } +module { name = "ns_set" } +command { service = "NickServ"; name = "SET"; command = "nickserv/set"; } +command { service = "NickServ"; name = "SET DISPLAY"; command = "nickserv/set/display"; } +command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; } +module { name = "ns_set_autoop" } +command { service = "NickServ"; name = "SET AUTOOP"; command = "nickserv/set/autoop"; } +command { service = "NickServ"; name = "SASET AUTOOP"; command = "nickserv/saset/autoop"; } +module { name = "ns_set_email" } +command { service = "NickServ"; name = "SET EMAIL"; command = "nickserv/set/email"; } +command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/email"; } +module { name = "ns_set_greet" } +command { service = "NickServ"; name = "SET GREET"; command = "nickserv/set/greet"; } +command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/greet"; } +module { name = "ns_set_hide" } +command { service = "NickServ"; name = "SET HIDE"; command = "nickserv/set/hide"; } +command { service = "NickServ"; name = "SASET HIDE"; command = "nickserv/saset/hide"; } +module { name = "ns_set_kill" } +command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; } +command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; } +module { name = "ns_set_language" } +command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; } +command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; } +module { name = "ns_set_message" } +command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; } +command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; } +module { name = "ns_set_private" } +command { service = "NickServ"; name = "SET PRIVATE"; command = "nickserv/set/private"; } +command { service = "NickServ"; name = "SASET PRIVATE"; command = "nickserv/set/private"; } +module { name = "ns_set_secure" } +command { service = "NickServ"; name = "SET SECURE"; command = "nickserv/set/secure"; } +command { service = "NickServ"; name = "SASET SECURE"; command = "nickserv/set/secure"; } +module { name = "ns_saset_noexpire" } +command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; } +module { name = "ns_sendpass" } +command { service = "NickServ"; name = "SENDPASS"; command = "nickserv/sendpass"; } +module { name = "ns_status" } +command { service = "NickServ"; name = "STATUS"; command = "nickserv/status"; } +module { name = "ns_suspend" } +command { service = "NickServ"; name = "SUSPEND"; command = "nickserv/suspend"; } +command { service = "NickServ"; name = "UNSUSPEND"; command = "nickserv/unsuspend"; } +module { name = "ns_update" } +command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; } + +module { name = "os_akill" } +command { service = "OperServ"; name = "AKILL"; command = "operserv/akill"; } +module { name = "os_chankill" } +command { service = "OperServ"; name = "CHANKILL"; command = "operserv/chankill"; } +module { name = "os_list" } +command { service = "OperServ"; name = "CHANLIST"; command = "operserv/chanlist"; } +command { service = "OperServ"; name = "USERLIST"; command = "operserv/userlist"; } +module { name = "os_config" } +command { service = "OperServ"; name = "CONFIG"; command = "operserv/config"; } +module { name = "os_forbid" } +command { service = "OperServ"; name = "FORBID"; command = "operserv/forbid"; } +module { name = "os_ignore" } +command { service = "OperServ"; name = "IGNORE"; command = "operserv/ignore"; } +module { name = "os_jupe" } +command { service = "OperServ"; name = "JUPE"; command = "operserv/jupe"; } +module { name = "os_kick" } +command { service = "OperServ"; name = "KICK"; command = "operserv/kick"; } +module { name = "os_login" } +command { service = "OperServ"; name = "LOGIN"; command = "operserv/login"; } +module { name = "os_mode" } +command { service = "OperServ"; name = "MODE"; command = "operserv/mode"; } +module { name = "os_modinfo" } +command { service = "OperServ"; name = "MODINFO"; command = "operserv/modinfo"; } +command { service = "OperServ"; name = "MODLIST"; command = "operserv/modlist"; } +module { name = "os_module" } +command { service = "OperServ"; name = "MODLOAD"; command = "operserv/modload"; } +command { service = "OperServ"; name = "MODRELOAD"; command = "operserv/modreload"; } +command { service = "OperServ"; name = "MODUNLOAD"; command = "operserv/modunload"; } +module { name = "os_news" } +command { service = "OperServ"; name = "LOGONNEWS"; command = "operserv/logonnews"; } +command { service = "OperServ"; name = "OPERNEWS"; command = "operserv/opernews"; } +command { service = "OperServ"; name = "RANDOMNEWS"; command = "operserv/randomnews"; } +module { name = "os_noop" } +command { service = "OperServ"; name = "NOOP"; command = "operserv/noop"; } +module { name = "os_oline" } +command { service = "OperServ"; name = "OLINE"; command = "operserv/oline"; } +module { name = "os_oper" } +command { service = "OperServ"; name = "OPER"; command = "operserv/oper"; } +module { name = "os_reload" } +command { service = "OperServ"; name = "RELOAD"; command = "operserv/reload"; } +module { name = "os_session" } +command { service = "OperServ"; name = "EXCEPTION"; command = "operserv/exception"; } +command { service = "OperServ"; name = "SESSION"; command = "operserv/session"; } +module { name = "os_set" } +command { service = "OperServ"; name = "SET"; command = "operserv/set"; } +module { name = "os_shutdown" } +command { service = "OperServ"; name = "QUIT"; command = "operserv/quit"; } +command { service = "OperServ"; name = "RESTART"; command = "operserv/restart"; } +command { service = "OperServ"; name = "SHUTDOWN"; command = "operserv/shutdown"; } +module { name = "os_stats" } +command { service = "OperServ"; name = "STATS"; command = "operserv/stats"; } +module { name = "os_svsnick" } +command { service = "OperServ"; name = "SVSNICK"; command = "operserv/svsnick"; } +module { name = "os_sxline" } +command { service = "OperServ"; name = "SNLINE"; command = "operserv/snline"; } +command { service = "OperServ"; name = "SQLINE"; command = "operserv/sqline"; } +command { service = "OperServ"; name = "SZLINE"; command = "operserv/szline"; } +module { name = "os_update" } +command { service = "OperServ"; name = "UPDATE"; command = "operserv/update"; } + diff --git a/data/example.conf b/data/example.conf index 8e5e49c92..754cfe598 100644 --- a/data/example.conf +++ b/data/example.conf @@ -157,12 +157,6 @@ serverinfo #id = "00A" /* - * These identify the ident@hostname which will be used by the Services pesudoclients. - */ - ident = "services" - hostname = "localhost.net" - - /* * The filename containing the Services process ID. The path is relative to the * services executable. If not given, defaults to "services.pid". */ @@ -469,598 +463,167 @@ options } /* - * [RECOMMENDED] Logging Configuration + * [RECOMMENDED] Service client configuration * - * This section is used for configuring what is logged and where it is logged to. - * You may have multiple log blocks if you wish. Remember to properly secure any - * channels you choose to have Anope log to! + * Defines some of the core services. Commands are later added to these services. */ -log -{ - /* - * Target(s) to log to, which may be one of the following: - * - a channel name - * - a filename - * - globops - */ - target = "services.log" - /* Log to both services.log and the channel #services */ - #target = "services.log #services" - - /* - * The source(s) to only accept log messages from. Leave commented to allow all sources. - * This can be a users name, a channel name, one of our clients (eg, OperServ), or a server name. - */ - #source = "" - - /* - * The number of days to keep logfiles, only useful if you are logging to a file. - * Set to 0 to never delete old logfiles. - * - * Note that Anope must run 24 hours a day for this feature to work correctly. - */ - logage = 7 - - /* - * Enable to have the core services clients join and stay in the log channel(s) when logging. - * Note: on some IRCds this is not optional, and is enforced on. - */ - inhabitlogchannel = yes +service +{ /* - * What types of log messages should be logged by this block. There are nine general categories: - * - * admin - Execution of admin commands (OperServ, etc). - * override - A services operator using their powers to execute a command they couldn't normally. - * commands - Execution of general commands. - * servers - Server actions, linking, squitting, etc. - * channels - Actions in channels such as joins, parts, kicks, etc. - * users - User actions such as connecting, disconnecting, changing name, etc. - * other - All other messages without a category. - * rawio - Logs raw input and output from services - * debug - Debug messages (log files can become VERY large from this). - * - * These options determine what messages from the categories should be logged. Wildcards are accepted, and - * you can also negate values with a ~. For example, "~operserv/akill operserv/*" would log all operserv - * messages except for operserv/akill. Note that processing stops at the first matching option, which - * means "* ~operserv/*" would log everything because * matches everything. - * - * Valid admin, override, and command options are: - * pesudo-serv/commandname (eg, operserv/akill, chanserv/set) - * - * Valid server options are: - * connect, quit, sync - * - * Valid channel options are: - * create, destroy, join, part, kick, leave, mode - * - * Valid user options are: - * connect, disconnect, quit, nick, ident, host, mode, maxusers - * - * Rawio and debug are simple yes/no answers, there are no types for them. - * - * Note that modules may add their own values to these options. + * The nick, user name, host, and real name of the service. */ - admin = "operserv/*" - override = "chanserv/* nickserv/* memoserv/set botserv/* ~botserv/set" - commands = "~operserv/* *" - servers = "*" - #channels = "~mode *" - users = "connect disconnect nick" - other = "*" - rawio = no - debug = no + nick = "BotServ" + user = "services" + host = "localhost.net" + gecos = "Bot Service" } -/* - * A log block to globops some useful things. - */ -log +service { - target = "globops" - admin = "global/* operserv/mode operserv/kick opeserv/akill operserv/s*line operserv/noop operserv/jupe */forbid nickserv/getpass */drop" -} - -/* - * [RECOMMENDED] Oper Access Config - * - * This section is used to set up staff access to restricted oper only commands. - * You may define groups of commands and privileges, as well as who may use them. - * - * This block is recommended, as without it you will be unable to access most oper commands. - * It replaces the old ServicesRoot directive amongst others. - * - * Note that third party modules may add additional commands and privileges to this list. - * - * Available privileges: - * botserv/administration - Can perform certain BotServ administrative tasks - * chanserv/access/modify - Can modify channel access and akick lists - * chanserv/auspex - Can see any information with /chanserv info - * chanserv/no-register-limit - May register an unlimited number of channels and nicknames - * chanserv/set - Can modify the settings of any channel (incl. changing of the owner and password!) - * memoserv/info - Can see any information with /memoserv info - * memoserv/set-limit - Can set the limit of max stored memos on any user and channel - * memoserv/no-limit - Can send memos through limits and throttles - * nickserv/auspex - Can see any information with /nickserv info - * nickserv/confirm - Can confirm other users nicknames - * nickserv/drop - Can drop other users nicks - * - * Available commands: - * botserv/bot/del botserv/bot/add botserv/bot/change botserv/assign/private - * botserv/botlist botserv/set/private botserv/set/nobot - * - * chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey - * chanserv/list chanserv/suspend chanserv/topic chanserv/status - * chanserv/mode - * - * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/entrymsg - * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/opnotice chanserv/saset/restricted - * chanserv/saset/peace chanserv/saset/persist chanserv/saset/private - * chanserv/saset/secure chanserv/saset/securefounder chanserv/saset/secureops - * chanserv/saset/signkick chanserv/saset/successor chanserv/saset/topiclock - * chanserv/saset/url chanserv/saset/xop - * - * memoserv/sendall memoserv/staff - * - * nickserv/getpass nickserv/sendpass nickserv/getemail nickserv/suspend - * nickserv/resetpass - * - * nickserv/saset/autoop nickserv/saset/email nickserv/saset/greet - * nickserv/saset/icq nickserv/saset/kill nickserv/saset/language nickserv/saset/message - * nickserv/saset/private nickserv/saset/secure nickserv/saset/url nickserv/saset/noexpire - * - * hostserv/set hostserv/del - * - * global/global - * - * operserv/news operserv/stats operserv/kick - * operserv/mode operserv/session operserv/modlist operserv/ignore - * operserv/chankill operserv/akill operserv/sqline operserv/snline - * operserv/szline operserv/staff operserv/config - * operserv/modload operserv/jupe operserv/set operserv/noop - * operserv/quit operserv/update operserv/reload operserv/restart - * operserv/shutdown operserv/svsnick operserv/oline - * - * Firstly, we define 'opertypes' which are named whatever we want ('Network Administrator', etc). - * These can contain commands for oper-only strings (see above) which grants access to that specific command, - * and privileges (which grant access to more general permissions for the named area). - * Wildcard entries are permitted for both, e.g. 'commands = "operserv/*"' for all OperServ commands. - * - * Below are some default example types, but this is by no means exhaustive, - * and it is recommended that you configure them to your needs. - */ - -opertype -{ - /* The name of this opertype */ - name = "Helper" - - /* What commands (see above) this opertype has */ - commands = "hostserv/*" -} - -opertype -{ - /* The name of this opertype */ - name = "Services Operator" - - /* What opertype(s) this inherits from. Seperate with a comma. */ - inherits = "Helper, Another Helper" - - /* What commands (see above) this opertype may use */ - commands = "chanserv/list chanserv/suspend chanserv/status chanserv/topic memoserv/staff nickserv/sendpass nickserv/resetpass nickserv/suspend operserv/mode operserv/chankill operserv/szline operserv/akill operserv/session operserv/modlist operserv/sqline operserv/staff operserv/kick operserv/ignore operserv/snline" - - /* What privs (see above) this opertype has */ - privs = "chanserv/auspex chanserv/no-register-limit memoserv/* nickserv/auxpex nickserv/confirm" -} - -opertype -{ - name = "Services Administrator" - - inherits = "Services Operator" - - commands = "chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey chanserv/set/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svsnick operserv/stats operserv/oline operserv/noop global/*" - - privs = "*" + nick = "ChanServ" + user = "services" + host = "localhost.net" + gecos = "Channel Registration Service" } -opertype +service { - name = "Services Root" - - commands = "*" - - privs = "*" -} - -/* - * After defining different types of operators in the above opertype section, we now define who is in these groups - * through 'oper' blocks, similar to ircd access. - * - * The default is to comment these out (so NOBODY will have Services access). - * You probably want to add yourself and a few other people at minimum. - * - * As with all permissions, make sure to only give trustworthy people access to Services. - */ - -oper -{ - /* The nickname of this services oper */ - #name = "nick1" - - /* The opertype this person will have */ - type = "Services Root" - - /* An optional password. If defined the user must login using /operserv login first */ - #password = "secret" - - /* An optional SSL fingerprint. If defined is required to use this opertype. */ - #certfp = "ed3383b3f7d74e89433ddaa4a6e5b2d7" + nick = "Global" + user = "services" + host = "localhost.net" + gecos = "Global Noticer" } -/* -oper +service { - name = "nick2" - type = "Services Administrator" + nick = "HostServ" + user = "services" + host = "localhost.net" + gecos = "vHost Service" } -oper +service { - name = "nick3" - type = "Helper" + nick = "MemoServ" + user = "services" + host = "localhost.net" + gecos = "Memo Service" } -*/ -/* - * [OPTIONAL] Mail Config - * - * This section contains settings related to the use of e-mail from Services. - * If the usemail directive is set to yes, unless specified otherwise, all other - * directives are required. - */ -mail +service { - /* - * If set, this option enables the mail commands in Services. You may choose - * to disable it if you have no Sendmail-compatible mailer installed. Whilst - * this directive (and entire block) is optional, it is required if the - * nickserv:emailregistration is set to yes. - */ - usemail = yes - - /* - * This is the command-line that will be used to call the mailer to send an - * e-mail. It must be called with all the parameters needed to make it - * scan the mail input to find the mail recipient; consult your mailer - * documentation. - * - * Postfix users must use the compatible sendmail utility provided with - * it. This one usually needs no parameters on the command-line. Most - * sendmail applications (or replacements of it) require the -t option - * to be used. - */ - sendmailpath = "/usr/sbin/sendmail -t" - - /* - * This is the e-mail address from which all the e-mails are to be sent from. - * It should really exist. - */ - sendfrom = "services@localhost.net" - - /* - * If set, SENDPASS and RESETPASS will be restricted to IRC operators. - * This directive is optional. - * - * WARNING: If you choose to not enable this option, you should limit the - * number of processes that the services user can have at a time (you can - * create a special user for this; remember to NEVER launch Services as - * root). - */ - restrict = yes - - /* - * This controls the minimum amount of time a user must wait before sending - * another e-mail after they have sent one. It also controls the minimum time - * a user must wait before they can receive another e-mail. - * - * This feature prevents users from being mail bombed using Services and - * it is highly recommended that it be used. - * - * This directive is optional, but highly recommended. - */ - delay = 5m - - /* - * If set, Services will not attempt to put quotes around the TO: fields - * in e-mails. - * - * This directive is optional, and as far as we know, it's only needed - * if you are using ESMTP or QMail to send out e-mails. - */ - #dontquoteaddresses = yes + nick = "NickServ" + user = "services" + host = "localhost.net" + gecos = "Nickname Registration Service" } -/* - * [OPTIONAL] DNS Config - * - * This section is used to configure DNS. - * At this time DNS is only used by a few modules (m_dnsbl) - * and is not required by the core to function. - */ -dns +service { - /* - * The nameserver to use for resolving hostnames, must be an IP or a resolver configuration file. - * The below should work fine on all unix like systems. Windows users will have to find their nameservers - * from ipconfig /all and put the IP here - */ - nameserver = "/etc/resolv.conf" - #nameserver = "127.0.0.1" - - /* - * How long to wait in seconds before a DNS query has timed out - */ - timeout = 5 + nick = "OperServ" + user = "services" + host = "localhost.net" + gecos = "Operator Service" } /* - * [RECOMMENDED] NickServ - * - * Comment the following line to disable NickServ. + * [RECOMMENDED] Core clients */ -module { name = "ns_main" } -/* - * [REQUIRED] NickServ Config - * - * This section is used to set up the Nickname Registration Service pseudo-client. - * Unless specified otherwise, all directives are required. - */ -nickserv +module { name = "bs_main" } +botserv { /* - * The nickname of the NickServ client. - */ - nick = "NickServ" - - /* - * The description of the NickServ client, which will be used as the GECOS - * (real name) of the client. + * The name of the client that should be BotServ. + * Clients are configured above. */ - description = "Nickname Registration Service" - - /* - * The core modules to load for NickServ. This is a space separated list that corresponds - * to the base names of the modules for NickServ. - * - * This directive is optional, but highly recommended. - */ - modules = "ns_help ns_register ns_group ns_identify ns_access ns_cert ns_set ns_saset ns_set_autoop ns_set_email ns_set_greet ns_set_hide ns_set_kill ns_set_language ns_set_message ns_set_private ns_set_secure ns_saset_noexpire ns_drop ns_recover ns_release ns_sendpass ns_ghost ns_alist ns_info ns_list ns_logout ns_status ns_update ns_getpass ns_getemail ns_suspend ns_resetpass ns_ajoin" - - /* - * Force users to give an e-mail address when they register a nick. - * - * This directive is recommended to be enabled, and required if e-mail registration is enabled. - */ - forceemail = yes - - /* - * Require users who change their email address to confirm they - * own it. - */ - confirmemailchanges = no - - /* - * Require an e-mail to be sent to the user before they can register their nick. - */ - #emailregistration = yes + nick = "BotServ" /* - * The default options for newly registered nicks. Note that changing these options - * will have no effect on nicks which are already registered. The list must be separated + * The default bot options for newly registered channels. Note that changing these options + * will have no effect on channels which are already registered. The list must be separated * by spaces. * * The options are: - * - kill: Kill nick if not identified within 60 seconds - * - killquick: Kill nick if not identified within 20 seconds, this one overrides the above - * option and the above must be specified with this one - * - secure: Enable nickname security, requiring the nick's password before any operations - * can be done on it - * - private: Hide the nick from NickServ's LIST command - * - hideemail: Hide's the nick's e-mail address from NickServ's INFO command - * - hideusermask: Hide's the nick's last or current user@host from NickServ's INFO command - * - hidequit: Hide's the nick's last quit message - * - memosignon: Notify user if they have a new memo when they sign into the nick - * - memoreceive: Notify user if they have a new memo as soon as it's received - * - autoop: User will be automatically opped in channels they enter and have access to - * - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires UsePrivmsg - * to be enabled as well - * - * This directive is optional, if left blank, the options will default to secure, memosignon, and - * memoreceive. If you really want no defaults, use "none" by itself as the option. - */ - defaults="secure private hideemail hideusermask memosignon memoreceive autoop" - - /* - * A list of languages to load on startup that will be available in /nickserv set language. - * Useful if you translate Anope to your language. (Explained further in docs/LANGUAGE). - * Note that english should not be listed here because it is the base language. - */ - languages = "ca_ES de_DE el_GR es_ES fr_FR hu_HU it_IT nl_NL pl_PL pt_PT ru_RU tr_TR" - - /* - * Default language that non- and newly-registered nicks will receive messages in. - * Leave empty to default to English. - */ - #defaultlanguage = "es_ES" - - /* - * The minimum length of time between consecutive uses of NickServ's REGISTER command. This - * directive is optional, but recommended. If not set, this restriction will be disabled. - */ - regdelay = 30s - - /* - * The minimum length of time between consecutive uses of NickServ's RESEND command. - * - * This directive is optional, but recommended. If not set, this restriction will be disabled. - */ - resenddelay = 90s - - /* - * The length of time before a nick registration expires. - * - * This directive is optional, but recommended. If not set, the default is 21 days. - */ - expire = 21d - - /* - * The length of time before a suspended nick becomes unsuspended. - * - * This directive is optional. If not set, the default is to never. - */ - #suspendexpire = 90d - - /* - * The length of time a user using an unconfirmed account has - * before the account will be released for general use again. - * - * This directive is only required if the e-mail registration option is enabled. - */ - #unconfirmedexpire = 1d - - /* - * The maximum number of nicks allowed in a group. + * - dontkickops: Channel operators will be protected against BotServ kicks + * - dontkickvoices: Voiced users will be protected against BotServ kicks + * - greet: The channel's BotServ bot will greet incoming users that have set a greet + * in their NickServ settings + * - fantasy: Enables the use of BotServ fantasy commands in the channel * - * This directive is optional, but recommended. If not set or set to 0, no limits will be applied. + * This directive is optional, if left blank, there will be no defaults. */ - maxaliases = 16 + defaults="greet fantasy" /* - * The maximum number of entries allowed on a nickname's access list. + * The minimum number of users there must be in a channel before the bot joins it. The best + * value for this setting is 1 or 2. This can be 0, the service bots will not part unless + * specifically unassigned, and will keep the channel open. */ - accessmax = 32 + minusers = 1 /* - * The username (and possibly hostname) used for the fake user created when NickServ collides - * a user. Should be in the user@host format. If the host is not given, the one from ServicesUser - * is used. + * The maximum number of entries a single bad words list can have. Setting it too high can + * reduce performance slightly. */ - enforceruser = "enforcer" - #enforceruser = "enforcer@localhost.net" + badwordsmax = 32 /* - * The delay before a NickServ collided nick is released. + * The amount of time that data for a user is valid in BotServ. If the data exceeds this time, + * it is reset or deleted depending on the case. Do not set it too high, otherwise your + * resources will be slightly affected. */ - releasetimeout = 1m + keepdata = 10m /* - * Allow the use of the IMMED option in the NickServ SET KILL command. + * The bots are currently not affected by any modes or bans when they try to join a channel. + * But some people may want to make it act like a real bot, that is, for example, remove all + * the bans affecting the bot before joining the channel, remove a ban that affects the bot + * set by a user when it is in the channel, and so on. Since it consumes a bit more CPU + * time, you should not enable this on larger networks. * * This directive is optional. */ - #allowkillimmed = yes - - /* - * If set, the NickServ GROUP command won't allow any group change. This is recommended for - * better performance and to protect against nick stealing, however users will have less - * flexibility. - * - * This directive is optional, but recommended. - */ - #nogroupchange = yes + #smartjoin = yes /* - * Limits the use of the NickServ LIST command to IRC operators. + * If set, the bots will use a kick reason that does not state the word when it is kicking. + * This is especially useful if you have young people on your network. * * This directive is optional. */ - #listopersonly = yes - - /* - * The maximum number of nicks to be returned for a NickServ LIST command. - */ - listmax = 50 - - /* - * When a user's nick is forcibly changed to enforce a "nick kill", their new nick will start - * with this value. The rest will be made up of 6 or 7 digits. - */ - guestnickprefix = "Guest" - - /* - * Prevents the use of the DROP, FORBID, GETPASS, and SET PASSWORD commands by Services Admins - * on other Services Admins or the Services Root(s). - * - * This directive is optional, but recommended. - */ - secureadmins = yes - - /* - * If set, any user wanting to use the privileges of Services Root, Services Admin, or Services - * Operator must have been logged as an IRC Operator with the /oper command. - * - * This directive is optional, but recommended. - */ - strictprivileges = yes + gentlebadwordreason = yes /* - * If set, Services will set the channel modes a user has access to upon identifying, assuming - * they are not already set. + * If set, BotServ will use case sensitive checking for badwords. * * This directive is optional. */ - modeonid = yes - - /* - * If set, Services will add the usermask of registering users to the access list of their - * newly created account. If not set, users will always have to identify to NickServ before - * being recognized, unless they manually add an address to the access list of their account. - * This directive is optional. - */ - addaccessonreg = yes + #casesensitive = yes /* - * The maximum number of channels a user can have on NickServ's AJOIN command. + * Defines the prefix for fantasy commands in channels. This character will have to be prepended + * to all fantasy commands. If you choose "!", for example, fantasy commands will be "!kick", + * "!op", etc. This directive is optional, if left out, the default fantasy character is "!". */ - ajoinmax = 10 + #fantasycharacter = "!" } /* - * [RECOMMENDED] ChanServ + * [RECOMMENDED] Core ChanServ module. * - * Comment the following line to disable ChanServ. + * Provides essential functionality for ChanServ */ module { name = "cs_main" } -/* - * [RECOMMENDED] ChanServ Config - * - * This section is used to set up the Channel Registration Service pseudo-client. - * Unless specified otherwise, all directives are required if you wish to use ChanServ. - */ chanserv { /* - * The nickname of the ChanServ client. + * The name of the client that should be ChanServ. Clients are configured + * with the service blocks. */ - nick = "ChanServ" - - /* - * The description of the ChanServ client, which will be used as the GECOS - * (real name) of the client. - */ - description = "Channel Registration Service" - - /* - * The core modules to load for ChanServ. This is a space separated list that corresponds - * to the base names of the modules for ChanServ. - * - * This directive is optional, but highly recommended. - */ - modules = "cs_help cs_register cs_set cs_saset cs_saset_noexpire cs_set_bantype cs_set_description cs_set_founder cs_set_keeptopic cs_set_opnotice cs_set_peace cs_set_persist cs_set_private cs_set_restricted cs_set_secure cs_set_securefounder cs_set_secureops cs_set_signkick cs_set_successor cs_set_topiclock cs_set_xop cs_xop cs_access cs_akick cs_drop cs_ban cs_clearusers cs_modes cs_getkey cs_invite cs_kick cs_list cs_topic cs_info cs_suspend cs_status cs_unban cs_clone cs_mode" + name = "ChanServ" /* * The default options for newly registered channels. Note that changing these options @@ -1177,38 +740,63 @@ chanserv #opersonly = yes } -/* - * [OPTIONAL] MemoServ - * - * Comment the following line to disable MemoServ. - */ -module { name = "ms_main" } - -/* [OPTIONAL] MemoServ configuration - * - * This section is used to set up the Memo Service pseudo-client. This is only required if ms_main - * is being loaded. - */ -memoserv +module { name = "gl_main" } +global { /* - * The nickname of the MemoServ client. + * The name of the client that should be Global. Clients are configured + * with the service blocks. */ - nick = "MemoServ" + name = "Global" /* - * The description of the MemoServ client, which will be used as the GECOS - * (real name) of the client. + * If set, Services will send global messages on starting up and shutting + * down/restarting. + * + * This directive is optional. */ - description = "Memo Service" + #globaloncycle = yes /* - * The core modules to load for MemoServ. This is a space separated list that corresponds - * to the base names of the modules for MemoServ. - * - * This directive is optional, but highly recommended. + * This is the global message that will be sent when Services are being + * shutdown/restarted. This directive is only required if you enable + * globaloncycle above. + */ + globaloncycledown = "Services are restarting, they will be back shortly - please be good while we're gone" + + /* + * This is the global message that will be sent when Services (re)join the + * network. This directive is only required if you enable globaloncycle above. + */ + globaloncycleup = "Services are now back online - have a nice day" + + /* + * If set, Services will hide the IRC operator's nick in a global + * message/notice. + * + * This directive is optional. + */ + #anonymousglobal = yes +} + +module { name = "hs_main" } +hostserv +{ + /* + * The name of the client that should be HostServ. Clients are configured + * with the service blocks. + */ + name = "HostServ" +} + +module { name = "ms_main" } +memoserv +{ + /* + * The name of the client that should be MemoServ. Clients are configured + * with the service blocks. */ - modules = "ms_send ms_cancel ms_list ms_read ms_del ms_set ms_info ms_rsend ms_check ms_staff ms_sendall ms_ignore ms_help" + name = "MemoServ" /* * The maximum number of memos a user is allowed to keep by default. Normal users may set the @@ -1241,180 +829,211 @@ memoserv #memoreceipt = 1 } -/* - * [OPTIONAL] BotServ - * - * Comment the following line to disable BotServ. - */ -module { name = "bs_main" } - -/* [OPTIONAL] BotServ configuration - * - * This section is used to set up the Bot Service pseudo-client. This is only required if ms_main - * is being loaded. - */ -botserv +module { name = "ns_main" } +nickserv { /* - * The nickname of the BotServ client. + * The name of the client that should be NickServ. Clients are configured + * with the service blocks. */ - nick = "BotServ" + name = "NickServ" /* - * The description of the BotServ client, which will be used as the GECOS - * (real name) of the client. + * Force users to give an e-mail address when they register a nick. + * + * This directive is recommended to be enabled, and required if e-mail registration is enabled. */ - description = "Bot Service" + forceemail = yes /* - * The core modules to load for BotServ. This is a space separated list that corresponds - * to the base names of the modules for BotServ. - * - * This directive is optional, but highly recommended. + * Require users who change their email address to confirm they + * own it. */ - modules = "bs_help bs_botlist bs_assign bs_set bs_kick bs_badwords bs_act bs_info bs_say bs_unassign bs_bot" + confirmemailchanges = no /* - * The default bot options for newly registered channels. Note that changing these options - * will have no effect on channels which are already registered. The list must be separated + * Require an e-mail to be sent to the user before they can register their nick. + */ + #emailregistration = yes + + /* + * The default options for newly registered nicks. Note that changing these options + * will have no effect on nicks which are already registered. The list must be separated * by spaces. * * The options are: - * - dontkickops: Channel operators will be protected against BotServ kicks - * - dontkickvoices: Voiced users will be protected against BotServ kicks - * - greet: The channel's BotServ bot will greet incoming users that have set a greet - * in their NickServ settings - * - fantasy: Enables the use of BotServ fantasy commands in the channel - * - symbiosis: Causes the BotServ bot to do all actions that would normally have been - * done by ChanServ + * - kill: Kill nick if not identified within 60 seconds + * - killquick: Kill nick if not identified within 20 seconds, this one overrides the above + * option and the above must be specified with this one + * - secure: Enable nickname security, requiring the nick's password before any operations + * can be done on it + * - private: Hide the nick from NickServ's LIST command + * - hideemail: Hide's the nick's e-mail address from NickServ's INFO command + * - hideusermask: Hide's the nick's last or current user@host from NickServ's INFO command + * - hidequit: Hide's the nick's last quit message + * - memosignon: Notify user if they have a new memo when they sign into the nick + * - memoreceive: Notify user if they have a new memo as soon as it's received + * - autoop: User will be automatically opped in channels they enter and have access to + * - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires UsePrivmsg + * to be enabled as well * - * This directive is optional, if left blank, there will be no defaults. + * This directive is optional, if left blank, the options will default to secure, memosignon, and + * memoreceive. If you really want no defaults, use "none" by itself as the option. */ - defaults="greet fantasy symbiosis" + defaults="secure private hideemail hideusermask memosignon memoreceive autoop" /* - * The minimum number of users there must be in a channel before the bot joins it. The best - * value for this setting is 1 or 2. This can be 0, the service bots will not part unless - * specifically unassigned, and will keep the channel open. + * A list of languages to load on startup that will be available in /nickserv set language. + * Useful if you translate Anope to your language. (Explained further in docs/LANGUAGE). + * Note that english should not be listed here because it is the base language. */ - minusers = 1 + languages = "ca_ES de_DE el_GR es_ES fr_FR hu_HU it_IT nl_NL pl_PL pt_PT ru_RU tr_TR" /* - * The maximum number of entries a single bad words list can have. Setting it too high can - * reduce performance slightly. + * Default language that non- and newly-registered nicks will receive messages in. + * Leave empty to default to English. */ - badwordsmax = 32 + #defaultlanguage = "es_ES" /* - * The amount of time that data for a user is valid in BotServ. If the data exceeds this time, - * it is reset or deleted depending on the case. Do not set it too high, otherwise your - * resources will be slightly affected. + * The minimum length of time between consecutive uses of NickServ's REGISTER command. This + * directive is optional, but recommended. If not set, this restriction will be disabled. */ - keepdata = 10m + regdelay = 30s /* - * The bots are currently not affected by any modes or bans when they try to join a channel. - * But some people may want to make it act like a real bot, that is, for example, remove all - * the bans affecting the bot before joining the channel, remove a ban that affects the bot - * set by a user when it is in the channel, and so on. Since it consumes a bit more CPU - * time, you should not enable this on larger networks. + * The minimum length of time between consecutive uses of NickServ's RESEND command. * - * This directive is optional. + * This directive is optional, but recommended. If not set, this restriction will be disabled. */ - #smartjoin = yes + resenddelay = 90s /* - * If set, the bots will use a kick reason that does not state the word when it is kicking. - * This is especially useful if you have young people on your network. + * The length of time before a nick registration expires. * - * This directive is optional. + * This directive is optional, but recommended. If not set, the default is 21 days. */ - gentlebadwordreason = yes + expire = 21d /* - * If set, BotServ will use case sensitive checking for badwords. + * The length of time before a suspended nick becomes unsuspended. * - * This directive is optional. + * This directive is optional. If not set, the default is to never. */ - #casesensitive = yes + #suspendexpire = 90d /* - * Defines the prefix for fantasy commands in channels. This character will have to be prepended - * to all fantasy commands. If you choose "!", for example, fantasy commands will be "!kick", - * "!op", etc. This directive is optional, if left out, the default fantasy character is "!". + * The length of time a user using an unconfirmed account has + * before the account will be released for general use again. + * + * This directive is only required if the e-mail registration option is enabled. */ - #fantasycharacter = "!" -} + #unconfirmedexpire = 1d -/* - * [OPTIONAL] HostServ - * - * Comment the following line to disable HostServ. - */ -module { name = "hs_main" } + /* + * The maximum number of nicks allowed in a group. + * + * This directive is optional, but recommended. If not set or set to 0, no limits will be applied. + */ + maxaliases = 16 -/* - * [OPTIONAL] HostServ Config - * - * This section is used to set up the vHost Service pseudo-client. - * - * Unless specified otherwise, all directives are required if you do wish to use HostServ. - */ -hostserv -{ /* - * The nickname of the HostServ client. + * The maximum number of entries allowed on a nickname's access list. */ - nick = "HostServ" + accessmax = 32 /* - * The description of the HostServ client, which will be used as the GECOS - * (real name) of the client. + * The username (and possibly hostname) used for the fake user created when NickServ collides + * a user. Should be in the user@host format. */ - description = "vHost Service" + enforceruser = "enforcer" + enforcerhost = "localhost.net" /* - * The core modules to load for HostServ. This is a space separated list that corresponds - * to the base names of the modules for HostServ. + * The delay before a NickServ collided nick is released. + */ + releasetimeout = 1m + + /* + * Allow the use of the IMMED option in the NickServ SET KILL command. * - * This directive is optional, but highly recommended. + * This directive is optional. */ - modules = "hs_help hs_on hs_off hs_group hs_list hs_set hs_setall hs_del hs_delall" -} + #allowkillimmed = yes -/* - * [RECOMMENDED] OperServ - * - * Comment the following line to disable OperServ. - */ -module { name = "os_main" } + /* + * If set, the NickServ GROUP command won't allow any group change. This is recommended for + * better performance and to protect against nick stealing, however users will have less + * flexibility. + * + * This directive is optional, but recommended. + */ + #nogroupchange = yes -/* - * [RECOMMENDED] OperServ Config - * - * This section is used to set up the Operator Service pseudo-client. Unless specified otherwise, - * all directives are required if you wish to use OperServ. - */ -operserv -{ /* - * The nickname of the OperServ client. + * Limits the use of the NickServ LIST command to IRC operators. + * + * This directive is optional. */ - nick = "OperServ" + #listopersonly = yes /* - * The description of the OperServ client, which will be used as the GECOS - * (real name) of the client. + * The maximum number of nicks to be returned for a NickServ LIST command. */ - description = "Operator Service" + listmax = 50 /* - * The core modules to load for OperServ. This is a space separated list that corresponds - * to the base names of the modules for OperServ. + * When a user's nick is forcibly changed to enforce a "nick kill", their new nick will start + * with this value. The rest will be made up of 6 or 7 digits. + */ + guestnickprefix = "Guest" + + /* + * Prevents the use of the DROP, FORBID, GETPASS, and SET PASSWORD commands by Services Admins + * on other Services Admins or the Services Root(s). * - * This directive is optional, but highly recommended. + * This directive is optional, but recommended. + */ + secureadmins = yes + + /* + * If set, any user wanting to use the privileges of Services Root, Services Admin, or Services + * Operator must have been logged as an IRC Operator with the /oper command. + * + * This directive is optional, but recommended. + */ + strictprivileges = yes + + /* + * If set, Services will set the channel modes a user has access to upon identifying, assuming + * they are not already set. + * + * This directive is optional. */ - modules = "os_help os_stats os_oper os_mode os_kick os_akill os_snline os_sqline os_szline os_chanlist os_userlist os_news os_session os_noop os_jupe os_ignore os_set os_reload os_update os_restart os_quit os_shutdown os_chankill os_svsnick os_oline os_modload os_modunload os_modreload os_modlist os_modinfo os_config os_login os_forbid" + modeonid = yes + + /* + * If set, Services will add the usermask of registering users to the access list of their + * newly created account. If not set, users will always have to identify to NickServ before + * being recognized, unless they manually add an address to the access list of their account. + * This directive is optional. + */ + addaccessonreg = yes + + /* + * The maximum number of channels a user can have on NickServ's AJOIN command. + */ + ajoinmax = 10 +} + +module { name = "os_main" } +operserv +{ + /* + * The name of the client that should be OperServ. Clients are configured + * with the service blocks. + */ + name = "OperServ" /* * If set, Services Admins will be able to use SUPERADMIN [ON|OFF] which will temporarily grant @@ -1567,806 +1186,415 @@ operserv } /* - * [RECOMMENDED] Global - * - * Comment the following line to disable Global. - */ -module { name = "gl_main" } - -/* - * [RECOMMENDED] Global Config - * - * This section is used to set up the Global pseudo-client. Unless specified otherwise, - * all directives are required if you wish to use Global. + * [RECOMMENDED] Logging Configuration * - * Globals two main functions are for sending globals and for logging miscellaneous data to - * the log channel(s). If disabled, many logs will NOT be sent to the log channel(s). + * This section is used for configuring what is logged and where it is logged to. + * You may have multiple log blocks if you wish. Remember to properly secure any + * channels you choose to have Anope log to! */ -global +log { /* - * The nickname of the Global client. - */ - nick = "Global" - - /* - * The description of the Global client, which will be used as the GECOS - * (real name) of the client. + * Target(s) to log to, which may be one of the following: + * - a channel name + * - a filename + * - globops */ - description = "Global Noticer" + target = "services.log" + /* Log to both services.log and the channel #services */ + #target = "services.log #services" /* - * The core modules to load for OperServ. This is a space separated list that corresponds - * to the base names of the modules for OperServ. - * - * This directive is optional, but highly recommended. + * The source(s) to only accept log messages from. Leave commented to allow all sources. + * This can be a users name, a channel name, one of our clients (eg, OperServ), or a server name. */ - modules = "gl_help gl_global" + #source = "" /* - * If set, Services will send global messages on starting up and shutting - * down/restarting. + * The number of days to keep logfiles, only useful if you are logging to a file. + * Set to 0 to never delete old logfiles. * - * This directive is optional. - */ - #globaloncycle = yes - - /* - * This is the global message that will be sent when Services are being - * shutdown/restarted. This directive is only required if you enable - * globaloncycle above. + * Note that Anope must run 24 hours a day for this feature to work correctly. */ - globaloncycledown = "Services are restarting, they will be back shortly - please be good while we're gone" + logage = 7 /* - * This is the global message that will be sent when Services (re)join the - * network. This directive is only required if you enable globaloncycle above. + * Enable to have the core services clients join and stay in the log channel(s) when logging. + * Note: on some IRCds this is not optional, and is enforced on. */ - globaloncycleup = "Services are now back online - have a nice day" + inhabitlogchannel = yes /* - * If set, Services will hide the IRC operator's nick in a global - * message/notice. + * What types of log messages should be logged by this block. There are nine general categories: * - * This directive is optional. - */ - #anonymousglobal = yes -} - -/* - * [OPTIONAL] DefCon Config - * - * This section is used to set up the DefCon system of OperServ. The block is optional and can be - * removed if you wish to disable DefCon in it's entirety. Unless specified otherwise, all directives - * are required if you do wish to use DefCon. - */ -defcon -{ - /* - * Default DefCon level (1-5) to use when starting Services up. Level 5 constitutes normal operation - * while level 1 constitutes the most restrictive operation. If this setting is left out or set to - * 0, DefCon will be disabled and the rest of this block will be ignored. - */ - #defaultlevel = 5 - - /* - * The following 4 directives define what operations will take place when DefCon is set to levels - * 1 through 4. Each level is a list that must be separated by spaces. + * admin - Execution of admin commands (OperServ, etc). + * override - A services operator using their powers to execute a command they couldn't normally. + * commands - Execution of general commands. + * servers - Server actions, linking, squitting, etc. + * channels - Actions in channels such as joins, parts, kicks, etc. + * users - User actions such as connecting, disconnecting, changing name, etc. + * other - All other messages without a category. + * rawio - Logs raw input and output from services + * debug - Debug messages (log files can become VERY large from this). * - * The following operations can be defined at each level: - * - nonewchannels: Disables registering new channels - * - nonewnicks: Disables registering new nicks - * - nomlockchanges: Disables changing MLOCK on registered channels - * - forcechanmodes: Forces all channels to have the modes given in the later chanmodes directive - * - reducedsessions: Reduces the session limit to the value given in the later sessionlimit directive - * - nonewclients: KILL any new clients trying to connect - * - operonly: Services will ignore all non-IRCops - * - silentoperonly: Services will silently ignore all non-IRCops - * - akillnewclients: AKILL any new clients trying to connect - * - nonewmemos: No new memos will be sent to block MemoServ attacks - */ - level4 = "nonewchannels nonewnicks nomlockchanges reducedsessions" - level3 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions" - level2 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly" - level1 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly akillnewclients" - - /* - * New session limit to use when a DefCon level is using "reduced" session limiting. - */ - #sessionlimit = 2 - - /* - * Length of time to add an AKILL for when DefCon is preventing new clients from connecting to the - * network. - */ - #akillexpire = 5m - - /* - * The channel modes to set on all channels when the DefCon channel mode system is in use. + * These options determine what messages from the categories should be logged. Wildcards are accepted, and + * you can also negate values with a ~. For example, "~operserv/akill operserv/*" would log all operserv + * messages except for operserv/akill. Note that processing stops at the first matching option, which + * means "* ~operserv/*" would log everything because * matches everything. * - * Note 1: Choose these modes carefully, because when DefCon switches to a level which does NOT have - * the mode setting selected, Services will set the reverse on all channels, e.g. if this setting - * is +RN when DefCon is used, all channels will be set to +RN, when DefCon is removed, all - * channels will be set to -RN. You don't want to set this to +k for example, because when DefCon - * is removed all channels with -k. + * Valid admin, override, and command options are: + * pesudo-serv/commandname (eg, operserv/akill, chanserv/set) * - * Note 2: MLOCKed modes will not be lost. - */ - #chanmodes = "+R" - - /* - * This value can be used to automatically return the network to DefCon level 5 after the specified - * time period, just in case any IRC Operator forgets to remove a DefCon setting. + * Valid server options are: + * connect, quit, sync * - * This directive is optional. - */ - #timeout = 15m - - /* - * If set, Services will send a global message on DefCon level changes. + * Valid channel options are: + * create, destroy, join, part, kick, leave, mode * - * This directive is optional. - */ - #globalondefcon = yes - - /* - * Defines a message that will be sent on DefCon level changes. + * Valid user options are: + * connect, disconnect, quit, nick, ident, host, mode, maxusers * - * This directive is optional. - */ - #message = "Put your message to send your users here. Dont forget to uncomment globalondefconmore" - - /* - * Defines the message that will be sent when DefCon is returned to level 5. This directive is optional, - * and will also override globalondefcon and globalondefconmore when set. - */ - #offmessage = "Services are now back to normal, sorry for any inconvenience" - - /* - * Defines the reason to use when clients are KILLed or AKILLed from the network while the proper - * DefCon operation is in effect. + * Rawio and debug are simple yes/no answers, there are no types for them. + * + * Note that modules may add their own values to these options. */ - #akillreason = "This network is currently not accepting connections, please try again later" + admin = "operserv/*" + override = "chanserv/* nickserv/* memoserv/set botserv/* ~botserv/set" + commands = "~operserv/* *" + servers = "*" + #channels = "~mode *" + users = "connect disconnect nick" + other = "*" + rawio = no + debug = no } /* - * [OPTIONAL] Additional includes - * - * You can include additional configuration files here. - * You may also include executable files, which will be executed and - * the output from it will be included into your configuration. + * A log block to globops some useful things. */ - -/* -include -{ - type = "file" - name = "some_other.conf" -} -include +log { - type = "executable" - name = "/usr/bin/wget -q -O - http://some.miconfigured.network.com/services.conf" + target = "globops" + admin = "global/* operserv/mode operserv/kick opeserv/akill operserv/s*line operserv/noop operserv/jupe */forbid nickserv/getpass */drop" } -*/ /* - * [OPTIONAL] Non-Core Modules + * [RECOMMENDED] Oper Access Config * - * The following blocks are used to load all non-core modules, including 3rd-party modules. - * Modules can be prevented from loading by commenting out the line, other modules can be added by - * adding a module block. These modules will be loaded prior to Services connecting to your network. - */ - -/* - * cs_appendtopic + * This section is used to set up staff access to restricted oper only commands. + * You may define groups of commands and privileges, as well as who may use them. * - * Adds the APPENDTOPIC command to ChanServ, which allows users to easially append text to - * the end of existing channel topics. - */ -module { name = "cs_appendtopic" } - -/* - * cs_enforce + * This block is recommended, as without it you will be unable to access most oper commands. + * It replaces the old ServicesRoot directive amongst others. * - * Adds the ENFORCE commad to ChanServ, which allows enforcing various channel settings like - * SECUREOPS and RESTRICTED. - */ -module { name = "cs_enforce" } - -/* - * cs_entrymsg + * Note that third party modules may add additional commands and privileges to this list. * - * Allows you to set entry messages on your channel, which are shown to anyone - * who joins. - */ -module { name = "cs_entrymsg" } -cs_entrymsg -{ - /* The maximum number of entrymsgs allowed per channel. If not set, defaults to 5. */ - maxentries = 5 -} - -/* - * cs_set_misc + * Available privileges: + * botserv/administration - Can perform certain BotServ administrative tasks + * chanserv/access/modify - Can modify channel access and akick lists + * chanserv/auspex - Can see any information with /chanserv info + * chanserv/no-register-limit - May register an unlimited number of channels and nicknames + * chanserv/set - Can modify the settings of any channel (incl. changing of the owner and password!) + * memoserv/info - Can see any information with /memoserv info + * memoserv/set-limit - Can set the limit of max stored memos on any user and channel + * memoserv/no-limit - Can send memos through limits and throttles + * nickserv/auspex - Can see any information with /nickserv info + * nickserv/confirm - Can confirm other users nicknames + * nickserv/drop - Can drop other users nicks * - * Allows you to create misc /chanserv set commands, and have the data - * show up in /chanserv info - */ -module { name = "cs_set_misc" } -cs_set_misc -{ - /* The name of the command */ - name = "OINFO" - /* A short description of the command */ - desc = "Associate oper only information to this channel" - /* Set to yes if only opers and privileged users can set it and see it */ - privileged = yes -} -cs_set_misc -{ - name = "URL" - desc = "Associate a URL with the channel" -} -cs_set_misc -{ - name = "EMAIL" - desc = "Associate an EMail with the channel" -} - -/* - * db_plain + * Available commands: + * botserv/bot/del botserv/bot/add botserv/bot/change botserv/assign/private + * botserv/botlist botserv/set/private botserv/set/nobot * - * This is the default flatfile database format. You must have at least one database - * module loaded or Anope will not save databases! - */ -module { name = "db_plain" } -db_plain -{ - /* - * The database db_plain should use - */ - database = "anope.db" -} - -/* - * db_mysql and db_mysql_live + * chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey + * chanserv/list chanserv/suspend chanserv/topic chanserv/status + * chanserv/mode * - * Enables (live) MySQL support. + * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/entrymsg + * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/opnotice chanserv/saset/restricted + * chanserv/saset/peace chanserv/saset/persist chanserv/saset/private + * chanserv/saset/secure chanserv/saset/securefounder chanserv/saset/secureops + * chanserv/saset/signkick chanserv/saset/successor chanserv/saset/topiclock + * chanserv/saset/url chanserv/saset/xop * - * The db_mysql_live module is an extension to db_mysql, and should only be used if - * db_mysql is being used. This module pulls data in real time from SQL as it is - * requested by the core as a result of someone executing commands. + * memoserv/sendall memoserv/staff * - * This effectively allows you to edit your database and have it be immediately - * reflected back in Anope. + * nickserv/getpass nickserv/sendpass nickserv/getemail nickserv/suspend + * nickserv/resetpass * - * For information on how to make db_mysql_live use asynchronous queries see - * m_async_commands. + * nickserv/saset/autoop nickserv/saset/email nickserv/saset/greet + * nickserv/saset/icq nickserv/saset/kill nickserv/saset/language nickserv/saset/message + * nickserv/saset/private nickserv/saset/secure nickserv/saset/url nickserv/saset/noexpire * - * At this time db_mysql_live only supports pulling data in real time from the three - * main tables: anope_cs_info, anope_ns_alias, and anope_ns_core. - */ -#module { name = "db_mysql" } -#module { name = "db_mysql_live" } - -/* - * The encryption modules are used when dealing with passwords. This determines how - * the passwords are stored in the databases, and does not add any security as - * far as transmitting passwords over the network goes. - * - * Without any encryption modules, passwords will be stored in plain text, allowing - * for passwords to be recovered later but isn't secure therefore is not recommended. - * - * The other encryption modules use one-way encryption, so the passwords can not - * be recovered later if those are used. + * hostserv/set hostserv/del * - * NOTE: enc_old is Anope's previous (broken) MD5 implementation, if your databases - * were made using that module, continue to use it and do not use enc_md5. + * global/global * - * NOTE: enc_sha1 relies on how the OS stores 2+ byte data internally, and is - * potentially broken when moving between 2 different OSes, such as moving from - * Linux to Windows. It is recommended that you use enc_sha256 instead if you want - * to use an SHA-based encryption. If you choose to do so, it is also recommended - * that you first try to get everyone's passwords converted to enc_sha256 before - * switching OSes by placing enc_sha256 at the beginning of the list. + * operserv/news operserv/stats operserv/kick + * operserv/mode operserv/session operserv/modlist operserv/ignore + * operserv/chankill operserv/akill operserv/sqline operserv/snline + * operserv/szline operserv/staff operserv/config + * operserv/modload operserv/jupe operserv/set operserv/noop + * operserv/quit operserv/update operserv/reload operserv/restart + * operserv/shutdown operserv/svsnick operserv/oline * - * The first encryption module loaded is the primary encryption module. All new passwords are - * encrypted by this module. Old passwords stored in another encryption method are - * automatically re-encrypted by the primary encryption module on next identify. - */ -module { name = "enc_md5" } -#module { name = "enc_sha1" } -#module { name = "enc_sha256" } - -/* - * When using enc_none, passwords will be stored without encryption in plain - * text, allowing for passwords to be recovered later. This isn't secure therefore - * is not recommended. - */ -#module { name = "enc_none" } - -/* - * enc_old is Anope's previous (broken) MD5 implementation, if your databases - * were made using that module, load it here to allow conversion to the primary - * encryption method. - */ -#module { name = "enc_old" } - -/* - * hs_request + * Firstly, we define 'opertypes' which are named whatever we want ('Network Administrator', etc). + * These can contain commands for oper-only strings (see above) which grants access to that specific command, + * and privileges (which grant access to more general permissions for the named area). + * Wildcard entries are permitted for both, e.g. 'commands = "operserv/*"' for all OperServ commands. * - * Allows users to request vhosts which opers may then view, accept or deny + * Below are some default example types, but this is by no means exhaustive, + * and it is recommended that you configure them to your needs. */ -module { name = "hs_request" } -hs_request + +opertype { - /* - * If set, Services will send a memo to the user requesting a vHost when it's been - * approved or rejected. - */ - #memouser = yes + /* The name of this opertype */ + name = "Helper" - /* - * If set, Services will send a memo to all Services staff when a new vHost is requested. - */ - #memooper = yes + /* What commands (see above) this opertype has */ + commands = "hostserv/*" } -/* - * m_alias - * - * Allows you to create custom command aliases. - */ -module { name = "m_alias" } -alias +opertype { - /* Set to yes to make this alias triggerable by fantasy commands. */ - fantasy = no - /* Set to yes to make this alias oper only */ - operonly = no - /* Set to yes to hide this command from HELP */ - #hide = yes + /* The name of this opertype */ + name = "Services Operator" - /* Source client and command. - */ - source_client = "NickServ" - source_command = "ID" + /* What opertype(s) this inherits from. Seperate with a comma. */ + inherits = "Helper, Another Helper" - /* Target client and command. - */ - target_client = "NickServ" - target_command = "IDENTIFY" + /* What commands (see above) this opertype may use */ + commands = "chanserv/list chanserv/suspend chanserv/status chanserv/topic memoserv/staff nickserv/sendpass nickserv/resetpass nickserv/suspend operserv/mode operserv/chankill operserv/szline operserv/akill operserv/session operserv/modlist operserv/sqline operserv/staff operserv/kick operserv/ignore operserv/snline" + + /* What privs (see above) this opertype has */ + privs = "chanserv/auspex chanserv/no-register-limit memoserv/* nickserv/auxpex nickserv/confirm" } -/* Adds the /chanserv alist command which becomes rewritten to /chanserv access #channel list" -alias + +opertype { - hide = yes + name = "Services Administrator" - source_client = "ChanServ" - source_command = "ALIST" + inherits = "Services Operator" - target_client = "ChanServ" - target_command = "ACCESS" - target_rewrite = "$0 LIST" -} -/* Provides the !k fantasy command */ -alias -{ - fantasy = yes - source_command = "K" + commands = "chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey chanserv/set/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svsnick operserv/stats operserv/oline operserv/noop global/*" - target_client = "ChanServ" - target_command = "KICK" - + privs = "*" } -/* Provides the !kb fantasy command */ -alias + +opertype { - fantasy = yes - source_command = "KB" + name = "Services Root" - target_client = "ChanServ" - target_command = "BAN" + commands = "*" + + privs = "*" } /* - * m_async_commands - * - * Threads for each command executed by users. You should - * only load this if you are using a module designed to work with this. + * After defining different types of operators in the above opertype section, we now define who is in these groups + * through 'oper' blocks, similar to ircd access. * - * If this is loaded with db_mysql_live then Anope will support - * processing multiple commands at once which will negate the "lag" - * issues caused from the overhead of SQL queries by db_mysql_live. + * The default is to comment these out (so NOBODY will have Services access). + * You probably want to add yourself and a few other people at minimum. * - * Note that this module is currently EXPERIMENTAL and you should report - * any bugs you find. + * As with all permissions, make sure to only give trustworthy people access to Services. */ -#module { name = "m_async_commands" } -/* m_dnsbl - * - * Allows configurable DNS blacklists to check connecting users against. If a user - * is found on the blacklist they will be immediately banned. This is a crucial module - * to prevent bot attacks. - */ -module { name = "m_dnsbl" } -m_dnsbl +oper { - /* - * If set, Services will check clients against the DNSBLs when services connect to its uplink. - * This is not recommended, and on large networks will open a very large amount of DNS queries. - * Whilst services are not drastically affected by this, your nameserver/DNSBL might care. - */ - check_on_connect = no + /* The nickname of this services oper */ + #name = "nick1" - /* - * If set, Services will check clients when coming back from a netsplit. This can cause a large number - * of DNS queries open at once. Whilst services are not drastically affected by this, your nameserver/DNSBL - * might care. - */ - check_on_netburst = no + /* The opertype this person will have */ + type = "Services Root" - /* - * If set, OperServ will add clients found in the DNSBL to the akill list. Without it, OperServ simply sends - * a timed G/K-line to the IRCd and forgets about it. Can be useful if your akill list is being fill up by bots. - */ - add_to_akill = yes -} -blacklist -{ - /* Name of the blacklist */ - name = "rbl.efnetrbl.org" - - /* How long to set the ban for */ - time = 4h - - /* Reason for akill. - * %n is the nick of the user - * %u is the ident/username of the user - * %g is the realname of the user - * %h is the hostname of the user - * %i is the IP of the user - * %r is the reason (configured below). Will be nothing if not configured. - * %N is the network name set in networkinfo:networkname - */ - reason = "You are listed in the efnet RBL, visit http://rbl.efnetrbl.org/?i=%i for info" - - /* Replies to ban and their reason. If this is totally ommited all replies get banned */ - 1 = "Open Proxy" - /* Don't ban for result 2 or 3 */ - #2 = "spamtrap666" - #3 = "spamtrap50" - 4 = "TOR" - 5 = "Drones / Flooding" -} -blacklist -{ - name = "dnsbl.dronebl.org" - time = 4h - reason = "You have a host listed in the DroneBL. For more information, visit http://dronebl.org/lookup_branded.do?ip=%i&network=%N" + /* An optional password. If defined the user must login using /operserv login first */ + #password = "secret" + + /* An optional SSL fingerprint. If defined is required to use this opertype. */ + #certfp = "ed3383b3f7d74e89433ddaa4a6e5b2d7" } -/* m_helpchan - * - * Gives users who are op in the specified help channel usermode +h (helpop). - */ -#module { name = "m_helpchan" } -m_helpchan +/* +oper { - helpchannel = "#help" + name = "nick2" + type = "Services Administrator" } -/* - * m_ldap - * - * This module allows other modules to use LDAP. By itself, this module does nothing useful. - */ -#module { name = "m_ldap" } -ldap +oper { - server = "ldap://127.0.0.1" - port = 389 - admin_binddn = "cn=Manager,dc=anope,dc=org" - admin_password = "secret" + name = "nick3" + type = "Helper" } +*/ /* - * m_ldap_authentication + * [OPTIONAL] Mail Config * - * This module allows many commands such as IDENTIFY, RELEASE, RECOVER, GHOST, etc. use - * LDAP to authenticate users. Requires m_ldap. -*/ -#module { name = "m_ldap_authentication" } -m_ldap_authentication + * This section contains settings related to the use of e-mail from Services. + * If the usemail directive is set to yes, unless specified otherwise, all other + * directives are required. + */ +mail { /* - * The distinguished name we should bind to when a user tries to identify. + * If set, this option enables the mail commands in Services. You may choose + * to disable it if you have no Sendmail-compatible mailer installed. Whilst + * this directive (and entire block) is optional, it is required if the + * nickserv:emailregistration is set to yes. */ - binddn = "ou=users,dc=anope,dc=org" + usemail = yes /* - * The object class used by LDAP to store user account information. - * Used for adding new users to LDAP if disable_ns_register is false + * This is the command-line that will be used to call the mailer to send an + * e-mail. It must be called with all the parameters needed to make it + * scan the mail input to find the mail recipient; consult your mailer + * documentation. + * + * Postfix users must use the compatible sendmail utility provided with + * it. This one usually needs no parameters on the command-line. Most + * sendmail applications (or replacements of it) require the -t option + * to be used. */ - object_class = "anopeUser"; + sendmailpath = "/usr/sbin/sendmail -t" /* - * The attribute value used for account names. + * This is the e-mail address from which all the e-mails are to be sent from. + * It should really exist. */ - username_attribute = "uid" + sendfrom = "services@localhost.net" /* - * The attribute value used for email addresses. + * If set, SENDPASS and RESETPASS will be restricted to IRC operators. * This directive is optional. + * + * WARNING: If you choose to not enable this option, you should limit the + * number of processes that the services user can have at a time (you can + * create a special user for this; remember to NEVER launch Services as + * root). */ - email_attribute = "email" - - /* - * The attribute value used for passwords. - * Used when registering new accounts in LDAP. - */ - password_attribute = "userPassword" + restrict = yes /* - * Enable to have this module disable /nickserv register. + * This controls the minimum amount of time a user must wait before sending + * another e-mail after they have sent one. It also controls the minimum time + * a user must wait before they can receive another e-mail. + * + * This feature prevents users from being mail bombed using Services and + * it is highly recommended that it be used. + * + * This directive is optional, but highly recommended. */ - disable_ns_register = false + delay = 5m /* - * The reason to give the users who try to /ns register if - * disable_ns_register is enabled. + * If set, Services will not attempt to put quotes around the TO: fields + * in e-mails. + * + * This directive is optional, and as far as we know, it's only needed + * if you are using ESMTP or QMail to send out e-mails. */ - #disable_reason = "To register on this network visit http://some.misconfigured.site/register" + #dontquoteaddresses = yes } /* - * m_ldap_oper - * - * This module dynamically ties users to Anope opertypes when they identify - * via LDAP group membership. Requires m_ldap. + * [OPTIONAL] DNS Config * - * Note that this doesn't give the user privileges on the IRCd, only in Services. + * This section is used to configure DNS. + * At this time DNS is only used by a few modules (m_dnsbl) + * and is not required by the core to function. */ -#module { name = "m_ldap_oper" } -m_ldap_oper +dns { - /* - * An optional binddn to use when searching for groups. - * %a is replaced with the account name of the user. - */ - #binddn = "cn=Manager,dc=anope,dc=org" - - /* - * An optional password to bind with. - */ - #password = "secret" - - /* - * The base DN where the groups are. - */ - basedn = "ou=groups,dc=anope,dc=org" - - /* - * The filter to use when searching for users. - * %a is replaced with the account name of the user. + /* + * The nameserver to use for resolving hostnames, must be an IP or a resolver configuration file. + * The below should work fine on all unix like systems. Windows users will have to find their nameservers + * from ipconfig /all and put the IP here */ - filter = "(member=uid=%a,ou=users,dc=anope,dc=org)" + nameserver = "/etc/resolv.conf" + #nameserver = "127.0.0.1" /* - * The attribute of the group that is the name of the opertype. - * The cn attribute should match a known opertype in the config. + * How long to wait in seconds before a DNS query has timed out */ - opertype_attribute = "cn" + timeout = 5 } /* - * m_mysql + * [REQUIRED] Encryption modules. * - * This module allows other modules (db_mysql/db_mysql_live) to use MySQL. - * Be sure you have imported the table schema with mydbgen before - * trying to use MySQL - */ -#module { name = "m_mysql" } -mysql -{ - database = "anope" - server = "127.0.0.1" - username = "anope" - password = "mypassword" - port = 3306 -} - -/* - * m_ssl + * The encryption modules are used when dealing with passwords. This determines how + * the passwords are stored in the databases, and does not add any security as + * far as transmitting passwords over the network goes. + * + * Without any encryption modules, passwords will be stored in plain text, allowing + * for passwords to be recovered later but isn't secure therefore is not recommended. + * + * The other encryption modules use one-way encryption, so the passwords can not + * be recovered later if those are used. * - * This module uses SSL to connect to the uplink server(s) - */ -module { name = "m_ssl" } - -/* - * m_statusupdate + * NOTE: enc_old is Anope's previous (broken) MD5 implementation, if your databases + * were made using that module, continue to use it and do not use enc_md5. * - * This module automatically updates users status on channels when the - * channel's access list is modified. - */ -module { name = "m_statusupdate" } - -/* - * m_xmlrpc + * NOTE: enc_sha1 relies on how the OS stores 2+ byte data internally, and is + * potentially broken when moving between 2 different OSes, such as moving from + * Linux to Windows. It is recommended that you use enc_sha256 instead if you want + * to use an SHA-based encryption. If you choose to do so, it is also recommended + * that you first try to get everyone's passwords converted to enc_sha256 before + * switching OSes by placing enc_sha256 at the beginning of the list. * - * Allows remote applications (websites) to execute queries in real time to retrieve data from Anope. - * By itself this module does nothing, but allows other modules (m_xmlrpc_main) to receive and send XMLRPC queries. + * The first encryption module loaded is the primary encryption module. All new passwords are + * encrypted by this module. Old passwords stored in another encryption method are + * automatically re-encrypted by the primary encryption module on next identify. */ -#module { name = "m_xmlrpc" } -m_xmlrpc -{ - /* IP to listen on */ - bindip = "127.0.0.1" - /* Port to listen on */ - port = 26673 - /* Enable for IPv6 */ - ipv6 = no - /* If enabled, requires m_ssl to be loaded */ - ssl = no - /* IPs allowed to connect (separate with spaces), this should be secured. We also recommend you firewall this - * with an outside program to increase security. - */ - allowed = "127.0.0.0/24" -} +module { name = "enc_md5" } +#module { name = "enc_sha1" } +#module { name = "enc_sha256" } /* - * m_xmlrpc_main - * - * Adds the main XMLRPC core functions. - * Requires m_xmlrpc. + * When using enc_none, passwords will be stored without encryption in plain + * text, allowing for passwords to be recovered later. This isn't secure therefore + * is not recommended. */ -#module { name = "m_xmlrpc_main" } +#module { name = "enc_none" } /* - * ns_maxemail - * - * Limits how many times the same email address may be used in Anope - * to register accounts. + * enc_old is Anope's previous (broken) MD5 implementation, if your databases + * were made using that module, load it here to allow conversion to the primary + * encryption method. */ -module { name = "ns_maxemail" } -ns_maxemail -{ - /* - * The limit to how many registered nicks can use the same e-mail address. If set to 0 or left - * commented, there will be no limit enforced when registering new accounts or using - * /msg NickServ SET EMAIL. - */ - #maxemails = 1 -} +#module { name = "enc_old" } /* - * ns_set_misc + * [OPTIONAL] Additional includes * - * Allows you to create misc /nickserv set commands, and have the data - * show up in /nickserv info + * You can include additional configuration files here. + * You may also include executable files, which will be executed and + * the output from it will be included into your configuration. */ -module { name = "ns_set_misc" } -ns_set_misc -{ - name = "OINFO" - desc = "Associate oper only information to this nick" - privileged = yes -} -ns_set_misc + +/* Include core commands */ +include { - name = "URL" - desc = "Associate a URL with the nick" + type = "file" + name = "commands.example.conf" } -ns_set_misc + +/* Extra (optional) modules */ +include { - name = "ICQ" - desc = "Associate an ICQ number with the nick" + type = "file" + name = "modules.example.conf" } - /* - * os_defcon - * - * Allows you to set services in defcon mode, which can be used to restrict services access - * during bot attacks. - */ -#module { "os_defcon" } -os_defcon +include { - /* - * Default DefCon level (1-5) to use when starting Services up. Level 5 constitutes normal operation - * while level 1 constitutes the most restrictive operation. If this setting is left out or set to - * 0, DefCon will be disabled and the rest of this block will be ignored. - */ - #defaultlevel = 5 - - /* - * The following 4 directives define what operations will take place when DefCon is set to levels - * 1 through 4. Each level is a list that must be separated by spaces. - * - * The following operations can be defined at each level: - * - nonewchannels: Disables registering new channels - * - nonewnicks: Disables registering new nicks - * - nomlockchanges: Disables changing MLOCK on registered channels - * - forcechanmodes: Forces all channels to have the modes given in the later chanmodes directive - * - reducedsessions: Reduces the session limit to the value given in the later sessionlimit directive - * - nonewclients: KILL any new clients trying to connect - * - operonly: Services will ignore all non-IRCops - * - silentoperonly: Services will silently ignore all non-IRCops - * - akillnewclients: AKILL any new clients trying to connect - * - nonewmemos: No new memos will be sent to block MemoServ attacks - */ - level4 = "nonewchannels nonewnicks nomlockchanges reducedsessions" - level3 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions" - level2 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly" - level1 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly akillnewclients" - - /* - * New session limit to use when a DefCon level is using "reduced" session limiting. - */ - #sessionlimit = 2 - - /* - * Length of time to add an AKILL for when DefCon is preventing new clients from connecting to the - * network. - */ - #akillexpire = 5m - - /* - * The channel modes to set on all channels when the DefCon channel mode system is in use. - * - * Note 1: Choose these modes carefully, because when DefCon switches to a level which does NOT have - * the mode setting selected, Services will set the reverse on all channels, e.g. if this setting - * is +RN when DefCon is used, all channels will be set to +RN, when DefCon is removed, all - * channels will be set to -RN. You don't want to set this to +k for example, because when DefCon - * is removed all channels with -k. - * - * Note 2: MLOCKed modes will not be lost. - */ - #chanmodes = "+R" - - /* - * This value can be used to automatically return the network to DefCon level 5 after the specified - * time period, just in case any IRC Operator forgets to remove a DefCon setting. - * - * This directive is optional. - */ - #timeout = 15m - - /* - * If set, Services will send a global message on DefCon level changes. - * - * This directive is optional. - */ - #globalondefcon = yes - - /* - * If set, Services will send the global message defined in the message directive on DefCon level - * changes. - * - * This directive is optional. - */ - #globalondefconmore = yes - - /* - * Defines the message that will be sent on DefCon level changes when globalondefconmore is set. - * - * This directive is required only when globalondefconmore is set. - */ - #message = "Put your message to send your users here. Dont forget to uncomment globalondefconmore" - - /* - * Defines the message that will be sent when DefCon is returned to level 5. This directive is optional, - * and will also override globalondefcon and globalondefconmore when set. - */ - #offmessage = "Services are now back to normal, sorry for any inconvenience" - - /* - * Defines the reason to use when clients are KILLed or AKILLed from the network while the proper - * DefCon operation is in effect. - */ - #akillreason = "This network is currently not accepting connections, please try again later" + type = "executable" + name = "/usr/bin/wget -q -O - http://some.miconfigured.network.com/services.conf" } +*/ + diff --git a/data/modules.example.conf b/data/modules.example.conf new file mode 100644 index 000000000..51f9f32f9 --- /dev/null +++ b/data/modules.example.conf @@ -0,0 +1,528 @@ + +/* + * [OPTIONAL] Non-Core Modules + * + * The following blocks are used to load all non-core modules, including 3rd-party modules. + * Modules can be prevented from loading by commenting out the line, other modules can be added by + * adding a module block. These modules will be loaded prior to Services connecting to your network. + */ + +/* + * cs_appendtopic + * + * Adds the APPENDTOPIC command to ChanServ, which allows users to easially append text to + * the end of existing channel topics. + */ +module { name = "cs_appendtopic" } +command { service = "ChanServ"; name = "APPENDTOPIC"; command = "chanserv/appendtopic"; } + +/* + * cs_enforce + * + * Adds the ENFORCE commad to ChanServ, which allows enforcing various channel settings like + * SECUREOPS and RESTRICTED. + */ +module { name = "cs_enforce" } +command { service = "ChanServ"; name = "ENFORCE"; command = "chanserv/enforce"; } + +/* + * cs_entrymsg + * + * Allows you to set entry messages on your channel, which are shown to anyone + * who joins. + */ +module { name = "cs_entrymsg" } +command { service = "ChanServ"; name = "ENTRYMSG"; command = "chanserv/entrymsg"; } +cs_entrymsg +{ + /* The maximum number of entrymsgs allowed per channel. If not set, defaults to 5. */ + maxentries = 5 +} + +/* + * cs_set_misc + * + * Allows you to create misc /chanserv set commands, and have the data + * show up in /chanserv info + */ +module { name = "cs_set_misc" } +cs_set_misc +{ + /* The name of the command */ + name = "OINFO" + /* A short description of the command */ + desc = "Associate oper only information to this channel" + /* Set to yes if only opers and privileged users can set it and see it */ + privileged = yes +} +cs_set_misc +{ + name = "URL" + desc = "Associate a URL with the channel" +} +cs_set_misc +{ + name = "EMAIL" + desc = "Associate an EMail with the channel" +} + +/* + * db_plain + * + * This is the default flatfile database format. You must have at least one database + * module loaded or Anope will not save databases! + */ +module { name = "db_plain" } +db_plain +{ + /* + * The database db_plain should use + */ + database = "anope.db" +} + +/* + * db_mysql and db_mysql_live + * + * Enables (live) MySQL support. + * + * The db_mysql_live module is an extension to db_mysql, and should only be used if + * db_mysql is being used. This module pulls data in real time from SQL as it is + * requested by the core as a result of someone executing commands. + * + * This effectively allows you to edit your database and have it be immediately + * reflected back in Anope. + * + * For information on how to make db_mysql_live use asynchronous queries see + * m_async_commands. + * + * At this time db_mysql_live only supports pulling data in real time from the three + * main tables: anope_cs_info, anope_ns_alias, and anope_ns_core. + */ +#module { name = "db_mysql" } +#module { name = "db_mysql_live" } + +/* + * hs_request + * + * Allows users to request vhosts which opers may then view, accept or deny + */ +module { name = "hs_request" } +command { service = "HostServ"; name = "REQUEST"; command = "hostserv/request"; } +command { service = "HostServ"; name = "ACTIVATE"; command = "hostserv/active"; } +command { service = "HostServ"; name = "REJECT"; command = "hostserv/reject"; } +command { service = "HostServ"; name = "WAITING"; command = "hostserv/waiting"; } +hs_request +{ + /* + * If set, Services will send a memo to the user requesting a vHost when it's been + * approved or rejected. + */ + #memouser = yes + + /* + * If set, Services will send a memo to all Services staff when a new vHost is requested. + */ + #memooper = yes +} + +/* + * m_async_commands + * + * Threads for each command executed by users. You should + * only load this if you are using a module designed to work with this. + * + * If this is loaded with db_mysql_live then Anope will support + * processing multiple commands at once which will negate the "lag" + * issues caused from the overhead of SQL queries by db_mysql_live. + * + * Note that this module is currently EXPERIMENTAL and you should report + * any bugs you find. + */ +#module { name = "m_async_commands" } + +/* m_dnsbl + * + * Allows configurable DNS blacklists to check connecting users against. If a user + * is found on the blacklist they will be immediately banned. This is a crucial module + * to prevent bot attacks. + */ +module { name = "m_dnsbl" } +m_dnsbl +{ + /* + * If set, Services will check clients against the DNSBLs when services connect to its uplink. + * This is not recommended, and on large networks will open a very large amount of DNS queries. + * Whilst services are not drastically affected by this, your nameserver/DNSBL might care. + */ + check_on_connect = no + + /* + * If set, Services will check clients when coming back from a netsplit. This can cause a large number + * of DNS queries open at once. Whilst services are not drastically affected by this, your nameserver/DNSBL + * might care. + */ + check_on_netburst = no + + /* + * If set, OperServ will add clients found in the DNSBL to the akill list. Without it, OperServ simply sends + * a timed G/K-line to the IRCd and forgets about it. Can be useful if your akill list is being fill up by bots. + */ + add_to_akill = yes +} +blacklist +{ + /* Name of the blacklist */ + name = "rbl.efnetrbl.org" + + /* How long to set the ban for */ + time = 4h + + /* Reason for akill. + * %n is the nick of the user + * %u is the ident/username of the user + * %g is the realname of the user + * %h is the hostname of the user + * %i is the IP of the user + * %r is the reason (configured below). Will be nothing if not configured. + * %N is the network name set in networkinfo:networkname + */ + reason = "You are listed in the efnet RBL, visit http://rbl.efnetrbl.org/?i=%i for info" + + /* Replies to ban and their reason. If this is totally ommited all replies get banned */ + 1 = "Open Proxy" + /* Don't ban for result 2 or 3 */ + #2 = "spamtrap666" + #3 = "spamtrap50" + 4 = "TOR" + 5 = "Drones / Flooding" +} +blacklist +{ + name = "dnsbl.dronebl.org" + time = 4h + reason = "You have a host listed in the DroneBL. For more information, visit http://dronebl.org/lookup_branded.do?ip=%i&network=%N" +} + +/* m_helpchan + * + * Gives users who are op in the specified help channel usermode +h (helpop). + */ +#module { name = "m_helpchan" } +m_helpchan +{ + helpchannel = "#help" +} + +/* + * m_ldap + * + * This module allows other modules to use LDAP. By itself, this module does nothing useful. + */ +#module { name = "m_ldap" } +ldap +{ + server = "ldap://127.0.0.1" + port = 389 + admin_binddn = "cn=Manager,dc=anope,dc=org" + admin_password = "secret" +} + +/* + * m_ldap_authentication + * + * This module allows many commands such as IDENTIFY, RELEASE, RECOVER, GHOST, etc. use + * LDAP to authenticate users. Requires m_ldap. +*/ +#module { name = "m_ldap_authentication" } +m_ldap_authentication +{ + /* + * The distinguished name we should bind to when a user tries to identify. + */ + binddn = "ou=users,dc=anope,dc=org" + + /* + * The object class used by LDAP to store user account information. + * Used for adding new users to LDAP if disable_ns_register is false + */ + object_class = "anopeUser" + + /* + * The attribute value used for account names. + */ + username_attribute = "uid" + + /* + * The attribute value used for email addresses. + * This directive is optional. + */ + email_attribute = "email" + + /* + * The attribute value used for passwords. + * Used when registering new accounts in LDAP. + */ + password_attribute = "userPassword" + + /* + * Enable to have this module disable /nickserv register. + */ + disable_ns_register = false + + /* + * The reason to give the users who try to /ns register if + * disable_ns_register is enabled. + */ + #disable_reason = "To register on this network visit http://some.misconfigured.site/register" +} + +/* + * m_ldap_oper + * + * This module dynamically ties users to Anope opertypes when they identify + * via LDAP group membership. Requires m_ldap. + * + * Note that this doesn't give the user privileges on the IRCd, only in Services. + */ +#module { name = "m_ldap_oper" } +m_ldap_oper +{ + /* + * An optional binddn to use when searching for groups. + * %a is replaced with the account name of the user. + */ + #binddn = "cn=Manager,dc=anope,dc=org" + + /* + * An optional password to bind with. + */ + #password = "secret" + + /* + * The base DN where the groups are. + */ + basedn = "ou=groups,dc=anope,dc=org" + + /* + * The filter to use when searching for users. + * %a is replaced with the account name of the user. + */ + filter = "(member=uid=%a,ou=users,dc=anope,dc=org)" + + /* + * The attribute of the group that is the name of the opertype. + * The cn attribute should match a known opertype in the config. + */ + opertype_attribute = "cn" +} + +/* + * m_mysql + * + * This module allows other modules (db_mysql/db_mysql_live) to use MySQL. + * Be sure you have imported the table schema with mydbgen before + * trying to use MySQL + */ +#module { name = "m_mysql" } +mysql +{ + database = "anope" + server = "127.0.0.1" + username = "anope" + password = "mypassword" + port = 3306 +} + +/* + * m_ssl + * + * This module uses SSL to connect to the uplink server(s) + */ +module { name = "m_ssl" } + +/* + * m_statusupdate + * + * This module automatically updates users status on channels when the + * channel's access list is modified. + */ +module { name = "m_statusupdate" } + +/* + * m_xmlrpc + * + * Allows remote applications (websites) to execute queries in real time to retrieve data from Anope. + * By itself this module does nothing, but allows other modules (m_xmlrpc_main) to receive and send XMLRPC queries. + */ +#module { name = "m_xmlrpc" } +m_xmlrpc +{ + /* IP to listen on */ + bindip = "127.0.0.1" + /* Port to listen on */ + port = 26673 + /* Enable for IPv6 */ + ipv6 = no + /* If enabled, requires m_ssl to be loaded */ + ssl = no + /* IPs allowed to connect (separate with spaces), this should be secured. We also recommend you firewall this + * with an outside program to increase security. + */ + allowed = "127.0.0.0/24" +} + +/* + * m_xmlrpc_main + * + * Adds the main XMLRPC core functions. + * Requires m_xmlrpc. + */ +#module { name = "m_xmlrpc_main" } + +/* + * ns_maxemail + * + * Limits how many times the same email address may be used in Anope + * to register accounts. + */ +module { name = "ns_maxemail" } +ns_maxemail +{ + /* + * The limit to how many registered nicks can use the same e-mail address. If set to 0 or left + * commented, there will be no limit enforced when registering new accounts or using + * /msg NickServ SET EMAIL. + */ + #maxemails = 1 +} + +/* + * ns_set_misc + * + * Allows you to create misc /nickserv set commands, and have the data + * show up in /nickserv info + */ +module { name = "ns_set_misc" } +ns_set_misc +{ + name = "OINFO" + desc = "Associate oper only information to this nick" + privileged = yes +} +ns_set_misc +{ + name = "URL" + desc = "Associate a URL with the nick" +} +ns_set_misc +{ + name = "ICQ" + desc = "Associate an ICQ number with the nick" +} + +/* + * os_defcon + * + * Allows you to set services in defcon mode, which can be used to restrict services access + * during bot attacks. + */ +#module { name = "os_defcon" } +command { service = "OperServ"; name = "DEFCON"; command = "operserv/defcon"; } +defcon +{ + /* + * Default DefCon level (1-5) to use when starting Services up. Level 5 constitutes normal operation + * while level 1 constitutes the most restrictive operation. If this setting is left out or set to + * 0, DefCon will be disabled and the rest of this block will be ignored. + */ + #defaultlevel = 5 + + /* + * The following 4 directives define what operations will take place when DefCon is set to levels + * 1 through 4. Each level is a list that must be separated by spaces. + * + * The following operations can be defined at each level: + * - nonewchannels: Disables registering new channels + * - nonewnicks: Disables registering new nicks + * - nomlockchanges: Disables changing MLOCK on registered channels + * - forcechanmodes: Forces all channels to have the modes given in the later chanmodes directive + * - reducedsessions: Reduces the session limit to the value given in the later sessionlimit directive + * - nonewclients: KILL any new clients trying to connect + * - operonly: Services will ignore all non-IRCops + * - silentoperonly: Services will silently ignore all non-IRCops + * - akillnewclients: AKILL any new clients trying to connect + * - nonewmemos: No new memos will be sent to block MemoServ attacks + */ + level4 = "nonewchannels nonewnicks nomlockchanges reducedsessions" + level3 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions" + level2 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly" + level1 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly akillnewclients" + + /* + * New session limit to use when a DefCon level is using "reduced" session limiting. + */ + #sessionlimit = 2 + + /* + * Length of time to add an AKILL for when DefCon is preventing new clients from connecting to the + * network. + */ + #akillexpire = 5m + + /* + * The channel modes to set on all channels when the DefCon channel mode system is in use. + * + * Note 1: Choose these modes carefully, because when DefCon switches to a level which does NOT have + * the mode setting selected, Services will set the reverse on all channels, e.g. if this setting + * is +RN when DefCon is used, all channels will be set to +RN, when DefCon is removed, all + * channels will be set to -RN. You don't want to set this to +k for example, because when DefCon + * is removed all channels with -k. + * + * Note 2: MLOCKed modes will not be lost. + */ + #chanmodes = "+R" + + /* + * This value can be used to automatically return the network to DefCon level 5 after the specified + * time period, just in case any IRC Operator forgets to remove a DefCon setting. + * + * This directive is optional. + */ + #timeout = 15m + + /* + * If set, Services will send a global message on DefCon level changes. + * + * This directive is optional. + */ + #globalondefcon = yes + + /* + * If set, Services will send the global message defined in the message directive on DefCon level + * changes. + * + * This directive is optional. + */ + #globalondefconmore = yes + + /* + * Defines the message that will be sent on DefCon level changes when globalondefconmore is set. + * + * This directive is required only when globalondefconmore is set. + */ + #message = "Put your message to send your users here. Dont forget to uncomment globalondefconmore" + + /* + * Defines the message that will be sent when DefCon is returned to level 5. This directive is optional, + * and will also override globalondefcon and globalondefconmore when set. + */ + #offmessage = "Services are now back to normal, sorry for any inconvenience" + + /* + * Defines the reason to use when clients are KILLed or AKILLed from the network while the proper + * DefCon operation is in effect. + */ + #akillreason = "This network is currently not accepting connections, please try again later" +} + diff --git a/data/mysql/tables.sql b/data/mysql/tables.sql index 13493279b..32bfcde35 100644 --- a/data/mysql/tables.sql +++ b/data/mysql/tables.sql @@ -301,31 +301,12 @@ CREATE TABLE IF NOT EXISTS `anope_ns_core_metadata` ( -- -------------------------------------------------------- -- --- Table structure for table `anope_os_akills` --- - -CREATE TABLE IF NOT EXISTS `anope_os_akills` ( - `user` varchar(255) NOT NULL, - `host` varchar(255) NOT NULL, - `xby` text NOT NULL, - `reason` text NOT NULL, - `seton` int(10) unsigned NOT NULL DEFAULT '0', - `expire` int(10) unsigned NOT NULL DEFAULT '0' -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- -- Table structure for table `anope_os_core` -- CREATE TABLE IF NOT EXISTS `anope_os_core` ( `maxusercnt` int(11) NOT NULL DEFAULT '0', `maxusertime` int(10) unsigned NOT NULL DEFAULT '0', - `akills_count` int(11) NOT NULL DEFAULT '0', - `snlines_count` int(11) NOT NULL DEFAULT '0', - `sqlines_count` int(11) NOT NULL DEFAULT '0', - `szlines_count` int(11) NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -------------------------------------------------------- @@ -350,7 +331,7 @@ CREATE TABLE IF NOT EXISTS `anope_os_exceptions` ( -- CREATE TABLE IF NOT EXISTS `anope_os_xlines` ( - `type` varchar(20) NOT NULL, + `type` varchar(1) NOT NULL, `mask` varchar(255) NOT NULL, `xby` text NOT NULL, `reason` text NOT NULL, diff --git a/docs/Changes.conf b/docs/Changes.conf index 31d42a5b2..fdbd2f608 100644 --- a/docs/Changes.conf +++ b/docs/Changes.conf @@ -1,30 +1,6 @@ Anope Version 1.9.5 ------------------- -** ADDED CONFIGURATION DIRECTIVES ** -global:modules -global:globaloncycle -global:globaloncycledown -global:globaloncycleup -global:anonymousglobal -operserv:modules added os_forbid - -** MODIFIED CONFIGURATION DIRECTIVES ** -opertype:permissions added memoserv/no-limit -operserv:modules removed os_global -operserv:modules renamed os_staff to os_oper - -** DELETED CONFIGURATION DIRECTIVES ** -memoserv:notifyall -options:globaloncycle -options:globaloncycledown -options:globaloncycleup -options:anonymousglobal -options:socketengine -options:encryption -options:database -serverinfo:protocol -chanserv:modules removed cs_forbid -nickserv:modules removed ns_forbid +Don't even try it, get a new config and start over. Anope Version 1.9.4 ------------------- diff --git a/include/bots.h b/include/bots.h index 7316f074e..7508e4091 100644 --- a/include/bots.h +++ b/include/bots.h @@ -8,12 +8,12 @@ #ifndef BOTS_H #define BOTS_H -#include "commands.h" - class BotInfo; extern CoreExport Anope::insensitive_map<BotInfo *> BotListByNick; extern CoreExport Anope::map<BotInfo *> BotListByUID; +typedef Anope::insensitive_map<BotInfo *> botinfo_map; +typedef Anope::insensitive_map<Anope::string> command_map; /** Flags settable on a bot */ @@ -25,11 +25,13 @@ enum BotFlag BI_CORE, /* This bot can only be assigned by IRCops */ BI_PRIVATE, + /* This bot is defined in the config */ + BI_CONF, BI_END }; -static const Anope::string BotFlagString[] = { "BEGIN", "CORE", "PRIVATE", "" }; +static const Anope::string BotFlagString[] = { "BEGIN", "CORE", "PRIVATE", "CONF", "" }; class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END> { @@ -37,7 +39,7 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END> uint32 chancount; time_t created; /* Birth date ;) */ time_t lastmsg; /* Last time we said something */ - CommandMap Commands; /* Commands on this bot */ + command_map commands; /* Commands, actual name to service name */ /** Create a new bot. * @param nick The nickname to assign to the bot. @@ -51,6 +53,8 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END> */ virtual ~BotInfo(); + void GenerateUID(); + /** Change the nickname for the bot. * @param newnick The nick to change to */ diff --git a/include/commands.h b/include/commands.h index 89fd1436c..0ee9af226 100644 --- a/include/commands.h +++ b/include/commands.h @@ -18,36 +18,15 @@ class Module; class BotInfo; class Command; -typedef std::map<Anope::string, Command *, std::less<ci::string> > CommandMap; - -/** The return value from commands. - */ -enum CommandReturn -{ - MOD_CONT, - MOD_STOP -}; - -extern CoreExport Command *FindCommand(BotInfo *bi, const Anope::string &cmd); -extern CoreExport void mod_help_cmd(BotInfo *bi, User *u, ChannelInfo *ci, const Anope::string &cmd); -extern CoreExport void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, const Anope::string &message); -extern CoreExport void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope::string &command, const Anope::string &message); - enum CommandFlag { CFLAG_ALLOW_UNREGISTERED, - CFLAG_ALLOW_SUSPENDED, - CFLAG_ALLOW_UNREGISTEREDCHANNEL, - CFLAG_STRIP_CHANNEL, - CFLAG_DISABLE_FANTASY + CFLAG_STRIP_CHANNEL }; const Anope::string CommandFlagStrings[] = { "CFLAG_ALLOW_UNREGISTERED", - "CFLAG_ALLOW_SUSPENDED", - "CFLAG_ALLOW_UNREGISTEREDCHANNEL", "CFLAG_STRIP_CHANNEL", - "CFLAG_DISABLE_FANTASY", "" }; @@ -56,14 +35,14 @@ struct CoreExport CommandSource { /* User executing the command */ User *u; - /* Channel (if applicable) */ - ChannelInfo *ci; + /* Channel the command was executed on (fantasy) */ + Channel *c; /* The service this command is on */ BotInfo *owner; /* The service the reply should come from, *not* necessarily the service the command is on */ BotInfo *service; - /* Whether or not this was a fantasy command */ - bool fantasy; + /* The actual name of the command being executed */ + Anope::string command; std::list<Anope::string> reply; @@ -75,38 +54,40 @@ struct CoreExport CommandSource /** Every services command is a class, inheriting from Command. */ -class CoreExport Command : public Flags<CommandFlag>, public Base +class CoreExport Command : public Service, public Flags<CommandFlag> { Anope::string desc; + std::vector<Anope::string> syntax; public: /* Maximum paramaters accepted by this command */ size_t MaxParams; /* Minimum parameters required to use this command */ size_t MinParams; - /* Command name */ - Anope::string name; /* Permission needed to use this comand */ Anope::string permission; /* Module which owns us */ Module *module; - /* Service this command is on */ - BotInfo *service; /** Create a new command. + * @param owner The owner of the command * @param sname The command name * @param min_params The minimum number of parameters the parser will require to execute this command * @param max_params The maximum number of parameters the parser will create, after max_params, all will be combined into the last argument. * NOTE: If max_params is not set (default), there is no limit to the max number of params. */ - Command(const Anope::string &sname, size_t min_params, size_t max_params = 0, const Anope::string &spermission = ""); + Command(Module *owner, const Anope::string &sname, size_t min_params, size_t max_params = 0, const Anope::string &spermission = ""); virtual ~Command(); protected: void SetDesc(const Anope::string &d); + void ClearSyntax(); + void SetSyntax(const Anope::string &s); + void SendSyntax(CommandSource &); + void SendSyntax(CommandSource &, const Anope::string &syntax); public: /** Get the command description * @return The commands description @@ -117,7 +98,7 @@ class CoreExport Command : public Flags<CommandFlag>, public Base * @param source The source * @param params Command parameters */ - virtual CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; + virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; /** Called when HELP is requsted for the client this command is on. * @param source The source @@ -141,23 +122,6 @@ class CoreExport Command : public Flags<CommandFlag>, public Base * @param reststr The permission required to successfully execute this command */ void SetPermission(const Anope::string &reststr); - - /** Add a subcommand to this command - * @param creator The creator of the subcommand - * @param c The command - */ - virtual bool AddSubcommand(Module *creator, Command *c); - - /** Delete a subcommand from this command - * @param c The command - */ - virtual bool DelSubcommand(Command *c); - - /** Find a subcommand - * @param name The subcommand name - * @return The subcommand - */ - virtual Command *FindSubcommand(const Anope::string &subcommand); }; #endif // COMMANDS_H diff --git a/include/config.h b/include/config.h index 07815466e..84ed2f8d3 100644 --- a/include/config.h +++ b/include/config.h @@ -342,7 +342,7 @@ class CoreExport ServerConfig /** Below here is a list of variables which contain the config files values */ - /* Host to connect to **/ + /* Host to bind to */ Anope::string LocalHost; /* List of uplink servers to try and connect to */ std::vector<Uplink *> Uplinks; @@ -351,10 +351,6 @@ class CoreExport ServerConfig Anope::string ServerName; /* Our servers description */ Anope::string ServerDesc; - /* The username/ident of services clients */ - Anope::string ServiceUser; - /* The hostname if services clients */ - Anope::string ServiceHost; /* Name of the network were on */ Anope::string NetworkName; @@ -368,49 +364,19 @@ class CoreExport ServerConfig /* Max length of passwords */ unsigned PassLen; - /* NickServ Name */ - Anope::string s_NickServ; - /* ChanServ Name */ - Anope::string s_ChanServ; - /* MemoServ Name */ - Anope::string s_MemoServ; - /* BotServ Name */ - Anope::string s_BotServ; - /* OperServ name */ - Anope::string s_OperServ; - /* Global name */ - Anope::string s_Global; - /* NickServs realname */ - Anope::string desc_NickServ; - /* ChanServ realname */ - Anope::string desc_ChanServ; - /* MemoServ realname */ - Anope::string desc_MemoServ; - /* BotServ realname */ - Anope::string desc_BotServ; - /* OperServ realname */ - Anope::string desc_OperServ; - /* Global realname */ - Anope::string desc_Global; - - /* HostServ Name */ - Anope::string s_HostServ; - /* HostServ realname */ - Anope::string desc_HostServ; - /* Core HostServ modules */ - Anope::string HostCoreModules; - /* Filename for the PID file */ Anope::string PIDFilename; /* MOTD filename */ Anope::string MOTDFilename; - /* Core MemoServ Modules */ - Anope::string MemoCoreModules; - /* Core OperServ Modules */ - Anope::string OperCoreModules; - /* Core Global Modules */ - Anope::string GlobalCoreModules; + Anope::string BotServ; + Anope::string ChanServ; + Anope::string Global; + Anope::string HostServ; + Anope::string NickServ; + Anope::string OperServ; + Anope::string MemoServ; + /* True if its ok to not be able to save backs */ bool NoBackupOkay; /* Do password checking when new people register */ diff --git a/include/extern.h b/include/extern.h index 91312d1ab..18df923a8 100644 --- a/include/extern.h +++ b/include/extern.h @@ -99,7 +99,6 @@ E const char *translate(const char *string); E const char *translate(User *u, const char *string); E const char *translate(NickCore *nc, const char *string); E const char *anope_gettext(const char *lang, const char *string); -E void SyntaxError(CommandSource &source, const Anope::string &command, const Anope::string &message); /**** main.c ****/ diff --git a/include/language.h b/include/language.h index efddc0a34..f2b9bec7b 100644 --- a/include/language.h +++ b/include/language.h @@ -25,8 +25,7 @@ #define CHAN_X_SUSPENDED _("Channel %s is currently suspended.") #define CHAN_X_NOT_REGISTERED _("Channel \002%s\002 isn't registered.") #define CHAN_X_NOT_IN_USE _("Channel \002%s\002 doesn't exist.") -#define NICK_IDENTIFY_REQUIRED _("Password authentication required for that command.\n" \ - "Retry after typing \002%s%s IDENTIFY \037password\037\002.") +#define NICK_IDENTIFY_REQUIRED _("Password authentication required for that command.") #define MAIL_X_INVALID _("\002%s\002 is not a valid e-mail address.") #define NO_REASON _("No reason") #define UNKNOWN _("<unknown>") @@ -47,11 +46,6 @@ #define NICK_SET_DISABLED _("Sorry, nickname option setting is temporarily disabled.") #define NICK_SET_UNKNOWN_OPTION _("Unknown SET option \002%s%s\002.") #define NICK_SET_DISPLAY_CHANGED _("The new display is now \002%s\002.") -#define NICK_SASET_SYNTAX _("SASET \037nickname\037 \037option\037 \037parameters\037") -#define NICK_SASET_DISPLAY_INVALID _("The new display for \002%s\002 MUST be a nickname of the nickname group!") -#define NICK_SASET_PASSWORD_FAILED _("Sorry, couldn't change password for \002%s\002.") -#define NICK_SASET_PASSWORD_CHANGED _("Password for \002%s\002 changed.") -#define NICK_SASET_PASSWORD_CHANGED_TO _("Password for \002%s\002 changed to \002%s\002.") #define NICK_INFO_OPTIONS _(" Options: %s") #define NICK_LIST_SYNTAX _("LIST \037pattern\037") #define LIST_HEADER _("List of entries matching \002%s\002:") @@ -64,8 +58,6 @@ #define CHAN_REACHED_CHANNEL_LIMIT _("Sorry, you have already reached your limit of \002%d\002 channels.") #define CHAN_EXCEEDED_CHANNEL_LIMIT _("Sorry, you have already exceeded your limit of \002%d\002 channels.") #define CHAN_SYMBOL_REQUIRED _("Please use the symbol of \002#\002 when attempting to register") -#define CHAN_SASET_SYNTAX _("SASET \002channel\002 \037option\037 \037parameters\037") -#define CHAN_SET_SYNTAX _("SET \037channel\037 \037option\037 \037parameters\037") #define CHAN_SET_DISABLED _("Sorry, channel option setting is temporarily disabled.") #define CHAN_SETTING_CHANGED _("%s for %s set to %s.") #define CHAN_SETTING_UNSET _("%s for %s unset.") @@ -94,8 +86,7 @@ #define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.") #define MEMO_X_HAS_NO_NEW_MEMOS _("%s has no new memos.") #define BOT_DOES_NOT_EXIST _("Bot \002%s\002 does not exist.") -#define BOT_NOT_ASSIGNED _("You must assign a bot to the channel before using this command.\n" \ - "Type %s%s HELP ASSIGN for more information.") +#define BOT_NOT_ASSIGNED _("You must assign a bot to the channel before using this command.") #define BOT_NOT_ON_CHANNEL _("Bot is not on channel \002%s\002.") #define BOT_ASSIGN_READONLY _("Sorry, bot assignment is temporarily disabled.") #define ENABLED _("Enabled") diff --git a/include/logger.h b/include/logger.h index 2a11967b9..d012c4450 100644 --- a/include/logger.h +++ b/include/logger.h @@ -29,6 +29,8 @@ struct LogFile Anope::string GetName() const; }; +class Command; + class CoreExport Log { public: diff --git a/include/modes.h b/include/modes.h index ae89c7ab7..95452bb30 100644 --- a/include/modes.h +++ b/include/modes.h @@ -295,8 +295,6 @@ class CoreExport ChannelModeBan : public ChannelModeList { public: ChannelModeBan(ChannelModeName mName, char modeChar) : ChannelModeList(mName, modeChar) { } - - void OnAdd(Channel *chan, const Anope::string &mask); }; /** Channel mode +k (key) diff --git a/include/module.h b/include/module.h index 4e4c96607..6435f9b7f 100644 --- a/include/module.h +++ b/include/module.h @@ -2,7 +2,8 @@ #define MODULE_H #include "services.h" -#include "commands.h" #include "modules.h" +#include "oper.h" +#include "commands.h" #endif // MODULE_H diff --git a/include/modules.h b/include/modules.h index b9ed03664..2169513a8 100644 --- a/include/modules.h +++ b/include/modules.h @@ -17,7 +17,6 @@ #include <stdio.h> #include "timers.h" #include "hashcomp.h" -#include "commands.h" /* Cross OS compatibility macros */ #ifdef _WIN32 @@ -187,8 +186,9 @@ class Version int GetBuild() const; }; -/* Forward declaration of CallBack class for the Module class */ class CallBack; +class XLineManager; +class CommandSource; /** Every module in Anope is actually a class. */ @@ -270,22 +270,6 @@ class CoreExport Module : public Extensible */ Version GetVersion() const; - /** - * Add a module provided command to the given service. - * @param bi The service to add the command to - * @param c The command to add - * @return MOD_ERR_OK on successfully adding the command - */ - int AddCommand(BotInfo *bi, Command *c); - - /** - * Delete a command from the service given. - * @param bi The service to remove the command from - * @param c Thec command to delete - * @return returns MOD_ERR_OK on success - */ - int DelCommand(BotInfo *bi, Command *c); - /** Called when the ircd notifies that a user has been kicked from a channel. * @param c The channel the user has been kicked from. * @param target The user that has been kicked. @@ -330,15 +314,17 @@ class CoreExport Module : public Extensible */ virtual void OnUserNickChange(User *u, const Anope::string &oldnick) { } - /** Called immediatly when a user tries to run a command - * @param u The user - * @param bi The bot the command is being run from - * @param command The command - * @param message The parameters used for the command - * @param ci If a tanasy command, the channel the comman was used on - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it + /** Called when someone uses the generic/help command + * @param source Command source + * @param params Params */ - virtual EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) { return EVENT_CONTINUE; } + virtual void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) { } + + /** Called when someone uses the generic/help command + * @param source Command source + * @param params Params + */ + virtual void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) { } /** Called before a command is due to be executed. * @param source The source of the command @@ -346,7 +332,7 @@ class CoreExport Module : public Extensible * @param params The parameters the user is sending * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; } + virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { return EVENT_CONTINUE; } /** Called after a command has been executed. * @param source The source of the command @@ -445,6 +431,13 @@ class CoreExport Module : public Extensible */ virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) { } + /** Called when a user leaves a channel. + * From either parting, being kicked, or quitting/killed! + * @param u The user + * @param c The channel + */ + virtual void OnLeaveChannel(User *u, Channel *c) { } + /** Called before a user joins a channel * @param u The user * @param c The channel @@ -582,18 +575,6 @@ class CoreExport Module : public Extensible */ virtual void OnDefconLevel(int level) { } - /** Called before an akill is added - * @param ak The akill - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it - */ - virtual EventReturn OnAddAkill(XLine *ak) { return EVENT_CONTINUE; } - - /** Called before an akill is deleted - * @param u The user removing the akill - * @param ak The akill, can be NULL for all akills! - */ - virtual void OnDelAkill(User *u, XLine *ak) { } - /** Called after an exception has been added * @param ex The exception * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it @@ -607,18 +588,19 @@ class CoreExport Module : public Extensible virtual void OnExceptionDel(User *u, Exception *ex) { } /** Called before a XLine is added - * @param sx The XLine - * @param Type The type of XLine this is + * @param u The user adding the XLine + * @param x The XLine + * @param xlm The xline manager it was added to * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnAddXLine(XLine *x, XLineType Type) { return EVENT_CONTINUE; } + virtual EventReturn OnAddXLine(User *u, XLine *x, XLineManager *xlm) { return EVENT_CONTINUE; } /** Called before a XLine is deleted * @param u The user deleting the XLine - * @param sx The XLine, can be NULL for all XLines - * @param Type The type of XLine this is + * @param x The XLine, can be NULL for all XLines + * @param xlm The xline manager it was deleted from */ - virtual void OnDelXLine(User *u, XLine *x, XLineType Type) { } + virtual void OnDelXLine(User *u, XLine *x, XLineManager *xlm) { } /** Called when a user is checked for whether they are a services oper * @param u The user @@ -746,6 +728,14 @@ class CoreExport Module : public Extensible */ virtual void OnAkickDel(User *u, ChannelInfo *ci, AutoKick *ak) { } + /** Called after a user join a channel when we decide whether to kick them or not + * @param u The user + * @param ci The channel + * @param kick Set to true to kick + * @return EVENT_ALLOW to stop processing immediatly + */ + virtual EventReturn OnCheckKick(User *u, ChannelInfo *ci, bool &kick) { return EVENT_CONTINUE; } + /** Called when a user requests info for a channel * @param source The user requesting info * @param ci The channel the user is requesting info for @@ -877,7 +867,7 @@ class CoreExport Module : public Extensible * @param password The password * @return EVENT_ALLOW to allow the password, EVENT_STOP to stop processing completely */ - virtual EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; } + virtual EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; } /** Called when a user does /ns update * @param u The user @@ -1013,10 +1003,10 @@ class CoreExport Module : public Extensible /** Called when we receive a PRIVMSG for a registered channel we are in * @param u The source of the message - * @param ci The channel + * @param c The channel * @param msg The message */ - virtual void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) { } + virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg) { } /** Called when any object is deleted * @param b The object @@ -1041,7 +1031,7 @@ enum Implementation /* ChanServ */ I_OnChanForbidden, I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, I_OnAccessChange, I_OnAccessDel, I_OnAccessClear, I_OnLevelChange, I_OnChanRegistered, I_OnChanUnsuspend, I_OnDelChan, I_OnChannelCreate, - I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, + I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick, I_OnChanInfo, I_OnFindChan, /* BotServ */ @@ -1056,7 +1046,7 @@ enum Implementation /* Users */ I_OnUserConnect, I_OnUserNickChange, I_OnUserQuit, I_OnUserLogoff, I_OnPreJoinChannel, - I_OnJoinChannel, I_OnPrePartChannel, I_OnPartChannel, I_OnFingerprint, I_OnUserAway, + I_OnJoinChannel, I_OnPrePartChannel, I_OnPartChannel, I_OnLeaveChannel, I_OnFingerprint, I_OnUserAway, /* OperServ */ I_OnDefconLevel, I_OnAddAkill, I_OnDelAkill, I_OnExceptionAdd, I_OnExceptionDel, @@ -1070,8 +1060,8 @@ enum Implementation I_OnModuleLoad, I_OnModuleUnload, /* Other */ - I_OnReload, I_OnNewServer, I_OnPreServerConnect, I_OnServerConnect, I_OnPreUplinkSync, I_OnServerDisconnect, I_OnPreCommandRun, - I_OnPreCommand, I_OnPostCommand, I_OnRestart, I_OnShutdown, + I_OnReload, I_OnNewServer, I_OnPreServerConnect, I_OnServerConnect, I_OnPreUplinkSync, I_OnServerDisconnect, + I_OnPreHelp, I_OnPostHelp, I_OnPreCommand, I_OnPostCommand, I_OnRestart, I_OnShutdown, I_OnServerQuit, I_OnTopicUpdated, I_OnEncrypt, I_OnDecrypt, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, @@ -1218,6 +1208,11 @@ class CoreExport ModuleManager */ static Service *GetService(const Anope::string &name); + /** Get the existing service key names + * @return The keys + */ + static std::vector<Anope::string> GetServiceKeys(); + private: /** Call the module_delete function to safely delete the module * @param m the module to delete diff --git a/include/oper.h b/include/oper.h index c718ea5fb..57ce92f7c 100644 --- a/include/oper.h +++ b/include/oper.h @@ -10,17 +10,6 @@ #define OPER_H class XLineManager; -extern CoreExport XLineManager *SGLine; -extern CoreExport XLineManager *SZLine; -extern CoreExport XLineManager *SQLine; -extern CoreExport XLineManager *SNLine; - -enum XLineType -{ - X_SNLINE, - X_SQLINE, - X_SZLINE -}; class CoreExport XLine { @@ -40,24 +29,29 @@ class CoreExport XLine Anope::string GetHost() const; }; -class CoreExport XLineManager +class CoreExport XLineManager : public Service { - private: - /* List of XLine managers we check users against in XLineManager::CheckAll */ - static std::list<XLineManager *> XLineManagers; - + char type; protected: /* List of XLines in this XLineManager */ std::vector<XLine *> XLines; public: + /* List of XLine managers we check users against in XLineManager::CheckAll */ + static std::list<XLineManager *> XLineManagers; + /** Constructor */ - XLineManager(); + XLineManager(Module *creator, const Anope::string &name, char t); /** Destructor */ virtual ~XLineManager(); + /** The type of xline provided by this service + * @return The type + */ + const char &Type(); + /** Register a XLineManager, places it in XLineManagers for use in XLineManager::CheckAll * It is important XLineManagers are registered in the proper order. Eg, if you had one akilling * clients and one handing them free olines, you would want the akilling one first. This way if a client @@ -165,65 +159,4 @@ class CoreExport XLineManager virtual void Send(User *u, XLine *x) = 0; }; -/* This is for AKILLS */ -class SGLineManager : public XLineManager -{ - public: - XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); - - void Del(XLine *x); - - void OnMatch(User *u, XLine *x); - - void OnExpire(XLine *x); - - void Send(User *u, XLine *x); -}; - -class SNLineManager : public XLineManager -{ - public: - XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); - - void Del(XLine *x); - - void OnMatch(User *u, XLine *x); - - void OnExpire(XLine *x); - - void Send(User *u, XLine *x); - - XLine *Check(User *u); -}; - -class SQLineManager : public XLineManager -{ - public: - XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); - - void Del(XLine *x); - - void OnMatch(User *u, XLine *x); - - void OnExpire(XLine *x); - - void Send(User *u, XLine *x); - - static bool Check(Channel *c); -}; - -class SZLineManager : public XLineManager -{ - public: - XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); - - void Del(XLine *x); - - void OnMatch(User *u, XLine *x); - - void OnExpire(XLine *x); - - void Send(User *u, XLine *x); -}; - #endif // OPER_H diff --git a/include/services.h b/include/services.h index fdc78ff59..556e1d715 100644 --- a/include/services.h +++ b/include/services.h @@ -660,8 +660,6 @@ enum BotServFlag BS_DONTKICKVOICES, /* BotServ bot accepts fantasy commands */ BS_FANTASY, - /* BotServ bot sets modes etc instead of ChanServ */ - BS_SYMBIOSIS, /* BotServ should show greets */ BS_GREET, /* BotServ bots are not allowed to be in this channel */ @@ -696,7 +694,7 @@ enum BotServFlag }; const Anope::string BotServFlagStrings[] = { - "BEGIN", "DONTKICKOPS", "DONTKICKVOICES", "FANTASY", "SYMBIOSIS", "GREET", "NOBOT", + "BEGIN", "DONTKICKOPS", "DONTKICKVOICES", "FANTASY", "GREET", "NOBOT", "KICK_BOLDs", "KICK_COLORS", "KICK_REVERSES", "KICK_UNDERLINES", "KICK_BADWORDS", "KICK_CAPS", "KICK_FLOOD", "KICK_REPEAT", "KICK_ITALICS", "KICK_AMSGS", "MSG_PRIVMSG", "MSG_NOTICE", "MSG_NOTICEOPS", "" @@ -817,10 +815,10 @@ class IRCdMessage; struct Uplink; class ServerConfig; class ConfigurationFile; +class XLine; #include "extern.h" #include "language.h" -#include "oper.h" #include "mail.h" #include "servers.h" #include "logger.h" diff --git a/include/users.h b/include/users.h index fd6600326..d6a0866ee 100644 --- a/include/users.h +++ b/include/users.h @@ -77,7 +77,7 @@ class CoreExport User : public Extensible * @param shost The hostname of the user * @param suid The unique identifier of the user. */ - User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &suid); + User(const Anope::string &snick, const Anope::string &sident, const Anope::string &shost, const Anope::string &suid = ""); /** Destroy a user. */ diff --git a/modules/core/botserv.h b/modules/core/botserv.h index 5c707278a..5fa03f870 100644 --- a/modules/core/botserv.h +++ b/modules/core/botserv.h @@ -52,8 +52,6 @@ class BotServService : public Service public: BotServService(Module *m) : Service(m, "BotServ") { } - virtual BotInfo *Bot() = 0; - virtual UserData *GetUserData(User *u, Channel *c) = 0; virtual BanData *GetBanData(User *u, Channel *c) = 0; diff --git a/modules/core/bs_act.cpp b/modules/core/bs_act.cpp deleted file mode 100644 index d06fc1848..000000000 --- a/modules/core/bs_act.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "botserv.h" - -class CommandBSAct : public Command -{ - public: - CommandBSAct() : Command("ACT", 2, 2) - { - this->SetDesc(_("Makes the bot do the equivalent of a \"/me\" command")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - ChannelInfo *ci = source.ci; - Anope::string message = params[1]; - - if (!check_access(u, ci, CA_SAY)) - { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; - } - - if (!ci->bi) - { - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); - return MOD_CONT; - } - - if (!ci->c || !ci->c->FindUser(ci->bi)) - { - source.Reply(_(BOT_NOT_ON_CHANNEL), ci->name.c_str()); - return MOD_CONT; - } - - size_t i = 0; - while ((i = message.find(1)) && i != Anope::string::npos) - message.erase(i, 1); - - ircdproto->SendAction(ci->bi, ci->name, "%s", message.c_str()); - ci->bi->lastmsg = Anope::CurTime; - - // XXX Need to be able to find if someone is overriding this. - Log(LOG_COMMAND, u, this, ci) << message; - - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "ACT", _("ACT \037channel\037 \037text\037")); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002ACT \037channel\037 \037text\037\002\n" - " \n" - "Makes the bot do the equivalent of a \"/me\" command\n" - "on the given channel using the given text.")); - return true; - } -}; - -class BSAct : public Module -{ - CommandBSAct commandbsact; - - public: - BSAct(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsact); - } -}; - -MODULE_INIT(BSAct) diff --git a/modules/core/bs_assign.cpp b/modules/core/bs_assign.cpp index f1e2e4f69..0a08eec3b 100644 --- a/modules/core/bs_assign.cpp +++ b/modules/core/bs_assign.cpp @@ -12,52 +12,59 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSAssign : public Command { public: - CommandBSAssign() : Command("ASSIGN", 2, 2) + CommandBSAssign(Module *creator) : Command(creator, "botserv/assign", 2, 2) { this->SetDesc(_("Assigns a bot to a channel")); + this->SetSyntax(_("\037channel\037 \037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &nick = params[1]; + User *u = source.u; - ChannelInfo *ci = source.ci; if (readonly) { - source.Reply(_(BOT_ASSIGN_READONLY)); - return MOD_CONT; + source.Reply(BOT_ASSIGN_READONLY); + return; + } + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; } BotInfo *bi = findbot(nick); if (!bi) { - source.Reply(_(BOT_DOES_NOT_EXIST), nick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, nick.c_str()); + return; } if (ci->botflags.HasFlag(BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !u->HasPriv("botserv/administration"))) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } - if (bi->HasFlag(BI_PRIVATE) && !u->HasCommand("botserv/assign/private")) + if (bi->HasFlag(BI_PRIVATE) && !u->HasCommand("botserv/botserv/assign/private")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } - if (ci->bi && nick.equals_ci(ci->bi->nick)) + if (ci->bi == bi) { source.Reply(_("Bot \002%s\002 is already assigned to channel \002%s\002."), ci->bi->nick.c_str(), chan.c_str()); - return MOD_CONT; + return; } bool override = !check_access(u, ci, CA_ASSIGN); @@ -65,38 +72,96 @@ class CommandBSAssign : public Command bi->Assign(u, ci); source.Reply(_("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), ci->name.c_str()); - return MOD_CONT; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ASSIGN \037chan\037 \037nick\037\002\n" - " \n" - "Assigns a bot pointed out by nick to the channel chan. You\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Assigns a bot pointed out by nick to the channel chan. You\n" "can then configure the bot for the channel so it fits\n" "your needs.")); return true; } +}; + +class CommandBSUnassign : public Command +{ + public: + CommandBSUnassign(Module *creator) : Command(creator, "botserv/unassign", 1, 1) + { + this->SetDesc(_("Unassigns a bot from a channel")); + this->SetSyntax(_("\037channel\037 \037nick\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + + if (readonly) + { + source.Reply(BOT_ASSIGN_READONLY); + return; + } + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!u->HasPriv("botserv/administration") && !check_access(u, ci, CA_ASSIGN)) + { + source.Reply(ACCESS_DENIED); + return; + } + + if (!ci->bi) + { + source.Reply(BOT_NOT_ASSIGNED); + return; + } + + if (ci->HasFlag(CI_PERSIST) && !ModeManager::FindChannelModeByName(CMODE_PERM)) + { + source.Reply(_("You can not unassign bots while persist is set on the channel.")); + return; + } + + bool override = !check_access(u, ci, CA_ASSIGN); + Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "for " << ci->bi->nick; + + ci->bi->UnAssign(u, ci); + source.Reply(_("There is no bot assigned to %s anymore."), ci->name.c_str()); + } - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - SyntaxError(source, "ASSIGN", _("ASSIGN \037chan\037 \037nick\037")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Unassigns a bot from a channel. When you use this command,\n" + "the bot won't join the channel anymore. However, bot\n" + "configuration for the channel is kept, so you will always\n" + "be able to reassign a bot later without have to reconfigure\n" + "it entirely.")); + return true; } }; class BSAssign : public Module { CommandBSAssign commandbsassign; + CommandBSUnassign commandbsunassign; public: - BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsassign(this), commandbsunassign(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsassign); + ModuleManager::RegisterService(&commandbsassign); + ModuleManager::RegisterService(&commandbsunassign); } }; diff --git a/modules/core/bs_badwords.cpp b/modules/core/bs_badwords.cpp index 1ea8161f1..a272bdff9 100644 --- a/modules/core/bs_badwords.cpp +++ b/modules/core/bs_badwords.cpp @@ -12,36 +12,36 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class BadwordsListCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; bool SentHeader; public: - BadwordsListCallback(CommandSource &_source, const Anope::string &list) : NumberList(list, false), source(_source), SentHeader(false) + BadwordsListCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &list) : NumberList(list, false), source(_source), ci(_ci), SentHeader(false) { } ~BadwordsListCallback() { if (!SentHeader) - source.Reply(_("No matching entries on %s bad words list."), source.ci->name.c_str()); + source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str()); } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetBadWordCount()) + if (!Number || Number > ci->GetBadWordCount()) return; if (!SentHeader) { SentHeader = true; source.Reply(_("Bad words list for %s:\n" - " Num Word Type"), source.ci->name.c_str()); + " Num Word Type"), ci->name.c_str()); } - DoList(source, Number - 1, source.ci->GetBadWord(Number - 1)); + DoList(source, Number - 1, ci->GetBadWord(Number - 1)); } static void DoList(CommandSource &source, unsigned Number, BadWord *bw) @@ -53,43 +53,43 @@ class BadwordsListCallback : public NumberList class BadwordsDelCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; Command *c; unsigned Deleted; bool override; public: - BadwordsDelCallback(CommandSource &_source, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), c(_c), Deleted(0), override(false) + BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), Deleted(0), override(false) { - if (!check_access(source.u, source.ci, CA_BADWORDS) && source.u->HasPriv("botserv/administration")) + if (!check_access(source.u, ci, CA_BADWORDS) && source.u->HasPriv("botserv/administration")) this->override = true; } ~BadwordsDelCallback() { if (!Deleted) - source.Reply(_("No matching entries on %s bad words list."), source.ci->name.c_str()); + source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str()); else if (Deleted == 1) - source.Reply(_("Deleted 1 entry from %s bad words list."), source.ci->name.c_str()); + source.Reply(_("Deleted 1 entry from %s bad words list."), ci->name.c_str()); else - source.Reply(_("Deleted %d entries from %s bad words list."), Deleted, source.ci->name.c_str()); + source.Reply(_("Deleted %d entries from %s bad words list."), Deleted, ci->name.c_str()); } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetBadWordCount()) + if (!Number || Number > ci->GetBadWordCount()) return; - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, source.ci) << "DEL " << source.ci->GetBadWord(Number - 1)->word; + Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, ci) << "DEL " << ci->GetBadWord(Number - 1)->word; ++Deleted; - source.ci->EraseBadWord(Number - 1); + ci->EraseBadWord(Number - 1); } }; class CommandBSBadwords : public Command { private: - CommandReturn DoList(CommandSource &source, const Anope::string &word) + void DoList(CommandSource &source, ChannelInfo *ci, const Anope::string &word) { - ChannelInfo *ci = source.ci; bool override = !check_access(source.u, ci, CA_BADWORDS); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "LIST"; @@ -97,7 +97,7 @@ class CommandBSBadwords : public Command source.Reply(_("%s bad words list is empty."), ci->name.c_str()); else if (!word.empty() && word.find_first_not_of("1234567890,-") == Anope::string::npos) { - BadwordsListCallback list(source, word); + BadwordsListCallback list(source, ci, word); list.Process(); } else @@ -126,12 +126,11 @@ class CommandBSBadwords : public Command source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoAdd(CommandSource &source, const Anope::string &word) + void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &word) { - ChannelInfo *ci = source.ci; size_t pos = word.rfind(' '); BadWordType type = BW_ANY; Anope::string realword = word; @@ -154,7 +153,7 @@ class CommandBSBadwords : public Command if (ci->GetBadWordCount() >= Config->BSBadWordsMax) { source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), Config->BSBadWordsMax); - return MOD_CONT; + return; } for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i) @@ -164,7 +163,7 @@ class CommandBSBadwords : public Command if (!bw->word.empty() && ((Config->BSCaseSensitive && realword.equals_cs(bw->word)) || (!Config->BSCaseSensitive && realword.equals_ci(bw->word)))) { source.Reply(_("\002%s\002 already exists in %s bad words list."), bw->word.c_str(), ci->name.c_str()); - return MOD_CONT; + return; } } @@ -174,16 +173,15 @@ class CommandBSBadwords : public Command source.Reply(_("\002%s\002 added to %s bad words list."), realword.c_str(), ci->name.c_str()); - return MOD_CONT; + return; } - CommandReturn DoDelete(CommandSource &source, const Anope::string &word) + void DoDelete(CommandSource &source, ChannelInfo *ci, const Anope::string &word) { - ChannelInfo *ci = source.ci; /* Special case: is it a number/list? Only do search if it isn't. */ if (!word.empty() && isdigit(word[0]) && word.find_first_not_of("1234567890,-") == Anope::string::npos) { - BadwordsDelCallback list(source, this, word); + BadwordsDelCallback list(source, ci, this, word); list.Process(); } else @@ -202,7 +200,7 @@ class CommandBSBadwords : public Command if (i == end) { source.Reply(_("\002%s\002 not found on %s bad words list."), word.c_str(), ci->name.c_str()); - return MOD_CONT; + return; } bool override = !check_access(source.u, ci, CA_BADWORDS); @@ -213,78 +211,83 @@ class CommandBSBadwords : public Command ci->EraseBadWord(i); } - return MOD_CONT; + return; } - CommandReturn DoClear(CommandSource &source) + void DoClear(CommandSource &source, ChannelInfo *ci) { - ChannelInfo *ci = source.ci; bool override = !check_access(source.u, ci, CA_BADWORDS); Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, this, ci) << "CLEAR"; ci->ClearBadWords(); source.Reply(_("Bad words list is now empty.")); - return MOD_CONT; + return; } public: - CommandBSBadwords() : Command("BADWORDS", 2, 3) + CommandBSBadwords(Module *creator) : Command(creator, "botserv/badwords", 2, 3) { this->SetDesc(_("Maintains bad words list")); + this->SetSyntax(_("\037channel\037 ADD \037word\037 [\037SINGLE\037 | \037START\037 | \037END\037]")); + this->SetSyntax(_("\037channel\037 DEL {\037word\037 | \037entry-num\037 | \037list\037}")); + this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]")); + this->SetSyntax(_("\037channel\037 CLEAR")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[1]; const Anope::string &word = params.size() > 2 ? params[2] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; bool need_args = cmd.equals_ci("LIST") || cmd.equals_ci("CLEAR"); if (!need_args && word.empty()) { this->OnSyntaxError(source, cmd); - return MOD_CONT; + return; + } + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; } + if (!check_access(u, ci, CA_BADWORDS) && (!need_args || !u->HasPriv("botserv/administration"))) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (readonly) { source.Reply(_("Sorry, channel bad words list modification is temporarily disabled.")); - return MOD_CONT; + return; } if (cmd.equals_ci("ADD")) - return this->DoAdd(source, word); + return this->DoAdd(source, ci, word); else if (cmd.equals_ci("DEL")) - return this->DoDelete(source, word); + return this->DoDelete(source, ci, word); else if (cmd.equals_ci("LIST")) - return this->DoList(source, word); + return this->DoList(source, ci, word); else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source); + return this->DoClear(source, ci); else this->OnSyntaxError(source, ""); - - return MOD_CONT; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002BADWORDS \037channel\037 ADD \037word\037 [\037SINGLE\037 | \037START\037 | \037END\037]\002\n" - " \002BADWORDS \037channel\037 DEL {\037word\037 | \037entry-num\037 | \037list\037}\002\n" - " \002BADWORDS \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002BADWORDS \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002bad words list\002 for a channel. The bad\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002bad words list\002 for a channel. The bad\n" "words list determines which words are to be kicked\n" "when the bad words kicker is enabled. For more information,\n" - "type \002%s%s HELP KICK BADWORDS\002.\n" + "type \002%s%s HELP KICK %s\002.\n" " \n" - "The \002BADWORDS ADD\002 command adds the given word to the\n" + "The \002ADD\002 command adds the given word to the\n" "badword list. If SINGLE is specified, a kick will be\n" "done only if a user says the entire word. If START is \n" "specified, a kick will be done if a user says a word\n" @@ -292,28 +295,23 @@ class CommandBSBadwords : public Command "will be done if a user says a word that ends with\n" "\037word\037. If you don't specify anything, a kick will\n" "be issued every time \037word\037 is said by a user.\n" - " \n"), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); - source.Reply(_("The \002BADWORDS DEL\002 command removes the given word from the\n" + " \n"), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + source.Reply(_("The \002DEL\002 command removes the given word from the\n" "bad words list. If a list of entry numbers is given, those\n" "entries are deleted. (See the example for LIST below.)\n" " \n" - "The \002BADWORDS LIST\002 command displays the bad words list. If\n" + "The \002LIST\002 command displays the bad words list. If\n" "a wildcard mask is given, only those entries matching the\n" "mask are displayed. If a list of entry numbers is given,\n" "only those entries are shown; for example:\n" - " \002BADWORDS #channel LIST 2-5,7-9\002\n" + " \002#channel LIST 2-5,7-9\002\n" " Lists bad words entries numbered 2 through 5 and\n" " 7 through 9.\n" " \n" - "The \002BADWORDS CLEAR\002 command clears all entries of the\n" + "The \002CLEAR\002 command clears all entries of the\n" "bad words list.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "BADWORDS", _("BADWORDS \037channel\037 {ADD|DEL|LIST|CLEAR} [\037word\037 | \037entry-list\037] [SINGLE|START|END]")); - } }; class BSBadwords : public Module @@ -321,14 +319,12 @@ class BSBadwords : public Module CommandBSBadwords commandbsbadwords; public: - BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsbadwords(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsbadwords); + ModuleManager::RegisterService(&commandbsbadwords); } }; diff --git a/modules/core/bs_bot.cpp b/modules/core/bs_bot.cpp index 4d42380f3..ec0bea734 100644 --- a/modules/core/bs_bot.cpp +++ b/modules/core/bs_bot.cpp @@ -12,12 +12,11 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSBot : public Command { private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params[1]; const Anope::string &user = params[2]; @@ -28,60 +27,60 @@ class CommandBSBot : public Command if (findbot(nick)) { source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); - return MOD_CONT; + return; } if (nick.length() > Config->NickLen) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } if (user.length() > Config->UserLen) { source.Reply(_("Bot Idents may only contain %d characters."), Config->UserLen); - return MOD_CONT; + return; } if (host.length() > Config->HostLen) { source.Reply(_("Bot Hosts may only contain %d characters."), Config->HostLen); - return MOD_CONT; + return; } /* Check the nick is valid re RFC 2812 */ if (isdigit(nick[0]) || nick[0] == '-') { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } for (unsigned i = 0, end = nick.length(); i < end && i < Config->NickLen; ++i) if (!isvalidnick(nick[i])) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } /* check for hardcored ircd forbidden nicks */ if (!ircdproto->IsNickValid(nick)) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } /* Check the host is valid re RFC 2812 */ if (!isValidHost(host, 3)) { source.Reply(_("Bot Hosts may only contain valid host characters.")); - return MOD_CONT; + return; } for (unsigned i = 0, end = user.length(); i < end && i < Config->UserLen; ++i) if (!isalnum(user[i])) { source.Reply(_("Bot Idents may only contain valid characters."), Config->UserLen); - return MOD_CONT; + return; } /* We check whether the nick is registered, and inform the user @@ -90,26 +89,21 @@ class CommandBSBot : public Command */ if (findnick(nick)) { - source.Reply(_(NICK_ALREADY_REGISTERED), nick.c_str()); - return MOD_CONT; + source.Reply(NICK_ALREADY_REGISTERED, nick.c_str()); + return; } - if (!(bi = new BotInfo(nick, user, host, real))) - { - // XXX this cant happen? - source.Reply(_("Sorry, bot creation failed.")); - return MOD_CONT; - } + bi = new BotInfo(nick, user, host, real); Log(LOG_ADMIN, source.u, this) << "ADD " << bi->GetMask() << " " << bi->realname; source.Reply(_("%s!%s@%s (%s) added to the bot list."), bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); FOREACH_MOD(I_OnBotCreate, OnBotCreate(bi)); - return MOD_CONT; + return; } - CommandReturn DoChange(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoChange(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &oldnick = params[1]; const Anope::string &nick = params.size() > 2 ? params[2] : ""; @@ -121,43 +115,43 @@ class CommandBSBot : public Command if (oldnick.empty() || nick.empty()) { this->OnSyntaxError(source, "CHANGE"); - return MOD_CONT; + return; } if (!(bi = findbot(oldnick))) { - source.Reply(_(BOT_DOES_NOT_EXIST), oldnick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, oldnick.c_str()); + return; } if (!oldnick.equals_ci(nick) && nickIsServices(oldnick, false)) { - source.Reply(_(BOT_DOES_NOT_EXIST), oldnick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, oldnick.c_str()); + return; } if (nick.length() > Config->NickLen) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } if (!user.empty() && user.length() > Config->UserLen) { source.Reply(_("Bot Idents may only contain %d characters."), Config->UserLen); - return MOD_CONT; + return; } if (!host.empty() && host.length() > Config->HostLen) { source.Reply(_("Bot Hosts may only contain %d characters."), Config->HostLen); - return MOD_CONT; + return; } if (!oldnick.equals_ci(nick) && nickIsServices(nick, false)) { - source.Reply(_(BOT_DOES_NOT_EXIST), oldnick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, oldnick.c_str()); + return; } /* Checks whether there *are* changes. @@ -168,34 +162,34 @@ class CommandBSBot : public Command if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1)) { source.Reply(_("Old info is equal to the new one.")); - return MOD_CONT; + return; } /* Check the nick is valid re RFC 2812 */ if (isdigit(nick[0]) || nick[0] == '-') { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } for (unsigned i = 0, end = nick.length(); i < end && i < Config->NickLen; ++i) if (!isvalidnick(nick[i])) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } /* check for hardcored ircd forbidden nicks */ if (!ircdproto->IsNickValid(nick)) { source.Reply(_("Bot Nicks may only contain valid nick characters.")); - return MOD_CONT; + return; } if (!host.empty() && !isValidHost(host, 3)) { source.Reply(_("Bot Hosts may only contain valid host characters.")); - return MOD_CONT; + return; } if (!user.empty()) @@ -203,13 +197,13 @@ class CommandBSBot : public Command if (!isalnum(user[i])) { source.Reply(_("Bot Idents may only contain valid characters."), Config->UserLen); - return MOD_CONT; + return; } if (!nick.equals_ci(bi->nick) && findbot(nick)) { source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); - return MOD_CONT; + return; } if (!nick.equals_ci(bi->nick)) @@ -220,8 +214,8 @@ class CommandBSBot : public Command */ if (findnick(nick)) { - source.Reply(_(NICK_ALREADY_REGISTERED), nick.c_str()); - return MOD_CONT; + source.Reply(NICK_ALREADY_REGISTERED, nick.c_str()); + return; } /* The new nick is really different, so we remove the Q line for the old nick. */ @@ -263,10 +257,10 @@ class CommandBSBot : public Command Log(LOG_ADMIN, source.u, this) << "CHANGE " << oldnick << " to " << bi->GetMask() << " " << bi->realname; FOREACH_MOD(I_OnBotChange, OnBotChange(bi)); - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params[1]; BotInfo *bi; @@ -274,19 +268,19 @@ class CommandBSBot : public Command if (nick.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } if (!(bi = findbot(nick))) { - source.Reply(_(BOT_DOES_NOT_EXIST), nick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, nick.c_str()); + return; } if (nickIsServices(nick, false)) { - source.Reply(_(BOT_DOES_NOT_EXIST), nick.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, nick.c_str()); + return; } FOREACH_MOD(I_OnBotDelete, OnBotDelete(bi)); @@ -295,16 +289,18 @@ class CommandBSBot : public Command source.Reply(_("Bot \002%s\002 has been deleted."), nick.c_str()); delete bi; - return MOD_CONT; + return; } public: - CommandBSBot() : Command("BOT", 1, 6) + CommandBSBot(Module *creator) : Command(creator, "botserv/bot", 1, 6) { - this->SetFlag(CFLAG_STRIP_CHANNEL); this->SetDesc(_("Maintains network bot list")); + this->SetSyntax(_("\002ADD \037nick\037 \037user\037 \037host\037 \037real\037\002")); + this->SetSyntax(_("\002CHANGE \037oldnick\037 \037newnick\037 [\037user\037 [\037host\037 [\037real\037]]]\002")); + this->SetSyntax(_("\002DEL \037nick\037\002")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[0]; User *u = source.u; @@ -312,22 +308,22 @@ class CommandBSBot : public Command if (readonly) { source.Reply(_("Sorry, bot modification is temporarily disabled.")); - return MOD_CONT; + return; } if (cmd.equals_ci("ADD")) { // ADD nick user host real - 5 - if (!u->HasCommand("botserv/bot/add")) + if (!u->HasCommand("botserv/botserv/bot/add")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (params.size() < 5) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } std::vector<Anope::string> tempparams = params; @@ -341,16 +337,16 @@ class CommandBSBot : public Command { // CHANGE oldn newn user host real - 6 // but only oldn and newn are required - if (!u->HasCommand("botserv/bot/change")) + if (!u->HasCommand("botserv/botserv/bot/change")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (params.size() < 3) { this->OnSyntaxError(source, "CHANGE"); - return MOD_CONT; + return; } return this->DoChange(source, params); @@ -358,16 +354,16 @@ class CommandBSBot : public Command else if (cmd.equals_ci("DEL")) { // DEL nick - if (!u->HasCommand("botserv/bot/del")) + if (!u->HasCommand("botserv/botserv/bot/del")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (params.size() < 1) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } return this->DoDel(source, params); @@ -375,16 +371,14 @@ class CommandBSBot : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002BOT ADD \037nick\037 \037user\037 \037host\037 \037real\037\002\n" - " \002BOT CHANGE \037oldnick\037 \037newnick\037 [\037user\037 [\037host\037 [\037real\037]]]\002\n" - " \002BOT DEL \037nick\037\002\n" - " \n" - "Allows Services Operators to create, modify, and delete\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Operators to create, modify, and delete\n" "bots that users will be able to use on their own\n" "channels.\n" " \n" @@ -401,13 +395,6 @@ class CommandBSBot : public Command "using the nick, they will be killed.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "BOT", _("BOT ADD \037nick\037 \037user\037 \037host\037 \037real\037\n" - "\002BOT CHANGE \037oldnick\037 \037newnick\037 [\037user\037 [\037host\037 [\037real\037]]]\002\n" - "\002BOT DEL \037nick\037\002")); - } }; class BSBot : public Module @@ -415,14 +402,12 @@ class BSBot : public Module CommandBSBot commandbsbot; public: - BSBot(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSBot(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsbot(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsbot); + ModuleManager::RegisterService(&commandbsbot); } }; diff --git a/modules/core/bs_botlist.cpp b/modules/core/bs_botlist.cpp index aa4731189..ee7e4d2d8 100644 --- a/modules/core/bs_botlist.cpp +++ b/modules/core/bs_botlist.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSBotList : public Command { public: - CommandBSBotList() : Command("BOTLIST", 0, 0) + CommandBSBotList(Module *creator) : Command(creator, "botserv/botlist", 0, 0) { this->SetDesc(_("Lists available bots")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; unsigned count = 0; @@ -40,7 +40,7 @@ class CommandBSBotList : public Command } } - if (u->HasCommand("botserv/botlist") && count < BotListByNick.size()) + if (u->HasCommand("botserv/botserv/botlist") && count < BotListByNick.size()) { source.Reply(_("Bots reserved to IRC operators:")); @@ -62,14 +62,14 @@ class CommandBSBotList : public Command else source.Reply(_("%d bots available."), count); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002BOTLIST\002\n" - " \n" - "Lists all available bots on this network.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all available bots on this network.")); return true; } }; @@ -79,14 +79,12 @@ class BSBotList : public Module CommandBSBotList commandbsbotlist; public: - BSBotList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSBotList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsbotlist(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsbotlist); + ModuleManager::RegisterService(&commandbsbotlist); } }; diff --git a/modules/core/bs_control.cpp b/modules/core/bs_control.cpp new file mode 100644 index 000000000..431739693 --- /dev/null +++ b/modules/core/bs_control.cpp @@ -0,0 +1,158 @@ +/* BotServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandBSSay : public Command +{ + public: + CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2) + { + this->SetDesc(_("Makes the bot say the given text on the given channel")); + this->SetSyntax(_("\037channel\037 \037text\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &text = params[1]; + + User *u = source.u; + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!check_access(u, ci, CA_SAY)) + { + source.Reply(ACCESS_DENIED); + return; + } + + if (!ci->bi) + { + source.Reply(BOT_NOT_ASSIGNED); + return; + } + + if (!ci->c || !ci->c->FindUser(ci->bi)) + { + source.Reply(BOT_NOT_ON_CHANNEL, ci->name.c_str()); + return; + } + + if (text[0] == '\001') + { + this->OnSyntaxError(source, ""); + return; + } + + ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", text.c_str()); + ci->bi->lastmsg = Anope::CurTime; + + // XXX need a way to find if someone is overriding this + Log(LOG_COMMAND, u, this, ci) << text; + + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Makes the bot say the given text on the given channel.")); + return true; + } +}; + +class CommandBSAct : public Command +{ + public: + CommandBSAct(Module *creator) : Command(creator, "botserv/act", 2, 2) + { + this->SetDesc(_("Makes the bot do the equivalent of a \"/me\" command")); + this->SetSyntax(_("\037channel\037 \037text\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + Anope::string message = params[1]; + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!check_access(u, ci, CA_SAY)) + { + source.Reply(ACCESS_DENIED); + return; + } + + if (!ci->bi) + { + source.Reply(BOT_NOT_ASSIGNED); + return; + } + + if (!ci->c || !ci->c->FindUser(ci->bi)) + { + source.Reply(BOT_NOT_ON_CHANNEL, ci->name.c_str()); + return; + } + + size_t i = 0; + while ((i = message.find(1)) && i != Anope::string::npos) + message.erase(i, 1); + + ircdproto->SendAction(ci->bi, ci->name, "%s", message.c_str()); + ci->bi->lastmsg = Anope::CurTime; + + // XXX Need to be able to find if someone is overriding this. + Log(LOG_COMMAND, u, this, ci) << message; + + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Makes the bot do the equivalent of a \"/me\" command\n" + "on the given channel using the given text.")); + return true; + } +}; + +class BSControl : public Module +{ + CommandBSSay commandbssay; + CommandBSAct commandbsact; + + public: + BSControl(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbssay(this), commandbsact(this) + { + this->SetAuthor("Anope"); + + ModuleManager::RegisterService(&commandbssay); + ModuleManager::RegisterService(&commandbsact); + } +}; + +MODULE_INIT(BSControl) diff --git a/modules/core/bs_help.cpp b/modules/core/bs_help.cpp deleted file mode 100644 index 953c5f37e..000000000 --- a/modules/core/bs_help.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "botserv.h" - -class CommandBSHelp : public Command -{ - public: - CommandBSHelp() : Command("HELP", 1, 1) - { - this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetFlag(CFLAG_STRIP_CHANNEL); - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(botserv->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - // Abuse syntax error to display general list help. - User *u = source.u; - source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n" - "It has been created for users that can't host or\n" - "configure a bot, or for use on networks that don't\n" - "allow user bots. Available commands are listed \n" - "below; to use them, type \002%s%s \037command\037\002. For\n" - "more information on a specific command, type\n" - "\002%s%s HELP \037command\037\002."), - Config->s_BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); - for (CommandMap::const_iterator it = botserv->Bot()->Commands.begin(), it_end = botserv->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - source.Reply(_("Bot will join a channel whenever there is at least\n" - "\002%d\002 user(s) on it. Additionally, all %s commands\n" - "can be used if fantasy is enabled by prefixing the command\n" - "name with a %c."), Config->BSMinUsers, Config->s_ChanServ.c_str(), Config->BSFantasyCharacter[0]); - } -}; - -class BSHelp : public Module -{ - CommandBSHelp commandbshelp; - - public: - BSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbshelp); - } -}; - -MODULE_INIT(BSHelp) diff --git a/modules/core/bs_info.cpp b/modules/core/bs_info.cpp index 9c996b247..38178a07b 100644 --- a/modules/core/bs_info.cpp +++ b/modules/core/bs_info.cpp @@ -13,7 +13,6 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSInfo : public Command { @@ -41,13 +40,13 @@ class CommandBSInfo : public Command return; } public: - CommandBSInfo() : Command("INFO", 1, 1) + CommandBSInfo(Module *creator) : Command(creator, "botserv/info", 1, 1) { - this->SetFlag(CFLAG_STRIP_CHANNEL); this->SetDesc(_("Allows you to see BotServ information about a channel or a bot")); + this->SetSyntax(_("\002INFO {\037chan\037 | \037nick\037}\002")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &query = params[0]; @@ -73,11 +72,11 @@ class CommandBSInfo : public Command { if (!check_access(u, ci, CA_FOUNDER) && !u->HasPriv("botserv/administration")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } - source.Reply(_(CHAN_INFO_HEADER), ci->name.c_str()); + source.Reply(CHAN_INFO_HEADER, ci->name.c_str()); if (ci->bi) source.Reply(_(" Bot nick : %s"), ci->bi->nick.c_str()); else @@ -86,93 +85,93 @@ class CommandBSInfo : public Command if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) { if (ci->ttb[TTB_BADWORDS]) - source.Reply(_(" Bad words kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_BADWORDS]); + source.Reply(_(" Bad words kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_BADWORDS]); else - source.Reply(_(" Bad words kicker : %s"), _(ENABLED)); + source.Reply(_(" Bad words kicker : %s"), ENABLED); } else - source.Reply(_(" Bad words kicker : %s"), _(DISABLED)); + source.Reply(_(" Bad words kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_BOLDS)) { if (ci->ttb[TTB_BOLDS]) - source.Reply(_(" Bolds kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_BOLDS]); + source.Reply(_(" Bolds kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_BOLDS]); else - source.Reply(_(" Bolds kicker : %s"), _(ENABLED)); + source.Reply(_(" Bolds kicker : %s"), ENABLED); } else - source.Reply(_(" Bolds kicker : %s"), _(DISABLED)); + source.Reply(_(" Bolds kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_CAPS)) { if (ci->ttb[TTB_CAPS]) - source.Reply(_(" Caps kicker : %s (%d kick(s) to ban; minimum %d/%d%%)"), _(ENABLED), ci->ttb[TTB_CAPS], ci->capsmin, ci->capspercent); + source.Reply(_(" Caps kicker : %s (%d kick(s) to ban; minimum %d/%d%%)"), ENABLED, ci->ttb[TTB_CAPS], ci->capsmin, ci->capspercent); else - source.Reply(_(" Caps kicker : %s (minimum %d/%d%%)"), _(ENABLED), ci->capsmin, ci->capspercent); + source.Reply(_(" Caps kicker : %s (minimum %d/%d%%)"), ENABLED, ci->capsmin, ci->capspercent); } else - source.Reply(_(" Caps kicker : %s"), _(DISABLED)); + source.Reply(_(" Caps kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_COLORS)) { if (ci->ttb[TTB_COLORS]) - source.Reply(_(" Colors kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_COLORS]); + source.Reply(_(" Colors kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_COLORS]); else - source.Reply(_(" Colors kicker : %s"), _(ENABLED)); + source.Reply(_(" Colors kicker : %s"), ENABLED); } else - source.Reply(_(" Colors kicker : %s"), _(DISABLED)); + source.Reply(_(" Colors kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_FLOOD)) { if (ci->ttb[TTB_FLOOD]) - source.Reply(_(" Flood kicker : %s (%d kick(s) to ban; %d lines in %ds)"), _(ENABLED), ci->ttb[TTB_FLOOD], ci->floodlines, ci->floodsecs); + source.Reply(_(" Flood kicker : %s (%d kick(s) to ban; %d lines in %ds)"), ENABLED, ci->ttb[TTB_FLOOD], ci->floodlines, ci->floodsecs); else - source.Reply(_(" Flood kicker : %s (%d lines in %ds)"), _(ENABLED), ci->floodlines, ci->floodsecs); + source.Reply(_(" Flood kicker : %s (%d lines in %ds)"), ENABLED, ci->floodlines, ci->floodsecs); } else - source.Reply(_(" Flood kicker : %s"), _(DISABLED)); + source.Reply(_(" Flood kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_REPEAT)) { if (ci->ttb[TTB_REPEAT]) - source.Reply(_(" Repeat kicker : %s (%d kick(s) to ban; %d times)"), _(ENABLED), ci->ttb[TTB_REPEAT], ci->repeattimes); + source.Reply(_(" Repeat kicker : %s (%d kick(s) to ban; %d times)"), ENABLED, ci->ttb[TTB_REPEAT], ci->repeattimes); else - source.Reply(_(" Repeat kicker : %s (%d times)"), _(ENABLED), ci->repeattimes); + source.Reply(_(" Repeat kicker : %s (%d times)"), ENABLED, ci->repeattimes); } else - source.Reply(_(" Repeat kicker : %s"), _(DISABLED)); + source.Reply(_(" Repeat kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_REVERSES)) { if (ci->ttb[TTB_REVERSES]) - source.Reply(_(" Reverses kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_REVERSES]); + source.Reply(_(" Reverses kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_REVERSES]); else - source.Reply(_(" Reverses kicker : %s"), _(ENABLED)); + source.Reply(_(" Reverses kicker : %s"), ENABLED); } else - source.Reply(_(" Reverses kicker : %s"), _(DISABLED)); + source.Reply(_(" Reverses kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_UNDERLINES)) { if (ci->ttb[TTB_UNDERLINES]) - source.Reply(_(" Underlines kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_UNDERLINES]); + source.Reply(_(" Underlines kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_UNDERLINES]); else - source.Reply(_(" Underlines kicker : %s"), _(ENABLED)); + source.Reply(_(" Underlines kicker : %s"), ENABLED); } else - source.Reply(_(" Underlines kicker : %s"), _(DISABLED)); + source.Reply(_(" Underlines kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_ITALICS)) { if (ci->ttb[TTB_ITALICS]) - source.Reply(_(" Italics kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_ITALICS]); + source.Reply(_(" Italics kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_ITALICS]); else - source.Reply(_(" Italics kicker : %s"), _(ENABLED)); + source.Reply(_(" Italics kicker : %s"), ENABLED); } else - source.Reply(_(" Italics kicker : %s"), _(DISABLED)); + source.Reply(_(" Italics kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_KICK_AMSGS)) { if (ci->ttb[TTB_AMSGS]) - source.Reply(_(" AMSG kicker : %s (%d kick(s) to ban)"), _(ENABLED), ci->ttb[TTB_AMSGS]); + source.Reply(_(" AMSG kicker : %s (%d kick(s) to ban)"), ENABLED, ci->ttb[TTB_AMSGS]); else - source.Reply(_(" AMSG kicker : %s"), _(ENABLED)); + source.Reply(_(" AMSG kicker : %s"), ENABLED); } else - source.Reply(_(" AMSG kicker : %s"), _(DISABLED)); + source.Reply(_(" AMSG kicker : %s"), DISABLED); if (ci->botflags.HasFlag(BS_MSG_PRIVMSG)) source.Reply(_(" Fantasy reply : %s"), "PRIVMSG"); @@ -208,34 +207,24 @@ class CommandBSInfo : public Command end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", need_comma ? ", " : "", _("No bot")); need_comma = true; } - if (ci->botflags.HasFlag(BS_SYMBIOSIS)) - { - end += snprintf(end, sizeof(buf) - (end - buf), "%s%s", need_comma ? ", " : "", _("Symbiosis")); - need_comma = true; - } source.Reply(_(" Options : %s"), *buf ? buf : _("None")); } else source.Reply(_("\002%s\002 is not a valid bot or registered channel."), query.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002INFO {\037chan\037 | \037nick\037}\002\n" - " \n" - "Allows you to see %s information about a channel or a bot.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to see %s information about a channel or a bot.\n" "If the parameter is a channel, then you'll get information\n" "such as enabled kickers. If the parameter is a nick,\n" "you'll get information about a bot, such as creation\n" - "time or number of channels it is on."), Config->s_NickServ.c_str()); + "time or number of channels it is on."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "INFO", _("INFO {\037chan\037 | \037nick\037}")); - } }; class BSInfo : public Module @@ -243,14 +232,12 @@ class BSInfo : public Module CommandBSInfo commandbsinfo; public: - BSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsinfo(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsinfo); + ModuleManager::RegisterService(&commandbsinfo); } }; diff --git a/modules/core/bs_kick.cpp b/modules/core/bs_kick.cpp index 467f4104e..a8c34e5cd 100644 --- a/modules/core/bs_kick.cpp +++ b/modules/core/bs_kick.cpp @@ -13,17 +13,17 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSKick : public Command { public: - CommandBSKick() : Command("KICK", 3, 6) + CommandBSKick(Module *creator) : Command(creator, "botserv/kick", 3, 6) { this->SetDesc(_("Configures kickers")); + this->SetSyntax(_("\037channel\037 \037option\037 {\037ON|\037} [\037settings\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &option = params[1]; @@ -31,18 +31,20 @@ class CommandBSKick : public Command const Anope::string &ttb = params.size() > 3 ? params[3] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); if (readonly) source.Reply(_("Sorry, kicker configuration is temporarily disabled.")); + else if (ci == NULL) + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); else if (chan.empty() || option.empty() || value.empty()) - SyntaxError(source, "KICK", _("KICK \037channel\037 \037option\037 {\037ON|\037} [\037settings\037]")); + this->OnSyntaxError(source, ""); else if (!value.equals_ci("ON") && !value.equals_ci("OFF")) - SyntaxError(source, "KICK", _("KICK \037channel\037 \037option\037 {\037ON|\037} [\037settings\037]")); + this->OnSyntaxError(source, ""); else if (!check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!ci->bi) - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); + source.Reply(BOT_NOT_ASSIGNED); else { bool override = !check_access(u, ci, CA_SET); @@ -65,7 +67,7 @@ class CommandBSKick : public Command /* reset the value back to 0 - TSL */ ci->ttb[TTB_BADWORDS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -102,7 +104,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_BOLDS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -138,7 +140,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_CAPS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -193,7 +195,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_COLORS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -230,7 +232,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_FLOOD] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -286,7 +288,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_REPEAT] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -332,7 +334,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_REVERSES] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -365,7 +367,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_UNDERLINES] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -399,7 +401,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_ITALICS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -433,7 +435,7 @@ class CommandBSKick : public Command { ci->ttb[TTB_AMSGS] = 0; source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return MOD_CONT; + return; } } else @@ -452,17 +454,18 @@ class CommandBSKick : public Command } } else - source.Reply(_(UNKNOWN_OPTION), Config->UseStrictPrivMsgString.c_str(), option.c_str(), this->name.c_str()); + source.Reply(UNKNOWN_OPTION, Config->UseStrictPrivMsgString.c_str(), option.c_str(), this->name.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { if (subcommand.empty()) - source.Reply(_("Syntax: \002KICK \037channel\037 \037option\037 \037parameters\037\002\n" - " \n" - "Configures bot kickers. \037option\037 can be one of:\n" + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Configures bot kickers. \037option\037 can be one of:\n" " \n" " AMSGS Sets if the bot kicks for amsgs\n" " BOLDS Sets if the bot kicks bolds\n" @@ -480,9 +483,10 @@ class CommandBSKick : public Command "on a specific option.\n" " \n" "Note: access to this command is controlled by the\n" - "level SET."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); + "level SET."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + } else if (subcommand.equals_ci("BADWORDS")) - source.Reply(_("Syntax: \002KICK \037#channel\037 BADWORDS {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037#channel\037 BADWORDS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the bad words kicker on or off. When enabled, this\n" "option tells the bot to kick users who say certain words\n" "on the channels.\n" @@ -491,16 +495,16 @@ class CommandBSKick : public Command "more information.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" - "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); + "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); else if (subcommand.equals_ci("BOLDS")) - source.Reply(_("Syntax: \002KICK \037channel\037 BOLDS {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 BOLDS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the bolds kicker on or off. When enabled, this\n" "option tells the bot to kick users who use bolds.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("CAPS")) - source.Reply(_("Syntax: \002KICK \037channel\037 CAPS {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002\n" + source.Reply(_("Syntax: \002\037channel\037 CAPS {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002\n" "Sets the caps kicker on or off. When enabled, this\n" "option tells the bot to kick users who are talking in\n" "CAPS.\n" @@ -512,14 +516,14 @@ class CommandBSKick : public Command "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("COLORS")) - source.Reply(_("Syntax: \002KICK \037channel\037 COLORS {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 COLORS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the colors kicker on or off. When enabled, this\n" "option tells the bot to kick users who use colors.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("FLOOD")) - source.Reply(_("Syntax: \002KICK \037channel\037 FLOOD {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002\n" + source.Reply(_("Syntax: \002\037channel\037 FLOOD {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002\n" "Sets the flood kicker on or off. When enabled, this\n" "option tells the bot to kick users who are flooding\n" "the channel using at least \002ln\002 lines in \002secs\002 seconds\n" @@ -529,7 +533,7 @@ class CommandBSKick : public Command "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("REPEAT")) - source.Reply(_("Syntax: \002KICK \037#channel\037 REPEAT {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002\n" + source.Reply(_("Syntax: \002\037#channel\037 REPEAT {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002\n" "Sets the repeat kicker on or off. When enabled, this\n" "option tells the bot to kick users who are repeating\n" "themselves \002num\002 times (if num is not given, it\n" @@ -538,28 +542,28 @@ class CommandBSKick : public Command "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("REVERSES")) - source.Reply(_("Syntax: \002KICK \037channel\037 REVERSES {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 REVERSES {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the reverses kicker on or off. When enabled, this\n" "option tells the bot to kick users who use reverses.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("UNDERLINES")) - source.Reply(_("Syntax: \002KICK \037channel\037 UNDERLINES {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 UNDERLINES {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the underlines kicker on or off. When enabled, this\n" "option tells the bot to kick users who use underlines.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("ITALICS")) - source.Reply(_("Syntax: \002KICK \037channel\037 ITALICS {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 ITALICS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the italics kicker on or off. When enabled, this\n" "option tells the bot to kick users who use italics.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" "the ban system once activated.")); else if (subcommand.equals_ci("AMSGS")) - source.Reply(_("Syntax: \002KICK \037channel\037 AMSGS {\037ON|OFF\037} [\037ttb\037]\002\n" + source.Reply(_("Syntax: \002\037channel\037 AMSGS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the amsg kicker on or off. When enabled, the bot will\n" "kick users who send the same message to multiple channels\n" "where BotServ bots are.\n" @@ -571,16 +575,121 @@ class CommandBSKick : public Command return true; } +}; + +struct BanData +{ + Anope::string mask; + time_t last_use; + int16 ttb[TTB_SIZE]; + + BanData() + { + this->Clear(); + } + + void Clear() + { + last_use = 0; + for (int i = 0; i < TTB_SIZE; ++i) + this->ttb[i] = 0; + } +}; + +struct UserData +{ + UserData() + { + this->Clear(); + } + + void Clear() + { + last_use = last_start = Anope::CurTime; + lines = times = 0; + lastline.clear(); + } + + /* Data validity */ + time_t last_use; + + /* for flood kicker */ + int16 lines; + time_t last_start; - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + /* for repeat kicker */ + Anope::string lastline; + Anope::string lasttarget; + int16 times; +}; + + +class BanDataPurger : public CallBack +{ + public: + BanDataPurger(Module *owner) : CallBack(owner, 300, Anope::CurTime, true) { } + + void Tick(time_t) { - SyntaxError(source, "KICK", _("KICK \037channel\037 \037option\037 {\037ON|\037} [\037settings\037]")); + Log(LOG_DEBUG) << "bs_main: Running bandata purger"; + + for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) + { + Channel *c = it->second; + + std::map<Anope::string, BanData> bandata; + if (c->GetExtRegular("bs_main_bandata", bandata)) + { + for (std::map<Anope::string, BanData>::iterator it2 = bandata.begin(), it2_end = bandata.end(); it2 != it2_end;) + { + const Anope::string &user = it->first; + BanData *bd = &it2->second; + ++it2; + + if (Anope::CurTime - bd->last_use > Config->BSKeepData) + { + bandata.erase(user); + continue; + } + } + + if (bandata.empty()) + c->Shrink("bs_main_bandata"); + } + } } }; class BSKick : public Module { CommandBSKick commandbskick; + BanDataPurger purger; + + BanData *GetBanData(User *u, Channel *c) + { + std::map<Anope::string, BanData> bandatamap; + if (!c->GetExtRegular("bs_main_bandata", bandatamap)); + c->Extend("bs_main_bandata", new ExtensibleItemRegular<std::map<Anope::string, BanData> >(bandatamap)); + c->GetExtRegular("bs_main_bandata", bandatamap); + + BanData *bd = &bandatamap[u->GetMask()]; + if (bd->last_use && Anope::CurTime - bd->last_use > Config->BSKeepData) + bd->Clear(); + bd->last_use = Anope::CurTime; + return bd; + } + + UserData *GetUserData(User *u, Channel *c) + { + UserData *ud = NULL; + UserContainer *uc = c->FindUser(u); + if (uc != NULL && !uc->GetExtPointer("bs_main_userdata", ud)) + { + ud = new UserData(); + uc->Extend("bs_main_userdata", new ExtensibleItemPointer<UserData>(ud)); + } + return ud; + } void check_ban(ChannelInfo *ci, User *u, int ttbtype) { @@ -588,7 +697,7 @@ class BSKick : public Module if (u->server->IsULined()) return; - BanData *bd = botserv->GetBanData(u, ci->c); + BanData *bd = this->GetBanData(u, ci->c); ++bd->ttb[ttbtype]; if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) @@ -625,19 +734,26 @@ class BSKick : public Module } public: - BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbskick(this), purger(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbskick); + ModuleManager::RegisterService(&commandbskick); ModuleManager::Attach(I_OnPrivmsg, this); } - void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) + ~BSKick() + { + for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) + { + cit->second->Shrink("bs_main_userdata"); + cit->second->Shrink("bs_main_bandata"); + } + } + + void OnPrivmsg(User *u, Channel *c, Anope::string &msg) { /* Now we can make kicker stuff. We try to order the checks * from the fastest one to the slowest one, since there's @@ -647,13 +763,16 @@ class BSKick : public Module * But FIRST we check whether the user is protected in any * way. */ + ChannelInfo *ci = c->ci; + if (ci == NULL) + return; bool Allow = true; if (check_access(u, ci, CA_NOKICK)) Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (ci->c->HasUserStatus(u, CMODE_HALFOP) || ci->c->HasUserStatus(u, CMODE_OP) || ci->c->HasUserStatus(u, CMODE_PROTECT) || ci->c->HasUserStatus(u, CMODE_OWNER))) + else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (c->HasUserStatus(u, CMODE_HALFOP) || c->HasUserStatus(u, CMODE_OP) || c->HasUserStatus(u, CMODE_PROTECT) || c->HasUserStatus(u, CMODE_OWNER))) Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE)) + else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && c->HasUserStatus(u, CMODE_VOICE)) Allow = false; if (Allow) @@ -819,7 +938,7 @@ class BSKick : public Module /* Flood kicker */ if (ci->botflags.HasFlag(BS_KICK_FLOOD)) { - ud = botserv->GetUserData(u, ci->c); + ud = GetUserData(u, c); if (ud) { if (Anope::CurTime - ud->last_start > ci->floodsecs) @@ -842,7 +961,7 @@ class BSKick : public Module if (ci->botflags.HasFlag(BS_KICK_REPEAT)) { if (!ud) - ud = botserv->GetUserData(u, ci->c); + ud = GetUserData(u, c); if (ud) { @@ -871,13 +990,13 @@ class BSKick : public Module { for (UChannelList::iterator it = u->chans.begin(); it != u->chans.end();) { - Channel *c = (*it)->chan; + Channel *chan = (*it)->chan; ++it; - if (c->ci != NULL && c->ci->botflags.HasFlag(BS_KICK_AMSGS) && !check_access(u, c->ci, CA_NOKICK)) + if (chan->ci != NULL && chan->ci->botflags.HasFlag(BS_KICK_AMSGS) && !check_access(u, chan->ci, CA_NOKICK)) { - check_ban(c->ci, u, TTB_AMSGS); - bot_kick(c->ci, u, _("Don't use AMSGs!")); + check_ban(chan->ci, u, TTB_AMSGS); + bot_kick(chan->ci, u, _("Don't use AMSGs!")); } } } diff --git a/modules/core/bs_main.cpp b/modules/core/bs_main.cpp index b47b7e128..ff1e1f0d4 100644 --- a/modules/core/bs_main.cpp +++ b/modules/core/bs_main.cpp @@ -12,179 +12,28 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" -#include "chanserv.h" - -static BotInfo *BotServ = NULL; - -class BotServBotInfo : public BotInfo -{ - public: - BotServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } - - void OnMessage(User *u, const Anope::string &message) - { - spacesepstream sep(message); - Anope::string command, param; - if (sep.GetToken(command) && sep.GetToken(param)) - { - Command *c = FindCommand(this, command); - if (c && !c->HasFlag(CFLAG_STRIP_CHANNEL)) - { - if (ircdproto->IsChannelValid(param)) - { - ChannelInfo *ci = cs_findchan(param); - if (ci) - { - if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) - { - u->SendMessage(this, CHAN_X_SUSPENDED, ci->name.c_str()); - Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; - return; - } - } - else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL)) - { - u->SendMessage(this, CHAN_X_NOT_REGISTERED, param.c_str()); - return; - } - } - /* A user not giving a channel name for a param that should be a channel */ - else - { - u->SendMessage(this, CHAN_X_INVALID, param.c_str()); - return; - } - } - } - - BotInfo::OnMessage(u, message); - } -}; - -class MyBotServService : public BotServService -{ - public: - MyBotServService(Module *m) : BotServService(m) { } - - BotInfo *Bot() - { - return BotServ; - } - - UserData *GetUserData(User *u, Channel *c) - { - UserData *ud = NULL; - UserContainer *uc = c->FindUser(u); - if (uc != NULL) - { - if (!uc->GetExtPointer("bs_main_userdata", ud)) - { - ud = new UserData(); - uc->Extend("bs_main_userdata", new ExtensibleItemPointer<UserData>(ud)); - } - } - return ud; - } - - BanData *GetBanData(User *u, Channel *c) - { - std::map<Anope::string, BanData> bandatamap; - if (!c->GetExtRegular("bs_main_bandata", bandatamap)); - c->Extend("bs_main_bandata", new ExtensibleItemRegular<std::map<Anope::string, BanData> >(bandatamap)); - c->GetExtRegular("bs_main_bandata", bandatamap); - - BanData *bd = &bandatamap[u->GetMask()]; - if (bd->last_use && Anope::CurTime - bd->last_use > Config->BSKeepData) - bd->Clear(); - bd->last_use = Anope::CurTime; - return bd; - } -}; - -class BanDataPurger : public CallBack -{ - public: - BanDataPurger(Module *owner) : CallBack(owner, 300, Anope::CurTime, true) { } - - void Tick(time_t) - { - Log(LOG_DEBUG) << "bs_main: Running bandata purger"; - - for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - { - Channel *c = it->second; - - std::map<Anope::string, BanData> bandata; - if (c->GetExtRegular("bs_main_bandata", bandata)) - { - for (std::map<Anope::string, BanData>::iterator it2 = bandata.begin(), it2_end = bandata.end(); it2 != it2_end;) - { - const Anope::string &user = it->first; - BanData *bd = &it2->second; - ++it2; - - if (Anope::CurTime - bd->last_use > Config->BSKeepData) - { - bandata.erase(user); - continue; - } - } - - if (bandata.empty()) - c->Shrink("bs_main_bandata"); - } - } - } -}; class BotServCore : public Module { - MyBotServService mybotserv; - BanDataPurger bdpurger; - + Channel *fantasy_channel; public: - BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), mybotserv(this), bdpurger(this) + BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), fantasy_channel(NULL) { this->SetAuthor("Anope"); - ModuleManager::RegisterService(&this->mybotserv); + BotInfo *BotServ = findbot(Config->BotServ); + if (BotServ == NULL) + throw ModuleException("No bot named " + Config->BotServ); - BotServ = new BotServBotInfo(Config->s_BotServ, Config->ServiceUser, Config->ServiceHost, Config->desc_BotServ); - BotServ->SetFlag(BI_CORE); + Implementation i[] = { I_OnPrivmsg, I_OnPreCommand, I_OnJoinChannel, I_OnLeaveChannel, + I_OnPreHelp, I_OnPostHelp, I_OnChannelModeSet }; + ModuleManager::Attach(i, this, 7); - Implementation i[] = { I_OnPrivmsg }; - ModuleManager::Attach(i, this, 1); - - spacesepstream coreModules(Config->BotCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); } - ~BotServCore() + void OnPrivmsg(User *u, Channel *c, Anope::string &msg) { - for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) - { - cit->second->Shrink("bs_main_userdata"); - cit->second->Shrink("bs_main_bandata"); - } - - spacesepstream coreModules(Config->BotCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } - - delete BotServ; - } - - void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) - { - if (!u || !ci || !ci->c || !ci->bi || msg.empty()) + if (!u || !c || !c->ci || !c->ci->bi || msg.empty()) return; /* Answer to ping if needed */ @@ -193,7 +42,7 @@ class BotServCore : public Module Anope::string ctcp = msg; ctcp.erase(ctcp.begin()); ctcp.erase(ctcp.length() - 1); - ircdproto->SendCTCP(ci->bi, u->nick, "%s", ctcp.c_str()); + ircdproto->SendCTCP(c->ci->bi, u->nick, "%s", ctcp.c_str()); } @@ -211,7 +60,7 @@ class BotServCore : public Module return; /* Fantaisist commands */ - if (ci->botflags.HasFlag(BS_FANTASY) && realbuf[0] == Config->BSFantasyCharacter[0] && !was_action && chanserv) + if (c->ci->botflags.HasFlag(BS_FANTASY) && realbuf[0] == Config->BSFantasyCharacter[0] && !was_action) { /* Strip off the fantasy character */ realbuf.erase(realbuf.begin()); @@ -226,30 +75,129 @@ class BotServCore : public Module rest = realbuf.substr(space + 1); } - if (check_access(u, ci, CA_FANTASIA)) + BotInfo *bi = findbot(Config->ChanServ); + if (bi == NULL) + bi = findbot(Config->BotServ); + if (bi == NULL || !bi->commands.count(command)) + return; + + if (check_access(u, c->ci, CA_FANTASIA)) { - Command *cmd = FindCommand(chanserv->Bot(), command); - /* Command exists and can be called by fantasy */ - if (cmd && !cmd->HasFlag(CFLAG_DISABLE_FANTASY)) - { - Anope::string params = rest; - /* Some commands don't need the channel name added.. eg !help */ - if (!cmd->HasFlag(CFLAG_STRIP_CHANNEL)) - params = ci->name + " " + params; - params = command + " " + params; - - mod_run_cmd(chanserv->Bot(), u, ci, params); - } + this->fantasy_channel = c; + bi->OnMessage(u, realbuf); + this->fantasy_channel = NULL; - FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, ci, rest)); + FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, c->ci, rest)); } else { - FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, ci, rest)); + FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, c->ci, rest)); + } + } + } + + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) + { + if (this->fantasy_channel != NULL) + { + if (!command->HasFlag(CFLAG_STRIP_CHANNEL)) + params.insert(params.begin(), this->fantasy_channel->name); + source.c = this->fantasy_channel; + } + + return EVENT_CONTINUE; + } + + void OnJoinChannel(User *user, Channel *c) + { + if (c->ci && c->ci->bi) + { + /** + * We let the bot join even if it was an ignored user, as if we don't, + * and the ignored user doesnt just leave, the bot will never + * make it into the channel, leaving the channel botless even for + * legit users - Rob + **/ + if (c->users.size() >= Config->BSMinUsers && !c->FindUser(c->ci->bi)) + c->ci->bi->Join(c, &Config->BotModeList); + /* Only display the greet if the main uplink we're connected + * to has synced, or we'll get greet-floods when the net + * recovers from a netsplit. -GD + */ + if (c->FindUser(c->ci->bi) && c->ci->botflags.HasFlag(BS_GREET) && user->Account() && !user->Account()->greet.empty() && check_access(user, c->ci, CA_GREET) && user->server->IsSynced()) + { + ircdproto->SendPrivmsg(c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), user->Account()->greet.c_str()); + c->ci->bi->lastmsg = Anope::CurTime; } } } + + void OnLeaveChannel(User *u, Channel *c) + { + /* Channel is persistant, it shouldn't be deleted and the service bot should stay */ + if (c->HasFlag(CH_PERSIST) || (c->ci && c->ci->HasFlag(CI_PERSIST))) + return; + + /* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly + * We also don't part the bot here either, if necessary we will part it after the sync + */ + if (c->HasFlag(CH_SYNCING)) + return; + + /* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */ + if (c->HasFlag(CH_INHABIT)) + return; + + if (c->ci && c->ci->bi && c->users.size() - 1 <= Config->BSMinUsers && c->FindUser(c->ci->bi)) + { + bool persist = c->HasFlag(CH_PERSIST); + c->SetFlag(CH_PERSIST); + c->ci->bi->Part(c->ci->c); + if (!persist) + c->UnsetFlag(CH_PERSIST); + } + } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->BotServ) + return; + source.Reply(_("\002%s\002 allows you to have a bot on your own channel.\n" + "It has been created for users that can't host or\n" + "configure a bot, or for use on networks that don't\n" + "allow user bots. Available commands are listed \n" + "below; to use them, type \002%s%s \037command\037\002. For\n" + "more information on a specific command, type\n" + "\002%s%s %s \037command\037\002.\n "), + Config->BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->BotServ.c_str(), source.command.c_str()); + } + + void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->BotServ) + return; + source.Reply(_(" \n" + "Bot will join a channel whenever there is at least\n" + "\002%d\002 user(s) on it. Additionally, all %s commands\n" + "can be used if fantasy is enabled by prefixing the command\n" + "name with a %c."), Config->BSMinUsers, Config->ChanServ.c_str(), Config->BSFantasyCharacter[0]); + } + + EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) + { + if (Config->BSSmartJoin && Name == CMODE_BAN && c->ci && c->ci->bi && c->FindUser(c->ci->bi)) + { + BotInfo *bi = c->ci->bi; + + Entry ban(CMODE_BAN, param); + if (ban.Matches(bi)) + c->RemoveMode(bi, CMODE_BAN, param); + } + + return EVENT_CONTINUE; + } }; MODULE_INIT(BotServCore) diff --git a/modules/core/bs_say.cpp b/modules/core/bs_say.cpp deleted file mode 100644 index 56176a947..000000000 --- a/modules/core/bs_say.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "botserv.h" - -class CommandBSSay : public Command -{ - public: - CommandBSSay() : Command("SAY", 2, 2) - { - this->SetDesc(_("Makes the bot say the given text on the given channel")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &text = params[1]; - - User *u = source.u; - ChannelInfo *ci = source.ci; - - if (!check_access(u, ci, CA_SAY)) - { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; - } - - if (!ci->bi) - { - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); - return MOD_CONT; - } - - if (!ci->c || !ci->c->FindUser(ci->bi)) - { - source.Reply(_(BOT_NOT_ON_CHANNEL), ci->name.c_str()); - return MOD_CONT; - } - - if (text[0] == '\001') - { - this->OnSyntaxError(source, ""); - return MOD_CONT; - } - - ircdproto->SendPrivmsg(ci->bi, ci->name, "%s", text.c_str()); - ci->bi->lastmsg = Anope::CurTime; - - // XXX need a way to find if someone is overriding this - Log(LOG_COMMAND, u, this, ci) << text; - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002SAY \037channel\037 \037text\037\002\n" - " \n" - "Makes the bot say the given text on the given channel.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SAY", _("SAY \037channel\037 \037text\037")); - } -}; - -class BSSay : public Module -{ - CommandBSSay commandbssay; - - public: - BSSay(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbssay); - } -}; - -MODULE_INIT(BSSay) diff --git a/modules/core/bs_set.cpp b/modules/core/bs_set.cpp index 29a585113..0fbba874e 100644 --- a/modules/core/bs_set.cpp +++ b/modules/core/bs_set.cpp @@ -12,18 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "botserv.h" class CommandBSSet : public Command { public: - CommandBSSet() : Command("SET", 3, 3) + CommandBSSet(Module *creator) : Command(creator, "botserv/set", 3, 3) { - this->SetFlag(CFLAG_STRIP_CHANNEL); this->SetDesc(_("Configures bot options")); + this->SetSyntax(_("\037(channel | bot)\037 \037option\037 \037settings\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &option = params[1]; @@ -34,14 +33,14 @@ class CommandBSSet : public Command if (readonly) source.Reply(_("Sorry, bot option setting is temporarily disabled.")); - else if (u->HasCommand("botserv/set/private") && option.equals_ci("PRIVATE")) + else if (u->HasCommand("botserv/botserv/set/private") && option.equals_ci("PRIVATE")) { BotInfo *bi; if (!(bi = findbot(chan))) { - source.Reply(_(BOT_DOES_NOT_EXIST), chan.c_str()); - return MOD_CONT; + source.Reply(BOT_DOES_NOT_EXIST, chan.c_str()); + return; } if (value.equals_ci("ON")) @@ -55,13 +54,13 @@ class CommandBSSet : public Command source.Reply(_("Private mode of bot %s is now \002off\002."), bi->nick.c_str()); } else - SyntaxError(source, "SET PRIVATE", _("SET \037botname\037 PRIVATE {\037ON|\037}")); - return MOD_CONT; + this->OnSyntaxError(source, "PRIVATE"); + return; } else if (!(ci = cs_findchan(chan))) - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); else if (!u->HasPriv("botserv/administration") && !check_access(u, ci, CA_SET)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { bool override = !check_access(u, ci, CA_SET); @@ -80,7 +79,7 @@ class CommandBSSet : public Command source.Reply(_("Bot \002will kick ops\002 on channel %s."), ci->name.c_str()); } else - SyntaxError(source, "SET DONTKICKOPS", _("SET \037channel\037 DONTKICKOPS {\037ON|\037}")); + this->OnSyntaxError(source, "DONTKICKOPS"); } else if (option.equals_ci("DONTKICKVOICES")) { @@ -95,7 +94,7 @@ class CommandBSSet : public Command source.Reply(_("Bot \002will kick voices\002 on channel %s."), ci->name.c_str()); } else - SyntaxError(source, "SET DONTKICKVOICES", _("SET \037channel\037 DONTKICKVOICES {\037ON|\037}")); + this->OnSyntaxError(source, "DONTKICKVOICE"); } else if (option.equals_ci("FANTASY")) { @@ -110,7 +109,7 @@ class CommandBSSet : public Command source.Reply(_("Fantasy mode is now \002off\002 on channel %s."), ci->name.c_str()); } else - SyntaxError(source, "SET FANTASY", _("SET \037channel\037 FANTASY {\037ON|\037}")); + this->OnSyntaxError(source, "FANTASY"); } else if (option.equals_ci("GREET")) { @@ -125,9 +124,9 @@ class CommandBSSet : public Command source.Reply(_("Greet mode is now \002off\002 on channel %s."), ci->name.c_str()); } else - SyntaxError(source, "SET GREET", _("SET \037channel\037 GREET {\037ON|\037}")); + this->OnSyntaxError(source, "GREET"); } - else if (u->HasCommand("botserv/set/nobot") && option.equals_ci("NOBOT")) + else if (u->HasCommand("botserv/botserv/set/nobot") && option.equals_ci("NOBOT")) { if (value.equals_ci("ON")) { @@ -142,22 +141,7 @@ class CommandBSSet : public Command source.Reply(_("No Bot mode is now \002off\002 on channel %s."), ci->name.c_str()); } else - SyntaxError(source, "SET NOBOT", _("SET \037botname\037 NOBOT {\037ON|\037}")); - } - else if (option.equals_ci("SYMBIOSIS")) - { - if (value.equals_ci("ON")) - { - ci->botflags.SetFlag(BS_SYMBIOSIS); - source.Reply(_("Symbiosis mode is now \002on\002 on channel %s."), ci->name.c_str()); - } - else if (value.equals_ci("OFF")) - { - ci->botflags.UnsetFlag(BS_SYMBIOSIS); - source.Reply(_("Symbiosis mode is now \002off\002 on channel %s."), ci->name.c_str()); - } - else - SyntaxError(source, "SET SYMBIOSIS", _("SET \037channel\037 SYMBIOSIS {\037ON|\037}")); + this->OnSyntaxError(source, "NOBOT"); } else if (option.equals_ci("MSG")) { @@ -190,34 +174,33 @@ class CommandBSSet : public Command source.Reply(_("Fantasy replies will be sent via NOTICE to channel ops on %s."), ci->name.c_str()); } else - SyntaxError(source, "SET MSG", _("SET \037channel\037 MSG {\037OFF|PRIVMSG|NOTICE|\037}")); + this->OnSyntaxError(source, "MSG"); } else - source.Reply(_(UNKNOWN_OPTION), option.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str(), this->name.c_str()); + source.Reply(UNKNOWN_OPTION, option.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), this->name.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { if (subcommand.empty()) { - source.Reply(_("Syntax: \002SET \037(channel | bot)\037 \037option\037 \037parameters\037\002\n" - " \n" - "Configures bot options. \037option\037 can be one of:\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Configures bot options. \037option\037 can be one of:\n" " \n" " DONTKICKOPS To protect ops against bot kicks\n" " DONTKICKVOICES To protect voices against bot kicks\n" " GREET Enable greet messages\n" " FANTASY Enable fantaisist commands\n" - " SYMBIOSIS Allow the bot to act as a real bot\n" " MSG Configure how fantasy commands should be replied to\n" " \n" "Type \002%s%s HELP SET \037option\037\002 for more information\n" "on a specific option.\n" "Note: access to this command is controlled by the\n" - "level SET."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); + "level SET."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); User *u = source.u; if (u->IsServicesOper()) source.Reply(_("These options are reserved to Services Operators:\n" @@ -261,13 +244,6 @@ class CommandBSSet : public Command "When it is enabled, the bot will display greet\n" "messages of users joining the channel, provided\n" "they have enough access to the channel.")); - else if (subcommand.equals_ci("SYMBIOSIS")) - source.Reply(_("Syntax: \002SET \037channel\037 SYMBIOSIS {\037ON|OFF\037}\n" - " \n" - "Enables or disables \002symbiosis\002 mode on a channel.\n" - "When it is enabled, the bot will do everything\n" - "normally done by %s on channels, such as MODEs,\n" - "KICKs, and even the entry message."), Config->s_ChanServ.c_str()); else if (subcommand.equals_ci("NOBOT")) source.Reply(_("Syntax: \002SET \037channel\037 NOBOT {\037ON|OFF\037}\002\n" " \n" @@ -295,7 +271,22 @@ class CommandBSSet : public Command void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { - SyntaxError(source, "SET", _("SET \037(channel | bot)\037 \037option\037 \037settings\037")); + if (subcommand.empty()) + Command::OnSyntaxError(source, ""); + else if (subcommand.equals_ci("PRIVATE")) + this->SendSyntax(source, "\037botname\037 PRIVATE {\037ON|OFF\037}"); + else if (subcommand.equals_ci("DONTKICKOPS")) + this->SendSyntax(source, "\037channel\037 DONTKICKOPS {\037ON|OFF\037}"); + else if (subcommand.equals_ci("DONTKICKVOICES")) + this->SendSyntax(source, "\037channel\037 DONTKICKVOICES {\037ON|OFF\037}"); + else if (subcommand.equals_ci("FANTASY")) + this->SendSyntax(source, "\037channel\037 FANTASY {\037ON|OFF\037}"); + else if (subcommand.equals_ci("GREET")) + this->SendSyntax(source, "\037channel\037 GREET {\037ON|OFF\037}"); + else if (subcommand.equals_ci("MSG")) + this->SendSyntax(source, "\037botname\037 NOBOT {\037ON|OFF\037}"); + else if (subcommand.equals_ci("NOBOT")) + this->SendSyntax(source, "\037botname\037 NOBOT {\037ON|OFF\037}"); } }; @@ -304,14 +295,12 @@ class BSSet : public Module CommandBSSet commandbsset; public: - BSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + BSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandbsset(this) { this->SetAuthor("Anope"); - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsset); + ModuleManager::RegisterService(&commandbsset); } }; diff --git a/modules/core/bs_unassign.cpp b/modules/core/bs_unassign.cpp deleted file mode 100644 index 6fe62d838..000000000 --- a/modules/core/bs_unassign.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "botserv.h" - -class CommandBSUnassign : public Command -{ - public: - CommandBSUnassign() : Command("UNASSIGN", 1, 1) - { - this->SetDesc(_("Unassigns a bot from a channel")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PERM); - - User *u = source.u; - ChannelInfo *ci = source.ci; - - if (readonly) - source.Reply(_(BOT_ASSIGN_READONLY)); - else if (!u->HasPriv("botserv/administration") && !check_access(u, ci, CA_ASSIGN)) - source.Reply(_(ACCESS_DENIED)); - else if (!ci->bi) - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); - else if (ci->HasFlag(CI_PERSIST) && !cm) - source.Reply(_("You can not unassign bots while persist is set on the channel.")); - else - { - bool override = !check_access(u, ci, CA_ASSIGN); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "for " << ci->bi->nick; - - ci->bi->UnAssign(u, ci); - source.Reply(_("There is no bot assigned to %s anymore."), ci->name.c_str()); - } - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002UNASSIGN \037chan\037\002\n" - " \n" - "Unassigns a bot from a channel. When you use this command,\n" - "the bot won't join the channel anymore. However, bot\n" - "configuration for the channel is kept, so you will always\n" - "be able to reassign a bot later without have to reconfigure\n" - "it entirely.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "UNASSIGN", _("UNASSIGN \037chan\037")); - } -}; - -class BSUnassign : public Module -{ - CommandBSUnassign commandbsunassign; - - public: - BSUnassign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!botserv) - throw ModuleException("BotServ is not loaded!"); - - this->AddCommand(botserv->Bot(), &commandbsunassign); - } -}; - -MODULE_INIT(BSUnassign) diff --git a/modules/core/chanserv.h b/modules/core/chanserv.h deleted file mode 100644 index 2017aa156..000000000 --- a/modules/core/chanserv.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CHANSERV_H -#define CHANSERV_H - -class ChanServService : public Service -{ - public: - ChanServService(Module *m) : Service(m, "ChanServ") { } - - virtual BotInfo *Bot() = 0; -}; - -static service_reference<ChanServService> chanserv("ChanServ"); - -#endif // CHANSERV_H - diff --git a/modules/core/cs_access.cpp b/modules/core/cs_access.cpp index 9e3af6eeb..06cb7299d 100644 --- a/modules/core/cs_access.cpp +++ b/modules/core/cs_access.cpp @@ -12,43 +12,43 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class AccessListCallback : public NumberList { protected: CommandSource &source; + ChannelInfo *ci; bool SentHeader; public: - AccessListCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), source(_source), SentHeader(false) + AccessListCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), source(_source), ci(_ci), SentHeader(false) { } ~AccessListCallback() { if (SentHeader) - source.Reply(_("End of access list."), source.ci->name.c_str()); + source.Reply(_("End of access list."), ci->name.c_str()); else - source.Reply(_("No matching entries on %s access list."), source.ci->name.c_str()); + source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); } virtual void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAccessCount()) + if (!Number || Number > ci->GetAccessCount()) return; if (!SentHeader) { SentHeader = true; - source.Reply(_(CHAN_ACCESS_LIST_HEADER), source.ci->name.c_str()); + source.Reply(CHAN_ACCESS_LIST_HEADER, ci->name.c_str()); } - DoList(source, Number - 1, source.ci->GetAccess(Number - 1)); + DoList(source, ci, Number - 1, ci->GetAccess(Number - 1)); } - static void DoList(CommandSource &source, unsigned Number, ChanAccess *access) + static void DoList(CommandSource &source, ChannelInfo *ci, unsigned Number, ChanAccess *access) { - if (source.ci->HasFlag(CI_XOP)) + if (ci->HasFlag(CI_XOP)) { Anope::string xop = get_xop_level(access->level); source.Reply(_(" %3d %s %s"), Number + 1, xop.c_str(), access->GetMask().c_str()); @@ -61,27 +61,26 @@ class AccessListCallback : public NumberList class AccessViewCallback : public AccessListCallback { public: - AccessViewCallback(CommandSource &_source, const Anope::string &numlist) : AccessListCallback(_source, numlist) + AccessViewCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &numlist) : AccessListCallback(_source, _ci, numlist) { } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAccessCount()) + if (!Number || Number > ci->GetAccessCount()) return; if (!SentHeader) { SentHeader = true; - source.Reply(_(CHAN_ACCESS_LIST_HEADER), source.ci->name.c_str()); + source.Reply(CHAN_ACCESS_LIST_HEADER, ci->name.c_str()); } - DoList(source, Number - 1, source.ci->GetAccess(Number - 1)); + DoList(source, ci, Number - 1, ci->GetAccess(Number - 1)); } - static void DoList(CommandSource &source, unsigned Number, ChanAccess *access) + static void DoList(CommandSource &source, ChannelInfo *ci, unsigned Number, ChanAccess *access) { - ChannelInfo *ci = source.ci; Anope::string timebuf; if (ci->c && nc_on_chan(ci->c, access->nc)) timebuf = "Now"; @@ -93,52 +92,52 @@ class AccessViewCallback : public AccessListCallback if (ci->HasFlag(CI_XOP)) { Anope::string xop = get_xop_level(access->level); - source.Reply(_(CHAN_ACCESS_VIEW_XOP_FORMAT), Number + 1, xop.c_str(), access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str()); + source.Reply(CHAN_ACCESS_VIEW_XOP_FORMAT, Number + 1, xop.c_str(), access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str()); } else - source.Reply(_(CHAN_ACCESS_VIEW_AXS_FORMAT), Number + 1, access->level, access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str()); + source.Reply(CHAN_ACCESS_VIEW_AXS_FORMAT, Number + 1, access->level, access->GetMask().c_str(), access->creator.c_str(), timebuf.c_str()); } }; class AccessDelCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; Command *c; unsigned Deleted; Anope::string Nicks; bool Denied; bool override; public: - AccessDelCallback(CommandSource &_source, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), c(_c), Deleted(0), Denied(false) + AccessDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), Deleted(0), Denied(false) { - if (!check_access(source.u, source.ci, CA_ACCESS_CHANGE) && source.u->HasPriv("chanserv/access/modify")) + if (!check_access(source.u, ci, CA_ACCESS_CHANGE) && source.u->HasPriv("chanserv/access/modify")) this->override = true; } ~AccessDelCallback() { if (Denied && !Deleted) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!Deleted) - source.Reply(_("No matching entries on %s access list."), source.ci->name.c_str()); + source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); else { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, source.ci) << "for user" << (Deleted == 1 ? " " : "s ") << Nicks; + Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, ci) << "for user" << (Deleted == 1 ? " " : "s ") << Nicks; if (Deleted == 1) - source.Reply(_("Deleted 1 entry from %s access list."), source.ci->name.c_str()); + source.Reply(_("Deleted 1 entry from %s access list."), ci->name.c_str()); else - source.Reply(_("Deleted %d entries from %s access list."), Deleted, source.ci->name.c_str()); + source.Reply(_("Deleted %d entries from %s access list."), Deleted, ci->name.c_str()); } } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAccessCount()) + if (!Number || Number > ci->GetAccessCount()) return; User *u = source.u; - ChannelInfo *ci = source.ci; ChanAccess *access = ci->GetAccess(Number - 1); @@ -164,10 +163,9 @@ class AccessDelCallback : public NumberList class CommandCSAccess : public Command { - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; Anope::string mask = params[2]; int level = ACCESS_INVALID; @@ -182,19 +180,19 @@ class CommandCSAccess : public Command int16 u_level = u_access ? u_access->level : 0; if (level >= u_level && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (!level) { source.Reply(_("Access level must be non-zero.")); - return MOD_CONT; + return; } else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { - source.Reply(_(CHAN_ACCESS_LEVEL_RANGE), ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); - return MOD_CONT; + source.Reply(CHAN_ACCESS_LEVEL_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + return; } bool override = !check_access(u, ci, CA_ACCESS_CHANGE) || level >= u_level; @@ -209,13 +207,13 @@ class CommandCSAccess : public Command /* Don't allow lowering from a level >= u_level */ if (access->level >= u_level && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (access->level == level) { source.Reply(_("Access level for \002%s\002 on %s unchanged from \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level); - return MOD_CONT; + return; } access->level = level; @@ -223,13 +221,13 @@ class CommandCSAccess : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level; source.Reply(_("Access level for \002%s\002 on %s changed to \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level); - return MOD_CONT; + return; } if (ci->GetAccessCount() >= Config->CSAccessMax) { source.Reply(_("Sorry, you can only have %d access entries on a channel."), Config->CSAccessMax); - return MOD_CONT; + return; } access = ci->AddAccess(mask, level, u->nick); @@ -239,13 +237,12 @@ class CommandCSAccess : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "ADD " << mask << " (level: " << level << ") as level " << u_level; source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->GetMask().c_str(), ci->name.c_str(), level); - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &mask = params[2]; @@ -253,7 +250,7 @@ class CommandCSAccess : public Command source.Reply(_("%s access list is empty."), ci->name.c_str()); else if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { - AccessDelCallback list(source, this, mask); + AccessDelCallback list(source, ci, this, mask); list.Process(); } else @@ -264,7 +261,7 @@ class CommandCSAccess : public Command if (!access) source.Reply(_("\002%s\002 not found on %s access list."), mask.c_str(), ci->name.c_str()); else if (access->nc != u->Account() && check_access(u, ci, CA_NOJOIN) && u_level <= access->level && !u->HasPriv("chanserv/access/modify")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { source.Reply(_("\002%s\002 deleted from %s access list."), access->GetMask().c_str(), ci->name.c_str()); @@ -277,20 +274,18 @@ class CommandCSAccess : public Command } } - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - const Anope::string &nick = params.size() > 2 ? params[2] : ""; if (!ci->GetAccessCount()) source.Reply(_("%s access list is empty."), ci->name.c_str()); else if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos) { - AccessListCallback list(source, nick); + AccessListCallback list(source, ci, nick); list.Process(); } else @@ -307,10 +302,10 @@ class CommandCSAccess : public Command if (!SentHeader) { SentHeader = true; - source.Reply(_(CHAN_ACCESS_LIST_HEADER), ci->name.c_str()); + source.Reply(CHAN_ACCESS_LIST_HEADER, ci->name.c_str()); } - AccessListCallback::DoList(source, i, access); + AccessListCallback::DoList(source, ci, i, access); } if (SentHeader) @@ -319,20 +314,18 @@ class CommandCSAccess : public Command source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoView(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - const Anope::string &nick = params.size() > 2 ? params[2] : ""; if (!ci->GetAccessCount()) source.Reply(_("%s access list is empty."), ci->name.c_str()); else if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos) { - AccessViewCallback list(source, nick); + AccessViewCallback list(source, ci, nick); list.Process(); } else @@ -349,10 +342,10 @@ class CommandCSAccess : public Command if (!SentHeader) { SentHeader = true; - source.Reply(_(CHAN_ACCESS_LIST_HEADER), ci->name.c_str()); + source.Reply(CHAN_ACCESS_LIST_HEADER, ci->name.c_str()); } - AccessViewCallback::DoList(source, i, access); + AccessViewCallback::DoList(source, ci, i, access); } if (SentHeader) @@ -361,16 +354,15 @@ class CommandCSAccess : public Command source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoClear(CommandSource &source) + void DoClear(CommandSource &source, ChannelInfo *ci) { User *u = source.u; - ChannelInfo *ci = source.ci; if (!IsFounder(u, ci) && !u->HasPriv("chanserv/access/modify")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { ci->ClearAccess(); @@ -383,23 +375,33 @@ class CommandCSAccess : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "CLEAR"; } - return MOD_CONT; + return; } public: - CommandCSAccess() : Command("ACCESS", 2, 4) + CommandCSAccess(Module *creator) : Command(creator, "chanserv/access", 2, 4) { this->SetDesc(_("Modify the list of privileged users")); + this->SetSyntax(_("\037channel\037 ADD \037mask\037 \037level\037")); + this->SetSyntax(_("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); + this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]")); + this->SetSyntax(_("\037channel\037 VIEW [\037mask\037 | \037list\037]")); + this->SetSyntax(_("\037channel\037 CLEAR\002")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[1]; const Anope::string &nick = params.size() > 2 ? params[2] : ""; const Anope::string &s = params.size() > 3 ? params[3] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } bool is_list = cmd.equals_ci("LIST") || cmd.equals_ci("VIEW"); bool is_clear = cmd.equals_ci("CLEAR"); @@ -425,54 +427,49 @@ class CommandCSAccess : public Command if (is_list || is_clear ? 0 : (cmd.equals_ci("DEL") ? (nick.empty() || !s.empty()) : s.empty())) this->OnSyntaxError(source, cmd); else if (!has_access) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); /* We still allow LIST and CLEAR in xOP mode, but not others */ else if (ci->HasFlag(CI_XOP) && !is_list && !is_clear) { if (ModeManager::FindChannelModeByName(CMODE_HALFOP)) source.Reply(_("You can't use this command. \n" "Use the AOP, SOP, HOP and VOP commands instead.\n" - "Type \002%s%s HELP \037command\037\002 for more information."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "Type \002%s%s HELP \037command\037\002 for more information."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); else source.Reply(_("You can't use this command. \n" "Use the AOP, SOP and VOP commands instead.\n" - "Type \002%s%s HELP \037command\037\002 for more information."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "Type \002%s%s HELP \037command\037\002 for more information."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); } else if (readonly && !is_list) source.Reply(_("Sorry, channel access list modification is temporarily disabled.")); else if (cmd.equals_ci("ADD")) - this->DoAdd(source, params); + this->DoAdd(source, ci, params); else if (cmd.equals_ci("DEL")) - this->DoDel(source, params); + this->DoDel(source, ci, params); else if (cmd.equals_ci("LIST")) - this->DoList(source, params); + this->DoList(source, ci, params); else if (cmd.equals_ci("VIEW")) - this->DoView(source, params); + this->DoView(source, ci, params); else if (cmd.equals_ci("CLEAR")) - this->DoClear(source); + this->DoClear(source, ci); else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ACCESS \037channel\037 ADD \037mask\037 \037level\037\002\n" - " \002ACCESS \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002ACCESS \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002ACCESS \037channel\037 VIEW [\037mask\037 | \037list\037]\002\n" - " \002ACCESS \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002access list\002 for a channel. The access\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002access list\002 for a channel. The access\n" "list specifies which users are allowed chanop status or\n" "access to %s commands on the channel. Different\n" "user levels allow for access to different subsets of\n" - "privileges; \002%s%s HELP ACCESS LEVELS\002 for more\n" - "specific information. Any nick not on the access list has\n" - "a user level of 0.\n" - " \n" - "The \002ACCESS ADD\002 command adds the given mask to the\n" + "privileges. Any nick not on the access list has\n" + "a user level of 0.")); + source.Reply(" "); + source.Reply(_("The \002ACCESS ADD\002 command adds the given mask to the\n" "access list with the given user level; if the mask is\n" "already present on the list, its access level is changed to\n" "the level specified in the command. The \037level\037 specified\n" @@ -481,15 +478,15 @@ class CommandCSAccess : public Command "access level of that nick must be less than the access level\n" "of the user giving the command. When a user joins the channel\n" "the access they receive is from the highest level entry in the\n" - "access list.\n" - " \n" - "The \002ACCESS DEL\002 command removes the given nick from the\n" + "access list.")); + source.Reply(" "); + source.Reply(_("The \002ACCESS DEL\002 command removes the given nick from the\n" "access list. If a list of entry numbers is given, those\n" "entries are deleted. (See the example for LIST below.)\n" "You may remove yourself from an access list, even if you\n" - "do not have access to modify that list otherwise.\n" - " \n" - "The \002ACCESS LIST\002 command displays the access list. If\n" + "do not have access to modify that list otherwise.")); + source.Reply(" "); + source.Reply(_("The \002ACCESS LIST\002 command displays the access list. If\n" "a wildcard mask is given, only those entries matching the\n" "mask are displayed. If a list of entry numbers is given,\n" "only those entries are shown; for example:\n" @@ -502,7 +499,7 @@ class CommandCSAccess : public Command " \n" "The \002ACCESS CLEAR\002 command clears all entries of the\n" "access list."), - Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + source.owner->nick.c_str()); source.Reply(_("\002User access levels\002\n" " \n" "By default, the following access levels are defined:\n" @@ -521,22 +518,16 @@ class CommandCSAccess : public Command " \n" "These levels may be changed, or new ones added, using the\n" "\002LEVELS\002 command; type \002%s%s HELP LEVELS\002 for\n" - "information."), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "information."), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "ACCESS", _("ACCESS \037channel\037 {ADD|DEL|LIST|VIEW|CLEAR} [\037mask\037 [\037level\037] | \037entry-list\037]")); - } }; class CommandCSLevels : public Command { - CommandReturn DoSet(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSet(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &what = params[2]; const Anope::string &lev = params[3]; @@ -555,7 +546,7 @@ class CommandCSLevels : public Command catch (const ConvertException &) { this->OnSyntaxError(source, "SET"); - return MOD_CONT; + return; } } @@ -577,20 +568,19 @@ class CommandCSLevels : public Command source.Reply(_("Level for %s on channel %s changed to founder only."), levelinfo[i].name.c_str(), ci->name.c_str()); else source.Reply(_("Level for \002%s\002 on channel %s changed to \002%d\002."), levelinfo[i].name.c_str(), ci->name.c_str(), level); - return MOD_CONT; + return; } } - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoDisable(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDisable(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &what = params[2]; @@ -607,19 +597,17 @@ class CommandCSLevels : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "DISABLE " << levelinfo[i].name; source.Reply(_("\002%s\002 disabled on channel %s."), levelinfo[i].name.c_str(), ci->name.c_str()); - return MOD_CONT; + return; } } - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS \002 for a list of valid settings."), what.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source) + void DoList(CommandSource &source, ChannelInfo *ci) { - ChannelInfo *ci = source.ci; - source.Reply(_("Access level settings for channel %s:"), ci->name.c_str()); if (!levelinfo_maxwidth) @@ -646,13 +634,12 @@ class CommandCSLevels : public Command source.Reply(_(" %-*s %d"), levelinfo_maxwidth, levelinfo[i].name.c_str(), j); } - return MOD_CONT; + return; } - CommandReturn DoReset(CommandSource &source) + void DoReset(CommandSource &source, ChannelInfo *ci) { User *u = source.u; - ChannelInfo *ci = source.ci; reset_levels(ci); FOREACH_MOD(I_OnLevelChange, OnLevelChange(u, ci, -1, 0)); @@ -661,23 +648,33 @@ class CommandCSLevels : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "RESET"; source.Reply(_("Access levels for \002%s\002 reset to defaults."), ci->name.c_str()); - return MOD_CONT; + return; } public: - CommandCSLevels() : Command("LEVELS", 2, 4) + CommandCSLevels(Module *creator) : Command(creator, "chanserv/levels", 2, 4) { this->SetDesc(_("Redefine the meanings of access levels")); + this->SetSyntax(_("\037channel\037 SET \037type\037 \037level\037")); + this->SetSyntax(_("\037channel\037 {DIS | DISABLE} \037type\037")); + this->SetSyntax(_("\037channel\037 LIST")); + this->SetSyntax(_("\037channel\037 RESET")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[1]; const Anope::string &what = params.size() > 2 ? params[2] : ""; const Anope::string &s = params.size() > 3 ? params[3] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } /* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only * one; else, we want none. @@ -687,19 +684,19 @@ class CommandCSLevels : public Command else if (ci->HasFlag(CI_XOP)) source.Reply(_("Levels are not available as xOP is enabled on this channel.")); else if (!check_access(u, ci, CA_FOUNDER) && !u->HasPriv("chanserv/access/modify")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (cmd.equals_ci("SET")) - this->DoSet(source, params); + this->DoSet(source, ci, params); else if (cmd.equals_ci("DIS") || cmd.equals_ci("DISABLE")) - this->DoDisable(source, params); + this->DoDisable(source, ci, params); else if (cmd.equals_ci("LIST")) - this->DoList(source); + this->DoList(source, ci); else if (cmd.equals_ci("RESET")) - this->DoReset(source); + this->DoReset(source, ci); else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -721,12 +718,10 @@ class CommandCSLevels : public Command source.Reply(_(" %-*s %s"), levelinfo_maxwidth, levelinfo[i].name.c_str(), translate(source.u, levelinfo[i].desc)); } else - source.Reply(_("Syntax: \002LEVELS \037channel\037 SET \037type\037 \037level\037\002\n" - " \002LEVELS \037channel\037 {DIS | DISABLE} \037type\037\002\n" - " \002LEVELS \037channel\037 LIST\002\n" - " \002LEVELS \037channel\037 RESET\002\n" - " \n" - "The \002LEVELS\002 command allows fine control over the meaning of\n" + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("The \002LEVELS\002 command allows fine control over the meaning of\n" "the numeric access levels used for channels. With this\n" "command, you can define the access level required for most\n" "of %s's functions. (The \002SET FOUNDER\002 and this command\n" @@ -744,14 +739,10 @@ class CommandCSLevels : public Command "\002HELP ACCESS LEVELS\002).\n" " \n" "For a list of the features and functions whose levels can be\n" - "set, see \002HELP LEVELS DESC\002."), Config->s_ChanServ.c_str()); + "set, see \002HELP LEVELS DESC\002."), source.owner->nick.c_str()); + } return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LEVELS", _("LEVELS \037channel\037 {SET | DIS[ABLE] | LIST | RESET} [\037item\037 [\037level\037]]")); - } }; class CSAccess : public Module @@ -760,15 +751,13 @@ class CSAccess : public Module CommandCSLevels commandcslevels; public: - CSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsaccess(this), commandcslevels(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsaccess); - this->AddCommand(chanserv->Bot(), &commandcslevels); + ModuleManager::RegisterService(&commandcsaccess); + ModuleManager::RegisterService(&commandcslevels); } }; diff --git a/modules/core/cs_akick.cpp b/modules/core/cs_akick.cpp index 1b629a83b..2a2ca8fa2 100644 --- a/modules/core/cs_akick.cpp +++ b/modules/core/cs_akick.cpp @@ -12,12 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" - -/* Split a usermask up into its constitutent parts. Returned strings are - * malloc()'d, and should be free()'d when done with. Returns "*" for - * missing parts. - */ static void split_usermask(const Anope::string &mask, Anope::string &nick, Anope::string &user, Anope::string &host) { @@ -56,69 +50,70 @@ class AkickListCallback : public NumberList { protected: CommandSource &source; + ChannelInfo *ci; bool SentHeader; public: - AkickListCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), source(_source), SentHeader(false) + AkickListCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), source(_source), ci(_ci), SentHeader(false) { } ~AkickListCallback() { if (!SentHeader) - source.Reply(_("No matching entries on %s autokick list."), source.ci->name.c_str()); + source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str()); } virtual void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAkickCount()) + if (!Number || Number > ci->GetAkickCount()) return; if (!SentHeader) { SentHeader = true; - source.Reply(_("Autokick list for %s:"), source.ci->name.c_str()); + source.Reply(_("Autokick list for %s:"), ci->name.c_str()); } - DoList(source, Number - 1, source.ci->GetAkick(Number - 1)); + DoList(source, ci, Number - 1, ci->GetAkick(Number - 1)); } - static void DoList(CommandSource &source, unsigned index, AutoKick *akick) + static void DoList(CommandSource &source, ChannelInfo *ci, unsigned index, AutoKick *akick) { - source.Reply(_(" %3d %s (%s)"), index + 1, akick->HasFlag(AK_ISNICK) ? akick->nc->display.c_str() : akick->mask.c_str(), !akick->reason.empty() ? akick->reason.c_str() : _(NO_REASON)); + source.Reply(_(" %3d %s (%s)"), index + 1, akick->HasFlag(AK_ISNICK) ? akick->nc->display.c_str() : akick->mask.c_str(), !akick->reason.empty() ? akick->reason.c_str() : NO_REASON); } }; class AkickViewCallback : public AkickListCallback { public: - AkickViewCallback(CommandSource &_source, const Anope::string &numlist) : AkickListCallback(_source, numlist) + AkickViewCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &numlist) : AkickListCallback(_source, _ci, numlist) { } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAkickCount()) + if (!Number || Number > ci->GetAkickCount()) return; if (!SentHeader) { SentHeader = true; - source.Reply(_("Autokick list for %s:"), source.ci->name.c_str()); + source.Reply(_("Autokick list for %s:"), ci->name.c_str()); } - DoList(source, Number - 1, source.ci->GetAkick(Number - 1)); + DoList(source, ci, Number - 1, ci->GetAkick(Number - 1)); } - static void DoList(CommandSource &source, unsigned index, AutoKick *akick) + static void DoList(CommandSource &source, ChannelInfo *ci, unsigned index, AutoKick *akick) { Anope::string timebuf; if (akick->addtime) timebuf = do_strftime(akick->addtime); else - timebuf = _(UNKNOWN); + timebuf = UNKNOWN; - source.Reply(_(CHAN_AKICK_VIEW_FORMAT), index + 1, akick->HasFlag(AK_ISNICK) ? akick->nc->display.c_str() : akick->mask.c_str(), !akick->creator.empty() ? akick->creator.c_str() : UNKNOWN, timebuf.c_str(), !akick->reason.empty() ? akick->reason.c_str() : _(NO_REASON)); + source.Reply(CHAN_AKICK_VIEW_FORMAT, index + 1, akick->HasFlag(AK_ISNICK) ? akick->nc->display.c_str() : akick->mask.c_str(), !akick->creator.empty() ? akick->creator.c_str() : UNKNOWN, timebuf.c_str(), !akick->reason.empty() ? akick->reason.c_str() : _(NO_REASON)); if (akick->last_used) source.Reply(_(" Last used %s"), do_strftime(akick->last_used).c_str()); @@ -128,17 +123,17 @@ class AkickViewCallback : public AkickListCallback class AkickDelCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; Command *c; unsigned Deleted; public: - AkickDelCallback(CommandSource &_source, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), c(_c), Deleted(0) + AkickDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), Deleted(0) { } ~AkickDelCallback() { User *u = source.u; - ChannelInfo *ci = source.ci; bool override = !check_access(u, ci, CA_AKICK); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, c, ci) << "DEL on " << Deleted << " users"; @@ -152,20 +147,19 @@ class AkickDelCallback : public NumberList void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAkickCount()) + if (!Number || Number > ci->GetAkickCount()) return; ++Deleted; - source.ci->EraseAkick(Number - 1); + ci->EraseAkick(Number - 1); } }; class CommandCSAKick : public Command { - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; Anope::string mask = params[2]; Anope::string reason = params.size() > 3 ? params[3] : ""; @@ -191,7 +185,7 @@ class CommandCSAKick : public Command { if (Anope::Match(modes.first->second, mask)) { - source.Reply(_(CHAN_EXCEPTED), mask.c_str(), ci->name.c_str()); + source.Reply(CHAN_EXCEPTED, mask.c_str(), ci->name.c_str()); return; } } @@ -205,7 +199,7 @@ class CommandCSAKick : public Command int16 nc_level = nc_access ? nc_access->level : 0, u_level = u_access ? u_access->level : 0; if (nc == ci->GetFounder() || nc_level >= u_level) { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); return; } } @@ -223,7 +217,7 @@ class CommandCSAKick : public Command if ((check_access(u2, ci, CA_FOUNDER) || u2_level >= u_level) && entry_mask.Matches(u2)) { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); return; } } @@ -241,7 +235,7 @@ class CommandCSAKick : public Command Anope::string buf = na->nick + "!" + na->last_usermask; if (Anope::Match(buf, mask)) { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); return; } } @@ -276,13 +270,12 @@ class CommandCSAKick : public Command source.Reply(_("\002%s\002 added to %s autokick list."), mask.c_str(), ci->name.c_str()); - this->DoEnforce(source); + this->DoEnforce(source, ci); } - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &mask = params[2]; AutoKick *akick; @@ -297,7 +290,7 @@ class CommandCSAKick : public Command /* Special case: is it a number/list? Only do search if it isn't. */ if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { - AkickDelCallback list(source, this, mask); + AkickDelCallback list(source, ci, this, mask); list.Process(); } else @@ -328,10 +321,9 @@ class CommandCSAKick : public Command } } - void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &mask = params.size() > 2 ? params[2] : ""; @@ -346,7 +338,7 @@ class CommandCSAKick : public Command if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { - AkickListCallback list(source, mask); + AkickListCallback list(source, ci, mask); list.Process(); } else @@ -371,7 +363,7 @@ class CommandCSAKick : public Command source.Reply(_("Autokick list for %s:"), ci->name.c_str()); } - AkickListCallback::DoList(source, i, akick); + AkickListCallback::DoList(source, ci, i, akick); } if (!SentHeader) @@ -379,10 +371,9 @@ class CommandCSAKick : public Command } } - void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoView(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &mask = params.size() > 2 ? params[2] : ""; @@ -397,7 +388,7 @@ class CommandCSAKick : public Command if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { - AkickViewCallback list(source, mask); + AkickViewCallback list(source, ci, mask); list.Process(); } else @@ -422,7 +413,7 @@ class CommandCSAKick : public Command source.Reply(_("Autokick list for %s:"), ci->name.c_str()); } - AkickViewCallback::DoList(source, i, akick); + AkickViewCallback::DoList(source, ci, i, akick); } if (!SentHeader) @@ -430,16 +421,15 @@ class CommandCSAKick : public Command } } - void DoEnforce(CommandSource &source) + void DoEnforce(CommandSource &source, ChannelInfo *ci) { User *u = source.u; - ChannelInfo *ci = source.ci; Channel *c = ci->c; int count = 0; if (!c) { - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); return; } @@ -457,10 +447,9 @@ class CommandCSAKick : public Command source.Reply(_("AKICK ENFORCE for \002%s\002 complete; \002%d\002 users were affected."), ci->name.c_str(), count); } - void DoClear(CommandSource &source) + void DoClear(CommandSource &source, ChannelInfo *ci) { User *u = source.u; - ChannelInfo *ci = source.ci; bool override = !check_access(u, ci, CA_AKICK); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "CLEAR"; @@ -469,54 +458,61 @@ class CommandCSAKick : public Command } public: - CommandCSAKick() : Command("AKICK", 2, 4) + CommandCSAKick(Module *creator) : Command(creator, "chanserv/akick", 2, 4) { this->SetDesc(_("Maintain the AutoKick list")); + this->SetSyntax(_("\037channel\037 ADD {\037nick\037 | \037mask\037} [\037reason\037]")); + this->SetSyntax(_("\037channel\037 DEL {\037nick\037 | \037mask\037 | \037entry-num\037 | \037list\037}")); + this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037entry-num\037 | \037list\037]")); + this->SetSyntax(_("\002AKICK \037channel\037 VIEW [\037mask\037 | \037entry-num\037 | \037list\037]")); + this->SetSyntax(_("\037channel\037 ENFORCE")); + this->SetSyntax(_("\037channel\037 CLEAR")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string chan = params[0]; Anope::string cmd = params[1]; Anope::string mask = params.size() > 2 ? params[2] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } if (mask.empty() && (cmd.equals_ci("ADD") || cmd.equals_ci("DEL"))) this->OnSyntaxError(source, cmd); else if (!check_access(u, ci, CA_AKICK) && !u->HasPriv("chanserv/access/modify")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && readonly) source.Reply(_("Sorry, channel autokick list modification is temporarily disabled.")); else if (cmd.equals_ci("ADD")) - this->DoAdd(source, params); + this->DoAdd(source, ci, params); else if (cmd.equals_ci("DEL")) - this->DoDel(source, params); + this->DoDel(source, ci, params); else if (cmd.equals_ci("LIST")) - this->DoList(source, params); + this->DoList(source, ci, params); else if (cmd.equals_ci("VIEW")) - this->DoView(source, params); + this->DoView(source, ci, params); else if (cmd.equals_ci("ENFORCE")) - this->DoEnforce(source); + this->DoEnforce(source, ci); else if (cmd.equals_ci("CLEAR")) - this->DoClear(source); + this->DoClear(source, ci); else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002AKICK \037channel\037 ADD {\037nick\037 | \037mask\037} [\037reason\037]\002\n" - " \002AKICK \037channel\037 DEL {\037nick\037 | \037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002AKICK \037channel\037 LIST [\037mask\037 | \037entry-num\037 | \037list\037]\002\n" - " \002AKICK \037channel\037 VIEW [\037mask\037 | \037entry-num\037 | \037list\037]\002\n" - " \002AKICK \037channel\037 ENFORCE\002\n" - " \002AKICK \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002AutoKick list\002 for a channel. If a user\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002AutoKick list\002 for a channel. If a user\n" "on the AutoKick list attempts to join the channel,\n" "%s will ban that user from the channel, then kick\n" "the user.\n" @@ -529,7 +525,7 @@ class CommandCSAKick : public Command "When akicking a \037registered nick\037 the nickserv account\n" "will be added to the akick list instead of the mask.\n" "All users within that nickgroup will then be akicked.\n"), - Config->s_ChanServ.c_str()); + source.owner->nick.c_str()); source.Reply(_( " \n" "The \002AKICK DEL\002 command removes the given nick or mask\n" @@ -549,14 +545,9 @@ class CommandCSAKick : public Command "AKICK mask.\n" " \n" "The \002AKICK CLEAR\002 command clears all entries of the\n" - "akick list."), Config->s_ChanServ.c_str()); + "akick list."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "AKICK", _("AKICK \037channel\037 {ADD | DEL | LIST | VIEW | ENFORCE | CLEAR} [\037nick-or-usermask\037] [\037reason\037]")); - } }; class CSAKick : public Module @@ -564,14 +555,12 @@ class CSAKick : public Module CommandCSAKick commandcsakick; public: - CSAKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSAKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsakick(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsakick); + ModuleManager::RegisterService(&commandcsakick); } }; diff --git a/modules/core/cs_ban.cpp b/modules/core/cs_ban.cpp index 53c91314d..599bab969 100644 --- a/modules/core/cs_ban.cpp +++ b/modules/core/cs_ban.cpp @@ -12,24 +12,30 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSBan : public Command { public: - CommandCSBan(const Anope::string &cname) : Command("BAN", 2, 3) + CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 3) { this->SetDesc(_("Bans a selected nick on a channel")); + this->SetSyntax(_("\037#channel\037 \037nick\037 [\037reason\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &target = params[1]; const Anope::string &reason = params.size() > 2 ? params[2] : "Requested"; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + User *u = source.u; - ChannelInfo *ci = source.ci; Channel *c = ci->c; bool is_same = target.equals_ci(u->nick); User *u2 = is_same ? u : finduser(target); @@ -38,21 +44,21 @@ class CommandCSBan : public Command uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); else if (!u2) - source.Reply(_(NICK_X_NOT_IN_USE), target.c_str()); + source.Reply(NICK_X_NOT_IN_USE, target.c_str()); else if (!is_same ? !check_access(u, ci, CA_BAN) : !check_access(u, ci, CA_BANME)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!is_same && ci->HasFlag(CI_PEACE) && u2_level >= u_level) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); /* * Dont ban/kick the user on channels where he is excepted * to prevent services <-> server wars. */ else if (matches_list(ci->c, u2, CMODE_EXCEPT)) - source.Reply(_(CHAN_EXCEPTED), u2->nick.c_str(), ci->name.c_str()); + source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str()); else if (u2->IsProtected()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { Anope::string mask; @@ -65,7 +71,7 @@ class CommandCSBan : public Command /* We still allow host banning while not allowing to kick */ if (!c->FindUser(u2)) - return MOD_CONT; + return; if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(u, ci, CA_SIGNKICK))) c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); @@ -73,24 +79,19 @@ class CommandCSBan : public Command c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002BAN \037#channel\037 \037nick\037 [\037reason\037]\002\n" - " \n" - "Bans a selected nick on a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Bans a selected nick on a channel.\n" " \n" "By default, limited to AOPs or those with level 5 access \n" "and above on the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "BAN", _("BAN \037#channel\037 \037nick\037 [\037reason\037]")); - } }; class CSBan : public Module @@ -98,14 +99,11 @@ class CSBan : public Module CommandCSBan commandcsban; public: - CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsban("BAN") + CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsban(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsban); + ModuleManager::RegisterService(&commandcsban); } }; diff --git a/modules/core/cs_clearusers.cpp b/modules/core/cs_clearusers.cpp index b3e9d5d91..52fb3b990 100644 --- a/modules/core/cs_clearusers.cpp +++ b/modules/core/cs_clearusers.cpp @@ -12,30 +12,30 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSClearUsers : public Command { public: - CommandCSClearUsers() : Command("CLEARUSERS", 1, 1) + CommandCSClearUsers(Module *creator) : Command(creator, "chanserv/clearusers", 1, 1) { - this->SetDesc(Anope::printf(_("Tells %s to kick all users on a channel"), Config->s_ChanServ.c_str())); + this->SetDesc(_("Kicks all users on a channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; - + Channel *c = findchan(chan); Anope::string modebuf; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); - else if (!check_access(u, ci, CA_FOUNDER)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); + else if (!c->ci) + source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); + else if (!check_access(u, c->ci, CA_FOUNDER)) + source.Reply(ACCESS_DENIED); Anope::string buf = "CLEARUSERS command from " + u->nick + " (" + u->Account()->display + ")"; @@ -48,24 +48,19 @@ class CommandCSClearUsers : public Command source.Reply(_("All users have been kicked from \2%s\2."), chan.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CLEARUSERS \037channel\037\002\n" - " \n" - "Tells %s to clear (kick) all users certain settings on a channel." + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Tells %s to clear (kick) all users certain settings on a channel." " \n" "By default, limited to those with founder access on the\n" - "channel."), Config->s_ChanServ.c_str()); + "channel."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CLEAR", _("CLEARUSERS \037channel\037")); - } }; class CSClearUsers : public Module @@ -73,14 +68,12 @@ class CSClearUsers : public Module CommandCSClearUsers commandcsclearusers; public: - CSClearUsers(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSClearUsers(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsclearusers(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsclearusers); + ModuleManager::RegisterService(&commandcsclearusers); } }; diff --git a/modules/core/cs_clone.cpp b/modules/core/cs_clone.cpp index 77bfc5387..9ce877825 100644 --- a/modules/core/cs_clone.cpp +++ b/modules/core/cs_clone.cpp @@ -12,46 +12,51 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSClone : public Command { public: - CommandCSClone() : Command("CLONE", 2, 3) + CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3) { this->SetDesc(_("Copy all settings from one channel to another")); + this->SetSyntax(_("\037channel\037 \037target\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &channel = params[0]; const Anope::string &target = params[1]; Anope::string what = params.size() > 2 ? params[2] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } if (!check_access(u, ci, CA_SET)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } ChannelInfo *target_ci = cs_findchan(target); if (!target_ci) { - source.Reply(_(CHAN_X_NOT_REGISTERED), target.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, target.c_str()); + return; } if (!IsFounder(u, ci) || !IsFounder(u, target_ci)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (Config->CSMaxReg && u->Account()->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) { - source.Reply(u->Account()->channelcount > Config->CSMaxReg ? _(CHAN_EXCEEDED_CHANNEL_LIMIT) : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); - return MOD_CONT; + source.Reply(u->Account()->channelcount > Config->CSMaxReg ? CHAN_EXCEEDED_CHANNEL_LIMIT : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); + return; } if (what.equals_ci("ALL")) @@ -98,7 +103,7 @@ public: target_ci->last_topic_time = target_ci->c->topic_time; } else - target_ci->last_topic_setter = Config->s_ChanServ; + target_ci->last_topic_setter = source.owner->nick; FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(target_ci)); @@ -143,29 +148,24 @@ public: else { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } Log(LOG_COMMAND, u, this, ci) << "to clone it to " << target_ci->name; - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CLONE \037channel\037 \037target\037 [all | access | akick | badwords]\002\n" - " \n" - "Copies all settings, access, akicks, etc from channel to the\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Copies all settings, access, akicks, etc from channel to the\n" "target channel. If access, akick, or badwords is specified then only\n" "the respective settings are transferred. You must have founder level\n" "access to \037channel\037 and \037target\037.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CLONE", _("CLONE \037channel\037 \037target\037")); - } }; class CSClone : public Module @@ -173,14 +173,11 @@ class CSClone : public Module CommandCSClone commandcsclone; public: - CSClone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSClone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsclone(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsclone); + ModuleManager::RegisterService(&commandcsclone); } }; diff --git a/modules/core/cs_drop.cpp b/modules/core/cs_drop.cpp index fc6949597..d206e35d2 100644 --- a/modules/core/cs_drop.cpp +++ b/modules/core/cs_drop.cpp @@ -12,42 +12,47 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSDrop : public Command { public: - CommandCSDrop() : Command("DROP", 1, 1) + CommandCSDrop(Module *creator) : Command(creator, "chanserv/drop", 1, 1) { - this->SetFlag(CFLAG_ALLOW_SUSPENDED); this->SetDesc(_("Cancel the registration of a channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; User *u = source.u; - ChannelInfo *ci = source.ci; if (readonly) { source.Reply(_("Sorry, channel de-registration is temporarily disabled.")); // XXX: READ_ONLY_MODE? - return MOD_CONT; + return; + } + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; } ci = cs_findchan(chan); - if (ci->HasFlag(CI_SUSPENDED) && !u->HasCommand("chanserv/drop")) + if (ci->HasFlag(CI_SUSPENDED) && !u->HasCommand("chanserv/chanserv/drop")) { - source.Reply(_(CHAN_X_SUSPENDED), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_SUSPENDED, chan.c_str()); + return; } - if ((ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER)) && !u->HasCommand("chanserv/drop")) + if ((ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER)) && !u->HasCommand("chanserv/chanserv/drop")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (ci->c && ModeManager::FindChannelModeByName(CMODE_REGISTERED)) @@ -62,30 +67,23 @@ class CommandCSDrop : public Command FOREACH_MOD(I_OnChanDrop, OnChanDrop(chan)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { User *u = source.u; + this->SendSyntax(source); + source.Reply(" "); if (u->IsServicesOper()) - source.Reply(_("Syntax: \002DROP \037channel\037\002\n" - " \n" - "Unregisters the named channel. Only \002Services Operators\002\n" + source.Reply(_("Unregisters the named channel. Only \002Services Operators\002\n" "can drop a channel for which they have not identified.")); else - source.Reply(_("Syntax: \002DROP \037channel\037\002\n" - " \n" - "Unregisters the named channel. Can only be used by\n" + source.Reply(_("Unregisters the named channel. Can only be used by\n" "\002channel founder\002.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DROP", _("DROP \037channel\037")); - } }; class CSDrop : public Module @@ -93,14 +91,11 @@ class CSDrop : public Module CommandCSDrop commandcsdrop; public: - CSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsdrop(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsdrop); + ModuleManager::RegisterService(&commandcsdrop); } }; diff --git a/modules/core/cs_getkey.cpp b/modules/core/cs_getkey.cpp index 63a13cce4..289110f14 100644 --- a/modules/core/cs_getkey.cpp +++ b/modules/core/cs_getkey.cpp @@ -12,55 +12,56 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSGetKey : public Command { public: - CommandCSGetKey() : Command("GETKEY", 1, 1) + CommandCSGetKey(Module *creator) : Command(creator, "chanserv/getkey", 1, 1) { this->SetDesc(_("Returns the key of the given channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } - if (!check_access(u, ci, CA_GETKEY) && !u->HasCommand("chanserv/getkey")) + + if (!check_access(u, ci, CA_GETKEY) && !u->HasCommand("chanserv/chanserv/getkey")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } Anope::string key; if (!ci->c || !ci->c->GetParam(CMODE_KEY, key)) { source.Reply(_("The channel \002%s\002 has no key."), chan.c_str()); - return MOD_CONT; + return; } bool override = !check_access(u, ci, CA_GETKEY); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci); source.Reply(_("Key for channel \002%s\002 is \002%s\002."), chan.c_str(), key.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GETKEY \037channel\037\002\n" - " \n" - "Returns the key of the given channel.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Returns the key of the given channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GETKEY", _("GETKEY \037channel\037")); - } }; class CSGetKey : public Module @@ -68,14 +69,11 @@ class CSGetKey : public Module CommandCSGetKey commandcsgetkey; public: - CSGetKey(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSGetKey(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsgetkey(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsgetkey); + ModuleManager::RegisterService(&commandcsgetkey); } }; diff --git a/modules/core/cs_help.cpp b/modules/core/cs_help.cpp deleted file mode 100644 index b2ff5e496..000000000 --- a/modules/core/cs_help.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "chanserv.h" - -class CommandCSHelp : public Command -{ - public: - CommandCSHelp() : Command("HELP", 1, 1) - { - this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetFlag(CFLAG_STRIP_CHANNEL); - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(chanserv->Bot(), source.u, NULL, params[0]); - - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("\002%s\002 allows you to register and control various\n" - "aspects of channels. %s can often prevent\n" - "malicious users from \"taking over\" channels by limiting\n" - "who is allowed channel operator privileges. Available\n" - "commands are listed below; to use them, type\n" - "\002%s%s \037command\037\002. For more information on a\n" - "specific command, type \002%s%s HELP \037command\037\002."), - Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str()); - for (CommandMap::const_iterator it = chanserv->Bot()->Commands.begin(); it != chanserv->Bot()->Commands.end(); ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - if (Config->CSExpire >= 86400) - source.Reply(_("Note that any channel which is not used for %d days\n" - "(i.e. which no user on the channel's access list enters\n" - "for that period of time) will be automatically dropped."), Config->CSExpire / 86400); - if (u->IsServicesOper()) - source.Reply(_(" \n" - "Services Operators can also drop any channel without needing\n" - "to identify via password, and may view the access, AKICK,\n" - "and level setting lists for any channel.")); - } -}; - -class CSHelp : public Module -{ - CommandCSHelp commandcshelp; - - public: - CSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcshelp); - } -}; - -MODULE_INIT(CSHelp) diff --git a/modules/core/cs_info.cpp b/modules/core/cs_info.cpp index 4b5ade172..17960cb67 100644 --- a/modules/core/cs_info.cpp +++ b/modules/core/cs_info.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSInfo : public Command { @@ -28,19 +27,24 @@ class CommandCSInfo : public Command } public: - CommandCSInfo() : Command("INFO", 1, 2) + CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetFlag(CFLAG_ALLOW_SUSPENDED); this->SetDesc(_("Lists information about the named registered channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } bool has_auspex = u->IsIdentified() && u->HasPriv("chanserv/auspex"); bool show_all = false; @@ -49,7 +53,7 @@ class CommandCSInfo : public Command if (has_auspex || check_access(u, ci, CA_INFO)) show_all = true; - source.Reply(_(CHAN_INFO_HEADER), chan.c_str()); + source.Reply(CHAN_INFO_HEADER, chan.c_str()); if (ci->GetFounder()) source.Reply(_(" Founder: %s"), ci->GetFounder()->display.c_str()); @@ -89,7 +93,7 @@ class CommandCSInfo : public Command CheckOptStr(optbuf, CI_PERSIST, _("Persistant"), ci, u->Account()); CheckOptStr(optbuf, CI_NO_EXPIRE, _("No expire"), ci, u->Account()); - source.Reply(_(NICK_INFO_OPTIONS), optbuf.empty() ? _("None") : optbuf.c_str()); + source.Reply(NICK_INFO_OPTIONS, optbuf.empty() ? _("None") : optbuf.c_str()); source.Reply(_(" Mode lock: %s"), ci->GetMLockAsString(true).c_str()); if (!ci->HasFlag(CI_NO_EXPIRE)) @@ -100,30 +104,25 @@ class CommandCSInfo : public Command Anope::string by, reason; ci->GetExtRegular("suspend_by", by); ci->GetExtRegular("suspend_reason", reason); - source.Reply(_(" Suspended: [%s] %s"), by.c_str(), !reason.empty() ? reason.c_str() : _(NO_REASON)); + source.Reply(_(" Suspended: [%s] %s"), by.c_str(), !reason.empty() ? reason.c_str() : NO_REASON); } FOREACH_MOD(I_OnChanInfo, OnChanInfo(source, ci, show_all)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002INFO \037channel\037\002\n" - " \n" - "Lists information about the named registered channel,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists information about the named registered channel,\n" "including its founder, time of registration, last time\n" "used, description, and mode lock, if any. If \002ALL\002 is \n" "specified, the entry message and successor will also \n" "be displayed.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "INFO", _("INFO \037channel\037")); - } }; class CSInfo : public Module @@ -131,14 +130,12 @@ class CSInfo : public Module CommandCSInfo commandcsinfo; public: - CSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsinfo(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsinfo); + ModuleManager::RegisterService(&commandcsinfo); } }; diff --git a/modules/core/cs_invite.cpp b/modules/core/cs_invite.cpp index ec0af478c..f3305a01d 100644 --- a/modules/core/cs_invite.cpp +++ b/modules/core/cs_invite.cpp @@ -12,36 +12,40 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSInvite : public Command { public: - CommandCSInvite() : Command("INVITE", 1, 3) + CommandCSInvite(Module *creator) : Command(creator, "chanserv/invite", 1, 3) { - this->SetDesc(Anope::printf(_("Tells %s to invite you into a channel"), Config->s_ChanServ.c_str())); + this->SetDesc(_("Invites you into a channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; + Channel *c = findchan(chan); - if (!(c = findchan(chan))) + if (!c) { - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); + return; } - ci = c->ci; + ChannelInfo *ci = c->ci; + if (!ci) + { + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); + return; + } if (!check_access(u, ci, CA_INVITE)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } User *u2; @@ -51,8 +55,8 @@ class CommandCSInvite : public Command { if (!(u2 = finduser(params[1]))) { - source.Reply(_(NICK_X_NOT_IN_USE), params[1].c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_IN_USE, params[1].c_str()); + return; } } @@ -67,24 +71,19 @@ class CommandCSInvite : public Command source.Reply(_("\002%s\002 has been invited to \002%s\002."), u2->nick.c_str(), c->name.c_str()); u2->SendMessage(ci->WhoSends(), _("You have been invited to \002%s\002."), c->name.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002INVITE \037channel\037\002\n" - " \n" - "Tells %s to invite you into the given channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Tells %s to invite you into the given channel.\n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), Config->s_ChanServ.c_str()); + "on the channel."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "INVITE", _("INVITE \037channel\037")); - } }; class CSInvite : public Module @@ -92,14 +91,11 @@ class CSInvite : public Module CommandCSInvite commandcsinvite; public: - CSInvite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSInvite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcsinvite(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsinvite); + ModuleManager::RegisterService(&commandcsinvite); } }; diff --git a/modules/core/cs_kick.cpp b/modules/core/cs_kick.cpp index 3f2988998..bead90487 100644 --- a/modules/core/cs_kick.cpp +++ b/modules/core/cs_kick.cpp @@ -12,25 +12,25 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSKick : public Command { public: - CommandCSKick() : Command("KICK", 2, 3) + CommandCSKick(Module *creator) : Command(creator, "chanserv/kick", 2, 3) { this->SetDesc(_("Kicks a selected nick from a channel")); + this->SetSyntax(_("\037channel\037 \037nick\037 [\037reason\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &target = params[1]; const Anope::string &reason = params.size() > 2 ? params[2] : "Requested"; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; + ChannelInfo *ci = cs_findchan(params[0]); + Channel *c = findchan(params[0]); bool is_same = target.equals_ci(u->nick); User *u2 = is_same ? u : finduser(target); @@ -38,17 +38,19 @@ class CommandCSKick : public Command uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); + else if (!ci) + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); else if (!u2) - source.Reply(_(NICK_X_NOT_IN_USE), target.c_str()); + source.Reply(NICK_X_NOT_IN_USE, target.c_str()); else if (!is_same ? !check_access(u, ci, CA_KICK) : !check_access(u, ci, CA_KICKME)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!is_same && (ci->HasFlag(CI_PEACE)) && u2_level >= u_level) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (u2->IsProtected()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!c->FindUser(u2)) - source.Reply(_(NICK_X_NOT_ON_CHAN), u2->nick.c_str(), c->name.c_str()); + source.Reply(NICK_X_NOT_ON_CHAN, u2->nick.c_str(), c->name.c_str()); else { // XXX @@ -59,24 +61,19 @@ class CommandCSKick : public Command else ci->c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002KICK \037#channel\037 \037nick\037 [\037reason\037]\002\n" - " \n" - "Kicks a selected nick on a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Kicks a selected nick on a channel.\n" " \n" "By default, limited to AOPs or those with level 5 access \n" "and above on the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "KICK", _("KICK \037#channel\037 \037nick\037 [\037reason\037]")); - } }; class CSKick : public Module @@ -84,14 +81,11 @@ class CSKick : public Module CommandCSKick commandcskick; public: - CSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcskick(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcskick); + ModuleManager::RegisterService(&commandcskick); } }; diff --git a/modules/core/cs_list.cpp b/modules/core/cs_list.cpp index 7e9a7b21e..639c23267 100644 --- a/modules/core/cs_list.cpp +++ b/modules/core/cs_list.cpp @@ -12,31 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSList : public Command { public: - CommandCSList() : Command("LIST", 1, 2) + CommandCSList(Module *creator) : Command(creator, "chanserv/list", 1, 2) { this->SetFlag(CFLAG_STRIP_CHANNEL); this->SetDesc(_("Lists all registered channels matching the given pattern")); + this->SetSyntax(_("\037pattern\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string pattern = params[0]; unsigned nchans; - bool is_servadmin = u->HasCommand("chanserv/list"); + bool is_servadmin = u->HasCommand("chanserv/chanserv/list"); int count = 0, from = 0, to = 0; bool suspended = false, channoexpire = false; if (Config->CSListOpersOnly && !u->HasMode(UMODE_OPER)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (pattern[0] == '#') @@ -51,10 +51,10 @@ class CommandCSList : public Command } catch (const ConvertException &) { - source.Reply(_(LIST_INCORRECT_RANGE)); + source.Reply(LIST_INCORRECT_RANGE); source.Reply(_("To search for channels starting with #, search for the channel\n" "name without the #-sign prepended (\002anope\002 instead of \002#anope\002).")); - return MOD_CONT; + return; } pattern = "*"; @@ -77,7 +77,7 @@ class CommandCSList : public Command Anope::string spattern = "#" + pattern; - source.Reply(_(LIST_HEADER), pattern.c_str()); + source.Reply(LIST_HEADER, pattern.c_str()); for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) { @@ -111,24 +111,19 @@ class CommandCSList : public Command } source.Reply(_("End of list - %d/%d matches shown."), nchans > Config->CSListMax ? Config->CSListMax : nchans, nchans); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002LIST \037pattern\037\002\n" - " \n" - "Lists all registered channels matching the given pattern.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all registered channels matching the given pattern.\n" "(Channels with the \002PRIVATE\002 option set are not listed.)\n" "Note that a preceding '#' specifies a range, channel names\n" "are to be written without '#'.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LIST", _(NICK_LIST_SYNTAX)); - } }; class CSList : public Module @@ -136,14 +131,11 @@ class CSList : public Module CommandCSList commandcslist; public: - CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandcslist(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcslist); + ModuleManager::RegisterService(&commandcslist); } }; diff --git a/modules/core/cs_main.cpp b/modules/core/cs_main.cpp index 49d1c800b..1aa346d41 100644 --- a/modules/core/cs_main.cpp +++ b/modules/core/cs_main.cpp @@ -12,154 +12,20 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" - -static BotInfo *ChanServ = NULL; - -class ChanServBotInfo : public BotInfo -{ - public: - ChanServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } - - void OnMessage(User *u, const Anope::string &message) - { - if (!u->HasMode(UMODE_OPER) && Config->CSOpersOnly) - { - u->SendMessage(ChanServ, ACCESS_DENIED); - return; - } - - spacesepstream sep(message); - Anope::string command, param; - if (sep.GetToken(command) && sep.GetToken(param)) - { - Command *c = FindCommand(this, command); - if (c && !c->HasFlag(CFLAG_STRIP_CHANNEL)) - { - if (ircdproto->IsChannelValid(param)) - { - ChannelInfo *ci = cs_findchan(param); - if (ci) - { - if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) - { - u->SendMessage(this, CHAN_X_SUSPENDED, ci->name.c_str()); - Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; - return; - } - } - else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL)) - { - u->SendMessage(this, CHAN_X_NOT_REGISTERED, param.c_str()); - return; - } - } - /* A user not giving a channel name for a param that should be a channel */ - else - { - u->SendMessage(this, CHAN_X_INVALID, param.c_str()); - return; - } - } - } - - BotInfo::OnMessage(u, message); - } -}; - -class MyChanServService : public ChanServService -{ - public: - MyChanServService(Module *m) : ChanServService(m) { } - - BotInfo *Bot() - { - return ChanServ; - } -}; - -class ExpireCallback : public CallBack -{ - public: - ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { } - - void Tick(time_t) - { - if (!Config->CSExpire || noexpire || readonly) - return; - - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) - { - ChannelInfo *ci = it->second; - ++it; - - bool expire = false; - if (ci->HasFlag(CI_SUSPENDED)) - { - if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) - expire = true; - } - else if (!ci->c && Anope::CurTime - ci->last_used >= Config->CSExpire) - expire = true; - - if (ci->HasFlag(CI_NO_EXPIRE)) - expire = false; - - if (expire) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); - if (MOD_RESULT == EVENT_STOP) - continue; - - Anope::string extra; - if (ci->HasFlag(CI_SUSPENDED)) - extra = "suspended "; - - Log(LOG_NORMAL, "chanserv/expire", ChanServ) << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")"; - FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); - delete ci; - } - } - } -}; class ChanServCore : public Module { - MyChanServService mychanserv; - ExpireCallback expires; - public: - ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), mychanserv(this), expires(this) + ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) { this->SetAuthor("Anope"); - ModuleManager::RegisterService(&this->mychanserv); - - ChanServ = new ChanServBotInfo(Config->s_ChanServ, Config->ServiceUser, Config->ServiceHost, Config->desc_ChanServ); - ChanServ->SetFlag(BI_CORE); + BotInfo *ChanServ = findbot(Config->ChanServ); + if (ChanServ == NULL) + throw ModuleException("No bot named " + Config->ChanServ); - Implementation i[] = { I_OnDelCore, I_OnDelChan }; - ModuleManager::Attach(i, this, 2); - - spacesepstream coreModules(Config->ChanCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); - } - - ~ChanServCore() - { - spacesepstream coreModules(Config->ChanCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } - - delete ChanServ; + Implementation i[] = { I_OnDelChan, I_OnPreHelp, I_OnPostHelp }; + ModuleManager::Attach(i, this, 3); } void OnDelCore(NickCore *nc) @@ -222,10 +88,34 @@ class ChanServCore : public Module } } - void OnDelChan(ChannelInfo *ci) + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->ChanServ) + return; + source.Reply(_("\002%s\002 allows you to register and control various\n" + "aspects of channels. %s can often prevent\n" + "malicious users from \"taking over\" channels by limiting\n" + "who is allowed channel operator privileges. Available\n" + "commands are listed below; to use them, type\n" + "\002%s%s \037command\037\002. For more information on a\n" + "specific command, type \002%s%s HELP \037command\037\002.\n "), + Config->ChanServ.c_str(), Config->ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->ChanServ.c_str(), Config->ChanServ.c_str(), source.command.c_str()); + } + + void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) { - if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) - ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); + if (!params.empty() || source.owner->nick != Config->ChanServ) + return; + if (Config->CSExpire >= 86400) + source.Reply(_(" \n" + "Note that any channel which is not used for %d days\n" + "(i.e. which no user on the channel's access list enters\n" + "for that period of time) will be automatically dropped."), Config->CSExpire / 86400); + if (source.u->IsServicesOper()) + source.Reply(_(" \n" + "Services Operators can also drop any channel without needing\n" + "to identify via password, and may view the access, akick,\n" + "and level setting lists for any channel.")); } }; diff --git a/modules/core/cs_mode.cpp b/modules/core/cs_mode.cpp index a7938d5dd..23bd9e577 100644 --- a/modules/core/cs_mode.cpp +++ b/modules/core/cs_mode.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSMode : public Command { @@ -37,10 +36,9 @@ class CommandCSMode : public Command return false; } - void DoLock(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoLock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &subcommand = params[2]; const Anope::string ¶m = params.size() > 3 ? params[3] : ""; @@ -159,10 +157,9 @@ class CommandCSMode : public Command this->OnSyntaxError(source, subcommand); } - void DoSet(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSet(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; spacesepstream sep(params.size() > 3 ? params[3] : ""); Anope::string modes = params[2], param; @@ -301,38 +298,39 @@ class CommandCSMode : public Command } public: - CommandCSMode() : Command("MODE", 3, 4) + CommandCSMode(Module *creator) : Command(creator, "chanserv/mode", 3, 4) { this->SetDesc(_("Control modes and mode locks on a channel")); + this->SetSyntax(_("\037channel\037 LOCK {ADD|DEL|LIST} [\037what\037]")); + this->SetSyntax(_("\037channel\037 SET \037modes\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &subcommand = params[1]; User *u = source.u; - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); if (!ci || !ci->c) - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); - else if (!check_access(u, ci, CA_MODE) && !u->HasCommand("chanserv/mode")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); + else if (!check_access(u, ci, CA_MODE) && !u->HasCommand("chanserv/chanserv/mode")) + source.Reply(ACCESS_DENIED); else if (subcommand.equals_ci("LOCK")) - this->DoLock(source, params); + this->DoLock(source, ci, params); else if (subcommand.equals_ci("SET")) - this->DoSet(source, params); + this->DoSet(source, ci, params); else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002MODE \037channel\037 LOCK {ADD|DEL|LIST} [\037what\037]\002\n" - " \002MODE \037channel\037 SET \037modes\037\002\n" - " \n" - "Mainly controls mode locks and mode access (which is different from channel access)\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Mainly controls mode locks and mode access (which is different from channel access)\n" "on a channel.\n" " \n" "The \002MODE LOCK\002 command allows you to add, delete, and view mode locks on a channel.\n" @@ -350,11 +348,6 @@ class CommandCSMode : public Command " Clears all extended bans that start with ~c:")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "MODE", _("MODE \037channel\037 {LOCK|SET} [\037modes\037 | {ADD|DEL|LIST} [\037what\037]]")); - } }; class CSMode : public Module @@ -362,14 +355,12 @@ class CSMode : public Module CommandCSMode commandcsmode; public: - CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsmode(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsmode); + ModuleManager::RegisterService(&commandcsmode); } }; diff --git a/modules/core/cs_modes.cpp b/modules/core/cs_modes.cpp index dbbe0e491..46bb72782 100644 --- a/modules/core/cs_modes.cpp +++ b/modules/core/cs_modes.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandModeBase : public Command { @@ -28,7 +27,7 @@ class CommandModeBase : public Command * @param levelself The access level required to set this mode on yourself * @param notice Flag required on a channel to send a notice */ - CommandReturn do_util(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, int level, int levelself, ChannelInfoFlag notice) + void do_util(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, int level, int levelself, ChannelInfoFlag notice) { User *u = source.u; @@ -38,7 +37,7 @@ class CommandModeBase : public Command else do_mode(source, com, cm, chan, !nick.empty() ? nick : u->nick, set, level, levelself, notice); - return MOD_CONT; + return; } void do_mode(CommandSource &source, Command *com, ChannelMode *cm, const Anope::string &chan, const Anope::string &nick, bool set, int level, int levelself, ChannelInfoFlag notice) @@ -54,19 +53,19 @@ class CommandModeBase : public Command uint16 u_level = u_access ? u_access->level : 0, u2_level = u2_access ? u2_access->level : 0; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); else if (!ci) - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); else if (!u2) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (is_same ? !check_access(u, ci, levelself) : !check_access(u, ci, level)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!set && !is_same && ci->HasFlag(CI_PEACE) && u2_level >= u_level) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!set && u2->IsProtected() && !is_same) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!c->FindUser(u2)) - source.Reply(_(NICK_X_NOT_ON_CHAN), u2->nick.c_str(), c->name.c_str()); + source.Reply(NICK_X_NOT_ON_CHAN, u2->nick.c_str(), c->name.c_str()); else { if (set) @@ -82,18 +81,21 @@ class CommandModeBase : public Command public: - CommandModeBase(const Anope::string &cname) : Command(cname, 0, 2) { } + CommandModeBase(Module *creator, const Anope::string &cname) : Command(creator, cname, 0, 2) + { + this->SetSyntax(_("[\037#channel\037] [\037nick\037]")); + } }; class CommandCSOp : public CommandModeBase { public: - CommandCSOp() : CommandModeBase("OP") + CommandCSOp(Module *creator) : CommandModeBase(creator, "chanserv/op") { this->SetDesc(_("Gives Op status to a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OP); @@ -102,9 +104,9 @@ class CommandCSOp : public CommandModeBase bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OP [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Ops a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Ops a selected nick on a channel. If nick is not given,\n" "it will op you. If channel is not given, it will op you\n" "on every channel.\n" " \n" @@ -112,22 +114,17 @@ class CommandCSOp : public CommandModeBase "and above on the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "OP", _("OP [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSDeOp : public CommandModeBase { public: - CommandCSDeOp() : CommandModeBase("DEOP") + CommandCSDeOp(Module *creator) : CommandModeBase(creator, "chanserv/deop") { this->SetDesc(_("Deops a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OP); @@ -136,32 +133,27 @@ class CommandCSDeOp : public CommandModeBase bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEOP [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Deops a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply("Deops a selected nick on a channel. If nick is not given,\n" "it will deop you. If channel is not given, it will deop\n" "you on every channel.\n" " \n" "By default, limited to AOPs or those with level 5 access \n" - "and above on the channel.")); + "and above on the channel."); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEOP", _("DEOP [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSVoice : public CommandModeBase { public: - CommandCSVoice() : CommandModeBase("VOICE") + CommandCSVoice(Module *creator) : CommandModeBase(creator, "chanserv/voice") { this->SetDesc(_("Voices a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_VOICE); @@ -170,9 +162,9 @@ class CommandCSVoice : public CommandModeBase bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002VOICE [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Voices a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Voices a selected nick on a channel. If nick is not given,\n" "it will voice you. If channel is not given, it will voice you\n" "on every channel.\n" " \n" @@ -181,22 +173,17 @@ class CommandCSVoice : public CommandModeBase "and above for self voicing.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "VOICE", _("VOICE [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSDeVoice : public CommandModeBase { public: - CommandCSDeVoice() : CommandModeBase("DEVOICE") + CommandCSDeVoice(Module *creator) : CommandModeBase(creator, "chanserv/devoice") { this->SetDesc(_("Devoices a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_VOICE); @@ -205,9 +192,9 @@ class CommandCSDeVoice : public CommandModeBase bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEVOICE [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Devoices a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Devoices a selected nick on a channel. If nick is not given,\n" "it will devoice you. If channel is not given, it will devoice\n" "you on every channel.\n" " \n" @@ -216,36 +203,31 @@ class CommandCSDeVoice : public CommandModeBase "and above for self devoicing.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEVOICE", _("DEVOICE [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSHalfOp : public CommandModeBase { public: - CommandCSHalfOp() : CommandModeBase("HALFOP") + CommandCSHalfOp(Module *creator) : CommandModeBase(creator, "chanserv/halfop") { this->SetDesc(_("Halfops a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_HALFOP); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_HALFOP, CA_HALFOPME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002HALFOP [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Halfops a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Halfops a selected nick on a channel. If nick is not given,\n" "it will halfop you. If channel is not given, it will halfop\n" "you on every channel.\n" " \n" @@ -253,36 +235,31 @@ class CommandCSHalfOp : public CommandModeBase "and above on the channel, or to HOPs or those with level 4 \n")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "HALFOP", _("HALFOP [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSDeHalfOp : public CommandModeBase { public: - CommandCSDeHalfOp() : CommandModeBase("DEHALFOP") + CommandCSDeHalfOp(Module *creator) : CommandModeBase(creator, "chanserv/dehalfop") { this->SetDesc(_("Dehalfops a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_HALFOP); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_HALFOP, CA_HALFOPME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEHALFOP [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Dehalfops a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Dehalfops a selected nick on a channel. If nick is not given,\n" "it will dehalfop you. If channel is not given, it will dehalfop\n" "you on every channel.\n" " \n" @@ -291,36 +268,31 @@ class CommandCSDeHalfOp : public CommandModeBase "and above for self dehalfopping.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEHALFOP", _("DEHALFOP [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSProtect : public CommandModeBase { public: - CommandCSProtect() : CommandModeBase("PROTECT") + CommandCSProtect(Module *creator) : CommandModeBase(creator, "chanserv/protect") { this->SetDesc(_("Protects a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PROTECT); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_PROTECT, CA_PROTECTME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002PROTECT [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Protects a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Protects a selected nick on a channel. If nick is not given,\n" "it will protect you. If channel is not given, it will protect\n" "you on every channel.\n" " \n" @@ -328,119 +300,99 @@ class CommandCSProtect : public CommandModeBase "level 10 and above on the channel for self protecting.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "PROTECT", _("PROTECT [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSDeProtect : public CommandModeBase { public: - CommandCSDeProtect() : CommandModeBase("DEPROTECT") + CommandCSDeProtect(Module *creator) : CommandModeBase(creator, "chanserv/deprotect") { this->SetDesc(_("Deprotects a selected nick on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PROTECT); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_PROTECT, CA_PROTECTME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEPROTECT [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Deprotects a selected nick on a channel. If nick is not given,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Deprotects a selected nick on a channel. If nick is not given,\n" "it will deprotect you. If channel is not given, it will deprotect\n" "you on every channel.\n" " \n" "By default, limited to the founder, or to SOPs or those with \n")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEPROTECT", _("DEROTECT [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSOwner : public CommandModeBase { public: - CommandCSOwner() : CommandModeBase("OWNER") + CommandCSOwner(Module *creator) : CommandModeBase(module, "chanserv/owner") { this->SetDesc(_("Gives you owner status on channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OWNER); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", true, CA_OWNER, CA_OWNERME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OWNER [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Gives the selected nick owner status on \002channel\002. If nick is not\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Gives the selected nick owner status on \002channel\002. If nick is not\n" "given, it will give you owner. If channel is not given, it will\n" "give you owner on every channel.\n" " \n" "Limited to those with founder access on the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "OWNER", _("OWNER [\037#channel\037] [\037nick\037]\002")); - } }; class CommandCSDeOwner : public CommandModeBase { public: - CommandCSDeOwner() : CommandModeBase("DEOWNER") + CommandCSDeOwner(Module *creator) : CommandModeBase(creator, "chanserv/deowner") { this->SetDesc(_("Removes your owner status on a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_OWNER); if (!cm) - return MOD_CONT; + return; return do_util(source, this, cm, !params.empty() ? params[0] : "", params.size() > 1 ? params[1] : "", false, CA_OWNER, CA_OWNERME, CI_BEGIN); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEOWNER [\037#channel\037] [\037nick\037]\002\n" - " \n" - "Removes owner status from the selected nick on \002channel\002. If nick\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Removes owner status from the selected nick on \002channel\002. If nick\n" "is not given, it will deowner you. If channel is not given, it will\n" "deowner you on every channel.\n" " \n" "Limited to those with founder access on the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEOWNER", _("DEOWNER [\037#channel\037] [\037nick\037]\002")); - } }; class CSModes : public Module @@ -457,54 +409,24 @@ class CSModes : public Module CommandCSDeVoice commandcsdevoice; public: - CSModes(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSModes(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsowner(this), commandcsdeowner(this), commandcsprotect(this), commandcsdeprotect(this), + commandcsop(this), commandcsdeop(this), commandcshalfop(this), commandcsdehalfop(this), + commandcsvoice(this), commandcsdevoice(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsop); - this->AddCommand(chanserv->Bot(), &commandcsdeop); - this->AddCommand(chanserv->Bot(), &commandcsvoice); - this->AddCommand(chanserv->Bot(), &commandcsdevoice); - - if (Me && Me->IsSynced()) - OnUplinkSync(NULL); - - Implementation i[] = {I_OnUplinkSync, I_OnServerDisconnect}; - ModuleManager::Attach(i, this, 2); - } - - void OnUplinkSync(Server *) - { - if (ModeManager::FindChannelModeByName(CMODE_OWNER)) - { - this->AddCommand(chanserv->Bot(), &commandcsowner); - this->AddCommand(chanserv->Bot(), &commandcsdeowner); - } - - if (ModeManager::FindChannelModeByName(CMODE_PROTECT)) - { - this->AddCommand(chanserv->Bot(), &commandcsprotect); - this->AddCommand(chanserv->Bot(), &commandcsdeprotect); - } - - if (ModeManager::FindChannelModeByName(CMODE_HALFOP)) - { - this->AddCommand(chanserv->Bot(), &commandcshalfop); - this->AddCommand(chanserv->Bot(), &commandcsdehalfop); - } - } - - void OnServerDisconnect() - { - this->DelCommand(chanserv->Bot(), &commandcsowner); - this->DelCommand(chanserv->Bot(), &commandcsdeowner); - this->DelCommand(chanserv->Bot(), &commandcsprotect); - this->DelCommand(chanserv->Bot(), &commandcsdeprotect); - this->DelCommand(chanserv->Bot(), &commandcshalfop); - this->DelCommand(chanserv->Bot(), &commandcsdehalfop); + ModuleManager::RegisterService(&commandcsop); + ModuleManager::RegisterService(&commandcsdeop); + ModuleManager::RegisterService(&commandcsvoice); + ModuleManager::RegisterService(&commandcsdevoice); + + ModuleManager::RegisterService(&commandcsowner); + ModuleManager::RegisterService(&commandcsdeowner); + ModuleManager::RegisterService(&commandcsprotect); + ModuleManager::RegisterService(&commandcsdeprotect); + ModuleManager::RegisterService(&commandcshalfop); + ModuleManager::RegisterService(&commandcsdehalfop); } }; diff --git a/modules/core/cs_register.cpp b/modules/core/cs_register.cpp index 8e150540b..599f88790 100644 --- a/modules/core/cs_register.cpp +++ b/modules/core/cs_register.cpp @@ -12,25 +12,24 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSRegister : public Command { public: - CommandCSRegister() : Command("REGISTER", 2, 2) + CommandCSRegister(Module *creator) : Command(creator, "chanserv/register", 2, 2) { - this->SetFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL); this->SetDesc(_("Register a channel")); + this->SetSyntax(_("\037channel\037 \037description\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &chan = params[0]; const Anope::string &chdesc = params[1]; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = findchan(chan); + Channel *c = findchan(params[0]); + ChannelInfo *ci = cs_findchan(params[0]); if (readonly) source.Reply(_("Sorry, channel registration is temporarily disabled.")); @@ -39,15 +38,15 @@ class CommandCSRegister : public Command else if (chan[0] == '&') source.Reply(_("Local channels cannot be registered.")); else if (chan[0] != '#') - source.Reply(_(CHAN_SYMBOL_REQUIRED)); + source.Reply(CHAN_SYMBOL_REQUIRED); else if (!ircdproto->IsChannelValid(chan)) - source.Reply(_(CHAN_X_INVALID), chan.c_str()); + source.Reply(CHAN_X_INVALID, chan.c_str()); else if (ci) source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str()); else if (c && !c->HasUserStatus(u, CMODE_OP)) source.Reply(_("You must be a channel operator to register the channel.")); else if (Config->CSMaxReg && u->Account()->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) - source.Reply(u->Account()->channelcount > Config->CSMaxReg ? _(CHAN_EXCEEDED_CHANNEL_LIMIT) : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); + source.Reply(u->Account()->channelcount > Config->CSMaxReg ? CHAN_EXCEEDED_CHANNEL_LIMIT : _(CHAN_REACHED_CHANNEL_LIMIT), Config->CSMaxReg); else { ci = new ChannelInfo(chan); @@ -61,7 +60,7 @@ class CommandCSRegister : public Command ci->last_topic_time = c->topic_time; } else - ci->last_topic_setter = Config->s_ChanServ; + ci->last_topic_setter = source.owner->nick; ci->bi = NULL; Log(LOG_COMMAND, u, this, ci); @@ -92,14 +91,14 @@ class CommandCSRegister : public Command FOREACH_MOD(I_OnChanRegistered, OnChanRegistered(ci)); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002REGISTER \037channel\037 \037description\037\002\n" - " \n" - "Registers a channel in the %s database. In order\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Registers a channel in the %s database. In order\n" "to use this command, you must first be a channel operator\n" "on the channel you're trying to register.\n" "The description, which \002must\002 be included, is a\n" @@ -117,29 +116,76 @@ class CommandCSRegister : public Command "NOTICE: In order to register a channel, you must have\n" "first registered your nickname. If you haven't,\n" "\002%s%s HELP\002 for information on how to do so."), - Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + source.owner->nick.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } +}; + +class ExpireCallback : public CallBack +{ + public: + ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { } - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + void Tick(time_t) { - SyntaxError(source, "REGISTER", _("REGISTER \037channel\037 \037description\037")); + if (!Config->CSExpire || noexpire || readonly) + return; + + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) + { + ChannelInfo *ci = it->second; + ++it; + + bool expire = false; + if (ci->HasFlag(CI_SUSPENDED)) + { + if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) + expire = true; + } + else if (!ci->c && Anope::CurTime - ci->last_used >= Config->CSExpire) + expire = true; + + if (ci->HasFlag(CI_NO_EXPIRE)) + expire = false; + + if (expire) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); + if (MOD_RESULT == EVENT_STOP) + continue; + + Anope::string extra; + if (ci->HasFlag(CI_SUSPENDED)) + extra = "suspended "; + + Log(LOG_NORMAL, "chanserv/expire") << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")"; + FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); + delete ci; + } + } } }; class CSRegister : public Module { CommandCSRegister commandcsregister; + ExpireCallback ecb; public: - CSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsregister(this), ecb(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); + ModuleManager::RegisterService(&commandcsregister); + ModuleManager::Attach(I_OnDelChan, this); + } - this->AddCommand(chanserv->Bot(), &commandcsregister); + void OnDelChan(ChannelInfo *ci) + { + if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) + ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); } }; diff --git a/modules/core/cs_saset.cpp b/modules/core/cs_saset.cpp index 21c1bf4d4..ba4df0c80 100644 --- a/modules/core/cs_saset.cpp +++ b/modules/core/cs_saset.cpp @@ -12,113 +12,46 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSASet : public Command { - typedef std::map<Anope::string, Command *, std::less<ci::string> > subcommand_map; - subcommand_map subcommands; - public: - CommandCSSASet() : Command("SASET", 2, 3) + CommandCSSASet(Module *creator) : Command(creator, "chanserv/saset", 2, 3, "chanserv/saset") { this->SetDesc(_("Forcefully set channel options and information")); + this->SetSyntax(_("\002channel\002 \037option\037 \037parameters\037")); } - ~CommandCSSASet() + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - this->subcommands.clear(); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (readonly) - { - source.Reply(_(CHAN_SET_DISABLED)); - return MOD_CONT; - } - - // XXX Remove after 1.9.4 release - if (params[1].equals_ci("MLOCK")) - { - source.Reply(_(CHAN_SET_MLOCK_DEPRECATED), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); - return MOD_CONT; - } - - Command *c = this->FindCommand(params[1]); - - if (c) - { - ChannelInfo *ci = source.ci; - Anope::string cmdparams = ci->name; - for (std::vector<Anope::string>::const_iterator it = params.begin() + 2, it_end = params.end(); it != it_end; ++it) - cmdparams += " " + *it; - Log(LOG_ADMIN, u, this, ci) << params[1] << " " << cmdparams; - mod_run_cmd(chanserv->Bot(), u, NULL, c, params[1], cmdparams); - } - else - { - source.Reply(_("Unknown SASET option \002%s\002."), params[1].c_str()); - source.Reply(_(MORE_INFO), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), "SET"); - } - - return MOD_CONT; + this->OnSyntaxError(source, ""); + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - if (subcommand.empty()) - { - source.Reply(_("Syntax: SASET \002channel\002 \037option\037 \037parameters\037\n" - " \n" - "Allows Services Operators to forcefully change settings\n" - "on channels.\n" - " \n" - "Available options:")); - for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) - it->second->OnServHelp(source); - source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); - return true; - } - else + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Operators to forcefully change settings\n" + "on channels.\n" + " \n" + "Available options:")); + Anope::string this_name = source.command; + for (command_map::iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) { - Command *c = this->FindCommand(subcommand); - - if (c) - return c->OnHelp(source, subcommand); + if (it->first.find_ci(this_name + " ") == 0) + { + service_reference<Command> command(it->second); + if (command) + { + source.command = it->first; + command->OnServHelp(source); + } + } } - - return false; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); - } - - bool AddSubcommand(Module *creator, Command *c) - { - c->module = creator; - c->service = this->service; - return this->subcommands.insert(std::make_pair(c->name, c)).second; - } - - bool DelSubcommand(Command *c) - { - return this->subcommands.erase(c->name); - } - - Command *FindCommand(const Anope::string &subcommand) - { - subcommand_map::const_iterator it = this->subcommands.find(subcommand); - - if (it != this->subcommands.end()) - return it->second; - - return NULL; + source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information on a\n" + "particular option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + return true; } }; @@ -127,14 +60,12 @@ class CSSASet : public Module CommandCSSASet commandcssaset; public: - CSSASet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSASet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssaset(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcssaset); + ModuleManager::RegisterService(&commandcssaset); } }; diff --git a/modules/core/cs_saset_noexpire.cpp b/modules/core/cs_saset_noexpire.cpp index 5f3be9624..414b822a7 100644 --- a/modules/core/cs_saset_noexpire.cpp +++ b/modules/core/cs_saset_noexpire.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSASetNoexpire : public Command { public: - CommandCSSASetNoexpire() : Command("NOEXPIRE", 2, 2, "chanserv/saset/noexpire") + CommandCSSASetNoexpire(Module *creator) : Command(creator, "chanserv/saset/noexpire", 2, 2, "chanserv/saset/noexpire") { this->SetDesc(_("Prevent the channel from expiring")); + this->SetDesc(_("\037channel\037 NOEXPIRE {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSASetNoexpire"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,22 +51,17 @@ class CommandCSSASetNoexpire : public Command else this->OnSyntaxError(source, "NOEXPIRE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET \037channel\037 NOEXPIRE {ON | OFF}\002\n" - " \n" - "Sets whether the given channel will expire. Setting this\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets whether the given channel will expire. Setting this\n" "to ON prevents the channel from expiring.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET NOEXPIRE", _("SET \037channel\037 NOEXPIRE {ON | OFF}")); - } }; class CSSetNoexpire : public Module @@ -64,23 +69,12 @@ class CSSetNoexpire : public Module CommandCSSASetNoexpire commandcssasetnoexpire; public: - CSSetNoexpire(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetNoexpire(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssasetnoexpire(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetnoexpire); - } - - ~CSSetNoexpire() - { - Command *c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetnoexpire); + ModuleManager::RegisterService(&commandcssasetnoexpire); } }; diff --git a/modules/core/cs_set.cpp b/modules/core/cs_set.cpp index e38d7f79f..c5ab3cbe5 100644 --- a/modules/core/cs_set.cpp +++ b/modules/core/cs_set.cpp @@ -12,117 +12,46 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSet : public Command { - typedef std::map<Anope::string, Command *, std::less<ci::string> > subcommand_map; - subcommand_map subcommands; - public: - CommandCSSet() : Command("SET", 2, 3) + CommandCSSet(Module *creator) : Command(creator, "chanserv/set", 2, 3) { this->SetDesc(_("Set channel options and information")); + this->SetSyntax(_("\037channel\037 \037option\037 \037parameters\037")); } - ~CommandCSSet() + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - this->subcommands.clear(); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (readonly) - { - source.Reply(_(CHAN_SET_DISABLED)); - return MOD_CONT; - } - if (!check_access(u, cs_findchan(params[0]), CA_SET)) - { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; - } - - // XXX Remove after 1.9.4 release - if (params[1].equals_ci("MLOCK")) - { - source.Reply(_(CHAN_SET_MLOCK_DEPRECATED), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); - return MOD_CONT; - } - - Command *c = this->FindCommand(params[1]); - - if (c) - { - ChannelInfo *ci = source.ci; - Anope::string cmdparams = ci->name; - for (std::vector<Anope::string>::const_iterator it = params.begin() + 2, it_end = params.end(); it != it_end; ++it) - cmdparams += " " + *it; - mod_run_cmd(chanserv->Bot(), u, NULL, c, params[1], cmdparams); - } - else - { - source.Reply(_(NICK_SET_UNKNOWN_OPTION), Config->UseStrictPrivMsgString.c_str(), params[1].c_str()); - source.Reply(_(MORE_INFO), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), "SET"); - } - - return MOD_CONT; + this->OnSyntaxError(source, ""); + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - if (subcommand.empty()) + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows the channel founder to set various channel options\n" + "and other information.\n" + " \n" + "Available options:")); + Anope::string this_name = source.command; + for (command_map::iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) { - source.Reply(_("Syntax: \002SET \037channel\037 \037option\037 \037parameters\037\002\n" - " \n" - "Allows the channel founder to set various channel options\n" - "and other information.\n" - " \n" - "Available options:")); - for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) - it->second->OnServHelp(source); - source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); - return true; + if (it->first.find_ci(this_name + " ") == 0) + { + service_reference<Command> command(it->second); + if (command) + { + source.command = it->first; + command->OnServHelp(source); + } + } } - else - { - Command *c = this->FindCommand(subcommand); - - if (c) - return c->OnHelp(source, subcommand); - } - - return false; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); - } - - bool AddSubcommand(Module *creator, Command *c) - { - c->module = creator; - c->service = this->service; - return this->subcommands.insert(std::make_pair(c->name, c)).second; - } - - bool DelSubcommand(Command *c) - { - return this->subcommands.erase(c->name); - } - - Command *FindCommand(const Anope::string &subcommand) - { - subcommand_map::const_iterator it = this->subcommands.find(subcommand); - - if (it != this->subcommands.end()) - return it->second; - - return NULL; + source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n" + "particular option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); + return true; } }; @@ -131,14 +60,12 @@ class CSSet : public Module CommandCSSet commandcsset; public: - CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsset(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - this->AddCommand(chanserv->Bot(), &commandcsset); + ModuleManager::RegisterService(&commandcsset); } }; diff --git a/modules/core/cs_set_bantype.cpp b/modules/core/cs_set_bantype.cpp index 1ae61a5ed..3dcecfd69 100644 --- a/modules/core/cs_set_bantype.cpp +++ b/modules/core/cs_set_bantype.cpp @@ -12,25 +12,38 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetBanType : public Command { public: - CommandCSSetBanType(const Anope::string &cpermission = "") : Command("BANTYPE", 2, 2, cpermission) + CommandCSSetBanType(Module *creator, const Anope::string &cname = "chanserv/set/bantype", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Set how Services make bans on the channel")); + this->SetSyntax(_("\037channel\037 BANTYPE \037bantype\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetBanType"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } try { - ci->bantype = convertTo<int16>(params[1]); + int16 new_type = convertTo<int16>(params[1]); + if (new_type < 0 || new_type > 3) + throw ConvertException("Invalid range"); + ci->bantype = new_type; source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype); } catch (const ConvertException &) @@ -38,14 +51,14 @@ class CommandCSSetBanType : public Command source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 BANTYPE \037bantype\037\002\n" - " \n" - "Sets the ban type that will be used by services whenever\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets the ban type that will be used by services whenever\n" "they need to ban someone from your channel.\n" " \n" "bantype is a number between 0 and 3 that means:\n" @@ -56,26 +69,14 @@ class CommandCSSetBanType : public Command "3: ban in the form *!*user@*.domain"), this->name.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); - } }; class CommandCSSASetBanType : public CommandCSSetBanType { public: - CommandCSSASetBanType() : CommandCSSetBanType("chanserv/saset/bantype") + CommandCSSASetBanType(Module *creator) : CommandCSSetBanType(creator, "chanserv/saset/bantype", "chanserv/saset/bantype") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); - } }; class CSSetBanType : public Module @@ -84,31 +85,13 @@ class CSSetBanType : public Module CommandCSSASetBanType commandcssasetbantype; public: - CSSetBanType(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetBanType(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetbantype(this), commandcssasetbantype(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetbantype); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetbantype); - } - - ~CSSetBanType() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetbantype); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetbantype); + ModuleManager::RegisterService(&commandcssetbantype); + ModuleManager::RegisterService(&commandcssasetbantype); } }; diff --git a/modules/core/cs_set_description.cpp b/modules/core/cs_set_description.cpp index 493445a91..0be0099b0 100644 --- a/modules/core/cs_set_description.cpp +++ b/modules/core/cs_set_description.cpp @@ -12,56 +12,54 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetDescription : public Command { public: - CommandCSSetDescription(const Anope::string &cpermission = "") : Command("DESC", 2, 2, cpermission) + CommandCSSetDescription(Module *creator, const Anope::string &cname = "chanserv/set/description", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Set the channel description")); + this->SetSyntax(_("\037channel\037 DESC \037description\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetDescription"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } ci->desc = params[1]; source.Reply(_("Description of %s changed to \002%s\002."), ci->name.c_str(), ci->desc.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 DESC \037description\037\002\n" - " \n" - "Sets the description for the channel, which shows up with\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets the description for the channel, which shows up with\n" "the \002LIST\002 and \002INFO\002 commands."), this->name.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); - } }; class CommandCSSASetDescription : public CommandCSSetDescription { public: - CommandCSSASetDescription() : CommandCSSetDescription("chanserv/saset/description") - { - } - - void OnSyntaxError(CommandSource &source, const Anope::string &) + CommandCSSASetDescription(Module *creator) : CommandCSSetDescription(creator, "chanserv/saset/description", "chanserv/saset/description") { - // XXX - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); } }; @@ -71,31 +69,13 @@ class CSSetDescription : public Module CommandCSSASetDescription commandcssasetdescription; public: - CSSetDescription(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetDescription(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetdescription(this), commandcssasetdescription(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetdescription); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetdescription); - } - - ~CSSetDescription() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetdescription); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetdescription); + ModuleManager::RegisterService(&commandcssetdescription); + ModuleManager::RegisterService(&commandcssasetdescription); } }; diff --git a/modules/core/cs_set_founder.cpp b/modules/core/cs_set_founder.cpp index a71794756..97eec8500 100644 --- a/modules/core/cs_set_founder.cpp +++ b/modules/core/cs_set_founder.cpp @@ -12,42 +12,51 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetFounder : public Command { public: - CommandCSSetFounder(const Anope::string &cpermission = "") : Command("FOUNDER", 2, 2, cpermission) + CommandCSSetFounder(Module *creator, const Anope::string &cname = "chanserv/set/founder", const Anope::string &cpermission = "") : Command(creator, "chanserv/founder", 2, 2, cpermission) { this->SetDesc(_("Set the founder of a channel")); + this->SetSyntax(_("\037channel\037 FOUNDER \037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetFounder"); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (this->permission.empty() && (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER))) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } NickAlias *na = findnick(params[1]); if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), params[1].c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str()); + return; } NickCore *nc = na->nc; if (Config->CSMaxReg && nc->channelcount >= Config->CSMaxReg && !u->HasPriv("chanserv/no-register-limit")) { source.Reply(_("\002%s\002 has too many channels registered."), na->nick.c_str()); - return MOD_CONT; + return; } Log(!this->permission.empty() ? LOG_ADMIN : LOG_COMMAND, u, this, ci) << "to change the founder to " << nc->display; @@ -56,37 +65,25 @@ class CommandCSSetFounder : public Command source.Reply(_("Founder of %s changed to \002%s\002."), ci->name.c_str(), na->nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 FOUNDER \037nick\037\002\n" - " \n" - "Changes the founder of a channel. The new nickname must\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the founder of a channel. The new nickname must\n" "be a registered one."), this->name.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); - } }; class CommandCSSASetFounder : public CommandCSSetFounder { public: - CommandCSSASetFounder() : CommandCSSetFounder("chanserv/saset/founder") + CommandCSSASetFounder(Module *creator) : CommandCSSetFounder(creator, "chanserv/saset/founder", "chanserv/saset/founder") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); - } }; class CSSetFounder : public Module @@ -95,31 +92,13 @@ class CSSetFounder : public Module CommandCSSASetFounder commandcssasetfounder; public: - CSSetFounder(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetFounder(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetfounder(this), commandcssasetfounder(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetfounder); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetfounder); - } - - ~CSSetFounder() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetfounder); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetfounder); + ModuleManager::RegisterService(&commandcssetfounder); + ModuleManager::RegisterService(&commandcssasetfounder); } }; diff --git a/modules/core/cs_set_keeptopic.cpp b/modules/core/cs_set_keeptopic.cpp index bb121aab4..497509753 100644 --- a/modules/core/cs_set_keeptopic.cpp +++ b/modules/core/cs_set_keeptopic.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetKeepTopic : public Command { public: - CommandCSSetKeepTopic(const Anope::string &cpermission = "") : Command("KEEPTOPIC", 2, 2, cpermission) + CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Retain topic when channel is not in use")); + this->SetSyntax(_("\037channel\037 KEEPTOPIC {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetKeepTopic"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,38 +51,28 @@ class CommandCSSetKeepTopic : public Command else this->OnSyntaxError(source, "KEEPTOPIC"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 KEEPTOPIC {ON | OFF}\002\n" - " \n" - "Enables or disables the \002topic retention\002 option for a \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002topic retention\002 option for a \n" "channel. When \002topic retention\002 is set, the topic for the\n" "channel will be remembered by %s even after the\n" "last user leaves the channel, and will be restored the\n" - "next time the channel is created."), this->name.c_str(), Config->s_ChanServ.c_str()); + "next time the channel is created."), this->name.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET KEEPTOPIC", _("SET \037channel\037 KEEPTOPIC {ON | OFF}")); - } }; class CommandCSSASetKeepTopic : public CommandCSSetKeepTopic { public: - CommandCSSASetKeepTopic() : CommandCSSetKeepTopic("chanserv/saset/keeptopic") + CommandCSSASetKeepTopic(Module *creator) : CommandCSSetKeepTopic(creator, "chanserv/saset/keeptopic", "chanserv/saset/keeptopic") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET KEEPTOPIC", _("SASET \002channel\002 KEEPTOPIC {ON | OFF}")); - } }; class CSSetKeepTopic : public Module @@ -81,31 +81,13 @@ class CSSetKeepTopic : public Module CommandCSSASetKeepTopic commandcssasetkeeptopic; public: - CSSetKeepTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetKeepTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetkeeptopic(this), commandcssasetkeeptopic(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetkeeptopic); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetkeeptopic); - } - - ~CSSetKeepTopic() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetkeeptopic); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetkeeptopic); + ModuleManager::RegisterService(&commandcssetkeeptopic); + ModuleManager::RegisterService(&commandcssasetkeeptopic); } }; diff --git a/modules/core/cs_set_opnotice.cpp b/modules/core/cs_set_opnotice.cpp index abaecdde1..558bab5c3 100644 --- a/modules/core/cs_set_opnotice.cpp +++ b/modules/core/cs_set_opnotice.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetOpNotice : public Command { public: - CommandCSSetOpNotice(const Anope::string &cpermission = "") : Command("OPNOTICE", 2, 2, cpermission) + CommandCSSetOpNotice(Module *creator, const Anope::string &cname = "chanserv/set/notice", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Send a notice when OP/DEOP commands are used")); + this->SetSyntax(_("\037channel\037 OPNOTICE {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetOpNotice"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,37 +51,27 @@ class CommandCSSetOpNotice : public Command else this->OnSyntaxError(source, "OPNOTICE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 OPNOTICE {ON | OFF}\002\n" - " \n" - "Enables or disables the \002op-notice\002 option for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002op-notice\002 option for a channel.\n" "When \002op-notice\002 is set, %s will send a notice to the\n" "channel whenever the \002OP\002 or \002DEOP\002 commands are used for a user\n" - "in the channel."), this->name.c_str(), Config->s_ChanServ.c_str()); + "in the channel."), this->name.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET OPNOTICE", _("SET \037channel\037 OPNOTICE {ON | OFF}")); - } }; class CommandCSSASetOpNotice : public CommandCSSetOpNotice { public: - CommandCSSASetOpNotice() : CommandCSSetOpNotice("chanserv/saset/opnotice") + CommandCSSASetOpNotice(Module *creator) : CommandCSSetOpNotice(creator, "chanserv/saset/opnotice", "chanserv/saset/opnotice") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET OPNOTICE", _("SASET \002channel\002 OPNOTICE {ON | OFF}")); - } }; class CSSetOpNotice : public Module @@ -80,31 +80,13 @@ class CSSetOpNotice : public Module CommandCSSASetOpNotice commandcssasetopnotice; public: - CSSetOpNotice(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetOpNotice(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetopnotice(this), commandcssasetopnotice(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetopnotice); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetopnotice); - } - - ~CSSetOpNotice() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetopnotice); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetopnotice); + ModuleManager::RegisterService(&commandcssetopnotice); + ModuleManager::RegisterService(&commandcssasetopnotice); } }; diff --git a/modules/core/cs_set_peace.cpp b/modules/core/cs_set_peace.cpp index cae57d588..e51f9e81b 100644 --- a/modules/core/cs_set_peace.cpp +++ b/modules/core/cs_set_peace.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetPeace : public Command { public: - CommandCSSetPeace(const Anope::string &cpermission = "") : Command("PEACE", 2, 2, cpermission) + CommandCSSetPeace(Module *creator, const Anope::string &cname = "chanserv/set/peace", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Regulate the use of critical commands")); + this->SetSyntax(_("\037channel\037 PEACE {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetPeace"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,37 +51,27 @@ class CommandCSSetPeace : public Command else this->OnSyntaxError(source, "PEACE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 PEACE {ON | OFF}\002\n" - " \n" - "Enables or disables the \002peace\002 option for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002peace\002 option for a channel.\n" "When \002peace\002 is set, a user won't be able to kick,\n" "ban or remove a channel status of a user that has\n" - "a level superior or equal to his via %s commands."), this->name.c_str(), Config->s_ChanServ.c_str()); + "a level superior or equal to his via %s commands."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET PEACE", _("SET \037channel\037 PEACE {ON | OFF}")); - } }; class CommandCSSASetPeace : public CommandCSSetPeace { public: - CommandCSSASetPeace() : CommandCSSetPeace("chanserv/saset/peace") + CommandCSSASetPeace(Module *creator) : CommandCSSetPeace(creator, "chanserv/saset/peace", "chanserv/saset/peace") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET PEACE", _("SASET \002channel\002 PEACE {ON | OFF}")); - } }; class CSSetPeace : public Module @@ -80,31 +80,13 @@ class CSSetPeace : public Module CommandCSSASetPeace commandcssasetpeace; public: - CSSetPeace(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetPeace(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetpeace(this), commandcssasetpeace(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetpeace); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetpeace); - } - - ~CSSetPeace() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetpeace); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetpeace); + ModuleManager::RegisterService(&commandcssetpeace); + ModuleManager::RegisterService(&commandcssasetpeace); } }; diff --git a/modules/core/cs_set_persist.cpp b/modules/core/cs_set_persist.cpp index 692b0dc1c..86d5ef2ca 100644 --- a/modules/core/cs_set_persist.cpp +++ b/modules/core/cs_set_persist.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetPersist : public Command { public: - CommandCSSetPersist(const Anope::string &cpermission = "") : Command("PERSIST", 2, 2, cpermission) + CommandCSSetPersist(Module *creator, const Anope::string &cname = "chanserv/set/persist", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Set the channel as permanent")); + this->SetSyntax(_("\037channel\037 PERSIST {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetPersist"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } ChannelMode *cm = ModeManager::FindChannelModeByName(CMODE_PERM); @@ -52,9 +62,15 @@ class CommandCSSetPersist : public Command */ if (!ci->bi && !cm) { - chanserv->Bot()->Assign(NULL, ci); - if (!ci->c->FindUser(chanserv->Bot())) - chanserv->Bot()->Join(ci->c); + BotInfo *bi = findbot(Config->ChanServ); + if (!bi) + { + source.Reply(_("ChanServ is required to enable persist on this network.")); + return; + } + bi->Assign(NULL, ci); + if (!ci->c->FindUser(bi)) + bi->Join(ci->c); } /* Set the perm mode */ @@ -89,9 +105,17 @@ class CommandCSSetPersist : public Command /* No channel mode, no BotServ, but using ChanServ as the botserv bot * which was assigned when persist was set on */ - if (!cm && Config->s_BotServ.empty() && ci->bi) + if (!cm && Config->BotServ.empty() && ci->bi) + { + BotInfo *bi = findbot(Config->ChanServ); + if (!bi) + { + source.Reply(_("ChanServ is required to enable persist on this network.")); + return; + } /* Unassign bot */ - chanserv->Bot()->UnAssign(NULL, ci); + bi->UnAssign(NULL, ci); + } } source.Reply(_("Channel \002%s\002 is no longer persistant."), ci->name.c_str()); @@ -99,13 +123,14 @@ class CommandCSSetPersist : public Command else this->OnSyntaxError(source, "PERSIST"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 PERSIST {ON | OFF}\002\n" - "Enables or disables the persistant channel setting.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the persistant channel setting.\n" "When persistant is set, the service bot will remain\n" "in the channel when it has emptied of users.\n" " \n" @@ -123,27 +148,17 @@ class CommandCSSetPersist : public Command "and is is set or unset (for any reason, including MLOCK),\n" "persist is automatically set and unset for the channel aswell.\n" "Additionally, services will set or unset this mode when you\n" - "set persist on or off."), this->name.c_str()); + "set persist on or off.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET PERSIST", _("SET \037channel\037 PERSIST {ON | OFF}")); - } }; class CommandCSSASetPersist : public CommandCSSetPersist { public: - CommandCSSASetPersist() : CommandCSSetPersist("chanserv/saset/persist") + CommandCSSASetPersist(Module *creator) : CommandCSSetPersist(creator, "chanserv/saset/persist", "chanserv/saset/persist") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET PERSIST", _("SASET \002channel\002 PERSIST {ON | OFF}")); - } }; class CSSetPersist : public Module @@ -152,31 +167,13 @@ class CSSetPersist : public Module CommandCSSASetPersist commandcssasetpeace; public: - CSSetPersist(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetPersist(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetpeace(this), commandcssasetpeace(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetpeace); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetpeace); - } - - ~CSSetPersist() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetpeace); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetpeace); + ModuleManager::RegisterService(&commandcssetpeace); + ModuleManager::RegisterService(&commandcssasetpeace); } }; diff --git a/modules/core/cs_set_private.cpp b/modules/core/cs_set_private.cpp index db7bf3b26..0aaa04d91 100644 --- a/modules/core/cs_set_private.cpp +++ b/modules/core/cs_set_private.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetPrivate : public Command { public: - CommandCSSetPrivate(const Anope::string &cpermission = "") : Command("PRIVATE", 2, 2, cpermission) + CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Hide channel from LIST command")); + this->SetSyntax(_("\037channel\037 PRIVATE {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetPrivate"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,36 +51,27 @@ class CommandCSSetPrivate : public Command else this->OnSyntaxError(source, "PRIVATE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 PRIVATE {ON | OFF}\002\n" - " \n" - "Enables or disables the \002private\002 option for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002private\002 option for a channel.\n" "When \002private\002 is set, a \002%s%s LIST\002 will not\n" - "include the channel in any lists."), this->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "include the channel in any lists."), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET PRIVATE", _("SET \037channel\037 PRIVATE {ON | OFF}")); - } }; class CommandCSSASetPrivate : public CommandCSSetPrivate { public: - CommandCSSASetPrivate() : CommandCSSetPrivate("chanserv/saset/private") + CommandCSSASetPrivate(Module *creator) : CommandCSSetPrivate(creator, "chanserv/saset/private", "chanserv/saset/private") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET PRIVATE", _("SASET \002channel\002 PRIVATE {ON | OFF}")); - } }; class CSSetPrivate : public Module @@ -79,31 +80,13 @@ class CSSetPrivate : public Module CommandCSSASetPrivate commandcssasetprivate; public: - CSSetPrivate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetPrivate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetprivate(this), commandcssasetprivate(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetprivate); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetprivate); - } - - ~CSSetPrivate() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetprivate); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetprivate); + ModuleManager::RegisterService(&commandcssetprivate); + ModuleManager::RegisterService(&commandcssasetprivate); } }; diff --git a/modules/core/cs_set_restricted.cpp b/modules/core/cs_set_restricted.cpp index f9ea3b514..6bbdb5299 100644 --- a/modules/core/cs_set_restricted.cpp +++ b/modules/core/cs_set_restricted.cpp @@ -11,21 +11,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetRestricted : public Command { public: - CommandCSSetRestricted(const Anope::string &cpermission = "") : Command("RESTRICTED", 2, 2, cpermission) + CommandCSSetRestricted(Module *creator, const Anope::string &cname = "chanserv/set/restricted", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Restrict access to the channel")); + this->SetSyntax(_("\037channel\037 RESTRICTED {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetRestricted"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -44,36 +54,26 @@ class CommandCSSetRestricted : public Command else this->OnSyntaxError(source, "RESTRICTED"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 RESTRICTED {ON | OFF}\002\n" - " \n" - "Enables or disables the \002restricted access\002 option for a\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002restricted access\002 option for a\n" "channel. When \002restricted access\002 is set, users not on the access list will\n" - "instead be kicked and banned from the channel."), this->name.c_str()); + "instead be kicked and banned from the channel.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET RESTRICTED", _("SET \037channel\037 RESTRICTED {ON | OFF}")); - } }; class CommandCSSASetRestricted : public CommandCSSetRestricted { public: - CommandCSSASetRestricted() : CommandCSSetRestricted("chanserv/saset/restricted") + CommandCSSASetRestricted(Module *creator) : CommandCSSetRestricted(creator, "chanserv/saset/restricted", "chanserv/saset/restricted") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET RESTRICTED", _("SASET \002channel\002 RESTRICTED {ON | OFF}")); - } }; class CSSetRestricted : public Module @@ -82,31 +82,13 @@ class CSSetRestricted : public Module CommandCSSASetRestricted commandcssasetrestricted; public: - CSSetRestricted(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetRestricted(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetrestricted(this), commandcssasetrestricted(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetrestricted); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetrestricted); - } - - ~CSSetRestricted() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetrestricted); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetrestricted); + ModuleManager::RegisterService(&commandcssetrestricted); + ModuleManager::RegisterService(&commandcssasetrestricted); } }; diff --git a/modules/core/cs_set_secure.cpp b/modules/core/cs_set_secure.cpp index 39d50fad2..73013be32 100644 --- a/modules/core/cs_set_secure.cpp +++ b/modules/core/cs_set_secure.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetSecure : public Command { public: - CommandCSSetSecure(const Anope::string &cpermission = "") : Command("SECURE", 2, 2, cpermission) + CommandCSSetSecure(Module *creator, const Anope::string &cname = "chanserv/set/secure", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { - this->SetDesc(Anope::printf(_("Activate %s's security features"), Config->s_ChanServ.c_str())); + this->SetDesc(_("Activate security features")); + this->SetSyntax(_("\037channel\037 SECURE {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetSecure"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,38 +51,28 @@ class CommandCSSetSecure : public Command else this->OnSyntaxError(source, "SECURE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 SECURE {ON | OFF}\002\n" - " \n" - "Enables or disables %s's security features for a\n" - "channel. When \002SECURE\002 is set, only users who have\n" - "registered their nicknames with %s and IDENTIFY'd\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables security features for a\n" + "channel. When \002%s\002 is set, only users who have\n" + "registered their nicknames and IDENTIFY'd\n" "with their password will be given access to the channel\n" - "as controlled by the access list."), this->name.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + "as controlled by the access list."), this->name.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET SECURE", _("SET \037channel\037 SECURE {ON | OFF}")); - } }; class CommandCSSASetSecure : public CommandCSSetSecure { public: - CommandCSSASetSecure() : CommandCSSetSecure("chanserv/saset/secure") + CommandCSSASetSecure(Module *creator) : CommandCSSetSecure(creator, "chanserv/saset/secure", "chanserv/saset/secure") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET SECURE", _("SASET \002channel\002 SECURE {ON | OFF}")); - } }; class CSSetSecure : public Module @@ -81,31 +81,13 @@ class CSSetSecure : public Module CommandCSSASetSecure commandcssasetsecure; public: - CSSetSecure(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetSecure(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetsecure(this), commandcssasetsecure(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetsecure); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetsecure); - } - - ~CSSetSecure() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetsecure); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetsecure); + ModuleManager::RegisterService(&commandcssetsecure); + ModuleManager::RegisterService(&commandcssasetsecure); } }; diff --git a/modules/core/cs_set_securefounder.cpp b/modules/core/cs_set_securefounder.cpp index a77df7f69..f620a128b 100644 --- a/modules/core/cs_set_securefounder.cpp +++ b/modules/core/cs_set_securefounder.cpp @@ -12,27 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetSecureFounder : public Command { public: - CommandCSSetSecureFounder(const Anope::string &cpermission = "") : Command("SECUREFOUNDER", 2, 2, cpermission) + CommandCSSetSecureFounder(Module *creator, const Anope::string &cname = "chanserv/set/securefounder", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Stricter control of channel founder status")); + this->SetDesc(_("\037channel\037 SECUREFOUNDER {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetSecureFounder"); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + if (this->permission.empty() && ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (params[1].equals_ci("ON")) @@ -48,38 +52,28 @@ class CommandCSSetSecureFounder : public Command else this->OnSyntaxError(source, "SECUREFOUNDER"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 SECUREFOUNDER {ON | OFF}\002\n" - " \n" - "Enables or disables the \002secure founder\002 option for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002secure founder\002 option for a channel.\n" "When \002secure founder\002 is set, only the real founder will be\n" "able to drop the channel, change its password, its founder and its\n" "successor, and not those who have founder level access through\n" - "the access/qop command."), this->name.c_str()); + "the access/qop command.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET SECUREFOUNDER", _("SET \037channel\037 SECUREFOUNDER {ON | OFF}")); - } }; class CommandCSSASetSecureFounder : public CommandCSSetSecureFounder { public: - CommandCSSASetSecureFounder() : CommandCSSetSecureFounder("chanserv/saset/securefounder") + CommandCSSASetSecureFounder(Module *creator) : CommandCSSetSecureFounder(creator, "chanserv/saset/securefounder", "chanserv/saset/securefounder") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET SECUREFOUNDER", _("SASET \002channel\002 SECUREFOUNDER {ON | OFF}")); - } }; class CSSetSecureFounder : public Module @@ -88,31 +82,13 @@ class CSSetSecureFounder : public Module CommandCSSASetSecureFounder commandcssasetsecurefounder; public: - CSSetSecureFounder(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetSecureFounder(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetsecurefounder(this), commandcssasetsecurefounder(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetsecurefounder); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetsecurefounder); - } - - ~CSSetSecureFounder() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetsecurefounder); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetsecurefounder); + ModuleManager::RegisterService(&commandcssetsecurefounder); + ModuleManager::RegisterService(&commandcssasetsecurefounder); } }; diff --git a/modules/core/cs_set_secureops.cpp b/modules/core/cs_set_secureops.cpp index 7f45fdce0..f816dc0f8 100644 --- a/modules/core/cs_set_secureops.cpp +++ b/modules/core/cs_set_secureops.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetSecureOps : public Command { public: - CommandCSSetSecureOps(const Anope::string &cpermission = "") : Command("SECUREOPS", 2, 2, cpermission) + CommandCSSetSecureOps(Module *creator, const Anope::string &cname = "chanserv/set/secureops", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Stricter control of chanop status")); + this->SetSyntax(_("\037channel\037 {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetSecureIos"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,36 +51,26 @@ class CommandCSSetSecureOps : public Command else this->OnSyntaxError(source, "SECUREOPS"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET \037%s\037 SECUREOPS {ON | OFF}\002\n" - " \n" - "Enables or disables the \002secure ops\002 option for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002secure ops\002 option for a channel.\n" "When \002secure ops\002 is set, users who are not on the userlist\n" - "will not be allowed chanop status."), this->name.c_str()); + "will not be allowed chanop status.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET SECUREOPS", _("SET \037channel\037 SECUREOPS {ON | OFF}")); - } }; class CommandCSSASetSecureOps : public CommandCSSetSecureOps { public: - CommandCSSASetSecureOps() : CommandCSSetSecureOps("chanserv/saset/secureops") + CommandCSSASetSecureOps(Module *creator) : CommandCSSetSecureOps(creator, "chanserv/saset/secureops", "chanserv/saset/secureops") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET SECUREOPS", _("SASET \002channel\002 SECUREOPS {ON | OFF}")); - } }; class CSSetSecureOps : public Module @@ -79,31 +79,13 @@ class CSSetSecureOps : public Module CommandCSSASetSecureOps commandcssasetsecureops; public: - CSSetSecureOps(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetSecureOps(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetsecureops(this), commandcssasetsecureops(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetsecureops); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetsecureops); - } - - ~CSSetSecureOps() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetsecureops); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetsecureops); + ModuleManager::RegisterService(&commandcssetsecureops); + ModuleManager::RegisterService(&commandcssasetsecureops); } }; diff --git a/modules/core/cs_set_signkick.cpp b/modules/core/cs_set_signkick.cpp index 6ac081f63..59961b5b4 100644 --- a/modules/core/cs_set_signkick.cpp +++ b/modules/core/cs_set_signkick.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetSignKick : public Command { public: - CommandCSSetSignKick(const Anope::string &cpermission = "") : Command("SIGNKICK", 2, 2, cpermission) + CommandCSSetSignKick(Module *creator, const Anope::string &cname = "chanserv/set/signkick", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Sign kicks that are done with KICK command")); + this->SetSyntax(_("\037channel\037 SIGNKICK {ON | LEVEL | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetSignKick"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -49,43 +59,30 @@ class CommandCSSetSignKick : public Command } else this->OnSyntaxError(source, "SIGNKICK"); - - return MOD_CONT; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET \037%s\037 SIGNKICK {ON | LEVEL | OFF}\002\n" - " \n" - "Enables or disables signed kicks for a\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables signed kicks for a\n" "channel. When \002SIGNKICK\002 is set, kicks issued with\n" - "%s KICK command will have the nick that used the\n" + "KICK command will have the nick that used the\n" "command in their reason.\n" " \n" "If you use \002LEVEL\002, those who have a level that is superior \n" "or equal to the SIGNKICK level on the channel won't have their \n" - "kicks signed. See \002%s%s HELP LEVELS\002 for more information."), this->name.c_str(), - Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "kicks signed.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET SIGNKICK", _("SET \037channel\037 SIGNKICK {ON | LEVEL | OFF}")); - } }; class CommandCSSASetSignKick : public CommandCSSetSignKick { public: - CommandCSSASetSignKick() : CommandCSSetSignKick("chanserv/saset/signkick") + CommandCSSASetSignKick(Module *creator) : CommandCSSetSignKick(creator, "chanserv/saset/signkick", "chanserv/saset/signkick") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET SIGNKICK", _("SASET \002channel\002 SIGNKICK {ON | OFF}")); - } }; class CSSetSignKick : public Module @@ -94,31 +91,13 @@ class CSSetSignKick : public Module CommandCSSASetSignKick commandcssasetsignkick; public: - CSSetSignKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetSignKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetsignkick(this), commandcssasetsignkick(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetsignkick); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetsignkick); - } - - ~CSSetSignKick() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetsignkick); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetsignkick); + ModuleManager::RegisterService(&commandcssetsignkick); + ModuleManager::RegisterService(&commandcssasetsignkick); } }; diff --git a/modules/core/cs_set_successor.cpp b/modules/core/cs_set_successor.cpp index f141398a3..be10a4b63 100644 --- a/modules/core/cs_set_successor.cpp +++ b/modules/core/cs_set_successor.cpp @@ -12,27 +12,36 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetSuccessor : public Command { public: - CommandCSSetSuccessor(const Anope::string &cpermission = "") : Command("SUCCESSOR", 1, 2, cpermission) + CommandCSSetSuccessor(Module *creator, const Anope::string &cname = "chanserv/set/successor", const Anope::string &cpermission = "") : Command(creator, cname, 1, 2, cpermission) { this->SetDesc(_("Set the successor for a channel")); + this->SetSyntax(_("\037channel\037 SUCCESSOR \037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetSuccessor"); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (this->permission.empty() && ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } NickCore *nc; @@ -43,13 +52,13 @@ class CommandCSSetSuccessor : public Command if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), params[1].c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str()); + return; } if (na->nc == ci->GetFounder()) { source.Reply(_("%s cannot be the successor on channel %s they are the founder."), na->nick.c_str(), ci->name.c_str()); - return MOD_CONT; + return; } nc = na->nc; } @@ -65,42 +74,30 @@ class CommandCSSetSuccessor : public Command else source.Reply(_("Successor for \002%s\002 unset."), ci->name.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 SUCCESSOR \037nick\037\002\n" - " \n" - "Changes the successor of a channel. If the founder's\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the successor of a channel. If the founder's\n" "nickname expires or is dropped while the channel is still\n" "registered, the successor will become the new founder of the\n" "channel. However, if the successor already has too many\n" "channels registered (%d), the channel will be dropped\n" "instead, just as if no successor had been set. The new\n" - "nickname must be a registered one."), this->name.c_str()); + "nickname must be a registered one."), Config->CSMaxReg); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); - } }; class CommandCSSASetSuccessor : public CommandCSSetSuccessor { public: - CommandCSSASetSuccessor() : CommandCSSetSuccessor("chanserv/saset/successor") + CommandCSSASetSuccessor(Module *creator) : CommandCSSetSuccessor(creator, "chanserv/saset/successor", "chanserv/saset/successor") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); - } }; class CSSetSuccessor : public Module @@ -109,31 +106,13 @@ class CSSetSuccessor : public Module CommandCSSASetSuccessor commandcssasetsuccessor; public: - CSSetSuccessor(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetSuccessor(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetsuccessor(this), commandcssasetsuccessor(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetsuccessor); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetsuccessor); - } - - ~CSSetSuccessor() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetsuccessor); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetsuccessor); + ModuleManager::RegisterService(&commandcssetsuccessor); + ModuleManager::RegisterService(&commandcssasetsuccessor); } }; diff --git a/modules/core/cs_set_topiclock.cpp b/modules/core/cs_set_topiclock.cpp index 8792f9d37..5e7e4447b 100644 --- a/modules/core/cs_set_topiclock.cpp +++ b/modules/core/cs_set_topiclock.cpp @@ -12,21 +12,31 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetTopicLock : public Command { public: - CommandCSSetTopicLock(const Anope::string &cpermission = "") : Command("TOPICLOCK", 2, 2, cpermission) + CommandCSSetTopicLock(Module *creator, const Anope::string &cname = "chanserv/set/topiclock", const Anope::string &cpermission = "") : Command(creator, cname, 2, 2, cpermission) { this->SetDesc(_("Topic can only be changed with TOPIC")); + this->SetSyntax(_("\037channel\037 TOPICLOCK {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetTopicLock"); + User *u = source.u; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -41,36 +51,25 @@ class CommandCSSetTopicLock : public Command else this->OnSyntaxError(source, "TOPICLOCK"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 TOPICLOCK {ON | OFF}\002\n" - " \n" - "Enables or disables the \002topic lock\002 option for a channel.\n" - "When \002topic lock\002 is set, %s will not allow the\n" - "channel topic to be changed except via the \002TOPIC\002\n" - "command."), this->name.c_str(), Config->s_ChanServ.c_str()); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the \002topic lock\002 option for a channel.\n" + "When \002topic lock\002 is set, the channel topic will be unchangable\n" + " except via the \002TOPIC\002 command.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET", _("SET \037channel\037 TOPICLOCK {ON | OFF}"));; - } }; class CommandCSSASetTopicLock : public CommandCSSetTopicLock { public: - CommandCSSASetTopicLock() : CommandCSSetTopicLock("chanserv/saset/topiclock") - { - } - - void OnSyntaxError(CommandSource &source, const Anope::string &) + CommandCSSASetTopicLock(Module *creator) : CommandCSSetTopicLock(creator, "chanserv/saset/topiclock", "chanserv/saset/topiclock") { - SyntaxError(source, "SASET", _("SASET \002channel\002 TOPICLOCK {ON | OFF}")); } }; @@ -80,31 +79,10 @@ class CSSetTopicLock : public Module CommandCSSASetTopicLock commandcssasettopiclock; public: - CSSetTopicLock(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetTopicLock(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssettopiclock(this), commandcssasettopiclock(this) { this->SetAuthor("Anope"); - - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssettopiclock); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasettopiclock); - } - - ~CSSetTopicLock() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssettopiclock); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasettopiclock); } }; diff --git a/modules/core/cs_set_xop.cpp b/modules/core/cs_set_xop.cpp index 39cfa6bac..a7f627263 100644 --- a/modules/core/cs_set_xop.cpp +++ b/modules/core/cs_set_xop.cpp @@ -11,31 +11,40 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" #define CHECKLEV(lev) (ci->levels[(lev)] != ACCESS_INVALID && access->level >= ci->levels[(lev)]) class CommandCSSetXOP : public Command { public: - CommandCSSetXOP(const Anope::string &cpermission = "") : Command("XOP", 2, 2, cpermission) + CommandCSSetXOP(Module *creator, const Anope::string &cname = "chanserv/set/xop", const Anope::string &cpermission = "") : Command(creator, "chanserv/xop", 2, 2, cpermission) { this->SetDesc(_("Toggle the user privilege system")); + this->SetSyntax(_("\037channel\037 XOP {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; if (!ModuleManager::FindModule("cs_xop")) { - source.Reply(_("xOP system is not available."), "XOP"); - return MOD_CONT; + source.Reply(_("xOP system is not available.")); + return; } - if (!ci) - throw CoreException("NULL ci in CommandCSSetXOP"); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!this->permission.empty() && !check_access(u, ci, CA_SET)) + { + source.Reply(ACCESS_DENIED); + return; + } if (params[1].equals_ci("ON")) { @@ -81,14 +90,14 @@ class CommandCSSetXOP : public Command else this->OnSyntaxError(source, "XOP"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002%s \037channel\037 XOP {ON | OFF}\002\n" - " \n" - "Enables or disables the xOP lists system for a channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Enables or disables the xOP lists system for a channel.\n" "When \002XOP\002 is set, you have to use the \002AOP\002/\002SOP\002/\002VOP\002\n" "commands in order to give channel privileges to\n" "users, else you have to use the \002ACCESS\002 command.\n" @@ -105,27 +114,17 @@ class CommandCSSetXOP : public Command "the \002LEVELS\002 command.\n" " \n" "Switching from xOP lists system to access list system\n" - "causes no problem though."), this->name.c_str()); + "causes no problem though.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET XOP", _("SET \037channel\037 XOP {ON | OFF}")); - } }; class CommandCSSASetXOP : public CommandCSSetXOP { public: - CommandCSSASetXOP() : CommandCSSetXOP("chanserv/saset/xop") + CommandCSSASetXOP(Module *creator) : CommandCSSetXOP(creator, "chanserv/saset/xop", "chanserv/saset/xop") { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET XOP", _("SASET \002channel\002 XOP {ON | OFF}")); - } }; class CSSetXOP : public Module @@ -134,31 +133,13 @@ class CSSetXOP : public Module CommandCSSASetXOP commandcssasetxop; public: - CSSetXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSetXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssetxop(this), commandcssasetxop(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandcssetxop); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandcssasetxop); - } - - ~CSSetXOP() - { - Command *c = FindCommand(chanserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandcssetxop); - - c = FindCommand(chanserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandcssasetxop); + ModuleManager::RegisterService(&commandcssetxop); + ModuleManager::RegisterService(&commandcssasetxop); } }; diff --git a/modules/core/cs_status.cpp b/modules/core/cs_status.cpp index f9107fc8e..586a3b2ce 100644 --- a/modules/core/cs_status.cpp +++ b/modules/core/cs_status.cpp @@ -12,35 +12,41 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSStatus : public Command { public: - CommandCSStatus() : Command("STATUS", 2, 2, "chanserv/status") + CommandCSStatus(Module *creator) : Command(creator, "chanserv/status", 2, 2, "chanserv/status") { this->SetDesc(_("Returns the current access level of a user on a channel")); + this->SetSyntax(_("\037channel\037 \037item\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; const Anope::string &nick = params[1]; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + User *u2 = finduser(nick); ChanAccess *u2_access = ci->GetAccess(u2); if (u2) source.Reply(_("STATUS %s %s %d"), ci->name.c_str(), u2->nick.c_str(), u2_access ? u2_access->level : 0); else /* !u2 */ source.Reply(_("STATUS ERROR Nick %s not online"), nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002STATUS \037channel\037 \037nickname\037\002\n" - " \n" - "Returns the current access level of the given nick on the\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Returns the current access level of the given nick on the\n" "given channel. The reply is of the form:\n" " \n" " STATUS \037channel\037 \037nickname\037 \037access-level\037\n" @@ -50,11 +56,6 @@ class CommandCSStatus : public Command " STATUS ERROR \037error-message\037")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "STATUS", _("STATUS \037channel\037 \037item\037")); - } }; class CSStatus : public Module @@ -62,11 +63,12 @@ class CSStatus : public Module CommandCSStatus commandcsstatus; public: - CSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsstatus(this) { this->SetAuthor("Anope"); - this->AddCommand(chanserv->Bot(), &commandcsstatus); + ModuleManager::RegisterService(&commandcsstatus); } }; diff --git a/modules/core/cs_suspend.cpp b/modules/core/cs_suspend.cpp index a027bc173..0e0a72bcf 100644 --- a/modules/core/cs_suspend.cpp +++ b/modules/core/cs_suspend.cpp @@ -12,49 +12,53 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSuspend : public Command { public: - CommandCSSuspend() : Command("SUSPEND", 1, 2, "chanserv/suspend") + CommandCSSuspend(Module *creator) : Command(creator, "chanserv/suspend", 1, 2, "chanserv/suspend") { this->SetDesc(_("Prevent a channel from being used preserving channel data and settings")); + this->SetSyntax(_("\037channel\037 [\037reason\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &reason = params.size() > 1 ? params[1] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; - /* Assumes that permission checking has already been done. */ if (Config->ForceForbidReason && reason.empty()) { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } ci->SetFlag(CI_SUSPENDED); ci->Extend("suspend_by", new ExtensibleItemRegular<Anope::string>(u->nick)); if (!reason.empty()) ci->Extend("suspend_reason", new ExtensibleItemRegular<Anope::string>(u->nick)); - if (c) + if (ci->c) { - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) + for (CUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ) { UserContainer *uc = *it++; if (uc->user->HasMode(UMODE_OPER)) continue; - c->Kick(NULL, uc->user, "%s", !reason.empty() ? reason.c_str() : translate(uc->user, _("This channel has been suspended."))); + ci->c->Kick(NULL, uc->user, "%s", !reason.empty() ? reason.c_str() : translate(uc->user, _("This channel has been suspended."))); } } @@ -63,49 +67,50 @@ class CommandCSSuspend : public Command FOREACH_MOD(I_OnChanSuspend, OnChanSuspend(ci)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SUSPEND \037channel\037 [\037reason\037]\002\n" - " \n" - "Disallows anyone from registering or using the given\n" - "channel. May be cancelled by using the UNSUSPEND\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Disallows anyone from using the given channel.\n" + "May be cancelled by using the UNSUSPEND\n" "command to preserve all previous channel data/settings.\n" " \n" "Reason may be required on certain networks.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SUSPEND", Config->ForceForbidReason ? _("SUSPEND \037channel\037 \037reason\037") : _("SUSPEND \037channel\037 \037freason\037")); - } }; class CommandCSUnSuspend : public Command { public: - CommandCSUnSuspend() : Command("UNSUSPEND", 1, 1, "chanserv/suspend") + CommandCSUnSuspend(Module *creator) : Command(creator, "chanserv/unsuspend", 1, 1, "chanserv/suspend") { - this->SetFlag(CFLAG_ALLOW_SUSPENDED); this->SetDesc(_("Releases a suspended channel")); + this->SetSyntax(_("\037channel\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); + + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } /* Only UNSUSPEND already suspended channels */ if (!ci->HasFlag(CI_SUSPENDED)) { source.Reply(_("Couldn't release channel \002%s\002!"), ci->name.c_str()); - return MOD_CONT; + return; } Anope::string by, reason; @@ -121,22 +126,17 @@ class CommandCSUnSuspend : public Command FOREACH_MOD(I_OnChanUnsuspend, OnChanUnsuspend(ci)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002UNSUSPEND \037channel\037\002\n" - " \n" - "Releases a suspended channel. All data and settings\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Releases a suspended channel. All data and settings\n" "are preserved from before the suspension.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "UNSUSPEND", _("UNSUSPEND \037channel\037")); - } }; class CSSuspend : public Module @@ -145,12 +145,13 @@ class CSSuspend : public Module CommandCSUnSuspend commandcsunsuspend; public: - CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcssuspend(this), commandcsunsuspend(this) { this->SetAuthor("Anope"); - this->AddCommand(chanserv->Bot(), &commandcssuspend); - this->AddCommand(chanserv->Bot(), &commandcsunsuspend); + ModuleManager::RegisterService(&commandcssuspend); + ModuleManager::RegisterService(&commandcsunsuspend); } }; diff --git a/modules/core/cs_topic.cpp b/modules/core/cs_topic.cpp index a6c6fad74..2cb821662 100644 --- a/modules/core/cs_topic.cpp +++ b/modules/core/cs_topic.cpp @@ -12,61 +12,59 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSTopic : public Command { public: - CommandCSTopic() : Command("TOPIC", 1, 2) + CommandCSTopic(Module *creator) : Command(creator, "chanserv/topic", 1, 2) { this->SetDesc(_("Manipulate the topic of the specified channel")); + this->SetSyntax(_("\037channel\037 [\037topic\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &topic = params.size() > 1 ? params[1] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; - if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); - else if (!check_access(u, ci, CA_TOPIC) && !u->HasCommand("chanserv/topic")) - source.Reply(_(ACCESS_DENIED)); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (!ci->c) + source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); + else if (!check_access(u, ci, CA_TOPIC) && !u->HasCommand("chanserv/chanserv/topic")) + source.Reply(ACCESS_DENIED); else { bool has_topiclock = ci->HasFlag(CI_TOPICLOCK); ci->UnsetFlag(CI_TOPICLOCK); - c->ChangeTopic(u->nick, topic, Anope::CurTime); + ci->c->ChangeTopic(u->nick, topic, Anope::CurTime); if (has_topiclock) ci->SetFlag(CI_TOPICLOCK); bool override = !check_access(u, ci, CA_TOPIC); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "to change the topic to " << (!topic.empty() ? topic : "No topic"); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002TOPIC \037channel\037 [\037topic\037]\002\n" - " \n" - "Causes %s to set the channel topic to the one\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Causes %s to set the channel topic to the one\n" "specified. If \002topic\002 is not given, then an empty topic\n" "is set. This command is most useful in conjunction\n" - "with \002SET TOPICLOCK\002. See \002%s%s HELP SET TOPICLOCK\002\n" - "for more information.\n" - " \n" + "with topic lock.\n" "By default, limited to those with founder access on the\n" - "channel."), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + "channel."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "TOPIC", _("TOPIC \037channel\037 [\037topic\037]")); - } }; class CSTopic : public Module @@ -74,11 +72,12 @@ class CSTopic : public Module CommandCSTopic commandcstopic; public: - CSTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcstopic(this) { this->SetAuthor("Anope"); - this->AddCommand(chanserv->Bot(), &commandcstopic); + ModuleManager::RegisterService(&commandcstopic); } }; diff --git a/modules/core/cs_unban.cpp b/modules/core/cs_unban.cpp index 8cdb0f2fd..dbd0d9ae3 100644 --- a/modules/core/cs_unban.cpp +++ b/modules/core/cs_unban.cpp @@ -12,32 +12,37 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSUnban : public Command { public: - CommandCSUnban() : Command("UNBAN", 1, 2) + CommandCSUnban(Module *creator) : Command(creator, "chanserv/unban", 1, 2) { this->SetDesc(_("Remove all bans preventing a user from entering a channel")); + this->SetSyntax(_("\037channel\037 [\037nick\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; - if (!c) + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) { - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (ci->c == NULL) + { + source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); + return; } if (!check_access(u, ci, CA_UNBAN)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } User *u2 = u; @@ -46,35 +51,30 @@ class CommandCSUnban : public Command if (!u2) { - source.Reply(_(NICK_X_NOT_IN_USE), params[1].c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_IN_USE, params[1].c_str()); + return; } common_unban(ci, u2, u == u2); if (u2 == u) - source.Reply(_("You have been unbanned from \002%s\002."), c->name.c_str()); + source.Reply(_("You have been unbanned from \002%s\002."), ci->c->name.c_str()); else - source.Reply(_("\002%s\002 has been unbanned from \002%s\002."), u2->nick.c_str(), c->name.c_str()); + source.Reply(_("\002%s\002 has been unbanned from \002%s\002."), u2->nick.c_str(), ci->c->name.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002UNBAN \037channel\037 [\037nick\037]\002\n" - " \n" - "Tells %s to remove all bans preventing you or the given\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Tells %s to remove all bans preventing you or the given\n" "user from entering the given channel. \n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), Config->s_ChanServ.c_str()); + "on the channel."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "UNBAN", _("UNBAN \037channel\037 [\037nick\037]")); - } }; class CSUnban : public Module @@ -82,11 +82,12 @@ class CSUnban : public Module CommandCSUnban commandcsunban; public: - CSUnban(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSUnban(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsunban(this) { this->SetAuthor("Anope"); - this->AddCommand(chanserv->Bot(), &commandcsunban); + ModuleManager::RegisterService(&commandcsunban); } }; diff --git a/modules/core/cs_xop.cpp b/modules/core/cs_xop.cpp index 666cb4da1..05981bf4b 100644 --- a/modules/core/cs_xop.cpp +++ b/modules/core/cs_xop.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" enum { @@ -27,20 +26,21 @@ enum class XOPListCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; int level; Command *c; bool SentHeader; public: - XOPListCallback(CommandSource &_source, const Anope::string &numlist, int _level, Command *_c) : NumberList(numlist, false), source(_source), level(_level), c(_c), SentHeader(false) + XOPListCallback(CommandSource &_source, ChannelInfo *_ci, const Anope::string &numlist, int _level, Command *_c) : NumberList(numlist, false), source(_source), ci(_ci), level(_level), c(_c), SentHeader(false) { } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAccessCount()) + if (!Number || Number > ci->GetAccessCount()) return; - ChanAccess *access = source.ci->GetAccess(Number - 1); + ChanAccess *access = ci->GetAccess(Number - 1); if (level != access->level) return; @@ -48,7 +48,7 @@ class XOPListCallback : public NumberList if (!SentHeader) { SentHeader = true; - source.Reply(_("%s list for %s:\n Num Nick"), this->c->name.c_str(), source.ci->name.c_str()); + source.Reply(_("%s list for %s:\n Num Nick"), this->c->name.c_str(), ci->name.c_str()); } DoList(source, access, Number - 1, level); @@ -63,36 +63,37 @@ class XOPListCallback : public NumberList class XOPDelCallback : public NumberList { CommandSource &source; + ChannelInfo *ci; Command *c; unsigned Deleted; Anope::string Nicks; bool override; public: - XOPDelCallback(CommandSource &_source, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), c(_c), Deleted(0), override(_override) + XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), Deleted(0), override(_override) { } ~XOPDelCallback() { if (!Deleted) - source.Reply(_("No matching entries on %s %s list."), source.ci->name.c_str(), this->c->name.c_str()); + source.Reply(_("No matching entries on %s %s list."), ci->name.c_str(), this->c->name.c_str()); else { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, source.ci) << "deleted access of users " << Nicks; + Log(override ? LOG_OVERRIDE : LOG_COMMAND, source.u, c, ci) << "deleted access of users " << Nicks; if (Deleted == 1) - source.Reply(_("Deleted one entry from %s %s list."), source.ci->name.c_str(), this->c->name.c_str()); + source.Reply(_("Deleted one entry from %s %s list."), ci->name.c_str(), this->c->name.c_str()); else - source.Reply(_("Deleted %d entries from %s %s list."), Deleted, source.ci->name.c_str(), this->c->name.c_str()); + source.Reply(_("Deleted %d entries from %s %s list."), Deleted, ci->name.c_str(), this->c->name.c_str()); } } void HandleNumber(unsigned Number) { - if (!Number || Number > source.ci->GetAccessCount()) + if (!Number || Number > ci->GetAccessCount()) return; - ChanAccess *access = source.ci->GetAccess(Number - 1); + ChanAccess *access = ci->GetAccess(Number - 1); ++Deleted; if (!Nicks.empty()) @@ -100,19 +101,18 @@ class XOPDelCallback : public NumberList else Nicks = access->GetMask(); - FOREACH_MOD(I_OnAccessDel, OnAccessDel(source.ci, source.u, access)); + FOREACH_MOD(I_OnAccessDel, OnAccessDel(ci, source.u, access)); - source.ci->EraseAccess(Number - 1); + ci->EraseAccess(Number - 1); } }; class XOPBase : public Command { private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms, int level) + void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, int level) { User *u = source.u; - ChannelInfo *ci = source.ci; Anope::string mask = params.size() > 2 ? params[2] : ""; int change = 0; @@ -120,13 +120,13 @@ class XOPBase : public Command if (mask.empty()) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } if (readonly) { source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), this->name.c_str()); - return MOD_CONT; + return; } ChanAccess *access = ci->GetAccess(u); @@ -134,8 +134,8 @@ class XOPBase : public Command if ((level >= ulev || ulev < ACCESS_AOP) && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } NickAlias *na = findnick(mask); @@ -150,8 +150,8 @@ class XOPBase : public Command **/ if (access->level >= ulev && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } ++change; } @@ -159,7 +159,7 @@ class XOPBase : public Command if (!change && ci->GetAccessCount() >= Config->CSAccessMax) { source.Reply(_("Sorry, you can only have %d %s entries on a channel."), Config->CSAccessMax, this->name.c_str()); - return MOD_CONT; + return; } if (!change) @@ -185,32 +185,31 @@ class XOPBase : public Command source.Reply(_("\002%s\002 moved to %s %s list."), access->GetMask().c_str(), ci->name.c_str(), this->name.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms, int level) + void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, int level) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &mask = params.size() > 2 ? params[2] : ""; if (mask.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } if (readonly) { source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), this->name.c_str()); - return MOD_CONT; + return; } if (!ci->GetAccessCount()) { source.Reply(_("%s %s list is empty."), ci->name.c_str(), this->name.c_str()); - return MOD_CONT; + return; } ChanAccess *access = ci->GetAccess(u); @@ -218,8 +217,8 @@ class XOPBase : public Command if ((!access || access->nc != u->Account()) && (level >= ulev || ulev < ACCESS_AOP) && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } access = ci->GetAccess(mask, 0, false); @@ -228,18 +227,18 @@ class XOPBase : public Command if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) { bool override = level >= ulev || ulev < ACCESS_AOP; - XOPDelCallback list(source, this, override, mask); + XOPDelCallback list(source, ci, this, override, mask); list.Process(); } else if (!access || access->level != level) { source.Reply(_("\002%s\002 not found on %s %s list."), mask.c_str(), ci->name.c_str(), this->name.c_str()); - return MOD_CONT; + return; } else { if (access->nc != u->Account() && ulev <= access->level && !u->HasPriv("chanserv/access/modify")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { bool override = ulev <= access->level; @@ -253,23 +252,22 @@ class XOPBase : public Command } } - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms, int level) + void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, int level) { User *u = source.u; - ChannelInfo *ci = source.ci; const Anope::string &nick = params.size() > 2 ? params[2] : ""; ChanAccess *access = ci->GetAccess(u); uint16 ulev = access ? access->level : 0; - if (!ulev && !u->HasCommand("chanserv/access/list")) + if (!ulev && !u->HasCommand("chanserv/chanserv/access/list")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } bool override = !ulev; @@ -278,12 +276,12 @@ class XOPBase : public Command if (!ci->GetAccessCount()) { source.Reply(_("%s %s list is empty."), ci->name.c_str(), this->name.c_str()); - return MOD_CONT; + return; } if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos) { - XOPListCallback list(source, nick, level, this); + XOPListCallback list(source, ci, nick, level, this); list.Process(); } else @@ -312,30 +310,29 @@ class XOPBase : public Command source.Reply(_("No matching entries on %s %s list."), ci->name.c_str(), this->name.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoClear(CommandSource &source, int level) + void DoClear(CommandSource &source, ChannelInfo *ci, int level) { User *u = source.u; - ChannelInfo *ci = source.ci; if (readonly) { source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), this->name.c_str()); - return MOD_CONT; + return; } if (!ci->GetAccessCount()) { source.Reply(_("%s %s list is empty."), ci->name.c_str(), this->name.c_str()); - return MOD_CONT; + return; } if (!check_access(u, ci, CA_FOUNDER) && !u->HasPriv("chanserv/access/modify")) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } bool override = !check_access(u, ci, CA_FOUNDER); @@ -352,69 +349,72 @@ class XOPBase : public Command source.Reply(_("Channel %s %s list has been cleared."), ci->name.c_str(), this->name.c_str()); - return MOD_CONT; + return; } protected: - CommandReturn DoXop(CommandSource &source, const std::vector<Anope::string> ¶ms, int level) + void DoXop(CommandSource &source, const std::vector<Anope::string> ¶ms, int level) { - ChannelInfo *ci = source.ci; + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } const Anope::string &cmd = params[1]; if (!ci->HasFlag(CI_XOP)) - source.Reply(_("You can't use this command. Use the ACCESS command instead.\n" - "Type \002%s%s HELP ACCESS\002 for more information."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + source.Reply(_("You can't use this command. Use the ACCESS command instead.")); else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params, level); + return this->DoAdd(source, ci, params, level); else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params, level); + return this->DoDel(source, ci, params, level); else if (cmd.equals_ci("LIST")) - return this->DoList(source, params, level); + return this->DoList(source, ci, params, level); else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source, level); + return this->DoClear(source, ci, level); else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } public: - XOPBase(const Anope::string &command) : Command(command, 2, 4) + XOPBase(Module *modname, const Anope::string &command) : Command(modname, command, 2, 4) { + this->SetSyntax("\037channel\037 ADD \037mask\037"); + this->SetSyntax("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}"); + this->SetSyntax("\037channel\037 LIST [\037mask\037 | \037list\037]"); + this->SetSyntax("\037channel\037 CLEAR"); } virtual ~XOPBase() { } - virtual CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; + virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; - - virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) = 0; }; class CommandCSQOP : public XOPBase { public: - CommandCSQOP() : XOPBase("QOP") + CommandCSQOP(Module *creator) : XOPBase(creator, "chanserv/qop") { this->SetDesc(_("Modify the list of QOP users")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoXop(source, params, ACCESS_QOP); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002QOP \037channel\037 ADD \037mask\037\002\n" - " \002QOP \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002QOP \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002QOP \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002QOP\002 (AutoOwner) \002list\002 for a channel. The QOP \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002QOP\002 (AutoOwner) \002list\002 for a channel. The QOP \n" "list gives users the right to be auto-owner on your channel,\n" "which gives them almost (or potentially, total) access.\n" " \n" @@ -445,38 +445,30 @@ class CommandCSQOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "QOP", _("QOP \037channel\037 {ADD|DEL|LIST|CLEAR} [\037nick\037 | \037entry-list\037]")); - } }; class CommandCSAOP : public XOPBase { public: - CommandCSAOP() : XOPBase("AOP") + CommandCSAOP(Module *creator) : XOPBase(creator, "chanserv/aop") { this->SetDesc(_("Modify the list of AOP users")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoXop(source, params, ACCESS_AOP); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002AOP \037channel\037 ADD \037mask\037\002\n" - " \002AOP \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002AOP \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002AOP \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002AOP\002 (AutoOP) \002list\002 for a channel. The AOP \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002AOP\002 (AutoOP) \002list\002 for a channel. The AOP \n" "list gives users the right to be auto-opped on your channel,\n" "to unban or invite themselves if needed, to have their\n" "greet message showed on join, and so on.\n" @@ -509,38 +501,30 @@ class CommandCSAOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "AOP", _("AOP \037channel\037 {ADD|DEL|LIST|CLEAR} [\037nick\037 | \037entry-list\037]")); - } }; class CommandCSHOP : public XOPBase { public: - CommandCSHOP() : XOPBase("HOP") + CommandCSHOP(Module *creator) : XOPBase(creator, "chanserv/hop") { this->SetDesc(_("Maintains the HOP (HalfOP) list for a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoXop(source, params, ACCESS_HOP); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002HOP \037channel\037 ADD \037mask\037\002\n" - " \002HOP \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002HOP \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002HOP \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002HOP\002 (HalfOP) \002list\002 for a channel. The HOP \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002HOP\002 (HalfOP) \002list\002 for a channel. The HOP \n" "list gives users the right to be auto-halfopped on your \n" "channel.\n" " \n" @@ -571,38 +555,30 @@ class CommandCSHOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "HOP", _("HOP \037channel\037 {ADD|DEL|LIST|CLEAR} [\037nick\037 | \037entry-list\037]")); - } }; class CommandCSSOP : public XOPBase { public: - CommandCSSOP() : XOPBase("SOP") + CommandCSSOP(Module *creator) : XOPBase(creator, "chanserv/sop") { this->SetDesc(_("Modify the list of SOP users")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoXop(source, params, ACCESS_SOP); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SOP \037channel\037 ADD \037mask\037\002\n" - " \002SOP \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002SOP \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002SOP \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002SOP\002 (SuperOP) \002list\002 for a channel. The SOP \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002SOP\002 (SuperOP) \002list\002 for a channel. The SOP \n" "list gives users all rights given by the AOP list, and adds\n" "those needed to use the AutoKick and the BadWords lists, \n" "to send and read channel memos, and so on.\n" @@ -635,38 +611,30 @@ class CommandCSSOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SOP", _("SOP \037channel\037 {ADD|DEL|LIST|CLEAR} [\037nick\037 | \037entry-list\037]")); - } }; class CommandCSVOP : public XOPBase { public: - CommandCSVOP() : XOPBase("VOP") + CommandCSVOP(Module *creator) : XOPBase(creator, "chanserv/vop") { this->SetDesc(_("Maintains the VOP (VOicePeople) list for a channel")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoXop(source, params, ACCESS_VOP); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002VOP \037channel\037 ADD \037mask\037\002\n" - " \002VOP \037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002VOP \037channel\037 LIST [\037mask\037 | \037list\037]\002\n" - " \002VOP \037channel\037 CLEAR\002\n" - " \n" - "Maintains the \002VOP\002 (VOicePeople) \002list\002 for a channel. \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Maintains the \002VOP\002 (VOicePeople) \002list\002 for a channel. \n" "The VOP list allows users to be auto-voiced and to voice \n" "themselves if they aren't.\n" " \n" @@ -698,15 +666,10 @@ class CommandCSVOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), - Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), + Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "VOP", _("VOP \037channel\037 {ADD|DEL|LIST|CLEAR} [\037nick\037 | \037entry-list\037]")); - } }; class CSXOP : public Module @@ -718,33 +681,16 @@ class CSXOP : public Module CommandCSVOP commandcsvop; public: - CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandcsqop(this), commandcssop(this), commandcsaop(this), commandcshop(this), commandcsvop(this) { this->SetAuthor("Anope"); - this->AddCommand(chanserv->Bot(), &commandcssop); - this->AddCommand(chanserv->Bot(), &commandcsaop); - this->AddCommand(chanserv->Bot(), &commandcsvop); - - if (Me && Me->IsSynced()) - OnUplinkSync(NULL); - - Implementation i[] = {I_OnUplinkSync, I_OnServerDisconnect}; - ModuleManager::Attach(i, this, 2); - } - - void OnUplinkSync(Server *) - { - if (ModeManager::FindChannelModeByName(CMODE_OWNER)) - this->AddCommand(chanserv->Bot(), &commandcsqop); - if (ModeManager::FindChannelModeByName(CMODE_HALFOP)) - this->AddCommand(chanserv->Bot(), &commandcshop); - } - - void OnServerDisconnect() - { - this->DelCommand(chanserv->Bot(), &commandcsqop); - this->DelCommand(chanserv->Bot(), &commandcshop); + ModuleManager::RegisterService(&commandcssop); + ModuleManager::RegisterService(&commandcsaop); + ModuleManager::RegisterService(&commandcsqop); + ModuleManager::RegisterService(&commandcsvop); + ModuleManager::RegisterService(&commandcshop); } }; diff --git a/modules/core/db_mysql.cpp b/modules/core/db_mysql.cpp index 6a5ba8900..3da43f6a7 100644 --- a/modules/core/db_mysql.cpp +++ b/modules/core/db_mysql.cpp @@ -1,5 +1,4 @@ #include "module.h" -#include "operserv.h" #include "../extra/sql.h" #include "os_session.h" @@ -53,18 +52,19 @@ static void WriteBotMetadata(const Anope::string &key, const Anope::string &data class CommandSQLSync : public Command { public: - CommandSQLSync() : Command("SQLSYNC", 0, 0, "operserv/sqlsync") + CommandSQLSync(Module *creator) : Command(creator, "SQLSYNC", 0, 0, "operserv/sqlsync") { this->SetDesc(_("Import your databases to SQL")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms); + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms); bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SQLSYNC\002\n" - " \n" - "This command syncs your databases with SQL. You should\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command syncs your databases with SQL. You should\n" "only have to execute this command once, when you initially\n" "import your databases into SQL.")); return true; @@ -102,8 +102,9 @@ class DBMySQL : public Module if (readonly && this->ro) { readonly = this->ro = false; - if (operserv) - ircdproto->SendGlobops(operserv->Bot(), "Found SQL again, going out of readonly mode..."); + BotInfo *bi = findbot(Config->OperServ); + if (bi) + ircdproto->SendGlobops(bi, "Found SQL again, going out of readonly mode..."); } SQL->Run(&sqlinterface, query); @@ -112,19 +113,19 @@ class DBMySQL : public Module { if (Anope::CurTime - Config->UpdateTimeout > lastwarn) { - if (operserv) - ircdproto->SendGlobops(operserv->Bot(), "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); + BotInfo *bi = findbot(Config->OperServ); + if (bi) + ircdproto->SendGlobops(bi, "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); readonly = this->ro = true; this->lastwarn = Anope::CurTime; } } } - DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), sqlinterface(this), SQL("mysql/main"), SessionInterface("session") + DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE), commandsqlsync(this), sqlinterface(this), SQL("mysql/main"), SessionInterface("session") { me = this; - this->lastwarn = 0; this->ro = false; @@ -133,8 +134,7 @@ class DBMySQL : public Module }; ModuleManager::Attach(i, this, 2); - if (operserv) - this->AddCommand(operserv->Bot(), &commandsqlsync); + ModuleManager::RegisterService(&commandsqlsync); if (CurrentUplink) OnServerConnect(); @@ -161,12 +161,12 @@ class DBMySQL : public Module /* MemoServ */ I_OnMemoSend, I_OnMemoDel, /* OperServ */ - I_OnAddAkill, I_OnDelAkill, I_OnExceptionAdd, I_OnExceptionDel, + I_OnExceptionAdd, I_OnExceptionDel, I_OnAddXLine, I_OnDelXLine, /* HostServ */ I_OnSetVhost, I_OnDeleteVhost }; - ModuleManager::Attach(i, this, 42); + ModuleManager::Attach(i, this, 41); } EventReturn OnLoadDatabase() @@ -546,46 +546,28 @@ class DBMySQL : public Module } } - if (SQLine) + for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it) { - query = "SELECT * FROM `anope_os_akills`"; + XLineManager *xm = *it; + + query = "SELECT * FROM `anope_os_xlines` WHERE `type` = @type"; + query.setValue("type", Anope::string(xm->Type())); r = SQL->RunQuery(query); for (int i = 0; i < r.Rows(); ++i) { Anope::string user = r.Get(i, "user"); Anope::string host = r.Get(i, "host"); - Anope::string by = r.Get(i, "by"); + Anope::string by = r.Get(i, "xby"); Anope::string reason = r.Get(i, "reason"); time_t seton = r.Get(i, "seton").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "seton")) : Anope::CurTime; time_t expires = r.Get(i, "expires").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "expires")) : Anope::CurTime; - XLine *x = SGLine->Add(user + "@" + host, by, expires, reason); + XLine *x = xm->Add(user + "@" + host, by, expires, reason); if (x) x->Created = seton; } } - query = "SELECT * FROM `anope_os_xlines`"; - r = SQL->RunQuery(query); - for (int i = 0; i < r.Rows(); ++i) - { - Anope::string mask = r.Get(i, "mask"); - Anope::string by = r.Get(i, "xby"); - Anope::string reason = r.Get(i, "reason"); - time_t seton = r.Get(i, "seton").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "seton")) : Anope::CurTime; - time_t expires = r.Get(i, "expire").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "expire")) : Anope::CurTime; - - XLine *x = NULL; - if (SNLine && r.Get(i, "type").equals_cs("SNLINE")) - x = SNLine->Add(mask, by, expires, reason); - else if (SQLine && r.Get(i, "type").equals_cs("SQLINE")) - x = SQLine->Add(mask, by, expires, reason); - else if (SZLine && r.Get(i, "type").equals_cs("SZLINE")) - x = SZLine->Add(mask, by, expires, reason); - if (x) - x->Created = seton; - } - query = "SELECT * FROM `anope_os_exceptions`"; r = SQL->RunQuery(query); for (int i = 0; i < r.Rows(); ++i) @@ -652,10 +634,6 @@ class DBMySQL : public Module query = "INSERT INTO `anope_os_core` (maxusercnt, maxusertime, akills_count, snlines_count, sqlines_count, szlines_count) VALUES(@maxusercnt, @maxusertime, @akills_count, @snlines_count, @sqlines_count, @szlines_count)"; query.setValue("maxusercnt", maxusercnt); query.setValue("maxusertime", maxusertime); - query.setValue("akills_count", SGLine ? SGLine->GetCount() : 0); - query.setValue("snlines_count", SQLine ? SQLine->GetCount() : 0); - query.setValue("sqlines_count", SNLine ? SNLine->GetCount() : 0); - query.setValue("szlines_count", SZLine ? SZLine->GetCount() : 0); this->RunQuery(query); for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it) @@ -678,10 +656,12 @@ class DBMySQL : public Module for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) { + if (it->second->HasFlag(BI_CONF)) + continue; + CurBot = it->second; FOREACH_MOD(I_OnDatabaseWriteMetadata, OnDatabaseWriteMetadata(WriteBotMetadata, CurBot)); - /* This is for the core bots, bots added by users are already handled by an event */ query = "INSERT INTO `anope_bs_core` (nick, user, host, rname, flags, created, chancount) VALUES(@nick, @user, @host, @rname, @flags, @created, @chancount) ON DUPLICATE KEY UPDATE nick=VALUES(nick), user=VALUES(user), host=VALUES(host), rname=VALUES(rname), flags=VALUES(flags), created=VALUES(created), chancount=VALUES(chancount)"; query.setValue("nick", CurBot->nick); query.setValue("user", CurBot->GetIdent()); @@ -703,215 +683,202 @@ class DBMySQL : public Module void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { User *u = source.u; - BotInfo *service = command->service; - ChannelInfo *ci = source.ci; - if (service->nick == Config->s_NickServ) + if (command->name.find("nickserv/set/") == 0 || command->name.find("nickserv/saset/") == 0) { - if (u->Account() && ((command->name.equals_ci("SET") && !params.empty()) || (command->name.equals_ci("SASET") && u->HasCommand("nickserv/saset") && params.size() > 1))) + NickAlias *na = findnick(command->name.find("nickserv/set/") == 0 ? source.u->nick : params[1]); + if (!na) + return; + + if (command->name == "nickserv/set/password" || command->name == "nickserv/saset/password") { - Anope::string cmd = (command->name.equals_ci("SET") ? params[0] : params[1]); - NickCore *nc = (command->name.equals_ci("SET") ? u->Account() : findcore(params[0])); - if (!nc) - return; - if (cmd.equals_ci("PASSWORD") && params.size() > 1) - { - SQLQuery query("UPDATE `anope_ns_core` SET `pass` = @pass WHERE `display` = @display"); - query.setValue("pass", nc->pass); - query.setValue("display", nc->display); - this->RunQuery(query); - } - else if (cmd.equals_ci("LANGUAGE") && params.size() > 1) - { - SQLQuery query("UPDATE `anope_ns_core` SET `language` = @language WHERE `display` = @display"); - query.setValue("language", nc->language); - query.setValue("display", nc->display); - this->RunQuery(query); - } - else if (cmd.equals_ci("EMAIL")) - { - SQLQuery query("UPDATE `anope_ns_core` SET `email` = @email WHERE `display` = @display"); - query.setValue("email", nc->email); - query.setValue("display", nc->display); - this->RunQuery(query); - } - else if (cmd.equals_ci("GREET")) - { - SQLQuery query("UPDATE `anope_ns_core` SET `greet` = @greet WHERE `display` = @display"); - query.setValue("greet", nc->greet); - query.setValue("display", nc->display); - this->RunQuery(query); - } - else if (cmd.equals_ci("KILL") || cmd.equals_ci("SECURE") || cmd.equals_ci("PRIVATE") || cmd.equals_ci("MSG") || cmd.equals_ci("HIDE") || cmd.equals_ci("AUTOOP")) - { - SQLQuery query("UPDATE `anope_ns_core` SET `flags` = @flags WHERE `display` = @display"); - query.setValue("flags", ToString(nc->ToString())); - query.setValue("display", nc->display); - this->RunQuery(query); - } + SQLQuery query("UPDATE `anope_ns_core` SET `pass` = @pass WHERE `display` = @display"); + query.setValue("pass", na->nc->pass); + query.setValue("display", na->nc->display); + this->RunQuery(query); + } + else if (command->name == "nickserv/set/language" || command->name == "nickserv/saset/language") + { + SQLQuery query("UPDATE `anope_ns_core` SET `language` = @language WHERE `display` = @display"); + query.setValue("language", na->nc->language); + query.setValue("display", na->nc->display); + this->RunQuery(query); + } + else if (command->name == "nickserv/set/email" || command->name == "nickserv/saset/email") + { + SQLQuery query("UPDATE `anope_ns_core` SET `email` = @email WHERE `display` = @display"); + query.setValue("email", na->nc->email); + query.setValue("display", na->nc->display); + this->RunQuery(query); + } + else if (command->name == "nickserv/set/greet" || command->name == "nickserv/saset/greet") + { + SQLQuery query("UPDATE `anope_ns_core` SET `greet` = @greet WHERE `display` = @display"); + query.setValue("greet", na->nc->greet); + query.setValue("display", na->nc->display); + this->RunQuery(query); + } + else + { + SQLQuery query("UPDATE `anope_ns_core` SET `flags` = @flags WHERE `display` = @display"); + query.setValue("flags", ToString(na->nc->ToString())); + query.setValue("display", na->nc->display); + this->RunQuery(query); } } - else if (service->nick == Config->s_ChanServ) + else if (command->name.find("chanserv/set") == 0 || command->name.find("chanserv/saset") == 0) { - if (command->name.equals_ci("SET") && u->Account() && params.size() > 1) + ChannelInfo *ci = params.size() > 0 ? cs_findchan(params[0]) : NULL; + if (!ci) + return; + + if (command->name == "chanserv/set/founder" || command->name == "chanserv/saset/founder") { - if (!ci) - return; - if (!u->HasPriv("chanserv/set") && check_access(u, ci, CA_SET)) - return; - if (params[1].equals_ci("FOUNDER")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `founder` = @founder WHERE `name` = @name"); - query.setValue("founder", ci->GetFounder() ? ci->GetFounder()->display : ""); - query.setValue("name", ci->name); - this->RunQuery(query); - } - else if (params[1].equals_ci("SUCCESSOR")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `successor` = @successor WHERE `name` = @name"); - query.setValue("successor", ci->successor ? ci->successor->display : ""); - query.setValue("name", ci->name); - this->RunQuery(query); - } - else if (params[1].equals_ci("DESC")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `descr` = @descr WHERE `name` = @name"); - query.setValue("descr", ci->desc); - query.setValue("name", ci->name); - this->RunQuery(query); - } - else if (params[1].equals_ci("BANTYPE")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `bantype` = @bantype WHERE `name` = @name"); - query.setValue("bantype", ci->bantype); - query.setValue("name", ci->name); - this->RunQuery(query); - } - else if (params[1].equals_ci("KEEPTOPIC") || params[1].equals_ci("TOPICLOCK") || params[1].equals_ci("PRIVATE") || params[1].equals_ci("SECUREOPS") || params[1].equals_ci("SECUREFOUNDER") || params[1].equals_ci("RESTRICTED") || params[1].equals_ci("SECURE") || params[1].equals_ci("SIGNKICK") || params[1].equals_ci("OPNOTICE") || params[1].equals_ci("XOP") || params[1].equals_ci("PEACE") || params[1].equals_ci("PERSIST") || params[1].equals_ci("NOEXPIRE")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `flags` = @flags WHERE `name` = @name"); - query.setValue("flags", ToString(ci->ToString())); - query.setValue("name", ci->name); - this->RunQuery(query); - } + SQLQuery query("UPDATE `anope_cs_info` SET `founder` = @founder WHERE `name` = @name"); + query.setValue("founder", ci->GetFounder() ? ci->GetFounder()->display : ""); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else if (command->name == "chanserv/set/successor" || command->name == "chanserv/saset/successor") + { + SQLQuery query("UPDATE `anope_cs_info` SET `successor` = @successor WHERE `name` = @name"); + query.setValue("successor", ci->successor ? ci->successor->display : ""); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else if (command->name == "chanserv/set/desc" || command->name == "chanserv/saset/desc") + { + SQLQuery query("UPDATE `anope_cs_info` SET `descr` = @descr WHERE `name` = @name"); + query.setValue("descr", ci->desc); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else if (command->name == "chanserv/set/bantype" || command->name == "chanserv/saset/bantype") + { + SQLQuery query("UPDATE `anope_cs_info` SET `bantype` = @bantype WHERE `name` = @name"); + query.setValue("bantype", ci->bantype); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else + { + SQLQuery query("UPDATE `anope_cs_info` SET `flags` = @flags WHERE `name` = @name"); + query.setValue("flags", ToString(ci->ToString())); + query.setValue("name", ci->name); + this->RunQuery(query); } } - else if (service->nick == Config->s_BotServ) + else if (command->name == "botserv/kick" && params.size() > 2) { - if (command->name.equals_ci("KICK") && params.size() > 2) + ChannelInfo *ci = cs_findchan(params[0]); + if (!ci) + return; + if (!check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) + return; + if (params[1].equals_ci("BADWORDS") || params[1].equals_ci("BOLDS") || params[1].equals_ci("CAPS") || params[1].equals_ci("COLORS") || params[1].equals_ci("FLOOD") || params[1].equals_ci("REPEAT") || params[1].equals_ci("REVERSES") || params[1].equals_ci("UNDERLINES")) { - if (!ci) - return; - if (!check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) - return; - if (params[1].equals_ci("BADWORDS") || params[1].equals_ci("BOLDS") || params[1].equals_ci("CAPS") || params[1].equals_ci("COLORS") || params[1].equals_ci("FLOOD") || params[1].equals_ci("REPEAT") || params[1].equals_ci("REVERSES") || params[1].equals_ci("UNDERLINES")) + if (params[2].equals_ci("ON") || params[2].equals_ci("OFF")) { - if (params[2].equals_ci("ON") || params[2].equals_ci("OFF")) + for (int i = 0; i < TTB_SIZE; ++i) + { + SQLQuery query("INSERT INTO `anope_cs_ttb` (channel, ttb_id, value) VALUES(@channel, @ttb_id, @value) ON DUPLICATE KEY UPDATE channel=VALUES(channel), ttb_id=VALUES(ttb_id), value=VALUES(value)"); + query.setValue("channel", ci->name); + query.setValue("ttb_id", i); + query.setValue("value", ci->ttb[i]); + this->RunQuery(query); + } + + { + SQLQuery query("UPDATE `anope_cs_info` SET `botflags` = @botflags WHERE `name` = @name"); + query.setValue("botflags", ToString(ci->botflags.ToString())); + query.setValue("name", ci->name); + this->RunQuery(query); + } + + if (params[1].equals_ci("CAPS")) + { + SQLQuery query("UPDATE `anope_cs_info` SET `capsmin` = @capsmin, `capspercent` = @capspercent WHERE `name` = @name"); + query.setValue("capsmin", ci->capsmin); + query.setValue("capspercent", ci->capspercent); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else if (params[1].equals_ci("FLOOD")) { - for (int i = 0; i < TTB_SIZE; ++i) - { - SQLQuery query("INSERT INTO `anope_cs_ttb` (channel, ttb_id, value) VALUES(@channel, @ttb_id, @value) ON DUPLICATE KEY UPDATE channel=VALUES(channel), ttb_id=VALUES(ttb_id), value=VALUES(value)"); - query.setValue("channel", ci->name); - query.setValue("ttb_id", i); - query.setValue("value", ci->ttb[i]); - this->RunQuery(query); - } - - { - SQLQuery query("UPDATE `anope_cs_info` SET `botflags` = @botflags WHERE `name` = @name"); - query.setValue("botflags", ToString(ci->botflags.ToString())); - query.setValue("name", ci->name); - this->RunQuery(query); - } - - if (params[1].equals_ci("CAPS")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `capsmin` = @capsmin, `capspercent` = @capspercent WHERE `name` = @name"); - query.setValue("capsmin", ci->capsmin); - query.setValue("capspercent", ci->capspercent); - query.setValue("name", ci->name); - this->RunQuery(query); - } - - else if (params[1].equals_ci("FLOOD")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `floodlines` = @floodlines, `floodsecs` = @floodsecs WHERE `name` = @name"); - query.setValue("floodlines", ci->floodlines); - query.setValue("floodsecs", ci->floodsecs); - query.setValue("name", ci->name); - this->RunQuery(query); - } - else if (params[1].equals_ci("REPEAT")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `repeattimes` = @ WHERE `name` = @"); - query.setValue("repeattimes", ci->repeattimes); - query.setValue("name", ci->name); - this->RunQuery(query); - } + SQLQuery query("UPDATE `anope_cs_info` SET `floodlines` = @floodlines, `floodsecs` = @floodsecs WHERE `name` = @name"); + query.setValue("floodlines", ci->floodlines); + query.setValue("floodsecs", ci->floodsecs); + query.setValue("name", ci->name); + this->RunQuery(query); + } + else if (params[1].equals_ci("REPEAT")) + { + SQLQuery query("UPDATE `anope_cs_info` SET `repeattimes` = @ WHERE `name` = @"); + query.setValue("repeattimes", ci->repeattimes); + query.setValue("name", ci->name); + this->RunQuery(query); } } } - else if (command->name.equals_ci("SET") && params.size() > 2) + } + else if (command->name == "botserv/set" && params.size() > 1) + { + ChannelInfo *ci = cs_findchan(params[0]); + if (ci && !check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) + return; + BotInfo *bi = NULL; + if (!ci) + bi = findbot(params[0]); + if (bi && params[1].equals_ci("PRIVATE") && u->HasPriv("botserv/set/private")) + { + SQLQuery query("UPDATE `anope_bs_core` SET `flags` = @ WHERE `nick` = @"); + query.setValue("flags", ToString(bi->ToString())); + query.setValue("nick", bi->nick); + this->RunQuery(query); + } + else if (!ci) + return; + else if (params[1].equals_ci("DONTKICKOPS") || params[1].equals_ci("DONTKICKVOICES") || params[1].equals_ci("FANTASY") || params[1].equals_ci("GREET") || params[1].equals_ci("SYMBIOSIS") || params[1].equals_ci("NOBOT")) { - if (ci && !check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) - return; - BotInfo *bi = NULL; - if (!ci) - bi = findbot(params[0]); - if (bi && params[1].equals_ci("PRIVATE") && u->HasPriv("botserv/set/private")) - { - SQLQuery query("UPDATE `anope_bs_core` SET `flags` = @ WHERE `nick` = @"); - query.setValue("flags", ToString(bi->ToString())); - query.setValue("nick", bi->nick); - this->RunQuery(query); - } - else if (!ci) - return; - else if (params[1].equals_ci("DONTKICKOPS") || params[1].equals_ci("DONTKICKVOICES") || params[1].equals_ci("FANTASY") || params[1].equals_ci("GREET") || params[1].equals_ci("SYMBIOSIS") || params[1].equals_ci("NOBOT")) - { - SQLQuery query("UPDATE `anope_cs_info` SET `botflags` = @ WHERE `name` = @"); - query.setValue("botflags", ToString(ci->botflags.ToString())); - query.setValue("name", ci->name); - this->RunQuery(query); - } + SQLQuery query("UPDATE `anope_cs_info` SET `botflags` = @ WHERE `name` = @"); + query.setValue("botflags", ToString(ci->botflags.ToString())); + query.setValue("name", ci->name); + this->RunQuery(query); } } - else if (service->nick == Config->s_MemoServ) + else if (command->name == "memoserv/ignore" && params.size() > 0) { - if (command->name.equals_ci("IGNORE") && params.size() > 0) + Anope::string target = params[0]; + NickCore *nc = NULL; + ChannelInfo *ci = NULL; + if (target[0] != '#') { - Anope::string target = params[0]; - NickCore *nc = NULL; - ci = NULL; - if (target[0] != '#') - { - target = u->nick; - nc = u->Account(); - if (!nc) - return; - } - else - { - ci = cs_findchan(target); - if (!ci || !check_access(u, ci, CA_MEMO)) - return; - } + target = u->nick; + nc = u->Account(); + if (!nc) + return; + } + else + { + ci = cs_findchan(target); + if (!ci || !check_access(u, ci, CA_MEMO)) + return; + } - MemoInfo *mi = ci ? &ci->memos : &nc->memos; - Anope::string table = ci ? "anope_cs_info_metadata" : "anope_ns_core_metadata"; - Anope::string ename = ci ? "channel" : "nick"; + MemoInfo *mi = ci ? &ci->memos : &nc->memos; + Anope::string table = ci ? "anope_cs_info_metadata" : "anope_ns_core_metadata"; + Anope::string ename = ci ? "channel" : "nick"; - SQLQuery query("DELETE FROM `" + table + "` WHERE `" + ename + "` = @target AND `name` = 'MEMO_IGNORE'"); - query.setValue("target", target); - this->RunQuery(query); + SQLQuery query("DELETE FROM `" + table + "` WHERE `" + ename + "` = @target AND `name` = 'MEMO_IGNORE'"); + query.setValue("target", target); + this->RunQuery(query); - query = "INSERT INTO `" + table + "` VALUES(" + ename + ", name, value) (@target, 'MEMO_IGNORE, @ignore)"; - query.setValue("target", target); - for (unsigned j = 0; j < mi->ignores.size(); ++j) - { - query.setValue("ignore", mi->ignores[j]); - this->RunQuery(query); - } + query = "INSERT INTO `" + table + "` VALUES(" + ename + ", name, value) (@target, 'MEMO_IGNORE, @ignore)"; + query.setValue("target", target); + for (unsigned j = 0; j < mi->ignores.size(); ++j) + { + query.setValue("ignore", mi->ignores[j]); + this->RunQuery(query); } } } @@ -1334,34 +1301,6 @@ class DBMySQL : public Module this->RunQuery(query); } - EventReturn OnAddAkill(XLine *ak) - { - SQLQuery query("INSERT INTO `anope_os_akills` (user, host, xby, reason, seton, expire) VALUES(@user, @host, @xby, @reason, @seton, @expire)"); - query.setValue("user", ak->GetUser()); - query.setValue("host", ak->GetHost()); - query.setValue("xby", ak->By); - query.setValue("reason", ak->Reason); - query.setValue("seton", ak->Created); - query.setValue("expire", ak->Expires); - this->RunQuery(query); - return EVENT_CONTINUE; - } - - void OnDelAkill(User *, XLine *ak) - { - SQLQuery query; - - if (ak) - { - query = "DELETE FROM `anope_os_akills` WHERE `host` = @host"; - query.setValue("host", ak->GetHost()); - } - else - query = "TRUNCATE TABLE `anope_os_akills`"; - - this->RunQuery(query); - } - EventReturn OnExceptionAdd(Exception *ex) { SQLQuery query("INSERT INTO `anope_os_exceptions` (mask, slimit, who, reason, time, expires) VALUES(@mask, @slimit, @who, @reason, @time, @expires)"); @@ -1381,10 +1320,10 @@ class DBMySQL : public Module this->RunQuery(query); } - EventReturn OnAddXLine(XLine *x, XLineType Type) + EventReturn OnAddXLine(XLine *x, XLineManager *xlm) { SQLQuery query("INSERT INTO `anope_os_xlines` (type, mask, xby, reason, seton, expire) VALUES(@type, @mask, @xby, @reason, @seton, @expire)"); - query.setValue("type", Type == X_SNLINE ? "SNLINE" : (Type == X_SQLINE ? "SQLINE" : "SZLINE")); + query.setValue("type", Anope::string(xlm->Type())); query.setValue("mask", x->Mask); query.setValue("xby", x->By); query.setValue("reason", x->Reason); @@ -1394,7 +1333,7 @@ class DBMySQL : public Module return EVENT_CONTINUE; } - void OnDelXLine(User *, XLine *x, XLineType Type) + void OnDelXLine(User *, XLine *x, XLineManager *xlm) { SQLQuery query; @@ -1402,12 +1341,12 @@ class DBMySQL : public Module { query = "DELETE FROM `anope_os_xlines` WHERE `mask` = @mask AND `type` = @type"; query.setValue("mask", x->Mask); - query.setValue("type", Type == X_SNLINE ? "SNLINE" : (Type == X_SQLINE ? "SQLINE" : "SZLINE")); + query.setValue("type", Anope::string(xlm->Type())); } else { query = "DELETE FROM `anope_os_xlines` WHERE `type` = @type"; - query.setValue("type", Type == X_SNLINE ? "SNLINE" : (Type == X_SQLINE ? "SQLINE" : "SZLINE")); + query.setValue("type", Anope::string(xlm->Type())); } this->RunQuery(query); @@ -1602,32 +1541,20 @@ static void SaveDatabases() } } - if (SGLine) - for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) - me->OnAddAkill(SGLine->GetEntry(i)); - - if (SZLine) - for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) - me->OnAddXLine(SZLine->GetEntry(i), X_SZLINE); - - if (SQLine) - for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) - me->OnAddXLine(SQLine->GetEntry(i), X_SQLINE); - - if (SNLine) - for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - me->OnAddXLine(SNLine->GetEntry(i), X_SNLINE); + for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it) + for (unsigned i = 0, end = (*it)->GetCount(); i < end; ++i) + me->OnAddXLine((*it)->GetEntry(i), *it); if (me->SessionInterface) for (SessionService::ExceptionVector::iterator it = me->SessionInterface->GetExceptions().begin(); it != me->SessionInterface->GetExceptions().end(); ++it) me->OnExceptionAdd(*it); } -CommandReturn CommandSQLSync::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) +void CommandSQLSync::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { SaveDatabases(); source.Reply(_("Updating MySQL.")); - return MOD_CONT; + return; } MODULE_INIT(DBMySQL) diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp index c05047487..d5ccfbfb8 100644 --- a/modules/core/db_plain.cpp +++ b/modules/core/db_plain.cpp @@ -11,7 +11,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "os_session.h" Anope::string DatabaseFile; @@ -305,38 +304,28 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms) maxusercnt = params[1].is_pos_number_only() ? convertTo<uint32>(params[1]) : 0; maxusertime = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0; } - else if (params[0].equals_ci("SNLINE") || params[0].equals_ci("SQLINE") || params[0].equals_ci("SZLINE")) + else if (params[0].equals_ci("SXLINE")) { - Anope::string mask = params[1]; - Anope::string by = params[2]; - time_t seton = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : 0; - time_t expires = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0; - Anope::string reason = params[5]; - - XLine *x = NULL; - if (params[0].equals_ci("SNLINE") && SNLine) - x = SNLine->Add(mask, by, expires, reason); - else if (params[0].equals_ci("SQLINE") && SQLine) - x = SQLine->Add(mask, by, expires, reason); - else if (params[0].equals_ci("SZLINE") && SZLine) - x = SZLine->Add(mask, by, expires, reason); - if (x) - x->Created = seton; - } - else if (params[0].equals_ci("AKILL") && SGLine) - { - Anope::string user = params[1]; - Anope::string host = params[2]; - Anope::string by = params[3]; - time_t seton = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0; - time_t expires = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0; - Anope::string reason = params[6]; - - XLine *x = SGLine->Add(user + "@" + host, by, expires, reason); - if (x) - x->Created = seton; + char type = params[1][0]; + for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it) + { + XLineManager *xl = *it; + if (xl->Type() == type) + { + Anope::string mask = params[2]; + Anope::string by = params[3]; + time_t seton = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0; + time_t expires = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0; + Anope::string reason = params[6]; + + XLine *x = xl->Add(mask, by, expires, reason); + if (x) + x->Created = seton; + break; + } + } } - else if (params[0].equals_ci("EXCEPTION")) + else if (params[0].equals_ci("EXCEPTION") && SessionInterface) { Exception *exception = new Exception(); exception->mask = params[1]; @@ -403,8 +392,6 @@ class DBPlain : public Module Log(LOG_DEBUG) << "db_plain: Attemping to rename " << DatabaseFile << " to " << newname; if (rename(DatabaseFile.c_str(), newname.c_str())) { - if (operserv) - ircdproto->SendGlobops(operserv->Bot(), "Unable to backup database!"); Log() << "Unable to back up database!"; if (!Config->NoBackupOkay) @@ -755,6 +742,9 @@ class DBPlain : public Module { BotInfo *bi = it->second; + if (bi->HasFlag(BI_CONF)) + continue; + db_buffer << "BI " << bi->nick << " " << bi->GetIdent() << " " << bi->host << " " << bi->created << " " << bi->chancount << " :" << bi->realname << endl; if (bi->FlagCount()) db_buffer << "MD FLAGS " << ToString(bi->ToString()) << endl; @@ -850,40 +840,23 @@ class DBPlain : public Module db_buffer << "OS STATS " << maxusercnt << " " << maxusertime << endl; - if (SGLine) - for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) - { - XLine *x = SGLine->GetEntry(i); - db_buffer << "OS AKILL " << x->GetUser() << " " << x->GetHost() << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; - } - - if (SNLine) - for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - { - XLine *x = SNLine->GetEntry(i); - db_buffer << "OS SNLINE " << x->Mask << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; - } - - if (SQLine) - for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) + for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it) + { + XLineManager *xl = *it; + for (unsigned i = 0, end = xl->GetCount(); i < end; ++i) { - XLine *x = SQLine->GetEntry(i); - db_buffer << "OS SQLINE " << x->Mask << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; + XLine *x = xl->GetEntry(i); + db_buffer << "OS SXLINE " << xl->Type() << " " << x->GetUser() << " " << x->GetHost() << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; } + } - if (SZLine) - for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) + if (SessionInterface) + for (SessionService::ExceptionVector::iterator it = SessionInterface->GetExceptions().begin(); it != SessionInterface->GetExceptions().end(); ++it) { - XLine *x = SZLine->GetEntry(i); - db_buffer << "OS SZLINE " << x->Mask << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; + Exception *e = *it; + db_buffer << "OS EXCEPTION " << e->mask << " " << e->limit << " " << e->who << " " << e->time << " " << e->expires << " " << e->reason << endl; } - for (SessionService::ExceptionVector::iterator it = SessionInterface->GetExceptions().begin(); it != SessionInterface->GetExceptions().end(); ++it) - { - Exception *e = *it; - db_buffer << "OS EXCEPTION " << e->mask << " " << e->limit << " " << e->who << " " << e->time << " " << e->expires << " " << e->reason << endl; - } - FOREACH_MOD(I_OnDatabaseWrite, OnDatabaseWrite(Write)); std::fstream db; diff --git a/modules/core/enc_md5.cpp b/modules/core/enc_md5.cpp index a4d528afa..68c13b8e6 100644 --- a/modules/core/enc_md5.cpp +++ b/modules/core/enc_md5.cpp @@ -339,7 +339,7 @@ class EMD5 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { NickAlias *na = findnick(account); NickCore *nc = na ? na->nc : NULL; diff --git a/modules/core/enc_none.cpp b/modules/core/enc_none.cpp index 998ade9ab..9f1637dcd 100644 --- a/modules/core/enc_none.cpp +++ b/modules/core/enc_none.cpp @@ -41,7 +41,7 @@ class ENone : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { NickAlias *na = findnick(account); NickCore *nc = na ? na->nc : NULL; diff --git a/modules/core/enc_old.cpp b/modules/core/enc_old.cpp index ff1226f12..689625fe1 100644 --- a/modules/core/enc_old.cpp +++ b/modules/core/enc_old.cpp @@ -349,7 +349,7 @@ class EOld : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { NickAlias *na = findnick(account); NickCore *nc = na ? na->nc : NULL; diff --git a/modules/core/enc_sha1.cpp b/modules/core/enc_sha1.cpp index 84425751b..165454737 100644 --- a/modules/core/enc_sha1.cpp +++ b/modules/core/enc_sha1.cpp @@ -192,7 +192,7 @@ class ESHA1 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { NickAlias *na = findnick(account); NickCore *nc = na ? na->nc : NULL; diff --git a/modules/core/enc_sha256.cpp b/modules/core/enc_sha256.cpp index a04510a33..8f11ef933 100644 --- a/modules/core/enc_sha256.cpp +++ b/modules/core/enc_sha256.cpp @@ -278,7 +278,7 @@ class ESHA256 : public Module return EVENT_ALLOW; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { NickAlias *na = findnick(account); NickCore *nc = na ? na->nc : NULL; diff --git a/modules/core/gl_global.cpp b/modules/core/gl_global.cpp index 9c944dd33..390d912ef 100644 --- a/modules/core/gl_global.cpp +++ b/modules/core/gl_global.cpp @@ -17,34 +17,34 @@ class CommandGLGlobal : public Command { public: - CommandGLGlobal() : Command("GLOBAL", 1, 1, "global/global") + CommandGLGlobal(Module *creator) : Command(creator, "global/global", 1, 1, "global/global") { this->SetDesc(_("Send a message to all users")); + this->SetSyntax(_("\037message\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &msg = params[0]; - Log(LOG_ADMIN, u, this); - global->SendGlobal(global->Bot(), u->nick, msg); - return MOD_CONT; + if (!global) + source.Reply("No global reference, is gl_main loaded?"); + else + { + Log(LOG_ADMIN, u, this); + global->SendGlobal(findbot(Config->Global), u->nick, msg); + } } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GLOBAL \037message\037\002\n" - " \n" - "Allows Administrators to send messages to all users on the \n" - "network. The message will be sent from the nick \002%s\002."), Config->s_Global.c_str()); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Administrators to send messages to all users on the \n" + "network. The message will be sent from the nick \002%s\002."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GLOBAL", _("GLOBAL \037message\037")); - } }; class GLGlobal : public Module @@ -52,14 +52,12 @@ class GLGlobal : public Module CommandGLGlobal commandglglobal; public: - GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandglglobal(this) { this->SetAuthor("Anope"); - if (Config->s_Global.empty()) - throw ModuleException("Global is disabled"); - - this->AddCommand(global->Bot(), &commandglglobal); + ModuleManager::RegisterService(&commandglglobal); } }; diff --git a/modules/core/gl_help.cpp b/modules/core/gl_help.cpp deleted file mode 100644 index e44c4797e..000000000 --- a/modules/core/gl_help.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* Global core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "global.h" - -class CommandGLHelp : public Command -{ - public: - CommandGLHelp() : Command("HELP", 1, 1) - { - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(global->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("%s commands:"), Config->s_Global.c_str()); - for (CommandMap::const_iterator it = global->Bot()->Commands.begin(), it_end = global->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - } -}; - -class GLHelp : public Module -{ - CommandGLHelp commandoshelp; - - public: - GLHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!global) - throw ModuleException("Global is not loaded!"); - - this->AddCommand(global->Bot(), &commandoshelp); - } -}; - -MODULE_INIT(GLHelp) diff --git a/modules/core/gl_main.cpp b/modules/core/gl_main.cpp index f52be0871..e7fdc95f8 100644 --- a/modules/core/gl_main.cpp +++ b/modules/core/gl_main.cpp @@ -14,26 +14,19 @@ #include "module.h" #include "global.h" -static BotInfo *Global = NULL; - class MyGlobalService : public GlobalService { - void ServerGlobal(Server *s, const Anope::string &message) - { - if (s != Me && !s->HasFlag(SERVER_JUPED)) - notice_server(Config->s_Global, s, "%s", message.c_str()); + void ServerGlobal(Server *s, const Anope::string &message) + { + if (s != Me && !s->HasFlag(SERVER_JUPED)) + notice_server(Config->Global, s, "%s", message.c_str()); for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) this->ServerGlobal(s->GetLinks()[i], message); - } + } public: MyGlobalService(Module *m) : GlobalService(m) { } - BotInfo *Bot() - { - return Global; - } - void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) { if (Me->GetLinks().empty()) @@ -52,57 +45,47 @@ class MyGlobalService : public GlobalService class GlobalCore : public Module { - MyGlobalService myglobal; + MyGlobalService myglobalservice; public: - GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), myglobal(this) + GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + myglobalservice(this) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnRestart, I_OnShutdown, I_OnNewServer }; - ModuleManager::Attach(i, this, 3); + BotInfo *Global = findbot(Config->Global); + if (Global == NULL) + throw ModuleException("No bot named " + Config->Global); - ModuleManager::RegisterService(&this->myglobal); - - Global = new BotInfo(Config->s_Global, Config->ServiceUser, Config->ServiceHost, Config->desc_Global); - Global->SetFlag(BI_CORE); + ModuleManager::RegisterService(&this->myglobalservice); - spacesepstream coreModules(Config->GlobalCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); - } - - ~GlobalCore() - { - spacesepstream coreModules(Config->GlobalCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } - - delete Global; + Implementation i[] = { I_OnRestart, I_OnShutdown, I_OnNewServer, I_OnPreHelp }; + ModuleManager::Attach(i, this, 3); } void OnRestart() { if (Config->GlobalOnCycle) - global->SendGlobal(global->Bot(), "", Config->GlobalOnCycleMessage); + global->SendGlobal(findbot(Config->Global), "", Config->GlobalOnCycleMessage); } void OnShutdown() { if (Config->GlobalOnCycle) - global->SendGlobal(global->Bot(), "", Config->GlobalOnCycleMessage); + global->SendGlobal(findbot(Config->Global), "", Config->GlobalOnCycleMessage); } void OnNewServer(Server *s) { if (Config->GlobalOnCycle && !Config->GlobalOnCycleUP.empty()) - notice_server(Config->s_Global, s, "%s", Config->GlobalOnCycleUP.c_str()); + notice_server(Config->Global, s, "%s", Config->GlobalOnCycleUP.c_str()); + } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->Global) + return; + source.Reply(_("%s commands:\n"), Config->Global.c_str()); } }; diff --git a/modules/core/global.h b/modules/core/global.h index 977a327e4..454e879c2 100644 --- a/modules/core/global.h +++ b/modules/core/global.h @@ -6,8 +6,6 @@ class GlobalService : public Service public: GlobalService(Module *m) : Service(m, "Global") { } - virtual BotInfo *Bot() = 0; - /** Send out a global message to all users * @param sender Our client which should send the global * @param source The sender of the global diff --git a/modules/core/help.cpp b/modules/core/help.cpp new file mode 100644 index 000000000..8362b48d9 --- /dev/null +++ b/modules/core/help.cpp @@ -0,0 +1,120 @@ +/* Core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandHelp : public Command +{ + public: + CommandHelp(Module *creator) : Command(creator, "generic/help", 0) + { + this->SetDesc(_("Displays this list and give information about commands")); + this->SetFlag(CFLAG_STRIP_CHANNEL); + this->SetFlag(CFLAG_ALLOW_UNREGISTERED); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + FOREACH_MOD(I_OnPreHelp, OnPreHelp(source, params)); + + User *u = source.u; + BotInfo *bi = source.owner; + + if (params.empty()) + { + for (command_map::iterator it = bi->commands.begin(), it_end = bi->commands.end(); it != it_end; ++it) + { + // Smaller command exists + Anope::string cmd = myStrGetToken(it->first, ' ', 0); + if (cmd != it->first && bi->commands.count(cmd)) + continue; + + service_reference<Command> c(it->second); + if (!c) + continue; + if (!Config->HidePrivilegedCommands || c->permission.empty() || u->HasCommand(c->permission)) + { + source.command = it->first; + c->OnServHelp(source); + } + } + } + else + { + bool helped = false; + for (unsigned max = params.size(); max > 0; --max) + { + Anope::string full_command; + for (unsigned i = 0; i < max; ++i) + full_command += " " + params[i]; + full_command.erase(full_command.begin()); + + std::map<Anope::string, Anope::string>::iterator it = bi->commands.find(full_command); + if (it == bi->commands.end()) + continue; + + service_reference<Command> c(it->second); + if (!c) + continue; + + if (Config->HidePrivilegedCommands && !c->permission.empty() && !u->HasCommand(c->permission)) + continue; + + const Anope::string &subcommand = params.size() > max ? params[max] : ""; + source.command = full_command; + if (!c->OnHelp(source, subcommand)) + continue; + + helped = true; + source.Reply(" "); + + /* Inform the user what permission is required to use the command */ + if (!c->permission.empty()) + source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), c->permission.c_str()); + if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) + source.Reply( _("You need to be identified to use this command.")); + /* User doesn't have the proper permission to use this command */ + else if (!c->permission.empty() && !u->HasCommand(c->permission)) + source.Reply(_("You cannot use this command.")); + /* User can use this command */ + else + source.Reply(_("You can use this command.")); + + break; + } + + if (helped == false) + source.Reply(_("No help available for \002%s\002."), params[0].c_str()); + } + + FOREACH_MOD(I_OnPostHelp, OnPostHelp(source, params)); + + return; + } +}; + +class Help : public Module +{ + CommandHelp commandhelp; + + public: + Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhelp(this) + { + this->SetAuthor("Anope"); + + ModuleManager::RegisterService(&commandhelp); + } +}; + +MODULE_INIT(Help) diff --git a/modules/core/hostserv.h b/modules/core/hostserv.h deleted file mode 100644 index 6f491a30e..000000000 --- a/modules/core/hostserv.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef HOSTSERV_H -#define HOSTSERV_H - -class HostServService : public Service -{ - public: - HostServService(Module *m) : Service(m, "HostServ") { } - - virtual BotInfo *Bot() = 0; - - virtual void Sync(NickAlias *na) = 0; -}; - -static service_reference<HostServService> hostserv("HostServ"); - -#endif // HOSTSERV_H - diff --git a/modules/core/hs_del.cpp b/modules/core/hs_del.cpp index ea27633b0..b4d101d44 100644 --- a/modules/core/hs_del.cpp +++ b/modules/core/hs_del.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSDel : public Command { public: - CommandHSDel() : Command("DEL", 1, 1, "hostserv/del") + CommandHSDel(Module *creator) : Command(creator, "hostserv/del", 1, 1, "hostserv/del") { this->SetDesc(_("Delete the vhost of another user")); + this->SetSyntax(_("\037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; @@ -32,41 +32,75 @@ class CommandHSDel : public Command Log(LOG_ADMIN, u, this) << "for user " << na->nick; FOREACH_MOD(I_OnDeleteVhost, OnDeleteVhost(na)); na->hostinfo.RemoveVhost(); - source.Reply(_("vhost for \002%s\002 removed."), nick.c_str()); + source.Reply(_("Vhost for \002%s\002 removed."), nick.c_str()); } else - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); - - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEL\002 \002<nick>\002\n" - "Deletes the vhost assigned to the given nick from the\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Deletes the vhost assigned to the given nick from the\n" "database.")); return true; } +}; - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) +class CommandHSDelAll : public Command +{ + public: + CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1, "hostserv/del") { - SyntaxError(source, "DEL", _("DEL \002<nick>\002.")); + this->SetDesc(_("Delete the vhost for all nicks in a group")); + this->SetSyntax(_("\037nick\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &nick = params[0]; + User *u = source.u; + NickAlias *na = findnick(nick); + if (na) + { + FOREACH_MOD(I_OnDeleteVhost, OnDeleteVhost(na)); + NickCore *nc = na->nc; + for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it) + { + na = *it; + na->hostinfo.RemoveVhost(); + } + Log(LOG_ADMIN, u, this) << "for all nicks in group " << nc->display; + source.Reply(_("vhosts for group \002%s\002 have been removed."), nc->display.c_str()); + } + else + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Deletes the vhost for all nicks in the same group as\n" + "that of the given nick.")); + return true; } }; class HSDel : public Module { CommandHSDel commandhsdel; + CommandHSDelAll commandhsdelall; public: - HSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhsdel(this), commandhsdelall(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsdel); + ModuleManager::RegisterService(&commandhsdel); + ModuleManager::RegisterService(&commandhsdelall); } }; diff --git a/modules/core/hs_delall.cpp b/modules/core/hs_delall.cpp deleted file mode 100644 index d55b3a161..000000000 --- a/modules/core/hs_delall.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "hostserv.h" - -class CommandHSDelAll : public Command -{ - public: - CommandHSDelAll() : Command("DELALL", 1, 1, "hostserv/del") - { - this->SetDesc(_("Delete the vhost for all nicks in a group")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &nick = params[0]; - User *u = source.u; - NickAlias *na = findnick(nick); - if (na) - { - FOREACH_MOD(I_OnDeleteVhost, OnDeleteVhost(na)); - NickCore *nc = na->nc; - for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it) - { - na = *it; - na->hostinfo.RemoveVhost(); - } - Log(LOG_ADMIN, u, this) << "for all nicks in group " << nc->display; - source.Reply(_("vhosts for group \002%s\002 have been removed."), nc->display.c_str()); - } - else - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002DELALL\002 \002<nick>\002.\n" - "Deletes the vhost for all nicks in the same group as\n" - "that of the given nick.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DELALL", _("DELALL <nick>\002.")); - } -}; - -class HSDelAll : public Module -{ - CommandHSDelAll commandhsdelall; - - public: - HSDelAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsdelall); - } -}; - -MODULE_INIT(HSDelAll) diff --git a/modules/core/hs_group.cpp b/modules/core/hs_group.cpp index 2a2f9545b..8d6fbd630 100644 --- a/modules/core/hs_group.cpp +++ b/modules/core/hs_group.cpp @@ -12,39 +12,51 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSGroup : public Command { + void Sync(NickAlias *na) + { + if (!na || !na->hostinfo.HasVhost()) + return; + + for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) + { + NickAlias *nick = *it; + nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); + } + } + public: - CommandHSGroup() : Command("GROUP", 0, 0) + CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0) { this->SetDesc(_("Syncs the vhost for all nicks in a group")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na = findnick(u->nick); if (na && u->Account() == na->nc && na->hostinfo.HasVhost()) { - hostserv->Sync(na); + this->Sync(na); if (!na->hostinfo.GetIdent().empty()) source.Reply(_("All vhost's in the group \002%s\002 have been set to \002%s\002@\002%s\002"), u->Account()->display.c_str(), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); else source.Reply(_("All vhost's in the group \002%s\002 have been set to \002%s\002"), u->Account()->display.c_str(), na->hostinfo.GetHost().c_str()); } else - source.Reply(_(HOST_NOT_ASSIGNED)); + source.Reply(HOST_NOT_ASSIGNED); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GROUP\002\n" - " \n" - "This command allows users to set the vhost of their\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command allows users to set the vhost of their\n" "CURRENT nick to be the vhost for all nicks in the same\n" "group.")); return true; @@ -56,14 +68,12 @@ class HSGroup : public Module CommandHSGroup commandhsgroup; public: - HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhsgroup(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsgroup); + ModuleManager::RegisterService(&commandhsgroup); } }; diff --git a/modules/core/hs_help.cpp b/modules/core/hs_help.cpp deleted file mode 100644 index 3cd221e10..000000000 --- a/modules/core/hs_help.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "hostserv.h" - -class CommandHSHelp : public Command -{ - public: - CommandHSHelp() : Command("HELP", 1, 1) - { - this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(hostserv->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("%s commands:"), Config->s_HostServ.c_str()); - for (CommandMap::const_iterator it = hostserv->Bot()->Commands.begin(), it_end = hostserv->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - } -}; - -class HSHelp : public Module -{ - CommandHSHelp commandhshelp; - - public: - HSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhshelp); - } -}; - -MODULE_INIT(HSHelp) diff --git a/modules/core/hs_list.cpp b/modules/core/hs_list.cpp index d6446f4c7..dbc852e5b 100644 --- a/modules/core/hs_list.cpp +++ b/modules/core/hs_list.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSList : public Command { public: - CommandHSList() : Command("LIST", 0, 1, "hostserv/list") + CommandHSList(Module *creator) : Command(creator, "hostserv/list", 0, 1, "hostserv/list") { this->SetDesc(_("Displays one or more vhost entries.")); + this->SetSyntax(_("\002[<key>|<#X-Y>]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &key = !params.empty() ? params[0] : ""; int from = 0, to = 0, counter = 1; @@ -37,15 +37,15 @@ class CommandHSList : public Command size_t tmp = key.find('-'); if (tmp == Anope::string::npos || tmp == key.length() || tmp == 1) { - source.Reply(_(LIST_INCORRECT_RANGE)); - return MOD_CONT; + source.Reply(LIST_INCORRECT_RANGE); + return; } for (unsigned i = 1, end = key.length(); i < end; ++i) { if (!isdigit(key[i]) && i != tmp) { - source.Reply(_(LIST_INCORRECT_RANGE)); - return MOD_CONT; + source.Reply(LIST_INCORRECT_RANGE); + return; } try { @@ -100,13 +100,14 @@ class CommandHSList : public Command else source.Reply(_("Displayed all records (Count: \002%d\002)"), display_counter); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002LIST\002 \002[<key>|<#X-Y>]\002\n" - "This command lists registered vhosts to the operator\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command lists registered vhosts to the operator\n" "if a Key is specified, only entries whos nick or vhost match\n" "the pattern given in <key> are displayed e.g. Rob* for all\n" "entries beginning with \"Rob\"\n" @@ -124,14 +125,12 @@ class HSList : public Module CommandHSList commandhslist; public: - HSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhslist(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhslist); + ModuleManager::RegisterService(&commandhslist); } }; diff --git a/modules/core/hs_main.cpp b/modules/core/hs_main.cpp index 309e235bf..c88f98a50 100644 --- a/modules/core/hs_main.cpp +++ b/modules/core/hs_main.cpp @@ -12,71 +12,23 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" - -static BotInfo *HostServ = NULL; - -class MyHostServService : public HostServService -{ - public: - MyHostServService(Module *m) : HostServService(m) { } - - BotInfo *Bot() - { - return HostServ; - } - - void Sync(NickAlias *na) - { - if (!na || !na->hostinfo.HasVhost()) - return; - - for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) - { - NickAlias *nick = *it; - nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); - } - } -}; class HostServCore : public Module { - MyHostServService myhostserv; - public: - HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), myhostserv(this) + HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) { this->SetAuthor("Anope"); if (!ircd || !ircd->vhost) throw ModuleException("Your IRCd does not suppor vhosts"); + + BotInfo *HostServ = findbot(Config->HostServ); + if (HostServ == NULL) + throw ModuleException("No bot named " + Config->HostServ); - ModuleManager::RegisterService(&this->myhostserv); - - HostServ = new BotInfo(Config->s_HostServ, Config->ServiceUser, Config->ServiceHost, Config->desc_HostServ); - HostServ->SetFlag(BI_CORE); - - Implementation i[] = { I_OnNickIdentify, I_OnNickUpdate }; - ModuleManager::Attach(i, this, 2); - - spacesepstream coreModules(Config->HostCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); - } - - ~HostServCore() - { - spacesepstream coreModules(Config->HostCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } - - delete HostServ; + Implementation i[] = { I_OnNickIdentify, I_OnNickUpdate, I_OnPreHelp }; + ModuleManager::Attach(i, this, 3); } void OnNickIdentify(User *u) @@ -105,10 +57,14 @@ class HostServCore : public Module if (ircd->vident && !na->hostinfo.GetIdent().empty()) u->SetVIdent(na->hostinfo.GetIdent()); - if (!na->hostinfo.GetIdent().empty()) - u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); - else - u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->hostinfo.GetHost().c_str()); + BotInfo *bi = findbot(Config->HostServ); + if (bi) + { + if (!na->hostinfo.GetIdent().empty()) + u->SendMessage(bi, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); + else + u->SendMessage(bi, _("Your vhost of \002%s\002 is now activated."), na->hostinfo.GetHost().c_str()); + } } } @@ -116,6 +72,13 @@ class HostServCore : public Module { this->OnNickIdentify(u); } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->HostServ) + return; + source.Reply(_("%s commands:\n"), Config->HostServ.c_str()); + } }; MODULE_INIT(HostServCore) diff --git a/modules/core/hs_off.cpp b/modules/core/hs_off.cpp index 85e96f62f..a3f11c2bd 100644 --- a/modules/core/hs_off.cpp +++ b/modules/core/hs_off.cpp @@ -12,23 +12,23 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSOff : public Command { public: - CommandHSOff() : Command("OFF", 0, 0) + CommandHSOff(Module *creator) : Command(creator, "hostserv/off", 0, 0) { this->SetDesc(_("Deactivates your assigned vhost")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na = findnick(u->nick); if (!na || !na->hostinfo.HasVhost()) - source.Reply(_(HOST_NOT_ASSIGNED)); + source.Reply(HOST_NOT_ASSIGNED); else { ircdproto->SendVhostDel(u); @@ -36,13 +36,14 @@ class CommandHSOff : public Command source.Reply(_("Your vhost was removed and the normal cloaking restored.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OFF\002\n" - "Deactivates the vhost currently assigned to the nick in use.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Deactivates the vhost currently assigned to the nick in use.\n" "When you use this command any user who performs a /whois\n" "on you will see your real IP address.")); return true; @@ -54,14 +55,12 @@ class HSOff : public Module CommandHSOff commandhsoff; public: - HSOff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSOff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhsoff(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsoff); + ModuleManager::RegisterService(&commandhsoff); } }; diff --git a/modules/core/hs_on.cpp b/modules/core/hs_on.cpp index 09735ba83..0ba124ba1 100644 --- a/modules/core/hs_on.cpp +++ b/modules/core/hs_on.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSOn : public Command { public: - CommandHSOn() : Command("ON", 0, 0) + CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 0) { this->SetDesc(_("Activates your assigned vhost")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na = findnick(u->nick); @@ -44,15 +44,16 @@ class CommandHSOn : public Command u->UpdateHost(); } else - source.Reply(_(HOST_NOT_ASSIGNED)); + source.Reply(HOST_NOT_ASSIGNED); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ON\002\n" - "Activates the vhost currently assigned to the nick in use.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Activates the vhost currently assigned to the nick in use.\n" "When you use this command any user who performs a /whois\n" "on you will see the vhost instead of your real IP address.")); return true; @@ -64,14 +65,12 @@ class HSOn : public Module CommandHSOn commandhson; public: - HSOn(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSOn(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandhson(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhson); + ModuleManager::RegisterService(&commandhson); } }; diff --git a/modules/core/hs_set.cpp b/modules/core/hs_set.cpp index 6e9949b3c..2b427983d 100644 --- a/modules/core/hs_set.cpp +++ b/modules/core/hs_set.cpp @@ -12,27 +12,27 @@ /*************************************************************************/ #include "module.h" -#include "hostserv.h" class CommandHSSet : public Command { public: - CommandHSSet() : Command("SET", 2, 2, "hostserv/set") + CommandHSSet(Module *creator) : Command(creator, "hostserv/set", 2, 2, "hostserv/set") { this->SetDesc(_("Set the vhost of another user")); + this->SetSyntax(_("\037nick\037 \037hostmask\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - Anope::string nick = params[0]; + const Anope::string &nick = params[0]; NickAlias *na = findnick(nick); if (na == NULL) { source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return MOD_CONT; + return; } Anope::string rawhostmask = params[1]; @@ -51,7 +51,7 @@ class CommandHSSet : public Command if (host.empty()) { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } if (!user.empty()) @@ -59,31 +59,31 @@ class CommandHSSet : public Command if (user.length() > Config->UserLen) { source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); - return MOD_CONT; + return; } else if (!ircd->vident) { source.Reply(HOST_NO_VIDENT); - return MOD_CONT; + return; } for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s) if (!isvalidchar(*s)) { source.Reply(HOST_SET_IDENT_ERROR); - return MOD_CONT; + return; } } if (host.length() > Config->HostLen) { - source.Reply(_(HOST_SET_TOOLONG), Config->HostLen); - return MOD_CONT; + source.Reply(HOST_SET_TOOLONG, Config->HostLen); + return; } if (!isValidHost(host, 3)) { - source.Reply(_(HOST_SET_ERROR)); - return MOD_CONT; + source.Reply(HOST_SET_ERROR); + return; } Log(LOG_ADMIN, u, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host; @@ -91,42 +91,145 @@ class CommandHSSet : public Command na->hostinfo.SetVhost(user, host, u->nick); FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); if (!user.empty()) - source.Reply(_("vhost for \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); + source.Reply(_("VHost for \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); else - source.Reply(_("vhost for \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); - - return MOD_CONT; + source.Reply(_("VHost for \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SET\002 \002<nick>\002 \002<hostmask>\002.\n" - "Sets the vhost for the given nick to that of the given\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets the vhost for the given nick to that of the given\n" "hostmask. If your IRCD supports vIdents, then using\n" "SET <nick> <ident>@<hostmask> set idents for users as \n" "well as vhosts.")); return true; } +}; + +class CommandHSSetAll : public Command +{ + void Sync(NickAlias *na) + { + if (!na || !na->hostinfo.HasVhost()) + return; + + for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) + { + NickAlias *nick = *it; + nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); + } + } + + public: + CommandHSSetAll(Module *creator) : Command(creator, "hostserv/setall", 2, 2, "hostserv/set") + { + this->SetDesc(_("Set the vhost for all nicks in a group")); + this->SetSyntax(_("\037nick\037 \037hostmask>\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + + Anope::string nick = params[0]; + + NickAlias *na = findnick(nick); + if (na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + return; + } + + Anope::string rawhostmask = params[1]; + + Anope::string user, host; + size_t a = rawhostmask.find('@'); + + if (a == Anope::string::npos) + host = rawhostmask; + else + { + user = rawhostmask.substr(0, a); + host = rawhostmask.substr(a + 1); + } + + if (host.empty()) + { + this->OnSyntaxError(source, ""); + return; + } + + if (!user.empty()) + { + if (user.length() > Config->UserLen) + { + source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); + return; + } + else if (!ircd->vident) + { + source.Reply(HOST_NO_VIDENT); + return; + } + for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s) + if (!isvalidchar(*s)) + { + source.Reply(HOST_SET_IDENT_ERROR); + return; + } + } + + if (host.length() > Config->HostLen) + { + source.Reply(HOST_SET_TOOLONG, Config->HostLen); + return; + } + + if (!isValidHost(host, 3)) + { + source.Reply(HOST_SET_ERROR); + return; + } + + Log(LOG_ADMIN, u, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host; + + na->hostinfo.SetVhost(user, host, u->nick); + this->Sync(na); + FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); + if (!user.empty()) + source.Reply(_("VHost for group \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); + else + source.Reply(_("VHost for group \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); + } - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - SyntaxError(source, "SET", _("SET \002<nick>\002 \002<hostmask>\002.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets the vhost for all nicks in the same group as that\n" + "of the given nick. If your IRCD supports vIdents, then\n" + "using SETALL <nick> <ident>@<hostmask> will set idents\n" + "for users as well as vhosts.\n" + "* NOTE, this will not update the vhost for any nicks\n" + "added to the group after this command was used.")); + return true; } }; class HSSet : public Module { CommandHSSet commandhsset; + CommandHSSetAll commandhssetall; public: - HSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + HSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), commandhsset(this), commandhssetall(this) { this->SetAuthor("Anope"); - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsset); + ModuleManager::RegisterService(&commandhsset); + ModuleManager::RegisterService(&commandhssetall); } }; diff --git a/modules/core/hs_setall.cpp b/modules/core/hs_setall.cpp deleted file mode 100644 index 0e6f5fdd1..000000000 --- a/modules/core/hs_setall.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "hostserv.h" - -class CommandHSSetAll : public Command -{ - public: - CommandHSSetAll() : Command("SETALL", 2, 2, "hostserv/set") - { - this->SetDesc(_("Set the vhost for all nicks in a group")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - Anope::string nick = params[0]; - - NickAlias *na = findnick(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return MOD_CONT; - } - - Anope::string rawhost = params[1]; - - Anope::string user, host; - size_t a = rawhost.find('@'); - - if (a == Anope::string::npos) - host = rawhost; - else - { - user = rawhost.substr(0, a); - host = rawhost.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return MOD_CONT; - } - - if (!user.empty()) - { - if (user.length() > Config->UserLen) - { - source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); - return MOD_CONT; - } - else if (!ircd->vident) - { - source.Reply(HOST_NO_VIDENT); - return MOD_CONT; - } - for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s) - if (!isvalidchar(*s)) - { - source.Reply(HOST_SET_IDENT_ERROR); - return MOD_CONT; - } - } - - if (host.length() > Config->HostLen) - { - source.Reply(_(HOST_SET_TOOLONG), Config->HostLen); - return MOD_CONT; - } - - if (!isValidHost(host, 3)) - { - source.Reply(_(HOST_SET_ERROR)); - return MOD_CONT; - } - - Log(LOG_ADMIN, u, this) << "to set the vhost for all nicks in group " << na->nc->display << " to " << (!user.empty() ? user + "@" : "") << host; - - na->hostinfo.SetVhost(user, host, u->nick); - hostserv->Sync(na); - FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); - if (!user.empty()) - source.Reply(_("vhost for group \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); - else - source.Reply(_("vhost for group \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002SETALL\002 \002<nick>\002 \002<hostmask>\002.\n" - "Sets the vhost for all nicks in the same group as that\n" - "of the given nick. If your IRCD supports vIdents, then\n" - "using SETALL <nick> <ident>@<hostmask> will set idents\n" - "for users as well as vhosts.\n" - "* NOTE, this will not update the vhost for any nicks\n" - "added to the group after this command was used.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SETALL", _("SETALL \002<nick>\002 \002<hostmask>\002.")); - } -}; - -class HSSetAll : public Module -{ - CommandHSSetAll commandhssetall; - - public: - HSSetAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhssetall); - } -}; - -MODULE_INIT(HSSetAll) diff --git a/modules/core/memoserv.h b/modules/core/memoserv.h index f6ea4772b..0bf0c79ca 100644 --- a/modules/core/memoserv.h +++ b/modules/core/memoserv.h @@ -14,8 +14,6 @@ class MemoServService : public Service MemoServService(Module *m) : Service(m, "MemoServ") { } - virtual BotInfo *Bot() = 0; - /** Retrieve the memo info for a nick or channel * @param target Target * @param ischan Set to true if target is a channel diff --git a/modules/core/ms_cancel.cpp b/modules/core/ms_cancel.cpp index 178f62d2f..e5beffa10 100644 --- a/modules/core/ms_cancel.cpp +++ b/modules/core/ms_cancel.cpp @@ -17,12 +17,13 @@ class CommandMSCancel : public Command { public: - CommandMSCancel() : Command("CANCEL", 1, 1) + CommandMSCancel(Module *creator) : Command(creator, "memoserv/cancel", 1, 1) { - this->SetDesc(_("Cancel last memo you sent")); + this->SetDesc(_("Cancel the last memo you sent")); + this->SetSyntax(_("{\037nick\037 | \037channel\037}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -32,7 +33,7 @@ class CommandMSCancel : public Command MemoInfo *mi = memoserv->GetMemoInfo(nname, ischan); if (mi == NULL) - source.Reply(ischan ? _(CHAN_X_NOT_REGISTERED) : _(NICK_X_NOT_REGISTERED), nname.c_str()); + source.Reply(ischan ? CHAN_X_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), nname.c_str()); else { for (int i = mi->memos.size() - 1; i >= 0; --i) @@ -41,27 +42,22 @@ class CommandMSCancel : public Command FOREACH_MOD(I_OnMemoDel, OnMemoDel(findnick(nname)->nc, mi, mi->memos[i])); mi->Del(mi->memos[i]); source.Reply(_("Last memo to \002%s\002 has been cancelled."), nname.c_str()); - return MOD_CONT; + return; } source.Reply(_("No memo was cancelable.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CANCEL {\037nick\037 | \037channel\037}\002\n" - " \n" - "Cancels the last memo you sent to the given nick or channel,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Cancels the last memo you sent to the given nick or channel,\n" "provided it has not been read at the time you use the command.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CANCEL", _("CANCEL {\037nick\037 | \037channel\037}")); - } }; class MSCancel : public Module @@ -69,14 +65,12 @@ class MSCancel : public Module CommandMSCancel commandmscancel; public: - MSCancel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSCancel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmscancel(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmscancel); + ModuleManager::RegisterService(&commandmscancel); } }; diff --git a/modules/core/ms_check.cpp b/modules/core/ms_check.cpp index 49b7f8c07..3019e270f 100644 --- a/modules/core/ms_check.cpp +++ b/modules/core/ms_check.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "memoserv.h" class CommandMSCheck : public Command { public: - CommandMSCheck() : Command("CHECK", 1, 1) + CommandMSCheck(Module *creator) : Command(creator, "memoserv/check", 1, 1) { this->SetDesc(_("Checks if last memo to a nick was read")); + this->SetSyntax(_("\037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -33,8 +33,8 @@ class CommandMSCheck : public Command NickAlias *na = findnick(recipient); if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), recipient.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, recipient.c_str()); + return; } MemoInfo *mi = &na->nc->memos; @@ -59,22 +59,17 @@ class CommandMSCheck : public Command if (!found) source.Reply(_("Nick %s doesn't have a memo from you."), na->nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CHECK \037nick\037\002\n" - " \n" - "Checks whether the _last_ memo you sent to \037nick\037 has been read\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Checks whether the _last_ memo you sent to \037nick\037 has been read\n" "or not. Note that this does only work with nicks, not with chans.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CHECK", _("CHECK \037nickname\037")); - } }; class MSCheck : public Module @@ -82,14 +77,12 @@ class MSCheck : public Module CommandMSCheck commandmscheck; public: - MSCheck(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSCheck(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmscheck(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmscheck); + ModuleManager::RegisterService(&commandmscheck); } }; diff --git a/modules/core/ms_del.cpp b/modules/core/ms_del.cpp index 630572521..c1d1e09c6 100644 --- a/modules/core/ms_del.cpp +++ b/modules/core/ms_del.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "memoserv.h" class MemoDelCallback : public NumberList { @@ -42,12 +41,13 @@ class MemoDelCallback : public NumberList class CommandMSDel : public Command { public: - CommandMSDel() : Command("DEL", 0, 2) + CommandMSDel(Module *creator) : Command(creator, "memoserv/del", 0, 2) { this->SetDesc(_("Delete a memo or memos")); + this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | ALL}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -62,18 +62,18 @@ class CommandMSDel : public Command if (!(ci = cs_findchan(chan))) { - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); + return; } else if (readonly) { - source.Reply(_(READ_ONLY_MODE)); - return MOD_CONT; + source.Reply(READ_ONLY_MODE); + return; } else if (!check_access(u, ci, CA_MEMO)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } mi = &ci->memos; } @@ -84,9 +84,9 @@ class CommandMSDel : public Command else if (mi->memos.empty()) { if (!chan.empty()) - source.Reply(_(MEMO_X_HAS_NO_MEMOS), chan.c_str()); + source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); else - source.Reply(_(MEMO_HAVE_NO_MEMOS)); + source.Reply(MEMO_HAVE_NO_MEMOS); } else { @@ -121,14 +121,14 @@ class CommandMSDel : public Command source.Reply(_("All of your memos have been deleted.")); } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEL [\037channel\037] {\037num\037 | \037list\037 | LAST | ALL}\002\n" - " \n" - "Deletes the specified memo or memos. You can supply\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Deletes the specified memo or memos. You can supply\n" "multiple memo numbers or ranges of numbers instead of a\n" "single number, as in the second example below.\n" " \n" @@ -144,11 +144,6 @@ class CommandMSDel : public Command " Deletes memos numbered 2 through 5 and 7 through 9.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEL", _("DEL [\037channel\037] {\037num\037 | \037list\037 | ALL}")); - } }; class MSDel : public Module @@ -156,14 +151,12 @@ class MSDel : public Module CommandMSDel commandmsdel; public: - MSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsdel(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsdel); + ModuleManager::RegisterService(&commandmsdel); } }; diff --git a/modules/core/ms_help.cpp b/modules/core/ms_help.cpp deleted file mode 100644 index 598e8ffa1..000000000 --- a/modules/core/ms_help.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "memoserv.h" - -class CommandMSHelp : public Command -{ - public: - CommandMSHelp() : Command("HELP", 1, 1) - { - this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(memoserv->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" - "messages to other IRC users, whether they are online at\n" - "the time or not, or to channels(*). Both the sender's\n" - "nickname and the target nickname or channel must be\n" - "registered in order to send a memo.\n" - "%s's commands include:"), Config->s_MemoServ.c_str(), Config->s_MemoServ.c_str()); - for (CommandMap::const_iterator it = memoserv->Bot()->Commands.begin(), it_end = memoserv->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - source.Reply(_("Type \002%s%s HELP \037command\037\002 for help on any of the\n" - "above commands.\n" - "(*) By default, any user with at least level 10 access on a\n" - " channel can read that channel's memos. This can be\n" - " changed with the %s \002LEVELS\002 command."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), Config->s_ChanServ.c_str()); - } -}; - -class MSHelp : public Module -{ - CommandMSHelp commandmshelp; - - public: - MSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmshelp); - } -}; - -MODULE_INIT(MSHelp) diff --git a/modules/core/ms_ignore.cpp b/modules/core/ms_ignore.cpp index 11290952f..250b1c171 100644 --- a/modules/core/ms_ignore.cpp +++ b/modules/core/ms_ignore.cpp @@ -17,12 +17,13 @@ class CommandMSIgnore : public Command { public: - CommandMSIgnore() : Command("IGNORE", 1, 3) + CommandMSIgnore(Module *creator) : Command(creator, "memoserv/ignore", 1, 3) { this->SetDesc(_("Manage your memo ignore list")); + this->SetSyntax(_("[\037channel\037] {\002ADD|DEL|LIST\002} [\037entry\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -40,9 +41,9 @@ class CommandMSIgnore : public Command bool ischan; MemoInfo *mi = memoserv->GetMemoInfo(channel, ischan); if (!mi) - source.Reply(ischan ? _(CHAN_X_NOT_REGISTERED) : _(NICK_X_NOT_REGISTERED), channel.c_str()); + source.Reply(ischan ? CHAN_X_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), channel.c_str()); else if (ischan && !check_access(u, cs_findchan(channel), CA_MEMO)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (command.equals_ci("ADD") && !param.empty()) { if (std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()) == mi->ignores.end()) @@ -79,22 +80,17 @@ class CommandMSIgnore : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002IGNORE [\037channel\037] {\002ADD|DEL|LIST\002} [\037entry\037]\n" - " \n" - "Allows you to ignore users by nick or host from memoing you. If someone on your\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to ignore users by nick or host from memoing you. If someone on your\n" "memo ignore list tries to memo you, they will not be told that you have them ignored.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "IGNORE", _("IGNORE [\037channel\037] {\002ADD|DEL|LIST\002} [\037entry\037]")); - } }; class MSIgnore : public Module @@ -102,14 +98,12 @@ class MSIgnore : public Module CommandMSIgnore commandmsignore; public: - MSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsignore(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsignore); + ModuleManager::RegisterService(&commandmsignore); } }; diff --git a/modules/core/ms_info.cpp b/modules/core/ms_info.cpp index 37ff64450..ae532fb9f 100644 --- a/modules/core/ms_info.cpp +++ b/modules/core/ms_info.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "memoserv.h" class CommandMSInfo : public Command { public: - CommandMSInfo() : Command("INFO", 0, 1) + CommandMSInfo(Module *creator) : Command(creator, "memoserv/info", 0, 1) { this->SetDesc(_("Displays information about your memos")); + this->SetSyntax(_("[\037nick\037 | \037channel\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -37,8 +37,8 @@ class CommandMSInfo : public Command na = findnick(nname); if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), nname.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, nname.c_str()); + return; } mi = &na->nc->memos; hardmax = na->nc->HasFlag(NI_MEMO_HARDMAX) ? 1 : 0; @@ -47,21 +47,21 @@ class CommandMSInfo : public Command { if (!(ci = cs_findchan(nname))) { - source.Reply(_(CHAN_X_NOT_REGISTERED), nname.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, nname.c_str()); + return; } else if (!check_access(u, ci, CA_MEMO)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } mi = &ci->memos; hardmax = ci->HasFlag(CI_MEMO_HARDMAX) ? 1 : 0; } else if (!nname.empty()) /* It's not a chan and we aren't services admin */ { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } else { @@ -180,31 +180,23 @@ class CommandMSInfo : public Command else source.Reply(_("You will not be notified of new memos.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - User *u = source.u; - if (u->IsServicesOper()) - source.Reply(_("Syntax: \002INFO [\037nick\037 | \037channel\037]\002\n" - "Without a parameter, displays information on the number of\n" - "memos you have, how many of them are unread, and how many\n" - "total memos you can receive.\n" - " \n" - "With a channel parameter, displays the same information for\n" - "the given channel.\n" - " \n" - "With a nickname parameter, displays the same information\n" - "for the given nickname. This use limited to \002Services\n" - "admins\002.")); - else - source.Reply(_("Syntax: \002INFO [\037channel\037]\002\n" - " \n" - "Displays information on the number of memos you have, how\n" - "many of them are unread, and how many total memos you can\n" - "receive. With a parameter, displays the same information\n" - "for the given channel.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Without a parameter, displays information on the number of\n" + "memos you have, how many of them are unread, and how many\n" + "total memos you can receive.\n" + " \n" + "With a channel parameter, displays the same information for\n" + "the given channel.\n" + " \n" + "With a nickname parameter, displays the same information\n" + "for the given nickname. This use limited to \002Services\n" + "Operators\002.")); return true; } @@ -215,14 +207,12 @@ class MSInfo : public Module CommandMSInfo commandmsinfo; public: - MSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsinfo(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsinfo); + ModuleManager::RegisterService(&commandmsinfo); } }; diff --git a/modules/core/ms_list.cpp b/modules/core/ms_list.cpp index 176cd931c..0e86de54d 100644 --- a/modules/core/ms_list.cpp +++ b/modules/core/ms_list.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "memoserv.h" class MemoListCallback : public NumberList { @@ -33,11 +32,7 @@ class MemoListCallback : public NumberList if (!SentHeader) { SentHeader = true; - if (ci) - source.Reply(_("Memos for %s. To read, type: \002%s%s READ %s \037num\037\002"), ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), ci->name.c_str()); - else - source.Reply(_("Memos for %s. To read, type: \002%s%s READ \037num\037\002"), source.u->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - + source.Reply(_("Memos for %s:"), ci ? ci->name.c_str() : source.u->nick.c_str()); source.Reply(_(" Num Sender Date/Time")); } @@ -54,12 +49,13 @@ class MemoListCallback : public NumberList class CommandMSList : public Command { public: - CommandMSList() : Command("LIST", 0, 2) + CommandMSList(Module *creator) : Command(creator, "memoserv/list", 0, 2) { this->SetDesc(_("List your memos")); + this->SetSyntax(_("[\037channel\037] [\037list\037 | NEW]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -75,13 +71,13 @@ class CommandMSList : public Command if (!(ci = cs_findchan(chan))) { - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); + return; } else if (!check_access(u, ci, CA_MEMO)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } mi = &ci->memos; } @@ -92,9 +88,9 @@ class CommandMSList : public Command else if (!mi->memos.size()) { if (!chan.empty()) - source.Reply(_(MEMO_X_HAS_NO_MEMOS), chan.c_str()); + source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); else - source.Reply(_(MEMO_HAVE_NO_MEMOS)); + source.Reply(MEMO_HAVE_NO_MEMOS); } else { @@ -113,10 +109,10 @@ class CommandMSList : public Command if (i == end) { if (!chan.empty()) - source.Reply(_(MEMO_X_HAS_NO_NEW_MEMOS), chan.c_str()); + source.Reply(MEMO_X_HAS_NO_NEW_MEMOS, chan.c_str()); else - source.Reply(_(MEMO_HAVE_NO_NEW_MEMOS)); - return MOD_CONT; + source.Reply(MEMO_HAVE_NO_NEW_MEMOS); + return; } } @@ -130,10 +126,7 @@ class CommandMSList : public Command if (!SentHeader) { SentHeader = true; - if (ci) - source.Reply(!param.empty() ? _("New memos for %s. To read, type: \002%s%s READ %s \037num\037\002") : _("Memos for %s. To read, type: \002%sR%s READ %s \037num\037\002"), ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), ci->name.c_str()); - else - source.Reply(!param.empty() ? _("New memos for %s. To read, type: \002%s%s READ \037num\037\002") : _("Memos for %s. To read, type: \002%s%s READ \037num\037\002"), u->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); + source.Reply(_("New memo for %s."), ci ? ci->name.c_str() : u->nick.c_str()); source.Reply(_(" Num Sender Date/Time")); } @@ -141,14 +134,14 @@ class CommandMSList : public Command } } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002LIST [\037channel\037] [\037list\037 | NEW]\002\n" - " \n" - "Lists any memos you currently have. With \002NEW\002, lists only\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists any memos you currently have. With \002NEW\002, lists only\n" "new (unread) memos. Unread memos are marked with a \"*\"\n" "to the left of the memo number. You can also specify a list\n" "of numbers, as in the example below:\n" @@ -156,11 +149,6 @@ class CommandMSList : public Command " Lists memos numbered 2 through 5 and 7 through 9.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LIST", _("LIST [\037channel\037] [\037list\037 | NEW]")); - } }; class MSList : public Module @@ -168,14 +156,12 @@ class MSList : public Module CommandMSList commandmslist; public: - MSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmslist(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmslist); + ModuleManager::RegisterService(&commandmslist); } }; diff --git a/modules/core/ms_main.cpp b/modules/core/ms_main.cpp index 487059413..cb3a21b59 100644 --- a/modules/core/ms_main.cpp +++ b/modules/core/ms_main.cpp @@ -14,7 +14,8 @@ #include "module.h" #include "memoserv.h" -static BotInfo *MemoServ = NULL; +static BotInfo *MemoServ; + static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) { Anope::string message = Anope::printf(translate(nc, _( @@ -34,11 +35,6 @@ class MyMemoServService : public MemoServService public: MyMemoServService(Module *m) : MemoServService(m) { } - BotInfo *Bot() - { - return MemoServ; - } - MemoInfo *GetMemoInfo(const Anope::string &target, bool &ischan) { if (!target.empty() && target[0] == '#') @@ -105,7 +101,7 @@ class MyMemoServService : public MemoServService if (check_access(cu->user, ci, CA_MEMO)) { if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE)) - cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), ci->name.c_str(), mi->memos.size()); + cu->user->SendMessage(MemoServ, MEMO_NEW_X_MEMO_ARRIVED, ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), ci->name.c_str(), mi->memos.size()); } } } @@ -121,7 +117,7 @@ class MyMemoServService : public MemoServService NickAlias *na = *it; User *user = finduser(na->nick); if (user && user->IsIdentified()) - user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); + user->SendMessage(MemoServ, MEMO_NEW_MEMO_ARRIVED, source.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), mi->memos.size()); } } @@ -146,22 +142,7 @@ class MyMemoServService : public MemoServService ++newcnt; } if (newcnt > 0) - { u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); - if (newcnt == 1 && (nc->memos.memos[i - 1]->HasFlag(MF_UNREAD))) - u->SendMessage(MemoServ, _("Type \002%s%s READ LAST\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - else if (newcnt == 1) - { - for (i = 0; i < end; ++i) - { - if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) - break; - } - u->SendMessage(MemoServ, _("Type \002%s%s READ %d\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), i); - } - else - u->SendMessage(MemoServ, _("Type \002%s%s LIST NEW\002 to list them."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - } if (nc->memos.memomax > 0 && nc->memos.memos.size() >= nc->memos.memomax) { if (nc->memos.memos.size() > nc->memos.memomax) @@ -175,38 +156,20 @@ class MyMemoServService : public MemoServService class MemoServCore : public Module { MyMemoServService mymemoserv; - public: - MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), mymemoserv(this) + MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + mymemoserv(this) { this->SetAuthor("Anope"); - Implementation i[] = { I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate }; - ModuleManager::Attach(i, this, 4); + MemoServ = findbot(Config->MemoServ); + if (MemoServ == NULL) + throw ModuleException("No bot named " + Config->MemoServ); - ModuleManager::RegisterService(&this->mymemoserv); - - MemoServ = new BotInfo(Config->s_MemoServ, Config->ServiceUser, Config->ServiceHost, Config->desc_MemoServ); - MemoServ->SetFlag(BI_CORE); - - spacesepstream coreModules(Config->MemoCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); - } + Implementation i[] = { I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate, I_OnPreHelp, I_OnPostHelp }; + ModuleManager::Attach(i, this, 6); - ~MemoServCore() - { - spacesepstream coreModules(Config->MemoCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } - - delete MemoServ; + ModuleManager::RegisterService(&this->mymemoserv); } void OnNickIdentify(User *u) @@ -235,6 +198,30 @@ class MemoServCore : public Module { this->mymemoserv.Check(u); } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->MemoServ) + return; + source.Reply(_("\002%s\002 is a utility allowing IRC users to send short\n" + "messages to other IRC users, whether they are online at\n" + "the time or not, or to channels(*). Both the sender's\n" + "nickname and the target nickname or channel must be\n" + "registered in order to send a memo.\n" + "%s's commands include:"), Config->MemoServ.c_str(), Config->MemoServ.c_str()); + } + + void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->MemoServ) + return; + source.Reply(_(" \n" + "Type \002%s%s HELP \037command\037\002 for help on any of the\n" + "above commands.\n" + "(*) By default, any user with at least level 10 access on a\n" + " channel can read that channel's memos. This can be\n" + " changed with the %s \002LEVELS\002 command."), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), Config->ChanServ.c_str()); + } }; MODULE_INIT(MemoServCore) diff --git a/modules/core/ms_read.cpp b/modules/core/ms_read.cpp index a868b5c88..dba38f5b8 100644 --- a/modules/core/ms_read.cpp +++ b/modules/core/ms_read.cpp @@ -69,9 +69,9 @@ class MemoListCallback : public NumberList { Memo *m = mi->memos[index]; if (ci) - source.Reply(_("Memo %d from %s (%s). To delete, type: \002%s%s DEL %s %d\002"), index + 1, m->sender.c_str(), do_strftime(m->time).c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), ci->name.c_str(), index + 1); + source.Reply(_("Memo %d from %s (%s). To delete, type: \002%s%s DEL %s %d\002"), index + 1, m->sender.c_str(), do_strftime(m->time).c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), ci->name.c_str(), index + 1); else - source.Reply(_("Memo %d from %s (%s). To delete, type: \002%s%s DEL %d\002"), index + 1, m->sender.c_str(), do_strftime(m->time).c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), index + 1); + source.Reply(_("Memo %d from %s (%s). To delete, type: \002%s%s DEL %d\002"), index + 1, m->sender.c_str(), do_strftime(m->time).c_str(), Config->UseStrictPrivMsgString.c_str(), Config->MemoServ.c_str(), index + 1); source.Reply("%s", m->text.c_str()); m->UnsetFlag(MF_UNREAD); @@ -84,12 +84,13 @@ class MemoListCallback : public NumberList class CommandMSRead : public Command { public: - CommandMSRead() : Command("READ", 1, 2) + CommandMSRead(Module *creator) : Command(creator, "memoserv/read", 1, 2) { this->SetDesc(_("Read a memo or memos")); + this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | NEW}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -104,13 +105,13 @@ class CommandMSRead : public Command if (!(ci = cs_findchan(chan))) { - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); + return; } else if (!check_access(u, ci, CA_MEMO)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } mi = &ci->memos; } @@ -122,9 +123,9 @@ class CommandMSRead : public Command else if (mi->memos.empty()) { if (!chan.empty()) - source.Reply(_(MEMO_X_HAS_NO_MEMOS), chan.c_str()); + source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); else - source.Reply(_(MEMO_HAVE_NO_MEMOS)); + source.Reply(MEMO_HAVE_NO_MEMOS); } else { @@ -142,9 +143,9 @@ class CommandMSRead : public Command if (!readcount) { if (!chan.empty()) - source.Reply(_(MEMO_X_HAS_NO_NEW_MEMOS), chan.c_str()); + source.Reply(MEMO_X_HAS_NO_NEW_MEMOS, chan.c_str()); else - source.Reply(_(MEMO_HAVE_NO_NEW_MEMOS)); + source.Reply(MEMO_HAVE_NO_NEW_MEMOS); } } else if (numstr.equals_ci("LAST")) @@ -158,14 +159,14 @@ class CommandMSRead : public Command list.Process(); } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002READ [\037channel\037] {\037num\037 | \037list\037 | LAST | NEW}\002\n" - " \n" - "Sends you the text of the memos specified. If LAST is\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends you the text of the memos specified. If LAST is\n" "given, sends you the memo you most recently received. If\n" "NEW is given, sends you all of your new memos. Otherwise,\n" "sends you memo number \037num\037. You can also give a list of\n" @@ -175,11 +176,6 @@ class CommandMSRead : public Command " Displays memos numbered 2 through 5 and 7 through 9.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "READ", _("READ [\037channel\037] {\037list\037 | LAST | NEW}")); - } }; class MSRead : public Module @@ -187,14 +183,12 @@ class MSRead : public Module CommandMSRead commandmsread; public: - MSRead(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSRead(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsread(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsread); + ModuleManager::RegisterService(&commandmsread); } }; diff --git a/modules/core/ms_rsend.cpp b/modules/core/ms_rsend.cpp index 0cc3b2b79..37c633e02 100644 --- a/modules/core/ms_rsend.cpp +++ b/modules/core/ms_rsend.cpp @@ -17,12 +17,13 @@ class CommandMSRSend : public Command { public: - CommandMSRSend() : Command("RSEND", 2, 2) + CommandMSRSend(Module *creator) : Command(creator, "memoserv/rsend", 2, 2) { this->SetDesc(_("Sends a memo and requests a read receipt")); + this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -34,11 +35,11 @@ class CommandMSRSend : public Command if ((na = findnick(nick)) && na->nc == u->Account()) { source.Reply(_("You can not request a receipt when sending a memo to yourself.")); - return MOD_CONT; + return; } if (Config->MSMemoReceipt == 1 && !u->IsServicesOper()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (Config->MSMemoReceipt > 2 || Config->MSMemoReceipt == 0) { Log() << "MSMemoReceipt is set misconfigured to " << Config->MSMemoReceipt; @@ -67,14 +68,14 @@ class CommandMSRSend : public Command } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002RSEND {\037nick\037 | \037channel\037} \037memo-text\037\002\n" - " \n" - "Sends the named \037nick\037 or \037channel\037 a memo containing\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends the named \037nick\037 or \037channel\037 a memo containing\n" "\037memo-text\037. When sending to a nickname, the recipient will\n" "receive a notice that he/she has a new memo. The target\n" "nickname/channel must be registered.\n" @@ -83,11 +84,6 @@ class CommandMSRSend : public Command "has been read.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "RSEND", _("RSEND {\037nick\037 | \037channel\037} \037memo-text\037")); - } }; class MSRSend : public Module @@ -95,17 +91,15 @@ class MSRSend : public Module CommandMSRSend commandmsrsend; public: - MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsrsend(this) { - if (!Config->MSMemoReceipt) - throw ModuleException("Invalid value for memoreceipt"); - this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); + if (!Config->MSMemoReceipt) + throw ModuleException("Invalid value for memoreceipt"); - this->AddCommand(memoserv->Bot(), &commandmsrsend); + ModuleManager::RegisterService(&commandmsrsend); } }; diff --git a/modules/core/ms_send.cpp b/modules/core/ms_send.cpp index 9bf4b3f40..9397e7ad7 100644 --- a/modules/core/ms_send.cpp +++ b/modules/core/ms_send.cpp @@ -17,12 +17,13 @@ class CommandMSSend : public Command { public: - CommandMSSend() : Command("SEND", 2, 2) + CommandMSSend(Module *creator) : Command(creator, "memoserv/send", 2, 2) { this->SetDesc(_("Send a memo to a nick or channel")); + this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params[0]; const Anope::string &text = params[1]; @@ -37,24 +38,19 @@ class CommandMSSend : public Command else if (result == MemoServService::MEMO_TARGET_FULL) source.Reply(_("%s currently has too many memos and cannot receive more."), nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SEND {\037nick\037 | \037channel\037} \037memo-text\037\002\n" - " \n" - "Sends the named \037nick\037 or \037channel\037 a memo containing\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends the named \037nick\037 or \037channel\037 a memo containing\n" "\037memo-text\037. When sending to a nickname, the recipient will\n" "receive a notice that he/she has a new memo. The target\n" "nickname/channel must be registered.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SEND", _(MEMO_SEND_SYNTAX)); - } }; class MSSend : public Module @@ -62,14 +58,12 @@ class MSSend : public Module CommandMSSend commandmssend; public: - MSSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmssend(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmssend); + ModuleManager::RegisterService(&commandmssend); } }; diff --git a/modules/core/ms_sendall.cpp b/modules/core/ms_sendall.cpp index d7ffb0489..6a764f829 100644 --- a/modules/core/ms_sendall.cpp +++ b/modules/core/ms_sendall.cpp @@ -17,20 +17,21 @@ class CommandMSSendAll : public Command { public: - CommandMSSendAll() : Command("SENDALL", 1, 1, "memoserv/sendall") + CommandMSSendAll(Module *creator) : Command(creator, "memoserv/sendall", 1, 1, "memoserv/sendall") { this->SetDesc(_("Send a memo to all registered users")); + this->SetSyntax(_("\037memo-text\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &text = params[0]; if (readonly) { - source.Reply(_(MEMO_SEND_DISABLED)); - return MOD_CONT; + source.Reply(MEMO_SEND_DISABLED); + return; } NickAlias *na = findnick(u->nick); @@ -44,20 +45,16 @@ class CommandMSSendAll : public Command } source.Reply(_("A massmemo has been sent to all registered users.")); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SENDALL\002 \002memo-text\002\n \n" - "Sends all registered users a memo containing \037memo-text\037.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends all registered users a memo containing \037memo-text\037.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SENDALL", _("SENDALL \037memo-text\037")); - } }; class MSSendAll : public Module @@ -65,14 +62,12 @@ class MSSendAll : public Module CommandMSSendAll commandmssendall; public: - MSSendAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSSendAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmssendall(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmssendall); + ModuleManager::RegisterService(&commandmssendall); } }; diff --git a/modules/core/ms_set.cpp b/modules/core/ms_set.cpp index 3885d37df..37ad0d7f8 100644 --- a/modules/core/ms_set.cpp +++ b/modules/core/ms_set.cpp @@ -12,12 +12,11 @@ /*************************************************************************/ #include "module.h" -#include "memoserv.h" class CommandMSSet : public Command { private: - CommandReturn DoNotify(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) + void DoNotify(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) { User *u = source.u; const Anope::string ¶m = params[1]; @@ -26,19 +25,19 @@ class CommandMSSet : public Command { u->Account()->SetFlag(NI_MEMO_SIGNON); u->Account()->SetFlag(NI_MEMO_RECEIVE); - source.Reply(_("%s will now notify you of memos when you log on and when they are sent to you."), Config->s_MemoServ.c_str()); + source.Reply(_("%s will now notify you of memos when you log on and when they are sent to you."), Config->MemoServ.c_str()); } else if (param.equals_ci("LOGON")) { u->Account()->SetFlag(NI_MEMO_SIGNON); u->Account()->UnsetFlag(NI_MEMO_RECEIVE); - source.Reply(_("%s will now notify you of memos when you log on or unset /AWAY."), Config->s_MemoServ.c_str()); + source.Reply(_("%s will now notify you of memos when you log on or unset /AWAY."), Config->MemoServ.c_str()); } else if (param.equals_ci("NEW")) { u->Account()->UnsetFlag(NI_MEMO_SIGNON); u->Account()->SetFlag(NI_MEMO_RECEIVE); - source.Reply(_("%s will now notify you of memos when they are sent to you."), Config->s_MemoServ.c_str()); + source.Reply(_("%s will now notify you of memos when they are sent to you."), Config->MemoServ.c_str()); } else if (param.equals_ci("MAIL")) { @@ -60,15 +59,15 @@ class CommandMSSet : public Command u->Account()->UnsetFlag(NI_MEMO_SIGNON); u->Account()->UnsetFlag(NI_MEMO_RECEIVE); u->Account()->UnsetFlag(NI_MEMO_MAIL); - source.Reply(_("%s will not send you any notification of memos."), Config->s_MemoServ.c_str()); + source.Reply(_("%s will not send you any notification of memos."), Config->MemoServ.c_str()); } else - SyntaxError(source, "SET NOTIFY", _("SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF }")); + this->OnSyntaxError(source, param); - return MOD_CONT; + return; } - CommandReturn DoLimit(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) + void DoLimit(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) { User *u = source.u; @@ -89,13 +88,13 @@ class CommandMSSet : public Command p3 = params.size() > 4 ? params[4] : ""; if (!(ci = cs_findchan(chan))) { - source.Reply(_(CHAN_X_NOT_REGISTERED), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); + return; } else if (!is_servadmin && !check_access(u, ci, CA_MEMO)) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } mi = &ci->memos; } @@ -106,8 +105,8 @@ class CommandMSSet : public Command NickAlias *na; if (!(na = findnick(p1))) { - source.Reply(_(NICK_X_NOT_REGISTERED), p1.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, p1.c_str()); + return; } user = p1; mi = &na->nc->memos; @@ -117,8 +116,8 @@ class CommandMSSet : public Command } else if (p1.empty() || (!p1.is_pos_number_only() && !p1.equals_ci("NONE")) || (!p2.empty() && !p2.equals_ci("HARD"))) { - SyntaxError(source, "SET LIMIT", _("SET LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]")); - return MOD_CONT; + this->OnSyntaxError(source, ""); + return; } if (!chan.empty()) { @@ -145,18 +144,18 @@ class CommandMSSet : public Command { if (p1.empty() || !p2.empty() || !isdigit(p1[0])) { - SyntaxError(source, "SET LIMIT", _("SET LIMIT [\037channel\037] \037limit\037")); - return MOD_CONT; + this->OnSyntaxError(source, ""); + return; } if (!chan.empty() && ci->HasFlag(CI_MEMO_HARDMAX)) { source.Reply(_("The memo limit for %s may not be changed."), chan.c_str()); - return MOD_CONT; + return; } else if (chan.empty() && nc->HasFlag(NI_MEMO_HARDMAX)) { source.Reply(_("You are not permitted to change your memo limit.")); - return MOD_CONT; + return; } limit = -1; try @@ -172,7 +171,7 @@ class CommandMSSet : public Command source.Reply(_("You cannot set the memo limit for %s higher than %d."), chan.c_str(), Config->MSMaxMemos); else source.Reply(_("You cannot set your memo limit higher than %d."), Config->MSMaxMemos); - return MOD_CONT; + return; } } mi->memomax = limit; @@ -197,15 +196,16 @@ class CommandMSSet : public Command else source.Reply(_("Memo limit \002disabled\002 for %s."), !chan.empty() ? chan.c_str() : user.c_str()); } - return MOD_CONT; + return; } public: - CommandMSSet() : Command("SET", 2, 5) + CommandMSSet(Module *creator) : Command(creator, "memoserv/set", 2, 5) { this->SetDesc(_("Set options related to memos")); + this->SetSyntax(_("\037option\037 \037parameters\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &cmd = params[0]; @@ -219,28 +219,31 @@ class CommandMSSet : public Command return this->DoLimit(source, params, mi); else { - source.Reply(_(NICK_SET_UNKNOWN_OPTION), Config->UseStrictPrivMsgString.c_str(), cmd.c_str()); - source.Reply(_(MORE_INFO), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), "SET"); + source.Reply(NICK_SET_UNKNOWN_OPTION, Config->UseStrictPrivMsgString.c_str(), cmd.c_str()); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), "SET"); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { if (subcommand.empty()) - source.Reply(_("Syntax: \002SET \037option\037 \037parameters\037\002\n \n" - "Sets various memo options. \037option\037 can be one of:\n" + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets various memo options. \037option\037 can be one of:\n" " \n" " NOTIFY Changes when you will be notified about\n" " new memos (only for nicknames)\n" " LIMIT Sets the maximum number of memos you can\n" " receive\n" " \n" - "Type \002%s%s HELP SET \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); + "Type \002%s%s HELP %s \037option\037\002 for more information\n" + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + } else if (subcommand.equals_ci("NOTIFY")) - source.Reply(_("Syntax: \002SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" + source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" "Changes when you will be notified about new memos:\n" " \n" " ON You will be notified of memos when you log on,\n" @@ -260,7 +263,7 @@ class CommandMSSet : public Command { User *u = source.u; if (u->IsServicesOper()) - source.Reply(_("Syntax: \002SET LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]\002\n" + source.Reply(_("Syntax: \002LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]\002\n" " \n" "Sets the maximum number of memos a user or channel is\n" "allowed to have. Setting the limit to 0 prevents the user\n" @@ -279,7 +282,7 @@ class CommandMSSet : public Command "remove their limit, may not set a limit above %d, and may\n" "not set a hard limit."), Config->MSMaxMemos); else - source.Reply(_("Syntax: \002SET LIMIT [\037channel\037] \037limit\037\002\n" + source.Reply(_("Syntax: \002LIMIT [\037channel\037] \037limit\037\002\n" " \n" "Sets the maximum number of memos you (or the given channel)\n" "are allowed to have. If you set this to 0, no one will be\n" @@ -291,11 +294,6 @@ class CommandMSSet : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SET", _(NICK_SET_SYNTAX)); - } }; class MSSet : public Module @@ -303,14 +301,12 @@ class MSSet : public Module CommandMSSet commandmsset; public: - MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsset(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsset); + ModuleManager::RegisterService(&commandmsset); } }; diff --git a/modules/core/ms_staff.cpp b/modules/core/ms_staff.cpp index 828186e2c..b4fe26f5c 100644 --- a/modules/core/ms_staff.cpp +++ b/modules/core/ms_staff.cpp @@ -17,19 +17,20 @@ class CommandMSStaff : public Command { public: - CommandMSStaff() : Command("STAFF", 1, 1, "memoserv/staff") + CommandMSStaff(Module *creator) : Command(creator, "memoserv/staff", 1, 1, "memoserv/staff") { this->SetDesc(_("Send a memo to all opers/admins")); + this->SetSyntax(_("\037memo-text\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &text = params[0]; if (readonly) { - source.Reply(_(MEMO_SEND_DISABLED)); - return MOD_CONT; + source.Reply(MEMO_SEND_DISABLED); + return; } for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it) @@ -40,22 +41,17 @@ class CommandMSStaff : public Command memoserv->Send(source.u->nick, nc->display, text, true); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002STAFF\002 \002memo-text\002\n" - " \n" - "Sends all services staff a memo containing \037memo-text\037.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends all services staff a memo containing \037memo-text\037.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "STAFF", _("STAFF \037memo-text\037")); - } }; class MSStaff : public Module @@ -63,14 +59,12 @@ class MSStaff : public Module CommandMSStaff commandmsstaff; public: - MSStaff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + MSStaff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandmsstaff(this) { this->SetAuthor("Anope"); - if (!memoserv) - throw ModuleException("MemoServ is not loaded!"); - - this->AddCommand(memoserv->Bot(), &commandmsstaff); + ModuleManager::RegisterService(&commandmsstaff); } }; diff --git a/modules/core/nickserv.h b/modules/core/nickserv.h index 71039c7ba..b58dbd65f 100644 --- a/modules/core/nickserv.h +++ b/modules/core/nickserv.h @@ -6,8 +6,6 @@ class NickServService : public Service public: NickServService(Module *m) : Service(m, "NickServ") { } - virtual BotInfo *Bot() = 0; - virtual void Validate(User *u) = 0; }; diff --git a/modules/core/ns_access.cpp b/modules/core/ns_access.cpp index d25520d43..df9ae6eed 100644 --- a/modules/core/ns_access.cpp +++ b/modules/core/ns_access.cpp @@ -12,12 +12,11 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSAccess : public Command { private: - CommandReturn DoServAdminList(CommandSource &source, const std::vector<Anope::string> ¶ms, NickCore *nc) + void DoServAdminList(CommandSource &source, const std::vector<Anope::string> ¶ms, NickCore *nc) { Anope::string mask = params.size() > 2 ? params[2] : ""; unsigned i, end; @@ -25,13 +24,13 @@ class CommandNSAccess : public Command if (nc->access.empty()) { source.Reply(_("Access list for \002%s\002 is empty."), nc->display.c_str()); - return MOD_CONT; + return; } if (nc->HasFlag(NI_SUSPENDED)) { - source.Reply(_(NICK_X_SUSPENDED), nc->display.c_str()); - return MOD_CONT; + source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); + return; } source.Reply(_("Access list for \002%s\002:"), params[1].c_str()); @@ -43,57 +42,57 @@ class CommandNSAccess : public Command source.Reply(" %s", access.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) + void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) { if (mask.empty()) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } if (nc->access.size() >= Config->NSAccessMax) { source.Reply(_("Sorry, you can only have %d access entries for a nickname."), Config->NSAccessMax); - return MOD_CONT; + return; } if (nc->FindAccess(mask)) { source.Reply(_("Mask \002%s\002 already present on your access list."), mask.c_str()); - return MOD_CONT; + return; } nc->AddAccess(mask); source.Reply(_("\002%s\002 added to your access list."), mask.c_str()); - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) + void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) { if (mask.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } if (!nc->FindAccess(mask)) { source.Reply(_("\002%s\002 not found on your access list."), mask.c_str()); - return MOD_CONT; + return; } source.Reply(_("\002%s\002 deleted from your access list."), mask.c_str()); nc->EraseAccess(mask); - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, NickCore *nc, const Anope::string &mask) + void DoList(CommandSource &source, NickCore *nc, const Anope::string &mask) { User *u = source.u; unsigned i, end; @@ -101,7 +100,7 @@ class CommandNSAccess : public Command if (nc->access.empty()) { source.Reply(_("Your access list is empty."), u->nick.c_str()); - return MOD_CONT; + return; } source.Reply(_("Access list:")); @@ -113,15 +112,18 @@ class CommandNSAccess : public Command source.Reply(" %s", access.c_str()); } - return MOD_CONT; + return; } public: - CommandNSAccess() : Command("ACCESS", 1, 3) + CommandNSAccess(Module *creator) : Command(creator, "nickserv/access", 1, 3) { this->SetDesc(_("Modify the list of authorized addresses")); + this->SetSyntax(_("ADD \037mask\037")); + this->SetSyntax(_("DEL \037mask\037")); + this->SetSyntax(_("LIST")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &cmd = params[0]; @@ -133,11 +135,11 @@ class CommandNSAccess : public Command if (!mask.empty() && mask.find('@') == Anope::string::npos) { - source.Reply(_(BAD_USERHOST_MASK)); - source.Reply(_(MORE_INFO), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), "ACCESS"); + source.Reply(BAD_USERHOST_MASK); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), this->name.c_str()); } else if (u->Account()->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), u->Account()->display.c_str()); + source.Reply(NICK_X_SUSPENDED, u->Account()->display.c_str()); else if (cmd.equals_ci("ADD")) return this->DoAdd(source, u->Account(), mask); else if (cmd.equals_ci("DEL")) @@ -147,16 +149,14 @@ class CommandNSAccess : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ACCESS ADD \037mask\037\002\n" - " \002ACCESS DEL \037mask\037\002\n" - " \002ACCESS LIST\002\n" - " \n" - "Modifies or displays the access list for your nick. This\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Modifies or displays the access list for your nick. This\n" "is the list of addresses which will be automatically\n" "recognized by %s as allowed to use the nick. If\n" "you want to use the nick from a different address, you\n" @@ -173,14 +173,9 @@ class CommandNSAccess : public Command " Reverses the previous command.\n" " \n" " \002ACCESS LIST\002\n" - " Displays the current access list."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + " Displays the current access list."), Config->NickServ.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "ACCESS", _("ACCESS {ADD | DEL | LIST} [\037mask\037]")); - } }; class NSAccess : public Module @@ -188,14 +183,12 @@ class NSAccess : public Module CommandNSAccess commandnsaccess; public: - NSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsaccess(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsaccess); + ModuleManager::RegisterService(&commandnsaccess); } }; diff --git a/modules/core/ns_ajoin.cpp b/modules/core/ns_ajoin.cpp index 52866c13a..2838352dd 100644 --- a/modules/core/ns_ajoin.cpp +++ b/modules/core/ns_ajoin.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSAJoin : public Command { @@ -40,7 +39,7 @@ class CommandNSAJoin : public Command if (channels.size() >= Config->AJoinMax) source.Reply(_("Your auto join list is full.")); else if (ircdproto->IsChannelValid(params[1]) == false) - source.Reply(_(CHAN_X_INVALID), params[1].c_str()); + source.Reply(CHAN_X_INVALID, params[1].c_str()); else { channels.push_back(std::make_pair(params[1], params.size() > 2 ? params[2] : "")); @@ -72,12 +71,13 @@ class CommandNSAJoin : public Command } public: - CommandNSAJoin() : Command("AJOIN", 1, 3) + CommandNSAJoin(Module *creator) : Command(creator, "nickserv/ajoin", 1, 3) { this->SetDesc(_("Manage your auto join list")); + this->SetSyntax(_("{ADD | DEL | LIST} [\037channel\037] [\037key\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { if (params[0].equals_ci("LIST")) this->DoList(source, params); @@ -90,22 +90,17 @@ class CommandNSAJoin : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002AJOIN {ADD | DEL | LIST} [\037channel\037] [\037key\037]\002\n" - " \n" - "This command manages your auto join list. When you identify\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command manages your auto join list. When you identify\n" "you will automatically join the channels on your auto join list")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "AJOIN", _("AJOIN {ADD | DEL | LIST} [\037channel\037] [\037key\037]")); - } }; class NSAJoin : public Module @@ -113,14 +108,12 @@ class NSAJoin : public Module CommandNSAJoin commandnsajoin; public: - NSAJoin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSAJoin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsajoin(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsajoin); + ModuleManager::RegisterService(&commandnsajoin); Implementation i[] = { I_OnNickIdentify, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 3); @@ -134,7 +127,7 @@ class NSAJoin : public Module for (unsigned i = 0; i < channels.size(); ++i) { Channel *c = findchan(channels[i].first); - ChannelInfo *ci = c != NULL? c->ci : cs_findchan(channels[i].first); + ChannelInfo *ci = c != NULL ? c->ci : cs_findchan(channels[i].first); if (c == NULL && ci != NULL) c = ci->c; @@ -190,12 +183,13 @@ class NSAJoin : public Module if (need_invite) { - if (!check_access(u, ci, CA_INVITE)) + BotInfo *bi = findbot(Config->NickServ); + if (!bi || !check_access(u, ci, CA_INVITE)) continue; - ircdproto->SendInvite(nickserv->Bot(), channels[i].first, u->nick); + ircdproto->SendInvite(bi, channels[i].first, u->nick); } - ircdproto->SendSVSJoin(Config->s_NickServ, u->nick, channels[i].first, key); + ircdproto->SendSVSJoin(Config->NickServ, u->nick, channels[i].first, key); } } diff --git a/modules/core/ns_alist.cpp b/modules/core/ns_alist.cpp index 863cf68e1..ec4686261 100644 --- a/modules/core/ns_alist.cpp +++ b/modules/core/ns_alist.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSAList : public Command { public: - CommandNSAList() : Command("ALIST", 0, 2) + CommandNSAList(Module *creator) : Command(creator, "nickserv/alist", 0, 2) { this->SetDesc(_("List channels you have access on")); + this->SetSyntax(_("[\037nickname\037] [\037level\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { /* * List the channels that the given nickname has access on @@ -88,9 +88,9 @@ class CommandNSAList : public Command } if (!na) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (min_level <= ACCESS_INVALID || min_level > ACCESS_FOUNDER) - source.Reply(_(CHAN_ACCESS_LEVEL_RANGE), ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); + source.Reply(CHAN_ACCESS_LEVEL_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); else { int chan_count = 0; @@ -130,38 +130,29 @@ class CommandNSAList : public Command source.Reply(_("End of list - %d/%d channels shown."), match_count, chan_count); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - User *u = source.u; - if (u->IsServicesOper()) - source.Reply(_("Syntax: \002ALIST [\037nickname\037] [\037level\037]\002\n" - " \n" - "With no parameters, lists channels you have access on. With\n" - "one parameter, lists channels that \002nickname\002 has access \n" - "on. With two parameters lists channels that \002nickname\002 has \n" - "\002level\002 access or greater on.\n" - "This use limited to \002Services Operators\002.")); - else - source.Reply(_("Syntax: \002ALIST [\037level\037]\002\n" - " \n" - "Lists all channels you have access on. Optionally, you can specify\n" - "a level in XOP or ACCESS format. The resulting list will only\n" - "include channels where you have the given level of access.\n" - "Examples:\n" - " \002ALIST Founder\002\n" - " Lists all channels where you have Founder\n" - " access.\n" - " \002ALIST AOP\002\n" - " Lists all channels where you have AOP\n" - " access or greater.\n" - " \002ALIST 10\002\n" - " Lists all channels where you have level 10\n" - " access or greater.\n" - "Channels that have the \037NOEXPIRE\037 option set will be\n" - "prefixed by an exclamation mark.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all channels you have access on. Optionally, you can specify\n" + "a level in XOP or ACCESS format. The resulting list will only\n" + "include channels where you have the given level of access.\n" + "Examples:\n" + " \002ALIST Founder\002\n" + " Lists all channels where you have Founder\n" + " access.\n" + " \002ALIST AOP\002\n" + " Lists all channels where you have AOP\n" + " access or greater.\n" + " \002ALIST 10\002\n" + " Lists all channels where you have level 10\n" + " access or greater.\n" + "Channels that have the \037NOEXPIRE\037 option set will be\n" + "prefixed by an exclamation mark. The nickname parameter is\n" + "limited to Services Operators")); return true; } @@ -172,11 +163,12 @@ class NSAList : public Module CommandNSAList commandnsalist; public: - NSAList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSAList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsalist(this) { this->SetAuthor("Anope"); - this->AddCommand(nickserv->Bot(), &commandnsalist); + ModuleManager::RegisterService(&commandnsalist); } }; diff --git a/modules/core/ns_cert.cpp b/modules/core/ns_cert.cpp index 213ddbe7c..c351dbd43 100644 --- a/modules/core/ns_cert.cpp +++ b/modules/core/ns_cert.cpp @@ -12,23 +12,22 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSCert : public Command { private: - CommandReturn DoServAdminList(CommandSource &source, NickCore *nc) + void DoServAdminList(CommandSource &source, NickCore *nc) { if (nc->cert.empty()) { source.Reply(_("Certificate list for \002%s\002 is empty."), nc->display.c_str()); - return MOD_CONT; + return; } if (nc->HasFlag(NI_SUSPENDED)) { - source.Reply(_(NICK_X_SUSPENDED), nc->display.c_str()); - return MOD_CONT; + source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); + return; } source.Reply(_("Certificate list for \002%s\002:"), nc->display.c_str()); @@ -38,78 +37,78 @@ class CommandNSCert : public Command source.Reply(" %s", fingerprint.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) + void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) { if (nc->cert.size() >= Config->NSAccessMax) { source.Reply(_("Sorry, you can only have %d certificate entries for a nickname."), Config->NSAccessMax); - return MOD_CONT; + return; } if (!source.u->fingerprint.empty() && !nc->FindCert(source.u->fingerprint)) { nc->AddCert(source.u->fingerprint); source.Reply(_("\002%s\002 added to your certificate list."), source.u->fingerprint.c_str()); - return MOD_CONT; + return; } if (mask.empty()) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } if (nc->FindCert(mask)) { source.Reply(_("Fingerprint \002%s\002 already present on your certificate list."), mask.c_str()); - return MOD_CONT; + return; } nc->AddCert(mask); source.Reply(_("\002%s\002 added to your certificate list."), mask.c_str()); - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) + void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) { if (!source.u->fingerprint.empty() && nc->FindCert(source.u->fingerprint)) { nc->EraseCert(source.u->fingerprint); source.Reply(_("\002%s\002 deleted from your certificate list."), source.u->fingerprint.c_str()); - return MOD_CONT; + return; } if (mask.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } if (!nc->FindCert(mask)) { source.Reply(_("\002%s\002 not found on your certificate list."), mask.c_str()); - return MOD_CONT; + return; } source.Reply(_("\002%s\002 deleted from your certificate list."), mask.c_str()); nc->EraseCert(mask); - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, NickCore *nc) + void DoList(CommandSource &source, NickCore *nc) { User *u = source.u; if (nc->cert.empty()) { source.Reply(_("Your certificate list is empty."), u->nick.c_str()); - return MOD_CONT; + return; } source.Reply(_("Cert list:")); @@ -119,16 +118,19 @@ class CommandNSCert : public Command source.Reply(" %s", fingerprint.c_str()); } - return MOD_CONT; + return; } public: - CommandNSCert() : Command("CERT", 1, 2) + CommandNSCert(Module *creator) : Command(creator, "nickserv/cert", 1, 2) { this->SetDesc("Modify the nickname client certificate list"); + this->SetSyntax("ADD \037fingerprint\037"); + this->SetSyntax("DEL \037fingerprint\037"); + this->SetSyntax("LIST"); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &cmd = params[0]; @@ -139,7 +141,7 @@ class CommandNSCert : public Command return this->DoServAdminList(source, na->nc); if (u->Account()->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), u->Account()->display.c_str()); + source.Reply(NICK_X_SUSPENDED, u->Account()->display.c_str()); else if (cmd.equals_ci("ADD")) return this->DoAdd(source, u->Account(), mask); else if (cmd.equals_ci("DEL")) @@ -149,20 +151,18 @@ class CommandNSCert : public Command else this->OnSyntaxError(source, cmd); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CERT ADD [\037fingerprint\037]\002\n" - " \002CERT DEL [\037<fingerprint>\037]\002\n" - " \002CERT LIST\002\n" - " \n" - "Modifies or displays the certificate list for your nick.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Modifies or displays the certificate list for your nick.\n" "If you connect to IRC and provide a client certificate with a\n" "matching fingerprint in the cert list, your nick will be\n" "automatically identified to %s.\n" - " \n"), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + " \n"), Config->NickServ.c_str(), Config->NickServ.c_str()); source.Reply(_("Examples:\n" " \n" " \002CERT ADD <fingerprint>\002\n" @@ -174,14 +174,9 @@ class CommandNSCert : public Command " Reverses the previous command.\n" " \n" " \002CERT LIST\002\n" - " Displays the current certificate list."), Config->s_NickServ.c_str()); + " Displays the current certificate list."), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CERT", _("CERT {ADD|DEL|LIST} [\037fingerprint\037]")); - } }; class NSCert : public Module @@ -190,8 +185,9 @@ class NSCert : public Module void DoAutoIdentify(User *u) { + BotInfo *bi = findbot(Config->NickServ); NickAlias *na = findnick(u->nick); - if (!na) + if (!bi || !na) return; if (u->IsIdentified() && u->Account() == na->nc) return; @@ -201,25 +197,23 @@ class NSCert : public Module return; u->Identify(na); - u->SendMessage(nickserv->Bot(), _("SSL Fingerprint accepted. You are now identified.")); + u->SendMessage(bi, _("SSL Fingerprint accepted. You are now identified.")); return; } public: - NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnscert(this) { this->SetAuthor("Anope"); if (!ircd || !ircd->certfp) throw ModuleException("Your IRCd does not support ssl client certificates"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - Implementation i[] = { I_OnUserNickChange, I_OnFingerprint }; ModuleManager::Attach(i, this, 2); - this->AddCommand(nickserv->Bot(), &commandnscert); + ModuleManager::RegisterService(&commandnscert); } void OnFingerprint(User *u) diff --git a/modules/core/ns_drop.cpp b/modules/core/ns_drop.cpp index ff6078002..7960652ff 100644 --- a/modules/core/ns_drop.cpp +++ b/modules/core/ns_drop.cpp @@ -12,18 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSDrop : public Command { public: - CommandNSDrop() : Command("DROP", 0, 1) + CommandNSDrop(Module *creator) : Command(creator, "nickserv/drop", 0, 1) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Cancel the registration of a nickname")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string nick = !params.empty() ? params[0] : ""; @@ -31,20 +30,20 @@ class CommandNSDrop : public Command if (readonly) { source.Reply(_("Sorry, nickname de-registration is temporarily disabled.")); - return MOD_CONT; + return; } NickAlias *na = findnick((u->Account() && !nick.empty() ? nick : u->nick)); if (!na) { - source.Reply(_(NICK_NOT_REGISTERED)); - return MOD_CONT; + source.Reply(NICK_NOT_REGISTERED); + return; } if (!u->Account()) { - source.Reply(_(NICK_IDENTIFY_REQUIRED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - return MOD_CONT; + source.Reply(NICK_IDENTIFY_REQUIRED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); + return; } bool is_mine = u->Account() == na->nc; @@ -53,13 +52,13 @@ class CommandNSDrop : public Command my_nick = na->nick; if (!is_mine && !u->HasPriv("nickserv/drop")) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (Config->NSSecureAdmins && !is_mine && na->nc->IsServicesOper()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); FOREACH_MOD(I_OnNickDrop, OnNickDrop(u, na)); @@ -79,26 +78,25 @@ class CommandNSDrop : public Command } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { User *u = source.u; if (u->Account() && u->HasPriv("nickserv/drop")) - source.Reply(_("Syntax: \002DROP [\037nickname\037]\002\n" + source.Reply(_("Syntax: \002%s [\037nickname\037]\002\n" " \n" - "Without a parameter, drops your nickname from the\n" - "%s database.\n" + "Without a parameter, deletes your nickname.\n" " \n" "With a parameter, drops the named nick from the database.\n" "You may drop any nick within your group without any \n" "special privileges. Dropping any nick is limited to \n" - "\002Services Operators\002."), Config->s_NickServ.c_str()); + "\002Services Operators\002."), source.command.c_str()); else - source.Reply(_("Syntax: \002DROP [\037nickname\037 | \037password\037]\002\n" + source.Reply(_("Syntax: \002%s [\037nickname\037 | \037password\037]\002\n" " \n" - "Drops your nickname from the %s database. A nick\n" + "Deltes your nickname. A nick\n" "that has been dropped is free for anyone to re-register.\n" " \n" "You may drop a nick within your group by passing it\n" @@ -109,8 +107,7 @@ class CommandNSDrop : public Command "your password as the \002password\002 parameter.\n" " \n" "In order to use this command, you must first identify\n" - "with your password (\002%s%s HELP IDENTIFY\002 for more\n" - "information)."), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + "with your password."), source.command.c_str()); return true; } @@ -121,14 +118,12 @@ class NSDrop : public Module CommandNSDrop commandnsdrop; public: - NSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsdrop(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsdrop); + ModuleManager::RegisterService(&commandnsdrop); } }; diff --git a/modules/core/ns_getemail.cpp b/modules/core/ns_getemail.cpp index 0bd6c8fb2..7519ae6d0 100644 --- a/modules/core/ns_getemail.cpp +++ b/modules/core/ns_getemail.cpp @@ -16,17 +16,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSGetEMail : public Command { public: - CommandNSGetEMail() : Command("GETEMAIL", 1, 1, "nickserv/getemail") + CommandNSGetEMail(Module *creator) : Command(creator, "nickserv/getemail", 1, 1, "nickserv/getemail") { this->SetDesc(_("Matches and returns all users that registered using given email")); + this->SetSyntax(_("\037user@email-host\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &email = params[0]; @@ -48,40 +48,34 @@ class CommandNSGetEMail : public Command if (j <= 0) { source.Reply(_("No Emails listed for \002%s\002."), email.c_str()); - return MOD_CONT; + return; } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GETEMAIL \037user@emailhost\037\002\n" - "Returns the matching nicks that used given email. \002Note\002 that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Returns the matching nicks that used given email. \002Note\002 that\n" "you can not use wildcards for either user or emailhost. Whenever\n" "this command is used, a message including the person who issued\n" "the command and the email it was used on will be logged.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GETMAIL", _("GETEMAIL \002user@email-host\002 No WildCards!!")); - } }; class NSGetEMail : public Module { CommandNSGetEMail commandnsgetemail; public: - NSGetEMail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSGetEMail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsgetemail(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsgetemail); + ModuleManager::RegisterService(&commandnsgetemail); } }; diff --git a/modules/core/ns_getpass.cpp b/modules/core/ns_getpass.cpp index 3d7ceb3ae..ab4bcd4e2 100644 --- a/modules/core/ns_getpass.cpp +++ b/modules/core/ns_getpass.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSGetPass : public Command { public: - CommandNSGetPass() : Command("GETPASS", 1, 1, "nickserv/getpass") + CommandNSGetPass(Module *creator) : Command(creator, "nickserv/getpass", 1, 1, "nickserv/getpass") { this->SetDesc(_("Retrieve the password for a nickname")); + this->SetSyntax(_("\037nickname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; @@ -30,9 +30,9 @@ class CommandNSGetPass : public Command NickAlias *na; if (!(na = findnick(nick))) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (Config->NSSecureAdmins && na->nc->IsServicesOper()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else { if (enc_decrypt(na->nc->pass, tmp_pass) == 1) @@ -43,24 +43,19 @@ class CommandNSGetPass : public Command else source.Reply(_("GETPASS command unavailable because encryption is in use.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GETPASS \037nickname\037\002\n" - " \n" - "Returns the password for the given nickname. \002Note\002 that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Returns the password for the given nickname. \002Note\002 that\n" "whenever this command is used, a message including the\n" "person who issued the command and the nickname it was used\n" "on will be logged and sent out as a WALLOPS/GLOBOPS.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GETPASS", _("GETPASS \037nickname\037")); - } }; class NSGetPass : public Module @@ -68,18 +63,16 @@ class NSGetPass : public Module CommandNSGetPass commandnsgetpass; public: - NSGetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSGetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsgetpass(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - Anope::string tmp_pass = "plain:tmp"; if (enc_decrypt(tmp_pass, tmp_pass) == -1) throw ModuleException("Incompatible with the encryption module being used"); - this->AddCommand(nickserv->Bot(), &commandnsgetpass); + ModuleManager::RegisterService(&commandnsgetpass); } }; diff --git a/modules/core/ns_ghost.cpp b/modules/core/ns_ghost.cpp index 0a8306734..37dcef9c7 100644 --- a/modules/core/ns_ghost.cpp +++ b/modules/core/ns_ghost.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSGhost : public Command { public: - CommandNSGhost() : Command("GHOST", 1, 2) + CommandNSGhost(Module *creator) : Command(creator, "nickserv/ghost", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Disconnects a \"ghost\" IRC session using your nick")); + this->SetSyntax("\037nickname\037 [\037password\037]"); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &nick = params[0]; const Anope::string &pass = params.size() > 1 ? params[1] : ""; @@ -33,11 +33,11 @@ class CommandNSGhost : public Command NickAlias *na = findnick(nick); if (!user) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (!na) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (na->nc->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); + source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (nick.equals_ci(u->nick)) source.Reply(_("You can't ghost yourself!")); else @@ -52,28 +52,28 @@ class CommandNSGhost : public Command else if (!pass.empty()) { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); if (MOD_RESULT == EVENT_STOP) - return MOD_CONT; + return; else if (MOD_RESULT == EVENT_ALLOW) ok = true; } if (ok) { - if (!user->IsIdentified() && FindCommand(nickserv->Bot(), "RECOVER")) + if (!user->IsIdentified()) source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); else { Log(LOG_COMMAND, u, this) << "for " << nick; Anope::string buf = "GHOST command used by " + u->nick; - user->Kill(Config->s_NickServ, buf); + user->Kill(Config->NickServ, buf); source.Reply(_("Ghost with your nick has been killed."), nick.c_str()); } } else { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); if (!pass.empty()) { Log(LOG_COMMAND, u, this) << "with an invalid password for " << nick; @@ -82,14 +82,14 @@ class CommandNSGhost : public Command } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GHOST \037nickname\037 [\037password\037]\002\n" - "" - "itermminates a \"ghost\" IRC session using your nick. A\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("itermminates a \"ghost\" IRC session using your nick. A\n" "ghost\" session is one which is not actually connected,\n" "but which the IRC server believes is still online for one\n" "reason or another. Typically, this happens if your\n" @@ -103,11 +103,6 @@ class CommandNSGhost : public Command "the nickname.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GHOST", _("GHOST \037nickname\037 [\037password\037]")); - } }; class NSGhost : public Module @@ -115,14 +110,12 @@ class NSGhost : public Module CommandNSGhost commandnsghost; public: - NSGhost(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSGhost(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsghost(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsghost); + ModuleManager::RegisterService(&commandnsghost); } }; diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp index 5a568ca7f..f3444a4ca 100644 --- a/modules/core/ns_group.cpp +++ b/modules/core/ns_group.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSGroup : public Command { public: - CommandNSGroup() : Command("GROUP", 1, 2) + CommandNSGroup(Module *creator) : Command(creator, "nickserv/group", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Join a group")); + this->SetSyntax(_("\037target\037 \037password\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -33,7 +33,7 @@ class CommandNSGroup : public Command if (readonly) { source.Reply(_("Sorry, nickname grouping is temporarily disabled.")); - return MOD_CONT; + return; } if (Config->RestrictOperNicks) @@ -43,36 +43,29 @@ class CommandNSGroup : public Command if (!u->HasMode(UMODE_OPER) && u->nick.find_ci(o->name) != Anope::string::npos) { - source.Reply(_(NICK_CANNOT_BE_REGISTERED), u->nick.c_str()); - return MOD_CONT; + source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); + return; } } NickAlias *target, *na = findnick(u->nick); if (!(target = findnick(nick))) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (Anope::CurTime < u->lastnickreg + Config->NSRegDelay) source.Reply(_("Please wait %d seconds before using the GROUP command again."), (Config->NSRegDelay + u->lastnickreg) - Anope::CurTime); - else if (u->Account() && u->Account()->HasFlag(NI_SUSPENDED)) - { - Log(nickserv->Bot()) << u->GetMask() << " tried to use GROUP from SUSPENDED nick " << target->nick; - source.Reply(_(NICK_X_SUSPENDED), u->nick.c_str()); - } else if (target && target->nc->HasFlag(NI_SUSPENDED)) { Log(LOG_COMMAND, u, this) << "tried to use GROUP for SUSPENDED nick " << target->nick; - source.Reply(_(NICK_X_SUSPENDED), target->nick.c_str()); + source.Reply(NICK_X_SUSPENDED, target->nick.c_str()); } else if (na && target->nc == na->nc) source.Reply(_("You are already a member of the group of \002%s\002."), target->nick.c_str()); else if (na && na->nc != u->Account()) - source.Reply(_(NICK_IDENTIFY_REQUIRED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + source.Reply(NICK_IDENTIFY_REQUIRED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); else if (na && Config->NSNoGroupChange) - source.Reply(_("Your nick is already registered; type \002%s%s DROP\002 first."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + source.Reply(_("Your nick is already registered.")); else if (Config->NSMaxAliases && (target->nc->aliases.size() >= Config->NSMaxAliases) && !target->nc->IsServicesOper()) - source.Reply(_("There are too many nicks in %s's group; list them and drop some.\n" - "Type \002%s%s HELP GLIST\002 and \002%s%s HELP DROP\002\n" - "for more information."), target->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + source.Reply(_("There are too many nicks in %s's group.")); else { bool ok = false; @@ -83,9 +76,9 @@ class CommandNSGroup : public Command else if (!pass.empty()) { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, target->nc->display, pass)); + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, target->nc->display, pass)); if (MOD_RESULT == EVENT_STOP) - return MOD_CONT; + return; else if (MOD_RESULT == EVENT_ALLOW) ok = true; } @@ -103,8 +96,8 @@ class CommandNSGroup : public Command if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && !u->nick.find_ci(Config->NSGuestNickPrefix) && !u->nick.substr(prefixlen).find_first_not_of("1234567890")) { - source.Reply(_(NICK_CANNOT_BE_REGISTERED), u->nick.c_str()); - return MOD_CONT; + source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); + return; } } @@ -129,18 +122,18 @@ class CommandNSGroup : public Command else { Log(LOG_COMMAND, u, this) << "failed group for " << target->nick; - source.Reply(_(PASSWORD_INCORRECT)); + source.Reply(PASSWORD_INCORRECT); bad_password(u); } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002GROUP \037target\037 \037password\037\002\n" - " \n" - "This command makes your nickname join the \037target\037 nickname's \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command makes your nickname join the \037target\037 nickname's \n" "group. \037password\037 is the password of the target nickname.\n" " \n" "Joining a group will allow you to share your configuration,\n" @@ -152,11 +145,9 @@ class CommandNSGroup : public Command "shared things described above, as long as there is at\n" "least one nick remaining in the group.\n" " \n" - "You can use this command even if you have not registered\n" + "You may be able to use this command even if you have not registered\n" "your nick yet. If your nick is already registered, you'll\n" - "need to identify yourself before using this command. Type\n" - "\037%s%s HELP IDENTIFY\037 for more information. This\n" - "last may be not possible on your IRC network.\n" + "need to identify yourself before using this command.\n" " \n" "It is recommended to use this command with a non-registered\n" "nick because it will be registered automatically when \n" @@ -167,26 +158,21 @@ class CommandNSGroup : public Command "You can only be in one group at a time. Group merging is\n" "not possible.\n" " \n" - "\037Note\037: all the nicknames of a group have the same password."), - Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + "\037Note\037: all the nicknames of a group have the same password.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "GROUP", _("\037target\037 \037password\037")); - } }; class CommandNSUngroup : public Command { public: - CommandNSUngroup() : Command("UNGROUP", 0, 1) + CommandNSUngroup(Module *creator) : Command(creator, "nickserv/ungroup", 0, 1) { this->SetDesc(_("Remove a nick from a group")); + this->SetSyntax(_("[\037nick\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string nick = !params.empty() ? params[0] : ""; @@ -195,7 +181,7 @@ class CommandNSUngroup : public Command if (u->Account()->aliases.size() == 1) source.Reply(_("Your nick is not grouped to anything, you can't ungroup it.")); else if (!na) - source.Reply(_(NICK_X_NOT_REGISTERED), !nick.empty() ? nick.c_str() : u->nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, !nick.empty() ? nick.c_str() : u->nick.c_str()); else if (na->nc != u->Account()) source.Reply(_("The nick %s is not in your group."), na->nick.c_str()); else @@ -224,17 +210,17 @@ class CommandNSUngroup : public Command User *user = finduser(na->nick); if (user) /* The user on the nick who was ungrouped may be identified to the old group, set -r */ - user->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); + user->RemoveMode(findbot(Config->NickServ), UMODE_REGISTERED); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002UNGROUP \037[nick]\037\002\n" - " \n" - "This command ungroups your nick, or if given, the specificed nick,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command ungroups your nick, or if given, the specificed nick,\n" "from the group it is in. The ungrouped nick keeps its registration\n" "time, password, email, greet, language, url, and icq. Everything\n" "else is reset. You may not ungroup yourself if there is only one\n" @@ -246,12 +232,12 @@ class CommandNSUngroup : public Command class CommandNSGList : public Command { public: - CommandNSGList() : Command("GLIST", 0, 1) + CommandNSGList(Module *creator) : Command(creator, "nickserv/glist", 0, 1) { this->SetDesc(_("Lists all nicknames in your group")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string nick = !params.empty() ? params[0] : ""; @@ -259,9 +245,9 @@ class CommandNSGList : public Command const NickCore *nc = u->Account(); if (!nick.empty() && (!nick.equals_ci(u->nick) && !u->IsServicesOper())) - source.Reply(_(ACCESS_DENIED), Config->s_NickServ.c_str()); + source.Reply(ACCESS_DENIED, Config->NickServ.c_str()); else if (!nick.empty() && (!findnick(nick) || !(nc = findnick(nick)->nc))) - source.Reply(nick.empty() ? _(NICK_NOT_REGISTERED) : _(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(nick.empty() ? NICK_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), nick.c_str()); else { source.Reply(!nick.empty() ? _("List of nicknames in the group of \002%s\002:") : _("List of nicknames in your group:"), nc->display.c_str()); @@ -273,25 +259,26 @@ class CommandNSGList : public Command } source.Reply(_("%d nicknames in the group."), nc->aliases.size()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { User *u = source.u; if (u->IsServicesOper()) - source.Reply(_("Syntax: \002GLIST [\037nickname\037]\002\n" + source.Reply(_("Syntax: \002%s [\037nickname\037]\002\n" " \n" "Without a parameter, lists all nicknames that are in\n" "your group.\n" " \n" "With a parameter, lists all nicknames that are in the\n" "group of the given nick.\n" - "This use limited to \002Services Operators\002.")); + "This use limited to \002Services Operators\002."), + source.command.c_str()); else - source.Reply(_("Syntax: \002GLIST\002\n" + source.Reply(_("Syntax: \002%s\002\n" " \n" - "Lists all nicks in your group.")); + "Lists all nicks in your group."), source.command.c_str()); return true; } @@ -304,13 +291,14 @@ class NSGroup : public Module CommandNSGList commandnsglist; public: - NSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsgroup(this), commandnsungroup(this), commandnsglist(this) { this->SetAuthor("Anope"); - this->AddCommand(nickserv->Bot(), &commandnsgroup); - this->AddCommand(nickserv->Bot(), &commandnsungroup); - this->AddCommand(nickserv->Bot(), &commandnsglist); + ModuleManager::RegisterService(&commandnsgroup); + ModuleManager::RegisterService(&commandnsungroup); + ModuleManager::RegisterService(&commandnsglist); } }; diff --git a/modules/core/ns_help.cpp b/modules/core/ns_help.cpp deleted file mode 100644 index 77c1b6f69..000000000 --- a/modules/core/ns_help.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "nickserv.h" - -class CommandNSHelp : public Command -{ - public: - CommandNSHelp() : Command("HELP", 1, 1) - { - this->SetFlag(CFLAG_ALLOW_UNREGISTERED); - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(nickserv->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("\002%s\002 allows you to \"register\" a nickname and\n" - "prevent others from using it. The following\n" - "commands allow for registration and maintenance of\n" - "nicknames; to use them, type \002%s%s \037command\037\002.\n" - "For more information on a specific command, type\n" - "\002%s%s HELP \037command\037\002."), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - for (CommandMap::const_iterator it = nickserv->Bot()->Commands.begin(), it_end = nickserv->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - if (u->IsServicesOper()) - source.Reply(_(" \n" - "Services Operators can also drop any nickname without needing\n" - "to identify for the nick, and may view the access list for\n" - "any nickname (\002%s%s ACCESS LIST \037nick\037\002)."), - Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - if (Config->NSExpire >= 86400) - source.Reply(_("Nicknames that are not used anymore are subject to \n" - "the automatic expiration, i.e. they will be deleted\n" - "after %d days if not used."), Config->NSExpire / 86400); - source.Reply(_(" \n" - "\002NOTICE:\002 This service is intended to provide a way for\n" - "IRC users to ensure their identity is not compromised.\n" - "It is \002NOT\002 intended to facilitate \"stealing\" of\n" - "nicknames or other malicious actions. Abuse of %s\n" - "will result in, at minimum, loss of the abused\n" - "nickname(s)."), Config->s_NickServ.c_str()); - } -}; - -class NSHelp : public Module -{ - CommandNSHelp commandnshelp; - - public: - NSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnshelp); - } -}; - -MODULE_INIT(NSHelp) diff --git a/modules/core/ns_identify.cpp b/modules/core/ns_identify.cpp index 6eb5c7e5c..b0a375cd2 100644 --- a/modules/core/ns_identify.cpp +++ b/modules/core/ns_identify.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSIdentify : public Command { public: - CommandNSIdentify() : Command("IDENTIFY", 1, 2) + CommandNSIdentify(Module *creator) : Command(creator, "nickserv/identify", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Identify yourself with your password")); + this->SetSyntax(_("[\037account\037] \037password\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -32,22 +32,22 @@ class CommandNSIdentify : public Command NickAlias *na = findnick(nick); if (na && na->nc->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); + source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (u->Account() && na && u->Account() == na->nc) source.Reply(_("You are already identified.")); else { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na ? na->nc->display : nick, pass)); + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na ? na->nc->display : nick, pass)); if (MOD_RESULT == EVENT_STOP) - return MOD_CONT; + return; if (!na) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (MOD_RESULT != EVENT_ALLOW) { Log(LOG_COMMAND, u, this) << "and failed to identify"; - source.Reply(_(PASSWORD_INCORRECT)); + source.Reply(PASSWORD_INCORRECT); bad_password(u); } else @@ -60,25 +60,20 @@ class CommandNSIdentify : public Command u->Identify(na); } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002IDENTIFY [account] \037password\037\002\n" - " \n" - "Tells %s that you are really the owner of this\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Tells %s that you are really the owner of this\n" "nick. Many commands require you to authenticate yourself\n" "with this command before you use them. The password\n" "should be the same one you sent with the \002REGISTER\002\n" - "command."), Config->s_NickServ.c_str()); + "command."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "IDENTIFY", _("IDENTIFY [account] \037password\037")); - } }; class NSIdentify : public Module @@ -86,14 +81,12 @@ class NSIdentify : public Module CommandNSIdentify commandnsidentify; public: - NSIdentify(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSIdentify(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsidentify(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsidentify); + ModuleManager::RegisterService(&commandnsidentify); } }; diff --git a/modules/core/ns_info.cpp b/modules/core/ns_info.cpp index 584ea67bf..5c8fd1fcd 100644 --- a/modules/core/ns_info.cpp +++ b/modules/core/ns_info.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSInfo : public Command { @@ -29,13 +28,14 @@ class CommandNSInfo : public Command } } public: - CommandNSInfo() : Command("INFO", 1, 2) + CommandNSInfo(Module *creator) : Command(creator, "nickserv/info", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Displays information about a given nickname")); + this->SetSyntax(_("\037nickname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -48,7 +48,7 @@ class CommandNSInfo : public Command if (nickIsServices(nick, true)) source.Reply(_("Nick \002%s\002 is part of this Network's Services."), nick.c_str()); else - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); } else { @@ -95,7 +95,7 @@ class CommandNSInfo : public Command if (show_hidden) { - if (!Config->s_HostServ.empty() && ircd->vhost && na->hostinfo.HasVhost()) + if (na->hostinfo.HasVhost()) { if (ircd->vident && !na->hostinfo.GetIdent().empty()) source.Reply(_(" vhost: %s@%s"), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); @@ -113,7 +113,7 @@ class CommandNSInfo : public Command CheckOptStr(optbuf, NI_MSG, _("Message mode"), na->nc); CheckOptStr(optbuf, NI_AUTOOP, _("Auto-op"), na->nc); - source.Reply(_(NICK_INFO_OPTIONS), optbuf.empty() ? _("None") : optbuf.c_str()); + source.Reply(NICK_INFO_OPTIONS, optbuf.empty() ? _("None") : optbuf.c_str()); if (na->nc->HasFlag(NI_SUSPENDED)) { @@ -139,24 +139,19 @@ class CommandNSInfo : public Command if (na->nc->HasFlag(NI_UNCONFIRMED)) source.Reply(_("This nickname is unconfirmed.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002INFO \037nickname\037\002\n" - " \n" - "Displays information about the given nickname, such as\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Displays information about the given nickname, such as\n" "the nick's owner, last seen address and time, and nick\n" "options.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "INFO", _("INFO \037nick\037")); - } }; class NSInfo : public Module @@ -164,14 +159,12 @@ class NSInfo : public Module CommandNSInfo commandnsinfo; public: - NSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsinfo(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsinfo); + ModuleManager::RegisterService(&commandnsinfo); } }; diff --git a/modules/core/ns_list.cpp b/modules/core/ns_list.cpp index c4536a613..e14983530 100644 --- a/modules/core/ns_list.cpp +++ b/modules/core/ns_list.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSList : public Command { public: - CommandNSList() : Command("LIST", 1, 2) + CommandNSList(Module *creator) : Command(creator, "nickserv/list", 1, 2) { this->SetDesc(_("List all registered nicknames that match a given pattern")); + this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -38,8 +38,8 @@ class CommandNSList : public Command if (Config->NSListOpersOnly && !u->HasMode(UMODE_OPER)) /* reverse the help logic */ { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } if (pattern[0] == '#') @@ -54,8 +54,8 @@ class CommandNSList : public Command } catch (const ConvertException &) { - source.Reply(_(LIST_INCORRECT_RANGE)); - return MOD_CONT; + source.Reply(LIST_INCORRECT_RANGE); + return; } pattern = "*"; @@ -80,7 +80,7 @@ class CommandNSList : public Command mync = u->Account(); - source.Reply(_(LIST_HEADER), pattern.c_str()); + source.Reply(LIST_HEADER, pattern.c_str()); for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) { NickAlias *na = it->second; @@ -123,68 +123,39 @@ class CommandNSList : public Command source.Reply(_("End of list - %d/%d matches shown."), nnicks > Config->NSListMax ? Config->NSListMax : nnicks, nnicks); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - User *u = source.u; - if (u->IsServicesOper()) - source.Reply(_("Syntax: \002LIST \037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]\002\n" - " \n" - "Lists all registered nicknames which match the given\n" - "pattern, in \037nick!user@host\037 format. Nicks with the \002PRIVATE\002\n" - "option set will only be displayed to Services Operators. Nicks\n" - "with the \002NOEXPIRE\002 option set will have a \002!\002 appended to\n" - "the nickname for Services Operators.\n" - " \n" - "If the SUSPENDED, NOEXPIRE or UNCONFIRMED options are given, only\n" - "nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n" - "NOEXPIRE flag set will be displayed. If multiple options are\n" - "given, all nicks matching at least one option will be displayed.\n" - "These options are limited to \037Services Operators\037. \n" - "Examples:\n" - " \n" - " \002LIST *!joeuser@foo.com\002\n" - " Lists all registered nicks owned by joeuser@foo.com.\n" - " \n" - " \002LIST *Bot*!*@*\002\n" - " Lists all registered nicks with \002Bot\002 in their\n" - " names (case insensitive).\n" - " \n" - " \002LIST * NOEXPIRE\002\n" - " Lists all registered nicks which have been set to\n")); - else - source.Reply(_("Syntax: \002LIST \037pattern\037\002\n" - " \n" - "Lists all registered nicknames which match the given\n" - "pattern, in \037nick!user@host\037 format. Nicks with the\n" - "\002PRIVATE\002 option set will not be displayed.\n" - " \n" - "Examples:\n" - " \n" - " \002LIST *!joeuser@foo.com\002\n" - " Lists all nicks owned by joeuser@foo.com.\n" - " \n" - " \002LIST *Bot*!*@*\002\n" - " Lists all registered nicks with \002Bot\002 in their\n" - " names (case insensitive).\n" - " \n" - " \002LIST *!*@*.bar.org\002\n" - " Lists all nicks owned by users in the \002bar.org\002\n" - " domain.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all registered nicknames which match the given\n" + "pattern, in \037nick!user@host\037 format. Nicks with the \002PRIVATE\002\n" + "option set will only be displayed to Services Operators. Nicks\n" + "with the \002NOEXPIRE\002 option set will have a \002!\002 appended to\n" + "the nickname for Services Operators.\n" + " \n" + "If the SUSPENDED, NOEXPIRE or UNCONFIRMED options are given, only\n" + "nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n" + "NOEXPIRE flag set will be displayed. If multiple options are\n" + "given, all nicks matching at least one option will be displayed.\n" + "These options are limited to \037Services Operators\037. \n" + "\n" + "Examples:\n" + " \n" + " \002LIST *!joeuser@foo.com\002\n" + " Lists all registered nicks owned by joeuser@foo.com.\n" + " \n" + " \002LIST *Bot*!*@*\002\n" + " Lists all registered nicks with \002Bot\002 in their\n" + " names (case insensitive).\n" + " \n" + " \002LIST * NOEXPIRE\002\n" + " Lists all registered nicks which have been set to not expire.\n")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - if (u->IsServicesOper()) - SyntaxError(source, "LIST", _("LIST \037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]")); - else - SyntaxError(source, "LIST", _(NICK_LIST_SYNTAX)); - } }; class NSList : public Module @@ -192,14 +163,12 @@ class NSList : public Module CommandNSList commandnslist; public: - NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnslist(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnslist); + ModuleManager::RegisterService(&commandnslist); } }; diff --git a/modules/core/ns_logout.cpp b/modules/core/ns_logout.cpp index d7e6cc4dc..476330a11 100644 --- a/modules/core/ns_logout.cpp +++ b/modules/core/ns_logout.cpp @@ -17,12 +17,13 @@ class CommandNSLogout : public Command { public: - CommandNSLogout() : Command("LOGOUT", 0, 2) + CommandNSLogout(Module *creator) : Command(creator, "nickserv/logout", 0, 2) { this->SetDesc(_("Reverses the effect of the IDENTIFY command")); + this->SetSyntax(_("[\037nickname\037 [REVALIDATE]]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -33,12 +34,12 @@ class CommandNSLogout : public Command if (!u->IsServicesOper() && !nick.empty()) this->OnSyntaxError(source, ""); else if (!(u2 = (!nick.empty() ? finduser(nick) : u))) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (!nick.empty() && !u2->IsServicesOper()) source.Reply(_("You can't logout %s because they are a Services Operator."), nick.c_str()); else { - if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE")) + if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE") && nickserv) nickserv->Validate(u2); u2->isSuperAdmin = 0; /* Dont let people logout and remain a SuperAdmin */ @@ -51,7 +52,7 @@ class CommandNSLogout : public Command source.Reply(_("Your nick has been logged out.")); ircdproto->SendAccountLogout(u2, u2->Account()); - u2->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); + u2->RemoveMode(source.owner, UMODE_REGISTERED); ircdproto->SendUnregisteredNick(u2); u2->Logout(); @@ -59,38 +60,24 @@ class CommandNSLogout : public Command /* Send out an event */ FOREACH_MOD(I_OnNickLogout, OnNickLogout(u2)); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - User *u = source.u; - if (u->IsServicesOper()) - source.Reply(_("Syntax: \002LOGOUT [\037nickname\037 [REVALIDATE]]\002\n" - " \n" - "Without a parameter, reverses the effect of the \002IDENTIFY\002 \n" - "command, i.e. make you not recognized as the real owner of the nick\n" - "anymore. Note, however, that you won't be asked to reidentify\n" - "yourself.\n" - " \n" - "With a parameter, does the same for the given nick. If you \n" - "specify REVALIDATE as well, Services will ask the given nick\n" - "to re-identify. This use limited to \002Services Operators\002.")); - else - source.Reply(_("Syntax: \002LOGOUT\002\n" - " \n" - "This reverses the effect of the \002IDENTIFY\002 command, i.e.\n" - "make you not recognized as the real owner of the nick\n" - "anymore. Note, however, that you won't be asked to reidentify\n" - "yourself.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Without a parameter, reverses the effect of the \002IDENTIFY\002 \n" + "command, i.e. make you not recognized as the real owner of the nick\n" + "anymore. Note, however, that you won't be asked to reidentify\n" + "yourself.\n" + " \n" + "With a parameter, does the same for the given nick. If you \n" + "specify REVALIDATE as well, Services will ask the given nick\n" + "to re-identify. This use limited to \002Services Operators\002.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LOGOUT", _("LOGOUT")); - } }; class NSLogout : public Module @@ -98,14 +85,12 @@ class NSLogout : public Module CommandNSLogout commandnslogout; public: - NSLogout(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSLogout(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnslogout(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnslogout); + ModuleManager::RegisterService(&commandnslogout); } }; diff --git a/modules/core/ns_main.cpp b/modules/core/ns_main.cpp index f4797fa29..e01d82391 100644 --- a/modules/core/ns_main.cpp +++ b/modules/core/ns_main.cpp @@ -14,18 +14,13 @@ #include "module.h" #include "nickserv.h" -static BotInfo *NickServ = NULL; +static BotInfo *NickServ; class MyNickServService : public NickServService { public: MyNickServService(Module *m) : NickServService(m) { } - BotInfo *Bot() - { - return NickServ; - } - void Validate(User *u) { NickAlias *na = findnick(u->nick); @@ -58,9 +53,9 @@ class MyNickServService : public NickServService if (u->IsRecognized() || !na->nc->HasFlag(NI_KILL_IMMED)) { if (na->nc->HasFlag(NI_SECURE)) - u->SendMessage(NickServ, NICK_IS_SECURE, Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + u->SendMessage(NickServ, NICK_IS_SECURE, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); else - u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); } if (na->nc->HasFlag(NI_KILLPROTECT) && !u->IsRecognized()) @@ -146,32 +141,15 @@ class NickServCore : public Module { this->SetAuthor("Anope"); - Implementation i[] = { I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup, I_OnNickUpdate }; - ModuleManager::Attach(i, this, 6); - - ModuleManager::RegisterService(&this->mynickserv); - - NickServ = new BotInfo(Config->s_NickServ, Config->ServiceUser, Config->ServiceHost, Config->desc_NickServ); - NickServ->SetFlag(BI_CORE); + NickServ = findbot(Config->NickServ); + if (NickServ == NULL) + throw ModuleException("No bot named " + Config->NickServ); - spacesepstream coreModules(Config->NickCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); - } - - ~NickServCore() - { - spacesepstream coreModules(Config->NickCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); - } + Implementation i[] = { I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup, + I_OnNickUpdate, I_OnUserNickChange, I_OnPreHelp, I_OnPostHelp }; + ModuleManager::Attach(i, this, 9); - delete NickServ; + ModuleManager::RegisterService(&this->mynickserv); } void OnDelNick(NickAlias *na) @@ -232,7 +210,7 @@ class NickServCore : public Module "case you forget it.")); u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + "any third-party person."), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); } if (u->Account()->HasFlag(NI_UNCONFIRMED)) @@ -261,6 +239,68 @@ class NickServCore : public Module chan_set_correct_modes(u, c, 1); } } + + void OnUserNickChange(User *u, const Anope::string &oldnick) + { + NickAlias *na = findnick(u->nick); + /* If the new nick isnt registerd or its registerd and not yours */ + if (!na || na->nc != u->Account()) + { + u->RemoveMode(NickServ, UMODE_REGISTERED); + ircdproto->SendUnregisteredNick(u); + + this->mynickserv.Validate(u); + } + else + { + if (na->nc->HasFlag(NI_UNCONFIRMED) == false) + { + u->SetMode(NickServ, UMODE_REGISTERED); + ircdproto->SetAutoIdentificationToken(u); + } + Log(NickServ) << u->GetMask() << " automatically identified for group " << u->Account()->display; + } + } + + void OnUserModeSet(User *u, UserModeName Name) + { + if (Name == UMODE_REGISTERED && !u->IsIdentified()) + u->RemoveMode(NickServ, Name); + } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->NickServ) + return; + source.Reply(_("\002%s\002 allows you to \"register\" a nickname and\n" + "prevent others from using it. The following\n" + "commands allow for registration and maintenance of\n" + "nicknames; to use them, type \002%s%s \037command\037\002.\n" + "For more information on a specific command, type\n" + "\002%s%s %s \037command\037\002.\n "), Config->NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), source.command.c_str()); + } + + void OnPostHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->NickServ) + return; + if (source.u->IsServicesOper()) + source.Reply(_(" \n" + "Services Operators can also drop any nickname without needing\n" + "to identify for the nick, and may view the access list for\n" + "any nickname.")); + if (Config->NSExpire >= 86400) + source.Reply(_("Nicknames that are not used anymore are subject to \n" + "the automatic expiration, i.e. they will be deleted\n" + "after %d days if not used."), Config->NSExpire / 86400); + source.Reply(_(" \n" + "\002NOTICE:\002 This service is intended to provide a way for\n" + "IRC users to ensure their identity is not compromised.\n" + "It is \002NOT\002 intended to facilitate \"stealing\" of\n" + "nicknames or other malicious actions. Abuse of %s\n" + "will result in, at minimum, loss of the abused\n" + "nickname(s)."), Config->NickServ.c_str()); + } }; MODULE_INIT(NickServCore) diff --git a/modules/core/ns_recover.cpp b/modules/core/ns_recover.cpp index b6a8e1c5d..5e45aab9a 100644 --- a/modules/core/ns_recover.cpp +++ b/modules/core/ns_recover.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSRecover : public Command { public: - CommandNSRecover() : Command("RECOVER", 1, 2) + CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Kill another user who has taken your nick")); + this->SetSyntax(_("\037nickname\037 [\037password\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -33,33 +33,33 @@ class CommandNSRecover : public Command NickAlias *na; User *u2; if (!(u2 = finduser(nick))) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (!(na = findnick(u2->nick))) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (na->nc->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); + source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (nick.equals_ci(u->nick)) source.Reply(_("You can't recover yourself!")); else if (!pass.empty()) { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); if (MOD_RESULT == EVENT_STOP) - return MOD_CONT; + return; if (MOD_RESULT == EVENT_ALLOW) { - u2->SendMessage(nickserv->Bot(), FORCENICKCHANGE_NOW); + u2->SendMessage(source.owner, FORCENICKCHANGE_NOW); u2->Collide(na); /* Convert Config->NSReleaseTimeout seconds to string format */ Anope::string relstr = duration(Config->NSReleaseTimeout); - source.Reply(_(NICK_RECOVERED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), nick.c_str(), relstr.c_str()); + source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), nick.c_str(), relstr.c_str()); } else { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); Log(LOG_COMMAND, u, this) << "with invalid password for " << nick; bad_password(u); } @@ -69,18 +69,18 @@ class CommandNSRecover : public Command if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc)) || (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) { - u2->SendMessage(nickserv->Bot(), FORCENICKCHANGE_NOW); + u2->SendMessage(source.owner, FORCENICKCHANGE_NOW); u2->Collide(na); /* Convert Config->NSReleaseTimeout seconds to string format */ Anope::string relstr = duration(Config->NSReleaseTimeout); - source.Reply(_(NICK_RECOVERED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), nick.c_str(), relstr.c_str()); + source.Reply(NICK_RECOVERED, Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), nick.c_str(), relstr.c_str()); } else - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -88,9 +88,9 @@ class CommandNSRecover : public Command /* Convert Config->NSReleaseTimeout seconds to string format */ Anope::string relstr = duration(Config->NSReleaseTimeout); - source.Reply(_("Syntax: \002RECOVER \037nickname\037 [\037password\037]\002\n" - " \n" - "Allows you to recover your nickname if someone else has\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to recover your nickname if someone else has\n" "taken it; this does the same thing that %s does\n" "automatically if someone tries to use a kill-protected\n" "nick.\n" @@ -109,15 +109,10 @@ class CommandNSRecover : public Command "current address as shown in /WHOIS must be on that nick's\n" "access list, you must be identified and in the group of\n" "that nick, or you must supply the correct password for\n" - "the nickname."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str(), relstr.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + "the nickname."), Config->NickServ.c_str(), Config->NickServ.c_str(), relstr.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "RECOVER", _("RECOVER \037nickname\037 [\037password\037]")); - } }; class NSRecover : public Module @@ -125,14 +120,12 @@ class NSRecover : public Module CommandNSRecover commandnsrecover; public: - NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsrecover(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsrecover); + ModuleManager::RegisterService(&commandnsrecover); } }; diff --git a/modules/core/ns_register.cpp b/modules/core/ns_register.cpp index 900e78f7c..552551994 100644 --- a/modules/core/ns_register.cpp +++ b/modules/core/ns_register.cpp @@ -12,20 +12,20 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" -static bool SendRegmail(User *u, NickAlias *na); +static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi); class CommandNSConfirm : public Command { public: - CommandNSConfirm() : Command("CONFIRM", 1, 2) + CommandNSConfirm(Module *creator) : Command(creator, "nickserv/confirm", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Confirm an auth code")); + this->SetSyntax(_("\037passcode\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &passcode = params[0]; @@ -34,7 +34,7 @@ class CommandNSConfirm : public Command { NickAlias *na = findnick(passcode); if (na == NULL) - source.Reply(_(NICK_X_NOT_REGISTERED), passcode.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, passcode.c_str()); else if (na->nc->HasFlag(NI_UNCONFIRMED) == false) source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str()); else @@ -56,7 +56,7 @@ class CommandNSConfirm : public Command ircdproto->SendAccountLogin(u, u->Account()); NickAlias *na = findnick(u->nick); if (na && na->nc == u->Account()) - u->SetMode(nickserv->Bot(), UMODE_REGISTERED); + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else source.Reply(_("Invalid passcode.")); @@ -64,15 +64,15 @@ class CommandNSConfirm : public Command else source.Reply(_("Invalid passcode.")); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { User *u = source.u; - source.Reply(_("Syntax: \002CONFIRM \037passcode\037\002\n" - " \n" - "This command is used by several commands as a way to confirm\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command is used by several commands as a way to confirm\n" "changes made to your account.\n" " \n" "This is most commonly used to confirm your email address once\n" @@ -88,20 +88,24 @@ class CommandNSConfirm : public Command void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_(NICK_CONFIRM_INVALID)); + source.Reply(NICK_CONFIRM_INVALID); } }; class CommandNSRegister : public Command { public: - CommandNSRegister() : Command("REGISTER", 1, 2) + CommandNSRegister(Module *creator) : Command(creator, "nickserv/register", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Register a nickname")); + if (Config->NSForceEmail) + this->SetSyntax(_("\037password\037 \037email\037")); + else + this->SetSyntax(_("\037password\037 \037[email]\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na; @@ -113,13 +117,13 @@ class CommandNSRegister : public Command if (readonly) { source.Reply(_("Sorry, nickname registration is temporarily disabled.")); - return MOD_CONT; + return; } if (!u->HasMode(UMODE_OPER) && Config->NickRegDelay && Anope::CurTime - u->my_signon < Config->NickRegDelay) { source.Reply(_("You must have been using this nick for at least %d seconds to register."), Config->NickRegDelay); - return MOD_CONT; + return; } /* Prevent "Guest" nicks from being registered. -TheShadow */ @@ -129,8 +133,8 @@ class CommandNSRegister : public Command */ if (nicklen <= prefixlen + 7 && nicklen >= prefixlen + 1 && !u->nick.find_ci(Config->NSGuestNickPrefix) && u->nick.substr(prefixlen).find_first_not_of("1234567890") == Anope::string::npos) { - source.Reply(_(NICK_CANNOT_BE_REGISTERED), u->nick.c_str()); - return MOD_CONT; + source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); + return; } if (Config->RestrictOperNicks) @@ -140,8 +144,8 @@ class CommandNSRegister : public Command if (!u->HasMode(UMODE_OPER) && u->nick.find_ci(o->name) != Anope::string::npos) { - source.Reply(_(NICK_CANNOT_BE_REGISTERED), u->nick.c_str()); - return MOD_CONT; + source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); + return; } } @@ -150,13 +154,13 @@ class CommandNSRegister : public Command else if (Anope::CurTime < u->lastnickreg + Config->NSRegDelay) source.Reply(_("Please wait %d seconds before using the REGISTER command again."), (u->lastnickreg + Config->NSRegDelay) - Anope::CurTime); else if ((na = findnick(u->nick))) - source.Reply(_(NICK_ALREADY_REGISTERED), u->nick.c_str()); + source.Reply(NICK_ALREADY_REGISTERED, u->nick.c_str()); else if (pass.equals_ci(u->nick) || (Config->StrictPasswords && pass.length() < 5)) - source.Reply(_(MORE_OBSCURE_PASSWORD)); + source.Reply(MORE_OBSCURE_PASSWORD); else if (pass.length() > Config->PassLen) - source.Reply(_(PASSWORD_TOO_LONG)); + source.Reply(PASSWORD_TOO_LONG); else if (!email.empty() && !MailValidate(email)) - source.Reply(_(MAIL_X_INVALID), email.c_str()); + source.Reply(MAIL_X_INVALID, email.c_str()); else { na = new NickAlias(u->nick, new NickCore(u->nick)); @@ -188,9 +192,9 @@ class CommandNSRegister : public Command if (Config->NSEmailReg) { na->nc->SetFlag(NI_UNCONFIRMED); - if (SendRegmail(u, na)) + if (SendRegmail(u, na, source.owner)) { - source.Reply(_("A passcode has been sent to %s, please type %s%s confirm <passcode> to confirm your email address."), email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + source.Reply(_("A passcode has been sent to %s, please type %s%s confirm <passcode> to confirm your email address."), email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); source.Reply(_("If you do not confirm your email address within %s your account will expire."), duration(Config->NSUnconfirmedExpire).c_str()); } } @@ -201,14 +205,14 @@ class CommandNSRegister : public Command u->lastnickreg = Anope::CurTime; } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002REGISTER \037password\037 \037[email]\037\002\n" - " \n" - "Registers your nickname in the %s database. Once\n" + this->SendSyntax(source); + source.Reply("\n"); + source.Reply(_("Registers your nickname in the %s database. Once\n" "your nick is registered, you can use the \002SET\002 and \002ACCESS\002\n" "commands to configure your nick's settings as you like\n" "them. Make sure you remember the password you use when\n" @@ -225,57 +229,49 @@ class CommandNSRegister : public Command "passwords are vulnerable to trial-and-error searches, so\n" "you should choose a password at least 5 characters long.\n" "Finally, the space character cannot be used in passwords.\n"), - Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); - - source.Reply(_(" \n" - "The parameter \037email\037 is optional and will set the email\n" - "for your nick immediately. However, it may be required\n" - "on certain networks.\n" - "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person.\n" - " \n" - "This command also creates a new group for your nickname,\n" + Config->NickServ.c_str(), Config->NickServ.c_str()); + + if (!Config->NSForceEmail) + source.Reply(_(" \n" + "The parameter \037email\037 is optional and will set the email\n" + "for your nick immediately.\n" + "Your privacy is respected; this e-mail won't be given to\n" + "any third-party person.\n" + " \n")); + + source.Reply(_("This command also creates a new group for your nickname,\n" "that will allow you to register other nicks later sharing\n" "the same configuration, the same set of memos and the\n" - "same channel privileges. For more information on this\n" - "feature, type \002%s%s HELP GROUP\002."), - Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + "same channel privileges.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - if (Config->NSForceEmail) - SyntaxError(source, "REGISTER", _("\037password\037 \037email\037")); - else - SyntaxError(source, "REGISTER", _("\037password\037 [\037email\037]")); - } }; class CommandNSResend : public Command { public: - CommandNSResend() : Command("RESEND", 0, 0) + CommandNSResend(Module *creator) : Command(creator, "nickserv/resend", 0, 0) { + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { if (!Config->NSEmailReg) - return MOD_CONT; + return; User *u = source.u; NickAlias *na = findnick(u->nick); if (na == NULL) - source.Reply(_(NICK_NOT_REGISTERED)); + source.Reply(NICK_NOT_REGISTERED); else if (na->nc != u->Account() || u->Account()->HasFlag(NI_UNCONFIRMED) == false) source.Reply(_("Your account is already confirmed.")); else { if (Anope::CurTime < u->Account()->lastmail + Config->NSResendDelay) source.Reply(_("Cannot send mail now; please retry a little later.")); - else if (!SendRegmail(u, na)) + else if (!SendRegmail(u, na, source.owner)) { na->nc->lastmail = Anope::CurTime; source.Reply(_("Your passcode has been re-sent to %s."), na->nc->email.c_str()); @@ -285,7 +281,7 @@ class CommandNSResend : public Command Log() << "Unable to resend registration verification code for " << u->nick; } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -293,9 +289,9 @@ class CommandNSResend : public Command if (!Config->NSEmailReg) return false; - source.Reply(_("Syntax: \002RESEND\002\n" - " \n" - "This command will re-send the auth code (also called passcode)\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command will re-send the auth code (also called passcode)\n" "to the e-mail address of the user whom is performing it.")); return true; } @@ -314,20 +310,18 @@ class NSRegister : public Module CommandNSResend commandnsrsend; public: - NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsregister(this), commandnsconfirm(this), commandnsrsend(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsregister); - this->AddCommand(nickserv->Bot(), &commandnsconfirm); - this->AddCommand(nickserv->Bot(), &commandnsrsend); + ModuleManager::RegisterService(&commandnsregister); + ModuleManager::RegisterService(&commandnsconfirm); + ModuleManager::RegisterService(&commandnsrsend); } }; -static bool SendRegmail(User *u, NickAlias *na) +static bool SendRegmail(User *u, NickAlias *na, BotInfo *bi) { Anope::string code; if (na->nc->GetExtRegular<Anope::string>("ns_register_passcode", code) == false) @@ -353,9 +347,9 @@ static bool SendRegmail(User *u, NickAlias *na) " \n" "If you don't know why this mail was sent to you, please ignore it silently.\n" " \n" - "%s administrators."), na->nick.c_str(), Config->NetworkName.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); + "%s administrators."), na->nick.c_str(), Config->NetworkName.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); - return Mail(u, na->nc, nickserv->Bot(), subject, message); + return Mail(u, na->nc, bi, subject, message); } MODULE_INIT(NSRegister) diff --git a/modules/core/ns_release.cpp b/modules/core/ns_release.cpp index c22efebad..20a3e295c 100644 --- a/modules/core/ns_release.cpp +++ b/modules/core/ns_release.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSRelease : public Command { public: - CommandNSRelease() : Command("RELEASE", 1, 2) + CommandNSRelease(Module *creator) : Command(creator, "nickserv/release", 1, 2) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Regain custody of your nick after RECOVER")); + this->SetSyntax(_("\037nickname\037 [\037password\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; @@ -31,17 +31,17 @@ class CommandNSRelease : public Command NickAlias *na; if (!(na = findnick(nick))) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else if (na->nc->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); + source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); else if (!na->HasFlag(NS_HELD)) source.Reply(_("Nick \002%s\002 isn't being held."), nick.c_str()); else if (!pass.empty()) { EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(u, this, params, na->nc->display, pass)); + FOREACH_RESULT(I_OnCheckAuthentication, OnCheckAuthentication(this, &source, params, na->nc->display, pass)); if (MOD_RESULT == EVENT_STOP) - return MOD_CONT; + return; if (MOD_RESULT == EVENT_ALLOW) { @@ -51,7 +51,7 @@ class CommandNSRelease : public Command } else { - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); Log(LOG_COMMAND, u, this) << "invalid password for " << nick; bad_password(u); } @@ -65,9 +65,9 @@ class CommandNSRelease : public Command source.Reply(_("Services' hold on your nick has been released.")); } else - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -75,9 +75,9 @@ class CommandNSRelease : public Command /* Convert Config->NSReleaseTimeout seconds to string format */ Anope::string relstr = duration(Config->NSReleaseTimeout); - source.Reply(_("Syntax: \002RELEASE \037nickname\037 [\037password\037]\002\n" - " \n" - "Instructs %s to remove any hold on your nickname\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Instructs %s to remove any hold on your nickname\n" "caused by automatic kill protection or use of the \002RECOVER\002\n" "command. This holds lasts for %s;\n" "This command gets rid of them sooner.\n" @@ -86,16 +86,11 @@ class CommandNSRelease : public Command "current address as shown in /WHOIS must be on that nick's\n" "access list, you must be identified and in the group of\n" "that nick, or you must supply the correct password for\n" - "the nickname."), Config->s_NickServ.c_str(), relstr.c_str()); + "the nickname."), Config->NickServ.c_str(), relstr.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "RELEASE", _("RELEASE \037nickname\037 [\037password\037]")); - } }; class NSRelease : public Module @@ -103,14 +98,12 @@ class NSRelease : public Module CommandNSRelease commandnsrelease; public: - NSRelease(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSRelease(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsrelease(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsrelease); + ModuleManager::RegisterService(&commandnsrelease); } }; diff --git a/modules/core/ns_resetpass.cpp b/modules/core/ns_resetpass.cpp index 55b4ae18b..b0d40226f 100644 --- a/modules/core/ns_resetpass.cpp +++ b/modules/core/ns_resetpass.cpp @@ -12,52 +12,48 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" -static bool SendResetEmail(User *u, NickAlias *na); +static bool SendResetEmail(User *u, NickAlias *na, BotInfo *bi); class CommandNSResetPass : public Command { public: - CommandNSResetPass() : Command("RESETPASS", 1, 1) + CommandNSResetPass(Module *creator) : Command(creator, "nickserv/resetpass", 1, 1) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Helps you reset lost passwords")); + this->SetSyntax(_("\037nickname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na; - if (Config->RestrictMail && (!u->Account() || !u->HasCommand("nickserv/resetpass"))) - source.Reply(_(ACCESS_DENIED)); + if (Config->RestrictMail && (!u->Account() || !u->HasCommand("nickserv/nickserv/resetpass"))) + source.Reply(ACCESS_DENIED); else if (!(na = findnick(params[0]))) - source.Reply(_(NICK_X_NOT_REGISTERED), params[0].c_str()); + source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); else { - if (SendResetEmail(u, na)) + if (SendResetEmail(u, na, source.owner)) { Log(LOG_COMMAND, u, this) << "for " << na->nick << " (group: " << na->nc->display << ")"; source.Reply(_("Password reset email for \002%s\002 has been sent."), na->nick.c_str()); } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002RESETPASS \037nickname\037\002\n" - "Sends a code key to the nickname with instructions on how to\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sends a code key to the nickname with instructions on how to\n" "reset their password.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "RESETPASS", _("RESETPASS \037nickname\037\002")); - } }; class NSResetPass : public Module @@ -65,26 +61,24 @@ class NSResetPass : public Module CommandNSResetPass commandnsresetpass; public: - NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsresetpass(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - if (!Config->UseMail) throw ModuleException("Not using mail."); - this->AddCommand(nickserv->Bot(), &commandnsresetpass); + ModuleManager::RegisterService(&commandnsresetpass); ModuleManager::Attach(I_OnPreCommand, this); } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { - User *u = source.u; - if (command->service->nick == Config->s_NickServ && command->name.equals_ci("CONFIRM") && params.size() > 1) + if (command->name == "nickserv/confirm" && params.size() > 1) { + User *u = source.u; NickAlias *na = findnick(params[0]); time_t t; @@ -108,7 +102,7 @@ class NSResetPass : public Module na->nc->UnsetFlag(NI_UNCONFIRMED); u->Identify(na); - source.Reply(_("You are now identified for your nick. Change your password using \"%s%s SET PASSWORD \002newpassword\002\" now."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + source.Reply(_("You are now identified for your nick. Change your passwor now.")); } else @@ -122,7 +116,7 @@ class NSResetPass : public Module } }; -static bool SendResetEmail(User *u, NickAlias *na) +static bool SendResetEmail(User *u, NickAlias *na, BotInfo *bi) { int min = 1, max = 62; int chars[] = { @@ -147,12 +141,12 @@ static bool SendResetEmail(User *u, NickAlias *na) " \n" "If you don't know why this mail was sent to you, please ignore it silently.\n" " \n" - "%s administrators.")), na->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), na->nick.c_str(), passcode.c_str(), Config->NetworkName.c_str()); + "%s administrators.")), na->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), na->nick.c_str(), passcode.c_str(), Config->NetworkName.c_str()); na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<Anope::string>(passcode)); na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(Anope::CurTime)); - return Mail(u, na->nc, nickserv->Bot(), subject, message); + return Mail(u, na->nc, bi, subject, message); } MODULE_INIT(NSResetPass) diff --git a/modules/core/ns_saset.cpp b/modules/core/ns_saset.cpp index c8915c38b..b3f732176 100644 --- a/modules/core/ns_saset.cpp +++ b/modules/core/ns_saset.cpp @@ -12,216 +12,141 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSASet : public Command { - typedef std::map<Anope::string, Command *, std::less<ci::string> > subcommand_map; - subcommand_map subcommands; - public: - CommandNSSASet() : Command("SASET", 2, 4) + CommandNSSASet(Module *creator) : Command(creator, "nickserv/saset", 2, 4) { this->SetDesc(_("Set SET-options on another nickname")); + this->SetSyntax(_("\037option\037 \037nickname\037 \037parameters\037")); } - ~CommandNSSASet() + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - this->subcommands.clear(); + this->OnSyntaxError(source, ""); + return; } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - User *u = source.u; - const Anope::string &nick = params[0]; - const Anope::string &cmd = params[1]; - - if (readonly) - { - source.Reply(_(NICK_SET_DISABLED)); - return MOD_CONT; - } - - NickAlias *na = findnick(nick); - if (!na) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); - else if (na->nc->HasFlag(NI_SUSPENDED)) - source.Reply(_(NICK_X_SUSPENDED), na->nick.c_str()); - else + this->SendSyntax(source); + source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); + Anope::string this_name = source.command; + for (command_map::iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) { - Command *c = this->FindCommand(params[1]); - - if (c) + if (it->first.find_ci(this_name + " ") == 0) { - Anope::string cmdparams = na->nick; - for (std::vector<Anope::string>::const_iterator it = params.begin() + 2; it != params.end(); ++it) - cmdparams += " " + *it; - /* Don't log the whole message for saset password */ - if (c->name != "PASSWORD") - Log(LOG_ADMIN, u, this) << params[1] << " " << cmdparams; - else - Log(LOG_ADMIN, u, this) << params[1] << " for " << params[0]; - mod_run_cmd(nickserv->Bot(), u, NULL, c, params[1], cmdparams); + service_reference<Command> command(it->second); + if (command) + { + source.command = it->first; + command->OnServHelp(source); + } } - else - source.Reply(_("Unknown SASET option \002%s\002."), cmd.c_str()); - } - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - if (subcommand.empty()) - { - source.Reply(_("Syntax: \002SASET \037nickname\037 \037option\037 \037parameters\037\002.\n" - " \n" - "Sets various nickname options. \037option\037 can be one of:")); - for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) - it->second->OnServHelp(source); - source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information\n" - "on a specific option. The options will be set on the given\n" - "\037nickname\037."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - return true; - } - else - { - Command *c = this->FindCommand(subcommand); - - if (c) - return c->OnHelp(source, subcommand); } - - return false; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SASET", _(NICK_SASET_SYNTAX)); - } - - bool AddSubcommand(Module *creator, Command *c) - { - c->module = creator; - c->service = this->service; - return this->subcommands.insert(std::make_pair(c->name, c)).second; - } - - bool DelSubcommand(Command *c) - { - return this->subcommands.erase(c->name); - } - - Command *FindCommand(const Anope::string &subcommand) - { - subcommand_map::const_iterator it = this->subcommands.find(subcommand); - - if (it != this->subcommands.end()) - return it->second; - - return NULL; + source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information\n" + "on a specific option. The options will be set on the given\n" + "\037nickname\037."), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str()); + return true; } }; class CommandNSSASetDisplay : public Command { public: - CommandNSSASetDisplay() : Command("DISPLAY", 2, 2, "nickserv/saset/display") + CommandNSSASetDisplay(Module *creator) : Command(creator, "nickserv/saset/display", 2, 2, "nickserv/saset/display") { this->SetDesc(_("Set the display of the group in Services")); + this->SetSyntax(_("\037nickname\037 \037new-display\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { NickAlias *setter_na = findnick(params[0]); - if (!setter_na) - throw CoreException("NULL na in CommandNSSASetDisplay"); + if (setter_na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); + return; + } NickCore *nc = setter_na->nc; NickAlias *na = findnick(params[1]); if (!na || na->nc != nc) { - source.Reply(_(NICK_SASET_DISPLAY_INVALID), nc->display.c_str()); - return MOD_CONT; + source.Reply(_("The new display for \002%s\002 MUST be a nickname of the nickname group!"), nc->display.c_str()); + return; } change_core_display(nc, params[1]); - source.Reply(_(NICK_SET_DISPLAY_CHANGED), nc->display.c_str()); - return MOD_CONT; + source.Reply(NICK_SET_DISPLAY_CHANGED, nc->display.c_str()); + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 DISPLAY \037new-display\037\002\n" - " \n" - "Changes the display used to refer to the nickname group in \n" + this->SendSyntax(source); + source.Reply(_("Changes the display used to refer to the nickname group in \n" "Services. The new display MUST be a nick of the group.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SASET", _(NICK_SASET_SYNTAX)); - } }; class CommandNSSASetPassword : public Command { public: - CommandNSSASetPassword() : Command("PASSWORD", 2, 2, "nickserv/saset/password") + CommandNSSASetPassword(Module *creator) : Command(creator, "nickserv/saset/password", 2, 2, "nickserv/saset/password") { this->SetDesc(_("Set the nickname password")); + this->SetSyntax(_("\037nickname\037 \037new-password\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *setter_na = findnick(params[0]); - if (!setter_na) - throw CoreException("NULL na in CommandNSSASetPassword"); + if (setter_na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); + return; + } NickCore *nc = setter_na->nc; size_t len = params[1].length(); if (Config->NSSecureAdmins && u->Account() != nc && nc->IsServicesOper()) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } else if (nc->display.equals_ci(params[1]) || (Config->StrictPasswords && len < 5)) { - source.Reply(_(MORE_OBSCURE_PASSWORD)); - return MOD_CONT; + source.Reply(MORE_OBSCURE_PASSWORD); + return; } else if (len > Config->PassLen) { - source.Reply(_(PASSWORD_TOO_LONG)); - return MOD_CONT; + source.Reply(PASSWORD_TOO_LONG); + return; } enc_encrypt(params[1], nc->pass); Anope::string tmp_pass; if (enc_decrypt(nc->pass, tmp_pass) == 1) - source.Reply(_(NICK_SASET_PASSWORD_CHANGED_TO), nc->display.c_str(), tmp_pass.c_str()); + source.Reply(_("Password for \002%s\002 changed to \002%s\002."), nc->display.c_str(), tmp_pass.c_str()); else - source.Reply(_(NICK_SASET_PASSWORD_CHANGED), nc->display.c_str()); + source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 PASSWORD \037new-password\037\002\n" - " \n" - "Changes the password used to identify as the nick's owner.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the password used to identify as the nick's owner.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET", _(NICK_SASET_SYNTAX)); - } }; class NSSASet : public Module @@ -231,17 +156,14 @@ class NSSASet : public Module CommandNSSASetPassword commandnssasetpassword; public: - NSSASet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSASet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssaset(this), commandnssasetdisplay(this), commandnssasetpassword(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnssaset); - - commandnssaset.AddSubcommand(this, &commandnssasetdisplay); - commandnssaset.AddSubcommand(this, &commandnssasetpassword); + ModuleManager::RegisterService(&commandnssaset); + ModuleManager::RegisterService(&commandnssasetdisplay); + ModuleManager::RegisterService(&commandnssasetpassword); } }; diff --git a/modules/core/ns_saset_noexpire.cpp b/modules/core/ns_saset_noexpire.cpp index 0dbee1e29..26da7786f 100644 --- a/modules/core/ns_saset_noexpire.cpp +++ b/modules/core/ns_saset_noexpire.cpp @@ -12,21 +12,24 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSASetNoexpire : public Command { public: - CommandNSSASetNoexpire() : Command("NOEXPIRE", 1, 2, "nickserv/saset/noexpire") + CommandNSSASetNoexpire(Module *creator) : Command(creator, "nickserv/saset/noexpire", 1, 2, "nickserv/saset/noexpire") { this->SetDesc(_("Prevent the nickname from expiring")); + this->SetSyntax(_("\037nickname\037 {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { NickAlias *na = findnick(params[0]); - if (!na) - throw CoreException("NULL na in CommandNSSASsetNoexpire"); + if (na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); + return; + } Anope::string param = params.size() > 1 ? params[1] : ""; @@ -43,22 +46,17 @@ class CommandNSSASetNoexpire : public Command else this->OnSyntaxError(source, "NOEXPIRE"); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 NOEXPIRE {ON | OFF}\002\n" - " \n" - "Sets whether the given nickname will expire. Setting this\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets whether the given nickname will expire. Setting this\n" "to \002ON\002 prevents the nickname from expiring.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET NOEXPIRE", _("SASET \037nickname\037 NOEXPIRE {ON | OFF}")); - } }; class NSSASetNoexpire : public Module @@ -66,23 +64,12 @@ class NSSASetNoexpire : public Module CommandNSSASetNoexpire commandnssasetnoexpire; public: - NSSASetNoexpire(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSASetNoexpire(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssasetnoexpire(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetnoexpire); - } - - ~NSSASetNoexpire() - { - Command *c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetnoexpire); + ModuleManager::RegisterService(&commandnssasetnoexpire); } }; diff --git a/modules/core/ns_sendpass.cpp b/modules/core/ns_sendpass.cpp index d1d47df84..ca185c68b 100644 --- a/modules/core/ns_sendpass.cpp +++ b/modules/core/ns_sendpass.cpp @@ -12,35 +12,35 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" -static bool SendPassMail(User *u, NickAlias *na, const Anope::string &pass); +static bool SendPassMail(User *u, NickAlias *na, BotInfo *bi, const Anope::string &pass); class CommandNSSendPass : public Command { public: - CommandNSSendPass() : Command("SENDPASS", 1, 1) + CommandNSSendPass(Module *creator) : Command(creator, "nickserv/sendpass", 1, 1) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Forgot your password? Try this")); + this->SetSyntax(_("\037nickname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; NickAlias *na; if (Config->RestrictMail && (!u->Account() || !u->HasCommand("nickserv/sendpass"))) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (!(na = findnick(nick))) - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); else { Anope::string tmp_pass; if (enc_decrypt(na->nc->pass, tmp_pass) == 1) { - if (SendPassMail(u, na, tmp_pass)) + if (SendPassMail(u, na, source.owner, tmp_pass)) { Log(Config->RestrictMail ? LOG_ADMIN : LOG_COMMAND, u, this) << "for " << na->nick; source.Reply(_("Password of \002%s\002 has been sent."), nick.c_str()); @@ -50,25 +50,20 @@ class CommandNSSendPass : public Command source.Reply(_("SENDPASS command unavailable because encryption is in use.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SENDPASS \037nickname\037\002\n" - " \n" - "Send the password of the given nickname to the e-mail address\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Send the password of the given nickname to the e-mail address\n" "set in the nickname record. This command is really useful\n" "to deal with lost passwords.\n" " \n" "May be limited to \002IRC operators\002 on certain networks.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SENDPASS", _("SENDPASS \037nickname\037")); - } }; class NSSendPass : public Module @@ -76,25 +71,23 @@ class NSSendPass : public Module CommandNSSendPass commandnssendpass; public: - NSSendPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSendPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssendpass(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - if (!Config->UseMail) - throw ModuleException("Not using mail, whut."); + throw ModuleException("Not using mail."); Anope::string tmp_pass = "plain:tmp"; if (enc_decrypt(tmp_pass, tmp_pass) == -1) throw ModuleException("Incompatible with the encryption module being used"); - this->AddCommand(nickserv->Bot(), &commandnssendpass); + ModuleManager::RegisterService(&commandnssendpass); } }; -static bool SendPassMail(User *u, NickAlias *na, const Anope::string &pass) +static bool SendPassMail(User *u, NickAlias *na, BotInfo *bi, const Anope::string &pass) { char subject[BUFSIZE], message[BUFSIZE]; @@ -109,7 +102,7 @@ static bool SendPassMail(User *u, NickAlias *na, const Anope::string &pass) " \n" "%s administrators.")), na->nick.c_str(), pass.c_str(), Config->NetworkName.c_str()); - return Mail(u, na->nc, nickserv->Bot(), subject, message); + return Mail(u, na->nc, bi, subject, message); } MODULE_INIT(NSSendPass) diff --git a/modules/core/ns_set.cpp b/modules/core/ns_set.cpp index ed234e4ba..8a419153f 100644 --- a/modules/core/ns_set.cpp +++ b/modules/core/ns_set.cpp @@ -12,165 +12,91 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSet : public Command { - typedef std::map<Anope::string, Command *, std::less<ci::string> > subcommand_map; - subcommand_map subcommands; - public: - CommandNSSet() : Command("SET", 1, 3) + CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3) { this->SetDesc(_("Set options, including kill protection")); + this->SetSyntax(_("\037option\037 \037parameters\037")); } - ~CommandNSSet() + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - this->subcommands.clear(); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (readonly) - { - source.Reply(_(NICK_SET_DISABLED)); - return MOD_CONT; - } - - if (u->Account()->HasFlag(NI_SUSPENDED)) - { - source.Reply(_(NICK_X_SUSPENDED), u->Account()->display.c_str()); - return MOD_CONT; - } - - Command *c = this->FindCommand(params[0]); - - if (c) - { - Anope::string cmdparams = u->Account()->display; - for (std::vector<Anope::string>::const_iterator it = params.begin() + 1, it_end = params.end(); it != it_end; ++it) - cmdparams += " " + *it; - /* Don't log the whole message for set password */ - if (c->name != "PASSWORD") - Log(LOG_COMMAND, u, this) << params[0] << " " << cmdparams; - else - Log(LOG_COMMAND, u, this) << params[0]; - mod_run_cmd(nickserv->Bot(), u, NULL, c, params[0], cmdparams); - } - else - source.Reply(_(NICK_SET_UNKNOWN_OPTION), Config->UseStrictPrivMsgString.c_str(), params[0].c_str()); - - return MOD_CONT; + this->OnSyntaxError(source, ""); + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - if (subcommand.empty()) + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); + Anope::string this_name = source.command; + for (command_map::iterator it = source.owner->commands.begin(), it_end = source.owner->commands.end(); it != it_end; ++it) { - source.Reply(_("Syntax: \002SET \037option\037 \037parameters\037\002\n" - " \n" - "Sets various nickname options. \037option\037 can be one of:")); - for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) - it->second->OnServHelp(source); - source.Reply(_("In order to use this command, you must first identify\n" - "with your password (\002%s%s HELP IDENTIFY\002 for more\n" - "information).\n" - " \n" - "Type \002%s%s HELP SET \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), (Config->UseStrictPrivMsg ? "/msg " : "/"), Config->s_NickServ.c_str()); - return true; + if (it->first.find_ci(this_name + " ") == 0) + { + service_reference<Command> command(it->second); + if (command) + { + source.command = it->first; + command->OnServHelp(source); + } + } } - else - { - Command *c = this->FindCommand(subcommand); - - if (c) - return c->OnHelp(source, subcommand); - } - - return false; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SET", _(NICK_SET_SYNTAX)); - } - - bool AddSubcommand(Module *creator, Command *c) - { - c->module = creator; - c->service = this->service; - return this->subcommands.insert(std::make_pair(c->name, c)).second; - } - - bool DelSubcommand(const Anope::string &command) - { - return this->subcommands.erase(command); - } - - Command *FindCommand(const Anope::string &subcommand) - { - subcommand_map::const_iterator it = this->subcommands.find(subcommand); - - if (it != this->subcommands.end()) - return it->second; - - return NULL; + source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); + return true; } }; class CommandNSSetDisplay : public Command { public: - CommandNSSetDisplay() : Command("DISPLAY", 2) + CommandNSSetDisplay(Module *creator) : Command(creator, "nickserv/set/display", 1) { this->SetDesc(_("Set the display of your group in Services")); + this->SetSyntax(_("\037new-display\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na = findnick(params[1]); if (!na || na->nc != u->Account()) { - source.Reply(_(NICK_SASET_DISPLAY_INVALID), u->Account()->display.c_str()); - return MOD_CONT; + source.Reply(_("The new display MUST be a nickname of your nickname group!")); + return; } change_core_display(u->Account(), params[1]); - source.Reply(_(NICK_SET_DISPLAY_CHANGED), u->Account()->display.c_str()); - return MOD_CONT; + source.Reply(NICK_SET_DISPLAY_CHANGED, u->Account()->display.c_str()); + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET DISPLAY \037new-display\037\002\n" - " \n" - "Changes the display used to refer to your nickname group in \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the display used to refer to your nickname group in \n" "Services. The new display MUST be a nick of your group.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(NICK_SET_SYNTAX)); - } }; class CommandNSSetPassword : public Command { public: - CommandNSSetPassword() : Command("PASSWORD", 2) + CommandNSSetPassword(Module *creator) : Command(creator, "nickserv/set/password", 1) { this->SetDesc(_("Set your nickname password")); + this->SetSyntax(_("\037new-password\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -179,39 +105,33 @@ class CommandNSSetPassword : public Command if (u->Account()->display.equals_ci(param) || (Config->StrictPasswords && len < 5)) { - source.Reply(_(MORE_OBSCURE_PASSWORD)); - return MOD_CONT; + source.Reply(MORE_OBSCURE_PASSWORD); + return; } else if (len > Config->PassLen) { - source.Reply(_(PASSWORD_TOO_LONG)); - return MOD_CONT; + source.Reply(PASSWORD_TOO_LONG); + return; } enc_encrypt(param, u->Account()->pass); Anope::string tmp_pass; if (enc_decrypt(u->Account()->pass, tmp_pass) == 1) - source.Reply(_(NICK_SASET_PASSWORD_CHANGED_TO), u->Account()->display.c_str(), tmp_pass.c_str()); + source.Reply(_("Password for \002%s\002 changed to \002%s\002."), u->Account()->display.c_str(), tmp_pass.c_str()); else - source.Reply(_(NICK_SASET_PASSWORD_CHANGED), u->Account()->display.c_str()); + source.Reply(_("Password for \002%s\002 changed."), u->Account()->display.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET PASSWORD \037new-password\037\002\n" - " \n" - "Changes the password used to identify you as the nick's\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the password used to identify you as the nick's\n" "owner.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - // XXX - SyntaxError(source, "SET", _(NICK_SET_SYNTAX)); - } }; class NSSet : public Module @@ -221,17 +141,14 @@ class NSSet : public Module CommandNSSetPassword commandnssetpassword; public: - NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsset(this), commandnssetdisplay(this), commandnssetpassword(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsset); - - commandnsset.AddSubcommand(this, &commandnssetdisplay); - commandnsset.AddSubcommand(this, &commandnssetpassword); + ModuleManager::RegisterService(&commandnsset); + ModuleManager::RegisterService(&commandnssetdisplay); + ModuleManager::RegisterService(&commandnssetpassword); } }; diff --git a/modules/core/ns_set_autoop.cpp b/modules/core/ns_set_autoop.cpp index 68513b849..a107f7188 100644 --- a/modules/core/ns_set_autoop.cpp +++ b/modules/core/ns_set_autoop.cpp @@ -12,25 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetAutoOp : public Command { public: - CommandNSSetAutoOp(const Anope::string &spermission = "") : Command("AUTOOP", 1, 2, spermission) + CommandNSSetAutoOp(Module *creator, const Anope::string &sname = "nickserv/set/autoop", size_t min = 1, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Should services op you automatically.")); + this->SetSyntax(_("{ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); - if (!na) - throw CoreException("NULL na in CommandNSSetAutoOp"); + NickAlias *na = findnick(user); + if (na == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params.size() > 1 ? params[1] : ""; - if (param.equals_ci("ON")) { nc->SetFlag(NI_AUTOOP); @@ -44,45 +45,47 @@ class CommandNSSetAutoOp : public Command else this->OnSyntaxError(source, "AUTOOP"); - return MOD_CONT; + return; } - bool OnHelp(CommandSource &source, const Anope::string &) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - source.Reply(_("Syntax: \002SET AUTOOP {ON | OFF}\002\n" - " \n" - "Sets whether you will be opped automatically. Set to ON to \n" - "allow ChanServ to op you automatically when entering channels.")); - return true; + this->Run(source, source.u->Account()->display, params[0]); } - void OnSyntaxError(CommandSource &source, const Anope::string &) + bool OnHelp(CommandSource &source, const Anope::string &) { - SyntaxError(source, "SET AUTOOP", _("SET AUTOOP {ON | OFF}")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets whether you will be opped automatically. Set to ON to \n" + "allow ChanServ to op you automatically when entering channels.")); + return true; } }; class CommandNSSASetAutoOp : public CommandNSSetAutoOp { public: - CommandNSSASetAutoOp() : CommandNSSetAutoOp("nickserv/saset/autoop") + CommandNSSASetAutoOp(Module *creator) : CommandNSSetAutoOp(creator, "nickserv/saset/autoop", 2, "nickserv/saset/autoop") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 {ON | OFF}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 AUTOOP {ON | OFF}\002\n" - " \n" - "Sets whether the given nickname will be opped automatically.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets whether the given nickname will be opped automatically.\n" "Set to \002ON\002 to allow ChanServ to op the given nickname \n" "omatically when joining channels.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET AUTOOP", _("SASET \037nickname\037 AUTOOP {ON | OFF}")); - } }; class NSSetAutoOp : public Module @@ -91,31 +94,13 @@ class NSSetAutoOp : public Module CommandNSSASetAutoOp commandnssasetautoop; public: - NSSetAutoOp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetAutoOp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetautoop(this), commandnssasetautoop(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetautoop); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetautoop); - } - - ~NSSetAutoOp() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetautoop); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetautoop); + ModuleManager::RegisterService(&commandnssetautoop); + ModuleManager::RegisterService(&commandnssasetautoop); } }; diff --git a/modules/core/ns_set_email.cpp b/modules/core/ns_set_email.cpp index 388914733..4f4131950 100644 --- a/modules/core/ns_set_email.cpp +++ b/modules/core/ns_set_email.cpp @@ -12,9 +12,8 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" -static bool SendConfirmMail(User *u) +static bool SendConfirmMail(User *u, BotInfo *bi) { int chars[] = { ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', @@ -37,43 +36,45 @@ static bool SendConfirmMail(User *u) " \n" "If you don't know why this mail was sent to you, please ignore it silently.\n" " \n" - "%s administrators."), u->Account()->email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); + "%s administrators."), u->Account()->email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); - return Mail(u, u->Account(), nickserv->Bot(), subject, message); + return Mail(u, u->Account(), bi, subject, message); } class CommandNSSetEmail : public Command { public: - CommandNSSetEmail(const Anope::string &spermission = "") : Command("EMAIL", 1, 2, spermission) + CommandNSSetEmail(Module *creator, const Anope::string &cname = "nickserv/set/email", size_t min = 0, const Anope::string &spermission = "") : Command(creator, cname, min, min + 1, spermission) { this->SetDesc(_("Associate an E-mail address with your nickname")); + this->SetSyntax(_("\037address\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { User *u = source.u; - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetEmail"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params.size() > 1 ? params[1] : ""; - if (param.empty() && Config->NSForceEmail) { source.Reply(_("You cannot unset the e-mail on this network.")); - return MOD_CONT; + return; } else if (Config->NSSecureAdmins && u->Account() != nc && nc->IsServicesOper()) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } else if (!param.empty() && !MailValidate(param)) { - source.Reply(_(MAIL_X_INVALID), param.c_str()); - return MOD_CONT; + source.Reply(MAIL_X_INVALID, param.c_str()); + return; } if (!param.empty() && Config->NSConfirmEmailChanges && !u->IsServicesOper()) @@ -81,7 +82,7 @@ class CommandNSSetEmail : public Command u->Account()->Extend("ns_set_email", new ExtensibleItemRegular<Anope::string>(param)); Anope::string old = u->Account()->email; u->Account()->email = param; - if (SendConfirmMail(u)) + if (SendConfirmMail(u, source.owner)) source.Reply(_("A confirmation email has been sent to \002%s\002. Follow the instructions in it to change your email address."), param.c_str()); u->Account()->email = old; } @@ -99,14 +100,19 @@ class CommandNSSetEmail : public Command } } - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params.size() ? params[0] : ""); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET EMAIL \037address\037\002\n" - " \n" - "Associates the given E-mail address with your nickname.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Associates the given E-mail address with your nickname.\n" "This address will be displayed whenever someone requests\n" "information on the nickname with the \002INFO\002 command.")); return true; @@ -116,15 +122,22 @@ class CommandNSSetEmail : public Command class CommandNSSASetEmail : public CommandNSSetEmail { public: - CommandNSSASetEmail() : CommandNSSetEmail("nickserv/saset/email") + CommandNSSASetEmail(Module *creator) : CommandNSSetEmail(creator, "nickserv/saset/email", 2, "nickserv/saset/email") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 \037address\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, params[0], params.size() > 1 ? params[1] : ""); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 EMAIL \037address\037\002\n" - " \n" - "Associates the given E-mail address with the nickname.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Associates the given E-mail address with the nickname.")); return true; } }; @@ -135,39 +148,21 @@ class NSSetEmail : public Module CommandNSSASetEmail commandnssasetemail; public: - NSSetEmail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetEmail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetemail(this), commandnssasetemail(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - ModuleManager::Attach(I_OnPreCommand, this); - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetemail); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetemail); - } - - ~NSSetEmail() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetemail); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetemail); + ModuleManager::RegisterService(&commandnssetemail); + ModuleManager::RegisterService(&commandnssasetemail); } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { User *u = source.u; - if (command->service->nick == Config->s_NickServ && command->name.equals_ci("CONFIRM") && !params.empty() && u->IsIdentified()) + if (command->name == "nickserv/confirm" && !params.empty() && u->IsIdentified()) { Anope::string new_email, passcode; if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode)) diff --git a/modules/core/ns_set_greet.cpp b/modules/core/ns_set_greet.cpp index 9723f78b5..ab5243724 100644 --- a/modules/core/ns_set_greet.cpp +++ b/modules/core/ns_set_greet.cpp @@ -12,25 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetGreet : public Command { public: - CommandNSSetGreet(const Anope::string &spermission = "") : Command("GREET", 1, 2, spermission) + CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Associate a greet message with your nickname")); + this->SetSyntax(_("\037message\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetGreet"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params.size() > 1 ? params[1] : ""; - if (!param.empty()) { nc->greet = param; @@ -42,14 +43,19 @@ class CommandNSSetGreet : public Command source.Reply(_("Greet message for \002%s\002 unset."), nc->display.c_str()); } - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params.size() > 0 ? params[0] : ""); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET GREET \037message\037\002\n" - " \n" - "Makes the given message the greet of your nickname, that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Makes the given message the greet of your nickname, that\n" "will be displayed when joining a channel that has GREET\n" "option enabled, provided that you have the necessary \n" "access on it.")); @@ -60,15 +66,22 @@ class CommandNSSetGreet : public Command class CommandNSSASetGreet : public CommandNSSetGreet { public: - CommandNSSASetGreet() : CommandNSSetGreet("nickserv/saset/greet") + CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1, "nickserv/saset/greet") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 \037message\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, params[0], params.size() > 1 ? params[1] : ""); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 GREET \037message\037\002\n" - " \n" - "Makes the given message the greet of the nickname, that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Makes the given message the greet of the nickname, that\n" "will be displayed when joining a channel that has GREET\n" "option enabled, provided that the user has the necessary \n" "access on it.")); @@ -82,31 +95,13 @@ class NSSetGreet : public Module CommandNSSASetGreet commandnssasetgreet; public: - NSSetGreet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetGreet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetgreet(this), commandnssasetgreet(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetgreet); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetgreet); - } - - ~NSSetGreet() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetgreet); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetgreet); + ModuleManager::RegisterService(&commandnssetgreet); + ModuleManager::RegisterService(&commandnssasetgreet); } }; diff --git a/modules/core/ns_set_hide.cpp b/modules/core/ns_set_hide.cpp index 6c5eeff29..e1a9ecb4e 100644 --- a/modules/core/ns_set_hide.cpp +++ b/modules/core/ns_set_hide.cpp @@ -12,29 +12,29 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetHide : public Command { public: - CommandNSSetHide(const Anope::string &spermission = "") : Command("HIDE", 2, 3, spermission) + CommandNSSetHide(Module *creator, const Anope::string &sname = "nickserv/set/hide", size_t min = 2, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Hide certain pieces of nickname information")); + this->SetSyntax(_("{EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m, const Anope::string &arg) { - NickAlias *na = findnick(params[0]); - if (!na) - throw CoreException("NULL na in CommandNSSetHide"); + NickAlias *na = findnick(user); + if (user == NULL) + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; Anope::string onmsg, offmsg; NickCoreFlag flag; - Anope::string param = params[1]; - Anope::string arg = params.size() > 2 ? params[2] : ""; - if (param.equals_ci("EMAIL")) { flag = NI_HIDE_EMAIL; @@ -62,70 +62,72 @@ class CommandNSSetHide : public Command else { this->OnSyntaxError(source, "HIDE"); - return MOD_CONT; + return; } if (arg.equals_ci("ON")) { nc->SetFlag(flag); - source.Reply(onmsg.c_str(), nc->display.c_str(), Config->s_NickServ.c_str()); + source.Reply(onmsg.c_str(), nc->display.c_str(), Config->NickServ.c_str()); } else if (arg.equals_ci("OFF")) { nc->UnsetFlag(flag); - source.Reply(offmsg.c_str(), nc->display.c_str(), Config->s_NickServ.c_str()); + source.Reply(offmsg.c_str(), nc->display.c_str(), Config->NickServ.c_str()); } else this->OnSyntaxError(source, "HIDE"); - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\002\n" - " \n" - "Allows you to prevent certain pieces of information from\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to prevent certain pieces of information from\n" "being displayed when someone does a %s \002INFO\002 on your\n" "nick. You can hide your E-mail address (\002EMAIL\002), last seen\n" "user@host mask (\002USERMASK\002), your services access status\n" "(\002STATUS\002) and last quit message (\002QUIT\002).\n" "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->s_NickServ.c_str()); + "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET HIDE", _("SET HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}")); - } }; class CommandNSSASetHide : public CommandNSSetHide { public: - CommandNSSASetHide() : CommandNSSetHide("nickserv/saset/command") + CommandNSSASetHide(Module *creator) : CommandNSSetHide(creator, "nickserv/saset/hide", 3, "nickserv/saset/hide") { + this->SetSyntax("\037nickname\037 {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->ClearSyntax(); + this->Run(source, params[0], params[1], params[2]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}\002\n" - " \n" - "Allows you to prevent certain pieces of information from\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to prevent certain pieces of information from\n" "being displayed when someone does a %s \002INFO\002 on the\n" "nick. You can hide the E-mail address (\002EMAIL\002), last seen\n" "user@host mask (\002USERMASK\002), the services access status\n" "(\002STATUS\002) and last quit message (\002QUIT\002).\n" "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->s_NickServ.c_str()); + "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET HIDE", _("SASET NICK_SASET_HIDE_SYNTAX37nicknameNICK_SASET_HIDE_SYNTAX37 HIDE {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}")); - } }; class NSSetHide : public Module @@ -134,31 +136,13 @@ class NSSetHide : public Module CommandNSSASetHide commandnssasethide; public: - NSSetHide(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetHide(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssethide(this), commandnssasethide(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssethide); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasethide); - } - - ~NSSetHide() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssethide); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasethide); + ModuleManager::RegisterService(&commandnssethide); + ModuleManager::RegisterService(&commandnssasethide); } }; diff --git a/modules/core/ns_set_kill.cpp b/modules/core/ns_set_kill.cpp index e0a536a0a..26a23292b 100644 --- a/modules/core/ns_set_kill.cpp +++ b/modules/core/ns_set_kill.cpp @@ -12,26 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetKill : public Command { public: - CommandNSSetKill(const Anope::string &spermission = "") : Command("KILL", 2, 3, spermission) + CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Turn protection on or off")); + this->SetSyntax(_("{ON | QUICK | IMMED | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetKill"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params[1]; - Anope::string arg = params.size() > 2 ? params[2] : ""; - if (param.equals_ci("ON")) { nc->SetFlag(NI_KILLPROTECT); @@ -68,14 +68,19 @@ class CommandNSSetKill : public Command else this->OnSyntaxError(source, "KILL"); - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params[0]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET KILL {ON | QUICK | IMMED | OFF}\002\n" - " \n" - "Turns the automatic protection option for your nick\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns the automatic protection option for your nick\n" "on or off. With protection on, if another user\n" "tries to take your nick, they will be given one minute to\n" "change to another nick, after which %s will forcibly change\n" @@ -86,28 +91,30 @@ class CommandNSSetKill : public Command "\002IMMED\002, user's nick will be changed immediately \037without\037 being\n" "warned first or given a chance to change their nick; please\n" "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), Config->s_NickServ.c_str()); + "network's administrators may have disabled this option."), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET KILL", Config->NSAllowKillImmed ? _("SET KILL {ON | QUICK | IMMED | OFF}") : _("SET KILL {ON | QUICK | OFF}")); - } }; class CommandNSSASetKill : public CommandNSSetKill { public: - CommandNSSASetKill() : CommandNSSetKill("nickserv/saset/kill") + CommandNSSASetKill(Module *creator) : CommandNSSetKill(creator, "nickserv/saset/kill", 2, "nickserv/saset/kill") { + this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->ClearSyntax(); + this->Run(source, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 KILL {ON | QUICK | IMMED | OFF}\002\n" - " \n" - "Turns the automatic protection option for the nick\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns the automatic protection option for the nick\n" "on or off. With protection on, if another user\n" "tries to take the nick, they will be given one minute to\n" "change to another nick, after which %s will forcibly change\n" @@ -118,14 +125,9 @@ class CommandNSSASetKill : public CommandNSSetKill "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" "warned first or given a chance to change their nick; please\n" "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), Config->s_NickServ.c_str()); + "network's administrators may have disabled this option."), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET KILL", Config->NSAllowKillImmed ? _("SASET \037nickname\037 KILL {ON | QUICK | IMMED | OFF}") : _("SASET \037nickname\037 KILL {ON | QUICK | OFF}")); - } }; class NSSetKill : public Module @@ -134,31 +136,13 @@ class NSSetKill : public Module CommandNSSASetKill commandnssasetkill; public: - NSSetKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetkill(this), commandnssasetkill(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetkill); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetkill); - } - - ~NSSetKill() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetkill); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetkill); + ModuleManager::RegisterService(&commandnssetkill); + ModuleManager::RegisterService(&commandnssasetkill); } }; diff --git a/modules/core/ns_set_language.cpp b/modules/core/ns_set_language.cpp index c614e7642..dcad104c5 100644 --- a/modules/core/ns_set_language.cpp +++ b/modules/core/ns_set_language.cpp @@ -12,25 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetLanguage : public Command { public: - CommandNSSetLanguage(const Anope::string &spermission = "") : Command("LANGUAGE", 2, 2, spermission) + CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Set the language Services will use when messaging you")); + this->SetSyntax(_("\037language\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetLanguage"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params[1]; - for (unsigned j = 0; j < languages.size(); ++j) { if (param == "en" || languages[j] == param) @@ -38,21 +39,26 @@ class CommandNSSetLanguage : public Command else if (j + 1 == languages.size()) { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } } nc->language = param != "en" ? param : ""; source.Reply(_("Language changed to \002English\002.")); - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶m) + { + this->Run(source, source.u->Account()->display, param[0]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET LANGUAGE \037language\037\002\n" - " \n" - "Changes the language Services uses when sending messages to\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the language Services uses when sending messages to\n" "you (for example, when responding to a command you send).\n" "\037language\037 should be chosen from the following list of\n" "supported languages:")); @@ -68,35 +74,32 @@ class CommandNSSetLanguage : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET LANGUAGE", _("SET LANGUAGE \037language\037")); - } }; class CommandNSSASetLanguage : public CommandNSSetLanguage { public: - CommandNSSASetLanguage() : CommandNSSetLanguage("nickserv/saset/language") + CommandNSSASetLanguage(Module *creator) : CommandNSSetLanguage(creator, "nickserv/saset/language", 2, "nickserv/saset/language") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 \037language\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET LANGUAGE \037language\037\002\n" - " \n" - "Changes the language Services uses when sending messages to\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Changes the language Services uses when sending messages to\n" "you (for example, when responding to a command you send).\n" "\037language\037 should be chosen from the following list of\n" "supported languages:")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET LANGUAGE", _("SASET \037nickname\037 LANGUAGE \037number\037")); - } }; class NSSetLanguage : public Module @@ -105,31 +108,13 @@ class NSSetLanguage : public Module CommandNSSASetLanguage commandnssasetlanguage; public: - NSSetLanguage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetLanguage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetlanguage(this), commandnssasetlanguage(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetlanguage); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetlanguage); - } - - ~NSSetLanguage() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetlanguage); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetlanguage); + ModuleManager::RegisterService(&commandnssetlanguage); + ModuleManager::RegisterService(&commandnssasetlanguage); } }; diff --git a/modules/core/ns_set_message.cpp b/modules/core/ns_set_message.cpp index d3f0d896c..fa9c7ae18 100644 --- a/modules/core/ns_set_message.cpp +++ b/modules/core/ns_set_message.cpp @@ -12,31 +12,32 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetMessage : public Command { public: - CommandNSSetMessage(const Anope::string &spermission = "") : Command("MSG", 2, 2, spermission) + CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { this->SetDesc(_("Change the communication method of Services")); + this->SetSyntax(_("{ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetMessage"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; if (!Config->UsePrivmsg) { source.Reply(_("Option \002%s\02 cannot be set on this network."), "MSG"); - return MOD_CONT; + return; } - const Anope::string ¶m = params.size() > 1 ? params[1] : ""; - if (param.equals_ci("ON")) { nc->SetFlag(NI_MSG); @@ -50,45 +51,47 @@ class CommandNSSetMessage : public Command else this->OnSyntaxError(source, "MSG"); - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params[0]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET MSG {ON | OFF}\002\n" - " \n" - "Allows you to choose the way Services are communicating with \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to choose the way Services are communicating with \n" "you. With \002MSG\002 set, Services will use messages, else they'll \n" "use notices.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET MSG", _("SET MSG {ON | OFF}")); - } }; class CommandNSSASetMessage : public CommandNSSetMessage { public: - CommandNSSASetMessage() : CommandNSSetMessage("nickserv/saset/message") + CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2, "nickserv/saset/message") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 {ON | OFF}")); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 MSG {ON | OFF}\002\n" - " \n" - "Allows you to choose the way Services are communicating with \n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to choose the way Services are communicating with \n" "the given user. With \002MSG\002 set, Services will use messages,\n" "else they'll use notices.")); return true; } - void OnSyntaxError(CommandSource &source, const Anope::string &) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - SyntaxError(source, "SASET MSG", _("SASAET \037nickname\037 PRIVATE {ON | OFF}")); + this->Run(source, params[0], params[1]); } }; @@ -98,31 +101,13 @@ class NSSetMessage : public Module CommandNSSASetMessage commandnssasetmessage; public: - NSSetMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetmessage(this), commandnssasetmessage(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetmessage); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetmessage); - } - - ~NSSetMessage() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetmessage); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetmessage); + ModuleManager::RegisterService(&commandnssetmessage); + ModuleManager::RegisterService(&commandnssasetmessage); } }; diff --git a/modules/core/ns_set_private.cpp b/modules/core/ns_set_private.cpp index 422cab2df..6e2948067 100644 --- a/modules/core/ns_set_private.cpp +++ b/modules/core/ns_set_private.cpp @@ -12,25 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetPrivate : public Command { public: - CommandNSSetPrivate(const Anope::string &spermission = "") : Command("PRIVATE", 2, 2, spermission) + CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1, const Anope::string &spermission = "") : Command(creator, sname, min, min + 1, spermission) { - this->SetDesc(Anope::printf(_("Prevent the nickname from appearing in a \002%s%s LIST\002"), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str())); + this->SetDesc(Anope::printf(_("Prevent the nickname from appearing in a \002%s%s LIST\002"), Config->UseStrictPrivMsgString.c_str(), Config->NickServ.c_str())); + this->SetSyntax(_("{ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetPrivate"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params[1]; - if (param.equals_ci("ON")) { nc->SetFlag(NI_PRIVATE); @@ -44,52 +45,54 @@ class CommandNSSetPrivate : public Command else this->OnSyntaxError(source, "PRIVATE"); - return MOD_CONT; + return; + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params[0]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET PRIVATE {ON | OFF}\002\n" - " \n" - "Turns %s's privacy option on or off for your nick.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns %s's privacy option on or off for your nick.\n" "With \002PRIVATE\002 set, your nickname will not appear in\n" "nickname lists generated with %s's \002LIST\002 command.\n" "(However, anyone who knows your nickname can still get\n" "information on it using the \002INFO\002 command.)"), - Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + Config->NickServ.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET PRIVATE", _("SET PRIVATE {ON | OFF}")); - } }; class CommandNSSASetPrivate : public CommandNSSetPrivate { public: - CommandNSSASetPrivate() : CommandNSSetPrivate("nickserv/saset/private") + CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2, "nickserv/saset/private") { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 {ON | OFF}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 PRIVATE {ON | OFF}\002\n" - " \n" - "Turns %s's privacy option on or off for the nick.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns %s's privacy option on or off for the nick.\n" "With \002PRIVATE\002 set, the nickname will not appear in\n" "nickname lists generated with %s's \002LIST\002 command.\n" "(However, anyone who knows the nickname can still get\n" "information on it using the \002INFO\002 command.)"), - Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + Config->NickServ.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET PRIVATE", _("SASET \037nickname\037 PRIVATE {ON | OFF}")); - } }; class NSSetPrivate : public Module @@ -98,31 +101,13 @@ class NSSetPrivate : public Module CommandNSSASetPrivate commandnssasetprivate; public: - NSSetPrivate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetPrivate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetprivate(this), commandnssasetprivate(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetprivate); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetprivate); - } - - ~NSSetPrivate() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetprivate); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetprivate); + ModuleManager::RegisterService(&commandnssetprivate); + ModuleManager::RegisterService(&commandnssasetprivate); } }; diff --git a/modules/core/ns_set_secure.cpp b/modules/core/ns_set_secure.cpp index 1c78e3f1b..8cf6590cf 100644 --- a/modules/core/ns_set_secure.cpp +++ b/modules/core/ns_set_secure.cpp @@ -12,25 +12,26 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetSecure : public Command { public: - CommandNSSetSecure(const Anope::string &cpermission = "") : Command("SECURE", 2, 2, cpermission) + CommandNSSetSecure(Module *creator, const Anope::string &sname = "nickserv/set/secure", size_t min = 1, const Anope::string &cpermission = "") : Command(creator, sname, min, min + 1, cpermission) { this->SetDesc(_("Turn nickname security on or off")); + this->SetSyntax(_("{ON | OFF}")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetSecure"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; - Anope::string param = params[1]; - if (param.equals_ci("ON")) { nc->SetFlag(NI_SECURE); @@ -43,55 +44,55 @@ class CommandNSSetSecure : public Command } else this->OnSyntaxError(source, "SECURE"); + } - return MOD_CONT; + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + this->Run(source, source.u->Account()->display, params[0]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SET SECURE {ON | OFF}\002\n" - " \n" - "Turns %s's security features on or off for your\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns %s's security features on or off for your\n" "nick. With \002SECURE\002 set, you must enter your password\n" "before you will be recognized as the owner of the nick,\n" "regardless of whether your address is on the access\n" "list. However, if you are on the access list, %s\n" "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + "\002KILL\002 option."), Config->NickServ.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET SECURE", _("SET SECURE {ON | OFF}")); - } }; class CommandNSSASetSecure : public CommandNSSetSecure { public: - CommandNSSASetSecure() : CommandNSSetSecure("nickserv/saset/secure") + CommandNSSASetSecure(Module *creator) : CommandNSSetSecure(creator, "nickserv/saset/secure", 2, "nickserv/saset/secure") + { + this->ClearSyntax(); + this->SetSyntax(_("\037nickname\037 {ON | OFF}")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { + this->Run(source, params[0], params[1]); } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: \002SASET \037nickname\037 SECURE {ON | OFF}\002\n" - " \n" - "Turns %s's security features on or off for your\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Turns %s's security features on or off for your\n" "nick. With \002SECURE\002 set, you must enter your password\n" "before you will be recognized as the owner of the nick,\n" "regardless of whether your address is on the access\n" "list. However, if you are on the access list, %s\n" "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + "\002KILL\002 option."), Config->NickServ.c_str(), Config->NickServ.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET SECURE", _("SASET \037nickname\037 SECURE {ON | OFF}")); - } }; class NSSetSecure : public Module @@ -100,31 +101,10 @@ class NSSetSecure : public Module CommandNSSASetSecure commandnssasetsecure; public: - NSSetSecure(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSetSecure(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssetsecure(this), commandnssasetsecure(this) { this->SetAuthor("Anope"); - - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->AddSubcommand(this, &commandnssetsecure); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->AddSubcommand(this, &commandnssasetsecure); - } - - ~NSSetSecure() - { - Command *c = FindCommand(nickserv->Bot(), "SET"); - if (c) - c->DelSubcommand(&commandnssetsecure); - - c = FindCommand(nickserv->Bot(), "SASET"); - if (c) - c->DelSubcommand(&commandnssasetsecure); } }; diff --git a/modules/core/ns_status.cpp b/modules/core/ns_status.cpp index 18fbadf87..9d8b58fcb 100644 --- a/modules/core/ns_status.cpp +++ b/modules/core/ns_status.cpp @@ -12,18 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSStatus : public Command { public: - CommandNSStatus() : Command("STATUS", 0, 16) + CommandNSStatus(Module *creator) : Command(creator, "nickserv/status", 0, 16) { this->SetFlag(CFLAG_ALLOW_UNREGISTERED); this->SetDesc(_("Returns the owner status of the given nickname")); + this->SetSyntax(_("\037nickname\037...")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = !params.empty() ? params[0] : u->nick; @@ -48,14 +48,14 @@ class CommandNSStatus : public Command */ source.Reply(_("STATUS %s %d %s"), nickbuf.c_str(), 1, u2->Account() ? u2->Account()->display.c_str() : ""); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002STATUS \037nickname\037...\002\n" - " \n" - "Returns whether the user using the given nickname is\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Returns whether the user using the given nickname is\n" "recognized as the owner of the nickname. The response has\n" "this format:\n" " \n" @@ -82,14 +82,12 @@ class NSStatus : public Module CommandNSStatus commandnsstatus; public: - NSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsstatus(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsstatus); + ModuleManager::RegisterService(&commandnsstatus); } }; diff --git a/modules/core/ns_suspend.cpp b/modules/core/ns_suspend.cpp index 3764f9dc6..33eb5ad67 100644 --- a/modules/core/ns_suspend.cpp +++ b/modules/core/ns_suspend.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSuspend : public Command { public: - CommandNSSuspend() : Command("SUSPEND", 2, 2, "nickserv/suspend") + CommandNSSuspend(Module *creator) : Command(creator, "nickserv/suspend", 2, 2, "nickserv/suspend") { this->SetDesc(_("Suspend a given nick")); + this->SetSyntax(_("\037nickname\037 \037reason\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -31,21 +31,21 @@ class CommandNSSuspend : public Command if (readonly) { - source.Reply(_(READ_ONLY_MODE)); - return MOD_CONT; + source.Reply(READ_ONLY_MODE); + return; } NickAlias *na = findnick(nick); if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + return; } if (Config->NSSecureAdmins && na->nc->IsServicesOper()) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } na->nc->SetFlag(NI_SUSPENDED); @@ -76,52 +76,50 @@ class CommandNSSuspend : public Command FOREACH_MOD(I_OnNickSuspended, OnNickSuspend(na)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: SUSPEND nickname reason\n" - "SUSPENDs a nickname from being used.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Suspends a registered nickname, which prevents from being used\n" + "while keeping all the data for that nick.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SUSPEND", _("SUSPEND nickname reason")); - } }; class CommandNSUnSuspend : public Command { public: - CommandNSUnSuspend() : Command("UNSUSPEND", 1, 1, "nickserv/suspend") + CommandNSUnSuspend(Module *creator) : Command(creator, "nickserv/unsuspend", 1, 1, "nickserv/suspend") { this->SetDesc(_("Unsuspend a given nick")); + this->SetSyntax(_("\037nickname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; if (readonly) { - source.Reply(_(READ_ONLY_MODE)); - return MOD_CONT; + source.Reply(READ_ONLY_MODE); + return; } NickAlias *na = findnick(nick); if (!na) { - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); + return; } if (Config->NSSecureAdmins && na->nc->IsServicesOper()) { - source.Reply(_(ACCESS_DENIED)); - return MOD_CONT; + source.Reply(ACCESS_DENIED); + return; } na->nc->UnsetFlag(NI_SUSPENDED); @@ -131,20 +129,16 @@ class CommandNSUnSuspend : public Command FOREACH_MOD(I_OnNickUnsuspended, OnNickUnsuspended(na)); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: UNSUSPEND nickname\n" - "UNSUSPENDS a nickname from being used.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Unsuspends a nickname which allows it to be used again.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "UNSUSPEND", _("UNSUSPEND nickname")); - } }; class NSSuspend : public Module @@ -153,15 +147,13 @@ class NSSuspend : public Module CommandNSUnSuspend commandnsunsuspend; public: - NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnssuspend(this), commandnsunsuspend(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnssuspend); - this->AddCommand(nickserv->Bot(), &commandnsunsuspend); + ModuleManager::RegisterService(&commandnssuspend); + ModuleManager::RegisterService(&commandnsunsuspend); } }; diff --git a/modules/core/ns_update.cpp b/modules/core/ns_update.cpp index d5e727fa6..d870e3532 100644 --- a/modules/core/ns_update.cpp +++ b/modules/core/ns_update.cpp @@ -12,35 +12,42 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSUpdate : public Command { public: - CommandNSUpdate() : Command("UPDATE", 0, 0) + CommandNSUpdate(Module *creator) : Command(creator, "nickserv/update", 0, 0) { this->SetDesc(_("Updates your current status, i.e. it checks for new memos")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; NickAlias *na = findnick(u->nick); + if (!na) + { + source.Reply(NICK_NOT_REGISTERED); + return; + } + na->last_realname = u->realname; na->last_seen = Anope::CurTime; FOREACH_MOD(I_OnNickUpdate, OnNickUpdate(u)); - source.Reply(_("Status updated (memos, vhost, chmodes, flags)."), Config->s_NickServ.c_str()); - return MOD_CONT; + source.Reply(_("Status updated (memos, vhost, chmodes, flags)."), Config->NickServ.c_str()); + return; } bool OnHelp(CommandSource &source, const Anope::string &) { - source.Reply(_("Syntax: UPDATE\n" - "Updates your current status, i.e. it checks for new memos,\n" - "sets needed chanmodes (ModeonID) and updates your vhost and\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Updates your current status, i.e. it checks for new memos,\n" + "sets needed channel modes and updates your vhost and\n" "your userflags (lastseentime, etc).")); return true; } @@ -51,14 +58,12 @@ class NSUpdate : public Module CommandNSUpdate commandnsupdate; public: - NSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + NSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandnsupdate(this) { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - - this->AddCommand(nickserv->Bot(), &commandnsupdate); + ModuleManager::RegisterService(&commandnsupdate); } }; diff --git a/modules/core/operserv.h b/modules/core/operserv.h deleted file mode 100644 index 97436b789..000000000 --- a/modules/core/operserv.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef OPERSERV_H -#define OPERSERV_H - -class OperServService : public Service -{ - public: - OperServService(Module *m) : Service(m, "OperServ") { } - - virtual BotInfo *Bot() = 0; -}; - -static service_reference<OperServService> operserv("OperServ"); - -#endif // OPERSERV_H - diff --git a/modules/core/os_akill.cpp b/modules/core/os_akill.cpp index 07d950d8d..9a268d333 100644 --- a/modules/core/os_akill.cpp +++ b/modules/core/os_akill.cpp @@ -12,7 +12,8 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" + +static service_reference<XLineManager> akills("xlinemanager/sgline"); class AkillDelCallback : public NumberList { @@ -38,7 +39,7 @@ class AkillDelCallback : public NumberList if (!Number) return; - XLine *x = SGLine->GetEntry(Number - 1); + XLine *x = akills->GetEntry(Number - 1); if (!x) return; @@ -49,7 +50,7 @@ class AkillDelCallback : public NumberList static void DoDel(CommandSource &source, XLine *x) { - SGLine->DelXLine(x); + akills->DelXLine(x); } }; @@ -68,7 +69,7 @@ class AkillListCallback : public NumberList if (!SentHeader) source.Reply(_("No matching entries on the AKILL list.")); else - source.Reply(_(END_OF_ANY_LIST), "Akill"); + source.Reply(END_OF_ANY_LIST, "Akill"); } void HandleNumber(unsigned Number) @@ -76,7 +77,7 @@ class AkillListCallback : public NumberList if (!Number) return; - XLine *x = SGLine->GetEntry(Number - 1); + XLine *x = akills->GetEntry(Number - 1); if (!x) return; @@ -93,7 +94,7 @@ class AkillListCallback : public NumberList static void DoList(CommandSource &source, XLine *x, unsigned Number) { - source.Reply(_(OPER_LIST_FORMAT), Number + 1, x->Mask.c_str(), x->Reason.c_str()); + source.Reply(OPER_LIST_FORMAT, Number + 1, x->Mask.c_str(), x->Reason.c_str()); } }; @@ -109,7 +110,7 @@ class AkillViewCallback : public AkillListCallback if (!Number) return; - XLine *x = SGLine->GetEntry(Number - 1); + XLine *x = akills->GetEntry(Number - 1); if (!x) return; @@ -125,14 +126,14 @@ class AkillViewCallback : public AkillListCallback static void DoList(CommandSource &source, XLine *x, unsigned Number) { - source.Reply(_(OPER_VIEW_FORMAT), Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expire_left(source.u->Account(), x->Expires).c_str(), x->Reason.c_str()); + source.Reply(OPER_VIEW_FORMAT, Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expire_left(source.u->Account(), x->Expires).c_str(), x->Reason.c_str()); } }; class CommandOSAKill : public Command { private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; unsigned last_param = 2; @@ -156,8 +157,8 @@ class CommandOSAKill : public Command /* Do not allow less than a minute expiry time */ if (expires && expires < 60) { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; + source.Reply(BAD_EXPIRY_TIME); + return; } else if (expires > 0) expires += Anope::CurTime; @@ -165,7 +166,7 @@ class CommandOSAKill : public Command if (params.size() <= last_param) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } Anope::string reason = params[last_param]; @@ -173,13 +174,13 @@ class CommandOSAKill : public Command reason += " " + params[3]; if (!mask.empty() && !reason.empty()) { - std::pair<int, XLine *> canAdd = SGLine->CanAdd(mask, expires); + std::pair<int, XLine *> canAdd = akills->CanAdd(mask, expires); if (mask.find('!') != Anope::string::npos) source.Reply(_("\002Reminder\002: AKILL masks cannot contain nicknames; make sure you have \002not\002 included a nick portion in your mask.")); else if (mask.find('@') == Anope::string::npos) - source.Reply(_(BAD_USERHOST_MASK)); + source.Reply(BAD_USERHOST_MASK); else if (mask.find_first_not_of("~@.*?") == Anope::string::npos) - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); else if (canAdd.first == 1) source.Reply(_("\002%s\002 already exists on the AKILL list."), canAdd.second->Mask.c_str()); else if (canAdd.first == 2) @@ -199,31 +200,36 @@ class CommandOSAKill : public Command if (percent > 95) { - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); Log(LOG_ADMIN, u, this) << "tried to akill " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; + return; } - XLine *x = SGLine->Add(mask, u->nick, expires, reason); + XLine *x = akills->Add(mask, u->nick, expires, reason); - if (!x) - return MOD_CONT; + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, akills)); + if (MOD_RESULT == EVENT_STOP) + { + delete x; + return; + } source.Reply(_("\002%s\002 added to the AKILL list."), mask.c_str()); Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); } } else this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &mask = params.size() > 1 ? params[1] : ""; @@ -231,13 +237,13 @@ class CommandOSAKill : public Command if (mask.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } - if (SGLine->GetList().empty()) + if (akills->GetList().empty()) { source.Reply(_("AKILL list is empty.")); - return MOD_CONT; + return; } if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) @@ -247,32 +253,32 @@ class CommandOSAKill : public Command } else { - XLine *x = SGLine->HasEntry(mask); + XLine *x = akills->HasEntry(mask); if (!x) { source.Reply(_("\002%s\002 not found on the AKILL list."), mask.c_str()); - return MOD_CONT; + return; } - FOREACH_MOD(I_OnDelAkill, OnDelAkill(u, x)); + FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, x, akills)); AkillDelCallback::DoDel(source, x); source.Reply(_("\002%s\002 deleted from the AKILL list."), mask.c_str()); } if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) { - if (SGLine->GetList().empty()) + if (akills->GetList().empty()) { source.Reply(_("AKILL list is empty.")); - return MOD_CONT; + return; } const Anope::string &mask = params.size() > 1 ? params[1] : ""; @@ -286,9 +292,9 @@ class CommandOSAKill : public Command { bool SentHeader = false; - for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) + for (unsigned i = 0, end = akills->GetCount(); i < end; ++i) { - XLine *x = SGLine->GetEntry(i); + XLine *x = akills->GetEntry(i); if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) { @@ -306,18 +312,18 @@ class CommandOSAKill : public Command if (!SentHeader) source.Reply(_("No matching entries on the AKILL list.")); else - source.Reply(_(END_OF_ANY_LIST), "Akill"); + source.Reply(END_OF_ANY_LIST, "Akill"); } - return MOD_CONT; + return; } - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) { - if (SGLine->GetList().empty()) + if (akills->GetList().empty()) { source.Reply(_("AKILL list is empty.")); - return MOD_CONT; + return; } const Anope::string &mask = params.size() > 1 ? params[1] : ""; @@ -331,9 +337,9 @@ class CommandOSAKill : public Command { bool SentHeader = false; - for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) + for (unsigned i = 0, end = akills->GetCount(); i < end; ++i) { - XLine *x = SGLine->GetEntry(i); + XLine *x = akills->GetEntry(i); if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) { @@ -351,28 +357,36 @@ class CommandOSAKill : public Command source.Reply(_("No matching entries on the AKILL list.")); } - return MOD_CONT; + return; } - CommandReturn DoClear(CommandSource &source) + void DoClear(CommandSource &source) { User *u = source.u; - FOREACH_MOD(I_OnDelAkill, OnDelAkill(u, NULL)); - SGLine->Clear(); + FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, NULL, akills)); + akills->Clear(); source.Reply(_("The AKILL list has been cleared.")); - return MOD_CONT; + return; } public: - CommandOSAKill() : Command("AKILL", 1, 4, "operserv/akill") + CommandOSAKill(Module *creator) : Command(creator, "operserv/akill", 1, 4, "operserv/akill") { this->SetDesc(_("Manipulate the AKILL list")); + this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037 \037reason\037")); + this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); + this->SetSyntax(_("LIST [\037mask\037 | \037list\037]")); + this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]")); + this->SetSyntax(_("CLEAR")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[0]; + if (!akills) + return; + if (cmd.equals_ci("ADD")) return this->DoAdd(source, params); else if (cmd.equals_ci("DEL")) @@ -386,18 +400,14 @@ class CommandOSAKill : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002AKILL ADD [+\037expiry\037] \037mask\037 \037reason\037\002\n" - " \002AKILL DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002AKILL LIST [\037mask\037 | \037list\037]\002\n" - " \002AKILL VIEW [\037mask\037 | \037list\037]\002\n" - " \002AKILL CLEAR\002\n" - " \n" - "Allows Services operators to manipulate the AKILL list. If\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services operators to manipulate the AKILL list. If\n" "a user matching an AKILL mask attempts to connect, Services\n" "will issue a KILL for that user and, on supported server\n" "types, will instruct all servers to add a ban (K-line) for\n" @@ -435,11 +445,6 @@ class CommandOSAKill : public Command "\002AKILL CLEAR\002 clears all entries of the AKILL list.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "AKILL", _("AKILL {ADD | DEL | LIST | VIEW | CLEAR} [[+\037expiry\037] {\037nick\037 | \037mask\037 | \037entry-list\037} [\037reason\037]]")); - } }; class OSAKill : public Module @@ -447,14 +452,12 @@ class OSAKill : public Module CommandOSAKill commandosakill; public: - OSAKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSAKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosakill(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosakill); + ModuleManager::RegisterService(&commandosakill); } }; diff --git a/modules/core/os_chankill.cpp b/modules/core/os_chankill.cpp index 6e5c8e748..54530d7af 100644 --- a/modules/core/os_chankill.cpp +++ b/modules/core/os_chankill.cpp @@ -12,18 +12,23 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" + +static service_reference<XLineManager> akills("xlinemanager/sgline"); class CommandOSChanKill : public Command { public: - CommandOSChanKill() : Command("CHANKILL", 2, 3, "operserv/chankill") + CommandOSChanKill(Module *creator) : Command(creator, "operserv/chankill", 2, 3, "operserv/chankill") { this->SetDesc(_("AKILL all users on a specific channel")); + this->SetSyntax(_("[+\037expiry\037] \037channel\037 \037reason\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { + if (!akills) + return; + User *u = source.u; Anope::string expiry, channel; time_t expires; @@ -43,8 +48,8 @@ class CommandOSChanKill : public Command expires *= 86400; if (expires && expires < 60) { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; + source.Reply(BAD_EXPIRY_TIME); + return; } else if (expires > 0) expires += Anope::CurTime; @@ -52,7 +57,7 @@ class CommandOSChanKill : public Command if (params.size() <= last_param) { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } Anope::string reason = params[last_param]; @@ -75,31 +80,27 @@ class CommandOSChanKill : public Command if (uc->user->HasMode(UMODE_OPER)) continue; - SGLine->Add("*@" + uc->user->host, u->nick, expires, realreason); - SGLine->Check(uc->user); + akills->Add("*@" + uc->user->host, u->nick, expires, realreason); + akills->Check(uc->user); } Log(LOG_ADMIN, u, this) << "(" << realreason << ")"; } else - source.Reply(_(CHAN_X_NOT_IN_USE), channel.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, channel.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CHANKILL [+\037expiry\037] \037channel\037 \037reason\037\002\n" - "Puts an AKILL for every nick on the specified channel. It\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Puts an AKILL for every nick on the specified channel. It\n" "uses the entire and complete real ident@host for every nick,\n" "then enforces the AKILL.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CHANKILL", _("CHANKILL [+\037expiry\037] {\037#channel\037} [\037reason\037]")); - } }; class OSChanKill : public Module @@ -107,14 +108,12 @@ class OSChanKill : public Module CommandOSChanKill commandoschankill; public: - OSChanKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSChanKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandoschankill(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoschankill); + ModuleManager::RegisterService(&commandoschankill); } }; diff --git a/modules/core/os_chanlist.cpp b/modules/core/os_chanlist.cpp deleted file mode 100644 index aebc3a035..000000000 --- a/modules/core/os_chanlist.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSChanList : public Command -{ - public: - CommandOSChanList() : Command("CHANLIST", 0, 2) - { - this->SetDesc(_("Lists all channel records")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &pattern = !params.empty() ? params[0] : ""; - const Anope::string &opt = params.size() > 1 ? params[1] : ""; - std::list<ChannelModeName> Modes; - User *u2; - - if (!opt.empty() && opt.equals_ci("SECRET")) - { - Modes.push_back(CMODE_SECRET); - Modes.push_back(CMODE_PRIVATE); - } - - if (!pattern.empty() && (u2 = finduser(pattern))) - { - source.Reply(_("\002%s\002 channel list:\n" - "Name Users Modes Topic"), u2->nick.c_str()); - - for (UChannelList::iterator uit = u2->chans.begin(), uit_end = u2->chans.end(); uit != uit_end; ++uit) - { - ChannelContainer *cc = *uit; - - if (!Modes.empty()) - for (std::list<ChannelModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) - if (!cc->chan->HasMode(*it)) - continue; - - source.Reply(_("%-20s %4d +%-6s %s"), cc->chan->name.c_str(), cc->chan->users.size(), cc->chan->GetModes(true, true).c_str(), !cc->chan->topic.empty() ? cc->chan->topic.c_str() : ""); - } - } - else - { - source.Reply(_("Channel list:\n" - "Name Users Modes Topic")); - - for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) - { - Channel *c = cit->second; - - if (!pattern.empty() && !Anope::Match(c->name, pattern)) - continue; - if (!Modes.empty()) - for (std::list<ChannelModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) - if (!c->HasMode(*it)) - continue; - - source.Reply(_("%-20s %4d +%-6s %s"), c->name.c_str(), c->users.size(), c->GetModes(true, true).c_str(), !c->topic.empty() ? c->topic.c_str() : ""); - } - } - - source.Reply(_("End of channel list.")); - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002CHANLIST [{\037pattern\037 | \037nick\037} [\037SECRET\037]]\002\n" - " \n" - "Lists all channels currently in use on the IRC network, whether they\n" - "are registered or not.\n" - "If \002pattern\002 is given, lists only channels that match it. If a nickname\n" - "is given, lists only the channels the user using it is on. If SECRET is\n" - "specified, lists only channels matching \002pattern\002 that have the +s or\n" - "+p mode.")); - return true; - } -}; - -class OSChanList : public Module -{ - CommandOSChanList commandoschanlist; - - public: - OSChanList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoschanlist); - } -}; - -MODULE_INIT(OSChanList) diff --git a/modules/core/os_config.cpp b/modules/core/os_config.cpp index c921600fb..ea7842b5d 100644 --- a/modules/core/os_config.cpp +++ b/modules/core/os_config.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSConfig : public Command { @@ -33,12 +32,13 @@ class CommandOSConfig : public Command } public: - CommandOSConfig() : Command("CONFIG", 1, 4, "operserv/config") + CommandOSConfig(Module *creator) : Command(creator, "operserv/config", 1, 4, "operserv/config") { this->SetDesc(_("View and change configuration file settings")); + this->SetSyntax(_("{\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &what = params[0]; @@ -136,14 +136,14 @@ class CommandOSConfig : public Command catch (const ConfigException &ex) { source.Reply(_("Error changing configuration value: ") + ex.GetReason()); - return MOD_CONT; + return; } ChangeHash(Config->config_data, params[1], params[2], params[3]); Log(LOG_ADMIN, source.u, this) << "to change the configuration value of " << params[1] << ":" << params[2] << " to " << params[3]; source.Reply(_("Value of %s:%s changed to %s"), params[1].c_str(), params[2].c_str(), params[3].c_str()); - return MOD_CONT; + return; } } @@ -173,9 +173,6 @@ class CommandOSConfig : public Command { const Anope::string &first = list[i].first, second = list[i].second; - if (first == "modules") - continue; // Modules list isn't important - source.Reply(_(" Name: %-15s Value: %s"), first.c_str(), second.c_str()); } } @@ -185,27 +182,22 @@ class CommandOSConfig : public Command else this->OnSyntaxError(source, what); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002CONFIG {\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]\002\n" - "\n" - "\002CONFIG\002 allows you to change and view configuration settings.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to change and view configuration settings.\n" "Settings changed by this command are temporary and will not be reflected\n" "back into the configuration file, and will be lost if Anope is shut down,\n" "restarted, or the RELOAD command is used.\n" " \n" "Example:\n" - " \002CONFIG MODIFY nickserv forcemail no\002")); + " \002MODIFY nickserv forcemail no\002")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "CONFIG", _("CONFIG {\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]")); - } }; class OSConfig : public Module @@ -213,14 +205,12 @@ class OSConfig : public Module CommandOSConfig commandosconfig; public: - OSConfig(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSConfig(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosconfig(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosconfig); + ModuleManager::RegisterService(&commandosconfig); } }; diff --git a/modules/core/os_forbid.cpp b/modules/core/os_forbid.cpp index 6ac4ffc0b..dabe8ee43 100644 --- a/modules/core/os_forbid.cpp +++ b/modules/core/os_forbid.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "os_forbid.h" class MyForbidService : public ForbidService @@ -64,7 +63,7 @@ class MyForbidService : public ForbidService else if (d->type == FT_EMAIL) type = "email"; - Log(operserv->Bot(), Config->s_OperServ + "/forbid") << "Expiring forbid for " << d->mask << " type " << type; + Log(LOG_NORMAL, Config->OperServ + "/forbid") << "Expiring forbid for " << d->mask << " type " << type; this->forbidData.erase(this->forbidData.begin() + i - 1); delete d; } @@ -78,15 +77,18 @@ class CommandOSForbid : public Command { service_reference<ForbidService> fs; public: - CommandOSForbid() : Command("FORBID", 1, 5, "operserv/forbid"), fs("forbid") + CommandOSForbid(Module *creator) : Command(creator, "operserv/forbid", 1, 5, "operserv/forbid"), fs("forbid") { this->SetDesc(_("Forbid usage of nicknames, channels, and emails")); + this->SetSyntax(_("ADD {NICK|CHAN|EMAIL} [+\037expiry\037] \037entry\037\002 [\037reason\037]")); + this->SetSyntax(_("DEL {NICK|CHAN|EMAIL} \037entry\037")); + this->SetSyntax(_("LIST (NICK|CHAN|EMAIL)")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { if (!this->fs) - return MOD_CONT; + return; const Anope::string &command = params[0]; const Anope::string &subcommand = params.size() > 1 ? params[1] : ""; @@ -180,24 +182,17 @@ class CommandOSForbid : public Command else this->OnSyntaxError(source, command); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002FORBID ADD {NICK|CHAN|EMAIL} [+\037expiry\037] \037entry\037\002 [\037reason\037]\n" - " \002FORBID DEL {NICK|CHAN|EMAIL} \037entry\037\002\n" - " \002FORBID LIST (NICK|CHAN|EMAIL)" - "\n" - "Forbid allows you to forbid usage of certain nicknames, channels,\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Forbid allows you to forbid usage of certain nicknames, channels,\n" "and email addresses. Wildcards are accepted for all entries.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "FORBID", _("FORBID {ADD|DEL|LIST} {NICK|CHAN|EMAIL} [+\037expiry\037] \037entry\037 [\037reason\037]")); - } }; class OSForbid : public Module @@ -206,24 +201,22 @@ class OSForbid : public Module CommandOSForbid commandosforbid; public: - OSForbid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), forbidService(this) + OSForbid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + forbidService(this), commandosforbid(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - Implementation i[] = { I_OnUserConnect, I_OnUserNickChange, I_OnJoinChannel, I_OnPreCommand, I_OnDatabaseWrite, I_OnDatabaseRead }; ModuleManager::Attach(i, this, 6); ModuleManager::RegisterService(&this->forbidService); - this->AddCommand(operserv->Bot(), &commandosforbid); + ModuleManager::RegisterService(&commandosforbid); } void OnUserConnect(dynamic_reference<User> &u, bool &exempt) { - if (!u || exempt || !operserv) + if (!u || exempt) return; this->OnUserNickChange(u, ""); @@ -231,27 +224,32 @@ class OSForbid : public Module void OnUserNickChange(User *u, const Anope::string &) { - if (!operserv || u->HasMode(UMODE_OPER)) + if (u->HasMode(UMODE_OPER)) return; ForbidData *d = this->forbidService.FindForbid(u->nick, FT_NICK); if (d != NULL) { - if (d->reason.empty()) - u->SendMessage(operserv->Bot(), _("This nickname has been forbidden.")); - else - u->SendMessage(operserv->Bot(), _("This nickname has been forbidden: %s"), d->reason.c_str()); + BotInfo *bi = findbot(Config->OperServ); + if (bi) + { + if (d->reason.empty()) + u->SendMessage(bi, _("This nickname has been forbidden.")); + else + u->SendMessage(bi, _("This nickname has been forbidden: %s"), d->reason.c_str()); + } u->Collide(NULL); } } void OnJoinChannel(User *u, Channel *c) { - if (!operserv || u->HasMode(UMODE_OPER)) + if (u->HasMode(UMODE_OPER)) return; + BotInfo *bi = findbot(Config->OperServ); ForbidData *d = this->forbidService.FindForbid(c->name, FT_CHAN); - if (d != NULL) + if (bi != NULL && d != NULL) { if (!c->HasFlag(CH_INHABIT)) { @@ -266,17 +264,17 @@ class OSForbid : public Module } if (d->reason.empty()) - c->Kick(operserv->Bot(), u, _("This channel has been forbidden.")); + c->Kick(bi, u, _("This channel has been forbidden.")); else - c->Kick(operserv->Bot(), u, _("This channel has been forbidden: %s"), d->reason.c_str()); + c->Kick(bi, u, _("This channel has been forbidden: %s"), d->reason.c_str()); } } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { if (source.u->HasMode(UMODE_OPER)) return EVENT_CONTINUE; - else if (command->service->nick == Config->s_NickServ && command->name == "REGISTER" && params.size() > 1) + else if (command->name == "nickserv/register" && params.size() > 1) { ForbidData *d = this->forbidService.FindForbid(params[1], FT_EMAIL); if (d != NULL) @@ -285,9 +283,9 @@ class OSForbid : public Module return EVENT_STOP; } } - else if (command->service->nick == Config->s_NickServ && command->name == "SET" && params.size() > 2 && params[0].equals_ci("EMAIL")) + else if (command->name == "nickserv/set/email" && params.size() > 0) { - ForbidData *d =this->forbidService.FindForbid(params[1], FT_EMAIL); + ForbidData *d = this->forbidService.FindForbid(params[0], FT_EMAIL); if (d != NULL) { source.Reply("Your email address is not allowed, choose a different one."); diff --git a/modules/core/os_help.cpp b/modules/core/os_help.cpp deleted file mode 100644 index 3bd047d72..000000000 --- a/modules/core/os_help.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSHelp : public Command -{ - public: - CommandOSHelp() : Command("HELP", 1, 1) - { - this->SetDesc(_("Displays this list and give information about commands")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - mod_help_cmd(operserv->Bot(), source.u, NULL, params[0]); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - User *u = source.u; - source.Reply(_("%s commands:"), Config->s_OperServ.c_str()); - for (CommandMap::const_iterator it = operserv->Bot()->Commands.begin(), it_end = operserv->Bot()->Commands.end(); it != it_end; ++it) - if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) - it->second->OnServHelp(source); - } -}; - -class OSHelp : public Module -{ - CommandOSHelp commandoshelp; - - public: - OSHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoshelp); - } -}; - -MODULE_INIT(OSHelp) diff --git a/modules/core/os_ignore.cpp b/modules/core/os_ignore.cpp index 90c695605..1e7977034 100644 --- a/modules/core/os_ignore.cpp +++ b/modules/core/os_ignore.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "os_ignore.h" class OSIgnoreService : public IgnoreService @@ -145,11 +144,11 @@ class OSIgnoreService : public IgnoreService class CommandOSIgnore : public Command { private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { service_reference<IgnoreService> ignore_service("operserv/ignore"); if (!ignore_service) - return MOD_CONT; + return; const Anope::string &time = params.size() > 1 ? params[1] : ""; const Anope::string &nick = params.size() > 2 ? params[2] : ""; @@ -158,7 +157,7 @@ class CommandOSIgnore : public Command if (time.empty() || nick.empty()) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } else { @@ -167,7 +166,7 @@ class CommandOSIgnore : public Command if (t <= -1) { source.Reply(_("You have to enter a valid number as time.")); - return MOD_CONT; + return; } ignore_service->AddIgnore(nick, source.u->nick, reason, t); @@ -177,14 +176,14 @@ class CommandOSIgnore : public Command source.Reply(_("\002%s\002 will now be ignored for \002%s\002."), nick.c_str(), time.c_str()); } - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source) + void DoList(CommandSource &source) { service_reference<IgnoreService> ignore_service("operserv/ignore"); if (!ignore_service) - return MOD_CONT; + return; const std::list<IgnoreData> &ignores = ignore_service->GetIgnores(); if (ignores.empty()) @@ -201,14 +200,14 @@ class CommandOSIgnore : public Command } } - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) { service_reference<IgnoreService> ignore_service("operserv/ignore"); if (!ignore_service) - return MOD_CONT; + return; const Anope::string nick = params.size() > 1 ? params[1] : ""; if (nick.empty()) @@ -218,28 +217,32 @@ class CommandOSIgnore : public Command else source.Reply(_("Nick \002%s\002 not found on ignore list."), nick.c_str()); - return MOD_CONT; + return; } - CommandReturn DoClear(CommandSource &source) + void DoClear(CommandSource &source) { service_reference<IgnoreService> ignore_service("operserv/ignore"); if (!ignore_service) - return MOD_CONT; + return; ignore_service->ClearIgnores(); source.Reply(_("Ignore list has been cleared.")); - return MOD_CONT; + return; } public: - CommandOSIgnore() : Command("IGNORE", 1, 4, "operserv/ignore") + CommandOSIgnore(Module *creator) : Command(creator, "operserv/ignore", 1, 4, "operserv/ignore") { this->SetDesc(_("Modify the Services ignore list")); + this->SetSyntax(_("ADD \037time\037 \037nick\037 \037reason\037")); + this->SetSyntax(_("DEL \037nick\037")); + this->SetSyntax(_("LIST")); + this->SetSyntax(_("CLEAR")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[0]; @@ -254,14 +257,14 @@ class CommandOSIgnore : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002IGNORE {ADD|DEL|LIST|CLEAR} [\037time\037] [\037nick\037] [\037reason\037]\002\n" - " \n" - "Allows Services Operators to make Services ignore a nick or mask\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Operators to make Services ignore a nick or mask\n" "for a certain time or until the next restart. The default\n" "time format is seconds. You can specify it by using units.\n" "Valid units are: \037s\037 for seconds, \037m\037 for minutes, \n" @@ -275,11 +278,6 @@ class CommandOSIgnore : public Command "Ignores will not be enforced on IRC Operators.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "IGNORE", _("IGNORE {ADD|DEL|LIST|CLEAR} [\037time\037] [\037nick\037] [\037reason\037]\002")); - } }; class OSIgnore : public Module @@ -288,17 +286,15 @@ class OSIgnore : public Module CommandOSIgnore commandosignore; public: - OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), osignoreservice(this, "operserv/ignore") + OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + osignoreservice(this, "operserv/ignore"), commandosignore(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosignore); + ModuleManager::RegisterService(&commandosignore); - Implementation i[] = { I_OnDatabaseRead, I_OnDatabaseWrite, I_OnPreCommandRun, I_OnBotPrivmsg }; - ModuleManager::Attach(i, this, 4); + Implementation i[] = { I_OnDatabaseRead, I_OnDatabaseWrite, I_OnBotPrivmsg }; + ModuleManager::Attach(i, this, 3); ModuleManager::RegisterService(&this->osignoreservice); } @@ -325,40 +321,27 @@ class OSIgnore : public Module void OnDatabaseWrite(void (*Write)(const Anope::string &)) { - service_reference<IgnoreService> ignore_service("operserv/ignore"); - if (ignore_service) + for (std::list<IgnoreData>::iterator ign = this->osignoreservice.GetIgnores().begin(), ign_end = this->osignoreservice.GetIgnores().end(); ign != ign_end; ) { - for (std::list<IgnoreData>::iterator ign = ignore_service->GetIgnores().begin(), ign_end = ignore_service->GetIgnores().end(); ign != ign_end; ) + if (ign->time && ign->time <= Anope::CurTime) { - if (ign->time && ign->time <= Anope::CurTime) - { - Log(LOG_DEBUG) << "[os_ignore] Expiring ignore entry " << ign->mask; - ign = ignore_service->GetIgnores().erase(ign); - } - else - { - std::stringstream buf; - buf << "OS IGNORE " << ign->mask << " " << ign->time << " " << ign->creator << " :" << ign->reason; - Write(buf.str()); - ++ign; - } + Log(LOG_DEBUG) << "[os_ignore] Expiring ignore entry " << ign->mask; + ign = this->osignoreservice.GetIgnores().erase(ign); + } + else + { + std::stringstream buf; + buf << "OS IGNORE " << ign->mask << " " << ign->time << " " << ign->creator << " :" << ign->reason; + Write(buf.str()); + ++ign; } } } - EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) - { - return this->OnBotPrivmsg(u, bi, message); - } - EventReturn OnBotPrivmsg(User *u, BotInfo *bi, const Anope::string &message) { - service_reference<IgnoreService> ignore_service("operserv/ignore"); - if (ignore_service) - { - if (ignore_service->Find(u->nick)) - return EVENT_STOP; - } + if (this->osignoreservice.Find(u->nick)) + return EVENT_STOP; return EVENT_CONTINUE; } diff --git a/modules/core/os_jupe.cpp b/modules/core/os_jupe.cpp index 17eb9577f..a0e06c272 100644 --- a/modules/core/os_jupe.cpp +++ b/modules/core/os_jupe.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSJupe : public Command { public: - CommandOSJupe() : Command("JUPE", 1, 2, "operserv/jupe") + CommandOSJupe(Module *creator) : Command(creator, "operserv/jupe", 1, 2, "operserv/jupe") { this->SetDesc(_("\"Jupiter\" a server")); + this->SetSyntax(_("\037server\037 [\037reason\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &jserver = params[0]; @@ -43,14 +43,14 @@ class CommandOSJupe : public Command Log(LOG_ADMIN, u, this) << "on " << jserver << " (" << rbuf << ")"; } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002JUPE \037server\037 [\037reason\037]\002\n" - " \n" - "Tells Services to jupiter a server -- that is, to create\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Tells Services to jupiter a server -- that is, to create\n" "a fake \"server\" connected to Services which prevents\n" "the real server of that name from connecting. The jupe\n" "may be removed using a standard \002SQUIT\002. If a reason is\n" @@ -60,11 +60,6 @@ class CommandOSJupe : public Command "person who jupitered the server.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "JUPE", _("JUPE \037servername\037 [\037reason\037]")); - } }; class OSJupe : public Module @@ -72,14 +67,12 @@ class OSJupe : public Module CommandOSJupe commandosjupe; public: - OSJupe(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSJupe(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosjupe(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosjupe); + ModuleManager::RegisterService(&commandosjupe); } }; diff --git a/modules/core/os_kick.cpp b/modules/core/os_kick.cpp index bf766deeb..cd36c118e 100644 --- a/modules/core/os_kick.cpp +++ b/modules/core/os_kick.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSKick : public Command { public: - CommandOSKick() : Command("KICK", 3, 3, "operserv/kick") + CommandOSKick(Module *creator) : Command(creator, "operserv/kick", 3, 3, "operserv/kick") { this->SetDesc(_("Kick a user from a channel")); + this->SetSyntax(_("\037channel\037 \037user\037 \037reason\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &chan = params[0]; @@ -33,42 +33,37 @@ class CommandOSKick : public Command if (!(c = findchan(chan))) { - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); - return MOD_CONT; + source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); + return; } else if (c->bouncy_modes) { source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); - return MOD_CONT; + return; } else if (!(u2 = finduser(nick))) { - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); - return MOD_CONT; + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); + return; } - c->Kick(operserv->Bot(), u2, "%s (%s)", u->nick.c_str(), s.c_str()); + c->Kick(source.owner, u2, "%s (%s)", u->nick.c_str(), s.c_str()); Log(LOG_ADMIN, u, this) << "on " << u2->nick << " in " << c->name; - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002KICK \037channel\037 \037user\037 \037reason\037\002\n" - " \n" - "Allows staff to kick a user from any channel.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows staff to kick a user from any channel.\n" "Parameters are the same as for the standard /KICK\n" "command. The kick message will have the nickname of the\n" "IRCop sending the KICK command prepended; for example:\n" " \n" - "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), Config->s_OperServ.c_str()); + "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "KICK", _("KICK \037channel\037 \037user\037 \037reason\037")); - } }; class OSKick : public Module @@ -76,14 +71,12 @@ class OSKick : public Module CommandOSKick commandoskick; public: - OSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandoskick(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoskick); + ModuleManager::RegisterService(&commandoskick); } }; diff --git a/modules/core/os_list.cpp b/modules/core/os_list.cpp new file mode 100644 index 000000000..9a582f97b --- /dev/null +++ b/modules/core/os_list.cpp @@ -0,0 +1,187 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandOSChanList : public Command +{ + public: + CommandOSChanList(Module *creator) : Command(creator, "operserv/chanlist", 0, 2) + { + this->SetDesc(_("Lists all channel records")); + this->SetSyntax(_("[{\037pattern\037 | \037nick\037} [\037SECRET\037]]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &pattern = !params.empty() ? params[0] : ""; + const Anope::string &opt = params.size() > 1 ? params[1] : ""; + std::list<ChannelModeName> Modes; + User *u2; + + if (!opt.empty() && opt.equals_ci("SECRET")) + { + Modes.push_back(CMODE_SECRET); + Modes.push_back(CMODE_PRIVATE); + } + + if (!pattern.empty() && (u2 = finduser(pattern))) + { + source.Reply(_("\002%s\002 channel list:\n" + "Name Users Modes Topic"), u2->nick.c_str()); + + for (UChannelList::iterator uit = u2->chans.begin(), uit_end = u2->chans.end(); uit != uit_end; ++uit) + { + ChannelContainer *cc = *uit; + + if (!Modes.empty()) + for (std::list<ChannelModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) + if (!cc->chan->HasMode(*it)) + continue; + + source.Reply(_("%-20s %4d +%-6s %s"), cc->chan->name.c_str(), cc->chan->users.size(), cc->chan->GetModes(true, true).c_str(), !cc->chan->topic.empty() ? cc->chan->topic.c_str() : ""); + } + } + else + { + source.Reply(_("Channel list:\n" + "Name Users Modes Topic")); + + for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) + { + Channel *c = cit->second; + + if (!pattern.empty() && !Anope::Match(c->name, pattern)) + continue; + if (!Modes.empty()) + for (std::list<ChannelModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) + if (!c->HasMode(*it)) + continue; + + source.Reply(_("%-20s %4d +%-6s %s"), c->name.c_str(), c->users.size(), c->GetModes(true, true).c_str(), !c->topic.empty() ? c->topic.c_str() : ""); + } + } + + source.Reply(_("End of channel list.")); + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all channels currently in use on the IRC network, whether they\n" + "are registered or not.\n" + "If \002pattern\002 is given, lists only channels that match it. If a nickname\n" + "is given, lists only the channels the user using it is on. If SECRET is\n" + "specified, lists only channels matching \002pattern\002 that have the +s or\n" + "+p mode.")); + return true; + } +}; + +class CommandOSUserList : public Command +{ + public: + CommandOSUserList(Module *creator) : Command(creator, "operserv/userlist", 0, 2) + { + this->SetDesc(_("Lists all user records")); + this->SetSyntax(_("[{\037pattern\037 | \037channel\037} [\037INVISIBLE\037]]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &pattern = !params.empty() ? params[0] : ""; + const Anope::string &opt = params.size() > 1 ? params[1] : ""; + Channel *c; + std::list<UserModeName> Modes; + + if (!opt.empty() && opt.equals_ci("INVISIBLE")) + Modes.push_back(UMODE_INVIS); + + if (!pattern.empty() && (c = findchan(pattern))) + { + source.Reply(_("\002%s\002 users list:\n" + "Nick Mask"), pattern.c_str()); + + for (CUserList::iterator cuit = c->users.begin(), cuit_end = c->users.end(); cuit != cuit_end; ++cuit) + { + UserContainer *uc = *cuit; + + if (!Modes.empty()) + for (std::list<UserModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) + if (!uc->user->HasMode(*it)) + continue; + + source.Reply(_("%-20s %s@%s"), uc->user->nick.c_str(), uc->user->GetIdent().c_str(), uc->user->GetDisplayedHost().c_str()); + } + } + else + { + source.Reply(_("Users list:\n" + "Nick Mask")); + + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u2 = it->second; + + if (!pattern.empty()) + { + Anope::string mask = u2->nick + "!" + u2->GetIdent() + "@" + u2->GetDisplayedHost(); + if (!Anope::Match(mask, pattern)) + continue; + if (!Modes.empty()) + for (std::list<UserModeName>::iterator mit = Modes.begin(), mit_end = Modes.end(); mit != mit_end; ++mit) + if (!u2->HasMode(*mit)) + continue; + } + source.Reply(_("%-20s %s@%s"), u2->nick.c_str(), u2->GetIdent().c_str(), u2->GetDisplayedHost().c_str()); + } + } + + source.Reply(_("End of users list.")); + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all users currently online on the IRC network, whether their\n" + "nick is registered or not.\n" + " \n" + "If \002pattern\002 is given, lists only users that match it (it must be in\n" + "the format nick!user@host). If \002channel\002 is given, lists only users\n" + "that are on the given channel. If INVISIBLE is specified, only users\n" + "with the +i flag will be listed.")); + return true; + } +}; + +class OSList : public Module +{ + CommandOSChanList commandoschanlist; + CommandOSUserList commandosuserlist; + + public: + OSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandoschanlist(this), commandosuserlist(this) + { + this->SetAuthor("Anope"); + + ModuleManager::RegisterService(&commandoschanlist); + ModuleManager::RegisterService(&commandosuserlist); + } +}; + +MODULE_INIT(OSList) diff --git a/modules/core/os_login.cpp b/modules/core/os_login.cpp index 4ff97da1f..332b00545 100644 --- a/modules/core/os_login.cpp +++ b/modules/core/os_login.cpp @@ -13,17 +13,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSLogin : public Command { public: - CommandOSLogin() : Command("LOGIN", 1, 1) + CommandOSLogin(Module *creator) : Command(creator, "operserv/login", 1, 1) { - this->SetDesc(Anope::printf(_("Login to %s"), Config->s_OperServ.c_str())); + this->SetDesc(Anope::printf(_("Login to %s"), Config->OperServ.c_str())); + this->SetSyntax(_("\037password\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &password = params[0]; @@ -36,33 +36,28 @@ class CommandOSLogin : public Command source.Reply(_("You are already identified.")); else if (o->password != password) { - source.Reply(_(PASSWORD_INCORRECT)); + source.Reply(PASSWORD_INCORRECT); bad_password(source.u); } else { - Log(LOG_ADMIN, source.u, this) << "and succesfully identified to " << Config->s_OperServ; + Log(LOG_ADMIN, source.u, this) << "and succesfully identified to " << source.owner->nick; source.u->Extend("os_login_password_correct"); source.Reply(_("Password accepted.")); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002LOGIN\002 \037password\037\n" - " \n" - "Logs you in to %s so you gain Services Operator privileges.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Logs you in to %s so you gain Services Operator privileges.\n" "This command may be unnecessary if your oper block is\n" - "configured without a password."), Config->s_OperServ.c_str()); + "configured without a password."), source.owner->nick.c_str()); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LOGIN", _("LOGIN \037password\037")); - } }; class OSLogin : public Module @@ -70,14 +65,12 @@ class OSLogin : public Module CommandOSLogin commandoslogin; public: - OSLogin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSLogin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandoslogin(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoslogin); + ModuleManager::RegisterService(&commandoslogin); ModuleManager::Attach(I_IsServicesOper, this); } diff --git a/modules/core/os_main.cpp b/modules/core/os_main.cpp index ec5e95ac8..e8d1f5e28 100644 --- a/modules/core/os_main.cpp +++ b/modules/core/os_main.cpp @@ -12,98 +12,305 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" -static BotInfo *OperServ = NULL; +static BotInfo *OperServ; -class OperServBotInfo : public BotInfo +class SGLineManager : public XLineManager { public: - OperServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } + SGLineManager(Module *creator) : XLineManager(creator, "xlinemanager/sgline", 'G') { } + + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) + { + Anope::string realreason = reason; + if (!creator.empty() && Config->AddAkiller) + realreason = "[" + creator + "] " + reason; + + XLine *x = new XLine(mask, creator, expires, realreason); + + this->AddXLine(x); + + if (UplinkSock && Config->AkillOnAdd) + this->Send(NULL, x); + + return x; + } + + void Del(XLine *x) + { + ircdproto->SendAkillDel(x); + } + + void OnMatch(User *u, XLine *x) + { + if (u) + u->Kill(Config->OperServ, x->Reason); + ircdproto->SendAkill(u, x); + } + + void OnExpire(XLine *x) + { + if (Config->WallAkillExpire) + ircdproto->SendGlobops(OperServ, "AKILL on %s has expired", x->Mask.c_str()); + } - void OnMessage(User *u, const Anope::string &message) + void Send(User *u, XLine *x) { - if (!u->HasMode(UMODE_OPER) && Config->OSOpersOnly) - { - u->SendMessage(OperServ, ACCESS_DENIED); - if (Config->WallBadOS) - ircdproto->SendGlobops(this, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); - } - else + ircdproto->SendAkill(u, x); + } +}; + +class SZLineManager : public XLineManager +{ + public: + SZLineManager(Module *creator) : XLineManager(creator, "xlinemanager/szline", 'Z') { } + + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) + { + XLine *x = new XLine(mask, creator, expires, reason); + + this->AddXLine(x); + + if (UplinkSock) + this->Send(NULL, x); + + return x; + } + + void Del(XLine *x) + { + ircdproto->SendSZLineDel(x); + } + + void OnMatch(User *u, XLine *x) + { + if (u) { - BotInfo::OnMessage(u, message); + Anope::string reason = "Z-Lined: " + x->Reason; + u->Kill(Config->OperServ, reason); } + + ircdproto->SendSZLine(u, x); + } + + void OnExpire(XLine *x) + { + if (Config->WallSZLineExpire) + ircdproto->SendGlobops(OperServ, "SZLINE on \2%s\2 has expired", x->Mask.c_str()); + } + + void Send(User *u, XLine *x) + { + ircdproto->SendSZLine(u, x); } }; -class MyOperServService : public OperServService +class SQLineManager : public XLineManager { public: - MyOperServService(Module *m) : OperServService(m) { } + SQLineManager(Module *creator) : XLineManager(creator, "xlinemanager/sqline", 'Q') { } + + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) + { + XLine *x = new XLine(mask, creator, expires, reason); + + this->AddXLine(x); + + if (Config->KillonSQline) + { + Anope::string rreason = "Q-Lined: " + reason; + + if (mask[0] == '#') + { + for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) + { + Channel *c = cit->second; + + if (!Anope::Match(c->name, mask)) + continue; + for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) + { + UserContainer *uc = *it; + ++it; + + if (uc->user->HasMode(UMODE_OPER) || uc->user->server == Me) + continue; + c->Kick(NULL, uc->user, "%s", reason.c_str()); + } + } + } + else + { + for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) + { + User *user = it->second; + ++it; + + if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->nick, x->Mask)) + user->Kill(Config->ServerName, rreason); + } + } + } + + if (UplinkSock) + this->Send(NULL, x); + + return x; + } + + void Del(XLine *x) + { + ircdproto->SendSQLineDel(x); + } + + void OnMatch(User *u, XLine *x) + { + if (u) + { + Anope::string reason = "Q-Lined: " + x->Reason; + u->Kill(Config->OperServ, reason); + } + + this->Send(u, x); + } + + void OnExpire(XLine *x) + { + if (Config->WallSQLineExpire) + ircdproto->SendGlobops(OperServ, "SQLINE on \2%s\2 has expired", x->Mask.c_str()); + } - BotInfo *Bot() + void Send(User *u, XLine *x) { - return OperServ; + ircdproto->SendSQLine(u, x); + } + + bool CheckChannel(Channel *c) + { + if (ircd->chansqline) + for (std::vector<XLine *>::const_iterator it = this->GetList().begin(), it_end = this->GetList().end(); it != it_end; ++it) + if (Anope::Match(c->name, (*it)->Mask)) + return true; + return false; } }; -class OperServCore : public Module +class SNLineManager : public XLineManager { - MyOperServService myoperserv; - public: - OperServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), myoperserv(this) + SNLineManager(Module *creator) : XLineManager(creator, "xlinemanager/snline", 'N') { } + + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - this->SetAuthor("Anope"); - this->SetPermanent(true); // Currently, /os modunload os_main explodes for obvious reasons + XLine *x = new XLine(mask, creator, expires, reason); - Implementation i[] = { I_OnServerQuit, I_OnUserModeSet, I_OnUserModeUnset, I_OnUserConnect }; - ModuleManager::Attach(i, this, 4); + this->AddXLine(x); - ModuleManager::RegisterService(&this->myoperserv); - - OperServ = new OperServBotInfo(Config->s_OperServ, Config->ServiceUser, Config->ServiceHost, Config->desc_OperServ); - OperServ->SetFlag(BI_CORE); + if (Config->KillonSNline && !ircd->sglineenforce) + { + Anope::string rreason = "G-Lined: " + reason; - /* Yes, these are in this order for a reason. Most violent->least violent. */ - XLineManager::RegisterXLineManager(SGLine = new SGLineManager()); - XLineManager::RegisterXLineManager(SZLine = new SZLineManager()); - XLineManager::RegisterXLineManager(SQLine = new SQLineManager()); - XLineManager::RegisterXLineManager(SNLine = new SNLineManager()); + for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) + { + User *user = it->second; + ++it; + + if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask)) + user->Kill(Config->ServerName, rreason); + } + } + + return x; + } + + void Del(XLine *x) + { + ircdproto->SendSGLineDel(x); + } + + void OnMatch(User *u, XLine *x) + { + if (u) + { + Anope::string reason = "G-Lined: " + x->Reason; + u->Kill(Config->OperServ, reason); + } + this->Send(u, x); + } + + void OnExpire(XLine *x) + { + if (Config->WallSNLineExpire) + ircdproto->SendGlobops(OperServ, "SNLINE on \2%s\2 has expired", x->Mask.c_str()); + } - spacesepstream coreModules(Config->OperCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) - ModuleManager::LoadModule(module, NULL); + void Send(User *u, XLine *x) + { + ircdproto->SendSGLine(u, x); } - ~OperServCore() + XLine *Check(User *u) { - spacesepstream coreModules(Config->OperCoreModules); - Anope::string module; - while (coreModules.GetToken(module)) + for (unsigned i = this->XLines.size(); i > 0; --i) { - Module *m = ModuleManager::FindModule(module); - if (m != NULL) - ModuleManager::UnloadModule(m, NULL); + XLine *x = this->XLines[i - 1]; + + if (x->Expires && x->Expires < Anope::CurTime) + { + this->OnExpire(x); + this->Del(x); + delete x; + this->XLines.erase(XLines.begin() + i - 1); + continue; + } + + if (Anope::Match(u->realname, x->Mask)) + { + this->OnMatch(u, x); + return x; + } } - delete SGLine; - SGLine = NULL; - delete SZLine; - SZLine = NULL; - delete SQLine; - SQLine = NULL; - delete SNLine; - SNLine = NULL; + return NULL; + } +}; + +class OperServCore : public Module +{ + SGLineManager sglines; + SZLineManager szlines; + SQLineManager sqlines; + SNLineManager snlines; - delete OperServ; + public: + OperServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + sglines(this), szlines(this), sqlines(this), snlines(this) + { + this->SetAuthor("Anope"); + + OperServ = findbot(Config->OperServ); + if (OperServ == NULL) + throw ModuleException("No bot named " + Config->OperServ); + + Implementation i[] = { I_OnServerQuit, I_OnUserModeSet, I_OnUserModeUnset, I_OnUserConnect, I_OnUserNickChange, I_OnPreHelp }; + ModuleManager::Attach(i, this, 6); + + ModuleManager::RegisterService(&sglines); + ModuleManager::RegisterService(&szlines); + ModuleManager::RegisterService(&sqlines); + ModuleManager::RegisterService(&snlines); + + /* Yes, these are in this order for a reason. Most violent->least violent. */ + XLineManager::RegisterXLineManager(&sglines); + XLineManager::RegisterXLineManager(&szlines); + XLineManager::RegisterXLineManager(&sqlines); + XLineManager::RegisterXLineManager(&snlines); } void OnServerQuit(Server *server) { if (server->HasFlag(SERVER_JUPED)) - ircdproto->SendGlobops(operserv->Bot(), "Received SQUIT for juped server %s", server->GetName().c_str()); + ircdproto->SendGlobops(OperServ, "Received SQUIT for juped server %s", server->GetName().c_str()); } void OnUserModeSet(User *u, UserModeName Name) @@ -127,6 +334,26 @@ class OperServCore : public Module if (u && !exempt) XLineManager::CheckAll(u); } + + void OnUserNickChange(User *u, const Anope::string &oldnick) + { + if (ircd->sqline && !u->HasMode(UMODE_OPER)) + this->sqlines.Check(u); + } + + EventReturn OnCheckKick(User *u, ChannelInfo *ci, bool &kick) + { + if (this->sqlines.CheckChannel(ci->c)) + kick = true; + return EVENT_CONTINUE; + } + + void OnPreHelp(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!params.empty() || source.owner->nick != Config->OperServ) + return; + source.Reply(_("%s commands:"), Config->OperServ.c_str()); + } }; MODULE_INIT(OperServCore) diff --git a/modules/core/os_mode.cpp b/modules/core/os_mode.cpp index 961dd05b7..83b567e25 100644 --- a/modules/core/os_mode.cpp +++ b/modules/core/os_mode.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSMode : public Command { public: - CommandOSMode() : Command("MODE", 2, 2, "operserv/mode") + CommandOSMode(Module *creator) : Command(creator, "operserv/mode", 2, 2, "operserv/mode") { this->SetDesc(_("Change channel or user modes")); + this->SetSyntax(_("{\037channel\037|\037user\037} \037modes\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &target = params[0]; @@ -32,12 +32,12 @@ class CommandOSMode : public Command { Channel *c = findchan(target); if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), target.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, target.c_str()); else if (c->bouncy_modes) source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); else { - c->SetModes(operserv->Bot(), false, modes.c_str()); + c->SetModes(source.owner, false, modes.c_str()); Log(LOG_ADMIN, u, this) << modes << " on " << target; } @@ -46,35 +46,30 @@ class CommandOSMode : public Command { User *u2 = finduser(target); if (!u2) - source.Reply(_(NICK_X_NOT_IN_USE), target.c_str()); + source.Reply(NICK_X_NOT_IN_USE, target.c_str()); else { - u2->SetModes(operserv->Bot(), "%s", modes.c_str()); + u2->SetModes(source.owner, "%s", modes.c_str()); source.Reply(_("Changed usermodes of \002%s\002 to %s."), u2->nick.c_str(), modes.c_str()); - u2->SendMessage(operserv->Bot(), _("\002%s\002 changed your usermodes to %s."), u->nick.c_str(), modes.c_str()); + u2->SendMessage(source.owner, _("\002%s\002 changed your usermodes to %s."), u->nick.c_str(), modes.c_str()); Log(LOG_ADMIN, u, this) << modes << " on " << target; } } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002MODE {\037channel\037|\037user\037} \037modes\037\002\n" - " \n" - "Allows Services operators to change modes for any channel or\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services operators to change modes for any channel or\n" "user. Parameters are the same as for the standard /MODE\n" "command.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "MODE", _("MODE {\037channel\037|\037user\037} \037modes\037")); - } }; class OSMode : public Module @@ -82,14 +77,12 @@ class OSMode : public Module CommandOSMode commandosmode; public: - OSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosmode(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmode); + ModuleManager::RegisterService(&commandosmode); } }; diff --git a/modules/core/os_modinfo.cpp b/modules/core/os_modinfo.cpp index 0a316c567..d62a7ebce 100644 --- a/modules/core/os_modinfo.cpp +++ b/modules/core/os_modinfo.cpp @@ -12,33 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSModInfo : public Command { - void showModuleCmdLoaded(BotInfo *bi, const Anope::string &mod_name, CommandSource &source) - { - if (!bi) - return; - - for (CommandMap::iterator it = bi->Commands.begin(), it_end = bi->Commands.end(); it != it_end; ++it) - { - Command *c = it->second; - - if (c->module && c->module->name.equals_ci(mod_name) && c->service) - { - source.Reply(_("Providing command: \002%s %s\002"), c->service->nick.c_str(), c->name.c_str()); - } - } - } - public: - CommandOSModInfo() : Command("MODINFO", 1, 1) + CommandOSModInfo(Module *creator) : Command(creator, "operserv/modinfo", 1, 1) { this->SetDesc(_("Info about a loaded module")); + this->SetSyntax(_("\037modname\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &file = params[0]; @@ -47,42 +31,212 @@ class CommandOSModInfo : public Command { source.Reply(_("Module: \002%s\002 Version: \002%s\002 Author: \002%s\002 loaded: \002%s\002"), m->name.c_str(), !m->version.empty() ? m->version.c_str() : "?", !m->author.empty() ? m->author.c_str() : "?", do_strftime(m->created).c_str()); - for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - this->showModuleCmdLoaded(it->second, m->name, source); + std::vector<Anope::string> services = ModuleManager::GetServiceKeys(); + for (unsigned i = 0; i < services.size(); ++i) + { + Service *s = ModuleManager::GetService(services[i]); + if (!s || s->owner != m) + continue; + source.Reply(_(" Providing service: \002%s\002"), s->name.c_str()); + + for (botinfo_map::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + { + BotInfo *bi = it->second; + + for (command_map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) + { + if (cit->second != s->name) + continue; + source.Reply(_(" Command \002%s\002 on \002%s\002 is linked to \002%s\002"), cit->first.c_str(), bi->nick.c_str(), s->name.c_str()); + } + } + } } else source.Reply(_("No information about module \002%s\002 is available"), file.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002MODINFO\002 \002FileName\002\n" - " \n" - "This command lists information about the specified loaded module")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command lists information about the specified loaded module")); return true; } +}; + +class CommandOSModList : public Command +{ + public: + CommandOSModList(Module *creator) : Command(creator, "operserv/modlist", 0, 1, "operserv/modlist") + { + this->SetDesc(_("List loaded modules")); + this->SetSyntax(_("[Core|3rd|protocol|encryption|supported]")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string ¶m = !params.empty() ? params[0] : ""; + + int count = 0; + int showCore = 0; + int showThird = 1; + int showProto = 1; + int showEnc = 1; + int showSupported = 1; + int showDB = 1; + + char core[] = "Core"; + char third[] = "3rd"; + char proto[] = "Protocol"; + char enc[] = "Encryption"; + char supported[] = "Supported"; + char db[] = "Database"; + + if (!param.empty()) + { + if (param.equals_ci(core)) + { + showCore = 1; + showThird = 0; + showProto = 0; + showEnc = 0; + showSupported = 0; + showDB = 0; + } + else if (param.equals_ci(third)) + { + showCore = 0; + showThird = 1; + showSupported = 0; + showProto = 0; + showEnc = 0; + showDB = 0; + } + else if (param.equals_ci(proto)) + { + showCore = 0; + showThird = 0; + showProto = 1; + showEnc = 0; + showSupported = 0; + showDB = 0; + } + else if (param.equals_ci(supported)) + { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 1; + showEnc = 0; + showDB = 0; + } + else if (param.equals_ci(enc)) + { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 0; + showEnc = 1; + showDB = 0; + } + else if (param.equals_ci(db)) + { + showCore = 0; + showThird = 0; + showProto = 0; + showSupported = 0; + showEnc = 0; + showDB = 1; + } + } + + source.Reply(_("Current Module list:")); + + for (std::list<Module *>::iterator it = Modules.begin(), it_end = Modules.end(); it != it_end; ++it) + { + Module *m = *it; + + switch (m->type) + { + case CORE: + if (showCore) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), core); + ++count; + } + break; + case THIRD: + if (showThird) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), third); + ++count; + } + break; + case PROTOCOL: + if (showProto) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), proto); + ++count; + } + break; + case SUPPORTED: + if (showSupported) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), supported); + ++count; + } + break; + case ENCRYPTION: + if (showEnc) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), enc); + ++count; + } + break; + case DATABASE: + if (showDB) + { + source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), db); + ++count; + } + break; + default: + break; + } + } + if (!count) + source.Reply(_("No modules currently loaded")); + else + source.Reply(_("%d Modules loaded."), count); + + return; + } - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - SyntaxError(source, "MODINFO", _("MODINFO \037FileName\037")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Lists all currently loaded modules.")); + return true; } }; class OSModInfo : public Module { CommandOSModInfo commandosmodinfo; + CommandOSModList commandosmodlist; public: - OSModInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSModInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosmodinfo(this), commandosmodlist(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmodinfo); + ModuleManager::RegisterService(&commandosmodinfo); + ModuleManager::RegisterService(&commandosmodlist); } }; diff --git a/modules/core/os_modlist.cpp b/modules/core/os_modlist.cpp deleted file mode 100644 index 70353eb5f..000000000 --- a/modules/core/os_modlist.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSModList : public Command -{ - public: - CommandOSModList() : Command("MODLIST", 0, 1, "operserv/modlist") - { - this->SetDesc(_("List loaded modules")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string ¶m = !params.empty() ? params[0] : ""; - - int count = 0; - int showCore = 0; - int showThird = 1; - int showProto = 1; - int showEnc = 1; - int showSupported = 1; - int showDB = 1; - - char core[] = "Core"; - char third[] = "3rd"; - char proto[] = "Protocol"; - char enc[] = "Encryption"; - char supported[] = "Supported"; - char db[] = "Database"; - - if (!param.empty()) - { - if (param.equals_ci(core)) - { - showCore = 1; - showThird = 0; - showProto = 0; - showEnc = 0; - showSupported = 0; - showDB = 0; - } - else if (param.equals_ci(third)) - { - showCore = 0; - showThird = 1; - showSupported = 0; - showProto = 0; - showEnc = 0; - showDB = 0; - } - else if (param.equals_ci(proto)) - { - showCore = 0; - showThird = 0; - showProto = 1; - showEnc = 0; - showSupported = 0; - showDB = 0; - } - else if (param.equals_ci(supported)) - { - showCore = 0; - showThird = 0; - showProto = 0; - showSupported = 1; - showEnc = 0; - showDB = 0; - } - else if (param.equals_ci(enc)) - { - showCore = 0; - showThird = 0; - showProto = 0; - showSupported = 0; - showEnc = 1; - showDB = 0; - } - else if (param.equals_ci(db)) - { - showCore = 0; - showThird = 0; - showProto = 0; - showSupported = 0; - showEnc = 0; - showDB = 1; - } - } - - source.Reply(_("Current Module list:")); - - for (std::list<Module *>::iterator it = Modules.begin(), it_end = Modules.end(); it != it_end; ++it) - { - Module *m = *it; - - switch (m->type) - { - case CORE: - if (showCore) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), core); - ++count; - } - break; - case THIRD: - if (showThird) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), third); - ++count; - } - break; - case PROTOCOL: - if (showProto) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), proto); - ++count; - } - break; - case SUPPORTED: - if (showSupported) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), supported); - ++count; - } - break; - case ENCRYPTION: - if (showEnc) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), enc); - ++count; - } - break; - case DATABASE: - if (showDB) - { - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), db); - ++count; - } - break; - default: - break; - } - } - if (!count) - source.Reply(_("No modules currently loaded")); - else - source.Reply(_("%d Modules loaded."), count); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002MODLIST\002 [Core|3rd|protocol|encryption|supported]\n" - " \n" - "Lists all currently loaded modules.")); - return true; - } -}; - -class OSModList : public Module -{ - CommandOSModList commandosmodlist; - - public: - OSModList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmodlist); - } -}; - -MODULE_INIT(OSModList) diff --git a/modules/core/os_modload.cpp b/modules/core/os_modload.cpp deleted file mode 100644 index 39687eeec..000000000 --- a/modules/core/os_modload.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSModLoad : public Command -{ - public: - CommandOSModLoad() : Command("MODLOAD", 1, 1, "operserv/modload") - { - this->SetDesc(_("Load a module")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - const Anope::string &mname = params[0]; - - ModuleReturn status = ModuleManager::LoadModule(mname, u); - if (status == MOD_ERR_OK) - { - ircdproto->SendGlobops(operserv->Bot(), "%s loaded module %s", u->nick.c_str(), mname.c_str()); - source.Reply(_("Module \002%s\002 loaded"), mname.c_str()); - - /* If a user is loading this module, then the core databases have already been loaded - * so trigger the event manually - */ - Module *m = ModuleManager::FindModule(mname); - if (m) - m->OnPostLoadDatabases(); - } - else if (status == MOD_ERR_EXISTS) - source.Reply(_("Module \002%s\002 is already loaded."), mname.c_str()); - else - source.Reply(_("Unable to load module \002%s\002"), mname.c_str()); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002MODLOAD\002 \002FileName\002\n" - " \n" - "This command loads the module named FileName from the modules\n" - "directory.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "MODLOAD", _("MODLOAD \037FileName\037")); - } -}; - -class OSModLoad : public Module -{ - CommandOSModLoad commandosmodload; - - public: - OSModLoad(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - this->SetPermanent(true); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmodload); - } -}; - -MODULE_INIT(OSModLoad) diff --git a/modules/core/os_modreload.cpp b/modules/core/os_modreload.cpp deleted file mode 100644 index 4eb14348e..000000000 --- a/modules/core/os_modreload.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSModReLoad : public Command -{ - public: - CommandOSModReLoad() : Command("MODRELOAD", 1, 1, "operserv/modload") - { - this->SetDesc(_("Reload a module")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - const Anope::string &mname = params[0]; - - Module *m = ModuleManager::FindModule(mname); - if (!m) - { - source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); - return MOD_CONT; - } - - if (!m->handle || m->GetPermanent()) - { - source.Reply(_("Unable to remove module \002%s\002"), m->name.c_str()); - return MOD_CONT; - } - - /* Unrecoverable */ - bool fatal = m->type == PROTOCOL; - ModuleReturn status = ModuleManager::UnloadModule(m, u); - - if (status != MOD_ERR_OK) - { - source.Reply(_("Unable to remove module \002%s\002"), mname.c_str()); - return MOD_CONT; - } - - status = ModuleManager::LoadModule(mname, u); - if (status == MOD_ERR_OK) - { - ircdproto->SendGlobops(operserv->Bot(), "%s reloaded module %s", u->nick.c_str(), mname.c_str()); - source.Reply(_("Module \002%s\002 reloaded"), mname.c_str()); - - /* If a user is loading this module, then the core databases have already been loaded - * so trigger the event manually - */ - m = ModuleManager::FindModule(mname); - if (m) - m->OnPostLoadDatabases(); - } - else - { - if (fatal) - throw FatalException("Unable to reload module " + mname); - else - source.Reply(_("Unable to load module \002%s\002"), mname.c_str()); - } - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002MODRELOAD\002 \002FileName\002\n" - " \n" - "This command reloads the module named FileName.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "MODLOAD", _("MODRELOAD \037FileName\037")); - } -}; - -class OSModReLoad : public Module -{ - CommandOSModReLoad commandosmodreload; - - public: - OSModReLoad(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - this->SetPermanent(true); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmodreload); - } -}; - -MODULE_INIT(OSModReLoad) diff --git a/modules/core/os_module.cpp b/modules/core/os_module.cpp new file mode 100644 index 000000000..fb56d322e --- /dev/null +++ b/modules/core/os_module.cpp @@ -0,0 +1,202 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class CommandOSModLoad : public Command +{ + public: + CommandOSModLoad(Module *creator) : Command(creator, "operserv/modload", 1, 1, "operserv/modload") + { + this->SetDesc(_("Load a module")); + this->SetSyntax(_("\037modname\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &mname = params[0]; + + ModuleReturn status = ModuleManager::LoadModule(mname, u); + if (status == MOD_ERR_OK) + { + ircdproto->SendGlobops(source.owner, "%s loaded module %s", u->nick.c_str(), mname.c_str()); + source.Reply(_("Module \002%s\002 loaded"), mname.c_str()); + + /* If a user is loading this module, then the core databases have already been loaded + * so trigger the event manually + */ + Module *m = ModuleManager::FindModule(mname); + if (m) + m->OnPostLoadDatabases(); + } + else if (status == MOD_ERR_EXISTS) + source.Reply(_("Module \002%s\002 is already loaded."), mname.c_str()); + else + source.Reply(_("Unable to load module \002%s\002"), mname.c_str()); + + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command loads the module named FileName from the modules\n" + "directory.")); + return true; + } +}; + +class CommandOSModReLoad : public Command +{ + public: + CommandOSModReLoad(Module *creator) : Command(creator, "operserv/modreload", 1, 1, "operserv/modload") + { + this->SetDesc(_("Reload a module")); + this->SetSyntax(_("\037modname\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &mname = params[0]; + + Module *m = ModuleManager::FindModule(mname); + if (!m) + { + source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); + return; + } + + if (!m->handle || m->GetPermanent()) + { + source.Reply(_("Unable to remove module \002%s\002"), m->name.c_str()); + return; + } + + /* Unrecoverable */ + bool fatal = m->type == PROTOCOL; + ModuleReturn status = ModuleManager::UnloadModule(m, u); + + if (status != MOD_ERR_OK) + { + source.Reply(_("Unable to remove module \002%s\002"), mname.c_str()); + return; + } + + status = ModuleManager::LoadModule(mname, u); + if (status == MOD_ERR_OK) + { + ircdproto->SendGlobops(source.owner, "%s reloaded module %s", u->nick.c_str(), mname.c_str()); + source.Reply(_("Module \002%s\002 reloaded"), mname.c_str()); + + /* If a user is loading this module, then the core databases have already been loaded + * so trigger the event manually + */ + m = ModuleManager::FindModule(mname); + if (m) + m->OnPostLoadDatabases(); + } + else + { + if (fatal) + throw FatalException("Unable to reload module " + mname); + else + source.Reply(_("Unable to load module \002%s\002"), mname.c_str()); + } + + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command reloads the module named FileName.")); + return true; + } +}; + +class CommandOSModUnLoad : public Command +{ + public: + CommandOSModUnLoad(Module *creator) : Command(creator, "operserv/modunload", 1, 1, "operserv/modload") + { + this->SetDesc(_("Un-Load a module")); + this->SetSyntax(_("\037modname\037")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &mname = params[0]; + + Module *m = ModuleManager::FindModule(mname); + if (!m) + { + source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); + return; + } + + if (!m->handle || m->GetPermanent() || m->type == PROTOCOL) + { + source.Reply(_("Unable to remove module \002%s\002"), m->name.c_str()); + return; + } + + Log() << "Trying to unload module [" << mname << "]"; + + ModuleReturn status = ModuleManager::UnloadModule(m, u); + + if (status == MOD_ERR_OK) + { + source.Reply(_("Module \002%s\002 unloaded"), mname.c_str()); + ircdproto->SendGlobops(source.owner, "%s unloaded module %s", u->nick.c_str(), mname.c_str()); + } + else + source.Reply(_("Unable to remove module \002%s\002"), mname.c_str()); + + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("This command unloads the module named FileName from the modules\n" + "directory.")); + return true; + } +}; + +class OSModule : public Module +{ + CommandOSModLoad commandosmodload; + CommandOSModReLoad commandosmodreload; + CommandOSModUnLoad commandosmodunload; + + public: + OSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosmodload(this), commandosmodreload(this), commandosmodunload(this) + { + this->SetAuthor("Anope"); + this->SetPermanent(true); + + ModuleManager::RegisterService(&commandosmodload); + ModuleManager::RegisterService(&commandosmodreload); + ModuleManager::RegisterService(&commandosmodunload); + } +}; + +MODULE_INIT(OSModule) diff --git a/modules/core/os_modunload.cpp b/modules/core/os_modunload.cpp deleted file mode 100644 index e349e9d02..000000000 --- a/modules/core/os_modunload.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSModUnLoad : public Command -{ - public: - CommandOSModUnLoad() : Command("MODUNLOAD", 1, 1, "operserv/modload") - { - this->SetDesc(_("Un-Load a module")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - const Anope::string &mname = params[0]; - - Module *m = ModuleManager::FindModule(mname); - if (!m) - { - source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); - return MOD_CONT; - } - - if (!m->handle || m->GetPermanent() || m->type == PROTOCOL) - { - source.Reply(_("Unable to remove module \002%s\002"), m->name.c_str()); - return MOD_CONT; - } - - Log() << "Trying to unload module [" << mname << "]"; - - ModuleReturn status = ModuleManager::UnloadModule(m, u); - - if (status == MOD_ERR_OK) - { - source.Reply(_("Module \002%s\002 unloaded"), mname.c_str()); - ircdproto->SendGlobops(operserv->Bot(), "%s unloaded module %s", u->nick.c_str(), mname.c_str()); - } - else - source.Reply(_("Unable to remove module \002%s\002"), mname.c_str()); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002MODUNLOAD\002 \002FileName\002\n" - " \n" - "This command unloads the module named FileName from the modules\n" - "directory.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "MODUNLOAD", _("MODUNLOAD \037FileName\037")); - } -}; - -class OSModUnLoad : public Module -{ - CommandOSModUnLoad commandosmodunload; - - public: - OSModUnLoad(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - this->SetPermanent(true); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosmodunload); - } -}; - -MODULE_INIT(OSModUnLoad) diff --git a/modules/core/os_news.cpp b/modules/core/os_news.cpp index 3423b1258..f43fd41cb 100644 --- a/modules/core/os_news.cpp +++ b/modules/core/os_news.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "global.h" #include "os_news.h" @@ -23,9 +22,7 @@ enum MSG_SYNTAX, MSG_LIST_HEADER, MSG_LIST_NONE, - MSG_ADD_SYNTAX, MSG_ADDED, - MSG_DEL_SYNTAX, MSG_DEL_NOT_FOUND, MSG_DELETED, MSG_DEL_NONE, @@ -37,9 +34,7 @@ struct NewsMessages msgarray[] = { {_("LOGONNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), _("Logon news items:"), _("There is no logon news."), - _("Syntax: \002LOGONNEWS ADD \037text\037\002"), _("Added new logon news item."), - _("Syntax: \002LOGONNEWS DEL {\037num\037 | ALL}"), _("Logon news item #%s not found!"), _("Logon news item #%d deleted."), _("No logon news items to delete!"), @@ -49,9 +44,7 @@ struct NewsMessages msgarray[] = { {_("OPERNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), _("Oper news items:"), _("There is no oper news."), - _("Syntax: \002OPERNEWS ADD \037text\037\002"), _("Added new oper news item."), - _("Syntax: \002OPERNEWS DEL {\037num\037 | ALL}"), _("Oper news item #%s not found!"), _("Oper news item #%d deleted."), _("No oper news items to delete!"), @@ -61,9 +54,7 @@ struct NewsMessages msgarray[] = { {_("RANDOMNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), _("Random news items:"), _("There is no random news."), - _("Syntax: \002RANDOMNEWS ADD \037text\037\002"), _("Added new random news item."), - _("Syntax: \002RANDOMNEWS DEL {\037num\037 | ALL}"), _("Random news item #%s not found!"), _("Random news item #%d deleted."), _("No random news items to delete!"), @@ -118,7 +109,7 @@ class NewsBase : public Command service_reference<NewsService> ns; protected: - CommandReturn DoList(CommandSource &source, NewsType type, const char **msgs) + void DoList(CommandSource &source, NewsType type, const char **msgs) { std::vector<NewsItem *> &list = this->ns->GetNewsList(type); if (list.empty()) @@ -128,13 +119,13 @@ class NewsBase : public Command source.Reply(msgs[MSG_LIST_HEADER]); for (unsigned i = 0, end = list.size(); i < end; ++i) source.Reply(_("%5d (%s by %s)\n"" %s"), i + 1, do_strftime(list[i]->time).c_str(), !list[i]->who.empty() ? list[i]->who.c_str() : "<unknown>", list[i]->text.c_str()); - source.Reply(_(END_OF_ANY_LIST), "News"); + source.Reply(END_OF_ANY_LIST, "News"); } - return MOD_CONT; + return; } - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type, const char **msgs) + void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type, const char **msgs) { const Anope::string text = params.size() > 1 ? params[1] : ""; @@ -143,7 +134,7 @@ class NewsBase : public Command else { if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); NewsItem *news = new NewsItem(); news->type = type; @@ -156,10 +147,10 @@ class NewsBase : public Command source.Reply(msgs[MSG_ADDED]); } - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type, const char **msgs) + void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type, const char **msgs) { const Anope::string &text = params.size() > 1 ? params[1] : ""; @@ -173,7 +164,7 @@ class NewsBase : public Command else { if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); if (!text.equals_ci("ALL")) { try @@ -183,7 +174,7 @@ class NewsBase : public Command { this->ns->DelNewsItem(list[num - 1]); source.Reply(msgs[MSG_DELETED], num); - return MOD_CONT; + return; } } catch (const ConvertException &) { } @@ -199,13 +190,13 @@ class NewsBase : public Command } } - return MOD_CONT; + return; } - CommandReturn DoNews(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type) + void DoNews(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType type) { if (!this->ns) - return MOD_CONT; + return; const Anope::string &cmd = params[0]; @@ -222,44 +213,43 @@ class NewsBase : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } public: - NewsBase(const Anope::string &newstype) : Command(newstype, 1, 2, "operserv/news"), ns("news") + NewsBase(Module *creator, const Anope::string &newstype) : Command(creator, newstype, 1, 2, "operserv/news"), ns("news") { + this->SetSyntax(_("ADD \037text\037")); + this->SetSyntax(_("DEL {\037num\037 | ALL}")); + this->SetSyntax(_("LIST")); } virtual ~NewsBase() { } - virtual CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; + virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; - - virtual void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) = 0; }; class CommandOSLogonNews : public NewsBase { public: - CommandOSLogonNews() : NewsBase("LOGONNEWS") + CommandOSLogonNews(Module *creator) : NewsBase(creator, "operserv/loginnews") { this->SetDesc(_("Define messages to be shown to users at logon")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoNews(source, params, NEWS_LOGON); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002LOGONNEWS ADD \037text\037\002\n" - " \002LOGONNEWS DEL {\037num\037 | ALL}\002\n" - " \002LOGONNEWS LIST\002\n" - " \n" - "Edits or displays the list of logon news messages. When a\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Edits or displays the list of logon news messages. When a\n" "user connects to the network, these messages will be sent\n" "to them. (However, no more than \002%d\002 messages will be\n" "sent in order to avoid flooding the user. If there are\n" @@ -269,33 +259,26 @@ class CommandOSLogonNews : public NewsBase "LOGONNEWS may only be used by Services Operators."), Config->NewsCount); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "LOGONNEWS", _("LOGONNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002")); - } }; class CommandOSOperNews : public NewsBase { public: - CommandOSOperNews() : NewsBase("OPERNEWS") + CommandOSOperNews(Module *creator) : NewsBase(creator, "operserv/opernews") { this->SetDesc(_("Define messages to be shown to users who oper")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoNews(source, params, NEWS_OPER); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OPERNEWS ADD \037text\037\002\n" - " \002OPERNEWS DEL {\037num\037 | ALL}\002\n" - " \002OPERNEWS LIST\002\n" - " \n" - "Edits or displays the list of oper news messages. When a\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Edits or displays the list of oper news messages. When a\n" "user opers up (with the /OPER command), these messages will\n" "be sent to them. (However, no more than \002%d\002 messages will\n" "be sent in order to avoid flooding the user. If there are\n" @@ -305,44 +288,32 @@ class CommandOSOperNews : public NewsBase "OPERNEWS may only be used by Services Operators."), Config->NewsCount); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "OPERNEWS", _("OPERNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002")); - } }; class CommandOSRandomNews : public NewsBase { public: - CommandOSRandomNews() : NewsBase("RANDOMNEWS") + CommandOSRandomNews(Module *creator) : NewsBase(creator, "operserv/randomnews") { this->SetDesc(_("Define messages to be randomly shown to users at logon")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoNews(source, params, NEWS_RANDOM); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002RANDOMNEWS ADD \037text\037\002\n" - " \002RANDOMNEWS DEL {\037num\037 | ALL}\002\n" - " \002RANDOMNEWS LIST\002\n" - " \n" - "Edits or displays the list of random news messages. When a\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Edits or displays the list of random news messages. When a\n" "user connects to the network, one (and only one) of the\n" "random news will be randomly chosen and sent to them.\n" " \n" "RANDOMNEWS may only be used by Services Operators.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "RANDOMNEWS", _("RANDOMNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002")); - } }; class OSNews : public Module @@ -374,7 +345,14 @@ class OSNews : public Module if (Type == NEWS_RANDOM && i != cur_rand_news) continue; - u->SendMessage(Type != NEWS_OPER && global ? global->Bot() : operserv->Bot(), msg.c_str(), do_strftime(newsList[i]->time).c_str(), newsList[i]->text.c_str()); + BotInfo *gl = findbot(Config->Global); + if (!gl && !BotListByNick.empty()) + gl = BotListByNick.begin()->second; + BotInfo *os = findbot(Config->OperServ); + if (!os) + os = gl; + if (gl) + u->SendMessage(Type != NEWS_OPER ? gl : os, msg.c_str(), do_strftime(newsList[i]->time).c_str(), newsList[i]->text.c_str()); ++displayed; @@ -393,16 +371,14 @@ class OSNews : public Module } public: - OSNews(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), newsservice(this) + OSNews(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + newsservice(this), commandoslogonnews(this), commandosopernews(this), commandosrandomnews(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandoslogonnews); - this->AddCommand(operserv->Bot(), &commandosopernews); - this->AddCommand(operserv->Bot(), &commandosrandomnews); + ModuleManager::RegisterService(&commandoslogonnews); + ModuleManager::RegisterService(&commandosopernews); + ModuleManager::RegisterService(&commandosrandomnews); Implementation i[] = { I_OnUserModeSet, I_OnUserConnect, I_OnDatabaseRead, I_OnDatabaseWrite }; ModuleManager::Attach(i, this, 4); diff --git a/modules/core/os_noop.cpp b/modules/core/os_noop.cpp index b17f26dfc..9fdaf0ebb 100644 --- a/modules/core/os_noop.cpp +++ b/modules/core/os_noop.cpp @@ -12,17 +12,18 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSNOOP : public Command { public: - CommandOSNOOP() : Command("NOOP", 2, 2, "operserv/noop") + CommandOSNOOP(Module *creator) : Command(creator, "operserv/noop", 2, 2, "operserv/noop") { this->SetDesc(_("Temporarily remove all O:lines of a server remotely")); + this->SetSyntax(_("SET \037server\037")); + this->SetSyntax(_("REVOKE \037server\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &cmd = params[0]; @@ -47,7 +48,7 @@ class CommandOSNOOP : public Command ++it; if (u2 && u2->HasMode(UMODE_OPER) && u2->server == s) - u2->Kill(Config->s_OperServ, reason); + u2->Kill(Config->OperServ, reason); } } else if (cmd.equals_ci("REVOKE")) @@ -59,15 +60,14 @@ class CommandOSNOOP : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002NOOP SET \037server\037\002\n" - " \002NOOP REVOKE \037server\037\002\n" - "\n" - "\002NOOP SET\002 remove all O:lines of the given\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("\002NOOP SET\002 remove all O:lines of the given\n" "\002server\002 and kill all IRCops currently on it to\n" "prevent them from rehashing the server (because this\n" "would just cancel the effect).\n" @@ -75,11 +75,6 @@ class CommandOSNOOP : public Command "on the given \002server\002.\n")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "NOOP", _("NOOP {SET|REVOKE} \037server\037")); - } }; class OSNOOP : public Module @@ -87,14 +82,12 @@ class OSNOOP : public Module CommandOSNOOP commandosnoop; public: - OSNOOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSNOOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosnoop(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosnoop); + ModuleManager::RegisterService(&commandosnoop); } }; diff --git a/modules/core/os_oline.cpp b/modules/core/os_oline.cpp index 861ea310a..f07996542 100644 --- a/modules/core/os_oline.cpp +++ b/modules/core/os_oline.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSOLine : public Command { public: - CommandOSOLine() : Command("OLINE", 2, 2, "operserv/oline") + CommandOSOLine(Module *creator) : Command(creator, "operserv/oline", 2, 2, "operserv/oline") { this->SetDesc(_("Give Operflags to a certain user")); + this->SetSyntax(_("\037nick\037 \037flags\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; @@ -31,41 +31,36 @@ class CommandOSOLine : public Command /* let's check whether the user is online */ if (!(u2 = finduser(nick))) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (u2 && flag[0] == '+') { - ircdproto->SendSVSO(Config->s_OperServ, nick, flag); - u2->SetMode(operserv->Bot(), UMODE_OPER); - u2->SendMessage(operserv->Bot(), _("You are now an IRC Operator.")); + ircdproto->SendSVSO(Config->OperServ, nick, flag); + u2->SetMode(source.owner, UMODE_OPER); + u2->SendMessage(source.owner, _("You are now an IRC Operator.")); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); - ircdproto->SendGlobops(operserv->Bot(), "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); + ircdproto->SendGlobops(source.owner, "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); } else if (u2 && flag[0] == '-') { - ircdproto->SendSVSO(Config->s_OperServ, nick, flag); + ircdproto->SendSVSO(Config->OperServ, nick, flag); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); - ircdproto->SendGlobops(operserv->Bot(), "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); + ircdproto->SendGlobops(source.owner, "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); } else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OLINE \037user\037 \037flags\037\002\n" - " \n" - "Allows Services Opers to give Operflags to any user.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Opers to give Operflags to any user.\n" "Flags have to be prefixed with a \"+\" or a \"-\". To\n" "remove all flags simply type a \"-\" instead of any flags.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "OLINE", _("OLINE \037nick\037 \037flags\037")); - } }; class OSOLine : public Module @@ -73,17 +68,15 @@ class OSOLine : public Module CommandOSOLine commandosoline; public: - OSOLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSOLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosoline(this) { + this->SetAuthor("Anope"); + if (!ircd || !ircd->omode) throw ModuleException("Your IRCd does not support OMODE."); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->SetAuthor("Anope"); - - this->AddCommand(operserv->Bot(), &commandosoline); + ModuleManager::RegisterService(&commandosoline); } }; diff --git a/modules/core/os_oper.cpp b/modules/core/os_oper.cpp index 80a5dc4be..e1a09dcb8 100644 --- a/modules/core/os_oper.cpp +++ b/modules/core/os_oper.cpp @@ -12,17 +12,20 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSOper : public Command { public: - CommandOSOper() : Command("OPER", 1, 3, "operserv/oper") + CommandOSOper(Module *creator) : Command(creator, "operserv/oper", 1, 3, "operserv/oper") { this->SetDesc(_("View and change services operators")); + this->SetSyntax(_("ADD \037oper\037 \037type\037")); + this->SetSyntax(_("DEL [\037oper\037]")); + this->SetSyntax(_("INFO [\037type\037]")); + this->SetSyntax(_("LIST")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &subcommand = params[0]; @@ -33,7 +36,7 @@ class CommandOSOper : public Command NickAlias *na = findnick(oper); if (na == NULL) - source.Reply(_(NICK_X_NOT_REGISTERED), oper.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); else { OperType *ot = OperType::Find(type); @@ -56,7 +59,7 @@ class CommandOSOper : public Command NickAlias *na = findnick(oper); if (na == NULL) - source.Reply(_(NICK_X_NOT_REGISTERED), oper.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); else if (!na->nc || !na->nc->o) source.Reply(_("Nick \2%s\2 is not a services operator."), oper.c_str()); else @@ -146,23 +149,18 @@ class CommandOSOper : public Command else this->OnSyntaxError(source, subcommand); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002OPER {ADD|DEL|LIST|INFO} [\037oper\037] [\037type\037\002\n" - "\n" - "\002OPER\002 allows you to change and view services operators.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows you to change and view services operators.\n" "Note that operators removed by this command but are still set in\n" "the configuration file are not permanently affected by this.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "OPER", _("OPER {ADD|DEL|LIST|INFO} [\037oper\037] [\037type\037")); - } }; class OSOper : public Module @@ -170,17 +168,15 @@ class OSOper : public Module CommandOSOper commandosoper; public: - OSOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosoper(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - Implementation i[] = { I_OnDatabaseWrite, I_OnDatabaseRead }; ModuleManager::Attach(i, this, 2); - this->AddCommand(operserv->Bot(), &commandosoper); + ModuleManager::RegisterService(&commandosoper); } void OnDatabaseWrite(void (*Write)(const Anope::string &)) @@ -212,7 +208,7 @@ class OSOper : public Module if (ot == NULL) return EVENT_CONTINUE; nc->o = new Oper(nc->display, "", "", ot); - Log(LOG_NORMAL, "operserv/oper", operserv->Bot()) << "Tied oper " << nc->display << " to type " << ot->GetName(); + Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName(); } return EVENT_CONTINUE; } diff --git a/modules/core/os_quit.cpp b/modules/core/os_quit.cpp deleted file mode 100644 index 5c73f4b8a..000000000 --- a/modules/core/os_quit.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * - */ -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSQuit : public Command -{ - public: - CommandOSQuit() : Command("QUIT", 0, 0, "operserv/quit") - { - this->SetDesc(_("Terminate the Services program with no save")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - quitmsg = "QUIT command received from " + u->nick; - quitting = true; - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002QUIT\002\n" - " \n" - "Causes Services to do an immediate shutdown; databases are\n" - "\002not\002 saved. This command should not be used unless\n" - "damage to the in-memory copies of the databases is feared\n" - "and they should not be saved. For normal shutdowns, use the\n" - "\002SHUTDOWN\002 command.")); - return true; - } -}; - -class OSQuit : public Module -{ - CommandOSQuit commandosquit; - - public: - OSQuit(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosquit); - } -}; - -MODULE_INIT(OSQuit) diff --git a/modules/core/os_reload.cpp b/modules/core/os_reload.cpp index 41d85f520..4d34a8ab1 100644 --- a/modules/core/os_reload.cpp +++ b/modules/core/os_reload.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSReload : public Command { public: - CommandOSReload() : Command("RELOAD", 0, 0, "operserv/reload") + CommandOSReload(Module *creator) : Command(creator, "operserv/reload", 0, 0, "operserv/reload") { this->SetDesc(_("Reload services' configuration file")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { ServerConfig *old_config = Config; @@ -40,13 +40,14 @@ class CommandOSReload : public Command source.Reply(_("Error reloading confguration file: ") + ex.GetReason()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002RELOAD\002\n" - "Causes Services to reload the configuration file. Note that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Causes Services to reload the configuration file. Note that\n" "some directives still need the restart of the Services to\n" "take effect (such as Services' nicknames, activation of the \n" "session limitation, etc.)")); @@ -59,14 +60,12 @@ class OSReload : public Module CommandOSReload commandosreload; public: - OSReload(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSReload(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosreload(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosreload); + ModuleManager::RegisterService(&commandosreload); } }; diff --git a/modules/core/os_restart.cpp b/modules/core/os_restart.cpp deleted file mode 100644 index ea8f4b864..000000000 --- a/modules/core/os_restart.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSRestart : public Command -{ - public: - CommandOSRestart() : Command("RESTART", 0, 0, "operserv/restart") - { - this->SetDesc(_("Save databases and restart Services")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - quitmsg = "RESTART command received from " + u->nick; - save_databases(); - quitting = restarting = true; - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002RESTART\002\n" - " \n" - "Causes Services to save all databases and then restart\n" - "(i.e. exit and immediately re-run the executable).")); - return true; - } -}; - -class OSRestart : public Module -{ - CommandOSRestart commandosrestart; - - public: - OSRestart(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosrestart); - } -}; - -MODULE_INIT(OSRestart) diff --git a/modules/core/os_session.cpp b/modules/core/os_session.cpp index 3926fbee1..e3575f8d1 100644 --- a/modules/core/os_session.cpp +++ b/modules/core/os_session.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "os_session.h" static service_reference<SessionService> sessionservice("session"); @@ -103,8 +102,9 @@ class ExpireTimer : public Timer if (!e->expires || e->expires > Anope::CurTime) continue; - if (Config->WallExceptionExpire) - ircdproto->SendGlobops(operserv->Bot(), "Session exception for %s has expired.", e->mask.c_str()); + BotInfo *bi = findbot(Config->OperServ); + if (Config->WallExceptionExpire && bi) + ircdproto->SendGlobops(bi, "Session exception for %s has expired.", e->mask.c_str()); sessionservice->DelException(e); delete e; } @@ -219,7 +219,7 @@ class ExceptionViewCallback : public ExceptionListCallback class CommandOSSession : public Command { private: - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string param = params[1]; @@ -246,10 +246,10 @@ class CommandOSSession : public Command } } - return MOD_CONT; + return; } - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string param = params[1]; Session *session = sessionservice->FindSession(param); @@ -262,22 +262,24 @@ class CommandOSSession : public Command source.Reply(_("The host \002%s\002 currently has \002%d\002 sessions with a limit of \002%d\002."), param.c_str(), session->count, exception ? exception-> limit : Config->DefSessionLimit); } - return MOD_CONT; + return; } public: - CommandOSSession() : Command("SESSION", 2, 2, "operserv/session") + CommandOSSession(Module *creator) : Command(creator, "operserv/session", 2, 2, "operserv/session") { this->SetDesc(_("View the list of host sessions")); + this->SetSyntax(_("LIST \037threshold\037")); + this->SetSyntax(_("VIEW \037host\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[0]; if (!Config->LimitSessions) { source.Reply(_("Session limiting is disabled.")); - return MOD_CONT; + return; } if (cmd.equals_ci("LIST")) @@ -287,15 +289,14 @@ class CommandOSSession : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SESSION LIST \037threshold\037\002\n" - " \002SESSION VIEW \037host\037\002\n" - " \n" - "Allows Services Operators to view the session list.\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Operators to view the session list.\n" "\002SESSION LIST\002 lists hosts with at least \037threshold\037 sessions.\n" "The threshold must be a number greater than 1. This is to \n" "prevent accidental listing of the large number of single \n" @@ -308,17 +309,12 @@ class CommandOSSession : public Command "hosts and groups thereof.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SESSION", _("SESSION LIST \037limit\037")); - } }; class CommandOSException : public Command { private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; Anope::string mask, expiry, limitstr; @@ -337,7 +333,7 @@ class CommandOSException : public Command if (params.size() <= last_param) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } Anope::string reason = params[last_param]; @@ -346,14 +342,14 @@ class CommandOSException : public Command if (reason.empty()) { this->OnSyntaxError(source, "ADD"); - return MOD_CONT; + return; } time_t expires = !expiry.empty() ? dotime(expiry) : Config->ExceptionExpiry; if (expires < 0) { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; + source.Reply(BAD_EXPIRY_TIME); + return; } else if (expires > 0) expires += Anope::CurTime; @@ -368,14 +364,14 @@ class CommandOSException : public Command if (limit < 0 || limit > static_cast<int>(Config->MaxSessionLimit)) { source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), Config->MaxSessionLimit); - return MOD_CONT; + return; } else { if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) { source.Reply(_("Invalid hostmask. Only real hostmasks are valid as sessionservice->GetExceptions() are not matched against nicks or usernames.")); - return MOD_CONT; + return; } for (std::vector<Exception *>::iterator it = sessionservice->GetExceptions().begin(), it_end = sessionservice->GetExceptions().end(); it != it_end; ++it) @@ -410,21 +406,21 @@ class CommandOSException : public Command sessionservice->AddException(exception); source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit); if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); } } - return MOD_CONT; + return; } - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &mask = params.size() > 1 ? params[1] : ""; if (mask.empty()) { this->OnSyntaxError(source, "DEL"); - return MOD_CONT; + return; } if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) @@ -447,12 +443,12 @@ class CommandOSException : public Command } if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); - return MOD_CONT; + return; } - CommandReturn DoMove(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoMove(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &n1str = params.size() > 1 ? params[1] : ""; /* From position */ const Anope::string &n2str = params.size() > 2 ? params[2] : ""; /* To position */ @@ -461,7 +457,7 @@ class CommandOSException : public Command if (n2str.empty()) { this->OnSyntaxError(source, "MOVE"); - return MOD_CONT; + return; } n1 = n2 = -1; @@ -481,15 +477,15 @@ class CommandOSException : public Command source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), sessionservice->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1); if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(READ_ONLY_MODE); } else this->OnSyntaxError(source, "MOVE"); - return MOD_CONT; + return; } - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string mask = params.size() > 1 ? params[1] : ""; @@ -519,10 +515,10 @@ class CommandOSException : public Command source.Reply(_("No matching entries on session-limit exception list.")); } - return MOD_CONT; + return; } - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string mask = params.size() > 1 ? params[1] : ""; @@ -551,23 +547,28 @@ class CommandOSException : public Command source.Reply(_("No matching entries on session-limit exception list.")); } - return MOD_CONT; + return; } public: - CommandOSException() : Command("EXCEPTION", 1, 5) + CommandOSException(Module *creator) : Command(creator, "operserv/exception", 1, 5) { this->SetDesc(_("Modify the session-limit exception list")); + this->SetSyntax(_("ADD [\037+expiry\037] \037mask\037 \037limit\037 \037reason\037")); + this->SetSyntax(_("DEL {\037mask\037 | \037list\037}")); + this->SetSyntax(_("MOVE \037num\037 \037position\037")); + this->SetSyntax(_("LIST [\037mask\037 | \037list\037]")); + this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &cmd = params[0]; if (!Config->LimitSessions) { source.Reply(_("Session limiting is disabled.")); - return MOD_CONT; + return; } if (cmd.equals_ci("ADD")) @@ -583,27 +584,24 @@ class CommandOSException : public Command else this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002EXCEPTION ADD [\037+expiry\037] \037mask\037 \037limit\037 \037reason\037\002\n" - " \002EXCEPTION DEL {\037mask\037 | \037list\037}\002\n" - " \002EXCEPTION MOVE \037num\037 \037position\037\002\n" - " \002EXCEPTION LIST [\037mask\037 | \037list\037]\002\n" - " \002EXCEPTION VIEW [\037mask\037 | \037list\037]\002\n" - " \n" - "Allows Services Operators to manipulate the list of hosts that\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services Operators to manipulate the list of hosts that\n" "have specific session limits - allowing certain machines, \n" "such as shell servers, to carry more than the default number\n" "of clients at a time. Once a host reaches its session limit,\n" "all clients attempting to connect from that host will be\n" "killed. Before the user is killed, they are notified, via a\n" "/NOTICE from %s, of a source of help regarding session\n" - "limiting. The content of this notice is a config setting.\n" - " \n" - "\002EXCEPTION ADD\002 adds the given host mask to the exception list.\n" + "limiting. The content of this notice is a config setting.\n"), + Config->OperServ.c_str()); + source.Reply(" "); + source.Reply(_("\002EXCEPTION ADD\002 adds the given host mask to the exception list.\n" "Note that \002nick!user@host\002 and \002user@host\002 masks are invalid!\n" "Only real host masks, such as \002box.host.dom\002 and \002*.host.dom\002,\n" "are allowed because sessions limiting does not take nick or\n" @@ -623,16 +621,9 @@ class CommandOSException : public Command "host mask and the expiry date and time.\n" " \n" "Note that a connecting client will \"use\" the first exception\n" - "their host matches. Large exception lists and widely matching\n" - "exception masks are likely to degrade services' performance."), - Config->s_OperServ.c_str()); + "their host matches.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "EXCEPTION", _("EXCEPTION {ADD | DEL | MOVE | LIST | VIEW} [\037params\037]")); - } }; class OSSession : public Module @@ -641,6 +632,7 @@ class OSSession : public Module ExpireTimer expiretimer; CommandOSSession commandossession; CommandOSException commandosexception; + service_reference<XLineManager> akills; void AddSession(User *u, bool exempt) { @@ -672,20 +664,25 @@ class OSSession : public Module if (kill && !exempt) { - if (!Config->SessionLimitExceeded.empty()) - u->SendMessage(operserv->Bot(), Config->SessionLimitExceeded.c_str(), u->host.c_str()); - if (!Config->SessionLimitDetailsLoc.empty()) - u->SendMessage(operserv->Bot(), "%s", Config->SessionLimitDetailsLoc.c_str()); + BotInfo *bi = findbot(Config->OperServ); + if (bi) + { + if (!Config->SessionLimitExceeded.empty()) + u->SendMessage(bi, Config->SessionLimitExceeded.c_str(), u->host.c_str()); + if (!Config->SessionLimitDetailsLoc.empty()) + u->SendMessage(bi, "%s", Config->SessionLimitDetailsLoc.c_str()); + } - u->Kill(Config->s_OperServ, "Session limit exceeded"); + u->Kill(Config->OperServ, "Session limit exceeded"); ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && SGLine) + if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && akills) { const Anope::string &akillmask = "*@" + u->host; const Anope::string &akillreason = "Session limit exceeded for " + u->host; - SGLine->Add(akillmask, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, akillreason); - ircdproto->SendGlobops(operserv->Bot(), "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); + akills->Add(akillmask, Config->OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, akillreason); + if (bi) + ircdproto->SendGlobops(bi, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); } } } @@ -721,18 +718,16 @@ class OSSession : public Module } public: - OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), ss(this) + OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + ss(this), commandossession(this), commandosexception(this), akills("xlinemanager/sgline") { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - Implementation i[] = { I_OnUserConnect, I_OnUserLogoff }; ModuleManager::Attach(i, this, 2); - this->AddCommand(operserv->Bot(), &commandossession); - this->AddCommand(operserv->Bot(), &commandosexception); + ModuleManager::RegisterService(&commandossession); + ModuleManager::RegisterService(&commandosexception); ModuleManager::RegisterService(&this->ss); } diff --git a/modules/core/os_set.cpp b/modules/core/os_set.cpp index de82eee4b..36c46e439 100644 --- a/modules/core/os_set.cpp +++ b/modules/core/os_set.cpp @@ -12,12 +12,11 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSSet : public Command { private: - CommandReturn DoList(CommandSource &source) + void DoList(CommandSource &source) { Log(LOG_ADMIN, source.u, this); @@ -30,10 +29,10 @@ class CommandOSSet : public Command index = noexpire ? _("%s is enabled") : _("%s is disabled"); source.Reply(index.c_str(), "NOEXPIRE"); - return MOD_CONT; + return; } - CommandReturn DoSetReadOnly(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSetReadOnly(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &setting = params.size() > 1 ? params[1] : ""; @@ -41,7 +40,7 @@ class CommandOSSet : public Command if (setting.empty()) { this->OnSyntaxError(source, "READONLY"); - return MOD_CONT; + return; } if (setting.equals_ci("ON")) @@ -59,10 +58,10 @@ class CommandOSSet : public Command else source.Reply(_("Setting for READONLY must be \002on\002 or \002off\002.")); - return MOD_CONT; + return; } - CommandReturn DoSetSuperAdmin(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSetSuperAdmin(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &setting = params.size() > 1 ? params[1] : ""; @@ -70,7 +69,7 @@ class CommandOSSet : public Command if (setting.empty()) { this->OnSyntaxError(source, "SUPERADMIN"); - return MOD_CONT; + return; } /** @@ -85,22 +84,22 @@ class CommandOSSet : public Command u->isSuperAdmin = 1; source.Reply(_("You are now a SuperAdmin")); Log(LOG_ADMIN, u, this) << "SUPERADMIN ON"; - ircdproto->SendGlobops(operserv->Bot(), _("%s is now a Super-Admin"), u->nick.c_str()); + ircdproto->SendGlobops(source.owner, _("%s is now a Super-Admin"), u->nick.c_str()); } else if (setting.equals_ci("OFF")) { u->isSuperAdmin = 0; source.Reply(_("You are no longer a SuperAdmin")); Log(LOG_ADMIN, u, this) << "SUPERADMIN OFF"; - ircdproto->SendGlobops(operserv->Bot(), _("%s is no longer a Super-Admin"), u->nick.c_str()); + ircdproto->SendGlobops(source.owner, _("%s is no longer a Super-Admin"), u->nick.c_str()); } else source.Reply(_("Setting for SuperAdmin must be \002on\002 or \002off\002 (must be enabled in services.conf)")); - return MOD_CONT; + return; } - CommandReturn DoSetDebug(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSetDebug(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &setting = params.size() > 1 ? params[1] : ""; @@ -108,7 +107,7 @@ class CommandOSSet : public Command if (setting.empty()) { this->OnSyntaxError(source, "DEBUG"); - return MOD_CONT; + return; } if (setting.equals_ci("ON")) @@ -130,17 +129,17 @@ class CommandOSSet : public Command debug = convertTo<int>(setting); Log(LOG_ADMIN, u, this) << "DEBUG " << debug; source.Reply(_("Services are now in debug mode (level %d)."), debug); - return MOD_CONT; + return; } catch (const ConvertException &) { } source.Reply(_("Setting for DEBUG must be \002ON\002, \002OFF\002, or a positive number.")); } - return MOD_CONT; + return; } - CommandReturn DoSetNoExpire(CommandSource &source, const std::vector<Anope::string> ¶ms) + void DoSetNoExpire(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &setting = params.size() > 1 ? params[1] : ""; @@ -148,7 +147,7 @@ class CommandOSSet : public Command if (setting.empty()) { this->OnSyntaxError(source, "NOEXPIRE"); - return MOD_CONT; + return; } if (setting.equals_ci("ON")) @@ -166,15 +165,16 @@ class CommandOSSet : public Command else source.Reply(_("Setting for NOEXPIRE must be \002on\002 or \002off\002.")); - return MOD_CONT; + return; } public: - CommandOSSet() : Command("SET", 1, 2, "operserv/set") + CommandOSSet(Module *creator) : Command(creator, "operserv/set", 1, 2, "operserv/set") { this->SetDesc(_("Set various global Services options")); + this->SetSyntax(_("\037option\037 \037setting\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &option = params[0]; @@ -191,25 +191,28 @@ class CommandOSSet : public Command else source.Reply(_("Unknown option \002%s\002."), option.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { if (subcommand.empty()) - source.Reply(_("Syntax: \002SET \037option\037 \037setting\037\002\n" - "Sets various global Services options. Option names\n" + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Sets various global Services options. Option names\n" "currently defined are:\n" " READONLY Set read-only or read-write mode\n" " DEBUG Activate or deactivate debug mode\n" " NOEXPIRE Activate or deactivate no expire mode\n" " SUPERADMIN Activate or deactivate super-admin mode\n" " LIST List the options")); + } else if (subcommand.equals_ci("LIST")) - source.Reply(_("Syntax: \002SET LIST\n" - "Display the various %s settings"), Config->s_OperServ.c_str()); + source.Reply(_("Syntax: \002LIST\n" + "Display the various %s settings"), Config->OperServ.c_str()); else if (subcommand.equals_ci("READONLY")) - source.Reply(_("Syntax: \002SET READONLY {ON | OFF}\002\n" + source.Reply(_("Syntax: \002READONLY {ON | OFF}\002\n" " \n" "Sets read-only mode on or off. In read-only mode, normal\n" "users will not be allowed to modify any Services data,\n" @@ -223,14 +226,14 @@ class CommandOSSet : public Command "This option is equivalent to the command-line option\n" "\002-readonly\002.")); else if (subcommand.equals_ci("NOEXPIRE")) - source.Reply(_("Syntax: \002SET NOEXPIRE {ON | OFF}\002\n" + source.Reply(_("Syntax: \002NOEXPIRE {ON | OFF}\002\n" "Sets no expire mode on or off. In no expire mode, nicks,\n" "channels, akills and exceptions won't expire until the\n" "option is unset.\n" "This option is equivalent to the command-line option\n" "\002-noexpire\002.")); else if (subcommand.equals_ci("SUPERADMIN")) - source.Reply(_("Syntax: \002SET SUPERADMIN {ON | OFF}\002\n" + source.Reply(_("Syntax: \002SUPERADMIN {ON | OFF}\002\n" "Setting this will grant you extra privileges such as the\n" "ability to be \"founder\" on all channel's etc...\n" "This option is \002not\002 persistent, and should only be used when\n" @@ -239,11 +242,6 @@ class CommandOSSet : public Command return false; return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SET", _("SET \037option\037 \037setting\037")); - } }; class OSSet : public Module @@ -251,14 +249,12 @@ class OSSet : public Module CommandOSSet commandosset; public: - OSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosset(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosset); + ModuleManager::RegisterService(&commandosset); } }; diff --git a/modules/core/os_shutdown.cpp b/modules/core/os_shutdown.cpp index ac37fe0b8..47cb2e4cf 100644 --- a/modules/core/os_shutdown.cpp +++ b/modules/core/os_shutdown.cpp @@ -12,47 +12,105 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" + +class CommandOSQuit : public Command +{ + public: + CommandOSQuit(Module *creator) : Command(creator, "operserv/quit", 0, 0, "operserv/quit") + { + this->SetDesc(_("Terminate Services WITHOUT saving")); + this->SetSyntax(""); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + quitmsg = "QUIT command received from " + u->nick; + quitting = true; + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Causes Services to do an immediate shutdown; databases are\n" + "\002not\002 saved. This command should not be used unless\n" + "damage to the in-memory copies of the databases is feared\n" + "and they should not be saved.")); + return true; + } +}; + +class CommandOSRestart : public Command +{ + public: + CommandOSRestart(Module *creator) : Command(creator, "operserv/restart", 0, 0, "operserv/restart") + { + this->SetDesc(_("Save databases and restart Services")); + this->SetSyntax(""); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + quitmsg = "RESTART command received from " + u->nick; + save_databases(); + quitting = restarting = true; + return; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(_("Causes Services to save all databases and then restart\n" + "(i.e. exit and immediately re-run the executable).")); + return true; + } +}; class CommandOSShutdown : public Command { public: - CommandOSShutdown() : Command("SHUTDOWN", 0, 0, "operserv/shutdown") + CommandOSShutdown(Module *creator) : Command(creator, "operserv/shutdown", 0, 0, "operserv/shutdown") { this->SetDesc(_("Terminate services with save")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - quitmsg = "SHUTDOWN command received from " + u->nick; + quitmsg = source.command + " command received from " + u->nick; save_databases(); quitting = true; - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SHUTDOWN\002\n" - " \n" - "Causes Services to save all databases and then shut down.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Causes Services to save all databases and then shut down.")); return true; } }; class OSShutdown : public Module { + CommandOSQuit commandosquit; + CommandOSRestart commandosrestart; CommandOSShutdown commandosshutdown; public: - OSShutdown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSShutdown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosquit(this), commandosrestart(this), commandosshutdown(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosshutdown); + ModuleManager::RegisterService(&commandosquit); + ModuleManager::RegisterService(&commandosrestart); + ModuleManager::RegisterService(&commandosshutdown); } }; diff --git a/modules/core/os_snline.cpp b/modules/core/os_snline.cpp deleted file mode 100644 index c2939f580..000000000 --- a/modules/core/os_snline.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class SNLineDelCallback : public NumberList -{ - CommandSource &source; - unsigned Deleted; - public: - SNLineDelCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), source(_source), Deleted(0) - { - } - - ~SNLineDelCallback() - { - if (!Deleted) - source.Reply(_("No matching entries on the SNLINE list.")); - else if (Deleted == 1) - source.Reply(_("Deleted 1 entry from the SNLINE list.")); - else - source.Reply(_("Deleted %d entries from the SNLINE list."), Deleted); - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SNLine->GetEntry(Number - 1); - - if (!x) - return; - - ++Deleted; - DoDel(source, x); - } - - static void DoDel(CommandSource &source, XLine *x) - { - SNLine->DelXLine(x); - } -}; - -class SNLineListCallback : public NumberList -{ - protected: - CommandSource &source; - bool SentHeader; - public: - SNLineListCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), source(_source), SentHeader(false) - { - } - - ~SNLineListCallback() - { - if (!SentHeader) - source.Reply(_("No matching entries on the SNLINE list.")); - } - - virtual void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SNLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SNLINE list:\n Num Mask Reason")); - } - - DoList(source, x, Number - 1); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - source.Reply(_(OPER_LIST_FORMAT), Number + 1, x->Mask.c_str(), x->Reason.c_str()); - } -}; - -class SNLineViewCallback : public SNLineListCallback -{ - public: - SNLineViewCallback(CommandSource &_source, const Anope::string &numlist) : SNLineListCallback(_source, numlist) - { - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SNLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SNLINE list:")); - } - - DoList(source, x, Number - 1); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - Anope::string expirebuf = expire_left(source.u->Account(), x->Expires); - source.Reply(_(OPER_VIEW_FORMAT), Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expirebuf.c_str(), x->Reason.c_str()); - } -}; - -class CommandOSSNLine : public Command -{ - private: - CommandReturn OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - unsigned last_param = 2; - Anope::string param, expiry; - time_t expires; - - param = params.size() > 1 ? params[1] : ""; - if (!param.empty() && param[0] == '+') - { - expiry = param; - param = params.size() > 2 ? params[2] : ""; - last_param = 3; - } - - expires = !expiry.empty() ? dotime(expiry) : Config->SNLineExpiry; - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (param.empty()) - { - this->OnSyntaxError(source, "ADD"); - return MOD_CONT; - } - - Anope::string rest = param; - if (params.size() > last_param) - rest += " " + params[last_param]; - - if (rest.find(':') == Anope::string::npos) - { - this->OnSyntaxError(source, "ADD"); - return MOD_CONT; - } - - sepstream sep(rest, ':'); - Anope::string mask; - sep.GetToken(mask); - Anope::string reason = sep.GetRemaining(); - - if (!mask.empty() && !reason.empty()) - { - std::pair<int, XLine *> canAdd = SNLine->CanAdd(mask, expires); - if (mask.find_first_not_of("*?") == Anope::string::npos) - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - else if (canAdd.first == 1) - source.Reply(_("\002%s\002 already exists on the SNLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - else - { - /* Clean up the last character of the mask if it is a space - * See bug #761 - */ - unsigned masklen = mask.length(); - if (mask[masklen - 1] == ' ') - mask.erase(masklen - 1); - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (Anope::Match(it->second->realname, mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SNLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } - - XLine *x = SNLine->Add(mask, u->nick, expires, reason); - - if (!x) - return MOD_CONT; - - source.Reply(_("\002%s\002 added to the SNLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - } - - } - else - this->OnSyntaxError(source, "ADD"); - - return MOD_CONT; - } - - CommandReturn OnDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (SNLine->GetList().empty()) - { - source.Reply(_("SNLINE list is empty.")); - return MOD_CONT; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return MOD_CONT; - } - - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SNLineDelCallback list(source, mask); - list.Process(); - } - else - { - XLine *x = SNLine->HasEntry(mask); - - if (!x) - { - source.Reply(_("\002%s\002 not found on the SNLINE list."), mask.c_str()); - return MOD_CONT; - } - - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, x, X_SNLINE)); - - SNLineDelCallback::DoDel(source, x); - source.Reply(_("\002%s\002 deleted from the SNLINE list."), mask.c_str()); - } - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - - return MOD_CONT; - } - - CommandReturn OnList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SNLine->GetList().empty()) - { - source.Reply(_("SNLINE list is empty.")); - return MOD_CONT; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SNLineListCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - { - XLine *x = SNLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SNLINE list:\n Num Mask Reason")); - } - - SNLineListCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SNLINE list.")); - else - source.Reply(_(END_OF_ANY_LIST), "SNLine"); - } - - return MOD_CONT; - } - - CommandReturn OnView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SNLine->GetList().empty()) - { - source.Reply(_("SNLINE list is empty.")); - return MOD_CONT; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SNLineViewCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - { - XLine *x = SNLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SNLINE list:")); - } - - SNLineViewCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SNLINE list.")); - } - - return MOD_CONT; - } - - CommandReturn OnClear(CommandSource &source) - { - User *u = source.u; - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, NULL, X_SNLINE)); - SNLine->Clear(); - source.Reply(_("The SNLINE list has been cleared.")); - - return MOD_CONT; - } - public: - CommandOSSNLine() : Command("SNLINE", 1, 3, "operserv/snline") - { - this->SetDesc(_("Manipulate the SNLINE list")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &cmd = params[0]; - - if (cmd.equals_ci("ADD")) - return this->OnAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->OnDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->OnList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->OnView(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->OnClear(source); - else - this->OnSyntaxError(source, ""); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002SNLINE ADD [+\037expiry\037] \037mask\037:\037reason\037\002\n" - " \002SNLINE DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002SNLINE LIST [\037mask\037 | \037list\037]\002\n" - " \002SNLINE VIEW [\037mask\037 | \037list\037]\002\n" - " \002SNLINE CLEAR\002\n" - " \n" - "Allows Services operators to manipulate the SNLINE list. If\n" - "a user with a realname matching an SNLINE mask attempts to \n" - "connect, Services will not allow it to pursue his IRC\n" - "session.\n" - " \n" - "\002SNLINE ADD\002 adds the given realname mask to the SNLINE\n" - "list for the given reason (which \002must\002 be given).\n" - "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" - "\0371h30m\037) are not permitted. If a unit specifier is not \n" - "included, the default is days (so \037+30\037 by itself means 30 \n" - "days). To add an SNLINE which does not expire, use \037+0\037. If the\n" - "realname mask to be added starts with a \037+\037, an expiry time must\n" - "be given, even if it is the same as the default. The\n" - "current SNLINE default expiry time can be found with the\n" - "\002STATS AKILL\002 command.\n" - "Note: because the realname mask may contain spaces, the\n" - "separator between it and the reason is a colon.\n" - " \n" - "The \002SNLINE DEL\002 command removes the given mask from the\n" - "SNLINE list if it is present. If a list of entry numbers is \n" - "given, those entries are deleted. (See the example for LIST \n" - "below.)\n" - " \n" - "The \002SNLINE LIST\002 command displays the SNLINE list. \n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SNLINE LIST 2-5,7-9\002\n" - " Lists SNLINE entries numbered 2 through 5 and 7 \n" - " through 9.\n" - " \n" - "\002SNLINE VIEW\002 is a more verbose version of \002SNLINE LIST\002, and \n" - "will show who added an SNLINE, the date it was added, and when \n" - "it expires, as well as the realname mask and reason.\n" - " \n" - "\002SNLINE CLEAR\002 clears all entries of the SNLINE list.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SNLINE", _("SNLINE {ADD | DEL | LIST | VIEW | CLEAR} [[+\037expiry\037] {\037mask\037 | \037entry-list\037}[:\037reason\037]]")); - } -}; - -class OSSNLine : public Module -{ - CommandOSSNLine commandossnline; - - public: - OSSNLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - if (!ircd || !ircd->snline) - throw ModuleException("Your IRCd does not support SNLine"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->SetAuthor("Anope"); - - this->AddCommand(operserv->Bot(), &commandossnline); - } -}; - -MODULE_INIT(OSSNLine) diff --git a/modules/core/os_sqline.cpp b/modules/core/os_sqline.cpp deleted file mode 100644 index 504ea202c..000000000 --- a/modules/core/os_sqline.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class SQLineDelCallback : public NumberList -{ - CommandSource &source; - unsigned Deleted; - public: - SQLineDelCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), source(_source), Deleted(0) - { - } - - ~SQLineDelCallback() - { - if (!Deleted) - source.Reply(_("No matching entries on the SQLINE list.")); - else if (Deleted == 1) - source.Reply(_("Deleted 1 entry from the SQLINE list.")); - else - source.Reply(_("Deleted %d entries from the SQLINE list."), Deleted); - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SQLine->GetEntry(Number - 1); - - if (!x) - return; - - ++Deleted; - DoDel(source, x); - } - - static void DoDel(CommandSource &source, XLine *x) - { - SQLine->DelXLine(x); - } -}; - -class SQLineListCallback : public NumberList -{ - protected: - CommandSource &source; - bool SentHeader; - public: - SQLineListCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), source(_source), SentHeader(false) - { - } - - ~SQLineListCallback() - { - if (!SentHeader) - source.Reply(_("No matching entries on the SQLINE list.")); - } - - virtual void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SQLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SQLINE list:\n Num Mask Reason")); - } - - DoList(source, x, Number - 1); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - source.Reply(_(OPER_LIST_FORMAT), Number + 1, x->Mask.c_str(), x->Reason.c_str()); - } -}; - -class SQLineViewCallback : public SQLineListCallback -{ - public: - SQLineViewCallback(CommandSource &_source, const Anope::string &numlist) : SQLineListCallback(_source, numlist) - { - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SQLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SQLINE list:")); - } - - DoList(source, x, Number); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - Anope::string expirebuf = expire_left(source.u->Account(), x->Expires); - source.Reply(_(OPER_VIEW_FORMAT), Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expirebuf.c_str(), x->Reason.c_str()); - } -}; - -class CommandOSSQLine : public Command -{ - private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - unsigned last_param = 2; - Anope::string expiry, mask; - time_t expires; - - mask = params.size() > 1 ? params[1] : ""; - if (!mask.empty() && mask[0] == '+') - { - expiry = mask; - mask = params.size() > 2 ? params[2] : ""; - last_param = 3; - } - - expires = !expiry.empty() ? dotime(expiry) : Config->SQLineExpiry; - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (params.size() <= last_param) - { - this->OnSyntaxError(source, "ADD"); - return MOD_CONT; - } - - Anope::string reason = params[last_param]; - if (last_param == 2 && params.size() > 3) - reason += " " + params[3]; - if (!mask.empty() && !reason.empty()) - { - std::pair<int, XLine *> canAdd = SQLine->CanAdd(mask, expires); - if (mask.find_first_not_of("*") == Anope::string::npos) - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - else if (canAdd.first == 1) - source.Reply(_("\002%s\002 already exists on the SQLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - else - { - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (Anope::Match(it->second->nick, mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } - XLine *x = SQLine->Add(mask, u->nick, expires, reason); - - if (!x) - return MOD_CONT; - - source.Reply(_("\002%s\002 added to the SQLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - } - - } - else - this->OnSyntaxError(source, "ADD"); - - return MOD_CONT; - } - - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (SQLine->GetList().empty()) - { - source.Reply(_("SQLINE list is empty.")); - return MOD_CONT; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return MOD_CONT; - } - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SQLineDelCallback list(source, mask); - list.Process(); - } - else - { - XLine *x = SQLine->HasEntry(mask); - - if (!x) - { - source.Reply(_("\002%s\002 not found on the SQLINE list."), mask.c_str()); - return MOD_CONT; - } - - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, x, X_SQLINE)); - - SQLineDelCallback::DoDel(source, x); - source.Reply(_("\002%s\002 deleted from the SQLINE list."), mask.c_str()); - } - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - - return MOD_CONT; - } - - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SQLine->GetList().empty()) - { - source.Reply(_("SQLINE list is empty.")); - return MOD_CONT; - } - - Anope::string mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SQLineListCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) - { - XLine *x = SQLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SQLINE list:\n Num Mask Reason")); - } - - SQLineListCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SQLINE list.")); - else - source.Reply(_(END_OF_ANY_LIST), "SQLine"); - } - - return MOD_CONT; - } - - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SQLine->GetList().empty()) - { - source.Reply(_("SQLINE list is empty.")); - return MOD_CONT; - } - - Anope::string mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SQLineViewCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) - { - XLine *x = SQLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SQLINE list:")); - } - - SQLineViewCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SQLINE list.")); - } - - return MOD_CONT; - } - - CommandReturn DoClear(CommandSource &source) - { - User *u = source.u; - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, NULL, X_SQLINE)); - SQLine->Clear(); - source.Reply(_("The SQLINE list has been cleared.")); - - return MOD_CONT; - } - public: - CommandOSSQLine() : Command("SQLINE", 1, 4, "operserv/sqline") - { - this->SetDesc(_("Manipulate the SQLINE list")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &cmd = params[0]; - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->DoView(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source); - else - this->OnSyntaxError(source, ""); - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002SQLINE ADD [+\037expiry\037] \037mask\037 \037reason\037\002\n" - " \002SQLINE DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002SQLINE LIST [\037mask\037 | \037list\037]\002\n" - " \002SQLINE VIEW [\037mask\037 | \037list\037]\002\n" - " \002SQLINE CLEAR\002\n" - " \n" - "Allows Services operators to manipulate the SQLINE list. If\n" - "a user with a nick matching an SQLINE mask attempts to \n" - "connect, Services will not allow it to pursue his IRC\n" - "session.\n" - "If the first character of the mask is #, services will \n" - "prevent the use of matching channels (on IRCds that \n" - "support it).\n" - " \n" - "\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n" - "list for the given reason (which \002must\002 be given).\n" - "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" - "\0371h30m\037) are not permitted. If a unit specifier is not \n" - "included, the default is days (so \037+30\037 by itself means 30 \n" - "days). To add an SQLINE which does not expire, use \037+0\037. \n" - "If the mask to be added starts with a \037+\037, an expiry time \n" - "must be given, even if it is the same as the default. The\n" - "current SQLINE default expiry time can be found with the\n" - "\002STATS AKILL\002 command.\n" - " \n" - "The \002SQLINE DEL\002 command removes the given mask from the\n" - "SQLINE list if it is present. If a list of entry numbers is \n" - "given, those entries are deleted. (See the example for LIST \n" - "below.)\n" - " \n" - "The \002SQLINE LIST\002 command displays the SQLINE list. \n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SQLINE LIST 2-5,7-9\002\n" - " Lists SQLINE entries numbered 2 through 5 and 7 \n" - " through 9.\n" - " \n" - "\002SQLINE VIEW\002 is a more verbose version of \002SQLINE LIST\002, and \n" - "will show who added an SQLINE, the date it was added, and when \n" - "it expires, as well as the mask and reason.\n" - " \n" - "\002SQLINE CLEAR\002 clears all entries of the SQLINE list.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SQLINE", _("SQLINE {ADD | DEL | LIST | VIEW | CLEAR} [[+\037expiry\037] {\037nick\037 | \037mask\037 | \037entry-list\037} [\037reason\037]]")); - } -}; - -class OSSQLine : public Module -{ - CommandOSSQLine commandossqline; - - public: - OSSQLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - if (!ircd || !ircd->sqline) - throw ModuleException("Your IRCd does not support QLines."); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->SetAuthor("Anope"); - - this->AddCommand(operserv->Bot(), &commandossqline); - } -}; - -MODULE_INIT(OSSQLine) diff --git a/modules/core/os_stats.cpp b/modules/core/os_stats.cpp index 80b0799dd..f8e57bee6 100644 --- a/modules/core/os_stats.cpp +++ b/modules/core/os_stats.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" /** * Count servers connected to server s @@ -35,31 +34,35 @@ static int stats_count_servers(Server *s) class CommandOSStats : public Command { + service_reference<XLineManager> akills, snlines, sqlines, szlines; private: - CommandReturn DoStatsAkill(CommandSource &source) + void DoStatsAkill(CommandSource &source) { int timeout; - /* AKILLs */ - source.Reply(_("Current number of AKILLs: \002%d\002"), SGLine->GetCount()); - timeout = Config->AutokillExpiry + 59; - if (timeout >= 172800) - source.Reply(_("Default AKILL expiry time: \002%d days\002"), timeout / 86400); - else if (timeout >= 86400) - source.Reply(_("Default AKILL expiry time: \0021 day\002")); - else if (timeout >= 7200) - source.Reply(_("Default AKILL expiry time: \002%d hours\002"), timeout / 3600); - else if (timeout >= 3600) - source.Reply(_("Default AKILL expiry time: \0021 hour\002")); - else if (timeout >= 120) - source.Reply(_("Default AKILL expiry time: \002%d minutes\002"), timeout / 60); - else if (timeout >= 60) - source.Reply(_("Default AKILL expiry time: \0021 minute\002")); - else - source.Reply(_("Default AKILL expiry time: \002No expiration\002")); - if (ircd->snline) + if (akills) + { + /* AKILLs */ + source.Reply(_("Current number of AKILLs: \002%d\002"), akills->GetCount()); + timeout = Config->AutokillExpiry + 59; + if (timeout >= 172800) + source.Reply(_("Default AKILL expiry time: \002%d days\002"), timeout / 86400); + else if (timeout >= 86400) + source.Reply(_("Default AKILL expiry time: \0021 day\002")); + else if (timeout >= 7200) + source.Reply(_("Default AKILL expiry time: \002%d hours\002"), timeout / 3600); + else if (timeout >= 3600) + source.Reply(_("Default AKILL expiry time: \0021 hour\002")); + else if (timeout >= 120) + source.Reply(_("Default AKILL expiry time: \002%d minutes\002"), timeout / 60); + else if (timeout >= 60) + source.Reply(_("Default AKILL expiry time: \0021 minute\002")); + else + source.Reply(_("Default AKILL expiry time: \002No expiration\002")); + } + if (ircd->snline && snlines) { /* SNLINEs */ - source.Reply(_("Current number of SNLINEs: \002%d\002"), SNLine->GetCount()); + source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount()); timeout = Config->SNLineExpiry + 59; if (timeout >= 172800) source.Reply(_("Default SNLINE expiry time: \002%d days\002"), timeout / 86400); @@ -76,10 +79,10 @@ class CommandOSStats : public Command else source.Reply(_("Default SNLINE expiry time: \002No expiration\002")); } - if (ircd->sqline) + if (ircd->sqline && sqlines) { /* SQLINEs */ - source.Reply(_("Current number of SQLINEs: \002%d\002"), SQLine->GetCount()); + source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount()); timeout = Config->SQLineExpiry + 59; if (timeout >= 172800) source.Reply(_("Default SQLINE expiry time: \002%d days\002"), timeout / 86400); @@ -96,10 +99,10 @@ class CommandOSStats : public Command else source.Reply(_("Default SQLINE expiry time: \002No expiration\002")); } - if (ircd->szline) + if (ircd->szline && szlines) { /* SZLINEs */ - source.Reply(_("Current number of SZLINEs: \002%d\002"), SZLine->GetCount()); + source.Reply(_("Current number of SZLINEs: \002%d\002"), szlines->GetCount()); timeout = Config->SZLineExpiry + 59; if (timeout >= 172800) source.Reply(_("Default SZLINE expiry time: \002%d days\002"), timeout / 86400); @@ -116,27 +119,27 @@ class CommandOSStats : public Command else source.Reply(_("Default SZLINE expiry time: \002No expiration\002")); } - return MOD_CONT; + return; } - CommandReturn DoStatsReset(CommandSource &source) + void DoStatsReset(CommandSource &source) { maxusercnt = usercnt; source.Reply(_("Statistics reset.")); - return MOD_CONT; + return; } - CommandReturn DoStatsUptime(CommandSource &source) + void DoStatsUptime(CommandSource &source) { time_t uptime = Anope::CurTime - start_time; source.Reply(_("Current users: \002%d\002 (\002%d\002 ops)"), usercnt, opcnt); source.Reply(_("Maximum users: \002%d\002 (%s)"), maxusercnt, do_strftime(maxusertime).c_str()); source.Reply(_("Services up %s"), duration(uptime).c_str()); - return MOD_CONT; + return; } - CommandReturn DoStatsUplink(CommandSource &source) + void DoStatsUplink(CommandSource &source) { Anope::string buf; @@ -150,16 +153,18 @@ class CommandOSStats : public Command source.Reply(_("Uplink server: %s"), Me->GetLinks().front()->GetName().c_str()); source.Reply(_("Uplink capab: %s"), buf.c_str()); source.Reply(_("Servers found: %d"), stats_count_servers(Me->GetLinks().front())); - return MOD_CONT; + return; } public: - CommandOSStats() : Command("STATS", 0, 1, "operserv/stats") + CommandOSStats(Module *creator) : Command(creator, "operserv/stats", 0, 1, "operserv/stats"), + akills("xlinemanager/sgline"), snlines("xlinemanager/snline"), sqlines("xlinemanager/sqline"), szlines("xlinemanager/szline") { this->SetDesc(_("Show status of Services and network")); + this->SetSyntax(_("[AKILL | ALL | RESET | UPLINK]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string extra = !params.empty() ? params[0] : ""; @@ -177,14 +182,14 @@ class CommandOSStats : public Command else if (!extra.equals_ci("UPLINK")) source.Reply(_("Unknown STATS option \002%s\002."), extra.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002STATS [AKILL | ALL | RESET | UPLINK]\002\n" - " \n" - "Without any option, shows the current number of users and\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Without any option, shows the current number of users and\n" "IRCops online (excluding Services), the highest number of\n" "users online since Services was started, and the length of\n" "time Services has been running.\n" @@ -209,14 +214,12 @@ class OSStats : public Module CommandOSStats commandosstats; public: - OSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosstats(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosstats); + ModuleManager::RegisterService(&commandosstats); } }; diff --git a/modules/core/os_svsnick.cpp b/modules/core/os_svsnick.cpp index 2422e0a4c..0e2199399 100644 --- a/modules/core/os_svsnick.cpp +++ b/modules/core/os_svsnick.cpp @@ -12,17 +12,17 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSSVSNick : public Command { public: - CommandOSSVSNick() : Command("SVSNICK", 2, 2, "operserv/svsnick") + CommandOSSVSNick(Module *creator) : Command(creator, "operserv/svsnick", 2, 2, "operserv/svsnick") { this->SetDesc(_("Forcefully change a user's nickname")); + this->SetSyntax(_("\037nick\037 \037newnick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &nick = params[0]; @@ -40,41 +40,36 @@ class CommandOSSVSNick : public Command if (newnick[0] == '-' || isdigit(newnick[0])) { source.Reply(_("Nick \002%s\002 is an illegal nickname and cannot be used."), newnick.c_str()); - return MOD_CONT; + return; } for (unsigned i = 0, end = newnick.length(); i < end; ++i) if (!isvalidnick(newnick[i])) { source.Reply(_("Nick \002%s\002 is an illegal nickname and cannot be used."), newnick.c_str()); - return MOD_CONT; + return; } /* Check for a nick in use or a forbidden/suspended nick */ if (!(u2 = finduser(nick))) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (finduser(newnick)) source.Reply(_("Nick \002%s\002 is currently in use."), newnick.c_str()); else { source.Reply(_("The nick \002%s\002 is now being changed to \002%s\002."), nick.c_str(), newnick.c_str()); - ircdproto->SendGlobops(operserv->Bot(), "%s used SVSNICK to change %s to %s", u->nick.c_str(), nick.c_str(), newnick.c_str()); + ircdproto->SendGlobops(source.owner, "%s used SVSNICK to change %s to %s", u->nick.c_str(), nick.c_str(), newnick.c_str()); ircdproto->SendForceNickChange(u2, newnick, Anope::CurTime); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002SVSNICK \037nick\037 \037newnick\037\002\n" - " \n" - "Forcefully changes a user's nickname from nick to newnick.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Forcefully changes a user's nickname from nick to newnick.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SVSNICK", _("SVSNICK \037nick\037 \037newnick\037 ")); - } }; class OSSVSNick : public Module @@ -82,17 +77,15 @@ class OSSVSNick : public Module CommandOSSVSNick commandossvsnick; public: - OSSVSNick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSSVSNick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandossvsnick(this) { + this->SetAuthor("Anope"); + if (!ircd || !ircd->svsnick) throw ModuleException("Your IRCd does not support SVSNICK"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->SetAuthor("Anope"); - - this->AddCommand(operserv->Bot(), &commandossvsnick); + ModuleManager::RegisterService(&commandossvsnick); } }; diff --git a/modules/core/os_sxline.cpp b/modules/core/os_sxline.cpp new file mode 100644 index 000000000..27df5d5d1 --- /dev/null +++ b/modules/core/os_sxline.cpp @@ -0,0 +1,807 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" + +class SXLineDelCallback : public NumberList +{ + XLineManager *xlm; + Command *command; + CommandSource &source; + unsigned Deleted; + public: + SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), xlm(x), command(c), source(_source), Deleted(0) + { + } + + ~SXLineDelCallback() + { + if (!Deleted) + source.Reply(_("No matching entries on the %s list."), this->command->name.c_str()); + else if (Deleted == 1) + source.Reply(_("Deleted 1 entry from the %s list."), this->command->name.c_str()); + else + source.Reply(_("Deleted %d entries from the %s list."), Deleted, this->command->name.c_str()); + } + + void HandleNumber(unsigned Number) + { + if (!Number) + return; + + XLine *x = this->xlm->GetEntry(Number - 1); + + if (!x) + return; + + ++Deleted; + DoDel(this->xlm, source, x); + } + + static void DoDel(XLineManager *xlm, CommandSource &source, XLine *x) + { + xlm->DelXLine(x); + } +}; + +class SXLineListCallback : public NumberList +{ + protected: + XLineManager *xlm; + Command *command; + CommandSource &source; + bool SentHeader; + public: + SXLineListCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), xlm(x), command(c), source(_source), SentHeader(false) + { + } + + ~SXLineListCallback() + { + if (!SentHeader) + source.Reply(_("No matching entries on the %s list."), this->command->name.c_str()); + } + + virtual void HandleNumber(unsigned Number) + { + if (!Number) + return; + + XLine *x = this->xlm->GetEntry(Number - 1); + + if (!x) + return; + + if (!SentHeader) + { + SentHeader = true; + source.Reply(_("Current %s list:\n Num Mask Reason"), this->command->name.c_str()); + } + + DoList(source, x, Number - 1); + } + + static void DoList(CommandSource &source, XLine *x, unsigned Number) + { + source.Reply(OPER_LIST_FORMAT, Number + 1, x->Mask.c_str(), x->Reason.c_str()); + } +}; + +class SXLineViewCallback : public SXLineListCallback +{ + public: + SXLineViewCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : SXLineListCallback(x, c, _source, numlist) + { + } + + void HandleNumber(unsigned Number) + { + if (!Number) + return; + + XLine *x = this->xlm->GetEntry(Number - 1); + + if (!x) + return; + + if (!SentHeader) + { + SentHeader = true; + source.Reply(_("Current %s list:"), this->command->name.c_str()); + } + + DoList(source, x, Number - 1); + } + + static void DoList(CommandSource &source, XLine *x, unsigned Number) + { + Anope::string expirebuf = expire_left(source.u->Account(), x->Expires); + source.Reply(OPER_VIEW_FORMAT, Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expirebuf.c_str(), x->Reason.c_str()); + } +}; + +class CommandOSSXLineBase : public Command +{ + private: + virtual XLineManager* xlm() = 0; + + virtual void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; + + void OnDel(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + + if (!this->xlm() || this->xlm()->GetList().empty()) + { + source.Reply(_("%s list is empty."), this->name.c_str()); + return; + } + + const Anope::string &mask = params.size() > 1 ? params[1] : ""; + + if (mask.empty()) + { + this->OnSyntaxError(source, "DEL"); + return; + } + + if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) + { + SXLineDelCallback list(this->xlm(), this, source, mask); + list.Process(); + } + else + { + XLine *x = this->xlm()->HasEntry(mask); + + if (!x) + { + source.Reply(_("\002%s\002 not found on the %s list."), mask.c_str(), this->name.c_str()); + return; + } + + FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, x, this->xlm())); + + SXLineDelCallback::DoDel(this->xlm(), source, x); + source.Reply(_("\002%s\002 deleted from the %s list."), mask.c_str(), this->name.c_str()); + } + + if (readonly) + source.Reply(READ_ONLY_MODE); + + return; + } + + void OnList(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!this->xlm() || this->xlm()->GetList().empty()) + { + source.Reply(_("%s list is empty."), this->name.c_str()); + return; + } + + const Anope::string &mask = params.size() > 1 ? params[1] : ""; + + if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) + { + SXLineListCallback list(this->xlm(), this, source, mask); + list.Process(); + } + else + { + bool SentHeader = false; + + for (unsigned i = 0, end = this->xlm()->GetCount(); i < end; ++i) + { + XLine *x = this->xlm()->GetEntry(i); + + if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) + { + if (!SentHeader) + { + SentHeader = true; + source.Reply(_("Current %s list:\n Num Mask Reason"), this->name.c_str()); + } + + SXLineListCallback::DoList(source, x, i); + } + } + + if (!SentHeader) + source.Reply(_("No matching entries on the %s list."), this->name.c_str()); + else + source.Reply(END_OF_ANY_LIST, this->name.c_str()); + } + + return; + } + + void OnView(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!this->xlm () || this->xlm()->GetList().empty()) + { + source.Reply(_("%s list is empty."), this->name.c_str()); + return; + } + + const Anope::string &mask = params.size() > 1 ? params[1] : ""; + + if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) + { + SXLineViewCallback list(this->xlm(), this, source, mask); + list.Process(); + } + else + { + bool SentHeader = false; + + for (unsigned i = 0, end = this->xlm()->GetCount(); i < end; ++i) + { + XLine *x = this->xlm()->GetEntry(i); + + if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) + { + if (!SentHeader) + { + SentHeader = true; + source.Reply(_("Current %s list:"), this->name.c_str()); + } + + SXLineViewCallback::DoList(source, x, i); + } + } + + if (!SentHeader) + source.Reply(_("No matching entries on the %s list."), this->name.c_str()); + } + + return; + } + + void OnClear(CommandSource &source) + { + User *u = source.u; + FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, NULL, this->xlm())); + this->xlm()->Clear(); + source.Reply(_("The %s list has been cleared."), this->name.c_str()); + + return; + } + public: + CommandOSSXLineBase(Module *creator, const Anope::string &cmd, const Anope::string &perm) : Command(creator, cmd, 1, 3, perm) + { + this->SetDesc(Anope::printf(_("Manipulate the %s list"), cmd.c_str())); + this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037:\037reason\037")); + this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); + this->SetSyntax(_("LIST [\037mask\037 | \037list\037]")); + this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]")); + this->SetSyntax(_("CLEAR")); + } + + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + const Anope::string &cmd = params[0]; + + if (cmd.equals_ci("ADD")) + return this->OnAdd(source, params); + else if (cmd.equals_ci("DEL")) + return this->OnDel(source, params); + else if (cmd.equals_ci("LIST")) + return this->OnList(source, params); + else if (cmd.equals_ci("VIEW")) + return this->OnView(source, params); + else if (cmd.equals_ci("CLEAR")) + return this->OnClear(source); + else + this->OnSyntaxError(source, ""); + + return; + } + + virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; +}; + +class CommandOSSNLine : public CommandOSSXLineBase +{ + XLineManager *xlm() + { + return this->snlines; + } + + void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!this->xlm()) + return; + + User *u = source.u; + unsigned last_param = 2; + Anope::string param, expiry; + time_t expires; + + param = params.size() > 1 ? params[1] : ""; + if (!param.empty() && param[0] == '+') + { + expiry = param; + param = params.size() > 2 ? params[2] : ""; + last_param = 3; + } + + expires = !expiry.empty() ? dotime(expiry) : Config->SNLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires && expires < 60) + { + source.Reply(BAD_EXPIRY_TIME); + return; + } + else if (expires > 0) + expires += Anope::CurTime; + + if (param.empty()) + { + this->OnSyntaxError(source, "ADD"); + return; + } + + Anope::string rest = param; + if (params.size() > last_param) + rest += " " + params[last_param]; + + if (rest.find(':') == Anope::string::npos) + { + this->OnSyntaxError(source, "ADD"); + return; + } + + sepstream sep(rest, ':'); + Anope::string mask; + sep.GetToken(mask); + Anope::string reason = sep.GetRemaining(); + + if (!mask.empty() && !reason.empty()) + { + std::pair<int, XLine *> canAdd = this->xlm()->CanAdd(mask, expires); + if (mask.find_first_not_of("*?") == Anope::string::npos) + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the %s list."), canAdd.second->Mask.c_str(), this->name.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + /* Clean up the last character of the mask if it is a space + * See bug #761 + */ + unsigned masklen = mask.length(); + if (mask[masklen - 1] == ' ') + mask.erase(masklen - 1); + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (Anope::Match(it->second->realname, mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to " << this->name << " " << percent << "% of the network (" << affected << " users)"; + return; + } + + XLine *x = this->xlm()->Add(mask, u->nick, expires, reason); + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, this->xlm())); + if (MOD_RESULT == EVENT_STOP) + { + delete x; + return; + } + + source.Reply(_("\002%s\002 added to the %s list."), mask.c_str(), this->name.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + + if (readonly) + source.Reply(READ_ONLY_MODE); + } + + } + else + this->OnSyntaxError(source, "ADD"); + + return; + } + + service_reference<XLineManager> snlines; + public: + CommandOSSNLine(Module *creator) : CommandOSSXLineBase(creator, "SNLINE", "operserv/snline"), snlines("xlinemanager/snline") + { + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services operators to manipulate the SNLINE list. If\n" + "a user with a realname matching an SNLINE mask attempts to \n" + "connect, Services will not allow it to pursue his IRC\n" + "session.\n")); + source.Reply(_(" \n" + "\002SNLINE ADD\002 adds the given realname mask to the SNLINE\n" + "list for the given reason (which \002must\002 be given).\n" + "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" + "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" + "\0371h30m\037) are not permitted. If a unit specifier is not \n" + "included, the default is days (so \037+30\037 by itself means 30 \n" + "days). To add an SNLINE which does not expire, use \037+0\037. If the\n" + "realname mask to be added starts with a \037+\037, an expiry time must\n" + "be given, even if it is the same as the default. The\n" + "current SNLINE default expiry time can be found with the\n" + "\002STATS AKILL\002 command.\n" + "Note: because the realname mask may contain spaces, the\n" + "separator between it and the reason is a colon.\n")); + source.Reply(_(" \n" + "The \002SNLINE DEL\002 command removes the given mask from the\n" + "SNLINE list if it is present. If a list of entry numbers is \n" + "given, those entries are deleted. (See the example for LIST \n" + "below.)\n" + " \n" + "The \002SNLINE LIST\002 command displays the SNLINE list. \n" + "If a wildcard mask is given, only those entries matching the\n" + "mask are displayed. If a list of entry numbers is given,\n" + "only those entries are shown; for example:\n" + " \002SNLINE LIST 2-5,7-9\002\n" + " Lists SNLINE entries numbered 2 through 5 and 7 \n" + " through 9.\n" + " \n" + "\002SNLINE VIEW\002 is a more verbose version of \002SNLINE LIST\002, and \n" + "will show who added an SNLINE, the date it was added, and when \n" + "it expires, as well as the realname mask and reason.\n" + " \n" + "\002SNLINE CLEAR\002 clears all entries of the SNLINE list.")); + return true; + } +}; + +class CommandOSSQLine : public CommandOSSXLineBase +{ + XLineManager *xlm() + { + return this->sqlines; + } + + void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!this->xlm()) + return; + + User *u = source.u; + unsigned last_param = 2; + Anope::string expiry, mask; + time_t expires; + + mask = params.size() > 1 ? params[1] : ""; + if (!mask.empty() && mask[0] == '+') + { + expiry = mask; + mask = params.size() > 2 ? params[2] : ""; + last_param = 3; + } + + expires = !expiry.empty() ? dotime(expiry) : Config->SQLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires && expires < 60) + { + source.Reply(BAD_EXPIRY_TIME); + return; + } + else if (expires > 0) + expires += Anope::CurTime; + + if (params.size() <= last_param) + { + this->OnSyntaxError(source, "ADD"); + return; + } + + Anope::string reason = params[last_param]; + if (last_param == 2 && params.size() > 3) + reason += " " + params[3]; + if (!mask.empty() && !reason.empty()) + { + std::pair<int, XLine *> canAdd = this->sqlines->CanAdd(mask, expires); + if (mask.find_first_not_of("*") == Anope::string::npos) + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the SQLINE list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (Anope::Match(it->second->nick, mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)"; + return; + } + + XLine *x = this->sqlines->Add(mask, u->nick, expires, reason); + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, this->xlm())); + if (MOD_RESULT == EVENT_STOP) + { + delete x; + return; + } + + source.Reply(_("\002%s\002 added to the SQLINE list."), mask.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + + if (readonly) + source.Reply(READ_ONLY_MODE); + } + + } + else + this->OnSyntaxError(source, "ADD"); + + return; + } + + service_reference<XLineManager> sqlines; + public: + CommandOSSQLine(Module *creator) : CommandOSSXLineBase(creator, "SQLINE", "operserv/sqline"), sqlines("xlinemanager/sqline") + { + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services operators to manipulate the SQLINE list. If\n" + "a user with a nick matching an SQLINE mask attempts to \n" + "connect, Services will not allow it to pursue his IRC\n" + "session.\n" + "If the first character of the mask is #, services will \n" + "prevent the use of matching channels (on IRCds that \n" + "support it).\n")); + source.Reply(_(" \n" + "\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n" + "list for the given reason (which \002must\002 be given).\n" + "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" + "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" + "\0371h30m\037) are not permitted. If a unit specifier is not \n" + "included, the default is days (so \037+30\037 by itself means 30 \n" + "days). To add an SQLINE which does not expire, use \037+0\037. \n" + "If the mask to be added starts with a \037+\037, an expiry time \n" + "must be given, even if it is the same as the default. The\n" + "current SQLINE default expiry time can be found with the\n" + "\002STATS AKILL\002 command.\n")); + source.Reply(_(" \n" + "The \002SQLINE DEL\002 command removes the given mask from the\n" + "SQLINE list if it is present. If a list of entry numbers is \n" + "given, those entries are deleted. (See the example for LIST \n" + "below.)\n" + " \n" + "The \002SQLINE LIST\002 command displays the SQLINE list. \n" + "If a wildcard mask is given, only those entries matching the\n" + "mask are displayed. If a list of entry numbers is given,\n" + "only those entries are shown; for example:\n" + " \002SQLINE LIST 2-5,7-9\002\n" + " Lists SQLINE entries numbered 2 through 5 and 7 \n" + " through 9.\n" + " \n" + "\002SQLINE VIEW\002 is a more verbose version of \002SQLINE LIST\002, and \n" + "will show who added an SQLINE, the date it was added, and when \n" + "it expires, as well as the mask and reason.\n" + " \n" + "\002SQLINE CLEAR\002 clears all entries of the SQLINE list.")); + return true; + } +}; + +class CommandOSSZLine : public CommandOSSXLineBase +{ + XLineManager *xlm() + { + return this->szlines; + } + + void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + if (!this->xlm()) + return; + + User *u = source.u; + unsigned last_param = 2; + Anope::string expiry, mask; + time_t expires; + + mask = params.size() > 1 ? params[1] : ""; + if (!mask.empty() && mask[0] == '+') + { + expiry = mask; + mask = params.size() > 2 ? params[2] : ""; + last_param = 3; + } + + expires = !expiry.empty() ? dotime(expiry) : Config->SZLineExpiry; + /* If the expiry given does not contain a final letter, it's in days, + * said the doc. Ah well. + */ + if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) + expires *= 86400; + /* Do not allow less than a minute expiry time */ + if (expires && expires < 60) + { + source.Reply(BAD_EXPIRY_TIME); + return; + } + else if (expires > 0) + expires += Anope::CurTime; + + if (params.size() <= last_param) + { + this->OnSyntaxError(source, "ADD"); + return; + } + + Anope::string reason = params[last_param]; + if (last_param == 2 && params.size() > 3) + reason += " " + params[3]; + if (!mask.empty() && !reason.empty()) + { + std::pair<int, XLine *> canAdd = this->szlines->CanAdd(mask, expires); + if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) + source.Reply(_("You can only add IP masks to the SZLINE list.")); + else if (mask.find_first_not_of("*?") == Anope::string::npos) + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the SZLINE list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + User *user = finduser(mask); + if (user && user->ip()) + mask = user->ip.addr(); + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (it->second->ip() && Anope::Match(it->second->ip.addr(), mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to SZLine " << percent << "% of the network (" << affected << " users)"; + return; + } + + XLine *x = this->szlines->Add(mask, u->nick, expires, reason); + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, this->xlm())); + if (MOD_RESULT == EVENT_STOP) + { + delete x; + return; + } + + source.Reply(_("\002%s\002 added to the SZLINE list."), mask.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + + if (readonly) + source.Reply(READ_ONLY_MODE); + } + + } + else + this->OnSyntaxError(source, "ADD"); + + return; + } + + service_reference<XLineManager> szlines; + public: + CommandOSSZLine(Module *creator) : CommandOSSXLineBase(creator, "SZLINE", "operserv/szline"), szlines("xlinemanager/szline") + { + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Allows Services operators to manipulate the SZLINE list. If\n" + "a user with an IP matching an SZLINE mask attempts to \n" + "connect, Services will not allow it to pursue his IRC\n" + "session (and this, whether the IP has a PTR RR or not).\n" + " \n")); + source.Reply(_("\002SZLINE ADD\002 adds the given (nick's) IP mask to the SZLINE\n" + "list for the given reason (which \002must\002 be given).\n" + "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" + "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" + "\0371h30m\037) are not permitted. If a unit specifier is not \n" + "included, the default is days (so \037+30\037 by itself means 30 \n" + "days). To add an SZLINE which does not expire, use \037+0\037. If the\n" + "realname mask to be added starts with a \037+\037, an expiry time must\n" + "be given, even if it is the same as the default. The\n" + "current SZLINE default expiry time can be found with the\n" + "\002STATS AKILL\002 command.\n")); + source.Reply(_(" \n" + "The \002SZLINE DEL\002 command removes the given mask from the\n" + "SZLINE list if it is present. If a list of entry numbers is \n" + "given, those entries are deleted. (See the example for LIST \n" + "below.)\n" + " \n" + "The \002SZLINE LIST\002 command displays the SZLINE list.\n" + "If a wildcard mask is given, only those entries matching the\n" + "mask are displayed. If a list of entry numbers is given,\n" + "only those entries are shown; for example:\n" + " \002SZLINE LIST 2-5,7-9\002\n" + " Lists SZLINE entries numbered 2 through 5 and 7 \n" + " through 9.\n" + " \n" + "\002SZLINE VIEW\002 is a more verbose version of \002SZLINE LIST\002, and \n" + "will show who added an SZLINE, the date it was added, and when\n" + "it expires, as well as the IP mask and reason.\n" + " \n" + "\002SZLINE CLEAR\002 clears all entries of the SZLINE list.")); + return true; + } +}; + +class OSSXLine : public Module +{ + CommandOSSNLine commandossnline; + CommandOSSQLine commandossqline; + CommandOSSZLine commandosszline; + + public: + OSSXLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandossnline(this), commandossqline(this), commandosszline(this) + { + this->SetAuthor("Anope"); + + if (ircd && ircd->snline) + ModuleManager::RegisterService(&commandossnline); + if (ircd && ircd->sqline) + ModuleManager::RegisterService(&commandossqline); + if (ircd && ircd->szline) + ModuleManager::RegisterService(&commandosszline); + } +}; + +MODULE_INIT(OSSXLine) diff --git a/modules/core/os_szline.cpp b/modules/core/os_szline.cpp deleted file mode 100644 index ac3ce61f6..000000000 --- a/modules/core/os_szline.cpp +++ /dev/null @@ -1,457 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class SZLineDelCallback : public NumberList -{ - CommandSource &source; - unsigned Deleted; - public: - SZLineDelCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), source(_source), Deleted(0) - { - } - - ~SZLineDelCallback() - { - if (!Deleted) - source.Reply(_("No matching entries on the SZLINE list.")); - else if (Deleted == 1) - source.Reply(_("Deleted 1 entry from the SZLINE list.")); - else - source.Reply(_("Deleted %d entries from the SZLINE list."), Deleted); - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SZLine->GetEntry(Number - 1); - - if (!x) - return; - - ++Deleted; - DoDel(source, x); - } - - static void DoDel(CommandSource &source, XLine *x) - { - SZLine->DelXLine(x); - } -}; - -class SZLineListCallback : public NumberList -{ - protected: - CommandSource &source; - bool SentHeader; - public: - SZLineListCallback(CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, false), source(_source), SentHeader(false) - { - } - - ~SZLineListCallback() - { - if (!SentHeader) - source.Reply(_("No matching entries on the SZLINE list.")); - } - - virtual void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SZLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SZLINE list:\n Num Mask Reason")); - } - - DoList(source, x, Number - 1); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - source.Reply(_(OPER_LIST_FORMAT), Number + 1, x->Mask.c_str(), x->Reason.c_str()); - } -}; - -class SZLineViewCallback : public SZLineListCallback -{ - public: - SZLineViewCallback(CommandSource &_source, const Anope::string &numlist) : SZLineListCallback(_source, numlist) - { - } - - void HandleNumber(unsigned Number) - { - if (!Number) - return; - - XLine *x = SZLine->GetEntry(Number - 1); - - if (!x) - return; - - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SZLINE list:")); - } - - DoList(source, x, Number - 1); - } - - static void DoList(CommandSource &source, XLine *x, unsigned Number) - { - Anope::string expirebuf = expire_left(source.u->Account(), x->Expires); - source.Reply(_(OPER_VIEW_FORMAT), Number + 1, x->Mask.c_str(), x->By.c_str(), do_strftime(x->Created).c_str(), expirebuf.c_str(), x->Reason.c_str()); - } -}; - -class CommandOSSZLine : public Command -{ - private: - CommandReturn DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - unsigned last_param = 2; - Anope::string expiry, mask; - time_t expires; - - mask = params.size() > 1 ? params[1] : ""; - if (!mask.empty() && mask[0] == '+') - { - expiry = mask; - mask = params.size() > 2 ? params[2] : ""; - last_param = 3; - } - - expires = !expiry.empty() ? dotime(expiry) : Config->SZLineExpiry; - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(_(BAD_EXPIRY_TIME)); - return MOD_CONT; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (params.size() <= last_param) - { - this->OnSyntaxError(source, "ADD"); - return MOD_CONT; - } - - Anope::string reason = params[last_param]; - if (last_param == 2 && params.size() > 3) - reason += " " + params[3]; - if (!mask.empty() && !reason.empty()) - { - std::pair<int, XLine *> canAdd = SZLine->CanAdd(mask, expires); - if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) - source.Reply(_("You can only add IP masks to the SZLINE list.")); - else if (mask.find_first_not_of("*?") == Anope::string::npos) - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - else if (canAdd.first == 1) - source.Reply(_("\002%s\002 already exists on the SZLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - else - { - User *user = finduser(mask); - if (user && user->ip()) - mask = user->ip.addr(); - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (it->second->ip() && Anope::Match(it->second->ip.addr(), mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SZLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } - - XLine *x = SZLine->Add(mask, u->nick, expires, reason); - - if (!x) - return MOD_CONT; - - source.Reply(_("\002%s\002 added to the SZLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - } - - } - else - this->OnSyntaxError(source, "ADD"); - - return MOD_CONT; - } - - CommandReturn DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - - if (SZLine->GetList().empty()) - { - source.Reply(_("SZLINE list is empty.")); - return MOD_CONT; - } - - Anope::string mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return MOD_CONT; - } - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SZLineDelCallback list(source, mask); - list.Process(); - } - else - { - XLine *x = SZLine->HasEntry(mask); - - if (!x) - { - source.Reply(_("\002%s\002 not found on the SZLINE list."), mask.c_str()); - return MOD_CONT; - } - - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, x, X_SZLINE)); - - SZLineDelCallback::DoDel(source, x); - source.Reply(_("\002%s\002 deleted from the SZLINE list."), mask.c_str()); - } - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); - - return MOD_CONT; - } - - CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SZLine->GetList().empty()) - { - source.Reply(_("SZLINE list is empty.")); - return MOD_CONT; - } - - Anope::string mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SZLineListCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) - { - XLine *x = SZLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SZLINE list:\n Num Mask Reason")); - } - - SZLineListCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SZLINE list.")); - } - - return MOD_CONT; - } - - CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (SZLine->GetList().empty()) - { - source.Reply(_("SZLINE list is empty.")); - return MOD_CONT; - } - - Anope::string mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SZLineViewCallback list(source, mask); - list.Process(); - } - else - { - bool SentHeader = false; - - for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) - { - XLine *x = SZLine->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->Mask) || Anope::Match(x->Mask, mask)) - { - if (!SentHeader) - { - SentHeader = true; - source.Reply(_("Current SZLINE list:")); - } - - SZLineViewCallback::DoList(source, x, i); - } - } - - if (!SentHeader) - source.Reply(_("No matching entries on the SZLINE list.")); - } - - return MOD_CONT; - } - - CommandReturn DoClear(CommandSource &source) - { - User *u = source.u; - FOREACH_MOD(I_OnDelXLine, OnDelXLine(u, NULL, X_SZLINE)); - SZLine->Clear(); - source.Reply(_("The SZLINE list has been cleared.")); - - return MOD_CONT; - } - public: - CommandOSSZLine() : Command("SZLINE", 1, 4, "operserv/szline") - { - this->SetDesc(_("Manipulate the SZLINE list")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &cmd = params[0]; - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->DoView(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source); - else - this->OnSyntaxError(source, ""); - - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002SZLINE ADD [+\037expiry\037] \037mask\037 \037reason\037\002\n" - " \002SZLINE DEL {\037mask\037 | \037entry-num\037 | \037list\037}\002\n" - " \002SZLINE LIST [\037mask\037 | \037list\037]\002\n" - " \002SZLINE VIEW [\037mask\037 | \037list\037]\002\n" - " \002SZLINE CLEAR\002\n" - " \n" - "Allows Services operators to manipulate the SZLINE list. If\n" - "a user with an IP matching an SZLINE mask attempts to \n" - "connect, Services will not allow it to pursue his IRC\n" - "session (and this, whether the IP has a PTR RR or not).\n" - " \n" - "\002SZLINE ADD\002 adds the given (nick's) IP mask to the SZLINE\n" - "list for the given reason (which \002must\002 be given).\n" - "\037expiry\037 is specified as an integer followed by one of \037d\037 \n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as \n" - "\0371h30m\037) are not permitted. If a unit specifier is not \n" - "included, the default is days (so \037+30\037 by itself means 30 \n" - "days). To add an SZLINE which does not expire, use \037+0\037. If the\n" - "realname mask to be added starts with a \037+\037, an expiry time must\n" - "be given, even if it is the same as the default. The\n" - "current SZLINE default expiry time can be found with the\n" - "\002STATS AKILL\002 command.\n" - " \n" - "The \002SZLINE DEL\002 command removes the given mask from the\n" - "SZLINE list if it is present. If a list of entry numbers is \n" - "given, those entries are deleted. (See the example for LIST \n" - "below.)\n" - " \n" - "The \002SZLINE LIST\002 command displays the SZLINE list.\n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SZLINE LIST 2-5,7-9\002\n" - " Lists SZLINE entries numbered 2 through 5 and 7 \n" - " through 9.\n" - " \n" - "\002SZLINE VIEW\002 is a more verbose version of \002SZLINE LIST\002, and \n" - "will show who added an SZLINE, the date it was added, and when\n" - "it expires, as well as the IP mask and reason.\n" - " \n" - "\002SZLINE CLEAR\002 clears all entries of the SZLINE list.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "SZLINE", _("SZLINE {ADD | DEL | LIST | VIEW | CLEAR} [[+\037expiry\037] {\037nick\037 | \037mask\037 | \037entry-list\037} [\037reason\037]]")); - } -}; - -class OSSZLine : public Module -{ - CommandOSSZLine commandosszline; - - public: - OSSZLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - if (!ircd || !ircd->szline) - throw ModuleException("Your IRCd does not support ZLINEs"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->SetAuthor("Anope"); - - this->AddCommand(operserv->Bot(), &commandosszline); - } -}; - -MODULE_INIT(OSSZLine) diff --git a/modules/core/os_update.cpp b/modules/core/os_update.cpp index d4793c124..a128f711f 100644 --- a/modules/core/os_update.cpp +++ b/modules/core/os_update.cpp @@ -12,28 +12,28 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" class CommandOSUpdate : public Command { public: - CommandOSUpdate() : Command("UPDATE", 0, 0, "operserv/update") + CommandOSUpdate(Module *creator) : Command(creator, "operserv/update", 0, 0, "operserv/update") { this->SetDesc(_("Force the Services databases to be updated immediately")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { source.Reply(_("Updating databases.")); save_databases(); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002UPDATE\002\n" - " \n" - "Causes Services to update all database files as soon as you\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Causes Services to update all database files as soon as you\n" "send the command.")); return true; } @@ -44,14 +44,12 @@ class OSUpdate : public Module CommandOSUpdate commandosupdate; public: - OSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) + OSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE), + commandosupdate(this) { this->SetAuthor("Anope"); - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosupdate); + ModuleManager::RegisterService(&commandosupdate); } }; diff --git a/modules/core/os_userlist.cpp b/modules/core/os_userlist.cpp deleted file mode 100644 index 9986630f1..000000000 --- a/modules/core/os_userlist.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" -#include "operserv.h" - -class CommandOSUserList : public Command -{ - public: - CommandOSUserList() : Command("USERLIST", 0, 2) - { - this->SetDesc(_("Lists all user records")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &pattern = !params.empty() ? params[0] : ""; - const Anope::string &opt = params.size() > 1 ? params[1] : ""; - Channel *c; - std::list<UserModeName> Modes; - - if (!opt.empty() && opt.equals_ci("INVISIBLE")) - Modes.push_back(UMODE_INVIS); - - if (!pattern.empty() && (c = findchan(pattern))) - { - source.Reply(_("\002%s\002 users list:\n" - "Nick Mask"), pattern.c_str()); - - for (CUserList::iterator cuit = c->users.begin(), cuit_end = c->users.end(); cuit != cuit_end; ++cuit) - { - UserContainer *uc = *cuit; - - if (!Modes.empty()) - for (std::list<UserModeName>::iterator it = Modes.begin(), it_end = Modes.end(); it != it_end; ++it) - if (!uc->user->HasMode(*it)) - continue; - - source.Reply(_("%-20s %s@%s"), uc->user->nick.c_str(), uc->user->GetIdent().c_str(), uc->user->GetDisplayedHost().c_str()); - } - } - else - { - source.Reply(_("Users list:\n" - "Nick Mask")); - - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u2 = it->second; - - if (!pattern.empty()) - { - Anope::string mask = u2->nick + "!" + u2->GetIdent() + "@" + u2->GetDisplayedHost(); - if (!Anope::Match(mask, pattern)) - continue; - if (!Modes.empty()) - for (std::list<UserModeName>::iterator mit = Modes.begin(), mit_end = Modes.end(); mit != mit_end; ++mit) - if (!u2->HasMode(*mit)) - continue; - } - source.Reply(_("%-20s %s@%s"), u2->nick.c_str(), u2->GetIdent().c_str(), u2->GetDisplayedHost().c_str()); - } - } - - source.Reply(_("End of users list.")); - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002USERLIST [{\037pattern | channel\037} [\037INVISIBLE\037]]\002\n" - " \n" - "Lists all users currently online on the IRC network, whether their\n" - "nick is registered or not.\n" - " \n" - "If \002pattern\002 is given, lists only users that match it (it must be in\n" - "the format nick!user@host). If \002channel\002 is given, lists only users\n" - "that are on the given channel. If INVISIBLE is specified, only users\n" - "with the +i flag will be listed.")); - return true; - } -}; - -class OSUserList : public Module -{ - CommandOSUserList commandosuserlist; - - public: - OSUserList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, CORE) - { - this->SetAuthor("Anope"); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); - - this->AddCommand(operserv->Bot(), &commandosuserlist); - } -}; - -MODULE_INIT(OSUserList) diff --git a/modules/extra/cs_appendtopic.cpp b/modules/extra/cs_appendtopic.cpp index bb6702237..41a69f9fc 100644 --- a/modules/extra/cs_appendtopic.cpp +++ b/modules/extra/cs_appendtopic.cpp @@ -17,7 +17,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" /* ------------------------------------------------------------ * Name: cs_appendtopic @@ -40,49 +39,48 @@ /* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING */ /* ---------------------------------------------------------------------- */ -static Module *me; - class CommandCSAppendTopic : public Command { public: - CommandCSAppendTopic() : Command("APPENDTOPIC", 2, 2) + CommandCSAppendTopic(Module *creator) : Command(creator, "APPENDTOPIC", 2, 2) { this->SetDesc(_("Add text to a channels topic")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &newtopic = params[1]; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; + Channel *c = findchan(params[0]);; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); - else if (!check_access(u, ci, CA_TOPIC)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); + else if (!c->ci) + source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); + else if (!check_access(u, c->ci, CA_TOPIC)) + source.Reply(ACCESS_DENIED); else { Anope::string topic; - if (!ci->last_topic.empty()) + if (!c->ci->last_topic.empty()) { - topic = ci->last_topic + " " + newtopic; - ci->last_topic.clear(); + topic = c->ci->last_topic + " " + newtopic; + c->ci->last_topic.clear(); } else topic = newtopic; - bool has_topiclock = ci->HasFlag(CI_TOPICLOCK); - ci->UnsetFlag(CI_TOPICLOCK); + bool has_topiclock = c->ci->HasFlag(CI_TOPICLOCK); + c->ci->UnsetFlag(CI_TOPICLOCK); c->ChangeTopic(u->nick, topic, Anope::CurTime); if (has_topiclock) - ci->SetFlag(CI_TOPICLOCK); + c->ci->SetFlag(CI_TOPICLOCK); - bool override = !check_access(u, ci, CA_TOPIC); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "changed topic to " << topic; + bool override = !check_access(u, c->ci, CA_TOPIC); + Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, c->ci) << "changed topic to " << topic; } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -107,16 +105,12 @@ class CSAppendTopic : public Module CommandCSAppendTopic commandcsappendtopic; public: - CSAppendTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) + CSAppendTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), + commandcsappendtopic(this) { this->SetAuthor("SGR"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - me = this; - - this->AddCommand(chanserv->Bot(), &commandcsappendtopic); + ModuleManager::RegisterService(&commandcsappendtopic); } }; diff --git a/modules/extra/cs_enforce.cpp b/modules/extra/cs_enforce.cpp index c39744ca2..d258f7458 100644 --- a/modules/extra/cs_enforce.cpp +++ b/modules/extra/cs_enforce.cpp @@ -14,9 +14,6 @@ */ #include "module.h" -#include "chanserv.h" - -static Module *me; class CommandCSEnforce : public Command { @@ -122,22 +119,24 @@ class CommandCSEnforce : public Command } } public: - CommandCSEnforce() : Command("ENFORCE", 1, 2) + CommandCSEnforce(Module *creator) : Command(creator, "ENFORCE", 1, 2) { this->SetDesc(_("Enforce various channel modes and set options")); + this->SetSyntax(_("\037channel\037 [\037what\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { const Anope::string &what = params.size() > 1 ? params[1] : ""; User *u = source.u; - ChannelInfo *ci = source.ci; - Channel *c = ci->c; + Channel *c = findchan(params[0]); if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), ci->name.c_str()); - else if (!check_access(u, ci, CA_AKICK)) + source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); + else if (!c->ci) + source.Reply(CHAN_X_NOT_REGISTERED, c->name.c_str()); + else if (!check_access(u, c->ci, CA_AKICK)) source.Reply(ACCESS_DENIED); else { @@ -170,12 +169,12 @@ class CommandCSEnforce : public Command this->OnSyntaxError(source, ""); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ENFORCE \037channel\037 [\037what\037]\002")); + this->SendSyntax(source); source.Reply(" "); source.Reply(_("Enforce various channel modes and set options. The \037channel\037\n" "option indicates what channel to enforce the modes and options\n" @@ -204,11 +203,6 @@ class CommandCSEnforce : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002ENFORCE \037channel\037 [\037what\037]\002")); - } }; class CSEnforce : public Module @@ -216,16 +210,12 @@ class CSEnforce : public Module CommandCSEnforce commandcsenforce; public: - CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) + CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), + commandcsenforce(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - - me = this; - - this->AddCommand(chanserv->Bot(), &commandcsenforce); + ModuleManager::RegisterService(&commandcsenforce); } }; diff --git a/modules/extra/cs_entrymsg.cpp b/modules/extra/cs_entrymsg.cpp index dbfe35d35..28f5603f8 100644 --- a/modules/extra/cs_entrymsg.cpp +++ b/modules/extra/cs_entrymsg.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" struct EntryMsg { @@ -41,7 +40,7 @@ class CommandEntryMessage : public Command { source.Reply(_("Entry message list for \2%s\2:"), ci->name.c_str()); for (unsigned i = 0; i < messages.size(); ++i) - source.Reply(_(CHAN_LIST_ENTRY), i + 1, messages[i].message.c_str(), messages[i].creator.c_str(), do_strftime(messages[i].when).c_str()); + source.Reply(CHAN_LIST_ENTRY, i + 1, messages[i].message.c_str(), messages[i].creator.c_str(), do_strftime(messages[i].when).c_str()); source.Reply(_("End of entry message list.")); } else @@ -98,17 +97,24 @@ class CommandEntryMessage : public Command } public: - CommandEntryMessage(const Anope::string &cname) : Command(cname, 2, 3) + CommandEntryMessage(Module *creator) : Command(creator, "ENTRYMSG", 2, 3) { this->SetDesc(_("Manage the channel's entry messages")); + this->SetSyntax(_("\037channel\037 {ADD|DEL|LIST|CLEAR} [\037message\037|\037num\037]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; - ChannelInfo *ci = source.ci; - if (ci && (IsFounder(u, ci) || u->HasCommand("chanserv/entrymsg"))) + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } + + if (IsFounder(u, ci) || u->HasCommand("chanserv/entrymsg")) { bool success = true; if (params[1].equals_ci("LIST")) @@ -133,23 +139,16 @@ class CommandEntryMessage : public Command Log(IsFounder(u, ci) ? LOG_COMMAND : LOG_OVERRIDE, u, this, ci) << params[1]; } else - { - source.Reply(_(ACCESS_DENIED)); - } + source.Reply(ACCESS_DENIED); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "ENTRYMSG", _("ENTRYMSG \037channel\037 {ADD|DEL|LIST|CLEAR} [\037message\037|\037num\037]")); + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ENTRYMSG \037channel\037 {ADD|DEL|LIST|CLEAR} [\037message\037|\037num\037]\002\n" - " \n" - "Controls what messages will be sent to users when they join the channel.")); + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("Controls what messages will be sent to users when they join the channel.")); return true; } }; @@ -159,17 +158,14 @@ class CSEntryMessage : public Module CommandEntryMessage commandentrymsg; public: - CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), commandentrymsg("ENTRYMSG") + CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), commandentrymsg(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - Implementation i[] = { I_OnJoinChannel, I_OnReload, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; ModuleManager::Attach(i, this, 4); - this->AddCommand(chanserv->Bot(), &commandentrymsg); + ModuleManager::RegisterService(&commandentrymsg); this->OnReload(); } diff --git a/modules/extra/cs_set_misc.cpp b/modules/extra/cs_set_misc.cpp index 2318d415c..03c498b07 100644 --- a/modules/extra/cs_set_misc.cpp +++ b/modules/extra/cs_set_misc.cpp @@ -11,52 +11,45 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" class CommandCSSetMisc : public Command { Anope::string Desc; public: - CommandCSSetMisc(const Anope::string &cname, const Anope::string &cdesc, const Anope::string &cpermission = "") : Command(cname, 1, 2, cpermission), Desc(cdesc) + CommandCSSetMisc(Module *creator, const Anope::string &cname, const Anope::string &cdesc, const Anope::string &cpermission = "") : Command(creator, "chanserv/set/" + cname, 1, 2, cpermission), Desc(cdesc) { this->SetDesc(cdesc); + this->SetSyntax(_("\037channel\037 \037option\037 \037parameters\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - if (!ci) - throw CoreException("NULL ci in CommandCSSetMisc"); + ChannelInfo *ci = cs_findchan(params[0]); + if (ci == NULL) + { + source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + return; + } ci->Shrink("chanserv:" + this->name); if (params.size() > 1) { ci->Extend("chanserv:" + this->name, new ExtensibleItemRegular<Anope::string>(params[1])); - source.Reply(_(CHAN_SETTING_CHANGED), this->name.c_str(), ci->name.c_str(), params[1].c_str()); + source.Reply(CHAN_SETTING_CHANGED, this->name.c_str(), ci->name.c_str(), params[1].c_str()); } else - source.Reply(_(CHAN_SETTING_UNSET), this->name.c_str(), ci->name.c_str()); + source.Reply(CHAN_SETTING_UNSET, this->name.c_str(), ci->name.c_str()); - return MOD_CONT; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SET", _(CHAN_SET_SYNTAX)); + return; } }; class CommandCSSASetMisc : public CommandCSSetMisc { public: - CommandCSSASetMisc(const Anope::string &cname, const Anope::string &cdesc) : CommandCSSetMisc(cname, cdesc, "chanserv/saset/" + cname) + CommandCSSASetMisc(Module *creator, const Anope::string &cname, const Anope::string &cdesc) : CommandCSSetMisc(creator, cname, cdesc, "chanserv/saset/" + cname) { } - - void OnSyntaxError(CommandSource &source, const Anope::string &) - { - SyntaxError(source, "SASET", _(CHAN_SASET_SYNTAX)); - } }; class CSSetMisc : public Module @@ -75,37 +68,8 @@ class CSSetMisc : public Module void RemoveAll() { - if (!chanserv || Commands.empty()) - return; - - Command *set = FindCommand(chanserv->Bot(), "SET"); - Command *saset = FindCommand(chanserv->Bot(), "SASET"); - - if (!set && !saset) - return; - for (std::map<Anope::string, CommandInfo *>::const_iterator it = this->Commands.begin(), it_end = this->Commands.end(); it != it_end; ++it) - { - if (set) - { - Command *c = set->FindSubcommand(it->second->Name); - if (c) - { - set->DelSubcommand(c); - delete c; - } - } - if (saset) - { - Command *c = saset->FindSubcommand(it->second->Name); - if (c) - { - saset->DelSubcommand(c); - delete c; - } - } - } - + delete it->second; this->Commands.clear(); } @@ -114,9 +78,6 @@ class CSSetMisc : public Module { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - Implementation i[] = { I_OnReload, I_OnChanInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); @@ -132,11 +93,6 @@ class CSSetMisc : public Module { RemoveAll(); - Command *set = FindCommand(chanserv->Bot(), "SET"); - Command *saset = FindCommand(chanserv->Bot(), "SASET"); - if (!set && !saset) - return; - ConfigReader config; for (int i = 0, num = config.Enumerate("cs_set_misc"); i < num; ++i) @@ -155,10 +111,8 @@ class CSSetMisc : public Module continue; } - if (set) - set->AddSubcommand(this, new CommandCSSetMisc(cname, desc)); - if (saset) - saset->AddSubcommand(this, new CommandCSSASetMisc(cname, desc)); + ModuleManager::RegisterService(new CommandCSSetMisc(this, cname, desc)); + ModuleManager::RegisterService(new CommandCSSASetMisc(this, cname, desc)); } } diff --git a/modules/extra/cs_tban.cpp b/modules/extra/cs_tban.cpp index 78c3b1fa9..a0bb6a626 100644 --- a/modules/extra/cs_tban.cpp +++ b/modules/extra/cs_tban.cpp @@ -16,7 +16,6 @@ /*************************************************************************/ #include "module.h" -#include "chanserv.h" static Module *me; @@ -42,11 +41,11 @@ static bool CanBanUser(CommandSource &source, Channel *c, User *u2) ChannelInfo *ci = c->ci; bool ok = false; if (!check_access(u, ci, CA_BAN)) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else if (matches_list(c, u2, CMODE_EXCEPT)) - source.Reply(_(CHAN_EXCEPTED), u2->nick.c_str(), ci->name.c_str()); + source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str()); else if (u2->IsProtected()) - source.Reply(_(ACCESS_DENIED)); + source.Reply(ACCESS_DENIED); else ok = true; @@ -56,25 +55,24 @@ static bool CanBanUser(CommandSource &source, Channel *c, User *u2) class CommandCSTBan : public Command { public: - CommandCSTBan() : Command("TBAN", 3, 3) + CommandCSTBan(Module *m) : Command(m, "TBAN", 3, 3) { this->SetDesc(_("Bans the user for a given length of time")); + this->SetSyntax(_("\037channel\037 \037nick\037 \037time\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - ChannelInfo *ci = source.ci; - Channel *c = ci->c; + Channel *c = findchan(params[0]); - const Anope::string &chan = params[0]; const Anope::string &nick = params[1]; const Anope::string &time = params[2]; User *u2; if (!c) - source.Reply(_(CHAN_X_NOT_IN_USE), chan.c_str()); + source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); else if (!(u2 = finduser(nick))) - source.Reply(_(NICK_X_NOT_IN_USE), nick.c_str()); + source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); else if (CanBanUser(source, c, u2)) { @@ -85,7 +83,7 @@ class CommandCSTBan : public Command source.Reply(_("%s banned from %s, will auto-expire in %s"), mask.c_str(), c->name.c_str(), time.c_str()); } - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) @@ -97,11 +95,6 @@ class CommandCSTBan : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: TBAN channel nick time")); - } }; class CSTBan : public Module @@ -109,16 +102,14 @@ class CSTBan : public Module CommandCSTBan commandcstban; public: - CSTBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) + CSTBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), + commandcstban(this) { this->SetAuthor("Anope"); - if (!chanserv) - throw ModuleException("ChanServ is not loaded!"); - me = this; - this->AddCommand(chanserv->Bot(), &commandcstban); + ModuleManager::RegisterService(&commandcstban); } }; diff --git a/modules/extra/hs_request.cpp b/modules/extra/hs_request.cpp index 518acb6de..74fe04dab 100644 --- a/modules/extra/hs_request.cpp +++ b/modules/extra/hs_request.cpp @@ -16,7 +16,6 @@ */ #include "module.h" -#include "hostserv.h" #include "memoserv.h" static bool HSRequestMemoUser = false; @@ -35,8 +34,6 @@ struct HostRequest typedef std::map<Anope::string, HostRequest *, std::less<ci::string> > RequestMap; RequestMap Requests; -static Module *me; - class CommandHSRequest : public Command { bool isvalidchar(char c) @@ -47,12 +44,13 @@ class CommandHSRequest : public Command } public: - CommandHSRequest() : Command("REQUEST", 1, 1) + CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1) { this->SetDesc(_("Request a vHost for your nick")); + this->SetSyntax(_("vhost")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -65,46 +63,46 @@ class CommandHSRequest : public Command rawhostmask = myStrGetTokenRemainder(rawhostmask, '@', 1); /* get the remaining string */ if (rawhostmask.empty()) { - source.Reply(_("Syntax: \002REQUEST \037vhost\037\002")); - return MOD_CONT; + this->SendSyntax(source); + return; } if (vIdent.length() > Config->UserLen) { - source.Reply(_(HOST_SET_IDENTTOOLONG), Config->UserLen); - return MOD_CONT; + source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); + return; } else for (Anope::string::iterator s = vIdent.begin(), s_end = vIdent.end(); s != s_end; ++s) if (!isvalidchar(*s)) { - source.Reply(_(HOST_SET_IDENT_ERROR)); - return MOD_CONT; + source.Reply(HOST_SET_IDENT_ERROR); + return; } if (!ircd->vident) { - source.Reply(_(HOST_NO_VIDENT)); - return MOD_CONT; + source.Reply(HOST_NO_VIDENT); + return; } } if (rawhostmask.length() < Config->HostLen) hostmask = rawhostmask; else { - source.Reply(_(HOST_SET_TOOLONG), Config->HostLen); - return MOD_CONT; + source.Reply(HOST_SET_TOOLONG, Config->HostLen); + return; } if (!isValidHost(hostmask, 3)) { - source.Reply(_(HOST_SET_ERROR)); - return MOD_CONT; + source.Reply(HOST_SET_ERROR); + return; } if (HSRequestMemoOper && Config->MSSendDelay > 0 && u && u->lastmemosend + Config->MSSendDelay > Anope::CurTime) { source.Reply(_("Please wait %d seconds before requesting a new vHost"), Config->MSSendDelay); u->lastmemosend = Anope::CurTime; - return MOD_CONT; + return; } my_add_host_request(u->nick, vIdent, hostmask, u->nick, Anope::CurTime); @@ -112,34 +110,30 @@ class CommandHSRequest : public Command req_send_memos(source, vIdent, hostmask); Log(LOG_COMMAND, u, this, NULL) << "to request new vhost " << (!vIdent.empty() ? vIdent + "@" : "") << hostmask; - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002REQUEST \037vhost\037\002")); + this->SendSyntax(source); source.Reply(" "); source.Reply(_("Request the given vHost to be actived for your nick by the\n" "network administrators. Please be patient while your request\n" "is being considered.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002REQUEST \037vhost\037\002")); - } }; class CommandHSActivate : public Command { public: - CommandHSActivate() : Command("ACTIVATE", 1, 1, "hostserv/set") + CommandHSActivate(Module *creator) : Command(creator, "hostserv/activate", 1, 1, "hostserv/set") { this->SetDesc(_("Approve the requested vHost of a user")); + this->SetSyntax(_("\037nick\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -155,7 +149,7 @@ class CommandHSActivate : public Command FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); if (HSRequestMemoUser && memoserv) - memoserv->Send(Config->s_HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); + memoserv->Send(Config->HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); source.Reply(_("vHost for %s has been activated"), na->nick.c_str()); Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!it->second->ident.empty() ? it->second->ident + "@" : "") << it->second->host; @@ -166,14 +160,14 @@ class CommandHSActivate : public Command source.Reply(_("No request for nick %s found."), nick.c_str()); } else - source.Reply(_(NICK_X_NOT_REGISTERED), nick.c_str()); + source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002ACTIVATE \037nick\037\002")); + this->SendSyntax(source); source.Reply(" "); source.Reply(_("Activate the requested vHost for the given nick.")); if (HSRequestMemoUser) @@ -181,22 +175,17 @@ class CommandHSActivate : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002ACTIVATE \037nick\037\002")); - } }; class CommandHSReject : public Command { public: - CommandHSReject() : Command("REJECT", 1, 2, "hostserv/set") + CommandHSReject(Module *creator) : Command(creator, "hostserv/reject", 1, 2, "hostserv/set") { this->SetDesc(_("Reject the requested vHost of a user")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; @@ -217,7 +206,7 @@ class CommandHSReject : public Command else message = _("[auto memo] Your requested vHost has been rejected."); - memoserv->Send(Config->s_HostServ, nick, message, true); + memoserv->Send(Config->HostServ, nick, message, true); } source.Reply(_("vHost for %s has been rejected"), nick.c_str()); @@ -226,12 +215,12 @@ class CommandHSReject : public Command else source.Reply(_("No request for nick %s found."), nick.c_str()); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002REJECT \037nick\037\002")); + this->SendSyntax(source); source.Reply(" "); source.Reply(_("Reject the requested vHost for the given nick.")); if (HSRequestMemoUser) @@ -239,17 +228,12 @@ class CommandHSReject : public Command return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002REJECT \037nick\037\002")); - } }; class HSListBase : public Command { protected: - CommandReturn DoList(CommandSource &source) + void DoList(CommandSource &source) { int counter = 1; int from = 0, to = 0; @@ -270,10 +254,10 @@ class HSListBase : public Command } source.Reply(_("Displayed all records (Count: \002%d\002)"), display_counter); - return MOD_CONT; + return; } public: - HSListBase(const Anope::string &cmd, int min, int max) : Command(cmd, min, max, "hostserv/set") + HSListBase(Module *creator, const Anope::string &cmd, int min, int max) : Command(creator, cmd, min, max, "hostserv/set") { } }; @@ -281,22 +265,22 @@ class HSListBase : public Command class CommandHSWaiting : public HSListBase { public: - CommandHSWaiting() : HSListBase("WAITING", 0, 0) + CommandHSWaiting(Module *creator) : HSListBase(creator, "hostserv/waiting", 0, 0) { - this->SetDesc(_("Convenience command for LIST +req")); + this->SetDesc(_("Retrieves the vhost requests")); + this->SetSyntax(""); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return this->DoList(source); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002WAITING\002")); + this->SendSyntax(source); source.Reply(" "); - source.Reply(_("This command is provided for convenience. It is essentially\n" - "the same as performing a LIST +req .")); + source.Reply(_("This command retrieves the vhost requests")); return true; } @@ -310,21 +294,17 @@ class HSRequest : public Module CommandHSWaiting commandhswaiting; public: - HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) + HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), + commandhsrequest(this), commandhsactive(this), commandhsreject(this), commandhswaiting(this) { - me = this; - - if (!hostserv) - throw ModuleException("HostServ is not loaded!"); - - this->AddCommand(hostserv->Bot(), &commandhsrequest); - this->AddCommand(hostserv->Bot(), &commandhsactive); - this->AddCommand(hostserv->Bot(), &commandhsreject); - this->AddCommand(hostserv->Bot(), &commandhswaiting); - this->SetAuthor("Anope"); - Implementation i[] = { I_OnPreCommand, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload }; + ModuleManager::RegisterService(&commandhsrequest); + ModuleManager::RegisterService(&commandhsactive); + ModuleManager::RegisterService(&commandhsreject); + ModuleManager::RegisterService(&commandhswaiting); + + Implementation i[] = { I_OnDelNick, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload }; ModuleManager::Attach(i, this, 4); this->OnReload(); @@ -340,46 +320,15 @@ class HSRequest : public Module } } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + void OnDelNick(NickAlias *na) { - BotInfo *service = source.owner; - if (service->nick == Config->s_HostServ) - { - if (command->name.equals_ci("LIST")) - { - Anope::string key = params.size() ? params[0] : ""; - - if (!key.empty() && key.equals_ci("+req")) - { - std::vector<Anope::string> emptyParams; - Command *c = FindCommand(hostserv->Bot(), "WAITING"); - if (!c) - throw CoreException("No waiting command?"); - c->Execute(source, emptyParams); - return EVENT_STOP; - } - } - } - else if (service->nick == Config->s_NickServ) - { - if (command->name.equals_ci("DROP")) - { - NickAlias *na = findnick(source.u->nick); - - if (na) - { - RequestMap::iterator it = Requests.find(na->nick); + RequestMap::iterator it = Requests.find(na->nick); - if (it != Requests.end()) - { - delete it->second; - Requests.erase(it); - } - } - } + if (it != Requests.end()) + { + delete it->second; + Requests.erase(it); } - - return EVENT_CONTINUE; } EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms) @@ -437,7 +386,7 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.u->GetMask().c_str()); - memoserv->Send(Config->s_HostServ, na->nick, message, true); + memoserv->Send(Config->HostServ, na->nick, message, true); } } diff --git a/modules/extra/m_alias.cpp b/modules/extra/m_alias.cpp deleted file mode 100644 index e1d35b111..000000000 --- a/modules/extra/m_alias.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -#include "module.h" -#include "chanserv.h" - -struct CommandAlias -{ - bool fantasy; - bool operonly; - Anope::string source_client; - Anope::string source_command; - Anope::string source_desc; - Anope::string target_client; - Anope::string target_command; - Anope::string target_rewrite; -}; - -class AliasCommand : public Command -{ - CommandAlias alias; - dynamic_reference<Command> target_command_c; - public: - AliasCommand(CommandAlias &a) : Command(a.source_command, 0, 0), alias(a), target_command_c(NULL) { } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { return MOD_CONT; } - - void OnServHelp(CommandSource &source) - { - Anope::string cdesc = this->alias.source_desc; - if (!this->target_command_c) - this->target_command_c = FindCommand(findbot(this->alias.target_client), this->alias.target_command); - if (this->target_command_c && cdesc.empty()) - cdesc = this->target_command_c->GetDesc(); - if (this->target_command_c) - source.Reply(" %-14s %s", this->name.c_str(), _(cdesc.c_str())); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - if (!this->alias.target_rewrite.empty()) - return false; - - if (!this->target_command_c) - this->target_command_c = FindCommand(findbot(this->alias.target_client), this->alias.target_command); - if (!this->target_command_c) - return false; - - mod_help_cmd(this->target_command_c->service, source.u, source.ci, this->target_command_c->name); - return true; - } -}; - -class ModuleAlias : public Module -{ - std::multimap<Anope::string, CommandAlias, std::less<ci::string> > aliases; - std::vector<AliasCommand *> commands; - - Anope::string RewriteCommand(Anope::string &message, const Anope::string &rewrite) - { - if (rewrite.empty()) - return message; - - std::vector<Anope::string> tokens = BuildStringVector(message); - spacesepstream sep(rewrite); - Anope::string token, final_message; - while (sep.GetToken(token)) - { - if (token[0] == '$' && token.length() > 1) - { - Anope::string number = token.substr(1); - bool all = false; - if (number[number.length() - 1] == '-') - { - number.erase(number.length() - 1); - all = true; - } - if (number.empty()) - continue; - - int index; - try - { - index = convertTo<int>(number); - } - catch (const ConvertException &ex) - { - continue; - } - - if (index < 0 || static_cast<unsigned>(index) >= tokens.size()) - continue; - - final_message += tokens[index] + " "; - if (all) - for (unsigned i = index + i; i < tokens.size(); ++i) - final_message += tokens[i] + " "; - } - else - final_message += token + " "; - } - - final_message.trim(); - return final_message; - } - - public: - ModuleAlias(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED) - { - this->SetAuthor("Anope"); - - Implementation i[] = { I_OnReload, I_OnPreCommandRun, I_OnBotFantasy }; - ModuleManager::Attach(i, this, 3); - - OnReload(); - } - - void OnReload() - { - ConfigReader config; - - this->aliases.clear(); - for (unsigned i = 0; i < this->commands.size(); ++i) - delete this->commands[i]; - this->commands.clear(); - - for (int i = 0; i < config.Enumerate("alias"); ++i) - { - bool fantasy = config.ReadFlag("alias", "fantasy", "no", i); - bool operonly = config.ReadFlag("alias", "operonly", "no", i); - bool hide = config.ReadFlag("alias", "hide", "no", i); - Anope::string source_client = config.ReadValue("alias", "source_client", "", i); - Anope::string source_command = config.ReadValue("alias", "source_command", "", i); - Anope::string source_desc = config.ReadValue("alias", "source_desc", "", i); - Anope::string target_client = config.ReadValue("alias", "target_client", "", i); - Anope::string target_command = config.ReadValue("alias", "target_command", "", i); - Anope::string target_rewrite = config.ReadValue("alias", "target_rewrite", "", i); - - if ((!fantasy && source_client.empty()) || source_command.empty() || target_client.empty() || target_command.empty()) - continue; - - CommandAlias alias; - alias.fantasy = fantasy; - alias.operonly = operonly; - alias.source_client = source_client; - alias.source_command = source_command; - alias.source_desc = source_desc; - alias.target_client = target_client; - alias.target_command = target_command; - alias.target_rewrite = target_rewrite; - - this->aliases.insert(std::make_pair(source_command, alias)); - if (hide == false) - { - AliasCommand *cmd = new AliasCommand(alias); - this->commands.push_back(cmd); - BotInfo *bi = findbot(alias.source_client); - if (bi != NULL) - this->AddCommand(bi, cmd); - } - } - } - - EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) - { - bool fantasy = ci != NULL; - std::multimap<Anope::string, CommandAlias, std::less<ci::string> >::const_iterator it = aliases.find(command), it_end = it; - if (it_end != aliases.end()) - it_end = aliases.upper_bound(command); - for (; it != it_end; ++it) - { - const CommandAlias &alias = it->second; - - if (!u->HasMode(UMODE_OPER) && alias.operonly) - continue; - else if (fantasy != alias.fantasy) - continue; - else if (fantasy && alias.fantasy) // OnBotFantasy gets this! - continue; - else if (!bi->nick.equals_ci(alias.source_client)) - continue; - - BotInfo *target = findbot(alias.target_client); - if (target) - bi = target; - command = alias.target_command; - message = this->RewriteCommand(message, alias.target_rewrite); - break; - } - - return EVENT_CONTINUE; - } - - void OnBotFantasy(const Anope::string &command, User *u, ChannelInfo *ci, const Anope::string ¶ms) - { - std::multimap<Anope::string, CommandAlias, std::less<ci::string> >::const_iterator it = aliases.find(command), it_end = it; - if (it_end != aliases.end()) - it_end = aliases.upper_bound(command); - for (; it != it_end; ++it) - { - const CommandAlias &alias = it->second; - - if (!u->HasMode(UMODE_OPER) && alias.operonly) - continue; - - BotInfo *target = findbot(alias.target_client); - if (!target) - target = chanserv->Bot(); - - Anope::string full_message = alias.target_command; - if (target == chanserv->Bot() || target->nick == Config->s_BotServ) - { - Command *target_c = FindCommand(target, alias.target_command); - if (target_c && !target_c->HasFlag(CFLAG_STRIP_CHANNEL)) - full_message += " " + ci->name; - } - if (!params.empty()) - full_message += + " " + params; - - full_message = this->RewriteCommand(full_message, alias.target_rewrite); - mod_run_cmd(target, u, ci, full_message); - break; - } - } -}; - -MODULE_INIT(ModuleAlias) diff --git a/modules/extra/m_async_commands.cpp b/modules/extra/m_async_commands.cpp index c223bcdc5..665ee536d 100644 --- a/modules/extra/m_async_commands.cpp +++ b/modules/extra/m_async_commands.cpp @@ -53,12 +53,9 @@ class AsynchCommandMutex : public CommandMutex } else { - CommandReturn ret = command->Execute(source, params); - if (ret != MOD_STOP) - { - FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, command, params)); - source.DoReply(); - } + command->Execute(source, params); + FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, command, params)); + source.DoReply(); } main_mutex.Unlock(); @@ -134,14 +131,14 @@ class ModuleAsynchCommands : public Module, public Pipe, public AsynchCommandsSe { AsynchCommandMutex *cm = debug_cast<AsynchCommandMutex *>(*it); - if (cm->started && (cm->command == b || cm->source.u == b || cm->source.owner == b || cm->source.service == b || cm->source.ci == b)) + if (cm->started && (cm->command == b || cm->source.u == b || cm->source.owner == b || cm->source.service == b)) cm->Destroy(); } this->reset = true; } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { if (ignore_pre_command) { diff --git a/modules/extra/m_dnsbl.cpp b/modules/extra/m_dnsbl.cpp index 06d55df92..a860a10f0 100644 --- a/modules/extra/m_dnsbl.cpp +++ b/modules/extra/m_dnsbl.cpp @@ -6,13 +6,8 @@ */ #include "module.h" -#include "operserv.h" -struct FakeAkill : public Command -{ - FakeAkill() : Command("AKILL", 0, 0) { this->service = findbot(Config->s_OperServ); } - CommandReturn Execute(CommandSource &, const std::vector<Anope::string> &) { return MOD_CONT; } -} fake_akill; +static service_reference<XLineManager> akills("xlinemanager/sgline"); struct Blacklist { @@ -62,17 +57,18 @@ class DNSBLResolver : public DNSRequest reason = reason.replace_all_cs("%N", Config->NetworkName); XLine *x = NULL; - if (this->add_to_akill && SGLine && (x = SGLine->Add(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason))) + BotInfo *operserv = findbot(Config->OperServ); + if (this->add_to_akill && akills && (x = akills->Add(Anope::string("*@") + user->host, Config->OperServ, Anope::CurTime + this->blacklist.bantime, reason))) { - Log(LOG_COMMAND, operserv->Bot(), &fake_akill) << "for " << user->GetMask() << " (Listed in " << this->blacklist.name << ")"; + Log(operserv) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; /* If AkillOnAdd is disabled send it anyway, noone wants bots around... */ if (!Config->AkillOnAdd) ircdproto->SendAkill(user, x); } else { - Log(operserv->Bot()) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; - XLine xline(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason); + Log(operserv) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name << "(" << reason << ")"; + XLine xline(Anope::string("*@") + user->host, Config->OperServ, Anope::CurTime + this->blacklist.bantime, reason); ircdproto->SendAkill(user, &xline); } } diff --git a/modules/extra/m_helpchan.cpp b/modules/extra/m_helpchan.cpp index 6e5cdd2be..5da492a3a 100644 --- a/modules/extra/m_helpchan.cpp +++ b/modules/extra/m_helpchan.cpp @@ -6,7 +6,6 @@ */ #include "module.h" -#include "operserv.h" class HelpChannel : public Module { @@ -25,12 +24,12 @@ class HelpChannel : public Module EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) { - if (Name == CMODE_OP && operserv && c && c->ci && c->name.equals_ci(this->HelpChan)) + if (Name == CMODE_OP && c && c->ci && c->name.equals_ci(this->HelpChan)) { User *u = finduser(param); if (u && check_access(u, c->ci, CA_OPDEOPME)) - u->SetMode(operserv->Bot(), UMODE_HELPOP); + u->SetMode(findbot(Config->OperServ), UMODE_HELPOP); } return EVENT_CONTINUE; diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index 59e532d50..a6fa5bd1b 100644 --- a/modules/extra/m_ldap_authentication.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -8,11 +8,12 @@ struct IdentifyInfo { dynamic_reference<User> user; dynamic_reference<Command> command; + CommandSource source; std::vector<Anope::string> params; Anope::string account; Anope::string pass; - IdentifyInfo(User *u, Command *c, const std::vector<Anope::string> &pa, const Anope::string &a, const Anope::string &p) : user(u), command(c), params(pa), account(a), pass(p) { } + IdentifyInfo(User *u, Command *c, CommandSource &s, const std::vector<Anope::string> &pa, const Anope::string &a, const Anope::string &p) : user(u), command(c), source(s), params(pa), account(a), pass(p) { } }; @@ -57,15 +58,14 @@ class IdentifyInterface : public LDAPInterface if (Config->NSAddAccessOnReg) na->nc->AddAccess(create_mask(u)); - u->SendMessage(nickserv->Bot(), _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); + BotInfo *bi = findbot(Config->NickServ); + if (bi) + u->SendMessage(bi, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); } enc_encrypt(ii->pass, na->nc->pass); - Anope::string params; - for (unsigned i = 0; i < ii->params.size(); ++i) - params += ii->params[i] + " "; - mod_run_cmd(c->service, u, NULL, c, c->name, params); + c->Execute(ii->source, ii->params); delete ii; } @@ -89,10 +89,7 @@ class IdentifyInterface : public LDAPInterface u->Extend("m_ldap_authentication_error"); - Anope::string params; - for (unsigned i = 0; i < ii->params.size(); ++i) - params += ii->params[i] + " "; - mod_run_cmd(c->service, u, NULL, c, c->name, params); + c->Execute(ii->source, ii->params); delete ii; } @@ -129,7 +126,9 @@ class OnIdentifyInterface : public LDAPInterface if (!email.equals_ci(u->Account()->email)) { u->Account()->email = email; - u->SendMessage(nickserv->Bot(), _("Your email has been updated to \002%s\002"), email.c_str()); + BotInfo *bi = findbot(Config->NickServ); + if (bi) + u->SendMessage(bi, _("Your email has been updated to \002%s\002"), email.c_str()); Log() << "m_ldap_authentication: Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email; } } @@ -201,9 +200,9 @@ class NSIdentifyLDAP : public Module this->disable_reason = config.ReadValue("m_ldap_authentication", "disable_reason", "", 0); } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { - if (this->disable_register && !this->disable_reason.empty() && nickserv && command->service == nickserv->Bot() && command->name == "REGISTER") + if (this->disable_register && !this->disable_reason.empty() && command->name == "nickserv/register") { source.Reply(_(this->disable_reason.c_str())); return EVENT_STOP; @@ -212,11 +211,14 @@ class NSIdentifyLDAP : public Module return EVENT_CONTINUE; } - EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) + EventReturn OnCheckAuthentication(Command *c, CommandSource *source, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { - if (u == NULL || c == NULL || !this->ldap) + + if (c == NULL || source == NULL || !this->ldap) return EVENT_CONTINUE; - else if (u->GetExt("m_ldap_authentication_authenticated")) + + User *u = source->u; + if (u->GetExt("m_ldap_authentication_authenticated")) { u->Shrink("m_ldap_authentication_authenticated"); return EVENT_ALLOW; @@ -227,7 +229,7 @@ class NSIdentifyLDAP : public Module return EVENT_CONTINUE; } - IdentifyInfo *ii = new IdentifyInfo(u, c, params, account, password); + IdentifyInfo *ii = new IdentifyInfo(u, c, *source, params, account, password); try { Anope::string full_binddn = this->username_attribute + "=" + account + "," + this->binddn; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 6a113a14a..895ad437c 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -8,7 +8,7 @@ class XMLRPCUser : public User dynamic_reference<NickAlias> na; public: - XMLRPCUser(const Anope::string &nnick) : User(nnick, Config->ServiceUser, Config->ServiceHost, ""), na(findnick(nick)) + XMLRPCUser(const Anope::string &nnick) : User(nnick, Config->NSEnforcerUser, Config->NSEnforcerHost, ""), na(findnick(nick)) { this->realname = "XMLRPC User"; this->server = Me; @@ -87,7 +87,7 @@ class MyXMLRPCEvent : public XMLRPCEvent else request->reply("online", "yes"); - mod_run_cmd(bi, u, NULL, command); + bi->OnMessage(u, command); if (created && u) { @@ -131,14 +131,6 @@ class MyXMLRPCEvent : public XMLRPCEvent void DoStats(XMLRPCServiceInterface *iface, XMLRPCClientSocket *source, XMLRPCRequest *request) { - if (SGLine) - request->reply("sglinecount", stringify(SGLine->GetCount())); - if (SQLine) - request->reply("sqlinecount", stringify(SQLine->GetCount())); - if (SNLine) - request->reply("snlinecount", stringify(SNLine->GetCount())); - if (SZLine) - request->reply("szlinecount", stringify(SZLine->GetCount())); request->reply("uptime", stringify(Anope::CurTime - start_time)); request->reply("uplinkname", Me->GetLinks().front()->GetName()); { diff --git a/modules/extra/ns_maxemail.cpp b/modules/extra/ns_maxemail.cpp index 25feffd79..18be74bce 100644 --- a/modules/extra/ns_maxemail.cpp +++ b/modules/extra/ns_maxemail.cpp @@ -71,24 +71,17 @@ class NSMaxEmail : public Module Log(LOG_DEBUG) << "[ns_maxemail] NSEmailMax set to " << NSEmailMax; } - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { - BotInfo *service = source.owner; - if (service->nick == Config->s_NickServ) + if (command->name == "nickserv/register") { - if (command->name.equals_ci("REGISTER")) - { - if (this->CheckLimitReached(source, params.size() > 1 ? params[1] : "")) - return EVENT_STOP; - } - else if (command->name.equals_ci("SET")) - { - Anope::string set = params[0]; - Anope::string email = params.size() > 1 ? params[1] : ""; - - if (set.equals_ci("email") && this->CheckLimitReached(source, email)) - return EVENT_STOP; - } + if (this->CheckLimitReached(source, params.size() > 1 ? params[1] : "")) + return EVENT_STOP; + } + else if (command->name == "nickserv/set/email") + { + if (this->CheckLimitReached(source, params.size() > 0 ? params[0] : "")) + return EVENT_STOP; } return EVENT_CONTINUE; diff --git a/modules/extra/ns_set_misc.cpp b/modules/extra/ns_set_misc.cpp index b70a871de..12fcf66c9 100644 --- a/modules/extra/ns_set_misc.cpp +++ b/modules/extra/ns_set_misc.cpp @@ -12,54 +12,54 @@ /*************************************************************************/ #include "module.h" -#include "nickserv.h" class CommandNSSetMisc : public Command { - private: - Anope::string Desc; - public: - CommandNSSetMisc(const Anope::string &cname, const Anope::string &cdesc, const Anope::string &cpermission = "") : Command(cname, 1, 2, cpermission), Desc(cdesc) + CommandNSSetMisc(Module *creator, const Anope::string &cname, const Anope::string &cdesc, const Anope::string &cpermission = "", size_t min = 1) : Command(owner, "nickserv/set/" + cname, min, min + 1, cpermission) { this->SetDesc(cdesc); + this->SetSyntax(_("\037parameter\037")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) { - NickAlias *na = findnick(params[0]); + NickAlias *na = findnick(user); if (!na) - throw CoreException("NULL na in CommandNSSetMisc"); + { + source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); + return; + } NickCore *nc = na->nc; nc->Shrink("nickserv:" + this->name); - if (params.size() > 1) + if (!param.empty()) { - nc->Extend("nickserv:" + this->name, new ExtensibleItemRegular<Anope::string>(params[1])); - source.Reply(_(CHAN_SETTING_CHANGED), this->name.c_str(), nc->display.c_str(), params[1].c_str()); + nc->Extend("nickserv:" + this->name, new ExtensibleItemRegular<Anope::string>(param)); + source.Reply(CHAN_SETTING_CHANGED, this->name.c_str(), nc->display.c_str(), param.c_str()); } else - source.Reply(_(CHAN_SETTING_UNSET), this->name.c_str(), nc->display.c_str()); + source.Reply(CHAN_SETTING_UNSET, this->name.c_str(), nc->display.c_str()); - return MOD_CONT; + return; } - void OnSyntaxError(CommandSource &source, const Anope::string &) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - SyntaxError(source, "SET", _(NICK_SET_SYNTAX)); + this->Run(source, source.u->Account()->display, params[0]); } }; class CommandNSSASetMisc : public CommandNSSetMisc { public: - CommandNSSASetMisc(const Anope::string &cname, const Anope::string &cdesc) : CommandNSSetMisc(cname, cdesc, "nickserv/saset/" + cname) + CommandNSSASetMisc(Module *creator, const Anope::string &cname, const Anope::string &cdesc) : CommandNSSetMisc(creator, "nickserv/saset/" + cname, cdesc, "nickserv/saset/" + cname, 2) { } - void OnSyntaxError(CommandSource &source, const Anope::string &) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - SyntaxError(source, "SASET", _(NICK_SASET_SYNTAX)); + this->Run(source, params[0], params[1]); } }; @@ -78,37 +78,8 @@ class NSSetMisc : public Module void RemoveAll() { - if (!nickserv || Commands.empty()) - return; - - Command *set = FindCommand(nickserv->Bot(), "SET"); - Command *saset = FindCommand(nickserv->Bot(), "SASET"); - - if (!set && !saset) - return; - for (std::map<Anope::string, CommandInfo *>::const_iterator it = this->Commands.begin(), it_end = this->Commands.end(); it != it_end; ++it) - { - if (set) - { - Command *c = set->FindSubcommand(it->second->Name); - if (c) - { - set->DelSubcommand(c); - delete c; - } - } - if (saset) - { - Command *c = saset->FindSubcommand(it->second->Name); - if (c) - { - saset->DelSubcommand(c); - delete c; - } - } - } - + delete it->second; this->Commands.clear(); } @@ -117,9 +88,6 @@ class NSSetMisc : public Module { this->SetAuthor("Anope"); - if (!nickserv) - throw ModuleException("NickServ is not loaded!"); - Implementation i[] = { I_OnReload, I_OnNickInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); @@ -135,11 +103,6 @@ class NSSetMisc : public Module { RemoveAll(); - Command *set = FindCommand(nickserv->Bot(), "SET"); - Command *saset = FindCommand(nickserv->Bot(), "SASET"); - if (!set && !saset) - return; - ConfigReader config; for (int i = 0, num = config.Enumerate("ns_set_misc"); i < num; ++i) @@ -158,10 +121,8 @@ class NSSetMisc : public Module continue; } - if (set) - set->AddSubcommand(this, new CommandNSSetMisc(cname, desc)); - if (saset) - saset->AddSubcommand(this, new CommandNSSASetMisc(cname, desc)); + ModuleManager::RegisterService(new CommandNSSetMisc(this, cname, desc)); + ModuleManager::RegisterService(new CommandNSSASetMisc(this, cname, desc)); } } diff --git a/modules/extra/os_defcon.cpp b/modules/extra/os_defcon.cpp index b7e523312..cad01e8a4 100644 --- a/modules/extra/os_defcon.cpp +++ b/modules/extra/os_defcon.cpp @@ -12,7 +12,6 @@ /*************************************************************************/ #include "module.h" -#include "operserv.h" #include "global.h" #include "os_session.h" @@ -30,7 +29,6 @@ enum DefconLevel DEFCON_NO_NEW_MEMOS }; -static Module *me = NULL; bool DefConModesSet = false; struct DefconConfig @@ -118,18 +116,17 @@ class DefConTimeout : public CallBack { DConfig.defaultlevel = level; FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(level)); - Log(operserv->Bot(), "operserv/defcon") << "Defcon level timeout, returning to level " << level; - ircdproto->SendGlobops(operserv->Bot(), translate(_("\002%s\002 Changed the DEFCON level to \002%d\002")), Config->s_OperServ.c_str(), level); + Log(findbot(Config->OperServ), "operserv/defcon") << "Defcon level timeout, returning to level " << level; if (DConfig.globalondefcon) { if (!DConfig.offmessage.empty()) - global->SendGlobal(global->Bot(), "", DConfig.offmessage); + global->SendGlobal(findbot(Config->Global), "", DConfig.offmessage); else - global->SendGlobal(global->Bot(), "", Anope::printf(translate(_("The Defcon Level is now at Level: \002%d\002")), DConfig.defaultlevel)); + global->SendGlobal(findbot(Config->Global), "", Anope::printf(translate(_("The Defcon Level is now at Level: \002%d\002")), DConfig.defaultlevel)); if (!DConfig.message.empty()) - global->SendGlobal(global->Bot(), "", DConfig.message); + global->SendGlobal(findbot(Config->Global), "", DConfig.message); } runDefCon(); @@ -165,12 +162,13 @@ class CommandOSDefcon : public Command } public: - CommandOSDefcon() : Command("DEFCON", 1, 1, "operserv/defcon") + CommandOSDefcon(Module *creator) : Command(creator, "operserv/defcon", 1, 1, "operserv/defcon") { this->SetDesc(_("Manipulate the DefCon system")); + this->SetSyntax(_("[\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); } - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { User *u = source.u; const Anope::string &lvl = params[0]; @@ -179,7 +177,7 @@ class CommandOSDefcon : public Command { source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); this->SendLevels(source); - return MOD_CONT; + return; } int newLevel = 0; @@ -192,7 +190,7 @@ class CommandOSDefcon : public Command if (newLevel < 1 || newLevel > 5) { this->OnSyntaxError(source, ""); - return MOD_CONT; + return; } DConfig.defaultlevel = newLevel; @@ -206,49 +204,46 @@ class CommandOSDefcon : public Command } if (DConfig.timeout) - timeout = new DefConTimeout(me, 5); + timeout = new DefConTimeout(this->module, 5); source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); this->SendLevels(source); Log(LOG_ADMIN, u, this) << "to change defcon level to " << newLevel; - ircdproto->SendGlobops(operserv->Bot(), _("\002%s\002 Changed the DEFCON level to \002%d\002"), u->nick.c_str(), newLevel); + /* Global notice the user what is happening. Also any Message that the Admin would like to add. Set in config file. */ if (DConfig.globalondefcon) { if (DConfig.defaultlevel == 5 && !DConfig.offmessage.empty()) - global->SendGlobal(global->Bot(), "", DConfig.offmessage); + global->SendGlobal(findbot(Config->Global), "", DConfig.offmessage); else if (DConfig.defaultlevel != 5) { - global->SendGlobal(global->Bot(), "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); + global->SendGlobal(findbot(Config->Global), "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); if (!DConfig.message.empty()) - global->SendGlobal(global->Bot(), "", DConfig.message); + global->SendGlobal(findbot(Config->Global), "", DConfig.message); } } /* Run any defcon functions, e.g. FORCE CHAN MODE */ runDefCon(); - return MOD_CONT; + return; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002DEFCON\002 [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]\n" - "The defcon system can be used to implement a pre-defined\n" + this->SendSyntax(source); + source.Reply(" "); + source.Reply(_("The defcon system can be used to implement a pre-defined\n" "set of restrictions to services useful during an attempted\n" "attack on the network.")); return true; } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEFCON", _("DEFCON [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); - } }; class OSDefcon : public Module { service_reference<SessionService> session_service; + service_reference<XLineManager> akills; CommandOSDefcon commandosdefcon; void ParseModeString() @@ -339,22 +334,17 @@ class OSDefcon : public Module } public: - OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), session_service("session") + OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, SUPPORTED), session_service("session"), akills("xlinemanager/sgline"), commandosdefcon(this) { if (!DConfig.defaultlevel) throw ModuleException("Invalid configuration settings"); - me = this; - this->SetAuthor("Anope"); - Implementation i[] = { I_OnReload, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommandRun, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate }; - ModuleManager::Attach(i, this, 9); - - if (!operserv) - throw ModuleException("OperServ is not loaded!"); + Implementation i[] = { I_OnReload, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate }; + ModuleManager::Attach(i, this, 8); - this->AddCommand(operserv->Bot(), &commandosdefcon); + ModuleManager::RegisterService(&commandosdefcon); this->OnReload(); } @@ -378,9 +368,9 @@ class OSDefcon : public Module dconfig.offmessage = config.ReadValue("defcon", "offmessage", 0); if (dconfig.defaultlevel < 1 || dconfig.defaultlevel > 5) - throw ConfigException("The value for <os_defcon:defaultlevel> must be between 1 and 5"); + throw ConfigException("The value for <defcon:defaultlevel> must be between 1 and 5"); else if (dconfig.akillexpire <= 0) - throw ConfigException("The value for <os_defcon:akillexpire> must be greater than zero!"); + throw ConfigException("The value for <defcon:akillexpire> must be greater than zero!"); for (unsigned level = 1; level < 5; ++level) { @@ -411,11 +401,11 @@ class OSDefcon : public Module } if (dconfig.Check(level, DEFCON_REDUCE_SESSION) && dconfig.sessionlimit <= 0) - throw ConfigException("The value for <os_defcon:sessionlimit> must be greater than zero!"); + throw ConfigException("The value for <defcon:sessionlimit> must be greater than zero!"); else if (dconfig.Check(level, DEFCON_AKILL_NEW_CLIENTS) && dconfig.akillreason.empty()) - throw ConfigException("The value for <os_defcon:akillreason> must not be empty!"); + throw ConfigException("The value for <defcon:akillreason> must not be empty!"); else if (dconfig.Check(level, DEFCON_FORCE_CHAN_MODES) && dconfig.chanmodes.empty()) - throw ConfigException("The value for <os_defcon:chanmodes> must not be empty!"); + throw ConfigException("The value for <defcon:chanmodes> must not be empty!"); } DConfig = dconfig; @@ -426,16 +416,16 @@ class OSDefcon : public Module { if (!exempt && u->server->IsSynced() && DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && !u->server->IsULined()) { - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && akills) { - Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; - XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + Log(findbot(Config->OperServ), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = akills->Add("*@" + u->host, Config->OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); if (x) - x->By = Config->s_OperServ; + x->By = Config->OperServ; } if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) - u->Kill(Config->s_OperServ, DConfig.akillreason); + u->Kill(Config->OperServ, DConfig.akillreason); return EVENT_STOP; } @@ -449,7 +439,7 @@ class OSDefcon : public Module if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOff.HasFlag(Name)) { - c->RemoveMode(operserv->Bot(), Name, param); + c->RemoveMode(findbot(Config->OperServ), Name, param); return EVENT_STOP; } @@ -466,9 +456,9 @@ class OSDefcon : public Module Anope::string param; if (DConfig.GetDefConParam(Name, param)) - c->SetMode(operserv->Bot(), Name, param); + c->SetMode(findbot(Config->OperServ), Name, param); else - c->SetMode(operserv->Bot(), Name); + c->SetMode(findbot(Config->OperServ), Name); return EVENT_STOP; @@ -477,61 +467,38 @@ class OSDefcon : public Module return EVENT_CONTINUE; } - EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) + EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) { - if (!u->HasMode(UMODE_OPER) && (DConfig.Check(DEFCON_OPER_ONLY) || DConfig.Check(DEFCON_SILENT_OPER_ONLY))) + if (command->name == "nickserv/register" || command->name == "nickserv/group") { - if (!DConfig.Check(DEFCON_SILENT_OPER_ONLY)) - u->SendMessage(bi, _("Services are in Defcon mode, Please try again later.")); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) - { - BotInfo *service = command->service; - if (service->nick == Config->s_NickServ) - { - if (command->name.equals_ci("REGISTER") || command->name.equals_ci("GROUP")) + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) { - if (DConfig.Check(DEFCON_NO_NEW_NICKS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; } } - else if (service->nick == Config->s_ChanServ) + else if (command->name == "chanserv/set/mlock") { - if (command->name.equals_ci("SET")) + if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) { - if (!params.empty() && params[0].equals_ci("MLOCK") && DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; } - else if (command->name.equals_ci("REGISTER")) + } + else if (command->name == "chanserv/register") + { + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) { - if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; } } - else if (service->nick == Config->s_MemoServ) + else if (command->name == "memoserv/send") { - if (command->name.equals_ci("SEND") || command->name.equals_ci("SENDALL")) + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) { - if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; } } @@ -543,37 +510,33 @@ class OSDefcon : public Module if (exempt || !u || !u->server->IsSynced() || u->server->IsULined()) return; - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && akills) { - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) - { - Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; - XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); - if (x) - x->By = Config->s_OperServ; - } - - if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) - { - u->Kill(Config->s_OperServ, DConfig.akillreason); - return; - } + Log(findbot(Config->OperServ), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = akills->Add("*@" + u->host, Config->OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + if (x) + x->By = Config->OperServ; + } + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + u->Kill(Config->OperServ, DConfig.akillreason); + return; } if (!DConfig.sessionlimit) return; - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && akills) { - Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; - XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, !DConfig.akillreason.empty() ? DConfig.akillreason : "DEFCON AKILL"); + Log(findbot(Config->OperServ), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = akills->Add("*@" + u->host, Config->OperServ, Anope::CurTime + DConfig.akillexpire, !DConfig.akillreason.empty() ? DConfig.akillreason : "DEFCON AKILL"); if (x) - x->By = Config->s_OperServ; + x->By = Config->OperServ; } if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) { - u->Kill(Config->s_OperServ, DConfig.akillreason); + u->Kill(Config->OperServ, DConfig.akillreason); return; } @@ -585,16 +548,16 @@ class OSDefcon : public Module if (session && session->count > DConfig.sessionlimit) { if (!Config->SessionLimitExceeded.empty()) - ircdproto->SendMessage(operserv->Bot(), u->nick, Config->SessionLimitExceeded.c_str(), u->host.c_str()); + ircdproto->SendMessage(findbot(Config->OperServ), u->nick, Config->SessionLimitExceeded.c_str(), u->host.c_str()); if (!Config->SessionLimitDetailsLoc.empty()) - ircdproto->SendMessage(operserv->Bot(), u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); + ircdproto->SendMessage(findbot(Config->OperServ), u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); - u->Kill(Config->s_OperServ, "Defcon session limit exceeded"); + u->Kill(Config->OperServ, "Defcon session limit exceeded"); ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) + if (akills && Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) { - SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Defcon session limit exceeded"); - ircdproto->SendGlobops(operserv->Bot(), "[DEFCON] Added a temporary AKILL for \2*@%s\2 due to excessive connections", u->host.c_str()); + akills->Add("*@" + u->host, Config->OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Defcon session limit exceeded"); + ircdproto->SendGlobops(findbot(Config->OperServ), "[DEFCON] Added a temporary AKILL for \2*@%s\2 due to excessive connections", u->host.c_str()); } } } @@ -609,7 +572,7 @@ class OSDefcon : public Module void OnChannelCreate(Channel *c) { if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) - c->SetModes(operserv->Bot(), false, "%s", DConfig.chanmodes.c_str()); + c->SetModes(findbot(Config->OperServ), false, "%s", DConfig.chanmodes.c_str()); } }; @@ -648,10 +611,10 @@ void runDefCon() { if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') { - Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels"; + Log(findbot(Config->OperServ), "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels"; DefConModesSet = true; for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - it->second->SetModes(operserv->Bot(), false, "%s", DConfig.chanmodes.c_str()); + it->second->SetModes(findbot(Config->OperServ), false, "%s", DConfig.chanmodes.c_str()); } } } @@ -665,9 +628,9 @@ void runDefCon() Anope::string newmodes = defconReverseModes(DConfig.chanmodes); if (!newmodes.empty()) { - Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; + Log(findbot(Config->OperServ), "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - it->second->SetModes(operserv->Bot(), false, "%s", newmodes.c_str()); + it->second->SetModes(findbot(Config->OperServ), false, "%s", newmodes.c_str()); } } } diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index ff2cab4d2..ece676f22 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "oper.h" #include "nickserv.h" IRCDVar myIrcd[] = { @@ -224,7 +225,7 @@ class BahamutIRCdProto : public IRCDProto /* nc_change was = 1, and there is no na->status */ void SendUnregisteredNick(const User *u) { - ircdproto->SendMode(nickserv->Bot(), u, "+d 1"); + ircdproto->SendMode(findbot(Config->NickServ), u, "+d 1"); } /* SERVER */ @@ -247,7 +248,7 @@ class BahamutIRCdProto : public IRCDProto if (!u->Account()) return; - ircdproto->SendMode(nickserv->Bot(), u, "+d %d", u->timestamp); + ircdproto->SendMode(findbot(Config->NickServ), u, "+d %d", u->timestamp); } void SendChannel(Channel *c) @@ -306,7 +307,7 @@ class BahamutIRCdMessage : public IRCdMessage { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else nickserv->Validate(user); @@ -472,49 +473,6 @@ class BahamutIRCdMessage : public IRCdMessage } }; -static bool event_xs(const Anope::string &bot, const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty() && !bot.empty()) - { - std::vector<Anope::string> p; - p.push_back(bot); - p.push_back(params[0]); - return ircdmessage->OnPrivmsg(source, p); - } - - return true; -} - -/* EVENT : OS */ -bool event_os(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - return event_xs(Config->s_OperServ, source, params); -} - -/* EVENT : NS */ -bool event_ns(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - return event_xs(Config->s_NickServ, source, params); -} - -/* EVENT : MS */ -bool event_ms(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - return event_xs(Config->s_MemoServ, source, params); -} - -/* EVENT : HS */ -bool event_hs(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - return event_xs(Config->s_HostServ, source, params); -} - -/* EVENT : CS */ -bool event_cs(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - return event_xs(Config->s_ChanServ, source, params); -} - bool event_burst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { Server *s = Server::Find(source); @@ -558,7 +516,7 @@ class ChannelModeFlood : public ChannelModeParam class ProtoBahamut : public Module { - Message message_svsmode, message_cs, message_hs, message_ms, message_ns, message_os, message_burst; + Message message_svsmode, message_burst; BahamutIRCdProto ircd_proto; BahamutIRCdMessage ircd_message; @@ -602,9 +560,7 @@ class ProtoBahamut : public Module public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_svsmode("SVSMODE", OnMode), message_cs("CS", event_cs), message_hs("HS", event_hs), - message_ms("MS", event_ms), message_ns("NS", event_ns), message_os("OS", event_os), - message_burst("BURST", event_burst) + message_svsmode("SVSMODE", OnMode), message_burst("BURST", event_burst) { this->SetAuthor("Anope"); diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index 54a615aaf..d58e1c987 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -33,7 +33,7 @@ class InspIRCdTS6Proto : public IRCDProto private: void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent) { - User *u = finduser(Config->s_HostServ); + User *u = finduser(Config->HostServ); if (!has_chgidentmod) Log() << "CHGIDENT not loaded!"; else @@ -42,7 +42,7 @@ class InspIRCdTS6Proto : public IRCDProto void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost) { - User *u = finduser(Config->s_HostServ); + User *u = finduser(Config->HostServ); if (!has_chghostmod) Log() << "CHGHOST not loaded!"; else @@ -53,7 +53,7 @@ class InspIRCdTS6Proto : public IRCDProto void SendAkillDel(const XLine *x) { - User *u = finduser(Config->s_OperServ); + User *u = finduser(Config->OperServ); send_cmd(u ? u->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); } @@ -79,7 +79,7 @@ class InspIRCdTS6Proto : public IRCDProto time_t timeleft = x->Expires - Anope::CurTime; if (timeleft > 172800 || !x->Expires) timeleft = 172800; - User *u = finduser(Config->s_OperServ); + User *u = finduser(Config->OperServ); send_cmd(u ? u->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); } @@ -153,7 +153,7 @@ class InspIRCdTS6Proto : public IRCDProto /* SQLINE */ void SendSQLine(User *, const XLine *x) { - send_cmd(Config->Numeric, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->s_OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); + send_cmd(Config->Numeric, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); } /* SQUIT */ @@ -183,13 +183,17 @@ class InspIRCdTS6Proto : public IRCDProto /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) { - send_cmd(nickserv->Bot()->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); + BotInfo *bi = findbot(Config->NickServ); + if (bi) + send_cmd(bi->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); } /* SVSHOLD - release */ void SendSVSHoldDel(const Anope::string &nick) { - send_cmd(nickserv->Bot()->GetUID(), "SVSHOLD %s", nick.c_str()); + BotInfo *bi = findbot(Config->NickServ); + if (bi) + send_cmd(bi->GetUID(), "SVSHOLD %s", nick.c_str()); } /* UNSZLINE */ diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 1790aaa84..961b36df3 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -14,6 +14,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" IRCDVar myIrcd[] = { {"InspIRCd 1.1", /* ircd name */ @@ -57,11 +58,11 @@ void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) { if (nick.empty() || vhost.empty()) return; - send_cmd(Config->s_OperServ, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); + send_cmd(Config->OperServ, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); } else { - BotInfo *bi = findbot(Config->s_OperServ); + BotInfo *bi = findbot(Config->OperServ); if (bi) ircdproto->SendGlobops(bi, "CHGHOST not loaded!"); } @@ -86,7 +87,7 @@ class InspIRCdProto : public IRCDProto { void SendAkillDel(const XLine *x) { - send_cmd(Config->s_OperServ, "GLINE %s", x->Mask.c_str()); + send_cmd(Config->OperServ, "GLINE %s", x->Mask.c_str()); } void SendTopic(BotInfo *whosets, Channel *c) @@ -126,7 +127,7 @@ class InspIRCdProto : public IRCDProto void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) { - send_cmd(source ? source->nick : Config->s_OperServ, "FMODE %s %u %s", dest->name.c_str(), static_cast<unsigned>(dest->creation_time), buf.c_str()); + send_cmd(source ? source->nick : Config->OperServ, "FMODE %s %u %s", dest->name.c_str(), static_cast<unsigned>(dest->creation_time), buf.c_str()); } void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) @@ -175,13 +176,13 @@ class InspIRCdProto : public IRCDProto /* UNSQLINE */ void SendSQLineDel(const XLine *x) { - send_cmd(Config->s_OperServ, "QLINE %s", x->Mask.c_str()); + send_cmd(Config->OperServ, "QLINE %s", x->Mask.c_str()); } /* SQLINE */ void SendSQLine(User *, const XLine *x) { - send_cmd(Config->ServerName, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->s_OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); + send_cmd(Config->ServerName, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); } /* SQUIT */ @@ -216,7 +217,7 @@ class InspIRCdProto : public IRCDProto { if (nick.empty() || vIdent.empty()) return; - send_cmd(Config->s_OperServ, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); + send_cmd(Config->OperServ, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); } else Log() << "CHGIDENT not loaded!"; @@ -225,19 +226,19 @@ class InspIRCdProto : public IRCDProto /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) { - send_cmd(Config->s_OperServ, "SVSHOLD %s %ds :Being held for registered user", nick.c_str(), static_cast<int>(Config->NSReleaseTimeout)); + send_cmd(Config->OperServ, "SVSHOLD %s %ds :Being held for registered user", nick.c_str(), static_cast<int>(Config->NSReleaseTimeout)); } /* SVSHOLD - release */ void SendSVSHoldDel(const Anope::string &nick) { - send_cmd(Config->s_OperServ, "SVSHOLD %s", nick.c_str()); + send_cmd(Config->OperServ, "SVSHOLD %s", nick.c_str()); } /* UNSZLINE */ void SendSZLineDel(const XLine *x) { - send_cmd(Config->s_OperServ, "ZLINE %s", x->Mask.c_str()); + send_cmd(Config->OperServ, "ZLINE %s", x->Mask.c_str()); } /* SZLINE */ @@ -326,7 +327,7 @@ class InspircdIRCdMessage : public IRCdMessage { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED)) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else nickserv->Validate(user); diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index 9e81c2b3f..639d892bf 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -14,6 +14,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" /* inspircd-ts6.h uses these */ static bool has_globopsmod = false; @@ -269,7 +270,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string NickAlias *user_na = findnick(u->nick); if (nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(nickserv->Bot(), UMODE_REGISTERED); + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } } @@ -768,7 +769,7 @@ class ProtoInspIRCd : public Module /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later * this will cancel out this -r, resulting in no mode changes. */ - u->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); + u->RemoveMode(findbot(Config->NickServ), UMODE_REGISTERED); } void OnServerSync(Server *s) diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 7d85bcc3f..92bbf7fba 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -14,6 +14,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" /* inspircd-ts6.h uses these */ static bool has_chghostmod = false; @@ -280,7 +281,7 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string NickAlias *user_na = findnick(u->nick); if (nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(nickserv->Bot(), UMODE_REGISTERED); + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } } diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index c83aa786e..438b74fac 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -12,6 +12,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" static Anope::string TS6UPLINK; @@ -101,20 +102,20 @@ class PlexusProto : public IRCDProto void SendSGLineDel(const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNXLINE * %s", x->Mask.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "UNXLINE * %s", x->Mask.c_str()); } void SendSGLine(User *, const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); } void SendAkillDel(const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); } void SendSQLineDel(const XLine *x) @@ -136,8 +137,8 @@ class PlexusProto : public IRCDProto void SendAkill(User *, const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); } void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) @@ -536,7 +537,7 @@ bool event_encap(const Anope::string &source, const std::vector<Anope::string> & { u->Login(nc); if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(nickserv->Bot(), UMODE_REGISTERED); + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } } diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 13a5e287a..95d8405d9 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -12,6 +12,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" static Anope::string TS6UPLINK; @@ -104,20 +105,20 @@ class RatboxProto : public IRCDProto void SendSGLineDel(const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNXLINE * %s", x->Mask.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "UNXLINE * %s", x->Mask.c_str()); } void SendSGLine(User *, const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); } void SendAkillDel(const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); } void SendSQLineDel(const XLine *x) @@ -143,8 +144,8 @@ class RatboxProto : public IRCDProto void SendAkill(User *, const XLine *x) { - BotInfo *bi = findbot(Config->s_OperServ); - send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); + BotInfo *bi = findbot(Config->OperServ); + send_cmd(bi ? bi->GetUID() : Config->OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); } void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 9e7768ef3..1fb58844d 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -14,6 +14,7 @@ #include "services.h" #include "modules.h" #include "nickserv.h" +#include "oper.h" IRCDVar myIrcd[] = { {"UnrealIRCd 3.2.x", /* ircd name */ @@ -98,7 +99,7 @@ class UnrealIRCdProto : public IRCDProto void SendAkillDel(const XLine *x) { - send_cmd("", "BD - G %s %s %s", x->GetUser().c_str(), x->GetHost().c_str(), Config->s_OperServ.c_str()); + send_cmd("", "BD - G %s %s %s", x->GetUser().c_str(), x->GetHost().c_str(), Config->OperServ.c_str()); } void SendTopic(BotInfo *whosets, Channel *c) @@ -108,7 +109,7 @@ class UnrealIRCdProto : public IRCDProto void SendVhostDel(User *u) { - BotInfo *bi = findbot(Config->s_HostServ); + BotInfo *bi = findbot(Config->HostServ); u->RemoveMode(bi, UMODE_CLOAK); u->RemoveMode(bi, UMODE_VHOST); ModeManager::ProcessModes(); @@ -259,7 +260,7 @@ class UnrealIRCdProto : public IRCDProto /* UNSZLINE */ void SendSZLineDel(const XLine *x) { - send_cmd("", "BD - Z * %s %s", x->Mask.c_str(), Config->s_OperServ.c_str()); + send_cmd("", "BD - Z * %s %s", x->Mask.c_str(), Config->OperServ.c_str()); } /* SZLINE */ @@ -327,12 +328,12 @@ class UnrealIRCdProto : public IRCDProto if (!u->Account()) return; - ircdproto->SendMode(nickserv->Bot(), u, "+d %d", u->timestamp); + ircdproto->SendMode(findbot(Config->NickServ), u, "+d %d", u->timestamp); } void SendUnregisteredNick(const User *u) { - ircdproto->SendMode(nickserv->Bot(), u, "+d 1"); + ircdproto->SendMode(findbot(Config->NickServ), u, "+d 1"); } void SendChannel(Channel *c) @@ -535,7 +536,7 @@ class Unreal32IRCdMessage : public IRCdMessage { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else if (nickserv) nickserv->Validate(user); @@ -557,7 +558,7 @@ class Unreal32IRCdMessage : public IRCdMessage { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); } else if (nickserv) nickserv->Validate(user); diff --git a/src/bots.cpp b/src/bots.cpp index f48a90228..13947c0bb 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -8,6 +8,7 @@ #include "services.h" #include "modules.h" #include "commands.h" +#include "oper.h" Anope::insensitive_map<BotInfo *> BotListByNick; Anope::map<BotInfo *> BotListByUID; @@ -35,30 +36,31 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_PROTECTED)); this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_GOD)); - for (unsigned i = 0; i < Config->LogInfos.size(); ++i) - { - LogInfo *l = Config->LogInfos[i]; - - if (ircd && !ircd->join2msg && !l->Inhabit) - continue; - - for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + if (Config) + for (unsigned i = 0; i < Config->LogInfos.size(); ++i) { - const Anope::string &target = *sit; + LogInfo *l = Config->LogInfos[i]; + + if (ircd && !ircd->join2msg && !l->Inhabit) + continue; - if (target[0] == '#') + for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) { - Channel *c = findchan(target); - if (!c) - c = new Channel(target); - c->SetFlag(CH_LOGCHAN); - c->SetFlag(CH_PERSIST); - - if (!c->FindUser(this)) - this->Join(c, &Config->BotModeList); + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + if (!c->FindUser(this)) + this->Join(c, &Config->BotModeList); + } } } - } } BotInfo::~BotInfo() @@ -79,20 +81,20 @@ BotInfo::~BotInfo() ci->bi = NULL; } - for (CommandMap::const_iterator it = this->Commands.begin(), it_end = this->Commands.end(); it != it_end;) - { - Command *c = it->second; - ++it; - - if (c->module) - c->module->DelCommand(this, c); - } - BotListByNick.erase(this->nick); if (!this->uid.empty()) BotListByUID.erase(this->uid); } +void BotInfo::GenerateUID() +{ + if (!this->uid.empty()) + throw CoreException("Bot already has a uid?"); + this->uid = ts6_uid_retrieve(); + BotListByUID[this->uid] = this; + UserListByUID[this->uid] = this; +} + void BotInfo::SetNewNick(const Anope::string &newnick) { UserListByNick.erase(this->nick); @@ -154,7 +156,7 @@ void BotInfo::UnAssign(User *u, ChannelInfo *ci) void BotInfo::Join(Channel *c, ChannelStatus *status) { - if (Config->BSSmartJoin) + if (Config && ircdproto && Config->BSSmartJoin) { std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = c->GetModeList(CMODE_BAN); @@ -179,7 +181,8 @@ void BotInfo::Join(Channel *c, ChannelStatus *status) } c->JoinUser(this); - ircdproto->SendJoin(this, c, status); + if (ircdproto) + ircdproto->SendJoin(this, c, status); FOREACH_MOD(I_OnBotJoin, OnBotJoin(c, this)); } @@ -198,6 +201,91 @@ void BotInfo::Part(Channel *c, const Anope::string &reason) void BotInfo::OnMessage(User *u, const Anope::string &message) { - mod_run_cmd(this, u, NULL, message); + std::vector<Anope::string> params = BuildStringVector(message); + + command_map::iterator it = this->commands.end(); + unsigned count = 0; + for (unsigned max = params.size(); it == this->commands.end() && max > 0; --max) + { + Anope::string full_command; + for (unsigned i = 0; i < max; ++i) + full_command += " " + params[i]; + full_command.erase(full_command.begin()); + + ++count; + it = this->commands.find(full_command); + } + + if (it == this->commands.end()) + { + u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str()); + return; + } + + service_reference<Command> c(it->second); + if (!c) + { + u->SendMessage(this, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), message.c_str(), Config->UseStrictPrivMsgString.c_str(), this->nick.c_str()); + Log(this) << "Command " << it->first << " exists on me, but its service " << it->second << " was not found!"; + return; + } + + // Command requires registered users only + if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) + { + u->SendMessage(this, NICK_IDENTIFY_REQUIRED); + Log(LOG_COMMAND, "denied", this) << "Access denied for unregistered user " << u->GetMask() << " with command " << c->name; + return; + } + + for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i) + params.erase(params.begin()); + + while (c->MaxParams > 0 && params.size() > c->MaxParams) + { + params[c->MaxParams - 1] += " " + params[c->MaxParams]; + params.erase(params.begin() + c->MaxParams); + } + + CommandSource source; + source.u = u; + source.c = NULL; + source.owner = this; + source.service = this; + source.command = it->first; + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params)); + if (MOD_RESULT == EVENT_STOP) + { + source.DoReply(); + return; + } + + + if (params.size() < c->MinParams) + { + c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : ""); + source.DoReply(); + return; + } + + // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED + if (!c->permission.empty() && !u->HasCommand(c->permission)) + { + u->SendMessage(this, ACCESS_DENIED); + Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << c->name; + source.DoReply(); + return; + } + + dynamic_reference<User> user_reference(u); + c->Execute(source, params); + if (user_reference) + { + FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params)); + if (user_reference) + source.DoReply(); + } } diff --git a/src/channels.cpp b/src/channels.cpp index d64a8b378..26ae18308 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -122,27 +122,6 @@ void Channel::JoinUser(User *user) ircdproto->SendChannel(this); this->Reset(); } - - if (!Config->s_BotServ.empty() && this->ci && this->ci->bi) - { - /** - * We let the bot join even if it was an ignored user, as if we don't, - * and the ignored user doesnt just leave, the bot will never - * make it into the channel, leaving the channel botless even for - * legit users - Rob - **/ - if (this->users.size() >= Config->BSMinUsers && !this->FindUser(this->ci->bi)) - this->ci->bi->Join(this, &Config->BotModeList); - /* Only display the greet if the main uplink we're connected - * to has synced, or we'll get greet-floods when the net - * recovers from a netsplit. -GD - */ - if (this->FindUser(this->ci->bi) && this->ci->botflags.HasFlag(BS_GREET) && user->Account() && !user->Account()->greet.empty() && check_access(user, this->ci, CA_GREET) && user->server->IsSynced()) - { - ircdproto->SendPrivmsg(this->ci->bi, this->name, "[%s] %s", user->Account()->display.c_str(), user->Account()->greet.c_str()); - this->ci->bi->lastmsg = Anope::CurTime; - } - } } /** Remove a user internally from the channel @@ -154,6 +133,7 @@ void Channel::DeleteUser(User *user) update_cs_lastseen(user, this->ci); Log(user, this, "leaves"); + FOREACH_MOD(I_OnLeaveChannel, OnLeaveChannel(user, this)); CUserList::iterator cit, cit_end = this->users.end(); for (cit = this->users.begin(); (*cit)->user != user && cit != cit_end; ++cit); @@ -170,14 +150,13 @@ void Channel::DeleteUser(User *user) UChannelList::iterator uit, uit_end = user->chans.end(); for (uit = user->chans.begin(); (*uit)->chan != this && uit != uit_end; ++uit); if (uit == uit_end) - { Log(LOG_DEBUG) << "Channel::DeleteUser() tried to delete nonexistant channel " << this->name << " from " << user->nick << "'s channel list"; - return; + else + { + delete *uit; + user->chans.erase(uit); } - delete *uit; - user->chans.erase(uit); - /* Channel is persistant, it shouldn't be deleted and the service bot should stay */ if (this->HasFlag(CH_PERSIST) || (this->ci && this->ci->HasFlag(CI_PERSIST))) return; @@ -192,12 +171,7 @@ void Channel::DeleteUser(User *user) if (this->HasFlag(CH_INHABIT)) return; - /* check for BSMinUsers and part the BotServ bot from the channel - * Use <= because the bot is included in this->users.size() - */ - if (!Config->s_BotServ.empty() && this->ci && this->ci->bi && this->users.size() <= Config->BSMinUsers && this->FindUser(this->ci->bi)) - this->ci->bi->Part(this->ci->c); - else if (this->users.empty()) + if (this->users.empty()) delete this; } @@ -298,10 +272,7 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool return; } - BotInfo *bi = NULL; - if (!Config->s_BotServ.empty()) - bi = findbot(param); - User *u = bi ? bi : finduser(param); + User *u = finduser(param); if (!u) { @@ -411,9 +382,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo return; } - BotInfo *bi = NULL; - if (!Config->s_BotServ.empty()) - bi = findbot(param); + BotInfo *bi = findbot(param); User *u = bi ? bi : finduser(param); if (!u) @@ -467,16 +436,7 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo this->UnsetFlag(CH_PERSIST); if (ci) - { ci->UnsetFlag(CI_PERSIST); - if (!Config->s_BotServ.empty() && ci->bi && this->FindUser(ci->bi) && Config->BSMinUsers && this->users.size() <= Config->BSMinUsers) - { - bool empty = this->users.size() == 1; - this->ci->bi->Part(this); - if (empty) - return; - } - } if (this->users.empty()) { @@ -780,7 +740,7 @@ void Channel::KickInternal(const Anope::string &source, const Anope::string &nic { User *sender = finduser(source); BotInfo *bi = NULL; - if (!Config->s_BotServ.empty() && this->ci) + if (this->ci && this->ci->bi) bi = findbot(nick); User *target = bi ? bi : finduser(nick); if (!target) diff --git a/src/chanserv.cpp b/src/chanserv.cpp index 42d637c38..6a39340ae 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -13,7 +13,6 @@ #include "services.h" #include "modules.h" -#include "chanserv.h" registered_channel_map RegisteredChannelList; @@ -124,8 +123,7 @@ void check_modes(Channel *c) /* Check for mode bouncing */ if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) { - ircdproto->SendGlobops(NULL, "Warning: unable to set modes on channel %s. Are your servers' U:lines configured correctly?", c->name.c_str()); - Log() << "Bouncy modes on channel " << c->name; + Log() << "Warning: unable to set modes on channel " << c->name << ". Are your servers' U:lines configured correctly?"; c->bouncy_modes = 1; return; } @@ -367,11 +365,12 @@ Anope::string get_xop_level(int level) ChanServTimer::ChanServTimer(Channel *chan) : Timer(Config->CSInhabit), c(chan) { - if (!chanserv || !c) + BotInfo *bi = findbot(Config->ChanServ); + if (!bi || !c) return; c->SetFlag(CH_INHABIT); if (!c->ci || !c->ci->bi) - chanserv->Bot()->Join(c); + bi->Join(c); else if (!c->FindUser(c->ci->bi)) c->ci->bi->Join(c); } @@ -385,8 +384,9 @@ void ChanServTimer::Tick(time_t) if (!c->ci || !c->ci->bi) { - if (chanserv) - chanserv->Bot()->Part(c); + BotInfo *bi = findbot(Config->ChanServ); + if (bi) + bi->Part(c); } else if (c->users.size() == 1 || c->users.size() < Config->BSMinUsers) c->ci->bi->Part(c); diff --git a/src/command.cpp b/src/command.cpp index f13be6ee5..8803edf05 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -7,6 +7,7 @@ #include "services.h" #include "modules.h" +#include "commands.h" void CommandSource::Reply(const char *message, ...) { @@ -42,29 +43,25 @@ void CommandSource::DoReply() const Anope::string &message = *it; // Send to the user if the reply is more than one line - if (!this->fantasy || !this->ci || this->reply.size() > 1) + if (!this->c || !this->c->ci || this->reply.size() > 1) u->SendMessage(this->service, message); - else if (this->ci->botflags.HasFlag(BS_MSG_PRIVMSG)) - ircdproto->SendPrivmsg(this->service, this->ci->name, message.c_str()); - else if (this->ci->botflags.HasFlag(BS_MSG_NOTICE)) - ircdproto->SendNotice(this->service, this->ci->name, message.c_str()); - else if (this->ci->botflags.HasFlag(BS_MSG_NOTICEOPS)) - ircdproto->SendNoticeChanops(this->service, this->ci->c, message.c_str()); + else if (this->c->ci->botflags.HasFlag(BS_MSG_PRIVMSG)) + ircdproto->SendPrivmsg(this->service, this->c->name, message.c_str()); + else if (this->c->ci->botflags.HasFlag(BS_MSG_NOTICE)) + ircdproto->SendNotice(this->service, this->c->name, message.c_str()); + else if (this->c->ci->botflags.HasFlag(BS_MSG_NOTICEOPS)) + ircdproto->SendNoticeChanops(this->service, this->c, message.c_str()); else u->SendMessage(this->service, message); } } -Command::Command(const Anope::string &sname, size_t min_params, size_t max_params, const Anope::string &spermission) : Flags<CommandFlag>(CommandFlagStrings), MaxParams(max_params), MinParams(min_params), name(sname), permission(spermission) +Command::Command(Module *owner, const Anope::string &sname, size_t min_params, size_t max_params, const Anope::string &spermission) : Service(owner, sname), Flags<CommandFlag>(CommandFlagStrings), MaxParams(max_params), MinParams(min_params), permission(spermission), module(owner) { - this->module = NULL; - this->service = NULL; } Command::~Command() { - if (this->module) - this->module->DelCommand(this->service, this); } void Command::SetDesc(const Anope::string &d) @@ -72,37 +69,52 @@ void Command::SetDesc(const Anope::string &d) this->desc = d; } -const Anope::string &Command::GetDesc() const +void Command::ClearSyntax() { - return this->desc; + this->syntax.clear(); } -void Command::OnServHelp(CommandSource &source) +void Command::SetSyntax(const Anope::string &s) { - source.Reply(" %-14s %s", this->name.c_str(), translate(source.u, (this->GetDesc().c_str()))); + this->syntax.push_back(s); } -bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; } +void Command::SendSyntax(CommandSource &source) +{ + if (!this->syntax.empty()) + { + source.Reply(_("Syntax: \002%s %s\002"), source.command.c_str(), this->syntax[0].c_str()); + for (unsigned i = 1, j = this->syntax.size(); i < j; ++i) + source.Reply(" \002%s %s\002", source.command.c_str(), this->syntax[i].c_str()); + } +} -void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { } +void Command::SendSyntax(CommandSource &source, const Anope::string &syntax) +{ + source.Reply(_("Syntax: \002%s %s\002"), source.command.c_str(), syntax.c_str()); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); +} -void Command::SetPermission(const Anope::string &reststr) +const Anope::string &Command::GetDesc() const { - this->permission = reststr; + return this->desc; } -bool Command::AddSubcommand(Module *creator, Command *c) +void Command::OnServHelp(CommandSource &source) { - return false; + source.Reply(" %-14s %s", source.command.c_str(), translate(source.u, (this->GetDesc().c_str()))); } -bool Command::DelSubcommand(Command *c) +bool Command::OnHelp(CommandSource &source, const Anope::string &subcommand) { return false; } + +void Command::OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { - return false; + this->SendSyntax(source); + source.Reply(MORE_INFO, Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), source.command.c_str()); } -Command *Command::FindSubcommand(const Anope::string &subcommand) +void Command::SetPermission(const Anope::string &reststr) { - return NULL; + this->permission = reststr; } diff --git a/src/commands.cpp b/src/commands.cpp deleted file mode 100644 index fea6e4376..000000000 --- a/src/commands.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* Routines for looking up commands in a *Serv command list. - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "services.h" -#include "modules.h" -#include "hashcomp.h" - -Command *FindCommand(BotInfo *bi, const Anope::string &name) -{ - if (!bi || bi->Commands.empty() || name.empty()) - return NULL; - - CommandMap::iterator it = bi->Commands.find(name); - - if (it != bi->Commands.end()) - return it->second; - - return NULL; -} - -void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, const Anope::string &fullmessage) -{ - if (!bi || !u) - return; - - spacesepstream sep(fullmessage); - Anope::string command, message; - - if (!sep.GetToken(command)) - return; - message = sep.GetRemaining(); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreCommandRun, OnPreCommandRun(u, bi, command, message, ci)); - if (MOD_RESULT == EVENT_STOP) - return; - - Command *c = FindCommand(bi, command); - - mod_run_cmd(bi, u, ci, c, command, message); -} - -void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope::string &command, const Anope::string &message) -{ - if (!bi || !u) - return; - - if (!c) - { - u->SendMessage(bi, _("Unknown command \002%s\002. \"%s%s HELP\" for help."), command.c_str(), Config->UseStrictPrivMsgString.c_str(), bi->nick.c_str()); - return; - } - - // Command requires registered users only - if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) - { - u->SendMessage(bi, NICK_IDENTIFY_REQUIRED, Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - Log(LOG_COMMAND, "denied", bi) << "Access denied for unregistered user " << u->GetMask() << " with command " << command; - return; - } - - std::vector<Anope::string> params; - Anope::string curparam, endparam; - spacesepstream sep(message); - while (sep.GetToken(curparam)) - { - // - 1 because params[0] corresponds with a maxparam of 1. - if (params.size() >= c->MaxParams - 1) - endparam += curparam + " "; - else - params.push_back(curparam); - } - - if (!endparam.empty()) - { - // Remove trailing space - endparam.erase(endparam.length() - 1); - - // Add it - params.push_back(endparam); - } - - bool fantasy = ci != NULL; - if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && ircdproto->IsChannelValid(params[0])) - ci = cs_findchan(params[0]); - - CommandSource source; - source.u = u; - source.ci = ci; - source.owner = bi; - source.service = fantasy && ci ? ci->bi : c->service; - source.fantasy = fantasy; - - if (params.size() < c->MinParams) - { - c->OnSyntaxError(source, !params.empty() ? params[params.size() - 1] : ""); - source.DoReply(); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreCommand, OnPreCommand(source, c, params)); - if (MOD_RESULT == EVENT_STOP) - { - source.DoReply(); - return; - } - - // If the command requires a permission, and they aren't registered or don't have the required perm, DENIED - if (!c->permission.empty() && !u->HasCommand(c->permission)) - { - u->SendMessage(bi, ACCESS_DENIED); - Log(LOG_COMMAND, "denied", bi) << "Access denied for user " << u->GetMask() << " with command " << command; - source.DoReply(); - return; - } - - dynamic_reference<User> user_reference(u); - CommandReturn ret = c->Execute(source, params); - if (ret != MOD_STOP && user_reference) - { - FOREACH_MOD(I_OnPostCommand, OnPostCommand(source, c, params)); - source.DoReply(); - } -} - -/** - * Prints the help message for a given command. - * @param bi Client the command is on - * @param u User - * @param ci Optional channel the command was executed one (fantasy) - * @param cmd Command - */ -void mod_help_cmd(BotInfo *bi, User *u, ChannelInfo *ci, const Anope::string &cmd) -{ - if (!bi || !u || cmd.empty()) - return; - - spacesepstream tokens(cmd); - Anope::string token; - tokens.GetToken(token); - - Command *c = FindCommand(bi, token); - Anope::string subcommand = tokens.StreamEnd() ? "" : tokens.GetRemaining(); - - CommandSource source; - source.u = u; - source.ci = ci; - source.owner = bi; - source.service = ci ? ci->bi : bi; - source.fantasy = ci != NULL; - - if (!c || (Config->HidePrivilegedCommands && !c->permission.empty() && !u->HasCommand(c->permission)) || !c->OnHelp(source, subcommand)) - source.Reply( _("No help available for \002%s\002."), cmd.c_str()); - else - { - source.Reply(" "); - - /* Inform the user what permission is required to use the command */ - if (!c->permission.empty()) - source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), c->permission.c_str()); - - /* User isn't identified and needs to be to use this command */ - if (!c->HasFlag(CFLAG_ALLOW_UNREGISTERED) && !u->IsIdentified()) - source.Reply( _("You need to be identified to use this command.")); - /* User doesn't have the proper permission to use this command */ - else if (!c->permission.empty() && !u->HasCommand(c->permission)) - source.Reply(_("You cannot use this command.")); - /* User can use this command */ - else - source.Reply(_("You can use this command.")); - } - - source.DoReply(); -} diff --git a/src/config.cpp b/src/config.cpp index 7d3efcb91..0d9341424 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -11,18 +11,17 @@ #include "services.h" #include "config.h" +#include "module.h" /*************************************************************************/ ConfigurationFile services_conf("services.conf", false); // Services configuration file name ServerConfig *Config = NULL; -static Anope::string Modules; static Anope::string UlineServers; static Anope::string OSNotifications; static Anope::string BSDefaults; static Anope::string CSDefaults; -static Anope::string temp_nsuserhost; static Anope::string NSDefaults; /*************************************************************************/ @@ -31,21 +30,6 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C { this->Read(); - if (!temp_nsuserhost.empty()) - { - size_t at = temp_nsuserhost.find('@'); - if (at == Anope::string::npos) - { - this->NSEnforcerUser = temp_nsuserhost; - this->NSEnforcerHost = this->ServiceHost; - } - else - { - this->NSEnforcerUser = temp_nsuserhost.substr(0, at); - this->NSEnforcerHost = temp_nsuserhost.substr(at + 1); - } - } - if (NSDefaults.empty()) { this->NSDefFlags.SetFlag(NI_SECURE); @@ -155,8 +139,6 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->BSDefFlags.SetFlag(BS_GREET); else if (option.equals_ci("fantasy")) this->BSDefFlags.SetFlag(BS_FANTASY); - else if (option.equals_ci("symbiosis")) - this->BSDefFlags.SetFlag(BS_SYMBIOSIS); } } @@ -196,23 +178,12 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->Ulines.push_back(uline); } - /* Modules Autoload building... :P */ - this->ModulesAutoLoad = BuildStringList(Modules); - if (this->LimitSessions) { if (this->MaxSessionKill && !this->SessionAutoKillExpiry) this->SessionAutoKillExpiry = 1800; /* 30 minutes */ } - if (!this->s_BotServ.empty()) - { - if (this->BSFantasyCharacter.empty()) - this->BSFantasyCharacter = "!"; - if (this->BSFantasyCharacter.length() > 1) - Log() << "*** " << this->BSFantasyCharacter << " is more than 1 character long. Only the first character will be used. The others will be ignored."; - } - /* Check the user keys */ if (this->UserKey1 == this->UserKey2 || this->UserKey1 == this->UserKey3 || this->UserKey3 == this->UserKey2) Log() << "Every UserKey must be different. It's for YOUR safety! Remember that!"; @@ -421,7 +392,7 @@ bool ValidateBantype(ServerConfig *, const Anope::string &, const Anope::string bool ValidateChanServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_ChanServ.empty()) + if (!config->ChanServ.empty()) { if ((value.equals_ci("decription") || value.equals_ci("autokickreason")) && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when ChanServ is enabled!"); @@ -435,7 +406,7 @@ bool ValidateChanServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateMemoServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_MemoServ.empty()) + if (!config->MemoServ.empty()) { if (value.equals_ci("description")) { @@ -448,7 +419,7 @@ bool ValidateMemoServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateBotServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_BotServ.empty()) + if (!config->BotServ.empty()) { if (value.equals_ci("description")) { @@ -471,7 +442,7 @@ bool ValidateBotServ(ServerConfig *config, const Anope::string &tag, const Anope bool ValidateHostServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_HostServ.empty()) + if (!config->HostServ.empty()) { if (value.equals_ci("description") && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when HostServ is enabled!"); @@ -494,7 +465,7 @@ bool ValidateLimitSessions(ServerConfig *config, const Anope::string &tag, const bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_OperServ.empty()) + if (!config->OperServ.empty()) { if (value.equals_ci("description") && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when OperServ is enabled!"); @@ -508,7 +479,7 @@ bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_Global.empty()) + if (!config->Global.empty()) { if (value.equals_ci("description") && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when Global is enabled!"); @@ -571,7 +542,7 @@ bool InitUplinks(ServerConfig *config, const Anope::string &) return true; } -bool DoUplink(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +static bool DoUplink(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) { // Validation variables Anope::string host = values[0].GetValue(), password = values[3].GetValue(); @@ -592,7 +563,7 @@ bool DoUplink(ServerConfig *config, const Anope::string &, const Anope::string * return true; } -bool DoneUplinks(ServerConfig *config, const Anope::string &) +static bool DoneUplinks(ServerConfig *config, const Anope::string &) { if (config->Uplinks.empty()) throw ConfigException("You must define at least one uplink block!"); @@ -746,27 +717,31 @@ static bool DoneInclude(ServerConfig *config, const Anope::string &) bool InitModules(ServerConfig *, const Anope::string &) { - Modules.clear(); return true; } -bool DoModule(ServerConfig *conf, const Anope::string &, const Anope::string *, ValueList &values, int *) +static bool DoModule(ServerConfig *conf, const Anope::string &, const Anope::string *, ValueList &values, int *) { // First we validate that there was a name in the module block Anope::string module = values[0].GetValue(); ValueItem vi(module); if (!ValidateNotEmpty(conf, "module", "name", vi)) throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); - // If the string isn't empty, add a space before we add the module name - if (!Modules.empty()) - Modules += " "; - // Add the module name to the string - Modules += values[0].GetValue(); + conf->ModulesAutoLoad.push_back(module); return true; } -bool DoneModules(ServerConfig *, const Anope::string &) +static bool DoneModules(ServerConfig *config, const Anope::string &) { + if (Config) + { + for (std::list<Anope::string>::iterator it = Config->ModulesAutoLoad.begin(); it != Config->ModulesAutoLoad.end(); ++it) + if (std::find(config->ModulesAutoLoad.begin(), config->ModulesAutoLoad.end(), *it) == config->ModulesAutoLoad.end()) + ModuleManager::UnloadModule(ModuleManager::FindModule(*it), NULL); + for (std::list<Anope::string>::iterator it = config->ModulesAutoLoad.begin(); it != config->ModulesAutoLoad.end(); ++it) + if (std::find(Config->ModulesAutoLoad.begin(), Config->ModulesAutoLoad.end(), *it) == Config->ModulesAutoLoad.end()) + ModuleManager::LoadModule(*it, NULL); + } return true; } @@ -809,7 +784,7 @@ bool InitLogs(ServerConfig *config, const Anope::string &) return true; } -bool DoLogs(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +static bool DoLogs(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) { //{"target", "source", "logage", "inhabit", "admin", "override", "commands", "servers", "channels", "users", "other", "rawio", "debug"}, Anope::string targets = values[0].GetValue(); @@ -846,7 +821,7 @@ bool DoLogs(ServerConfig *config, const Anope::string &, const Anope::string *, return true; } -bool DoneLogs(ServerConfig *config, const Anope::string &) +static bool DoneLogs(ServerConfig *config, const Anope::string &) { Log() << "Loaded " << config->LogInfos.size() << " log blocks"; @@ -873,7 +848,7 @@ bool DoneLogs(ServerConfig *config, const Anope::string &) { BotInfo *bi = it->second; if (!c->FindUser(bi)) - bi->Join(c, &config->BotModeList); + bi->Join(c, NULL); } } } @@ -882,6 +857,106 @@ bool DoneLogs(ServerConfig *config, const Anope::string &) return true; } +/*************************************************************************/ + +static bool InitCommands(ServerConfig *config, const Anope::string &) +{ + for (botinfo_map::iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + it->second->commands.clear(); + return true; +} + +static bool DoCommands(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +{ + Anope::string service = values[0].GetValue(); + Anope::string name = values[1].GetValue(); + Anope::string command = values[2].GetValue(); + + ValueItem vi(service); + if (!ValidateNotEmpty(config, "command", "service", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + vi = ValueItem(name); + if (!ValidateNotEmpty(config, "command", "name", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + vi = ValueItem(command); + if (!ValidateNotEmpty(config, "command", "command", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + BotInfo *bi = findbot(service); + if (bi == NULL) + throw ConfigException("Command " + name + " exists for nonexistant service " + service); + + if (bi->commands.count(name)) + throw ConfigException("Command name " + name + " already exists on " + bi->nick); + + bi->commands[name] = command; + return true; +} + +static bool DoneCommands(ServerConfig *config, const Anope::string &) +{ + return true; +} + +/*************************************************************************/ + +static std::set<Anope::string> services; +static bool InitServices(ServerConfig *config, const Anope::string &) +{ + services.clear(); + return true; +} + +static bool DoServices(ServerConfig *config, const Anope::string &, const Anope::string *, ValueList &values, int *) +{ + Anope::string nick = values[0].GetValue(); + Anope::string user = values[1].GetValue(); + Anope::string host = values[2].GetValue(); + Anope::string gecos = values[3].GetValue(); + + ValueItem vi(nick); + if (!ValidateNotEmpty(config, "service", "nick", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + vi = ValueItem(user); + if (!ValidateNotEmpty(config, "service", "user", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + vi = ValueItem(host); + if (!ValidateNotEmpty(config, "service", "host", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + vi = ValueItem(gecos); + if (!ValidateNotEmpty(config, "service", "gecos", vi)) + throw ConfigException("One or more values in your configuration file failed to validate. Please see your log for more information."); + + services.insert(nick); + BotInfo *bi = findbot(nick); + if (bi != NULL) + return true; + bi = new BotInfo(nick, user, host, gecos); + bi->SetFlag(BI_CONF); + return true; +} + +static bool DoneServices(ServerConfig *config, const Anope::string &) +{ + for (botinfo_map::iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end;) + { + BotInfo *bi = it->second; + ++it; + + if (bi->HasFlag(BI_CONF) && services.count(bi->nick) == 0) + delete bi; + } + services.clear(); + return true; +} + +/*************************************************************************/ + ConfigurationFile::ConfigurationFile(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL) { } @@ -1000,8 +1075,6 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"serverinfo", "description", "", new ValueContainerString(&conf->ServerDesc), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"serverinfo", "localhost", "", new ValueContainerString(&conf->LocalHost), DT_HOSTNAME | DT_NORELOAD, NoValidation}, {"serverinfo", "id", "", new ValueContainerString(&conf->Numeric), DT_NOSPACES | DT_NORELOAD, NoValidation}, - {"serverinfo", "ident", "", new ValueContainerString(&conf->ServiceUser), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, - {"serverinfo", "hostname", "", new ValueContainerString(&conf->ServiceHost), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"serverinfo", "pid", "services.pid", new ValueContainerString(&conf->PIDFilename), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"serverinfo", "motd", "services.motd", new ValueContainerString(&conf->MOTDFilename), DT_STRING, ValidateNotEmpty}, {"networkinfo", "networkname", "", new ValueContainerString(&conf->NetworkName), DT_STRING, ValidateNotEmpty}, @@ -1035,10 +1108,8 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"options", "botmodes", "", new ValueContainerString(&conf->BotModes), DT_STRING, NoValidation}, {"options", "retrywait", "60", new ValueContainerInt(&conf->RetryWait), DT_INTEGER, ValidateNotZero}, {"options", "hideprivilegedcommands", "no", new ValueContainerBool(&conf->HidePrivilegedCommands), DT_BOOLEAN, NoValidation}, - {"nickserv", "nick", "NickServ", new ValueContainerString(&conf->s_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, - {"nickserv", "description", "Nickname Registration Service", new ValueContainerString(&conf->desc_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, + {"nickserv", "name", "NickServ", new ValueContainerString(&conf->NickServ), DT_STRING, NoValidation}, {"nickserv", "emailregistration", "no", new ValueContainerBool(&conf->NSEmailReg), DT_BOOLEAN, NoValidation}, - {"nickserv", "modules", "", new ValueContainerString(&conf->NickCoreModules), DT_STRING, NoValidation}, {"nickserv", "forceemail", "no", new ValueContainerBool(&conf->NSForceEmail), DT_BOOLEAN, ValidateEmailReg}, {"nickserv", "confirmemailchanges", "no", new ValueContainerBool(&conf->NSConfirmEmailChanges), DT_BOOLEAN, NoValidation}, {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation}, @@ -1051,7 +1122,8 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"nickserv", "unconfirmedexpire", "0", new ValueContainerTime(&conf->NSUnconfirmedExpire), DT_TIME, ValidateEmailReg}, {"nickserv", "maxaliases", "0", new ValueContainerUInt(&conf->NSMaxAliases), DT_UINTEGER, NoValidation}, {"nickserv", "accessmax", "0", new ValueContainerUInt(&conf->NSAccessMax), DT_UINTEGER, ValidateNotZero}, - {"nickserv", "enforceruser", "", new ValueContainerString(&temp_nsuserhost), DT_STRING, ValidateNotEmpty}, + {"nickserv", "enforceruser", "", new ValueContainerString(&conf->NSEnforcerUser), DT_STRING, ValidateNotEmpty}, + {"nickserv", "enforcerhost", "", new ValueContainerString(&conf->NSEnforcerHost), DT_STRING, ValidateNotEmpty}, {"nickserv", "releasetimeout", "0", new ValueContainerTime(&conf->NSReleaseTimeout), DT_TIME, ValidateNotZero}, {"nickserv", "allowkillimmed", "no", new ValueContainerBool(&conf->NSAllowKillImmed), DT_BOOLEAN | DT_NORELOAD, NoValidation}, {"nickserv", "nogroupchange", "no", new ValueContainerBool(&conf->NSNoGroupChange), DT_BOOLEAN, NoValidation}, @@ -1071,9 +1143,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"mail", "dontquoteaddresses", "no", new ValueContainerBool(&conf->DontQuoteAddresses), DT_BOOLEAN, NoValidation}, {"dns", "nameserver", "127.0.0.1", new ValueContainerString(&conf->NameServer), DT_STRING, NoValidation}, {"dns", "timeout", "5", new ValueContainerTime(&conf->DNSTimeout), DT_TIME, NoValidation}, - {"chanserv", "nick", "", new ValueContainerString(&conf->s_ChanServ), DT_STRING | DT_NORELOAD, NoValidation}, - {"chanserv", "description", "Channel Registration Service", new ValueContainerString(&conf->desc_ChanServ), DT_STRING | DT_NORELOAD, ValidateChanServ}, - {"chanserv", "modules", "", new ValueContainerString(&conf->ChanCoreModules), DT_STRING, ValidateChanServ}, + {"chanserv", "name", "ChanServ", new ValueContainerString(&conf->ChanServ), DT_STRING, NoValidation}, {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, ValidateChanServ}, {"chanserv", "maxregistered", "0", new ValueContainerUInt(&conf->CSMaxReg), DT_UINTEGER, ValidateChanServ}, {"chanserv", "expire", "14d", new ValueContainerTime(&conf->CSExpire), DT_TIME, ValidateChanServ}, @@ -1087,16 +1157,13 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"chanserv", "listopersonly", "no", new ValueContainerBool(&conf->CSListOpersOnly), DT_BOOLEAN, ValidateChanServ}, {"chanserv", "listmax", "0", new ValueContainerUInt(&conf->CSListMax), DT_UINTEGER, ValidateChanServ}, {"chanserv", "opersonly", "no", new ValueContainerBool(&conf->CSOpersOnly), DT_BOOLEAN, ValidateChanServ}, - {"memoserv", "nick", "", new ValueContainerString(&conf->s_MemoServ), DT_STRING | DT_NORELOAD, NoValidation}, - {"memoserv", "description", "Memo Service", new ValueContainerString(&conf->desc_MemoServ), DT_STRING | DT_NORELOAD, ValidateMemoServ}, - {"memoserv", "modules", "", new ValueContainerString(&conf->MemoCoreModules), DT_STRING, NoValidation}, + {"memoserv", "name", "MemoServ", new ValueContainerString(&conf->MemoServ), DT_STRING, NoValidation}, {"memoserv", "maxmemos", "0", new ValueContainerUInt(&conf->MSMaxMemos), DT_UINTEGER, NoValidation}, {"memoserv", "senddelay", "0", new ValueContainerTime(&conf->MSSendDelay), DT_TIME, NoValidation}, {"memoserv", "notifyall", "no", new ValueContainerBool(&conf->MSNotifyAll), DT_BOOLEAN, NoValidation}, {"memoserv", "memoreceipt", "0", new ValueContainerUInt(&conf->MSMemoReceipt), DT_UINTEGER, NoValidation}, - {"botserv", "nick", "", new ValueContainerString(&conf->s_BotServ), DT_STRING | DT_NORELOAD, NoValidation}, - {"botserv", "description", "Bot Service", new ValueContainerString(&conf->desc_BotServ), DT_STRING | DT_NORELOAD, ValidateBotServ}, - {"botserv", "modules", "", new ValueContainerString(&conf->BotCoreModules), DT_STRING, NoValidation}, + {"hostserv", "name", "HostServ", new ValueContainerString(&conf->HostServ), DT_STRING, NoValidation}, + {"botserv", "name", "BotServ", new ValueContainerString(&conf->BotServ), DT_STRING, NoValidation}, {"botserv", "defaults", "", new ValueContainerString(&BSDefaults), DT_STRING, NoValidation}, {"botserv", "minusers", "0", new ValueContainerUInt(&conf->BSMinUsers), DT_UINTEGER, ValidateBotServ}, {"botserv", "badwordsmax", "0", new ValueContainerUInt(&conf->BSBadWordsMax), DT_UINTEGER, ValidateBotServ}, @@ -1105,12 +1172,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"botserv", "gentlebadwordreason", "no", new ValueContainerBool(&conf->BSGentleBWReason), DT_BOOLEAN, NoValidation}, {"botserv", "casesensitive", "no", new ValueContainerBool(&conf->BSCaseSensitive), DT_BOOLEAN, NoValidation}, {"botserv", "fantasycharacter", "!", new ValueContainerString(&conf->BSFantasyCharacter), DT_STRING, NoValidation}, - {"hostserv", "nick", "", new ValueContainerString(&conf->s_HostServ), DT_STRING | DT_NORELOAD, NoValidation}, - {"hostserv", "description", "vHost Service", new ValueContainerString(&conf->desc_HostServ), DT_STRING | DT_NORELOAD, ValidateHostServ}, - {"hostserv", "modules", "", new ValueContainerString(&conf->HostCoreModules), DT_STRING, NoValidation}, - {"operserv", "nick", "", new ValueContainerString(&conf->s_OperServ), DT_STRING | DT_NORELOAD, NoValidation}, - {"operserv", "description", "Operator Service", new ValueContainerString(&conf->desc_OperServ), DT_STRING | DT_NORELOAD, ValidateOperServ}, - {"operserv", "modules", "", new ValueContainerString(&conf->OperCoreModules), DT_STRING, NoValidation}, + {"operserv", "name", "OperServ", new ValueContainerString(&conf->OperServ), DT_STRING, NoValidation}, {"operserv", "superadmin", "no", new ValueContainerBool(&conf->SuperAdmin), DT_BOOLEAN, NoValidation}, {"operserv", "autokillexpiry", "0", new ValueContainerTime(&conf->AutokillExpiry), DT_TIME, ValidateOperServ}, {"operserv", "chankillexpiry", "0", new ValueContainerTime(&conf->ChankillExpiry), DT_TIME, ValidateOperServ}, @@ -1131,9 +1193,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"operserv", "sessionautokillexpiry", "0", new ValueContainerTime(&conf->SessionAutoKillExpiry), DT_TIME, NoValidation}, {"operserv", "addakiller", "no", new ValueContainerBool(&conf->AddAkiller), DT_BOOLEAN, NoValidation}, {"operserv", "opersonly", "no", new ValueContainerBool(&conf->OSOpersOnly), DT_BOOLEAN, NoValidation}, - {"global", "nick", "", new ValueContainerString(&conf->s_Global), DT_STRING | DT_NORELOAD, NoValidation}, - {"global", "description", "Global Noticer", new ValueContainerString(&conf->desc_Global), DT_STRING | DT_NORELOAD, ValidateGlobal}, - {"global", "modules", "", new ValueContainerString(&conf->GlobalCoreModules), DT_STRING, NoValidation}, + {"global", "name", "Global", new ValueContainerString(&conf->Global), DT_STRING, NoValidation}, {"global", "globaloncycle", "no", new ValueContainerBool(&conf->GlobalOnCycle), DT_BOOLEAN, NoValidation}, {"global", "globaloncycledown", "", new ValueContainerString(&conf->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, {"global", "globaloncycleup", "", new ValueContainerString(&conf->GlobalOnCycleUP), DT_STRING, ValidateGlobalOnCycle}, @@ -1161,11 +1221,6 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"", ""}, {DT_STRING}, InitModules, DoModule, DoneModules}, - {"log", - {"target", "source", "logage", "inhabitlogchannel", "admin", "override", "commands", "servers", "channels", "users", "other", "rawio", "debug", ""}, - {"", "", "7", "yes", "", "", "", "", "", "", "no", "no", ""}, - {DT_STRING, DT_STRING, DT_INTEGER, DT_BOOLEAN, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_BOOLEAN, DT_BOOLEAN}, - InitLogs, DoLogs, DoneLogs}, {"opertype", {"name", "inherits", "commands", "privs", ""}, {"", "", "", "", ""}, @@ -1176,6 +1231,21 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"", "", "", "", ""}, {DT_STRING, DT_STRING, DT_STRING, DT_STRING}, InitOpers, DoOper, DoneOpers}, + {"service", + {"nick", "user", "host", "gecos", ""}, + {"", "", "", "", ""}, + {DT_STRING, DT_STRING, DT_STRING, DT_STRING}, + InitServices, DoServices, DoneServices}, + {"log", + {"target", "source", "logage", "inhabitlogchannel", "admin", "override", "commands", "servers", "channels", "users", "other", "rawio", "debug", ""}, + {"", "", "7", "yes", "", "", "", "", "", "", "no", "no", ""}, + {DT_STRING, DT_STRING, DT_INTEGER, DT_BOOLEAN, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_STRING, DT_BOOLEAN, DT_BOOLEAN}, + InitLogs, DoLogs, DoneLogs}, + {"command", + {"service", "name", "command", ""}, + {"", "", "", ""}, + {DT_STRING, DT_STRING, DT_STRING}, + InitCommands, DoCommands, DoneCommands}, {"", {""}, {""}, @@ -1424,14 +1494,11 @@ void ServerConfig::LoadConf(ConfigurationFile &file) if (in_quote) { if (ch == '"') - { in_quote = in_word = false; - continue; - } - wordbuffer += ch; - continue; + else + wordbuffer += ch; } - if (in_ml_comment) + else if (in_ml_comment) { if (ch == '*' && c + 1 < len && line[c + 1] == '/') { @@ -1440,8 +1507,8 @@ void ServerConfig::LoadConf(ConfigurationFile &file) } continue; } - if (ch == '#' || (ch == '/' && c + 1 < len && line[c + 1] == '/')) - break; // Line comment, ignore the rest of the line (much like this one!) + else if (ch == '#' || (ch == '/' && c + 1 < len && line[c + 1] == '/')) + c = len - 1; // Line comment, ignore the rest of the line (much like this one!) else if (ch == '/' && c + 1 < len && line[c + 1] == '*') { // Multiline (or less than one line) comment @@ -1463,7 +1530,6 @@ void ServerConfig::LoadConf(ConfigurationFile &file) throw ConfigException("Unexpected quoted string (prior unhandled words): " + file.GetName() + ":" + stringify(linenumber)); } in_quote = in_word = true; - continue; } else if (ch == '=') { @@ -1498,70 +1564,62 @@ void ServerConfig::LoadConf(ConfigurationFile &file) in_word = false; section = wordbuffer; wordbuffer.clear(); + continue; + } + else if (ch == ' ' || ch == '\r' || ch == '\t') + { + // Terminate word + in_word = false; } + else if (!in_word && ch == ';') + ; else if (ch == '}') + ; + else { - if (section.empty()) + if (!in_word && !wordbuffer.empty()) { file.Close(); - throw ConfigException("Stray '}': " + file.GetName() + ":" + stringify(linenumber)); + throw ConfigException("Unexpected word: " + file.GetName() + ":" + stringify(linenumber)); } - if (!wordbuffer.empty() || !itemname.empty()) + wordbuffer += ch; + in_word = true; + } + + if (ch == ';' || ch == '}' || c + 1 == len) + { + if (in_quote) + { + // Quotes can span multiple lines; all we need to do is go to the next line without clearing things + wordbuffer += "\n"; + continue; + } + in_word = false; + if (!itemname.empty()) { - // this will allow for the construct: section { key = value } - // but will not allow for anything else, such as: section { key = value; key = value } - if (!sectiondata.empty()) + if (wordbuffer.empty()) { file.Close(); - throw ConfigException("Unexpected end of section: " + file.GetName() + ":" + stringify(linenumber)); + throw ConfigException("Item without value: " + file.GetName() + ":" + stringify(linenumber)); } - // this is the same as the below section for testing if itemname is non-empty after the loop, but done inside it to allow the above construct - Log(LOG_DEBUG) << "ln "<< linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; + Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; sectiondata.push_back(KeyVal(itemname, wordbuffer)); wordbuffer.clear(); itemname.clear(); } - this->config_data.insert(std::pair<Anope::string, KeyValList>(section, sectiondata)); - section.clear(); - sectiondata.clear(); - } - else if (ch == ';' || ch == '\r') - continue; // Ignore - else if (ch == ' ' || ch == '\t') - { - // Terminate word - if (in_word) - in_word = false; - } - else - { - if (!in_word && !wordbuffer.empty()) + + if (ch == '}') { - file.Close(); - throw ConfigException("Unexpected word: " + file.GetName() + ":" + stringify(linenumber)); + if (section.empty()) + { + file.Close(); + throw ConfigException("Stray '}': " + file.GetName() + ":" + stringify(linenumber)); + } + this->config_data.insert(std::pair<Anope::string, KeyValList>(section, sectiondata)); + section.clear(); + sectiondata.clear(); } - wordbuffer += ch; - in_word = true; - } - } - if (in_quote) - { - // Quotes can span multiple lines; all we need to do is go to the next line without clearing things - wordbuffer += "\n"; - continue; - } - in_word = false; - if (!itemname.empty()) - { - if (wordbuffer.empty()) - { - file.Close(); - throw ConfigException("Item without value: " + file.GetName() + ":" + stringify(linenumber)); } - Log(LOG_DEBUG) << "ln " << linenumber << " EOL: s='" << section << "' '" << itemname << "' set to '" << wordbuffer << "'"; - sectiondata.push_back(KeyVal(itemname, wordbuffer)); - wordbuffer.clear(); - itemname.clear(); } } if (in_ml_comment) diff --git a/src/init.cpp b/src/init.cpp index 73589b468..0f2f30a58 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "oper.h" Uplink *uplink_server; @@ -401,6 +402,12 @@ void Init(int ac, char **av) throw FatalException("You must load a protocol module!"); else if (ModuleManager::FindFirstOf(ENCRYPTION) == NULL) throw FatalException("You must load at least one encryption module"); + + for (botinfo_map::iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + { + it->second->GenerateUID(); + it->second->server = Me; + } Log() << "Using IRCd protocol " << protocol->name; diff --git a/src/language.cpp b/src/language.cpp index 4e1b94e02..222008b8c 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -1,5 +1,6 @@ #include "services.h" -#include <stack> +#include "modules.h" +#include "commands.h" std::vector<Anope::string> languages; std::vector<Anope::string> domains; @@ -94,9 +95,3 @@ const char *anope_gettext(const char *lang, const char *string) } #endif -void SyntaxError(CommandSource &source, const Anope::string &command, const Anope::string &message) -{ - source.Reply(_("Syntax: \002%s\002"), message.c_str()); - source.Reply(_(_(MORE_INFO)), Config->UseStrictPrivMsgString.c_str(), source.owner->nick.c_str(), command.c_str()); -} - diff --git a/src/logger.cpp b/src/logger.cpp index 8a1be9ab2..1725e8670 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -11,9 +11,7 @@ #include "services.h" #include "modules.h" -#include "chanserv.h" -#include "operserv.h" -#include "global.h" +#include "commands.h" static Anope::string GetTimeStamp() { @@ -67,8 +65,8 @@ Anope::string LogFile::GetName() const Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type(type), Category(category) { - if (!bi && global) - bi = global->Bot(); + if (!bi) + bi = Config ? findbot(Config->Global) : NULL; if (bi) this->Sources.push_back(bi->nick); } @@ -81,8 +79,13 @@ Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN) throw CoreException("This constructor does not support this log type"); - this->bi = c->service ? c->service : (global ? global->Bot() : NULL); - this->Category = (c->service ? c->service->nick + "/" : "") + c->name; + size_t sl = c->name.find('/'); + this->bi = NULL; + if (sl != Anope::string::npos) + this->bi = findbot(c->name.substr(0, sl)); + if (this->bi == NULL) + this->bi = Config ? findbot(Config->Global) : NULL; + this->Category = c->name; if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(u->nick); @@ -96,7 +99,8 @@ Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) buf << "OVERRIDE: "; else buf << "COMMAND: "; - buf << u->GetMask() << " used " << c->name << " "; + Anope::string cname = sl != Anope::string::npos ? c->name.substr(sl + 1) : c->name; + buf << u->GetMask() << " used " << cname << " "; if (ci) buf << "on " << ci->name << " "; } @@ -106,7 +110,7 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) if (!c) throw CoreException("Invalid pointers passed to Log::Log"); - this->bi = chanserv ? chanserv->Bot() : NULL; + this->bi = Config ? findbot(Config->ChanServ) : NULL; this->Category = category; if (this->bi) this->Sources.push_back(this->bi->nick); @@ -126,8 +130,7 @@ Log::Log(User *u, const Anope::string &category) : bi(NULL), Type(LOG_USER), Cat if (!u) throw CoreException("Invalid pointers passed to Log::Log"); - if (!this->bi && global) - this->bi = global->Bot(); + this->bi = Config ? findbot(Config->Global) : NULL; if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(u->nick); @@ -140,10 +143,9 @@ Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), if (!s) throw CoreException("Invalid pointer passed to Log::Log"); - if (operserv) - this->bi = operserv->Bot(); - if (!this->bi && global) - this->bi = global->Bot(); + this->bi = Config ? findbot(Config->OperServ) : NULL; + if (!this->bi) + this->bi = Config ? findbot(Config->Global) : NULL; if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(s->GetName()); @@ -153,8 +155,8 @@ Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_NORMAL), Category(category) { - if (!b && global) - this->bi = global->Bot(); + if (!this->bi) + this->bi = Config ? findbot(Config->Global) : NULL; if (this->bi) this->Sources.push_back(bi->nick); } diff --git a/src/main.cpp b/src/main.cpp index 4a02e532d..0c1db63ea 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -110,7 +110,7 @@ class UplinkSocket : public ConnectionSocket ~UplinkSocket() { - if (Me && Me->GetUplink() && Me->GetUplink()->IsSynced()) + if (Me && !Me->GetLinks().empty() && Me->GetLinks()[0]->IsSynced()) { FOREACH_MOD(I_OnServerDisconnect, OnServerDisconnect()); @@ -397,6 +397,8 @@ int main(int ac, char **av, char **envp) quitmsg = "Terminating, reason unknown"; Log() << quitmsg; + delete UplinkSock; + ModuleManager::UnloadAll(); SocketEngine::Shutdown(); for (Module *m; (m = ModuleManager::FindFirstOf(PROTOCOL)) != NULL;) diff --git a/src/misc.cpp b/src/misc.cpp index 967e2f6ef..4c1d03af2 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -225,7 +225,7 @@ Anope::string duration(const time_t &t, NickCore *nc) if (hours) { buffer += need_comma ? ", " : ""; - buffer += stringify(hours) + " " + (hours != 1 ? translate(nc, _("hounslaters")) : translate(nc, _("hour"))); + buffer += stringify(hours) + " " + (hours != 1 ? translate(nc, _("hours")) : translate(nc, _("hour"))); need_comma = true; } if (minutes) diff --git a/src/modes.cpp b/src/modes.cpp index b91cc9b85..daada4322 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -279,29 +279,6 @@ bool ChannelModeRegistered::CanSet(User *u) const return false; } -/** Add a ban to the channel - * @param chan The channel - * @param mask The ban - */ -void ChannelModeBan::OnAdd(Channel *chan, const Anope::string &mask) -{ - /* check for NULL values otherwise we will segfault */ - if (!chan || mask.empty()) - return; - - /* Check whether it matches a botserv bot */ - if (!Config->s_BotServ.empty() && Config->BSSmartJoin && chan->ci && chan->ci->bi && chan->FindUser(chan->ci->bi)) - { - BotInfo *bi = chan->ci->bi; - - Entry ban(CMODE_BAN, mask); - if (ban.Matches(bi)) - chan->RemoveMode(NULL, CMODE_BAN, mask); - } - - Log(LOG_DEBUG) << "Added ban " << mask << " to channel " << chan->name; -} - void StackerInfo::AddMode(Mode *mode, bool Set, const Anope::string &Param) { ChannelMode *cm = NULL; diff --git a/src/modulemanager.cpp b/src/modulemanager.cpp index 1c4e07eef..8f5e15146 100644 --- a/src/modulemanager.cpp +++ b/src/modulemanager.cpp @@ -523,3 +523,14 @@ Service *ModuleManager::GetService(const Anope::string &name) return NULL; } +/** Get the existing service key names + * @return The keys + */ +std::vector<Anope::string> ModuleManager::GetServiceKeys() +{ + std::vector<Anope::string> keys; + for (std::map<Anope::string, Service *>::const_iterator it = ModuleManager::ServiceProviders.begin(), it_end = ModuleManager::ServiceProviders.end(); it != it_end; ++it) + keys.push_back(it->first); + return keys; +} + diff --git a/src/modules.cpp b/src/modules.cpp index c379a66dd..241054715 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -65,49 +65,6 @@ std::vector<Message *> Anope::FindMessage(const Anope::string &name) return messages; } -/******************************************************************************* - * Command Functions - *******************************************************************************/ - -int Module::AddCommand(BotInfo *bi, Command *c) -{ - if (!bi || !c) - return MOD_ERR_PARAMS; - - c->module = this; - c->service = bi; - - std::pair<CommandMap::iterator, bool> it = bi->Commands.insert(std::make_pair(c->name, c)); - - if (it.second != true) - { - Log() << "Error creating command " << c->name << ". Command already exists!"; - return MOD_ERR_EXISTS; - } - - return MOD_ERR_OK; -} - -/** - * Delete a command from the service given. - * @param cmdTable the cmdTable for the services to remove the command from - * @param name the name of the command to delete from the service - * @return returns MOD_ERR_OK on success - */ -int Module::DelCommand(BotInfo *bi, Command *c) -{ - if (!bi || !c) - return MOD_ERR_PARAMS; - - if (!bi->Commands.erase(c->name)) - return MOD_ERR_NOEXIST; - - c->module = NULL; - c->service = NULL; - - return MOD_ERR_OK; -} - Service::Service(Module *o, const Anope::string &n) : owner(o), name(n) { } diff --git a/src/operserv.cpp b/src/operserv.cpp index 7426d4b20..9546b7ee1 100644 --- a/src/operserv.cpp +++ b/src/operserv.cpp @@ -11,9 +11,7 @@ #include "services.h" #include "modules.h" -#include "operserv.h" - -XLineManager *SGLine = NULL, *SZLine = NULL, *SQLine = NULL, *SNLine = NULL; +#include "oper.h" /* List of XLine managers we check users against in XLineManager::CheckAll */ std::list<XLineManager *> XLineManager::XLineManagers; @@ -63,7 +61,7 @@ Anope::string XLine::GetHost() const /** Constructor */ -XLineManager::XLineManager() +XLineManager::XLineManager(Module *creator, const Anope::string &name, char t) : Service(creator, name), type(t) { } @@ -75,6 +73,14 @@ XLineManager::~XLineManager() this->Clear(); } +/** The type of xline provided by this service + * @return The type + */ +const char &XLineManager::Type() +{ + return this->type; +} + /** Register a XLineManager, places it in XLineManagers for use in XLineManager::CheckAll * It is important XLineManagers are registered in the proper order. Eg, if you had one akilling * clients and one handing them free olines, you would want the akilling one first. This way if a client @@ -340,278 +346,3 @@ void XLineManager::OnExpire(XLine *x) { } -XLine *SGLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) -{ - Anope::string realreason = reason; - if (!creator.empty() && Config->AddAkiller) - realreason = "[" + creator + "] " + reason; - - XLine *x = new XLine(mask, creator, expires, realreason); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddAkill, OnAddAkill(x)); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return NULL; - } - - this->AddXLine(x); - - if (UplinkSock && Config->AkillOnAdd) - this->Send(NULL, x); - - return x; -} - -void SGLineManager::Del(XLine *x) -{ - ircdproto->SendAkillDel(x); -} - -void SGLineManager::OnMatch(User *u, XLine *x) -{ - if (u) - u->Kill(Config->s_OperServ, x->Reason); - ircdproto->SendAkill(u, x); -} - -void SGLineManager::OnExpire(XLine *x) -{ - if (Config->WallAkillExpire && operserv) - ircdproto->SendGlobops(operserv->Bot(), "AKILL on %s has expired", x->Mask.c_str()); -} - -void SGLineManager::Send(User *u, XLine *x) -{ - ircdproto->SendAkill(u, x); -} - -XLine *SNLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) -{ - XLine *x = new XLine(mask, creator, expires, reason); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SNLINE)); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return NULL; - } - - this->AddXLine(x); - - if (Config->KillonSNline && !ircd->sglineenforce) - { - Anope::string rreason = "G-Lined: " + reason; - - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) - { - User *user = it->second; - ++it; - - if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask)) - user->Kill(Config->ServerName, rreason); - } - } - - return x; -} - -void SNLineManager::Del(XLine *x) -{ - ircdproto->SendSGLineDel(x); -} - -void SNLineManager::OnMatch(User *u, XLine *x) -{ - if (u) - { - Anope::string reason = "G-Lined: " + x->Reason; - u->Kill(Config->s_OperServ, reason); - } - this->Send(u, x); -} - -void SNLineManager::OnExpire(XLine *x) -{ - if (Config->WallSNLineExpire && operserv) - ircdproto->SendGlobops(operserv->Bot(), "SNLINE on \2%s\2 has expired", x->Mask.c_str()); -} - -void SNLineManager::Send(User *u, XLine *x) -{ - ircdproto->SendSGLine(u, x); -} - -XLine *SNLineManager::Check(User *u) -{ - for (unsigned i = this->XLines.size(); i > 0; --i) - { - XLine *x = this->XLines[i - 1]; - - if (x->Expires && x->Expires < Anope::CurTime) - { - this->OnExpire(x); - this->Del(x); - delete x; - this->XLines.erase(XLines.begin() + i - 1); - continue; - } - - if (Anope::Match(u->realname, x->Mask)) - { - this->OnMatch(u, x); - return x; - } - } - - return NULL; -} - -XLine *SQLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) -{ - XLine *x = new XLine(mask, creator, expires, reason); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SQLINE)); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return NULL; - } - - this->AddXLine(x); - - if (Config->KillonSQline) - { - Anope::string rreason = "Q-Lined: " + reason; - - if (mask[0] == '#') - { - for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) - { - Channel *c = cit->second; - - if (!Anope::Match(c->name, mask)) - continue; - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) - { - UserContainer *uc = *it; - ++it; - - if (uc->user->HasMode(UMODE_OPER) || uc->user->server == Me) - continue; - c->Kick(NULL, uc->user, "%s", reason.c_str()); - } - } - } - else - { - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) - { - User *user = it->second; - ++it; - - if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->nick, x->Mask)) - user->Kill(Config->ServerName, rreason); - } - } - } - - if (UplinkSock) - this->Send(NULL, x); - - return x; -} - -void SQLineManager::Del(XLine *x) -{ - ircdproto->SendSQLineDel(x); -} - -void SQLineManager::OnMatch(User *u, XLine *x) -{ - if (u) - { - Anope::string reason = "Q-Lined: " + x->Reason; - u->Kill(Config->s_OperServ, reason); - } - - this->Send(u, x); -} - -void SQLineManager::OnExpire(XLine *x) -{ - if (Config->WallSQLineExpire && operserv) - ircdproto->SendGlobops(operserv->Bot(), "SQLINE on \2%s\2 has expired", x->Mask.c_str()); -} - -void SQLineManager::Send(User *u, XLine *x) -{ - ircdproto->SendSQLine(u, x); -} - -bool SQLineManager::Check(Channel *c) -{ - if (ircd->chansqline && SQLine) - { - for (std::vector<XLine *>::const_iterator it = SQLine->GetList().begin(), it_end = SQLine->GetList().end(); it != it_end; ++it) - { - XLine *x = *it; - - if (Anope::Match(c->name, x->Mask)) - return true; - } - } - - return false; -} - -XLine *SZLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) -{ - XLine *x = new XLine(mask, creator, expires, reason); - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SZLINE)); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return NULL; - } - - this->AddXLine(x); - - if (UplinkSock) - this->Send(NULL, x); - - return x; -} - -void SZLineManager::Del(XLine *x) -{ - ircdproto->SendSZLineDel(x); -} - -void SZLineManager::OnMatch(User *u, XLine *x) -{ - if (u) - { - Anope::string reason = "Z-Lined: " + x->Reason; - u->Kill(Config->s_OperServ, reason); - } - - ircdproto->SendSZLine(u, x); -} - -void SZLineManager::OnExpire(XLine *x) -{ - if (Config->WallSZLineExpire && operserv) - ircdproto->SendGlobops(operserv->Bot(), "SZLINE on \2%s\2 has expired", x->Mask.c_str()); -} - -void SZLineManager::Send(User *u, XLine *x) -{ - ircdproto->SendSZLine(u, x); -} - diff --git a/src/protocol.cpp b/src/protocol.cpp index dc1c5960d..1c2ef4d7d 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -329,7 +329,7 @@ bool IRCdMessage::OnKill(const Anope::string &source, const std::vector<Anope::s return true; /* Recover if someone kills us. */ - if (!Config->s_BotServ.empty() && u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) + if (u->server == Me && (bi = dynamic_cast<BotInfo *>(u))) { introduce_user(bi->nick); bi->RejoinAll(); @@ -384,11 +384,10 @@ bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope if (receiver[0] == '#') { - ChannelInfo *ci = cs_findchan(receiver); - /* Some paranoia checks */ - if (ci && ci->c) + Channel *c = findchan(receiver); + if (c) { - FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, ci, message)); + FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, c, message)); } } else @@ -500,28 +499,22 @@ bool IRCdMessage::OnSQuit(const Anope::string &source, const std::vector<Anope:: bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - const Anope::string &who = params[0]; - - if (!source.empty() && !who.empty()) + if (!source.empty() && !params.empty()) { - User *u; - BotInfo *bi = findbot(who); - if (bi) - { - ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); - ircdproto->SendNumeric(Config->ServerName, 307, source, "%s :is a registered nick", bi->nick.c_str()); - ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", bi->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); - ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); - ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", who.c_str()); - } - else if ((u = finduser(who)) && u->server == Me) + User *u = finduser(params[0]); + if (u && u->server == Me) { + BotInfo *bi = findbot(u->nick); ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); + if (bi) + ircdproto->SendNumeric(Config->ServerName, 307, source, "%s :is a registered nick", bi->nick.c_str()); ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); - ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", u->nick.c_str()); + if (bi) + ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); + ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", params[0].c_str()); } else - ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such user.", who.c_str()); + ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such user.", params[0].c_str()); } return true; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index cf2cb42df..131fdf29c 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -11,8 +11,6 @@ #include "services.h" #include "modules.h" -#include "chanserv.h" -#include "nickserv.h" ChanAccess::ChanAccess(const Anope::string &umask) { @@ -193,9 +191,14 @@ NickCore *ChannelInfo::GetFounder() const */ BotInfo *ChannelInfo::WhoSends() { - if (!this || !this->bi || !this->c || !this->botflags.HasFlag(BS_SYMBIOSIS) || !this->c->FindUser(this->bi)) - return chanserv ? chanserv->Bot() : (nickserv ? nickserv->Bot() : NULL); - return this->bi; + if (this && this->bi) + return this->bi; + BotInfo *bi = findbot(Config->ChanServ); + if (bi) + return bi; + else if (!BotListByNick.empty()) + return BotListByNick.begin()->second; + return NULL; } /** Add an entry to the channel access list @@ -786,8 +789,11 @@ bool ChannelInfo::CheckKick(User *user) return false; bool set_modes = false, do_kick = false; - if (ircd->chansqline && SQLineManager::Check(this->c)) - do_kick = true; + + EventReturn MOD_RESULT; + FOREACH_MOD(I_OnCheckKick, OnCheckKick(user, this, do_kick)); + if (MOD_RESULT == EVENT_ALLOW) + return false; Anope::string mask, reason; if (!user->HasMode(UMODE_OPER) && this->HasFlag(CI_SUSPENDED)) diff --git a/src/servers.cpp b/src/servers.cpp index 19140c154..5aa44be82 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "oper.h" /* Anope */ Server *Me = NULL; diff --git a/src/users.cpp b/src/users.cpp index 5c993fcf0..343ef058a 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -11,7 +11,6 @@ #include "services.h" #include "modules.h" -#include "nickserv.h" Anope::insensitive_map<User *> UserListByNick; Anope::map<User *> UserListByUID; @@ -309,6 +308,9 @@ void User::SendMessage(BotInfo *source, Anope::string msg) */ void User::Collide(NickAlias *na) { + BotInfo *bi = findbot(Config->NickServ); + if (!bi) + return; if (na) na->SetFlag(NS_COLLIDED); @@ -323,15 +325,15 @@ void User::Collide(NickAlias *na) } while (finduser(guestnick) && i++ < 10); if (i == 11) - this->Kill(Config->s_NickServ, "Services nickname-enforcer kill"); + this->Kill(Config->NickServ, "Services nickname-enforcer kill"); else { - this->SendMessage(nickserv->Bot(), _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); + this->SendMessage(bi, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); ircdproto->SendForceNickChange(this, guestnick, Anope::CurTime); } } else - this->Kill(Config->s_NickServ, "Services nickname-enforcer kill"); + this->Kill(Config->NickServ, "Services nickname-enforcer kill"); } /** Identify the user to the Nick @@ -679,11 +681,6 @@ void User::SetModesInternal(const char *umodes, ...) ++opcnt; else --opcnt; - - break; - case UMODE_REGISTERED: - if (add && !this->IsIdentified() && nickserv) - this->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); break; case UMODE_CLOAK: case UMODE_VHOST: @@ -836,30 +833,10 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop old_na->OnCancel(user); NickAlias *na = findnick(user->nick); - /* If the new nick isnt registerd or its registerd and not yours */ - if (!na || na->nc != user->Account()) - { - user->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); - ircdproto->SendUnregisteredNick(user); - - nickserv->Validate(user); - } - else + if (na && na->nc == user->Account()) { na->last_seen = Anope::CurTime; user->UpdateHost(); - if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - { - user->SetMode(nickserv->Bot(), UMODE_REGISTERED); - ircdproto->SetAutoIdentificationToken(user); - } - Log(nickserv->Bot()) << user->GetMask() << " automatically identified for group " << user->Account()->display; - } - - if (ircd->sqline) - { - if (user->HasMode(UMODE_OPER) && SQLine->Check(user)) - return NULL; } } |