Browse Source

Split main README into separate per-module manpages lmoa

Wazakindjes 1 year ago
parent
commit
b963ab72a9

File diff suppressed because it is too large
+ 15 - 1234
README.md


+ 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.