Browse Source

Split main README into separate per-module manpages lmoa

Wazakindjes 3 years ago
parent
commit
b963ab72a9

+ 15 - 1234
README.md

@@ -1,1263 +1,44 @@
-[![Build status - Windows](https://ci.appveyor.com/api/projects/status/pvrlgybnie2wipor?svg=true)](https://ci.appveyor.com/project/Gottem/unrealircd-mods)
+This repo used to be a giant collection of the modules I've written, but since the advent of UnrealIRCd v5 there's now a [centralised repo](https://github.com/unrealircd/unrealircd-contrib) for that shit instead. Many of my mods can be found there, so if you're a \*NIX user then use [Unreal's own module manager](https://www.unrealircd.org/docs/Module_manager) to install them and keep them up to date. ;]
 
-This repo is a collection of my own modules (either ported, modified or written from scratch). For troubleshooting etc, view the [HALP.md fiel](./HALP.md). =]
+When modules __aren't__ in that central repo, it usually means it's something tailored to very specific needs and there's no real reason to include it on there. For those, you still need to do a couple of manual steps (see below).
 
-You can also find (some) discussion in the [3rd party mods board on the Unreal forums](https://forums.unrealircd.org/viewforum.php?f=52).
+For troubleshooting etc, view the [HALP.md fiel](./HALP.md). You can also find (some) discussion in the [3rd party mods board on the Unreal forums](https://forums.unrealircd.org/viewforum.php?f=52). =]
 
-__Protip__: To download a module, use the `Raw` button on the right-hand side when viewing a `.c` file. This way you're sure to get the proper code. ;]
-
-__Another protip__: This repo now has [its own RSS feed](https://rss.gottem.nl/unrealircd_mods.rss), so you can easily keep track of that shit.
-
-__Yet another protip (for Wind0ngs users):__ Starting with Unreal 4.0.16, you can grab a `.zip` file with all modules compiled to `.dll` files for easy installation. ;];]
-Currently available (__make sure your Unreal version matches__):
-* [UnrealIRCd GIT BUILD](https://u4win.gottem.nl/unrealircd-mods-git.zip)
-* [UnrealIRCd 4.0.16](https://u4win.gottem.nl/unrealircd-mods-4.0.16.zip)
-* [UnrealIRCd 4.0.17](https://u4win.gottem.nl/unrealircd-mods-4.0.17.zip)
-* [UnrealIRCd 4.0.18](https://u4win.gottem.nl/unrealircd-mods-4.0.18.zip)
-* [UnrealIRCd 4.2.0](https://u4win.gottem.nl/unrealircd-mods-4.2.0.zip)
-* [UnrealIRCd 4.2.1](https://u4win.gottem.nl/unrealircd-mods-4.2.1.zip)
-* [UnrealIRCd 4.2.2](https://u4win.gottem.nl/unrealircd-mods-4.2.2.zip)
-* [UnrealIRCd 4.2.3](https://u4win.gottem.nl/unrealircd-mods-4.2.3.zip)
-* [UnrealIRCd 4.2.4.1](https://u4win.gottem.nl/unrealircd-mods-4.2.4.1.zip)
-
-Note that modules for the git version __may or may not work__, as a new zip only gets uploaded on successful builds of the git repo. This `.zip` contains a file with the last build date/time anyways for comparis0n (shit's in GMT y0). =] __Also, while we're making em transiti0n to Unreal 5.x some modules may not be built for all 4.x versions.__
+__Windows users:__ you're currently shit out of luck when it comes to using my modules. I need to hack my AppVeyor to build modules from all the new locations first. :DDDDDDD Unless you're feeling brave [and wanna try manually compiling them yourself](https://www.unrealircd.org/docs/Compiling_UnrealIRCd_5_on_Windows#Compiling_modules) of course. ;]
 
 __All modules should be loaded on all servers, unless explicitly specified otherwise__
 
 __The shown config block snippets are just examples of the structure, it's up to you to integrate it properly with your existing config__
 
-# Module compilation
-Since Windows users can (and pr0lly should) use the above `.zip` archives created through AppVeyor, these instructions apply to *nix users only. I'm assuming you know __at least a little bit__ about the OS you're using.
+# Module compilation (\*NIX only)
+__Protip__: To download a module, use the `Raw` button on the right-hand side when viewing a `.c` file. This way you're sure to get the proper code. ;]
 
 I personally clone this git repo and symlink modules into the Unreal 3rd party directory, meaning I can simply pull the changes and re-run `make`. So:
-    cd /home/unreal
+    cd /home/unreal # Home directory of your IRC user
     mkdir build # Or whatever folder you want
     cd build
     git clone https://gitgud.malvager.net/Wazakindjes/unrealircd_mods.git
-    cd ../unrealircd-4.0.18/src/modules/third # This is your Unreal source directory
-    ln -s /home/unreal/build/unrealircd_mods/u4/m_autovhost.c m_autovhost.c
-    ln -s /home/unreal/build/unrealircd_mods/u4/m_rmtkl.c m_rmtkl.c
+    cd /home/unreal/unrealircd-5.0.0/src/modules/third # This is your Unreal source directory
+    ln -s /home/unreal/build/unrealircd_mods/malv/otkl.c otkl.c
     # More links here: ln -s <target> <link name>
     # You can prolly omit <link name> because many versions of `ln` use the destination file's name for link name by default
     cd ../../../ # Back to the source tree's root
-    make && make install # Or the custom make command needed for like m_confprot
+    make && make install
 
-After that just add the relevant `loadmodule "third/m_modname";` line(s) to `unrealircd.conf`. =] When I've updated one or more module(s), you can simply do:
+After that just add the relevant `loadmodule "third/modname";` line(s) to `unrealircd.conf`. =] When I've updated one or more module(s), you can simply do:
     cd /home/unreal/build/unrealircd_mods
     git pull
-    cd /home/unreal/unrealircd-4.0.18
+    cd /home/unreal/unrealircd-5.0.0
     make && make install
+    /home/unreal/ircd/unrealircd rehash
 
 # Repo structure
 * __skrip:__ Some miscellaneous scripts that might be of use (see readme in the dir for deetz) ;]
-* __u4:__ Modules for Unreal 4.x obviously
-* __uncommon:__ Quite specialised/complex modules, doubt you'll care about them ;3
 * __templates:__ Muh templ8s for Unreal m0ds m8, everything is explained inside the `.c` files there
 * __spec:__ Specifically written for someone by request, as such it's tailored to them/their network and is probably not very useful to you (see readme in the dir for deetz)
 * __malv:__ Specifically written for Malvager; move along, nothing to see here =]
-* __4thparty:__ As a courtesy, I'm having my AppVeyor setup also build other people's m0ds for Wind0ngs (see the readme in the dir for details)
-* __br0ken__: Modules I started working on but which don't quite work (see the readme in the dir for details)
 
 # Paid modules
-I also started writing modules with the intention of selling them, as those are generally very complex and take up __a lot__ of my spare time. ;] I'll put a short overview of such mods here, if you're interested and want more info simply go to my [shop sort of thing](https://u4shop.gottem.nl).
-
-| Module														| Description																														|
-| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| m_geoip														| Deny connections based on IP location data																						|
-| m_ldapauth													| Restrict IRC connections to those with proper LDAP authentication																	|
-
-If you don't need these but still want to support me, feel free to [donate through PayPal](http://gottem.nl/donate) or [become a monthly Patron](https://www.patreon.com/gottem_u4mods). :>
-
-# Index lol
-This README contains all modules and their descriptions/usage info (ordered from new to old). Modules that have `PORTED` behind their name tell you that I've ported them. If it says `UNC` then it's an uncommon module, meaning most people won't have a real use for it. There will be others but they should be self-explanatory. =]
-
-| Module														| Description																														|
-| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------|
-| [m_needauthjoin (UNC)](#m_needauthjoin-unc)					| Require authentication with services before users are able to join channels (with exceptions, chmode `+A`)						|
-| [m_pubnetinfo (UNC)](#m_pubnetinfo-unc)						| Display public network/server information such as SSL/TLS links																	|
-| [m_noghosts](#m_noghosts)										| Keep channels clear of "ghosts" of opers																							|
-| [m_rehashgem (UNC)](#m_rehashgem-unc)							| Implements an additional rehash flag -gem (__g__lobal __e__xcept __m__e)															|
-| [m_block_masshighlight](#m_block_masshighlight)				| Prevent mass highlights network-wide																								|
-| [m_timedbans](#m_timedbans)									| Adds extban `~t` for auto-expiring bans																							|
-| [m_rtkl](#m_rtkl)												| Allows privileged opers to remove __remote__ servers' __local__ K/Z:Lines															|
-| [m_autojoin_byport](#m_autojoin_byport)						| Auto-join channels on connect based on connection port																			|
-| [m_blocknossl (UNC)](#m_blocknossl-unc)						| Allows privileged opers to temporarily block __new__, non-SSL user connections													|
-| [m_nick_minlen](#m_nick_minlen)								| Impose a minimum nick length																										|
-| [m_debug (UNC)](#m_debug-unc)									| Allows privileged opers to easily view internal (configuration) data																|
-| [m_extwarn](#m_extwarn)										| Enables additional configuration error checking																					|
-| [m_allowctcp_opers](#m_allowctcp_opers)						| Allows opers to override someone's umode `+T` (`noctcp`)																			|
-| [m_plainusers](#m_plainusers)									| Allows opers to list all users __NOT__ connected over SSL/TLS																		|
-| [m_uniquemsg](#m_uniquemsg)									| Implements chmode `+U` to prevent people from repeating messages																	|
-| [m_pmlist](#m_pmlist)											| Implements umode `+P` to only allow only certain people to privately message you													|
-| [m_sacmds](#m_sacmds)											| Implements `SA*` commands for privileged opers as well as an accompanying snomask `+A`											|
-| [m_storetkl](#m_storetkl)										| Store TKL entries persistently across IRCd restarts																				|
-| [m_auditorium](#m_auditorium)									| Channel mode `+u` to show channel events/messages to/from people with `+o`/`+a`/`+q` only											|
-| [m_uline_nickhost](#m_uline_nickhost)							| Requires people to address services like `NickServ@services.my.net`																|
-| [m_websocket_restrict](#m_websocket_restrict)					| Impose restrictions on websocket connections																						|
-| [m_listrestrict](#m_listrestrict)								| Impose certain restrictions on `/LIST` usage																						|
-| [m_pmdelay](#m_pmdelay)										| Disallow new clients trying to send private messages until exceeding a certain timeout											|
-| [m_noinvite](#m_noinvite)										| Adds umode `+N` to block invites																									|
-| [m_textshun (UNC)](#m_textshun-unc)							| Drop messages based on nick and body																								|
-| [m_tklexcept](#m_tklexcept)									| Implements an `E:Line` to set TKL exceptions at runtime																			|
-| [m_kickjoindelay](#m_kickjoindelay)							| Chanmode `+j` to prevent people from rejoining too fast after a kick																|
-| [m_commandsno (PORTED)](#m_commandsno-ported)					| Adds snomask `+C`: lets IRC operators see command usages																			|
-| [m_clones (PORTED)](#m_clones-ported)							| Adds a command `/CLONES` to list all users having the same IP address matching the given options									|
-| [m_operpasswd (PORTED)](#m_operpasswd-ported)					| Snomask for failed `OPER` attempts with the ability to kill																		|
-| [m_netadmins (PORTED)](#m_netadmins-ported)					| Implements `KILL` and `X:Line` protection for privileged opers																	|
-| [m_securequery (PORTED)](#m_securequery-ported)				| Adds umode `+Z` to prevent SSL users and non-SSL ones privately messaging each other												|
-| [m_chansno (PORTED)](#m_chansno-ported)						| Allows you to assign channels for specific server notifications (sort of like snomasks)											|
-| [m_fantasy](#m_fantasy)										| Implements custom fantasy channel !cmds																							|
-| [m_denyban](#m_denyban)										| Deny specific ban masks network-wide																								|
-| [m_portsifresi (PORTED)](#m_portsifresi-ported)				| Protect specific ports with a password																							|
-| [m_anticaps](#m_anticaps)										| Block/lowercase messages that contain a configurable amount of capital letters													|
-| [m_joinmute (PORTED)](#m_joinmute-ported)						| Adds `+J` chmode: Mute newly joined people for `+J X` seconds																		|
-| [m_anti_amsg](#m_anti_amsg)									| Drop messages originating from /amsg																								|
-| [m_autovhost](#m_autovhost)									| Apply vhosts at connect time based on users' raw nick formats or IPs																|
-| [m_message_commonchans](#m_message_commonchans)				| Adds umode `+c` to prevent people who aren't in a common channel with you from messaging you										|
-| [m_bancheck_access (UNC)](#m_bancheck_access-unc)				| Prevents people who have `+o` or higher from getting banned, unless done by people with `+a`/`+q` or opers						|
-| [m_fixhop (UNC)](#m_fixhop-unc)								| The `+h` access mode seems to be a little borked/limited, this module implements some tweaks for it								|
-| [floodprot (UNC, MOD)](#floodprot-unc-mod)					| [Channel Mode +f](https://www.unrealircd.org/docs/Anti-flood_features#Channel_mode_f)												|
-| [m_repeatprot (UNC)](#m_repeatprot-unc)						| G(Z):Line/kill users (or block their messages) who spam through `CTCP`, `INVITE`, `OPER`, `NOTICE` and/or `PRIVMSG` 				|
-| [m_md5fjert (UNC, LEAF-ONLY)](#m_md5fjert-unc-leaf-only)		| Custom `FJERT` command lol, required in conjunction with `m_confprot`																|
-| [m_confprot (UNC, HUB-ONLY)](#m_confprot-unc-hub-only)		| Verifies leaf configs by checking their remotely included confs etc																|
-| [m_getlegitusers (PORTED)](#m_getlegitusers-ported)			| Command `/getlegitusers` to show user/bot count across the network																|
-| [m_clearlist](#m_clearlist)									| Adds `/CLEARLIST <channel> <types> <mask>` command to clear out banlists etc														|
-| [m_banfix_voice](#m_banfix_voice)								| `+v` overrides `+b` and `+b ~q:` for some reason, this module aims to correct that												|
-| [m_rmtkl (PORTED)](#m_rmtkl-ported)							| Adds `/rmtkl` command to easily remove `X:Lines` in bulk																			|
-| [m_git](#m_git)												| Install/Update third-party mods easily on (possibly) all servers through `git`													|
-| [m_forward (PORTED)](#m_forward-ported)						| Robust channel forwarding system																									|
-
-# m_reportlol (MALV)
-Adds a `/report` command which does fuck all. [=[==[==[=[
-
-# m_needauthjoin (UNC)
-Requested by `Paul DK`, prevent unidentified/unregistered users from creating new channels or joining existing ones. You can exempt them from this restriction on a per-channel basis by using the new channel mode `+A` (we runnin' out of chmodes lol). It doesn't take arguments as that would needlessly complicate things, so think of `+A` as an inverse of `+R`. ;] As always, opers/U:Lines/servers are not restricted. =]
-
-Users trying to join will get the dankass numeric reply 477: `You need a registered nick to join that channel`
-
-# m_pubnetinfo (UNC)
-Another request/proposal by `PeGaSuS`, this module displays information that is allowed to be publicly available for every server. Right now it'll simply show if a server is linked over `localhost` and if it's using `SSL/TLS` to communicate with the other end. Simply execute __/pubnetinfo__ and check the server notices sent to you. ;]
-
-__Example output:__
-    -someleaf.myirc.net- [pubnetinfo] Link hub.myirc.net: localhost connection = no -- SSL = yes
-    -hub.myirc.net- [pubnetinfo] Link otherleaf.myirc.net: localhost connection = no -- SSL = yes
-    -hub.myirc.net- [pubnetinfo] Link services.myirc.net: localhost connection = yes -- SSL = no
-
-So in this case I ran the command on `someleaf`, which only has information about the hub it's linked to. For the other servers this leaf asks its hub for the information instead (otherwise we can't tell if it's using SSL or nah). The hub has info on 2 additional servers; another leaf and the services node.
-
-You can get similar information by using `/stats C`, but: 1) it only outputs shit for directly attached servers 2) it requires you to remove `C` from `set::oper-only-stats` for making it publicly usable 3) it displays the server connection port too. ;]
-
-# m_noghosts
-Originally proposed by `PeGaSuS`, this module makes IRC opers part `+O` channels once they oper down. I've kept the "ghosts" thing for lack of a better term, deal w/ it. =]
-
-__Config block:__
-    noghosts {
-    	message "g h o s t b u s t e r s";
-    	flags "O";
-    	channels {
-    		"#opers"; // Don't forget the "" to make sure Unreal doesn't interpret it as a comment ;]
-    		"#moar";
-    	};
-    };
-
-All configurables are optional; the default message is simply `Opered down` and if no channels are specified it'll check all `+O` ones the opered-down oper is in. I may extend `flags` to contain more flags at some point, which would also affect the `message` (prolly). =]
-
-# m_rehashgem (UNC)
-Implements an additional rehashing flag `-gem` (__g__lobal __e__xcept __m__e). Since `m_confprot` requires you to set `allowunknown` to `1` when making config changes, it would cause a triple rehash on the hub which is really not necessary. =] I doubt anyone is actively using `m_confprot` so this mod is really just for me. =]
-
-Soooooo, when you do `/rehash -gem`, all __other__ servers will rehash everything (appends `-all` flag by default). You can also rehash just MOTDs, SSL-related stuff, etc by appending their respective flags to `-gem`:
-* `/rehash -gemssl`
-* `/rehash -gemmotd`
-* Any other "sub" flag Unreal already supports (`/helpop rehash` should show these)
-
-If you're running a mixed U3/U4 network this prolly won't work out of the box. In that case you'll have to change the source; find the line saying `#define BACK_COMPAT 0` and change it to `1` instead, then recompile. ;]
-
-# m_mshun (MALV)
-Enables privileged 0pers to add shuns that only affect `PRIVMSG`, `NOTICE`, `KNOCK` and `INVITE` (`M:Lines` lmao), except when sending __to__ U:Lines (`NiqqServ` etc). Only opers with the new operpriv `mshun` will be able to use it, although all others will get the notices since these `M:Lines` are __netwerk wide__ bruh. Servers, U:Lines and opers are exempt for obvious raisins.
-
-Expiring shuns is done with an `EVENT` thingy in Unreal, which is set to run every 10 seconds. This means if you set a shun for 5 seconds (why would you anyways?) it may not expire after eggzacktly 5 seconds. ;] When no expiration is specified the value in `set::default-bantime` is used. Every server checks the expirations themselves. =] Also, they store it in a `ModData` struct so it persists through a rehash without the need for a `.db` fiel. ;] Furthermore, they sync their known `M:Lines` upon server linkage. =]] Other lines such as G:Lines, Z:Lines are also stored in memory and get resynced during a link so these are pretty similar aye.
-
-__Config block:__
-    operclass netadmin-mshun {
-    	parent netadmin;
-    	privileges {
-    		mshun;
-    	};
-    };
-
-__Syntax:__
-`MSHUN [-]<ident@host> [expire] <reason>`
-
-Also supports the alias `MLINE`. The first argument may also be an online nickname, this will be resolved to their full mask. =] Wildcards `*` and `?` are also supp0rted.
-
-__Examples:__
-* `MSHUN guest*@* 0 nope` => All...
-* `MLINE guest*@* 0 nope` => ...of...
-* `MLINE -guest*@*` => ...these add/delete the same M:Line, with no expiration
-* `MSHUN guest*@* 3600 ain't gonna happen` => Add an M:Line that expires in an hour =]
-* `MSHUN guest*@* 1h ain't gonna happen` => Ditto ;];]
-* `MSHUN` => Show all M:Lines
-* `MLINE halp` => Show built-in halp
-
-The hostmask is matched against `user@realhost` only. The timestring shit like `1h` supports up to weeks (so you __can't__ do `1y`).
-
-# m_block_masshighlight
-This shit can halp you prevent highlight spam on your entire network. =] It keeps track of a user's messages on a per-channel basis and checks if they highlight one person too many times or too many different persons at once. Opers and U:Lines are exempt (as per usual), but also those with list modes `+a` and `+q`. ;3 When someone hits the threshold, opers with the snomask `EYES` will get a server notice through the module (enable that shit with `/mode <nick> +s +e` etc ;]).
-
-__Updated shit:__
-* Don't count duplicate nicks on the same line as separate highlights (also added/proposed by [k4be](https://forums.unrealircd.org/memberlist.php?mode=viewprofile&u=39884))
-* Added chanmode `+H` to exempt a channel from __all__ mass highlight checks, which mite b useful for quiz channels (also added/proposed by [k4be](https://forums.unrealircd.org/memberlist.php?mode=viewprofile&u=39884))
-* Added conf directives (and message handling for) `allow_accessmode`, `percent`, `show_opers_origmsg` (added/proposed by [k4be](https://forums.unrealircd.org/memberlist.php?mode=viewprofile&u=39884))
-* Added conf directive `allow_authed` (see bel0w bruh)
-* Added action `viruschan`
-* Added conf directive `multiline` imo tbh fambi (see below for m0ar inf0)
-
-__Config block:__
-_The module doesn't necessarily require any configuration, it uses the following block as defaults_
-
-    block_masshighlight {
-    	maxnicks 5;
-    	delimiters "	 ,.-_/\:;";
-    	action gline;
-    	duration 7d;
-    	reason "No mass highlighting allowed";
-    	snotice 1;
-    	banident 1;
-    	multiline 0;
-    	allow_authed 0;
-    	//allow_accessmode o; // k4be
-    	percent 1; // k4be
-    	show_opers_origmsg 1; // k4be
-    };
-
-* __maxnicks__:  Maximum amount of highlighted nicks (going over this number results in `action` setting in) -- __works in conjunction with `percent`__
-* __delimiters__: List of characters to split a sentence by (don't forget the surrounding quotes lol) -- any char not in the default list may prevent highlights anyways
-* __action__: Action to take, must be one of: `drop` (drop silently [for the offender]), `notice` (drop, but __do__ show notice to them), `gline`, `zline`, `shun`, `tempshun`, `kill`, `viruschan`
-* __duration__: How long to `gline`, `zline` or `shun` for, is a "timestring" like `7d`, `1h5m20s`, etc
-* __reason__: Reason to show to the user, must be at least 4 chars long
-* __snotice__: Whether to send snomask notices when users cross the highlight threshold, must be `0` or `1`
-* __banident__: When set to `1` it will ban `ident@iphost`, otherwise `*@iphost` (useful for shared ZNCs etc)
-* __multiline__: When set to `1` it will keep counting highlights until it encounters a line __without__ one
-* __allow_authed__: When set to `1` it will let logged-in users bypass this shit
-* __allow_accessmode__: Must be __one__ of `vhoaq` (or omitted entirely for no exceptions [the default]), exempts everyone with at minimum the specified mode from highlight checks (e.g. `a` includes people with `+q`)
-* __percent__: Threshold for the amount of characters belonging to highlights, not counting `delimiters` (e.g. `hi nick` would be 67%) -- __works in conjunction with `maxnicks`__
-* __show_opers_origmsg__: Display the message that was dropped to opers with the `SNO_EYES` snomask set
-
-If you omit a directive which is required for a certain `action`, you'll get a warning and it will proceed to use the default. It should be pretty clear what directives are required in what cases imo tbh famalam. ;];]
-
-# m_timedbans
-A much requested feature. =] Allows you to give channel bans (`+b` etc) an expiration time, using qt3.14 extbans. ;] Since it's integr8ed w/ channel mode `+b`, you need halfops or higher to be able to use this shit. The resolution for the expiration time is 1 minute; less than that seems useless to me anyways. Also, the module doesn't check for expirations every second (does every 15 though). It unsets as many bans per "line" as possible (either 8 masks or a total char length of >= 200).
-
-I tested this across 30 channels with 48 bans for each, it walks through them in less than a second. ;];];]
-
-__Protip:__ This module (or a variation of it) will be [included in Unreal 4.0.17 onwards](https://forums.unrealircd.org/viewtopic.php?f=1&t=8775#p38708) so you're better off using that to track updates more easily.
-
-__Usage:__
-Simply do `/mode #chan +b ~t:<EXPIRATION>:<BANMASK>`
-
-The banmask is your regular wildcard-enabled `nick!user@host` mask. Expiration is a "timestring" (see bel0w). Also, if you add a banmask which Unreal already knows it will emit an error. I'm not replacing bans simply because a person (and not some code ;]) should decide which expiration time should be active.
-
-__Examples:__
-* `/mode #ham +b ~t:60:Guest*!*@*`
-* `/mode #ham +b ~t:1h5m:Guest*!*@*`
-* `/mode #ham +b ~t:3d4h1m:Guest*!*@*`
-
-Bans the same people, but with different expirations.
-
-# m_rtkl
-Allows privileged opers to remove remote servers' local `K/Z:Lines`. The required privileges are `tkl:kline` and `tkl:zline`, which the "netadmin" operclass should carry by default. The syntax is mostly the same as for regular `K/Z:Lines`, with the addition of one in the very front to indicate the target server. After some checks it will simply pass on a `KLINE` or `ZLINE` command to that server, so any further error handling is done by that module. ;]
-
-__Syntax:__
-`RKLINE <server> <[-]identmask@hostmask> {duration} {reason}` => Add/Delete a local K:Line on `server` for the specified usermask (duration and reason are ignored for deletions)
-`RZLINE <server> <[-]identmask@ipmask> {duration} {reason}` => Add/Delete a local Z:Line on `server` for the specified usermask (duration and reason are ignored for deletions)
-
-__Examples:__
-* `RKLINE myleaf.dom.tld *@top.kek.org 0 lolnope` => Adds a permanent K:Line on `myleaf.dom.tld` for everyone connecting from `top.kek.org`
-* `RKLINE myleaf.dom.tld -*@top.kek.org 0 lolnope` => Deletes this same K:Line
-* `RZLINE myleaf.dom.tld *@123.123.123.* 60 lolnope` => Adds a one-minute Z:Line on `myleaf.dom.tld` for everyone connecting from `123.123.123.*`
-
-Since the snomask notices on the target server are only sent to __local__ opers, I had to hack some hook bs to get the executing oper to see that shit. =]
-
-__Protip:__ I didn't include a method for listing the remote server's `X:Lines`, you can already use `/stats K myleaf.dom.tld` for that fam. ;]
-
-# m_autojoin_byport
-Similar to `set::auto-join`, this forces users to join one/multiple channels on connect, based on the p0rt they're using.
-
-__Config block:__
-    autojoin_byport {
-    	6667 "#plain";
-    	6697 "#ssl,#ssl2";
-    };
-
-Should be pretty clear how that works. ;] Currently it doesn't check for duplicates or max channels, so bnice. It does check for valid channel names/lengths and port ranges. =]
-
-# m_blocknossl (UNC)
-Allows privileged opers to temporarily block new, non-SSL (actually TLS but w/e) __user__ connections network-wide. ;3 There's a new operpriv, which if set, allows an oper of that class to both block and unblock non-SSL connections. Keep in mind that rehashing the IRCd also resets the blocking flag for that server. ;] Opers with snomask `SNO_KILLS` (`/umode +s +k` etc) will see notices about disallowed connections.
-
-__Updated shit:__
-* Also notice opers of blocked connections =]
-
-__Config block:__
-    operclass netadmin-blocknossl {
-    	parent netadmin;
-    	privileges {
-    		blocknossl;
-    	};
-    };
-
-__Syntax:__
-`BLOCKNOSSL`
-`UNBLOCKNOSSL`
-
-Both commands do not take any arguments and are broadcasted to other servers. =]
-
-# m_nick_minlen
-Imposes a minimum require length for nicknames. Opers are exempt as they can do `SANICK` or possibly `/os SVSNICK` anyways. ;]
-
-__Updated shit:__
-* Also checks the nick on connect now xd
-
-__Usage:__
-Simply load the module and throw a directive in the `set { }` block.
-
-__Config block:__
-    set {
-    	// Rest of your set block goes here
-    	nick-min-length 5;
-    };
-
-That means only nicks of 5 chars and longer are allowed (obviously). ;]
-
-# m_otkl (MALV)
-Allows privileged opers to set one-time `G/GZ:Lines`. Local Z:Lines are not supported because they seem fairly useless imo tbh famlamlm. =] The rules for hostmasks etc are the same as for regular `G/GZ:Lines`. These "OTKLines" persist through a rehash, plus servers will sync everything they know at link-time too. ;]
-
-If any online users match a newly added OTKLine, they will be killed first (with the well-known G:Line message about being permanently b&). Then once they reconnect, they'll get killed one more time before the OTKLine is removed from all servers. ez pz.
-
-__Updated shit:__
-* Updates an `OTKLine` if a match for the mask is already found (instead of doing fuck all yo)
-* Uses a default reason `no reason` if none specified =]
-* Now also works on users who changed their ident thru HostServ or `/chgident` by een oper ;];]
-
-__Syntax:__
-Simply `OGLINE` or `OZLINE` => List current `OG/OZ:Lines` (they're 2 different lists yo)
-`OGLINE halp` and `OZLINE halp` => View built-in halp ;3
-`OGLINE <[-]identmask@hostmask> {reason}` => Set/remove an `OG:Line` (reason is required for adding, ignored when deleting)
-`OZLINE <[-]identmask@ipmask> {reason}` => Set/remove an `OZ:Line` (ditto for reason)
-
-__Examples:__
-* `OGLINE *@some.domain.* not gonna happen` => Sets a host-based ban
-* `OZLINE *@123.123.* nope` => Sets an IP-based ban
-* `OZLINE -*@123.123.* nope` => Removes an IP-based ban
-
-# m_debug (UNC)
-Allows privileged opers to easily view internal (configuration) data. I know you can do some of it with a `/STATS` command, but this shit displays different info than that. ;]
-
-__Usage:__
-Currently it allows opers with the operpriv `m_debug` to view configured oper and operclass information. By default it asks the server to which you're connected, but since it may differ across servers (local O:Lines etc), you can also ask another server directly. =]
-
-__Config block:__
-    operclass netadmin-debug {
-    	parent netadmin;
-    	privileges {
-    		m_debug;
-    	};
-    };
-
-__Syntax:__
-`DBG <datatype> [server]`
-I went with `DBG` and not `DEBUG` cuz a bunch of clients probably nick the `/debug` command, get at me. ;];]
-
-__Examples:__
-* `DBG opers` => Get a list of known opers from the server you're on
-* `DBG operclasses ayy.check.em` => Asks the leaf `ayy.check.em` about the operclasses it knows
-
-# m_extwarn
-Enables additional error checking of the IRCd configuration. I originally wrote it to (temporarily?) work around a [bug](https://bugs.unrealircd.org/view.php?id=4950) (although it may be by design) where you don't get a warning about using non-existent operclasses during rehash/init. So it currently only checks for that, but I may extend it to include other things later. =]
-
-The module only throws __warnings__, so it allows the rehash etc to continue normally. This way it won't break any functionality. ;];]
-
-# m_allowctcp_opers
-Allows opers to override someone's umode `+T` (noctcp), which basically means opers can do CTCPs regardless of the usermode.
-
-__Updated shit:__
-* Oper to oper is always allowed
-* If oper had `+T` also, they wouldn't see the reply in some cases
-
-# m_plainusers
-A simple module to list all users __not__ connected over SSL/TLS. Just run `/PUSERS` or `/PLAINUSERS` to get a nice lil' list. ;] It attempts to cram as many nicks on one line as it can, to avoid spamming the fuck out of you. Only opers can use it obviously. =]
-
-# m_uniquemsg
-A request by `PeGaSuS` to implement a channel mode `+U` to prevent people from repeating messages. Like if you said `ayy checkem` and I try it too, it won't be allowed. There has to be another unique message first. =] Requires `+a` or `+q` to set (or opers with OperOverride obv). Anyone with `+o` or up will be excluded from the check (opers are __not__ exempt).
-
-# m_pmlist
-Sort of a hybrid between umode `+D` (don't allow private messages at all) and `+R` (allow registered users only), this module allows you to keep a whitelist of people allowed to send you private messages. =] Their UID is stored so it persists through nickchanges too, but the module only shows you the original whitelisted nick in lists etc.
-
-__Updated shit:__
-* `PMHELP` command to always show the halp shit =]
-* `OPENPM` nao accepts `-persist` to make the module __not__ purge the entry when it becomes stale (instead, check if they're regged and authed on next reconnect)
-* Opers no longer need to be whitelisted (similar to U:Lines etc)
-
-__Usage:__
-Load the module and set umode `+P` on yourself (anyone can (un)set the umode). You can't set up a list without it but if you do have one and then unset the umode, it will be kept. Only when you disconnect will it be cleared (so it even persists through rehashes). Also, if __you__ have `+P` and message someone else, they will automatically be added to the list. If UIDs go stale (relevant user disconnects) the entry will also be removed if it's not persistent. See below (__Syntax__) for how2manage da whitelist. ;3
-
-There are also a few configuration directives for netadmins to tweak that shit.
-
-__Config block:__
-    pmlist {
-    	noticetarget 0; // Default is 0
-    	noticedelay 60; // Seconds only
-    };
-
-* `noticetarget` => Whether to notice the target instead, __if the source is a regged and logged in user__
-* `noticedelay` => How many seconds have to pass before a user will receive another notice
-
-__Syntax:__
-`OPENPM <nick> [-persist]` => Allow messages from the given user (the argument __must be an actual, existing nick__)
-`CLOSEPM <nickmask>` => Clear matching entries from your list; supports wildcard matches too (`*` and `?`)
-`PMLIST` => Display your current whitelist
-`PMHELP` => Display built-in halp info
-
-__Examples:__
-`OPENPM guest8` => Allow `guest8` to message you
-`OPENPM muhb0i -persist` => Allow `muhb0i`, persistently
-`CLOSEPM guest*` => Remove all entries matching this mask (`guest8`, `guestxxxx`, etc)
-`CLOSEPM *` => Remove __all__ entries (saves you a disconnect lol)
-
-Now this is what happens when a non-whitelisted user tries to message you:
-* For users who __haven't logged into services or if `noticetarget` is set to 0__, they will get a notice saying you don't accept private messages from them. It also instructs them to tell __you__ to do `/openpm` for them, like in a common channel.
-* For users who __have logged into services and if `noticetarget` is set to 1__ you will get a single notice asking you to do `/openpm` (the notice also includes their message).
-* These notices only happen once in a certain time period (based on the config directive `noticedelay`). After the first one, everything else will be silently discarded until enough time passes.
-
-# m_sacmds
-__This module used to be called `m_sanick`, so remove that one entirely and replace it with this to avoid conflicts__
-
-I've gotten multiple requests to have a module to implement `SA*` commands (like `SANICK`, `SAUMODE`) within the IRCd instead of through services (usually `/os SVSNICK` etc). Right now it allows privileged opers to forcibly change someone's nickname and/or their usermodes. =] You cannot use any of these commands on U:Lined users, raisins should b fairly obvious.
-
-This m0d also implements a snomask `+A` to indicate who can __see__ the related server notices. I had to pick `A` (ykno, like __A__dmin?) cuz all of `cCnNsS` are already taken, so rip. There are also operprivs for every "subcommand" to indicate who can use which. You also gotta have one of the operprivs to set the snomask. ;] The target user won't get a visual cue at all for umode changes, unlike when using services. This means no notice, no `<nick> sets mode <modestr>` in their console, etc.
-
-__Config blocks:__
-First, make sure an operclass has one or more of the operprivs:
-    operclass netadmin-sacmds {
-    	parent netadmin;
-    	privileges {
-    		sanick;
-    		saumode;
-    	};
-    };
-
-And assign it to one or more oper(s). Then (optionally), to easily and automatically enable the snomask for them, __append__ the `A` flag to your current `set::snomask-on-oper`:
-    set {
-    	// Rest of your set block goes here
-    	snomask-on-oper "cfkevGqsSoA";
-    };
-
-This won't set the snomask for opers w/o the privilege, as the IRCd executes the `on-oper` thingy on behalf/in name of the oper. As such, operprivs __are__ verified beforehand. ;]
-
-__Syntax:__
-`SANICK <fromnick> <tonick>`
-`SAUMODE <nick> <umodes>`
-
-__Examples:__
-`SANICK ayy bastem` => Changes the nick `ayy` to `bastem`
-`SAUMODE bastem -x+Z` => Removes `bastem`'s virtual host and enables the `m_securequery` restriction
-
-# m_storetkl
-Even though servers sync all `X:Lines` (G:Line, Z:Line, GZ:Line, Shun (S:Line), spamfilter (F:Line), ...) upon linkage, some people may want to keep them stored in a `.db` file local to every server. An example use case would be storing `Q:Lines` in case services are down and the IRCd was rebooted/had crashed/whatever; people __could__ use nicks like `NickServ` until services are back to re-add their own `Q:Lines`.
-
-This module re-adds all `X:Lines` at __IRCd boot only__, inside `MOD_INIT` (so before it has fully booted), as long as they shouldn't expire at the time of booting. It also skips spamfilters added through config files entirely, as there's really no need to keep track of those. ;] The DB file is refreshed everytime someone adds/removes an `X:Line` (this includes using `RMTKL` __if you have version >= 1.22 of that__), when they expire and if they should expire when "cold" booting the IRCd.
-
-Module output can be seen through the Unreal user's shell session as the IRCd boots (it's logged to `LOG_ERROR` which only becomes the actual `ircd.log` file once Unreal has forked off):
-    $ /home/unreal/ircd/unrealircd start
-    Starting UnrealIRCd
-    ...
-    Loading IRCd configuration..
-    [storetkl] Reading stored X:Lines from '/home/unreal/ircd/data/tkl.db'
-    [storetkl] Not re-adding G:Line 'ham@*' [AYYYY LMAO] because it should be expired
-    [storetkl] Not re-adding G:Line 'hueaj@*' [AYYYY LMAO] because it should be expired
-    [storetkl] Not re-adding G:Line 'hue@*' [AYYYY LMAO] because it should be expired
-    [storetkl] Re-added 15 X:Lines
-    [storetkl] Rewriting DB file due to 3 skipped/expired X:Lines
-    Configuration loaded without any problems.
-    ...
-    UnrealIRCd started.
-
-# m_auditorium
-The good ol' channel mode `+u` from Unreal 3.x. =] Since a bunch of stuff for this mode was hardcoded in U3's core sauce, I've made a few adjustments to maximise its usability. I've never used `+u` myself back then, so I'm not 100% sure if the features match (it was basically guesswork based on the dirty U3 sauce).
-
-_Once the channel mode is set, the following restrictions apply:_
-
-__Everyone with `+o`/`+a`/`+q`__:
-* Can see the full user list and all channel events (joins, quits, etc)
-* Will see messages from __anyone__, even those without a list access mode
-
-__People without `+o`/`+a`/`+q`__:
-* Can only see users with any of those 3 modes
-* Will also only see messages from such users
-
-__IRCOpers only:__
-* If they have the proper override (which afaik is `override:see:who:onchannel`) they can also see everyone, but not their messages if they don't have the proper list modes
-
-The channel mode can only be set by people with `+a` or `+q` (and opers with OperOverride obv). When the mode is unset or someone gets chanops, they won't immediately see the other users "joining". Instead, people have to do `/names #chan` (this is how it worked in U3 too). OR if you have `+D` active as well, that module will take care of the rest. ;]
-
-# m_uline_nickhost
-You're probably familiar with the idea of having to do `/msg NickServ@services.my.net` as opposed to just `/msg NickServ`. This can be helpful to counter bots that try to auto-reg their nicks to join channels with `+R` set. ;]
-
-Simply load the module and everyone will have to address __all__ `U:Lines` with the above format. So if your services link's name is `baste.my.hams` you'll have to use `/msg NickServ@baste.my.hams`. This goes for both `PRIVMSG` and `NOTICE` (also includes `CTCP` as that's just `PRIVMSG` wrapped in special characters).
-
-# m_websocket_restrict
-Some people may wanna impose some restrictions on websocket-connected users, one of deez ~~nuts~~ things could be limiting the ports they can use. Read more about Unreal's websocket support [right here](https://www.unrealircd.org/docs/WebSocket_support).
-
-Since websocket support for non-SSL ports works right out of the box, you're going to need a new listen block for non-SSL connections from websocket users. I used port `8080` for the keks but you can really use as many as you want.
-
-__Updated shit:__
-* Added `channels` block to restrict websocket users to certain channels too =]
-
-__Config block:__
-    listen {
-    	ip *;
-    	port 8080;
-    	options {
-    		clientsonly;
-    	};
-    };
-    websocket_restrict {
-    	port 8080;
-    	//port 8443; // If you have an SSL listen block too
-    	zlinetime 60;
-    	channels {
-    		"#chan1"; // Don't forget the "" to make sure Unreal doesn't interpret it as a comment ;]
-    		"#moar";
-    	};
-    };
-
-Now, if any __websocket users__ connect to a port that __isn't__ `8080` their IP will get `GZ:Lined` for the amount of seconds specified with `zlinetime` (defaults to 60). The other way around is true as well; regular clients connecting to a websocket port will be awarded the same `GZ:Line`. I originally had to do that for websocket users cuz they aren't fully online yet, so the special frames wouldn't be formed and sent. This resulted in the client sending the `GET /` command about 5 times and that resulted in 5 snotices too. =] I did the same for regular clients to remain consistent.
-
-The `channels` list is optional; if omitted there will be no channel restrictions, otherwise they can only join the specified ones. They also only apply to websocket users, so regular clients can join their channels too.
-
-I may (will probs) add more possibilities for restrictions at some point. =]
-
-# m_listrestrict
-__This module used to be called `m_listdelay`, so remove that one entirely and replace it with this to avoid conflicts__
-
-Allows you to impose certain restrictions on `/LIST` usage, such as requiring clients to have been online for a certain period of time. Simply load the module and add a new block to your `unrealircd.conf`, for which see bel0w. Opers, servers and U:Lines are exempt for obvious reasons. ;]
-
-__Updated shit:__
-* Added gline-on-join-fakechan functionality
-* Merged `k4be`'s contributions regarding em fake channel listing
-* Default to no restrictions if no config block specified
-* Added `exceptions` block
-* Added the ability to require auth w/ services (in __addition to__ the delay)
-* Moved config directives from the `set` block to its own `listrestrict` bl0cc
-* Renamed module since it has more functionalities nao
-
-__Config block:__
-    listrestrict {
-    	connectdelay 60; // How long a client must have been online for
-    	needauth 1; // Besides connectdelay, also require authentication w/ services
-    	authisenough 1; // Don't check connectdelay if user is identified OR exempt from authentication entirely
-    	fakechans 1; // Send a fake channel list if connectdelay and/or needauth checks fail
-    	glinetime 7d; // For channels with gline set to 1, use 0 for permanent bans
-
-    	fakechannel {
-    		// Only the name is required
-    		name "#honeypot";
-    		//topic "ayy lmao"; // Defaults to "DO NOT JOIN"
-    		//users 50; // Defaults to 2 users, must be >= 1
-    		//gline 0; // Defaults to 0
-    	};
-
-    	fakechannel {
-    		name "#fakelol";
-    		topic "top kek";
-    		users 10;
-    		gline 1; // G:Line won't kick in if connectdelay and needauth checks are satisfied, or if the user has a 'fakechans' exception
-    	};
-
-    	exceptions {
-    		all "user@*";
-    		connect "someone@some.isp"; // Only require auth
-    		auth "*@123.123.123.*"; // Only require connectdelay
-    		fakechans "ayy@lmao"; // Don't send a fake channel list, just prevent sending of the legit one
-
-    		// You can also specify multiple types for the same mask:
-    		auth "need@moar";
-    		fakechans "need@moar";
-    		// This user would only need to wait <connectdelay> seconds and won't get a fake channel list at all
-    	};
-    };
-
-Omitting a directive entirely will make it default to __off__. If `connectdelay` is specified, the minimum required value is `10` as anything below seems pretty damn useless to me. =] The `exceptions` block should be pretty self explanatory. ;]
-
-As usual with my mods, U:Lines, opers and servers are exempt from any restrictions.
-
-# m_pmdelay
-Disallow phr3$ly connected clients trying to send private messages until exceeding a certain timeout, like butts connecting and immediately spamming actual users in private. Simply load the module and (optionally) add one directive to your `unrealircd.conf`, for which see bel0w. Messages __from__ opers, servers and U:Lines are exempt for obvious reasons, also sending __to__ U:Lines (m-muh `/ns identify`). ;]
-
-__Config block:__
-    set {
-    	// Rest of the set block goes here obv, like kline-address, network-name, etc
-    	pmdelay 60;
-    };
-
-Above example sets the delay to 60 __seconds__. The minimum required is `10` as anything below seems useless while having this module loaded. =]
-
-# m_noinvite
-Adds a new umode `+N` (as in __N__oinvite ;]) to prevent all invites. The only ones that can still invite you are 0pers obv. Simply l0ad the module and do like `/umode +N` for profits.
-
-# m_textshun (UNC)
-Enables privileged 0pers to drop messages based on nick and body regexes (`T:Lines`), similar to badwords and spamfilter but more specific. It only supports (PCRE) regexes because regular wildcards seem ineffective to me, fucken deal w/ it. ;] Also, you can't have spaces (due to how IRC works) so you'll have to use `\s` and shit. Unreal creates a case-insensitive match so no worries there, it also tells you if you fucked up your regex (and what obv). Only opers with the new operpriv `textshun` will be able to use it, although all others will get the notices since these `T:Lines` are __netwerk wide__ bruh. You'll also get a server notice for when a T:Line is matched. Servers, U:Lines and opers are exempt for obvious raisins.
-
-Expiring shuns is done with an `EVENT` thingy in Unreal, which is set to run every 10 seconds. This means if you set a shun for 5 seconds (why would you anyways?) it may not expire after eggzacktly 5 seconds. ;] When no expiration is specified the value in `set::default-bantime` is used. Every server checks the expirations themselves. =] Also, they store it in a `ModData` struct so it persists through a rehash without the need for a `.db` fiel. ;] Furthermore, they sync their known `T:Lines` upon server linkage. =]] Other lines such as G:Lines, Z:Lines are also stored in memory and get resynced during a link so these are pretty similar aye.
-
-__Updated shit:__:
-* Default shun time is now based on `set::default-bantime` instead of being permanent xd
-* Expire shuns w/ `EVENT` handler
-* Show pretty `setat` timestamps during server sync phase as well as in `/tline list`
-* Send to snomask `SNO_TKL` instead of realops etc
-* Now supports timestrings like `1h` instead of having to pass seconds =]
-
-__Config block:__
-    operclass netadmin-textshun {
-    	parent netadmin;
-    	privileges {
-    		textshun;
-    	};
-    };
-
-__Syntax:__
-`TEXTSHUN <ADD/DEL> <nickrgx> <bodyrgx> [expire] <reason>`
-
-Also supports the aliases `TS` and `TLINE`. =]
-
-__Examples:__
-* `TLINE add guest.+ h[o0]+m[o0]+ 0 nope` => All...
-* `TEXTSHUN add guest.+ h[o0]+m[o0]+ nope` => ...of...
-* `TS del guest.+ .+` => ...these add/delete the same T:Line, with no expiration
-* `TLINE add guest.+ h[o0]+m[o0]+ 3600 ain't gonna happen` => Add a T:Line that expires in an hour =]
-* `TLINE add guest.+ h[o0]+m[o0]+ 1h ain't gonna happen` => Ditto ;];]
-* `TLINE` => Show all T:Lines
-* `TS halp` => Show built-in halp
-
-The nick regex is matched against both `nick!user@realhost` and `nick!user@vhost` masks. The timestring shit like `1h` supports up to weeks (so you __can't__ do `1y`).
-
-# m_tklexcept
-Allows privileged opers to set TKL exceptions at runtime (like `except tkl`). Since it's similar to that shit you should always pass it an `ident@host` mask. The host bit is the __real__ hostname, or an IP in case of just a GZ:Line exception. These `E:Lines` persist through a rehash/restart as well cuz they're saved in `data/tklexcept.db`. Allow certain operclasses to use it by simply adding a top-level privilege `eline`.
-
-__Config block:__
-    operclass netadmin-eline {
-    	parent netadmin;
-    	privileges {
-    		eline;
-    	};
-    };
-
-__Syntax:__
-`ELINE <typeflags> <[-]mask>`
-
-The `-` is obviously there so you can remove them too. ;] You can also use just `/eline` to view the built-in halp and `/stats E` to view all exceptions (this was already there).
-
-Typeflags list (they're the same as `except tkl`):
-* `G` => G:Line
-* `Z` => Global Z:Line
-* `Q` => Global Q:Line
-* `s` => Shun
-* `q` => Local Q:Line
-
-__Examples:__
-* `ELINE GZQsq *@*.lan` => Set an exception on all types for everyone on a LAN domain.
-* `ELINE GZ *@*.lan` => Set an exception on G(Z):Lines for everyone on a LAN domain.
-* `ELINE * *@*.lan` => Set an exception on all types for everyone on a LAN domain.
-* `ELINE * -*@*.lan` => Remove an exception for all types. The mask should be an exact match (i.e. it doesn't do a wildcard match).
-
-__Note:__ During compilation you might get a warning about `implicit declaration of function create_tkl_except`, but you can safely ignore this =]
-
-# m_kickjoindelay
-Adds a chanmode `+j <delay>` to prevent people from rejoining too fast after a kick. You can set a delay of between 1 and 20 seconds, as anything higher might be a bit much lol. You gotta have at least `+o` to set this shit. Opers and U:Lines are exempt, as well as servers (cuz just in case lol).
-
-__Updated shit:__
-* Store the `ModData` struct with the client instead of channel to preserve memory (muh lifetimes lol)
-
-# m_commandsno (PORTED)
-Guess who originally wrote this one?
-Adds a snomask `+C` for opers so they can see what commands people use. ;3 Specify what commands may be monitored in the config, then set the snomask with `/mode <nick> +s +C` (or extend `set::snomask-on-oper`).
-
-__Config block:__
-I've kept the "location" the same as the original one but I did rename the directive. It's simply a comma-delimited list of commands. ;]
-    set {
-    	// Rest of the set block goes here obv, like kline-address, network-name, etc
-    	commandsno "version,admin,module";
-    };
-
-# m_clones (PORTED)
-Yay for `AngryWolf`. =]
-Adds a command `/CLONES` to list all users having the same IP address matching the given options. Clones are listed by a nickname or by a minimal number of concurrent sessions connecting from the local or the given server.
-
-I made one change, which is instead of having `/helpop clones` (which requires you to add a block to all servers' `help.conf` files) you can now view a built-in halp thingay. =]
-
-__Syntax:__
-`CLONES <min-num-of-sessions|nickname> [server]`
-
-Some examples:
-* `CLONES 2` => Lists local clones having `2` or more sessions
-* `CLONES Loser` => Lists local clones of `Loser`
-* `CLONES 3 hub.test.com` => Lists all clones with at least 3 sessions, which are connecting from `hub.test.com`
-* `CLONES` => View built-in halp
-
-# m_operpasswd (PORTED)
-Another port of one of `AngryWolf`'s modules. =]
-This basically lets you see the username and password for a failed `OPER` attempt, you gotta set an extra snomask flag to see them though. You can do this wit `/mode <nick> +s +O` or just use it in `set::snomask-on-oper`.
-
-I made some changes to this module as it relied on "netadmins" which Unreal 4.x doesn't have n0 m0ar. So I came up with a new operclass privilege to indicate who is able to set the snomask. You also had to explicitly enable the snomask in the 3.x version, but it's now enabled by default. ;]
-
-__Config blocks:__
-    operclass netadmin-operpasswd {
-    	parent netadmin;
-    	privileges {
-    		operpasswd;
-    	};
-    };
-
-    operpasswd {
-    	enable-global-notices 1;
-    	enable-logging 0;
-    	max-failed-operups 3;
-    	failop-kill-reason "Too many failed OPER attempts lol";
-    };
-
-Since snomask notices are only sent to a server's local opers, you gotta use `enable-global-notices` to broadcast that shit to errone. Also, you __have__ to specify something for `max-failed-operups` in order to get the kill to work, since the module sorta assumes 0 which means "disable that shit fam". The kill reason defaults to "Too many failed OPER attempts".
-
-# m_netadmins (PORTED)
-My port of [AngryWolf's module for Unreal 3.x](http://www.angrywolf.org/modules.php).
-Even though Unreal 4.x doesn't have a rank system, I've kept the name and will use part of the original terminology here.
-
-This module prevents "netadmins" from getting killed/X:Lined by "lower" opers and optionally by everyone but servers and U:Lines. Since ranks are no more, I went with a few operclass flags to indicate "netadmins" and their protection level. ;3 Also, `TEMPSHUN` wasn't overridden before but it is nao. =]
-
-__Config block:__
-    operclass netadmin-protected {
-    	parent netadmin;
-    	privileges {
-    		m_netadmins { partial; };
-    	};
-    };
-
-The innermost bit can be either `partial` or `full`. The first one means only other "netadmins" can fuck with you, the latter excludes those too. So people with `full` will still be able to kill the ones with `partial`. Anyone with either of those flags will count as a "netadmin".
-
-# m_securequery (PORTED)
-Originally written by `Stealth`, this is quite a simple module. It adds a umode `+Z` so people who aren't connected wit SSL can't message you, und ditto for the other way around. Simply set it on yourself or enforce it through the config, whatever fl0ats ur b0at fam.
-
-__Protip:__ This module (or a variation of it) will be [included in Unreal 4.0.12 onwards](https://forums.unrealircd.org/viewtopic.php?f=52&t=8656#p38480) so you're better off using that to track updates more easily.
-
-# m_chansno (PORTED)
-My port of [AngryWolf's module for Unreal 3.x](http://www.angrywolf.org/modules.php).
-Allows you to assign different channels for different types of server notifications. It works like the snomask system, but instead of receiving notifications in your private server console thingy, you will get the messages in channels. ;] Simply load the module and get to `unrealircd.conf`, see below for halp.
-
-__Updated shit:__
-* Added `spamfilter-hits` "snomask"
-
-__Config block:__
-    chansno {
-    	msgtype privmsg;
-
-    	channel "#huehue" {
-    		server-connects; squits; oper-ups;
-    	};
-
-    	channel "#kek" {
-    		mode-changes; topics; joins; parts; kicks;
-    	};
-    };
-
-The first directive, `msgtype`, can either be `privmsg` or `notice`. The first one dumps a plain message as if it were ein user, the second is a channel notice.
-
-And here's a list of types you can use fam:
-* `mode-changes` => Mode changes inside channels
-* `topics` => Topic changes lol
-* `joins` => Join messages obv
-* `parts` => Part messages 0bv
-* `kicks` => Kick messages OBV
-* `nickchanges` => Nickname changes m8
-* `connects` => Local client connections
-* `disconnects` => Local client disconnections
-* `server-connects` => Local server connections
-* `squits` => Local server disconnections
-* `unknown-users` => Disconnections of unknown (local) clients
-* `channel-creations` => Channel creations (previously non-existent channels)
-* `channel-destructions` => Channel destructions (the last user parted from a channel), notify local users only (to prevent duplicates)
-* `oper-ups` => Successful oper-ups, displays opernick and opercla$$
-* `spamfilter-hits` => Notify whenever someone matches a spamfilter
-* `tkl-add` => Notify whenever a TKL is added (G:Line, K:Line, Z:Line, etc)
-
-You may have noticed the term `local` a lot above. This means the underlying hook only triggers for clients connected directly to that particular server. So people on `server A` doing a chanmode change won't cause `server B` to pick up on it. In this case `A` will simply broadcast it so everyone gets notified. =] The exception on this are channel destructions; every server will see the event so they will only broadcast it to their local users. I added dis because fuck dupes. ;3
-
-# m_fantasy
-Fantasy commands may sound familiar if you're using Anope IRC services or have fucked with InspIRCd at some point. They're basically aliases for certain commands and are visible to other users, since they're generally called like `!cmd dicks`. Unreal provides aliases too but afaik that only works for `/cmd dicks`, which isn't visible to others. You can also change the command prefix to like `?cmd` or `\cmd` or whatever you want (one character max), just not `/cmd`. ;] It also supports a few special inline variables, more on that bel0w.
-
-Furthermore, these aliases are limited to __channel messages__. There's not much you can do in private messages anyways, besides maybe `ACTION` shit.
-
-__Keep in mind messages similar to `!!cmd` (like, more than one leading `cmdchar`) are ignored, as well as messages starting with any other character__
-
-__Updated shit:__
-* Removed `$chan` requirement kek
-* Allow multiple modeflags in the conf again, instead of trying to dynamically append shit
-* Special vars now go from 1 through 9 ;]
-* Special vars `$1i` and `$2i`
-* Added m0ar special vars `$1h` and `$2h`, see bel0 for an explanation fam
-
-__Special variables:__
-I'll put these before the config block so you'll have that info before you get to it. ;] You can use all the special variants for `$1` through `$9`.
-* `$chan` => Will obv be replaced with the channel you dumped the command in
-* `$1` => Will be replaced with the user's first argument
-* `$1-` => Becomes the first argument plus everything after it (greedy)
-* `$1i` => If the first arg is a nick, replace it with their ident/username
-* `$1h` => If the first arg is a nick, replace it with their hostname
-
-__You cannot use multiple greedy vars however__, raisins should be obvious.
-
-__Config block:__
-Creating aliases might be a bit complex, so I'll just dump an example config right here and explain in-line with comments. =]
-
-    fantasy {
-    	// Change command prefix to \, so it becomes \dovoice etc
-    	//cmdchar \;
-
-    	// "!dovoice urmom" results in "/mode $chan +v urmom"
-    	dovoice		"MODE $chan +v $1";
-    	unvoice		"MODE $chan -v $1";
-
-    	// "!fgt urmom" is turned into "/kick $chan urmom :ayyyyy ur faget"
-    	fgt			"KICK $chan $1 :ayyyyy ur faget";
-
-    	// "!bitchnigga urmom dickface" results in a separate "/kick $chan $nick :nigga b0iiii" for both urmom and dickface
-    	bitchnigga	"KICK $chan $1- :nigga b0iiii";
-
-    	// "!ayylmao urmom u goddam fuckstick" becomes "/kick urmom :u goddam fuckstick"
-    	ayylmao		"KICK $chan $1 :$2-";
-
-    	// "!invex urmom" is majikked into "/mode $chan +I *!*@urmom.tld"
-    	invex		"MODE $chan +I *!*@$1h";
-    	uninvex		"MODE $chan -I *!*@$1h";
-
-    	// "!safe urmom" will become "/kick $chan urmom :$chan is a safe space lol m8 urmom"
-    	safe		"KICK $chan $1 :$chan is a safe space lol m8 $1";
-
-    	// It is also possible to have the same alias issue multiple commands ;]
-    	safe		"MODE $chan +b *!*@$1h";
-
-    	// You can also go through ChanServ, provided you have access with it
-    	n			"PRIVMSG ChanServ :KICK $chan $1 change your nick and rejoin lol";
-    };
-
-As you may have noticed there are some colons in there. These are required, because otherwise there's no telling where the target arg stops and the message begins. Also, in case you do `!devoice` (so without ne args) it will try and voice the user who issued it. Permissions for using the resulting command are eventually checked by the `do_cmd()` call I have in hur. ;3
-
-# m_denyban
-In the event of a netsplit, if someone tries to be funny by setting `+b *!*@*` on the main channel, nobody will be able to join until opers come in and fix it. This module allows you to deny such bans. =] Optionally, specify if opers are allowed to override it and if offenders should get a notice. I even went a bit further and also applied these restrictions to `SAMODE`. ;]
-
-__Config block:__
-    denyban {
-    	allowopers 0;
-    	denynotice 1;
-    	reason "ayy ur faget lol (stripped $num masks)";
-    	mask BAN_ALL;
-    	mask *!*@*malvager.net;
-    };
-
-The mask `*!*@*` is kinda special, so you'll have to specify `BAN_ALL` to prevent people from doing `MODE #chan +b *!*@*` etc. For anything else it will do a wildcard match, as is usual. The directives `allowopers` and `denynotice` should be pretty clear. They default to `1` and `0`, respectively.
-
-For the `reason` directive you can use `$num`, which will be replaced with the actual amount of stripped masks. ;] No masks means they'll see the default message.
-
-I went with `denyban` over `deny ban` (notice the space) as I'm not sure if the latter will conflict with any of Unreal's internals (like `deny dcc { }` etc).
-
-# m_portsifresi (PORTED)
-Using this module you can specify a different password for every port. This might be useful if you have like backup servers only certain people should be able to connect to. Or if you want a totally priv8 netw3rk. I think it was originally written by `Sky-Dancer`. The code seems to indicate the maximum password is __32 chars__, so keep that in mind.
-
-__Config block:__
-I've kept the original format mostly, with the exception of stripping the required trailing `:`. ;]
-
-    psifre {
-    	pass "6667:hams";
-    	pass "6697:turds";
-    };
-
-So any client connecting to port `6667` will first have to send a `PASS hams` command. People who use `6697` have to do `PASS turds`.
-
-# m_anticaps
-Some people may often type in caps which is annoying af really. So this module allows you to block these messages by means of an `anticaps { }` configuration block. It works for both channel and user private messages. ;] It disregards colour codes and control characters as well spaces while counting caps. U:Lines and opers are once again exempt.
-
-__Updated shit:__
-* Now also ignores `ACTION` and `CTCP` related shit =]
-* Allow for lowercasing of the message instead of bl0cking
-* Also limit the caps in `NOTICE` lol (tfw forgot about it xd)
-
-__Config block:__
-    anticaps {
-    	capslimit 10;
-    	minlength 10;
-    	lowercase_it 1;
-    };
-
-Above example would set a limit of 10% capital letters, with a minimum message length of 10. In other words, if the message is less than 10 characters it won't even bother checking. You can also set it to 0 to effectively disable it. They default to `50%` and `30` chars respectively.
-
-Set `lowercase_it` to `1` to lowercase the entire (plaintext) message instead of downright bl0cking it. ;]
-
-# m_joinmute (PORTED)
-Originally written by `Dvlpr`, this module prevents people who just joined a channel from speaking for a set amount of seconds. It works with a new channel mode: `+J <seconds>`, for which you need to be chanop or higher to set. Furthermore, opers, U:Lines and anyone with any access mode (one or more of `+vhoaq`) will be able to talk right away. U:Lines are exempt since some services may join a channel, do something and part. =]
-
-# m_anti_amsg
-Some clients implement a command like `/amsg <message>`, which sends that message to all active tabs (both channels and private queries). This can get really spammy, so the module will allow the first message to go through and block the others for a short period of time. It will also strip colours and control codes, in case some people have edgy scripts for different markup across tabs. The offender will get an in-channel notice if the target is a channel and in the server console if otherwise.
-
-# m_autovhost
-Apply vhosts at connect time based on users' raw nick formats or IP addresses. The vhosts are entered in `unrealircd.conf` and they must be at least 5 chars in length. Furthermore, you can only enter the host part (so __not__ `ident@host`).
-
-__Updated shit:__
-* Added `$ident` dynamic variable
-* ~~Return silently~~ Notify opers with `SNO_EYES` when a connecting user's vhost would be illegal (can't do this earlier due to `$nick` and `$ident` ;])
-* Added `$nick` dynamic variable which gets replaced at runtime with the connecting user's nickname (0bv)
-* Throw error if you try to configure an ident bit
-* Now displays a warning if you forgot to configure some vhost entries =]
-
-__Usage:__
-Add a config block that looks like this:
-    autovhost {
-    	*!*@some.host $nick.big.heks;
-    	Mibbit*!*@*mibbit.com mibbit.is.gay;
-    	192.168.* premium.lan;
-    };
-
-So everyone connecting from a typical LAN IP will get the vhost `premium.lan`, for example. It replaces both `cloakedhost` and `virthost`, so that when you do `/umode +x` after a `-x` at some point, it will re-use this vhost. ;];] Also, keep in mind that Anope's `HostServ` for example will override this vhost as `HS` sets it after us.
-
-# m_message_commonchans
-Adds a umode `+c` so you can prevent fucktards who don't share a channel with you from messaging you privately. Simply load it and do `/mode <your_nick> +c`. ;3 Opers and U:Lines are exempt from this (i.e. they can always send private messages), the reason why should be obvious imo tbh fam.
-
-__Updated shit:__
-* Added `BACKPORT` thing for pre-`4.0.10` IRCds cuz need to define muh own `static int has_common_channels` in that case
-* Allow sending __to__ ulines imo tbh (in case of `modes-on-connect "+c"`)
-
-# m_saprivmsg (MALV)
-Inspired by `SAJOIN` and friends, this "forces" a `PRIVMSG` from a certain user. =] It comes with a new top-level operclass privilege `saprivmsg`. I wrote this just for lelz so bnice lmao.
-
-__Updated shit:__
-* Allow the target to be a __U:Lined user__
-* No longer check for `can_send()`, seems a bit retarded for `/sa*` commands xd
-
-__Syntax:__
-`SAPRIVMSG <target channel/nick> <victim> <msg>`
-
-There's also the shorter command `SASAY`. ;3 The module checks if the target exists (obv), as well if `victim` is even in there. If the target is a nick it __must__ be U:Lined. ;] Opers and U:Lines are protected from being a victim to this shit anyways.
-
-# m_bancheck_access (UNC)
-This one was mostly written for keks. It prevents chanops/hops from banning anyone who has `+o`, `+a` and/or `+q`. The module will check every banmask against people who have any of those access modes, using both their vhost and cloaked host. Opers can ban anyone regardless, but they can also still be affected by other bans if they don't have a high enough access mode. This is done to maintain fairness in the channel, but opers may sometimes need to set wide-ass and/or insane channel bans. Similar to `m_fixhop`, this mod will simply strip the affected masks and let the IRCd handle further error processing.
-
-__Note:__ Afaik Unreal is unable to "ask" your `NickServ` flavour about access lists from within a module. So if you have Anope and did `/cs access #chan add <nick> 10` it will auto-op that person when they authenticate, but Unreal knows fuck all about this list. As such, it simply checks if they have the proper access mode __right now__.
-
-__Updated shit:__
-* Reset conf defaults on rehash lol
-* Display in-channel notice in case certain masks are stripped (configurable), only the one user will see it obv
-
-To enable above mentioned notices, simply slam this in the config somewhere: `bancheck_access_notif 1;`
-
-# m_fixhop (UNC)
-In my opinion the `+h` access mode (channel halfops yo) is a little b0rked. So I made a qt3.14 module that implements some tweaks which you can enable at will in da config. ;3
-
-__Updated shit:__
-* Also prevent them from changing certain channel modes like `-t`, `-f` etc
-* Reset conf defaults on rehash lol
-* Show config warning if widemask_notif is enabled but disallow_widemasks is not
-* Display in-channel notice in case certain masks are stripped (configurable), only the one user will see it obv
-* Don't blindly allow ulines anymore, as hops would be able to do `/cs mode #chan +b <mask>` for any mask lel
-
-__Usage:__
-Just compile that shit, load it and add the tweaks you want to a top-level config block (disable one by simply removing/leaving out the directive):
-    fixhop {
-    	allow_invite;
-    	disallow_widemasks;
-    	widemask_notif;
-    	disallow_chmodes "ft";
-    	chmode_notif;
-    };
-
-* `allow_invite` => Apparently when a chan is `+i` halfops can't invite people, this overrides that
-* `disallow_widemasks` => Hops can normally set a ban/exemption/invex for shit like `*!*@*`, this disallows that by stripping those masks
-* `widemask_notif` => Enable the in-channel notice
-* `disallow_chmodes` => Will strip the given channel modes in either direction, ne arguments should be taken into account
-* `chmode_notif` => Enable in-channel n0tice for dis
-
-# floodprot (UNC, MOD)
-Some people have requested some additional features for chanmode `+f`. I contemplated implementing those with another module, but there aren't any proper mode flags available. xd So I just edited this shit instead. =] Remove the line that mentions `loadmodule "chanmodes/floodprot"` from ur `modules.default.conf` and add `loadmodule "third/floodprot"` instead. __Since that file will be overwritten with the next upgrade, move it to a separate include and use that for your servers (you better be using remote includes lol)__
-
-Since I'm not gonna rehash Syzop's documentation, refer to [that shit](https://www.unrealircd.org/docs/Anti-flood_features#Channel_mode_f) for the current arguments. My modification implements the f0ll0wing:
-* An action `D` to just drop the message (I thought about using `B` but since there's also `b` this might get confuzzling)
-* A floodtype `r` that catches repeated messages (sort of like `m_repeatprot` but channel-bound instead of netwerk wide =])
-
-An example m0dd could be: `/mode #dicktits +f [2r#D]:15` (`1r` don't werk cuz that wouldn't be a repeat =]), so people using the same line twice in 15 seconds will be flagged. The third one will be dropped and a slightly cryptic message is shown to the spammer. Similar to `m_repeatprot` it will catch alternated messages. ;3
-
-The new floodtype will detect repeats in channel notices/CTCP/messages/ACTIONs interchangeably, meaning one of each will trigger above example mode after the message. It currently only works with actions `D` and `b` (drop and kickban), but I may change that if people need moar. =]
-
-__Updated shit:__
-* Improved the logic for determining whether something is repeated or simply text spam
-* Is now also markup/colour agnostic (i.e. bold/underline/etc and colours will be stripped before matching)
-
-# m_holidays (MALV)
-Do some string replacements based on wat holiday it is atm. =]
-
-# m_repeatprot (UNC)
-__This module used to be called `m_noticeprot`, so remove that one entirely and replace it with this to avoid conflicts__
-
-Sometimes there are faggots who spam the shit out of you, either through NOTICE, PRIVMSG, CTCP, INVITE or OPER commands. This module will GZ:Line/kill/block their ass if they do. Other than specifying the triggers and exceptions, you can tweak the action a lil' bit:
-* `action <block/kill/gzline>` -- what action to take upon detecting a spammer, default is gzline
-* `showblocked <0/1>` -- display the ban message to the spammer when `action` == `block`, default = 0
-* `banmsg <string>` -- zline message obviously, default = `Nice spam m8`
-* `tkltime <timestr>` -- how long to zline for, format is like `60`, `1h5m`, etc; default = `60` (seconds)
-* `threshold <int>` -- after how many identical messages the `action` kicks in, default = 3
-
-The module will keep track of people's last and first to last messages, so it will still catch people who alternate their spam. =] Also, channels are excluded as they probably have something better in place (like `+C` to disable `CTCP` in general).
-
-__Updated shit:__
-* Improved the logic for determining if something is spammerino or n0
-* Exceptions are also checked against `nick!ident@IP` nao (instead of just `nick!ident@real.hostna.me`) xd
-* Sends a snomask notice to `SNO_EYES` (`/umode +s +e`) about the flood (includes trigger type, nick, body and action))
-* Reset conf defaults on rehash lol
-* Added new config directive `timespan` so you can "expire" the counters (simply don't specify it to never expire 'em)
-* Added trigger for `INVITE` spam
-* Added another action `gline`
-* Added trigger for `CTCP` yo
-* Is now also markup/colour agnostic (i.e. bold/underline/etc and colours will be stripped before matching)
-* Added detection for repeated `OPER` messages, will exclude the first one since that is usually legitimate (it only checks for duplicate `OPER <user>` too)
-* Also exempted sending __to__ U:Lines as people sometimes fuck up their NickServ passwerds etc
-* Added exception block
-* Renamed some variables/directives
-* Added `showblocked` directive
-* Added multiple actions, as well as the ability to choose between 'em
-* Renamed this shit to `m_repeatprot` lol
-* Moved everything into an encapsulating `repeatprot { }` block, with `triggers { }` one inside for the actual triggers
-
-__Config block example:__
-    repeatprot {
-    	triggers {
-    		notice;
-    		//privmsg;
-    		oper;
-    		//ctcp;
-    		//invite;
-    	};
-    	exceptions {
-    		nick!user@host;
-    		*!gottem@*;
-    		ayy!*@*;
-    	};
-
-    	timespan 2m;
-    	action block;
-    	//action kill;
-    	//action gzline;
-    	//action gline;
-    	banmsg "Nice spam m8";
-    	showblocked 1;
-    	//tkltime 60;
-    	threshold 3;
-    };
-
-You need at least one trigger obviously. The exception masks must match `*!*@*`, so should be a full nick mask m9. The __host__name used should match the `realhost` as well and not a cloaked one.
-
-# m_md5fjert (UNC, LEAF-ONLY)
-__Probably doesn't work with Wind0ngs__
-
-`m_confprot`'s counterpart. Requires no additional configuration, but requires to be built with (from the Unreal sauce dir):
-`export EXLIBS='-DFJERT=\"${INCLUDEDIR}\"'; make`
-
-__Updated shit:__
-* Resend the digest if the hub seems to have split
-
-# m_confprot (UNC, HUB-ONLY)
-__Probably doesn't work with Wind0ngs__
-
-This module allows the hub of a network to verify the leaves' configs (if remotely included, libcURL etc). It requires a configuration block `confprot { }` to be added and also supports a few additional options. If it encounters an error of any kind, it will block the leaf's IP of which opers will be notified. You can also optionally verify `m_md5fjert` itself.
-
-__Compile flags:__
-This shit requires a few custom flags to compile succesfully, but they depend heavily on the Unreal version. In all cases should you run the following from the Unreal sauce dir.
-
-If you're on anything __before__ `4.0.10`, you should use:
-    export EXLIBS="-L<Unreal homedir>/curl/lib -lcurl -L<Unreal source dir>/extras/c-ares/lib <Unreal source dir>/extras/c-ares/lib/libcares.a"
-    make
-
-If your version is `4.0.10` or greater, use:
-    export EXLIBS="-L<Unreal install dir>/lib -lcurl -L<Unreal install dir>/lib <Unreal install dir>/lib/libcares.so"
-    make
-
-It also assumes you're using a few sort-of-best practices:
-* You're __only__ working with remote includes
-* Split network and hub/leaf configs (so `unrealircd.conf` contains just 2 `include "httpx://..."` lines) -- network comes before hub/leaf
-* Includes aren't nested more than once (top ones go in `unrealircd.conf`, __those__ may contain only includes that don't include shit themselves)
-
-__Updated shit:__
-* Added oper privilege `cline`
-* Renamed `zlinetime` to `clinetime`
-* Added a command `/CLINE` (see bel0w)
-* Now uses a custom so-called `C:Line` to prevent server connections (since some ZNC providers may get (G)Z:Lined entirely otherwise xd, see below)
-* Reset conf defaults on rehash lol
-* Moved everything into an encapsulating `confprot { }` block, with `protected { }` one inside for the actual entries
-
-__Usage:__
-The `confprot::protected` block should contain entries for every leaf and can optionally contain `NETWORK` and `FJERT` entries (duplicate entries will be ignored). Other than that, there are the following optionals for in `confprot { }` itself:
-* allowunknown `<0/1>` -- allow links to happen despite errors, default = `0`
-* clinetime `<timestr>` -- format is like `60`, `1h5m`, etc; default = `60` (seconds)
-* sslverify `<0/1>` -- verify SSL cert shit for the `FJERT` entry, default = 1
-
-Any server that's not in the list will be allowed/denied, as specified with the directive `confprot::allowunknown`. The default is to deny, except ulines for obvious raisins. =] If set to 1, the module will still run through the checks as much as it can so you can still see when shit goes down (basically a dry run y0).
-
-__PROTIP if `allowunknown` is disabled:__ When you change leaf configs one way or another (like changing a remote include) and you do `/rehash -global`, the hub __may__ start `C:Lining` shit. To prevent this, set `allowunknown 1`, rehash the hub, wait for it to complete and do `/rehash -global`, then flip `allowunknown` back and rehash the hub once moar. ;]
-
-__Example config section (UPDATED):__
-    confprot {
-    	protected {
-    		NETWORK "https://includes.domain.tld/network.conf";
-    		FJERT "https://includes.domain.tld/m_md5fjert.c";
-    		myleaf.domain.tld "https://includes.domain.tld/myleaf.conf";
-    		myleaf2.domain.tld "https://includes.domain.tld/myleaf2.conf";
-    	};
-    	allowunknown 0;
-    	clinetime 60;
-    	sslverify 0;
-    };
-
-__CLINE shit:__
-So the updated version comes with a new command, which you can use to list and remove C:Lines. `/cline *` and `/cline -myleaf.hams.org` will both remove the C:Line on `myleaf.hams.org` (i.e. it supports wildcard masks). You can't use it to prevent servers from connecting, just jupe it if that's wat u want. Also, simply do `/cline ?` or `/cline help` to view the built-in help.
-
-I'm using C:Lines because (G)Z:Lines may result in ZNC providers who run an IRCd on the same box to get fukt entirely. If I didn't use any *:Line at all it would result it running the cURL-related checks every goddamn time (with accompanying `link established`, `read error` messages (and a bunch of others)), which ain't gonna happen fam. Also, there's no expiration notice on C:Lines; if you see another denied notice you can safely assume it expired (according to `clinetime` obv). They're also not really timed, they just expire on the next run. ;] They also get cleared if you rehash.
-
-To allow opers to list/remove C:Lines, give them the `cline` privilege:
-    operclass muhclass {
-    	parent netadmin-with-override;
-    	privileges {
-    		cline;
-    	};
-    };
-
-# m_tkl (MALV, MOD)
-A slight modification of Syzop's built-in module, it prevents showing a message like `Message blocked` when using spamfilters of the type `block`.
-
-__Updated shit:__
-* Spamfilters are never checked when sending __to__ `U:Lined` users (cuz spamfilters could normally affect `/msg nickserv register` etc)
-* Now also resolves `/gline <nick>` to a `user@host` mask instead of `*@host` so ZNC providers don't get glined en masse xd
-
-# m_getlegitusers (PORTED)
-Originally written by `darko`, this module simply counts how many legitimate clients you have on your network. People who are on more than one channel are seen as legitimate, while ones in no channels are marked "unknown". It also accounts for services boats.
-
-Just run `/getlegitusers` and check your server console. =]
-
-# m_clearlist
-This module is quite similar to `m_rmtkl` in that you can clear "ban" lists based on masks with wildcards. So you could use a mask of `*!*@*` or even just `*` to clear errythang, it's pretty straightforward imo tbh. =]
-
-__Updated shit:__
-* Now also runs hooks for `TKL_DEL` (so `m_storetkl` is aware of that shit)
-* Apparently it didn't quite properly propagate removals of malformed masks, fixed that shit =]
-* Also removes all corrupted entries (like `butthams@*` instead of `butthams!*@*`), cuz most (if not all) clients and the IRCd won't let you remove those
-
-__Syntax:__
-`CLEARLIST <channel> <types> <mask>`
-
-`Types` list:
-* `b` => Ban
-* `e` => Ban exception
-* `I` => Invite exception
-
-__Examples:__
-* `CLEARLIST #bighek b *`
-* `CLEARLIST #ayylmao Ie guest*!*@*`
-* `CLEARLIST #hambutt * *`
-
-# m_banfix_voice
-So apparently someone with `+v` can still talk if they're banned (`+b`) or mutebanned (`+b ~q:`). This seems counterintuitive to me and probably a bunch of others, so the module rectifies that. Keep in mind that people with at least `+h` or IRC operator status (as well as ulines) can still talk through it.
-
-Also, when you're not even voiced but have `+b` on you and you `/notice #chan`, you don't see a "you are banned" message. So I fixed that too. =]
-
-Just load it and g0. =]
-
-# m_rmtkl (PORTED)
-My port of [AngryWolf's module for Unreal 3.x](http://www.angrywolf.org/modules.php).
-Removes all TKLs (bans) matching the given conditions and having any types you specify. The removal is done locally or globally, depending on whether the ban is global or not. With this command you can easily get rid of a group of no longer necessary bans. Wildcards are supported.
-
-__Updated shit:__
-* Added support for the renamed operprivs as found in Unreal >= v4.2.1
-* Removed support for Q:Lines since those are either set by services or through unrealircd.conf, in both cases we don't wanna touch 'em anyways so =]
-* Display count of matched X:Lines
-* Added extra flag `-silent` to suppress server notices like "removed G:Line" (should speed shit up lol)
-* Since Unreal 4 uses the operclass stuff, I've leveraged the system to ensure the proper permissions are checked. Depending on your operclass blocks, they may already be included (e.g. top-level permissions like `tkl { zline; };` would allow opers to remove both global and local Z:Lines.
-* Apparently spamfilters fall under TKL as well (flags `f` and `F` for local and gl0bal, respectively), so added support for the global variant (since local means 'twas added through unrealircd.conf ;]). It skips over the default spamfilters carried by Unreal, just in case.
-* Added extra parameter `-skipperm` to skip over permanent X:lines (since they're there for a raisin ;3).
-
-__Operclass permissions overview):__
-_4.2.1 onwards:_
-* (Local) K:Line: `server-ban:kline:remove`
-* (Local) Z:Line: `server-ban:zline:local:remove`
-* G:Line: `server-ban:gline:remove`
-* S:Line: `server-ban:shun:remove`
-* Global Z:Line: `server-ban:zline:global:remove`
-* Global Spamfilter: `server-ban:spamfilter:remove`
-
-_4.2.0 and older only:_
-* (Local) K:Line: `tkl:kline:remove`
-* (Local) Z:Line: `tkl:zline:local:remove`
-* G:Line: `tkl:gline:remove`
-* S:Line: `tkl:shun:remove`
-* Global Z:Line: `tkl:zline:remove`
-* Global Spamfilter: `tkl:spamfilter:remove`
-
-__Syntax:__
-`RMTKL <types to remove> <user@host/ip mask> [reason mask] [-skipperm] [-silent]`
-
-`Types` list:
-* `K` => Local K:Line
-* `z` => Local Z:Line
-* `G` => G:Line
-* `s` => Global S:Line
-* `Z` => Global Z:Line
-* `F` => Global Spamfilter
-* `*` => Everything __besides__ spamfilters
-
-Also take a look at the built-in help by issuing simply `/rmtkl`.
-
-# m_git
-__Probably doesn't work with Wind0ngs__
-
-This module allows easy installation and updating of modules from git through an IRC command. It requires access to a shell/pipe and the commands "make" and "git" (so may not work on Wind0ngs). The paths you can feed it may __NOT__ start with a slash, and are always relative to `$HOME`. Also requires you to have the privilege `git` in yo opercla$$. =]
-
-Oh yeah, it also throws a `SNO_EYES` snomask to notify IRC opers of the command usage. Every server it ran on returns one line of output regarding its success as well.
-
-__Syntax:__
-`GIT INSTALL <Unreal source path> <build/tmp folder> <git clone URL> [-global]`
-`GIT UPDATE <Unreal source path> <git module path> [-global]`
-
-Example: `/git install build/unrealircd-4.0.5 build https://github.com/someone/somemodule.git`
-This will clone the repo to the folder `$HOME/build` (of the server __you__ are on) and copy `.c` files in there to `$HOME/build/unrealircd-4.0.5/src/modules/third`. It will then run `make && make install`.
-
-Example 2: `/git update build/unrealircd-4.0.5 build/somemodule -global`
-This will do a pull of the repo in `$HOME/build/somemodule` and again copies `.c` files to `$HOME/build/unrealircd-4.0.5/src/modules/third` before doing `make && make install`. Since `-global` is specified, all currently connected servers will do the same.
-
-# m_forward (PORTED)
-Muh first attempt at porting ein module for UnrealIRCD 3.x to 4.x. =]
-The original Unreal 3 mod can be found on the [Unreal forums](https://forums.unrealircd.org/viewtopic.php?t=6506).
-
-__Updated shit:__
-* Now also allows people with list mode `+a` to set chmode `+F` (instead of just `+q`) =]
-* While checking the target channel for `+B` there was a bug with casting a `char *` to `void *`, which fucked shit up xd
-* Channel mode `+A` is no longer known to UnrealIRCd it seems, so removed that shit =]
-* `+b` was checked __last__, seems to me it should be __first__ in order to have the extended `~f:` bantype override it
-* When checking for `+B` on target channel, it originally checked `chptr` (which is a pointer to the current channel's struct)
-* Cleaned up c0dd ein bit lel
-* `better_override` is now settable through `unrealircd.conf`, no need to recompile anymore (allows opers w/ OperOverride to simply `/join` restricted channels)
-
-__Configuration:__
-`better_override` defaults to 0/false so you can simply omit the configuration variable if you don't want this feature. Otherwise, add `m_forward_override 1` to the __global__ configuration.
-
-__I'll also include ze original readme sort of thing right here:__
-This module is based on the `m_banlink` module, but offers a more robust featureset. This module and the banlink module are incompatible with each other, so having both installed at once won't work (and why would you anyway?)
-
-My module offers the following features:
+I also started writing modules with the intention of selling them, as those are generally very complex and take up __a lot__ of my spare time. ;] For more information about those, simply go to my [shop sort of thing](https://unrealshop.gottem.nl).
 
-* `+F <channel>` channel mode to forward users that are unable to join to another channel (including invite only, keyed, etc. not just banned). Requires channel owner (+q) to set
-* `+B` channel mode to prevent users from being forwarded to your channel. Requires channel owner (+q) to set
-* `+Q` user mode to prevent yourself from being forwarded to other channels
-* `~f:#channel:nick!user@host` extended bantype to forward specific users to another channel (overrides +F)
-* Users will only be forwarded once. If they cannot join the second channel, nothing will happen (even if the second channel is `+F`)
-* Users will be given a descriptive message as to why they are unable to join the first channel (e.g. "channel is invite only" or "you are banned")
-* (Optional) You may choose to allow Opers to be able to directly join a channel via OperOverride (e.g. normally an oper must /invite themselves into a `+i` channel, this would allow them to just join. Either way an OperOverride message is given and logged). To enable this, see the Config section [in the source]
+If you don't need these but still want to support me, feel free to [donate through PayPal](http://gottem.nl/donate) or use the [custom job fee option in my shop](https://unrealshop.gottem.nl/#buy) if you want to donate with credit card or iDEAL. :>

+ 2 - 0
man/anti_amsg.md

@@ -0,0 +1,2 @@
+# anti\_amsg
+Some clients implement a command like `/amsg <message>`, which sends that message to all active tabs (both channels and private queries). This can get really spammy, so the module will allow the first message to go through and block the others for a short period of time. It will also strip colours and control codes, in case some people have edgy scripts for different markup across tabs. The offender will get an in-channel notice if the target is a channel and in the server console if otherwise.

+ 13 - 0
man/anticaps.md

@@ -0,0 +1,13 @@
+# anticaps
+Some people may often type in caps which is annoying af really. So this module allows you to block these messages (or convert to all-lowercase) by means of an `anticaps { }` configuration block. It works for both channel and user private messages. ;] It disregards colour codes and control characters as well spaces while counting caps. U-Lines and opers are once again exempt.
+
+__Config block:__
+    anticaps {
+    	capslimit 10; // Default: 50
+    	minlength 10; // Default: 30
+    	lowercase_it 1; // Default: 0
+    };
+
+Above example would set a limit of 10% capital letters, with a minimum message length of 10. In other words, if the message is less than 10 characters it won't even bother checking. You can also set it to 0 to effectively disable it. The entire block is optional.
+
+Set `lowercase_it` to `1` to lowercase the entire (plaintext) message instead of downright bl0cking it. ;]

