Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add message-status client tags specification #319

Closed
wants to merge 8 commits into from

Conversation

@MuffinMedic
Copy link
Contributor

@MuffinMedic MuffinMedic commented Aug 23, 2017

Adds three new client tags: typing, delivered, and read

typing rendered view available here.
delivered and read rendered view available here.

Adds three new client tags: typing, delivered, and read
@luxaritas
Copy link

@luxaritas luxaritas commented Aug 23, 2017

As a note, this would resolve ircv3/ircv3-ideas#1

Copy link
Member

@jwheare jwheare left a comment

Thanks for writing this up, great start!

Overall, I think typing should be split off from read/delivery receipts. I can imagine implementors only wishing to support one or the other of them and I'd rather they didn't worry about not having more green ticks in the support tables.

---
## Purpose
This specification defines several `message-status` client tags, which allows clients to send and receive various information about the status of messages before and after they are sent.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

message-status is just a name, rather than a CAP or a tag so shouldn't be code formatted.

The specification includes three client tags for message tracking: `typing`, `delivered`, and `read`. The `typing` tag indicates that a user is currently typing a message to a specific target. `delivered` and `read` provide for delivery and read receipts, respectively, and enable users to know when and by whom a message has been delivered to or read.

For the purpose of this specification, the terms "delivery receipt" and "read receipt" are synonymous with the use of the `delievered` and `read` client tags, respectively.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Typo: delievered


## Format
All tags are sent as a [`TAGMSG`][tags] with an appropriate [`server-time`][time]. `delivered` and `read` must also include the [`labeled-response` tag][labels] of the original message. `typing` can be either `true` or `false`; `delivered` and `read` contain no values.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

labeled-response is inappropriate here, that's just for servers acknowledging receipt back to the sending client. This would be better if the delivered and read tags simply took the referenced msgid as a value.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Also, I'm unclear why server-time is needed at all.

This comment has been minimized.

@MuffinMedic

MuffinMedic Aug 24, 2017
Author Contributor

@jwheare Would it be appropriate to use the draft/msgid tag as a response ID? My understanding is that it identifies a unique message, not a response to one unless used as either a labeled-response or reply tag.

Would using the reply client tag be appropriate for this use case?

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Read the labeled-response spec again, it's completely unrelated to msgid. It's main purpose is for acknowledging echo-message.

I'm not suggesting using the msgid tag, but using its value in the read/delivery receipt tags.

e.g.

C1: @msgid=123 PRIVMSG #chan :hi there
C2: @delivered=123;read=123 TAGMSG #chan

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Worth mentioning that clients should consider all previous messages up to the indicated msgid read/delivered when receiving such a message. And also not to ever go "back in time"

For example:

C1: @msgid=123 PRIVMSG #chan :hi there
C1: @msgid=456 PRIVMSG #chan :hi there again
C2: @delivered=456;read=456 TAGMSG #chan
C2: @delivered=123;read=123 TAGMSG #chan

C2 has received/read up to message 456, the second TAGMSG for 123 can be ignored as superfluous.

This doesn't prevent clients from maintaining their own concept of what has been read, i.e. some clients might want to let users artificially move their read marker back in time as a reference, but that wouldn't be meaningfully propagated to anyone else.

Upon clearing of the text-input field by the user (e.g., message cancelled), the client MUST send a `typing=false` tag to notify other users.

After receiving a `typing=true` tag, the client SHOULD assume the state is unchanged until either a `PRIVMSG`,[`batch`][batch] end, or `typing=false` is received.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

This would work better if typing was a valueless tag that gets sent every few seconds and receiving clients are instructed to unset the status after a timeout of the same number of seconds + some slop.

Removes some complexity from the sending client of having to track typing status, instead of simply sending a debounced "yup still typing" announcement. Also, prevents the case of a stuck typing indicator if the sending client gets disconnected before they can send a typing=false.

This comment has been minimized.

@MuffinMedic

