- If a user is muted, the `userlist_muted` class is added to the
corresponding `.userlist_item`.
- If the user is shadowmuted, the `userlist_smuted` and `userlist_muted`
classes are added.
- If the user is AFK, the `userlist_afk` class is added.
When the chandump is saved, the size of the file is checked. If it is over the limit, moderators are displayed a message indicating that the channel is too large and they should remove extra playlist items, filters, and/or emotes.
This is a partial solution for #421.
Whenever a urlRetrieve() fails due to an unexpected error (ENOTFOUND, ETIMEDOUT, Socket hang up, etc.), the domain handler and the global exception handler would detect this and not crash the server, however the dirty internal state would somehow prevent future HTTP requests from completing successfully.
Removed domain usage since that feature is marked "unstable" and is rumored to be marked for deprecation in future versions of node. Using the "error" event of the request object itself, which means errors are local in scope and won't pollute global state. This should have been the solution originally, but when urlRetrieve() was written, I was not as familiar with node.
The underlying cause of #419 is the default utf8 collation in MySQL/MariaDB, which only supports the base plane of Unicode (\u0000-\uffff). By changing the collation to utf8mb4_general_ci, stuff like ban reasons and profile text may have emoji and other non-base-plane Unicode.
The charset for playlist titles is NOT changed, and non-base-plane characters are replaced by question marks. This is because switching to utf8mb4 would make the primary key too long.
Instead of silently failing when browser policy blocks HTTP embeds over HTTPS, pre-fill the video div with an error message and attempt to salvage the link with s/http/https/g.