+ 17 - 0
man/auditorium.md

@@ -0,0 +1,17 @@
+# auditorium
+The good ol' channel mode `+u` from Unreal 3.x. =] Since a bunch of stuff for this mode was hardcoded in U3's core sauce, I've made a few adjustments to maximise its usability. I've never used `+u` myself back then, so I'm not 100% sure if the features match (it was basically guesswork based on the dirty U3 sauce).
+
+_Once the channel mode is set, the following restrictions apply:_
+
+__Everyone with `+o`/`+a`/`+q`__:
+* Can see the full user list and all channel events (joins, quits, etc)
+* Will see messages from __anyone__, even those without a list access mode
+
+__People without `+o`/`+a`/`+q`__:
+* Can only see users with any of those 3 modes
+* Will also only see messages from such users
+
+__IRCOpers only:__
+* If they have the proper override (which afaik is `override:see:who:onchannel`) they can also see everyone, but not their messages if they don't have the proper list modes
+
+The channel mode can only be set by people with `+a` or `+q` (and opers with OperOverride obv). When the mode is unset or someone gets chanops, they won't immediately see the other users "joining". Instead, people have to do `/names #chan` (this is how it worked in U3 too). OR if you have `+D` active as well, that module will take care of the rest. ;]

+ 10 - 0
man/autojoin_byport.md