MuffinMedic Aug 24, 2017
Author Contributor

I considered that. How should the timeout be defined, in the spec or leave it up to the network to decide?

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Yup, in the spec, something like 3 seconds seems reasonable.


### `typing`
The `typing=true` client tag SHOULD be sent by the client when the first character is typed in the text-input field. Upon receipt of the `PRIVMSG` or end of a multiline [`batch`][batch], clients SHOULD assume that `typing=false` (no explicit tag needs to be sent).

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Can this apply to NOTICE and TAGMSG (e.g. a reaction) as well?


## Privacy Considerations
Read receipts introduce additional privacy concerns for users who may not wish to inform others of when they have read their messages. Servers SHOULD implement mechanisms at all levels to allow full control over the ability to send and receive `read` client tags. Network operators SHOULD be able to enable or disable the tag server-wide. Channels SHOULD have mechanism in place to allow operators to prevent this tag channel wide (e.g. a channel mode). Users SHOULD have the option of disabling read receipts across the entire network. IRC services SHOULD provide a setting to disable read receipts for an account.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

A lot of these SHOULDs are non-normative implementation considerations, and are covered by the
Moderation considerations section of the message-tags spec.

Copy link
Member

@jwheare jwheare left a comment

Nice one, looks great!

Client tag examples should use the full prefixed draft versions, e.g. +draft/read not read

Also, these need the "Notes for implementing work-in-progress version" headers as seen in other client tag drafts:

https://github.com/ircv3/ircv3-specifications/blob/master/client-tags/reply.md

[C1] @typing :nick!ident@host TAGMSG target

## Use Cases
This specification is intended for use on servers and/or channels where knowing if another user is typing a message would be useful. Current implementations on similar platforms has proven useful, especially in collaborative team environments.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

have proven useful.

