Skip to content

Conversation

4e554c4c
Copy link

This edit is in response to my client implementations—especially halloy which does not yet support message redaction—and much reaction testing. In the draft phase, most implementations have settled on reactions being nick-based, but message redaction is account based. This creates an asymmetry between creating and removing reactions, which most users consider to be equivalent features.

I think it's OK for authorized users to remove reactions through a REDACT, but this should be performed for moderation reasons. Meanwhile average users may freely use +draft/react and +draft/unreact to change their reactions.

This specification is implemented in squidowl/halloy#1039.

@jwheare
Copy link
Member

jwheare commented Jun 23, 2025

This has also been supported on the receiving end by IRCCloud for about 8 years.

@emersion
Copy link
Contributor

emersion commented Jul 9, 2025

I still believe this is inferior to REDACT.

@skizzerz
Copy link

skizzerz commented Sep 2, 2025

This has a large number of advantages over REDACT:

  1. It doesn't require a completely separate CAP to remove a reaction, because it's just another client tag.
  2. A server may support message-tags but not support message-redaction so the REDACT command is unavailable.
  3. It implements a semantic difference between the user removing their own reaction as part of how users commonly interact with reactions and moderation of reactions. Clients can make use of this semantic difference to handle the "user changes their mind" case and the "this has been moderated out of existence" cases differently.

In every other chat platform that has them, reactions are very easy to change and users do change them with semi-frequent occurrence. A mechanism to accomplish that on IRC really needs to be part of the spec introducing the reaction feature.

I'm building out a proof-of-concept module for solanum implementing this draft (including the +draft/unreact tag) and have no intention of implementing message-redaction anytime soon (if ever; I don't see that one being useful without chathistory) so my point 2 is particularly poignant in the specific case for that ircd.

@Herringway
Copy link

Herringway commented Sep 2, 2025

This has a large number of advantages over REDACT:

  1. It doesn't require a completely separate CAP to remove a reaction, because it's just another client tag.
  2. A server may support message-tags but not support message-redaction so the REDACT command is unavailable.
  3. It implements a semantic difference between the user removing their own reaction as part of how users commonly interact with reactions and moderation of reactions. Clients can make use of this semantic difference to handle the "user changes their mind" case and the "this has been moderated out of existence" cases differently.

Unless the client and the server software choose not to support REDACT entirely, you'll still need to consider how these two features will interact. It just seems like a bunch of extra effort for a case that doesn't appear to exist.

Especially if a server opts to block the client tag, which seems to be a common case right now.

@skizzerz
Copy link

skizzerz commented Sep 2, 2025

Unless the client and the server software choose not to support REDACT entirely, you'll still need to consider how these two features will interact. It just seems like a bunch of extra effort for a case that doesn't appear to exist.

Once this is out of draft, having both react and unreact being specified means that servers which filter client tags would support either both or neither, meaning clients can rely on the functionality existing. This seems like a much better UX than "sometimes you can remove a reaction, sometimes you can't." To avoid the case you mentioned where clients need to implement heuristics and workarounds would happen if this is ratified without unreact, and then unreact is added later. I think avoiding that entirely is better.

@Herringway
Copy link

Unless the client and the server software choose not to support REDACT entirely, you'll still need to consider how these two features will interact. It just seems like a bunch of extra effort for a case that doesn't appear to exist.

Once this is out of draft, having both react and unreact being specified means that servers which filter client tags would support either both or neither, meaning clients can rely on the functionality existing. This seems like a much better UX than "sometimes you can remove a reaction, sometimes you can't." To avoid the case you mentioned where clients need to implement heuristics and workarounds would happen if this is ratified without unreact, and then unreact is added later. I think avoiding that entirely is better.

Servers already exist that are configured to support only one of the two. You cannot rely on servers supporting both or neither.

@skizzerz
Copy link

skizzerz commented Sep 2, 2025

Servers already exist that are configured to support only one of the two. You cannot rely on servers supporting both or neither.