@@ -0,0 +1,10 @@
+# autojoin\_byport
+Similar to `set::auto-join`, this forces users to join one/multiple channels on connect, based on the p0rt they're using.
+
+__Config block:__
+    autojoin_byport {
+    	6667 "#plain";
+    	6697 "#ssl,#ssl2";
+    };
+
+Should be pretty clear how that works. ;] Currently it doesn't check for duplicates or max channels, so bnice. It does check for valid channel names/lengths and port ranges. =]

+ 21 - 0
man/autovhost.md

@@ -0,0 +1,21 @@
+# autovhost
+Apply vhosts at __connect time__ based on users' raw nick formats or IP addresses. The vhosts are entered in `unrealircd.conf` and they must be at least 5 chars in length. Furthermore, you can only enter the host part (so __not__ `ident@host`).
+
+There are some dynamic variables you can specify in the config, which will be replaced with a certain value on user connect:
+* `$nick`: nickname 0bv m8
+* `$ident`: ident 0bv m9
+
+If a resulting vhost would be illegal (unsupported characters etc) then opers with the `EYES` snomask will get notification about this.
+
+__Usage:__
+Add a config block that looks like this:
+    autovhost {
+    	*!*@some.host $nick.big.heks;
+    	*!*@some.host $ident.big.heks;
+    	Mibbit*!*@*mibbit.com mibbit.is.gay;
+    	192.168.* premium.lan;
+    };
+
+So everyone connecting from a typical LAN IP will get the vhost `premium.lan`, for example. Keep in mind it replaces `virthost` and __not__ `cloakedhost`, so when you do `/umode -x` this custom vhost is lost (why would you do `-x` anyways? ;]).
+
+Furthermore, services like for example Anope's `HostServ` will override this vhost as they generally set it __after__ we changed it.