## Limitations
Clients must support the [`message-tags`][tags] capability. Specific [Privacy Considerations](#privacy-considerations) are addressed below.

This specification is primarily intended for instances where all users are familiar with each other. In large channels of unknown users, the additional client tags add extra data that must be transmitted over the network with little potentential benefit to the users.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Might also be beneficial in private messages on larger servers.

This specification is primarily intended for instances where all users are familiar with each other. In large channels of unknown users, the additional client tags add extra data that must be transmitted over the network with little potentential benefit to the users.

## Privacy Considerations
Typing status indicators introduce additional privacy concerns for users who may not wish to inform others of when they are creating or replying to a message. Servers SHOULD implement mechanisms at all levels to allow full control over the ability to send and receive `typing` client tags in accordance with the [message-tags moderation considerations][tags].

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

This (and the other spec) are client tag specs, so "Servers SHOULD" doesn't really make sense.

How about this instead of the second sentence:

Clients are encouraged to provide appropriate privacy controls when enabling this feature. Standard implementation guidelines on [message tag moderation considerations][tags] also apply to servers.
For the purpose of this specification, a message is defined as a user-generated `PRIVMSG`, `NOTICE`, `TAGMSG`, or [`batch`][batch] end.

## Format
`delivered` and `read` are sent as a [`TAGMSG`][tags] and must include the [`draft/msgid`][labels] of the original message as the client tag parameter.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

[labels] -> [id]

[C1] :irc.host BATCH -ID
[C2] @draft/read=ID1 :nick!ident@host TAGMSG target
[C2] @draft/read=ID2 :nick!ident@host TAGMSG target
[C2] @draft/read=ID3 :nick!ident@host TAGMSG target

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Still missing the + prefix in examples here and in typing.

## Format
The `typing` tag is sent as a [`TAGMSG`][tags]. The client tag takes no parameters.

The `typing` client tag SHOULD be sent by the client when the first character is typed in the text-input field. If new text is entered into the text-input field following sending of the text-input field content, the client MUST send a new `typing` tag after sending the preceding content.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

The client needs to keep sending typing notifications every (say) 3 seconds while typing, otherwise the receiving end will always time it out 10 seconds after the sender starts typing.

@jwheare jwheare added this to the Roadmap milestone Aug 24, 2017
@@ -27,14 +27,14 @@ For the purpose of this specification, a message is defined as a user-generated
## Format
The `typing` tag is sent as a [`TAGMSG`][tags]. The client tag takes no parameters.

The `typing` client tag SHOULD be sent by the client when the first character is typed in the text-input field. If new text is entered into the text-input field following sending of the text-input field content, the client MUST send a new `typing` tag after sending the preceding content.
The `typing` client tag SHOULD be sent by the client when the first character is typed in the text-input field and after every 3 seconds of a non-empty text-input field to avoid a state change. If new text is entered into the text-input field following sending of the text-input field content, the client MUST send a new `typing` tag after sending the preceding content.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

How about replacing this paragraph with something like:

The typing notification SHOULD be sent by clients whenever any update is made to the text-input field. Input event handlers SHOULD be throttled so that typing notifications are not sent within 3 seconds of each other.

This allows clients to throttle more aggressively if they choose, but I think that's OK.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

Also, we should probably recommend NOT sending typing notifications if the user is typing a /slash command.

@@ -27,14 +27,14 @@ For the purpose of this specification, a message is defined as a user-generated
## Format
The `typing` tag is sent as a [`TAGMSG`][tags]. The client tag takes no parameters.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

For consistency with other client tag specs, how about this:

A typing notification is represented by a [`TAGMSG`][tags] command sent with a tag using the client-only prefix `+` and no value:

    +draft/typing

We can then refer to just "typing notifications" without backticks in the rest of the spec.


After receiving a `typing` tag, the client SHOULD assume the state is unchanged until either a message end is received, or a period of 10 seconds has elapsed from when the last `typing` client tag was received and none of the previously defined message types were received in the appropriate target.
After receiving a `typing` tag, the client SHOULD assume the state is unchanged until either a message end is received, or a period of 3 seconds has elapsed from when the last `typing` client tag was received and none of the previously defined message types were received in the appropriate target.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

The recipient timeout here should be longer than the throttling on the sender's end to allow for network delays. 6 seconds maybe?

After receiving a typing notification, clients SHOULD assume the sender is still typing until either a message is received, the sender leaves the channel or quits the server, or at least 6 seconds have elapsed since their last typing notification was received.

Again, this lets clients wait more than 6 seconds, but I think that's OK too.

@jwheare
Copy link
Member

@jwheare jwheare commented Aug 24, 2017

Neat! Will have a go at an implementation.

@dequis
Copy link
Contributor

@dequis dequis commented Aug 24, 2017

Prior art for typing notifications

Bitlbee has a typing notifications implementation with CTCP TYPING (which makes it unsuitable for other servers where CTCP is likely to actually get delivered to the other side), written back in 2010. Implementation: (1), (2), (3). Client scripts: irssi, weechat

It has three values:

Value Bitlbee constant Libpurple constant XMPP equivalent Meaning
0 FALSE PURPLE_NOT_TYPING active Not typing
1 OPT_TYPING PURPLE_TYPING composing Currently typing
2 OPT_THINKING PURPLE_TYPED paused Stopped typing with text left in the box ("stale")

The XMPP values are defined in XEP-0085 - section 2 has more definitions and section 5.2 has "MUST"/"SHOULD" requirements level for each. Only active and composing are MUST. Other two values are defined by that spec, inactive and gone, but they are not very relevant to this.

Of all other IM protocols I see implementations for, the only ones who care about the third state are XMPP, OSCAR (AIM/ICQ), and google hangouts (the newer proprietary protocol, not XMPP)

Some of them rely on timeouts to unset it, some of them expect it to last forever. In the case of bitlbee all of them rely on timeouts to simplify things. The timeout is specified in the IRC client side, the irssi script is based on the time required for MSN/skype, 7 seconds, and the weechat script used 4 seconds. All values are arbitrary and no need to keep them the same.

Worth noting that XMPP's XEP-0085 does the opposite, and disallows sending multiple composing messages in a row.

Prior art for delivered/read notifications

Bitlbee doesn't cover delivered/read notifications. Read can be inferred by the presence of any typing notifications (even with value 0), or the active state in XMPP, but that's not recommended or reliable.

There's a more modern (but less widespread, and still experimental) XMPP spec, XEP-0333 "chat markers" which covers the rest of the functionality. IMO, it supersedes the earlier "message delivery receipts" (per-message acks) and is much simpler, and much more like this spec or other modern messaging systems. TL;DR: you leave a mark at some message ID. Marks only move forward. You can skip marking messages in the middle. It suports three states:

  • received -- the message has been received by a client.
  • displayed -- the message has been displayed to a user in a active chat and not in a system notification.
  • acknowledged -- the message has been acknowledged by some user interaction e.g. pressing an acknowledgement button.

I'm not sure of the usefulness of the third one.

@jwheare
Copy link
Member

@jwheare jwheare commented Aug 24, 2017

Nice, might be worth splitting out the long run-on sentence of conditions at some point, but seems alright.

Should clients also send typing-done if they pause with stuff in the text box and they have auto-away detection? e.g. using something like IRCCloud and closed the app.


Both client tags follow the same format. Clients MUST send a `delivered` tag immediately upon receipt of the message, including the [`draft/msgid`][id] as the client tag parameter. Clients MUST send a `read` tag when the message is first brought into view (e.g. the correct target with the corresponding message is in focus). If the message is delivered and read at the same time, clients MAY send both tags in the same `TAGMSG` or send `delivered` followed by `read` as separate `TAGMSG`s. Clients SHOULD NOT elect to send only a `read` tag and MUST NOT send `read` before `delivered`.

A `delivered` and `read` tag MUST be sent for each unique `draft/msgid`. If a [`batch`][batch] is received, the client MUST NOT send a single `delivered` and `read` for the entirety of the batch. Clients MAY send `delivered` and `read` tags before a [`batch`][batch] end is received. Upon receipt of a `delivered` or `read` tag, clients SHOULD assume all previous messages in the given target have also been delivered or read by the user as appropriate.

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

SHOULD. It would be a pain for some clients to implement READ status reliably.

This comment has been minimized.

@dequis

dequis Aug 24, 2017
Contributor

Yeah in general it would be nice to have all the sending features opt-in, and being able to be compliant with both specs by supporting receiving.

[C1] @batch=ID;draft/msgid=ID3;time=YYYY-MM-DDThh:mm:ss.sssZ :nick!ident@host PRIVMSG target :message
[C2] @+draft/delivered=ID3 :nick!ident@host TAGMSG target
[C1] :irc.host BATCH -ID
[C2] @+draft/read=ID1 :nick!ident@host TAGMSG target

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

Flooding the IRC server.

19:10:04) <Zarthus> So let's say I'm using weechat, and I attach after 5 days of inactivity. I hop over to #ircv3
(19:10:14) <Zarthus> then my client sends a huge batch of 5,000 messages being read
(19:10:18) <@jwheare> you mark all as read
(19:10:31) <@jwheare> your client sends one notification with the latest message id
## Use Cases
This specification is intended for use on servers and/or channels where knowing if another user is typing a message would be useful. Current implementations on similar platforms have proven useful, especially in collaborative team environments.