If this is added now and then the spec is later ratified (i.e. taken out of draft) with both +react and +unreact tags as part of the specification, any conforming server supporting the non-draft ratified version would support both or neither. That is entirely the point I am trying to make. The draft phase is designed to be a state of flux where things can change in incompatible ways, but once the spec is ratified then things are pretty much set in stone. Having a good design is important for that step, and would involve adding this to the draft. A tiny bit of pain now solves a whole bunch of pain later rather than making this a perpetual problem.

@ValwareIRC
Copy link
Contributor

Not sure which other IRCds filter message-tags, but with UnrealIRCd, I support this and would happily supply a module that permits usage of this tag.
I will also be implementing this in ObsidianIRC. This has my vote.

I also agree with @skizzerz · I think most IRCds don't filter message-tags, so this would be much simpler to support from a client and server perspective, giving much wider support more easily without having to rely on a CAP that seems unpopular (redact) which also relies on another CAP (chathistory). Even though UnrealIRCd itself supports message redaction through a module from @progval (which deletes from chathistory), I want to point out the chathistory spec says:

the server SHOULD send additional lines relevant to the chat history, including but not limited to TAGMSG, JOIN, PART, QUIT, MODE, TOPIC, and NICK.

This means there might not even be a reaction TAGMSG available for deletion, since it's not mandatory to store TAGMSG in the channel's chathistory.

TLDR: I support and will be implementing (soon) +draft/unreact, it's definitely needed.

@emersion
Copy link
Contributor

emersion commented Sep 9, 2025

Thanks for expanding on the motivations, @skizzerz. There is overwhelming support for this approach, so feel free to move forward.

Copy link

@hhirtz hhirtz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two comments mostly for server implementation considerations that might not be obvious at first glance:

If the server filters reactions or unreactions (e.g. moderation, or unneeded/spurious unreact messages where the unreact value doesn't match any reaction from the user), how does this work with echo-message? Should the server drop the whole message (then you need labeled-response to get the ACK), or only the tags?

Second, with regards to chathistory, when the client sends an unreact message, the server must keep it in history (as opposed to removing the react and the unreact), otherwise some clients might not remove the reaction when they reconnect later.

Otherwise the spec looks good to me.

@ValwareIRC
Copy link
Contributor

If the server filters reactions or unreactions (e.g. moderation, or unneeded/spurious unreact messages where the unreact value doesn't match any reaction from the user), how does this work with echo-message? Should the server drop the whole message (then you need labeled-response to get the ACK), or only the tags?

I think typically the tags is the whole message for doing an +unreact (via TAGMSG). Although there is nothing preventing it from happening, I think it wouldn't make sense for a client to send an +unreact in the same line as a PRIVMSG or other line other than TAGMSG. That said, I would drop the whole line, but I think it's up to you.

Second, with regards to chathistory, when the client sends an unreact message, the server must keep it in history (as opposed to removing the react and the unreact), otherwise some clients might not remove the reaction when they reconnect later.

Currently the chathistory spec doesn't force servers to store anything more than PRIVMSG, anything else is a SHOULD not a MUST (although it would be nice to be able to rely on it for such things)

@4e554c4c
Copy link
Author

Currently the chathistory spec doesn't force servers to store anything more than PRIVMSG, anything else is a SHOULD not a MUST (although it would be nice to be able to rely on it for such things)

If you carefully read the TAGMSG spec, it says that TAGMSGs should be treated as PRIVMSGs (supposedly this includes in chathistory), so I consider this to be a chathistory omission.

The chathistory issue is real, but again I think this burden should fall on the clients. Of course, it depends on how clients store their data, but I know many clients keep a history of of the last fetched date to now, in which case they would never fetch a reaction whose unreaction has not been processed. In this case a client simply needs to keep an integer reaction_count for each reaction, and not display it if it is less than or equal to zero.

@jwheare
Copy link
Member

jwheare commented Sep 22, 2025

The SHOULD allows servers to drop eg typing tag messages from chathistory, which is a good thing. It’s deliberate not an omission.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
7 participants