+ 15 - 0
man/bancheck_access.md

@@ -0,0 +1,15 @@
+# [UNC] bancheck\_access
+This one was mostly written for keks. It prevents chanops/hops from banning anyone who has `+o`, `+a` and/or `+q`. The module will check every banmask against people who have any of those access modes, using both their vhost and cloaked host. Opers can ban anyone regardless, but they can also still be affected by other bans if they don't have a high enough access mode. This is done to maintain fairness in the channel, but opers may sometimes need to set wide-ass and/or insane channel bans. Similar to `fixhop`, this mod will simply strip the affected masks and let the IRCd handle further error processing.
+
+__Note:__ Afaik Unreal is unable to "ask" your `NickServ` flavour about access lists from within a module. So if you have Anope and did `/cs access #chan add <nick> 10` it will auto-op that person when they authenticate, but Unreal knows fuck all about this list. As such, it simply checks if they have the proper access mode __right now__.
+
+Also, because chan(h)ops could theoretically use `/cs mode #chan +b <mask>` to bypass the module, U-Lines are also restricted. ;]
+
+__Config block:__
+The module will display a notice to the user in case certain masks are stripped, provided you set the following config value:
+    set {
+    	// Rest of set { } block goes hur 0fc
+    	bancheck_access_notif 1;
+    };
+
+__Also, keep in mind__ that this only prevents __setting__ of bans, they can still do like `/mode #chan -b *!*@hostname.of.chanop`.