## Limitations

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

Not quite a limitation, but it is worth mentioning that copy-and-paste exists. Perhaps a client should wait a little bit before sending active because some messages are finished typing in less than 100ms.

This comment has been minimized.

@jwheare

jwheare Aug 24, 2017
Member

That would be covered by typing-paused.

## Format
A typing notification is represented by a [`TAGMSG`][tags] command sent with a `typing` tag using the client-only prefix `+` and possible values of `active`, `paused`, and `done`.

The typing-active notification SHOULD be sent by clients whenever any update is made to the text-input field and the text is not a "/slash command". If the user begins typing in the text-input field and pauses typing without clearing the text-input field, the client SHOULD send a typing-paused notification until typing is resumed or the text-input field is cleared. If the user clears the text-input field without sending a message, the client SHOULD send a typing-done notification.

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

Caveat: Client-side scripts.

Example: mIRC has ON INPUT events that .. unfortunately enough .. can be used to halt incoming messages. Rare edge case that could end up sending a "I am typing .." when the message will never be sent to the channel.

Some users run scripts that would transform !<whatever> into some sort of /slash command equivelent. People are dumb.

## Format
A typing notification is represented by a [`TAGMSG`][tags] command sent with a `typing` tag using the client-only prefix `+` and possible values of `active`, `paused`, and `done`.

