When sending a message that is too long, thelounge will split it up into
multiple PRIVMSGs. These will be saved to the sqlite database with
identical timestamps. Thelounge retrieves messages from the DB using
`ORDER BY time DESC`, which under certain circumstances causes these
messages to be loaded and displayed in the wrong order. This PR
addresses that by also ordering by id (only affects messages with
identical timestamps).
Before:
<img width="1050" height="107" alt="image"
src="https://github.com/user-attachments/assets/54fac085-a989-48fa-9538-1faecb09aa44"
/>
After:
<img width="1058" height="114" alt="image"
src="https://github.com/user-attachments/assets/0bb99db9-5a5d-481d-b799-87162d0535e8"
/>
Found by claude:
```
server/plugins/inputs/mute.ts — /mute slash command never persists. Missing client.save(). Mutes set via the command vanish on restart. The socket handler (server/server.ts:768-797) does save.
server/plugins/inputs/mute.ts:18 — /mute #Foo fails when channel was joined as #foo. Uses case-sensitive c.name === arg; IRC channel names are case-insensitive.
```
- Mentions were doing a bunch of mutations; not just uses derived state
- no need for a separate `ClientMention`
- added `extractInputHistory` for shared logic
- tests made by claude
Replace the manual deleteFolder() recursive implementation with
fs.rmSync({recursive: true, force: true}), which handles both files
and directories. This also resolves the ENOTDIR error caused by
.DS_Store and other non-directory entries in the storage folder.
Apparently sqlite started validating this in certain versions.
Crashes on BSDs with:
SQLite version 3.50.4 2025-07-30 19:33:53
sqlite> SELECT msg, type, time, network, channel FROM messages WHERE type = "message";
Parse error: no such column: "message" - should this be a string literal in single-quotes?
time, network, channel FROM messages WHERE type = "message";
error here ---^
The framework may emit messages which do not have a time stamp.
We tried to unconditionally convert the time field, fix that.
The Msg constructor replaces falsey time fields with the current
date so we can also remove the duplication from that codepath.
The publicClient interface is utterly horrific.
It allows any client to inject arbitrary events into the socket.io
event stream.
This should get wrapped into a "plugin" event so that it can get properly
typed, better yet, this should get removed completely.
This is laying the foundation to build a cleaning task that's
sort of database agnostic.
All calls are done by acting on a "DeletionRequest" so interpretation
of the config will go through a single point
So far the bind config only impacted the IRC connections.
However, nothing in our doc comment says that this is intentional.
> ### bind
> Set the local IP to bind to for outgoing connections.
This commit fixes the leak and uses it for all outgoing requests
as described by the docstring.