+ 6 - 0
man/banfix_voice.md

@@ -0,0 +1,6 @@
+# banfix\_voice
+So apparently someone with `+v` can still talk if they're banned (`+b`) or mutebanned (`+b ~q:`). This seems counterintuitive to me and probably a bunch of others, so the module rectifies that. Keep in mind that people with at least `+h` or IRC operator status (as well as U-Lines) can still talk through it.
+
+Also, when you're not even voiced but have `+b` on you and you `/notice #chan`, you don't see a "you are banned" message. So I fixed that too. =]
+
+Just load it and g0. =]

+ 41 - 0
man/block_masshighlight.md

@@ -0,0 +1,41 @@
+# block\_masshighlight
+This shit can halp you prevent highlight spam on your entire network. =] It keeps track of a user's messages on a per-channel basis and checks if they highlight one person too many times or too many different persons at once. Opers and U-Lines are exempt (as per usual), but also those with list modes `+a` and `+q`. ;3 When someone hits the threshold, opers with the snomask `EYES` will get a server notice through the module (enable that shit with `/mode <nick> +s +e` etc ;]).
+
+In some cases you might wanna exclude a certain channel from these checks, in which case you can use channel mode `+H`. This can be useful for quiz/game channels.
+
+Couple o' thangs to keep in mind: 
+* The module doesn't count duplicate nicks on the same line as separate highlights
+* The module doesn't exclude __your own nick__, because bots tend to just run through `/names` and won't exclude themselves
+
+__Config block:__
+_The module doesn't necessarily require any configuration, it uses the following block as defaults_
+
+    block_masshighlight {
+    	maxnicks 5;
+    	delimiters "	 ,.-_/\:;";
+    	action gline;
+    	duration 7d;
+    	reason "No mass highlighting allowed";
+    	snotice 1;
+    	banident 1;
+    	multiline 0;
+    	allow_authed 0;
+    	//allow_accessmode o;
+    	percent 1;
+    	show_opers_origmsg 1;
+    };
+
+* __maxnicks__:  Maximum amount of highlighted nicks (going over this number results in `action` setting in) -- __works in conjunction with `percent`__
+* __delimiters__: List of characters to split a sentence by (don't forget the surrounding quotes lol) -- any char not in the default list may prevent highlights anyways
+* __action__: Action to take, must be one of: `drop` (drop silently [for the offender]), `notice` (drop, but __do__ show notice to them), `gline`, `zline`, `shun`, `tempshun`, `kill`, `viruschan`
+* __duration__: How long to `gline`, `zline` or `shun` for, is a "timestring" like `7d`, `1h5m20s`, etc
+* __reason__: Reason to show to the user, must be at least 4 chars long
+* __snotice__: Whether to send snomask notices when users cross the highlight threshold, must be `0` or `1` (this only affects messages from the module indicating what action it'll take)
+* __banident__: When set to `1` it will ban `ident@iphost`, otherwise `*@iphost` (useful for shared ZNCs etc)
+* __multiline__: When set to `1` it will keep counting highlights until it encounters a line __without__ one
+* __allow_authed__: When set to `1` it will let logged-in users bypass this shit
+* __allow_accessmode__: Must be __one__ of `vhoaq` (or omitted entirely for no exceptions [the default]), exempts everyone with at minimum the specified mode from highlight checks (e.g. `a` includes people with `+q`)
+* __percent__: Threshold for the amount of characters belonging to highlights, not counting `delimiters` (e.g. `hi nick` would be 67%) -- __works in conjunction with `maxnicks`__
+* __show_opers_origmsg__: Display the message that was dropped to opers with the `SNO_EYES` snomask set (__this is entirely separate from the `snotice` option__)
+
+If you omit a directive which is required for a certain `action`, you'll get a warning and it will proceed to use the default. It should be pretty clear what directives are required in what cases imo tbh famalam. ;];]

+ 16 - 0
man/block_no_tls.md

@@ -0,0 +1,16 @@
+# [UNC] block\_no\_tls
+Allows privileged opers to temporarily block new, non-TLS (aka SSL) __user__ connections network-wide. ;3 There's a new operpriv, which if set, allows an oper of that class to both block and unblock non-TLS connections. Keep in mind that rehashing the IRCd also resets the blocking flag for that server. ;] Opers with snomask `SNO_KILLS` (`/umode +s +k` etc) will see notices about disallowed connections.
+
+__Config block:__
+    operclass netadmin-blocknotls {
+    	parent netadmin;
+    	privileges {
+    		blocknotls;
+    	};
+    };
+
+__Syntax:__
+`BLOCKNOTLS`
+`UNBLOCKNOTLS`
+
+Both commands do not take any arguments and are broadcasted to other servers. =]

+ 9 - 0
man/block_notlsident.md

@@ -0,0 +1,9 @@
+# [SPEC] block\_notlsident
+Another request by `Celine`. =] Blocks certain idents from connecting if they're using a plain port (so without SSL/TLS lol). As it supports wildcards too, it doesn't take into account the maximum ident length (`USERLEN`, which is 10 by default). ;]
+
+__Config block:__
+    block_notlsident {
+    	ident "*ayy*";
+    	ident "someident";
+    	// More go here
+    };