The typing-active notification SHOULD be sent by clients whenever any update is made to the text-input field and the text is not a "/slash command". If the user begins typing in the text-input field and pauses typing without clearing the text-input field, the client SHOULD send a typing-paused notification until typing is resumed or the text-input field is cleared. If the user clears the text-input field without sending a message, the client SHOULD send a typing-done notification.

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

Caveat: NOTICEs

Line 22 suggests NOTICEs, but I don't know a single client that has a NOTICE UI and we always have to write /notice <nick> <message>

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

Caveat to caveat: Multi-target notices. e.g. /notice nick,nick2,nick3 <message>


Input event handlers SHOULD be throttled so that typing notifications are not sent within 3 seconds of each other for a given target.

After receiving a typing notification, clients SHOULD assume the sender is still typing until either a message is received, the sender leaves the channel or quits the server, or a done-notification is received. If at least 30 seconds have elapsed since the last typing-paused notification was received or at least 6 seconds have passed since the last typing-active notification was received and no typing-paused notification was received, clients SHOULD assume the user is no longer typing.

This comment has been minimized.

@Zarthus

Zarthus Aug 24, 2017

I feel like this paragraph could be rephrased to make more sense. It feels very stictched together and constructed with arbitrary limitations.

"A typing notification ends under the following conditions: ..." perhaps might make more sense.

## Format
`delivered` and `read` are sent as a [`TAGMSG`][tags] and must include the [`draft/msgid`][id] of the original message as the client tag parameter.

Both client tags follow the same format. Clients MUST send a `delivered` tag immediately upon receipt of the message, including the [`draft/msgid`][id] as the client tag parameter. Clients MUST send a `read` tag when the message is first brought into view (e.g. the correct target with the corresponding message is in focus). If the message is delivered and read at the same time, clients MAY send both tags in the same `TAGMSG` or send `delivered` followed by `read` as separate `TAGMSG`s. Clients SHOULD NOT elect to send only a `read` tag and MUST NOT send `read` before `delivered`.

This comment has been minimized.

@ProgVal

ProgVal Sep 17, 2017
Contributor

Clients MUST send a delivered tag immediately upon receipt of the message

Shouldn't this be changed to allow clients to throttle outgoing messages?

@jwheare
Copy link
Member

@jwheare jwheare commented Oct 9, 2018

We've got an implementation of typing in IRCCloud in the Slack gateway now and it works well. I'd be happy to merge that, pending any last minute nitpick edits.

Read and delivered still have open questions about their suitability in channels, but might still be useful to spec scoped to private messages only? Either way, would be good to split these into separate PRs so we can resolve and merge them independently. @MuffinMedic you still around to do that?

@MuffinMedic MuffinMedic closed this Nov 4, 2018
@MuffinMedic MuffinMedic deleted the MuffinMedic:message-status branch Nov 4, 2018
@MuffinMedic
Copy link
Contributor Author

@MuffinMedic MuffinMedic commented Nov 4, 2018

Moving to separate PRs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

6 participants
You can’t perform that action at this time.