IRC: no history backfill — implement IRCv3 chathistory #73

Closed
opened 2026-09-02 00:04:16 -04:00 by Salastil · 1 comment
Owner

IRC negotiates exactly two capabilities: WANTED_CAPS = ["server-time", "multi-prefix"] (backend/irc.rs:477). draft/chathistory is not among them, so there is no backfill of any kind — getBacklog serves only the local SQLite scrollback, and a fresh join shows nothing that was said before you arrived.

Most modern IRCds worth using (Ergo, and InspIRCd/UnrealIRCd with the right module) support it.

Done looks like: request draft/chathistory and batch, and page CHATHISTORY BEFORE on scroll, the way Discord's extend_history does.

IRC negotiates exactly two capabilities: `WANTED_CAPS = ["server-time", "multi-prefix"]` (`backend/irc.rs:477`). `draft/chathistory` is not among them, so there is no backfill of any kind — `getBacklog` serves only the local SQLite scrollback, and a fresh join shows nothing that was said before you arrived. Most modern IRCds worth using (Ergo, and InspIRCd/UnrealIRCd with the right module) support it. **Done looks like:** request `draft/chathistory` and `batch`, and page `CHATHISTORY BEFORE` on scroll, the way Discord's `extend_history` does.
Author
Owner

Finished — https://git.salastil.com/Salastil/nobilis/commit/d106147

The capability list was server-time and multi-prefix. It now also requests message-tags, batch, and chathistory under both its spellings — the capability was draft/chathistory for years and is chathistory now, and a server offering one and not the other is the ordinary case.

message-tags is what makes the rest possible. IRC has no message id, so the daemon generates one, and a generated id can never match the message it is a second copy of. Replayed history would therefore have arrived as a fresh copy of everything already on screen. With msgid the dedup every other protocol here relies on works for IRC too — after a reconnect as much as after a backfill.

History is requested on joining a channel rather than on connecting, because a channel nobody opens is history nobody reads. Paging further back happens on scroll. That one is watched for rather than awaited, and the shape is worth being honest about: a batch ending is not something an RPC call can be handed, so the store is polled for up to three seconds. The wait ends the moment anything lands, and being wrong costs a page that fills in a moment later rather than a page that is missing.

Nothing is asked for unless the server granted it — capabilities are requested without waiting for the answer, so what was actually granted is recorded from the ACK and cleared when the connection ends. A server that gave history last time is not promising to this time.

Note on your networks: none of Libera, Rizon, coreirc or abjects implement chathistory today, so the caps are refused and nothing is requested. Verified against all four just now — they connect clean with no errors. Ergo-based networks will get history immediately.

Also included, since it was the same gap in miniature: a bare MODE on join. Servers announce a change but never the current state, so a channel joined before anything changed showed no modes at all. #ELITEWAREZ now reports +mnt on sight, which is the difference between "why did my message not appear" and knowing the channel is moderated.

Finished — https://git.salastil.com/Salastil/nobilis/commit/d106147 The capability list was `server-time` and `multi-prefix`. It now also requests `message-tags`, `batch`, and chathistory under both its spellings — the capability was `draft/chathistory` for years and is `chathistory` now, and a server offering one and not the other is the ordinary case. **`message-tags` is what makes the rest possible.** IRC has no message id, so the daemon generates one, and a generated id can never match the message it is a second copy of. Replayed history would therefore have arrived as a fresh copy of everything already on screen. With `msgid` the dedup every other protocol here relies on works for IRC too — after a reconnect as much as after a backfill. History is requested on joining a channel rather than on connecting, because a channel nobody opens is history nobody reads. Paging further back happens on scroll. That one is watched for rather than awaited, and the shape is worth being honest about: a batch ending is not something an RPC call can be handed, so the store is polled for up to three seconds. The wait ends the moment anything lands, and being wrong costs a page that fills in a moment later rather than a page that is missing. Nothing is asked for unless the server granted it — capabilities are requested without waiting for the answer, so what was actually granted is recorded from the ACK and cleared when the connection ends. A server that gave history last time is not promising to this time. **Note on your networks:** none of Libera, Rizon, coreirc or abjects implement chathistory today, so the caps are refused and nothing is requested. Verified against all four just now — they connect clean with no errors. Ergo-based networks will get history immediately. Also included, since it was the same gap in miniature: a bare MODE on join. Servers announce a change but never the current state, so a channel joined before anything changed showed no modes at all. #ELITEWAREZ now reports `+mnt` on sight, which is the difference between "why did my message not appear" and knowing the channel is moderated.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Salastil/moho#73