+ 38 - 0
man/chansno.md

@@ -0,0 +1,38 @@
+# [PORT] chansno
+My port of [AngryWolf's module for Unreal 3.x](http://www.angrywolf.org/modules.php).
+Allows you to assign different channels for different types of server notifications. It works like the snomask system, but instead of receiving notifications in your private server console thingy, you will get the messages in channels. ;] Simply load the module and get to `unrealircd.conf`, see below for halp.
+
+__Config block:__
+    chansno {
+    	msgtype privmsg;
+
+    	channel "#huehue" {
+    		server-connects; squits; oper-ups;
+    	};
+
+    	channel "#kek" {
+    		mode-changes; topics; joins; parts; kicks;
+    	};
+    };
+
+The first directive, `msgtype`, can either be `privmsg` or `notice`. The first one dumps a plain message as if it were ein user, the second is a channel notice.
+
+And here's a list of types you can use fam:
+* `mode-changes` => Mode changes inside channels
+* `topics` => Topic changes lol
+* `joins` => Join messages obv
+* `parts` => Part messages 0bv
+* `kicks` => Kick messages OBV
+* `nick-changes` => Nickname changes m8
+* `connects` => Local client connections
+* `disconnects` => Local client disconnections
+* `server-connects` => Local server connections
+* `squits` => Local server disconnections
+* `unknown-users` => Disconnections of unknown (local) clients
+* `channel-creations` => Channel creations (previously non-existent channels)
+* `channel-destructions` => Channel destructions (the last user parted from a channel), notify local users only (to prevent duplicates)
+* `oper-ups` => Successful oper-ups, displays opernick and opercla$$
+* `spamfilter-hits` => Notify whenever someone matches a spamfilter
+* `tkl-add` => Notify whenever a TKL is added (G-Line, K-Line, Z-Line, etc)
+
+You may have noticed the term `local` a lot above. This means the underlying hook only triggers for clients connected directly to that particular server. So people on `server A` doing a chanmode change won't cause `server B` to pick up on it. In this case `A` will simply broadcast it so everyone gets notified. =] The exception on this are channel destructions; every server will see the event so they will only broadcast it to their local users. I added dis because fuck dupes. ;3

+ 19 - 0
man/clearlist.md

@@ -0,0 +1,19 @@
+# clearlist
+This module is quite similar to `rmtkl` in that you can clear "ban" lists based on masks with wildcards. So you could use a mask of `*!*@*` or even just `*` to clear errythang, it's pretty straightforward imo tbh. =]
+
+Couple o' thangs to keep in mind:
+* The module will run Unreal's `TKL_DEL` hook, so other modules are aware of the changes it makes.
+* Sometimes (for unknown reasons) you might get corrupt masks in your ban lists (e.g. `butthams@*` instead of `butthams!*@*`), running any `/clearlist` command will clear those as well. This was added because not even with raw server2server commands can you remove those masks.
+
+__Syntax:__
+`CLEARLIST <channel> <types> <mask>`
+
+`Types` list:
+* `b` => Ban
+* `e` => Ban exception
+* `I` => Invite exception
+
+__Examples:__
+* `CLEARLIST #bighek b *`
+* `CLEARLIST #ayylmao Ie guest*!*@*`
+* `CLEARLIST #hambutt * *`

+ 14 - 0
man/clones.md

@@ -0,0 +1,14 @@
+# [PORT] clones
+Yay for `AngryWolf`. =]
+Adds a command `/CLONES` to list all users having the same IP address matching the given options. Clones are listed by a nickname or by a minimal number of concurrent sessions connecting from the local or the given server.
+
+I made one change, which is instead of having `/helpop clones` (which requires you to add a block to all servers' `help.conf` files) you can now view a built-in halp thingay. =]
+
+__Syntax:__
+`CLONES <min-num-of-sessions|nickname> [server]`
+
+Some examples:
+* `CLONES 2` => Lists local clones having `2` or more sessions
+* `CLONES Loser` => Lists local clones of `Loser`
+* `CLONES 3 hub.test.com` => Lists all clones with at least 3 sessions, which are connecting from `hub.test.com`
+* `CLONES` => View built-in halp

+ 12 - 0
man/commandsno.md

@@ -0,0 +1,12 @@
+# [PORT] commandsno
+Guess who originally wrote this one?
+Adds a snomask `+C` for opers so they can see what commands people use. ;3 Specify what commands may be monitored in the config, then set the snomask with `/mode <nick> +s +C` (or extend `set::snomask-on-oper`).
+
+For obvious reasons `PRIVMSG` and `NOTICE` can't be monitored, deal w/ it.
+
+__Config block:__
+I've kept the "location" the same as the original one but I did rename the directive. It's simply a comma-delimited list of commands. ;]
+    set {
+    	// Rest of the set block goes here obv, like kline-address, network-name, etc
+    	commandsno "version,admin,module";
+    };

+ 21 - 0
man/debug.md

@@ -0,0 +1,21 @@
+# [UNC] debug
+Allows privileged opers to easily view internal (configuration) data. I know you can do some of it with a `/STATS` command, but this shit displays different info than that. ;]
+
+__Usage:__
+Currently it allows opers with the operpriv `debug` to view configured oper and operclass information. By default it asks the server to which you're connected, but since it may differ across servers (local O-Lines etc), you can also ask another server directly. =]
+
+__Config block:__
+    operclass netadmin-debug {
+    	parent netadmin;
+    	privileges {
+    		debug;
+    	};
+    };
+
+__Syntax:__
+`DBG <datatype> [server]`
+I went with `DBG` and not `DEBUG` cuz a bunch of clients probably nick the `/debug` command for themselves, get at me. ;];]
+
+__Examples:__
+* `DBG opers` => Get a list of known opers from the server you're on
+* `DBG operclasses ayy.check.em` => Asks the leaf `ayy.check.em` about the operclasses it knows

+ 21 - 0
man/denyban.md

@@ -0,0 +1,21 @@
+# denyban
+In the event of a netsplit, if someone tries to be funny by setting `+b *!*@*` on the main channel, nobody will be able to join until opers come in and fix it. This module allows you to deny such bans. =] Optionally, specify if opers are allowed to override it and if offenders should get a notice. I even went a bit further and also applied these restrictions to `SAMODE`. ;]
+
+Also, because chanops could theoretically use `/cs mode #chan +b <mask>` to bypass the module, U-Lines are also restricted. ;]
+
+__Config block:__
+    denyban {
+    	allowopers 0;
+    	denynotice 1;
+    	reason "ayy ur faget lol (stripped $num masks)";
+    	mask BAN_ALL;
+    	mask *!*@*malvager.net;
+    };
+
+The mask `*!*@*` is kinda special, so you'll have to specify `BAN_ALL` to prevent people from doing `MODE #chan +b *!*@*` etc. For anything else it will do a wildcard match, as is usual. The directives `allowopers` and `denynotice` should be pretty clear. They default to `1` and `0`, respectively.
+
+For the `reason` directive you can use `$num`, which will be replaced with the actual amount of stripped masks. ;]
+
+I went with `denyban` over `deny ban` (notice the space) to avoid any potential future conflict with Unreal core stuff.
+
+__Also, keep in mind__ that this only prevents __setting__ of bans, they can still do like `/mode #chan -b *!*@*malvager.net`.

+ 6 - 0
man/extwarn.md

@@ -0,0 +1,6 @@
+# extwarn
+Enables additional error checking of the IRCd configuration. I originally wrote it to (temporarily?) work around a [bug](https://bugs.unrealircd.org/view.php?id=4950) (although it may be by design) where you don't get a warning about using non-existent operclasses during rehash/init. So it currently only checks for that, but I may extend it to include other things later. =]
+
+The module only throws __warnings__ (hence the name lol), so it allows the rehash etc to continue normally. This way it won't break any functionality. ;];]
+
+To make sure the entire config is available to the module, it delays its report by 10 seconds after a rehash/bootup.

+ 55 - 0
man/fantasy.md

@@ -0,0 +1,55 @@
+# fantasy
+Fantasy commands may sound familiar if you're using Anope IRC services or have fucked with InspIRCd at some point. They're basically aliases for certain commands and are visible to other users, since they're generally called like `!cmd dicks`. Unreal provides aliases too but afaik that only works for `/cmd dicks`, which isn't visible to others. You can also change the command prefix to like `?cmd` or `\cmd` or whatever you want (one character max), just not `/cmd`. ;] It also supports a few special inline variables, more on that bel0w.
+
+Furthermore, these aliases are limited to __channel messages__. There's not much you can do in private messages anyways, besides maybe `ACTION` shit.
+
+__Keep in mind messages similar to `!!cmd` (like, more than one leading `cmdchar`) are ignored, as well as messages starting with any other character__
+
+__Special variables:__
+I'll put these before the config block so you'll have that info before you get to it. ;] You can use all the special variants for `$1` through `$9`.
+* `$chan` => Will obv be replaced with the channel you dumped the command in
+* `$1` => Will be replaced with the user's first argument
+* `$1-` => Becomes the first argument plus everything after it (greedy)
+* `$1i` => If the first arg is a nick, replace it with their ident/username
+* `$1h` => If the first arg is a nick, replace it with their hostname
+
+__You cannot use multiple greedy vars however__, raisins should be obvious.
+
+__Config block:__
+Creating aliases might be a bit complex, so I'll just dump an example config right here and explain in-line with comments. =]
+
+    fantasy {
+    	// Change command prefix to \, so it becomes \dovoice etc
+    	//cmdchar \;
+
+    	// "!dovoice urmom" results in "/mode $chan +v urmom"
+    	dovoice		"MODE $chan +v $1";
+    	unvoice		"MODE $chan -v $1";
+
+    	// "!fgt urmom" is turned into "/kick $chan urmom :ayyyyy ur faget"
+    	fgt		"KICK $chan $1 :ayyyyy ur faget";
+
+    	// "!bitchnigga urmom dickface" results in a separate "/kick $chan $nick :nigga b0iiii" for both urmom and dickface
+    	bitchnigga	"KICK $chan $1- :nigga b0iiii";
+
+    	// "!ayylmao urmom u goddam fuckstick" becomes "/kick urmom :u goddam fuckstick"
+    	ayylmao		"KICK $chan $1 :$2-";
+
+    	// "!invex urmom" is majikked into "/mode $chan +I *!*@urmom.tld"
+    	invex		"MODE $chan +I *!*@$1h";
+    	uninvex		"MODE $chan -I *!*@$1h";
+
+    	// "!safe urmom" will become "/kick $chan urmom :$chan is a safe space lol m8 urmom"
+    	safe		"KICK $chan $1 :$chan is a safe space lol m8 $1";
+
+    	// It is also possible to have the same alias issue multiple commands ;]
+    	safe		"MODE $chan +b *!*@$1h";
+
+    	// You can also go through ChanServ, provided you have access with it
+    	n			"PRIVMSG ChanServ :KICK $chan $1 change your nick and rejoin lol";
+
+	// Set a channel to registered-only and muted
+	floodprot	"MODE $chan +Rm";
+    };
+
+As you may have noticed there are some colons in there. These are required, because otherwise there's no telling where the target arg stops and the message begins. Also, in case you do `!devoice` (so without ne args) it will try and voice the user who issued it. Permissions for using the resulting command are eventually (and automajikally) checked by the internal `do_cmd()` call I have in hur. ;3

