title | layout | work-in-progress | copyrights | |||||||
---|---|---|---|---|---|---|---|---|---|---|
IRCv3 Message Modification |
spec |
true |
|
This is a work-in-progress specification.
Software implementing this work-in-progress specification MUST NOT use the
unprefixed +edit
or +delete
tag names. Instead, implementations SHOULD
use the +draft/edit
and +draft/delete
tag names to be interoperable with
other software implementing a compatible work-in-progress version.
The final version of the specification will use unprefixed tag names.
Most text-based chat systems today allow both editing and deleting messages. This allows people to correct typos, remove messages that were accidentally sent, and fix similar issues that regularly occur while typing.
Clients wishing to use these features MUST negotiate the draft/message-tags
and account-tag
capabilities with the server, and SHOULD negotiate the chghost
extension. Additionally, these features rely on messages being sent with the draft/msgid
tag.
The +draft/delete
client tag allows clients to delete their own messages, and channel operators to delete messages in their channel. Its value references the server-provided ID of another message (specifically, the message the sending client wishes to delete).
For instance, the tag +draft/delete=abcd123
indicates that the client wishes to delete the message with the ID abcd123
.
Deleting messages can be done by either the original sender of the message, or by a channel operator if the message was posted in their channel.
When checking the original sender, clients MUST check the message author using the techniques in the "Validating Message Authors" section below. To be precise, if the same account
tag is included on both the original message and the message with the +draft/delete
tag, that's also confirmation of the same user deleting their message.
For channel operators, the check is relatively simple. If the user sending the delete message is at least a channel operator, and has a higher channel privilege than that of the user who originally posted the message, they can delete the message.
Clients SHOULD NOT allow their users to 'delete' messages in their UI if they do not have the privileges to do so. This is to avoid confusion when other users do not see their message deletion (as it would be rejected and ignored by those other clients).
If a +draft/delete
client tag is received but the message cannot be deleted for any reason, it MUST be ignored.
The +draft/edit
client tag allows clients to edit their own messages. It does NOT allow channel operators to edit others' messages. Its value references the server-provided ID of another message (specifically, the message the sending client wishes to edit).
For instance, the tag +draft/edit=abcd1234
indicates that the client wishes to delete the message with the ID abcd1234
.
Editing messages can only be done by the original sender of that message, and by nobody else.
When checking the original sender, clients MUST check the message author using the techniques in the "Validating Message Authors" section below. To be precise, if the same account
tag is included on both the original message and the message with the +draft/edit
tag, that's also confirmation of the same user deleting their message.
Clients SHOULD NOT allow their users to 'edit' messages in their UI if they do not have the privileges to do so. This is to avoid confusion when other users do not see their message edit (as it would be rejected and ignored by those other clients).
+draft/edit
tag MUST be sent with the PRIVMSG
command. When a client receives a PRIVMSG
with the +draft/edit
client tag, and the client has permission to edit the original message, they MUST replace the content of the original message with the content of the new private message that has just been received.
This tag is always sent as a PRIVMSG
to avoid unduly notifying clients that do not support client tags, and will simply receive the edited message in whole instead.
This section describes how users validate the original authors of messages.
Clients implementing this specification MUST implement the account-tag
specification, and SHOULD implement the chghost
extension.
For each channel a client is joined to, the client MUST remember which user and account posted each of the last 20 messages in that channel. Clients MAY remember more history than the last 20 messages if desired.
When remembering which user posted a channel, clients MUST track users across nickname changes, and username and hostname changes if the chghost
extension is negotiated. It must track this while it shares a common channel with each user. If the client no longer shares a common channel with a user, all tracking information with regards to which messages a user has posted, aside from identical nickmask comparison (nickname!username@hostname
) and account comparison MUST no longer be used for validation.
dan
posts a message, changes nickname, and the other clients in the channel must validate.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
S: (#chan1) @draft/msgid=123 :dan!~d@localhost #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
C: (dan) NICK coolguy
S: (#chan1) :dan!~d@localhost NICK coolguy
Clients in #chan1
MUST be able to tell that the user currently with the nick coolguy
originally posted message 123
.
Client deleting their own message after posting it.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
S: (#chan1) @draft/msgid=123 :dan!~d@localhost #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
C: (dan) @+draft/delete=123 TAGMSG #chan1
S: (#chan1) @+draft/delete=123 :dan!~d@localhost TAGMSG #chan1
Clients in #chan1 see that dan
is deleting his own message and processes it.
Channel operator @eve
deleting dan
's message.
C: (dan) PRIVMSG #chan1 :SPAM SPAM SPAM SPAM LOOK AT ALL THIS SPAM SPAM SPAM SPAM
S: (#chan1) @draft/msgid=543 :dan!~d@localhost #chan1 :SPAM SPAM SPAM SPAM LOOK AT ALL THIS SPAM SPAM SPAM SPAM
C: (eve) @+draft/delete=543 TAGMSG #chan1
S: (#chan1) @+draft/delete=543 :eve!e@local.host2 TAGMSG #chan1
Clients in #chan1 see that @eve
, a chanop, is removing dan
's message and processes it.
Client deleting their own message with different clients dan
and coolg
.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
S: (#chan1) @account=coolguy;draft/msgid=123 :dan!~d@localhost #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
C: (coolg) @+draft/delete=123 TAGMSG #chan1
S: (#chan1) @account=coolguy;+draft/delete=123 :coolg!uy@localhost TAGMSG #chan1
Clients in #chan1 should see that the same account that created the message sent the deletion request, and processes it.
Client editing their own message after posting it.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan1's based on X, Y, and Z
S: (#chan1) @draft/msgid=123 :dan!~d@localhost #chan1 :So as we were discussing, #chan1's based on X, Y, and Z
C: (dan) @+draft/edit=123 PRIVMSG #chan1 :So as we were discussing, #chan1's based on X and Y
S: (#chan1) @+draft/edit=123 :dan!~d@localhost PRIVMSG #chan1 :So as we were discussing, #chan1's based on X and Y
Clients in #chan1 see that dan
is editing his own message and processes it.
Channel operator @eve
attempting to edit dan
's message.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan1's based on X, Y, and Z
S: (#chan1) @draft/msgid=543 :dan!~d@localhost #chan1 :So as we were discussing, #chan1's based on X, Y, and Z
C: (eve) @+draft/edit=123 PRIVMSG #chan1 :So as we were discussing, #chan1's based on A, B, and C
S: (#chan1) @+draft/edit=123 :eve!e@local.host2 PRIVMSG #chan1 :So as we were discussing, #chan1's based on A, B, and C
Clients in #chan1 see that @eve
is not dan
, and did not author dan
's message. Clients reject and do not display the edit.
Client editing their own message with different clients dan
and coolg
.
C: (dan) PRIVMSG #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
S: (#chan1) @account=coolguy;draft/msgid=123 :dan!~d@localhost #chan1 :So as we were discussing, #chan5's based on X, Y, and Z
C: (coolg) @+draft/edit=123 PRIVMSG #chan1 :So as we were discussing, #chan1's based on X and Y
S: (#chan1) @+draft/edit=123 :coolg!uy@localhost PRIVMSG #chan1 :So as we were discussing, #chan1's based on X and Y
Clients in #chan1 should see that the same account that created the message sent the edit request, and processes it.
This section is non-normative.
Clients may wish to only allow message edits for a certain length of time after the original message is posted. Or may only allow editing/deleting messages for the last X number of messages in their channel, depending on how message IDs and how related message attributes such as accounts are stored.
Similarly, particularly long-running clients may wish to disable editing or deleting messages in their GUI after a certain amount of time has passed. If they do, the developers of those clients should stay aware of the time or message-count-based limits of message modification, and tune the timings used by their own clients to be similar.
Clients should make an effort to allow a reasonably long amount of message deletion, particularly within channels, to match the asynchronous nature of IRC communications.
Clients should be aware that not all clients may see the modifications they make after posting messages.
Alternatives that have been discussed include making edit
and delete
tags that are validated by the server before being passed along. I have not done this here, since this requires servers to store fairly in-depth message history, for at least as long as clients want to edit messages.
For the edit
tag, it's been suggested to put the new replacement message text in as a separate edit-text
tag instead. I have not done this here as making it a PRIVMSG forces backwards compatibility, in that clients will be able to see the new, edited messages (which can in some cases completely change the context or content of a previously-sent message). In my experience, resending messages to fix edits is already common enough that doing so here shouldn't cause a big fuss.
As well, adding the text as an edit-text
tag rather than using the body of a PRIVMSG causes issues as we allow the maximum length of tags and of the rest of the message to differ (or may in the future, see #281 for context). Doing message editing in the way specified here bypasses any possible complications or issues caused by that in the future.