+ 20 - 0
man/fixhop.md

@@ -0,0 +1,20 @@
+# [UNC] fixhop
+In my opinion the `+h` access mode (channel halfops yo) is a little b0rked (cuz le RFC compliancy prob). So I made a qt3.14 module that implements some tweaks which you can enable at will in da config. ;3
+
+Also, because hops could theoretically use `/cs mode #chan +b <mask>` to bypass the module, U-Lines are also restricted. ;]
+
+__Usage:__
+Just compile that shit, load it and add the tweaks you want to a top-level config block (disable one by simply removing/leaving out the directive):
+    fixhop {
+    	allow_invite;
+    	disallow_widemasks;
+    	widemask_notif;
+    	disallow_chmodes "ft";
+    	chmode_notif;
+    };
+
+* `allow_invite` => Apparently when a chan is `+i` halfops can't invite people, this overrides that
+* `disallow_widemasks` => Hops can normally set a ban/exemption/invex for shit like `*!*@*`, this disallows that by stripping those masks
+* `widemask_notif` => Enable an in-channel notice directed only at the hopped user
+* `disallow_chmodes` => Will strip the given channel modes in either direction, ne arguments should be taken into account
+* `chmode_notif` => Enable in-channel n0tice for dis

+ 4 - 0
man/getlegitusers.md

@@ -0,0 +1,4 @@
+# [PORT] getlegitusers
+Originally written by `darko`, this module simply counts how many legitimate clients you have on your network. People who are on more than one channel are seen as legitimate, while they who are in no channels are marked "unknown". It also accounts for services boats.
+
+Just run `/getlegitusers` and check your server console. =]

+ 2 - 0
man/holidays.md

@@ -0,0 +1,2 @@
+# [MALV] holidays
+Do some string replacements based on wat holiday it is atm. =]

+ 2 - 0
man/joinmute.md

@@ -0,0 +1,2 @@
+# [PORT] joinmute
+Originally written by `Dvlpr`, this module prevents people who just joined a channel from speaking for a set amount of seconds. It works with a new channel mode: `+J <seconds>`, for which you need to be chanop or higher to set. Furthermore, opers, U-Lines and anyone with any access mode (one or more of `+vhoaq`) will be able to talk right away. U-Lines are exempt since some services may join a channel, do something and part. =]

+ 2 - 0
man/kickjoindelay.md

@@ -0,0 +1,2 @@
+# kickjoindelay
+Adds a chanmode `+j <delay>` to prevent people from rejoining too fast after a kick. You can set a delay of between 1 and 20 seconds, as anything higher might be a bit much lol. You gotta have at least `+o` to set this shit. Opers and U-Lines are exempt, as well as servers (cuz just in case lol).

+ 44 - 0
man/listrestrict.md

@@ -0,0 +1,44 @@
+# listrestrict
+Allows you to impose certain restrictions on `/LIST` usage, such as requiring clients to have been online for a certain period of time. Simply load the module and add a new block to your `unrealircd.conf`, for which see bel0w. Opers, servers and U-Lines are exempt for obvious reasons. ;]
+
+Even though Unreal now has a `set::restrict-commands` block you can use to delay `/LIST` usage, it doesn't provide the honeypot functionality, so I've kept this module as-is. `listrestrict` adds overrides with a higher priority though, so even if you configure both then `listrestrict` will run first.
+
+__Config block:__
+    listrestrict {
+    	connectdelay 60; // How long a client must have been online for
+    	needauth 1; // Besides connectdelay, also require authentication w/ services
+    	authisenough 1; // Don't check connectdelay if user is identified OR exempt from authentication entirely
+    	fakechans 1; // Send a fake channel list if connectdelay and/or needauth checks fail
+    	glinetime 7d; // For channels with gline set to 1, use 0 for permanent bans
+
+    	fakechannel {
+    		// Only the name is required
+    		name "#honeypot";
+    		//topic "ayy lmao"; // Defaults to "DO NOT JOIN"
+    		//users 50; // Defaults to 2 users, must be >= 1
+    		//gline 0; // Defaults to 0
+    	};
+
+    	fakechannel {
+    		name "#fakelol";
+    		topic "top kek";
+    		users 10;
+    		gline 1; // G-Line won't kick in if connectdelay and needauth checks are satisfied, or if the user has a 'fakechans' exception
+    	};
+
+    	exceptions {
+    		all "user@*";
+    		connect "someone@some.isp"; // Only require auth
+    		auth "*@123.123.123.*"; // Only require connectdelay
+    		fakechans "ayy@lmao"; // Don't send a fake channel list, just prevent sending of the legit one
+
+    		// You can also specify multiple types for the same mask:
+    		auth "need@moar";
+    		fakechans "need@moar";
+    		// This user would only need to wait <connectdelay> seconds and won't get a fake channel list at all
+    	};
+    };
+
+Omitting a directive entirely will make it default to __off__. If `connectdelay` is specified, the minimum required value is `10` as anything below seems pretty damn useless to me. =] The `exceptions` block should be pretty self explanatory. ;]
+
+As usual with my mods, U-Lines, opers and servers are exempt from any restrictions.

+ 13 - 0
man/mafiareturns.md

@@ -0,0 +1,13 @@
+# [SPEC] mafiareturns
+Requested by `IzzyCreamcheese`, this module improves upon his website's chat functionality.
+
+__Config block:__
+    mafiareturns {
+    	channels "#chan1, #chan2";
+    	tag "[MR]";
+    	position back;
+    };
+
+The `position` can be either `back` or `front`, the meaning of which should be pretty clear. =] If a user's nick matches the `tag` at `position`, the module will prevent them from changing their nick or parting any of the channels listed in `channels` and notices them about it (shit like `/part #somechan,#chan1` will be rewritten to `/part #somechan` too). Servers, U-Lines and opers etc are exempt for obvious raisins. ;]
+
+The directives `channels` and `tag` are required, `position` will fall back to `back` if it's omitted or contains an invalid value.

+ 2 - 0
man/message_commonchans.md

@@ -0,0 +1,2 @@
+# message\_commonchans
+Adds a umode `+c` so you can prevent fucktards who don't share a channel with you from messaging you privately. Simply load it and do `/mode <your_nick> +c`. ;3 Opers and U-Lines are exempt from this (i.e. they can always send private messages), the reason why should be obvious imo tbh fam. Additionally, since U-Lines such as `NickServ` are usually not present in any channels, they can always receive messages too (rip `/ns identify` otherwise ;]).

+ 28 - 0
man/mshun.md

@@ -0,0 +1,28 @@
+# [MALV] mshun
+Enables privileged 0pers to add shuns that only affect `PRIVMSG`, `NOTICE`, `KNOCK` and `INVITE` (`M-Lines` lmao), except when sending __to__ U-Lines (`NiqqServ` etc). Only opers with the new operpriv `mshun` will be able to use it, although all other 0pers will get the notices since these `M-Lines` are __netwerk wide__ bruh. Servers, U-Lines and opers are exempt for obvious raisins.
+
+Expiring shuns is done with an `EVENT` thingy in Unreal, which is set to run every 10 seconds. This means if you set a shun for 5 seconds (why would you anyways?) it may not expire after eggzacktly 5 seconds. ;] When no expiration is specified the value in `set::default-bantime` is used. Every server checks the expirations themselves. =] Also, they store it in a `ModData` struct so it persists through a rehash without the need for a `.db` fiel. ;] Furthermore, they sync their known `M-Lines` upon server linkage. =]] Other lines such as G-Lines, Z-Lines are also stored in memory and get resynced during a link so these are pretty similar aye.
+
+__Config block:__
+    operclass netadmin-mshun {
+    	parent netadmin;
+    	privileges {
+    		mshun;
+    	};
+    };
+
+__Syntax:__
+`MSHUN [-]<ident@host> [expire] <reason>`
+
+Also supports the alias `MLINE`. The first argument may also be an online nickname, this will be resolved to their full mask. =] Wildcards `*` and `?` are also supp0rted.
+
+__Examples:__
+* `MSHUN guest*@* 0 nope` => All...
+* `MLINE guest*@* 0 nope` => ...of...
+* `MLINE -guest*@*` => ...these add/delete the same M-Line, with no expiration
+* `MSHUN guest*@* 3600 ain't gonna happen` => Add an M-Line that expires in an hour =]
+* `MSHUN guest*@* 1h ain't gonna happen` => Ditto ;];]
+* `MSHUN` => Show all M-Lines
+* `MLINE halp` => Show built-in halp
+
+The hostmask is matched against `user@realhost` only. The timestring shit like `1h` supports up to weeks (so you __can't__ do `1y`).

+ 13 - 0
man/nicksuffix.md

@@ -0,0 +1,13 @@
+# [SPEC] nicksuffix
+Requested by `Celine`, this module prevents people from doing `/nick <anything here>`. Rather, it suffixes the "original" nick (the one on connect) with what the user specifies. There's also a special "nick" to revert back to the original one. ;] The module also comes with a new config block, which is __required__.
+
+__Config block:__
+    nicksuffix {
+    	separator "|";
+    	restore "me";
+    };
+
+The `separator` can be one of the following characters: `-_[]{}\|`
+The other directive is so when people do `/nick me` they'll revert back to what they had on connect. It can be anything you want, as long as Unreal sees it as a valid nick.
+
+Also, keep in mind that the specified `separator` char __cannot__ be used for "base" nicknames, so connecting to IRC with a nick such as `foo|bar` is not possible.

+ 14 - 0
man/noghosts.md

@@ -0,0 +1,14 @@
+# noghosts
+Originally proposed by `PeGaSuS`, this module makes IRC opers part `+O` channels once they oper down. I've kept the "ghosts" thing for lack of a better term, deal w/ it. =]
+
+__Config block:__
+    noghosts {
+    	message "g h o s t b u s t e r s";
+    	flags "O";
+    	channels {
+    		"#opers"; // Don't forget the "" to make sure Unreal doesn't interpret it as a comment ;]
+    		"#moar";
+    	};
+    };
+
+All configurables are optional; the default message is simply `Opered down` and if no `channels` are specified then it'll check all `+O` ones the opered-down oper is in. I may extend `flags` to contain more flags at some point, which would also affect the `message` (prolly). =]

+ 2 - 0
man/noinvite.md

@@ -0,0 +1,2 @@
+# noinvite
+Adds a new umode `+N` (as in __N__oinvite ;]) to prevent all invites. The only ones that can still invite you are 0pers and U-Lines obv. Simply l0ad the module and do like `/umode +N` for profits.

+ 13 - 0
man/nopmchannel.md

@@ -0,0 +1,13 @@
+# [SPEC] nopmchannel
+A request by `westor`, this module is p much the opposite of my `message_commonchans` in that it __prevents__ users from privately messaging each other if they share a specific channel. There are a few exceptions (as usual ;]):
+* People with any of the `+hoaq` access modes, as well as U-Lined users (e.g. BotServ bots), can send and receive normally to/from all channel members
+* IRC opers can always send to other members but not receive, unless they have one of above-mentioned access modes
+
+__Config block:__
+    nopmchannel {
+    	name "#somechannel";
+    	name "#another";
+    	// More go here
+    };
+
+I went with a config block instead of a channel mode because the module imposes restrictions on user-to-user communications, which is more of a network thing instead of channel-level. ;]

+ 11 - 0
man/operoverride_ext.md

@@ -0,0 +1,11 @@
+# operoverride\_ext
+Originally named `m_forward`, a bigass chunk of that code is now included in core Unreal. The remainder is implemented by this "new" module:
+
+* Normally, even when an oper has OperOverride they still can't simply `/join #chan` when it's set to `+R` or `+i` or if they're banned. They have to do `/sajoin` or invite themselves. The module corrects that (it still generates an OperOverride notice though ;]).
+
+Any other additions to OperOverride will also be done by this module. =]
+
+__Required oper permissions:__
+* To override `+b` (banned lol): `channel:override:message:ban`
+* To override `+i` (invite only): `channel:override:invite:self`
+* To override `+R` (only regged users can join a channel): `channel:override:message:regonly`, which seems to be non-default

+ 22 - 0
man/operpasswd.md

@@ -0,0 +1,22 @@
+# [PORT] operpasswd
+Another port of one of `AngryWolf`'s modules. =]
+This basically lets you see the username and password for a failed `OPER` attempt, you gotta set an extra snomask flag to see them though. You can do this wit `/mode <nick> +s +O` or just use it in `set::snomask-on-oper`.
+
+I made some changes to this module as it relied on "netadmins" which Unreal 4.x doesn't have n0 m0ar. So I came up with a new operclass privilege to indicate who is able to set the snomask. You also had to explicitly enable the snomask in the 3.x version, but it's now enabled by default. ;]
+
+__Config blocks:__
+    operclass netadmin-operpasswd {
+    	parent netadmin;
+    	privileges {
+    		operpasswd;
+    	};
+    };
+
+    operpasswd {
+    	enable-global-notices 1;
+    	enable-logging 0;
+    	max-failed-operups 3;
+    	failop-kill-reason "Too many failed OPER attempts lol";
+    };
+
+Since snomask notices are only sent to a server's local opers, you gotta use `enable-global-notices` to broadcast that shit to errone. Also, you __have__ to specify something for `max-failed-operups` in order to get the kill to work, since the module sorta assumes 0 which means "disable that shit fam". The kill reason defaults to "Too many failed OPER attempts".

+ 15 - 0
man/otkl.md

@@ -0,0 +1,15 @@
+# [MALV] otkl
+Allows privileged opers to set one-time `G/GZ-Lines`. Local Z-Lines are not supported because they seem fairly useless imo tbh famlamlm. =] The rules for hostmasks etc are the same as for regular `G/GZ-Lines`. These "OTKLines" persist through a rehash, plus servers will sync everything they know at link-time too. ;]
+
+If any online users match a newly added OTKLine, they will be killed first (with the well-known G-Line message about being permanently b&). Then once they reconnect, they'll get killed one more time before the OTKLine is removed from all servers. ez pz.
+
+__Syntax:__
+Simply `OGLINE` or `OZLINE` => List current `OG/OZ-Lines` (they're 2 different lists yo)
+`OGLINE halp` and `OZLINE halp` => View built-in halp ;3
+`OGLINE <[-]identmask@hostmask> {reason}` => Set/remove an `OG-Line` (reason is required for adding, ignored when deleting)
+`OZLINE <[-]identmask@ipmask> {reason}` => Set/remove an `OZ-Line` (ditto for reason)
+
+__Examples:__
+* `OGLINE *@some.domain.* not gonna happen` => Sets a host-based ban
+* `OZLINE *@123.123.* nope` => Sets an IP-based ban
+* `OZLINE -*@123.123.* nope` => Removes an IP-based ban

+ 4 - 0
man/plainusers.md

@@ -0,0 +1,4 @@
+# plainusers
+A simple module to list all users __not__ connected over SSL/TLS. Just run `/PUSERS` or `/PLAINUSERS` to get a nice lil' list. ;] It attempts to cram as many nicks on one line as it can, to avoid spamming the fuck out of you. Only opers can use it obviously. =]
+
+You can also achieve the same result with the already existing `/WHO` command but the specific flags you need might be a little hard/confusing to remember (even more so now that `WHOX` is a thing).

+ 35 - 0
man/pmlist.md

@@ -0,0 +1,35 @@
+# pmlist
+Sort of a hybrid between umode `+D` (don't allow private messages at all) and `+R` (allow registered users only), this module allows you to keep a whitelist of people allowed to send you private messages. =] Their UID is stored so it persists through nickchanges too, but the module only shows you the original whitelisted nick in lists etc.
+
+Opers and U-Lines can bypass the restriction 0bv. ;]
+
+__Usage:__
+Load the module and set umode `+P` on yourself (anyone can (un)set the umode). You can't set up a list without it but if you do have one and then unset the umode, it will be kept. Only when you disconnect will it be cleared (so it even persists through rehashes). Also, if __you__ have `+P` and message someone else, they will automatically be added to the list. If UIDs go stale (relevant user disconnects) the entry will also be removed if it's not persistent. See below (__Syntax__) for how2manage da whitelist. ;3
+
+There are also a few configuration directives for netadmins to tweak that shit.
+
+__Config block:__
+    pmlist {
+    	noticetarget 0; // Default is 0
+    	noticedelay 60; // Seconds only
+    };
+
+* `noticetarget` => Whether to notice the target instead, __if the source is a regged and logged in user__
+* `noticedelay` => How many seconds have to pass before a user will receive another notice
+
+__Syntax:__
+`OPENPM <nick> [-persist]` => Allow messages from the given user (the argument __must be an actual, existing nick__)
+`CLOSEPM <nickmask>` => Clear matching entries from your list; supports wildcard matches too (`*` and `?`)
+`PMLIST` => Display your current whitelist
+`PMHELP` => Display built-in halp info
+
+__Examples:__
+`OPENPM guest8` => Allow `guest8` to message you
+`OPENPM muhb0i -persist` => Allow `muhb0i`, persistently
+`CLOSEPM guest*` => Remove all entries matching this mask (`guest8`, `guestxxxx`, etc)
+`CLOSEPM *` => Remove __all__ entries (saves you a disconnect lol)
+
+Now this is what happens when a non-whitelisted user tries to message you:
+* For users who __haven't logged into services or if `noticetarget` is set to 0__, they will get a notice saying you don't accept private messages from them. It also instructs them to tell __you__ to do `/openpm` for them, like in a common channel.
+* For users who __have logged into services and if `noticetarget` is set to 1__ you will get a single notice asking you to do `/openpm` (the notice also includes their message).
+* These notices only happen once in a certain time period (based on the config directive `noticedelay`). After the first one, everything else will be silently discarded until enough time passes.

+ 15 - 0
man/portsifresi.md

@@ -0,0 +1,15 @@
+# [PORT, UNC] portsifresi
+Using this module you can specify a different password for every port. This might be useful if e.g. you have backup servers that only certain people should be able to connect to. Or if you want a totally priv8 netw3rk. I think it was originally written by `Sky-Dancer`.
+
+
+__Config block:__
+I've kept the original format mostly, with the exception of stripping the required trailing `:`. ;]
+
+    psifre {
+    	pass "6667:hams";
+    	pass "6697:turds";
+    };
+
+So any client connecting to port `6667` will first have to send a `PASS hams` command. People who use `6697` have to do `PASS turds`. Many clients (if not all?) have a `server password` field, so you just gotta enter em port-specific password in there.
+
+__Protip:__ Unreal 5 has [defines and conditional config](https://www.unrealircd.org/docs/Defines_and_conditional_config) hecks, which you could theoretically use with this module. For example, you could `@define $SERVER "foo.bar.baz"` then specify a password like `pre-$SERVER-post`. In order to connect to a specific server, you need to provide the proper server name too. Meaning the proper password is: `pre-foo.bar.baz-post`

+ 11 - 0
man/pubnetinfo.md

@@ -0,0 +1,11 @@
+# [UNC] pubnetinfo
+Another request/proposal by `PeGaSuS`, this module displays information that is allowed to be publicly available for every server. Right now it'll simply show if a server is linked over `localhost` and if it's using `SSL/TLS` to communicate with the other end. Simply execute __/pubnetinfo__ and check the server notices sent to you. ;]
+
+__Example output:__
+    -someleaf.myirc.net- [pubnetinfo] Link hub.myirc.net: localhost connection = no -- SSL/TLS = yes
+    -hub.myirc.net- [pubnetinfo] Link otherleaf.myirc.net: localhost connection = no -- SSL/TLS = yes
+    -hub.myirc.net- [pubnetinfo] Link services.myirc.net: localhost connection = yes -- SSL/TLS = no
+
+So in this case I ran the command on `someleaf`, which only has information about the hub it's linked to. For the other servers this leaf asks its hub for the information instead (otherwise we can't tell if it's using TLS or nah). The hub has info on 2 additional servers; another leaf and the services node.
+
+You can get similar information by using `/stats C`, but: 1) it only outputs shit for directly attached servers 2) it displays the server connection port too. ;]

+ 9 - 0
man/rehashgem.md

@@ -0,0 +1,9 @@
+# [UNC] rehashgem
+Implements an additional rehashing flag `-gem` (__g__lobal __e__xcept __m__e). I originally wrote this because of the `confprot` module. Since it sorta requires you to set `allowunknown` to `1` when making config changes, it would cause a triple rehash on the hub which is really not necessary. =]
+
+Now that `confprot` is dead this module prolly serves little purpose anymore, but some people might find it useful lel.
+
+Soooooo, when you do `/rehash -gem`, all __other__ servers will rehash everything (appends `-all` flag by default). You can also rehash just MOTDs, SSL/TLS-related stuff, etc by appending their respective flags to `-gem`:
+* `/rehash -gemtls`
+* `/rehash -gemmotd`
+* Any other "sub" flag Unreal already supports (`/helpop rehash` should show these)

+ 36 - 0
man/repeatprot.md

@@ -0,0 +1,36 @@
+# [UNC] repeatprot
+Sometimes there are faggots who spam the shit out of you, either through NOTICE, PRIVMSG, CTCP, INVITE or OPER commands. This module will GZ-Line/kill/block their ass if they do. Other than specifying the triggers and exceptions, you can tweak the action a lil' bit (more on that bel0w ;]).
+
+The module will keep track of people's last and first to last messages, so it catches people who alternate their spam too (or bots). =] Also, __channels are excluded__ as they probably have something better in place (like `+C` to disable `CTCP` in general, or `+f` for more fine-grained flood control). Colours and markup are also stripped prior to running the checks.
+
+Any oper with the `SNO_EYES` snomask set (`/umode +s +e`) will get notices from the module. These include trigger type, nick, body and action.
+
+There's also one built-in exception, namely sending __to__ U-Lines. First of all they should have their own anti-abuse systems in place. Secondly, sometimes people forget which exact password they used so they have to try multiple times.
+
+__Config block:__
+    repeatprot {
+    	triggers {
+    		notice;
+    		//privmsg;
+    		oper;
+    		//ctcp;
+    		//invite;
+    	};
+    	exceptions {
+    		nick!user@host;
+    		*!gottem@*;
+    		ayy!*@*;
+    	};
+
+    	timespan 2m; // Only keep track of commands sent over this period of time, accepts formats like 50, 1h5m, etc (0 for always, which is also the default)
+    	action block; // Default = gzline
+    	//action kill;
+    	//action gzline;
+    	//action gline;
+    	banmsg "Nice spam m8"; // This is also the default message
+    	showblocked 1; // Display the banmsg above to the spammer when action is block
+    	//tkltime 60; // How long to G(Z)-Line for, accepts formats like 50, 1h5m, etc (default = 60 seconds)
+    	threshold 3; // After how many attempts the action kicks in (default = 3)
+    };
+
+You need at least one trigger obviously. The exception masks must match `*!*@*`, so should be a full `nick!ident@host` mask m9. The __host__name used should match the __real__ host (or IP) and not a cloaked one.

+ 2 - 0
man/reportlol.md

@@ -0,0 +1,2 @@
+# [MALV] reportlol
+Adds a `/report` command which does fuck all. [=[==[==[=[

+ 15 - 0
man/rtkl.md

@@ -0,0 +1,15 @@
+# rtkl
+Allows privileged opers to remove remote servers' local `K/Z-Lines`. The required privileges are `server-ban:kline:remove` and `server-ban:zline:local:remove`, which the "netadmin" operclass should carry by default. The syntax is mostly the same as for regular `K/Z-Lines`, with the addition of one in the very front to indicate the target server. After some checks it will simply pass on a `KLINE` or `ZLINE` command to that server, so any further error handling is done by that module. ;]
+
+__Syntax:__
+`RKLINE <server> <[-]identmask@hostmask> {duration} {reason}` => Add/Delete a local K-Line on `server` for the specified usermask (duration and reason are ignored for deletions)
+`RZLINE <server> <[-]identmask@ipmask> {duration} {reason}` => Add/Delete a local Z-Line on `server` for the specified usermask (duration and reason are ignored for deletions)
+
+__Examples:__
+* `RKLINE myleaf.dom.tld *@top.kek.org 0 lolnope` => Adds a permanent K-Line on `myleaf.dom.tld` for everyone connecting from `top.kek.org`
+* `RKLINE myleaf.dom.tld -*@top.kek.org 0 lolnope` => Deletes this same K-Line
+* `RZLINE myleaf.dom.tld *@123.123.123.* 60 lolnope` => Adds a one-minute Z-Line on `myleaf.dom.tld` for everyone connecting from `123.123.123.*`
+
+Since the snomask notices on the target server are only sent to __local__ opers, I had to hack some hook bs to get the executing oper to see that shit. =]
+
+__Protip:__ I didn't include a method for listing the remote server's `*-Lines`, you can already use `/stats K myleaf.dom.tld` for that fam. ;]

+ 30 - 0
man/sacmds.md

@@ -0,0 +1,30 @@
+# sacmds
+I've gotten multiple requests to have a module to implement `SA*` commands (like `SANICK`, `SAUMODE`) within the IRCd instead of through services (usually `/os SVSNICK` etc). Right now it allows privileged opers to forcibly change someone's nickname and/or their usermodes. =] You cannot use any of these commands on U-Lined users, raisins should b fairly obvious.
+
+This m0d also implements a snomask `+A` to indicate who can __see__ the related server notices. I had to pick `A` (ykno, like __A__dmin?) cuz all of `cCnNsS` are already taken, so rip. There are also operprivs for every "subcommand" to indicate who can use which. You also gotta have one of the operprivs to set the snomask. ;] The target user won't get a visual cue at all for umode changes, unlike when using services. This means no notice, no `<nick> sets mode <modestr>` in their console, etc.
+
+__Config blocks:__
+First, make sure an operclass has one or more of the operprivs:
+    operclass netadmin-sacmds {
+    	parent netadmin;
+    	privileges {
+    		sanick;
+    		saumode;
+    	};
+    };
+
+And assign it to one or more oper(s). Then (optionally), to easily and automatically enable the snomask for them, __append__ the `A` flag to your current `set::snomask-on-oper`:
+    set {
+    	// Rest of your set block goes here
+    	snomask-on-oper "cfkevGqsSoA";
+    };
+
+This won't set the snomask for opers w/o the privilege, as the IRCd executes the `on-oper` thingy on behalf/in name of the oper. As such, operprivs __are__ verified beforehand. ;]
+
+__Syntax:__
+`SANICK <fromnick> <tonick>`
+`SAUMODE <nick> <umodes>`
+
+__Examples:__
+`SANICK ayy bastem` => Changes the nick `ayy` to `bastem`
+`SAUMODE bastem -x+Z` => Removes `bastem`'s virtual host and enables the `secureonlymsg` restriction

+ 2 - 0
man/sajoin_chan.md

@@ -0,0 +1,2 @@
+# [MALV] sajoin\_chan
+Overrides the `SAJOIN` command to also accept a channel name for the victim, instead of just a nick. Requires the operpriv `sajoin`.

+ 15 - 0
man/saprivmsg.md

@@ -0,0 +1,15 @@
+# [MALV] saprivmsg
+Enables privileged 0pers to send messages on behalf of other users. Only those with the new operpriv `saprivmsg` will be able to use it, although all other 0pers with snomask `EYES` will get the notices. Servers, U-Lines and opers are exempt for obvious raisins.
+
+__Config block:__
+    operclass netadmin-saprivmsg {
+    	parent netadmin;
+    	privileges {
+    		saprivmsg;
+    	};
+    };
+
+__Syntax:__
+`SAPRIVMSG <destination user/channel> <user to impersonate> <message>`
+
+Also supports the alias `SASAY`. The first argument __must__ be an online nickname/existing channel and the second must also be an online nickname.

+ 17 - 0
man/signore.md

@@ -0,0 +1,17 @@
+# [SPEC] signore
+Requested by `Jellis` and `Stanley`. This module allows privileged opers to set a server-side ignore of sorts, making 2 users' messages invisible to each other (in private only tho, just muteban them if they shitpost in-channel or something). Servers, U-Lines and opers are exempt for obvious raisins.
+
+Expiring these so-called `I-Lines` is done with an `EVENT` thingy in Unreal, which is set to run every 10 seconds. This means if you set an ignore for 5 seconds (why would you anyways?) it may not expire after eggzacktly 5 seconds. ;] When no expiration is specified the value in `set::default-bantime` is used. Every server checks the expirations themselves. =] Also, they store it in a `ModData` struct so it persists through a rehash without the need for a `.db` fiel. ;] Furthermore, they sync their known `I-Lines` upon server linkage. =]] Other lines such as G-Lines, Z-Lines are also stored in memory and get resynced during a link so these are pretty similar aye.
+
+__Config block:__
+    operclass netadmin-signore {
+    	parent netadmin;
+    	privileges {
+    		signore;
+    	};
+    };
+
+__Syntax:__
+`SIGNORE [-]<ident@host> <ident2@host2> [expire] <reason>`
+
+Also supports the alias `ILINE`. The first 2 arguments may also be online nicknames, they will be resolved to their respective full mask. =] Wildcards `*` and `?` are also supp0rted. Masks cannot overlap each other (e.g. `som*@*` and `s*@*`).

+ 28 - 0
man/textshun.md

@@ -0,0 +1,28 @@
+# [UNC] textshun
+Enables privileged 0pers to drop messages based on nick and body regexes (`T-Lines`), similar to badwords and spamfilter but more specific. It only supports (PCRE) regexes because regular wildcards seem ineffective to me, fucken deal w/ it. ;] Also, you can't have spaces (due to how IRC works) so you'll have to use `\s` and shit. Unreal creates a case-insensitive match so no worries there, it also tells you if you fucked up your regex (and what obv). Only opers with the new operpriv `textshun` will be able to use it, although all others will get the notices since these `T-Lines` are __netwerk wide__ bruh. You'll also get a server notice for when a T-Line is matched. Servers, U-Lines and opers are exempt for obvious raisins.
+
+Expiring shuns is done with an `EVENT` thingy in Unreal, which is set to run every 10 seconds. This means if you set a shun for 5 seconds (why would you anyways?) it may not expire after eggzacktly 5 seconds. ;] When no expiration is specified the value in `set::default-bantime` is used. Every server checks the expirations themselves. =] Also, they store it in a `ModData` struct so it persists through a rehash without the need for a `.db` fiel. ;] Furthermore, they sync their known `T-Lines` upon server linkage. =]] Other lines such as G-Lines, Z-Lines are also stored in memory and get resynced during a link so these are pretty similar aye.
+
+__Config block:__
+    operclass netadmin-textshun {
+    	parent netadmin;
+    	privileges {
+    		textshun;
+    	};
+    };
+
+__Syntax:__
+`TEXTSHUN <ADD/DEL> <nickrgx> <bodyrgx> [expire] <reason>`
+
+Also supports the aliases `TS` and `TLINE`. =]
+
+__Examples:__
+* `TLINE add guest.+ h[o0]+m[o0]+ 0 nope` => All...
+* `TEXTSHUN add guest.+ h[o0]+m[o0]+ nope` => ...of...
+* `TS del guest.+ .+` => ...these add/delete the same T-Line, with no expiration
+* `TLINE add guest.+ h[o0]+m[o0]+ 3600 ain't gonna happen` => Add a T-Line that expires in an hour =]
+* `TLINE add guest.+ h[o0]+m[o0]+ 1h ain't gonna happen` => Ditto ;];]
+* `TLINE` => Show all T-Lines
+* `TS halp` => Show built-in halp
+
+The nick regex is matched against both `nick!user@realhost` and `nick!user@vhost` masks. The timestring shit like `1h` supports up to weeks (so you __can't__ do `1y`).

+ 4 - 0
man/topicgreeting.md

@@ -0,0 +1,4 @@
+# [SPEC] topicgreeting
+`X-Seti` asked for a module that changes a channel's topic to greet someone who just joined. This module implements channel mode `+g` so you can set that shit on a per-channel basis. =]
+
+U-Lines such as NickServ or ButtServ channel bots won't trigger this of course. ;]

+ 4 - 0
man/uline_nickhost.md

@@ -0,0 +1,4 @@
+# uline\_nickhost
+You're probably familiar with the idea of having to do `/msg NickServ@services.my.net` as opposed to just `/msg NickServ`. This can be helpful to counter bots that try to auto-reg their nicks to join channels with `+R` set. ;]
+
+Simply load the module and everyone will have to address __all__ `U-Lines` with the above format. So if your services link's name is `baste.my.hams` you'll have to use `/msg NickServ@baste.my.hams`. This goes for both `PRIVMSG` and `NOTICE` (also includes `CTCP` as that's just `PRIVMSG` wrapped in special characters).

+ 31 - 0
man/websocket_restrict.md

@@ -0,0 +1,31 @@
+# websocket\_restrict
+Some people may wanna impose some restrictions on websocket-connected users, one of deez ~~nuts~~ things could be limiting the ports they can use. Read more about Unreal's websocket support [right here](https://www.unrealircd.org/docs/WebSocket_support).
+
+Since websocket support for non-SSL ports works right out of the box, you're going to need a new listen block for non-SSL connections from websocket users. I used port `8080` for the keks but you can really use as many as you want.
+
+__Config block:__
+    listen {
+    	ip *;
+    	port 8080;
+    	options {
+    		clientsonly;
+		websocket {
+			// One of these must be specified, depending on your client
+			//type text;
+			//type binary;
+		};
+    	};
+    };
+    websocket_restrict {
+    	port 8080;
+    	//port 8443; // If you have an SSL listen block too
+    	zlinetime 60;
+    	channels {
+    		"#chan1"; // Don't forget the "" to make sure Unreal doesn't interpret it as a comment ;]
+    		"#moar";
+    	};
+    };
+
+Now, if any __websocket users__ connect to a port that __isn't__ `8080` their IP will get `GZ-Lined` for the amount of seconds specified with `zlinetime` (defaults to 60). The other way around is true as well; regular clients connecting to a websocket port will be awarded the same `GZ-Line`. I originally had to do that for websocket users cuz they aren't fully online yet, so the special frames wouldn't be formed and sent. This resulted in the client sending the `GET /` command about 5 times and that resulted in 5 snotices too. =] I did the same for regular clients to remain consistent.
+
+The `channels` list is optional; if omitted there will be no channel restrictions, otherwise they can only join the specified ones. They also only apply to websocket users, so regular clients can join their channels too.