IRC metadatata extension temporary specification
This document is based on prior work of the following people:
- Kiyoshi Aman, 2012, kiyoshi.aman@gmail.com
- Attila Molnar, 2015-2016, attilamolnar@hush.com
- James Wheare, 2018. james@irccloud.com
This version was put together by k4be (irc.pirc.pl) in 2020-2021.
Introduction
It is generally useful to associate metadata with one's IRC presence, e.g. to make one's homepage or non-IRC contact details more discoverable. There are several mechanisms for doing this, but they typically rely on the presence of services and aren't really suitable for transient metadata such as a user's current location.
This proposal aims to codify one mechanism for working with metadata: metadata may be configured through a client-to-server event created specifically for this purpose.
We hope to get some version of this specification to be ratified by the IRCv3 working group. Meanwhile, as the development there is stagnant, I've decided to create a temporary spec to help client and server developers to implement these features earlier. This document is not intended to be directly included into a specification registry, it should serve only as a description of current implementations. The functionality, as described here, is implemented in UnrealIRCd module (available through the module manager as third/metadata
) - server side, and PIRC web client - client side. It is also known to work with current (at the time of this writing) IRCcloud client with no known issues.
Notes for implementing work-in-progress version
This is a work-in-progress specification.
Software implementing this work-in-progress specification MUST NOT use the unprefixed metadata
capability name. Instead, implementations SHOULD use the draft/metadata-notify-2
capability name to be interoperable with other software implementing a compatible work-in-progress version.
The final version of the specification will use an unprefixed capability name.
Mechanisms
This document defines the following new protocol features:
- Capability:
draft/metadata
(generic) - Capability:
draft/metadata-notify-2
(for IRCcloud compatibility) - ISUPPORT key:
METADATA
- Server notification:
METADATA
- Client command:
METADATA
- Server reply and error numerics
Capability
If METADATA
is supported, it MUST be specified in RPL_ISUPPORT
using the METADATA
key. Servers MAY specify a limit on the number of explicitly-set keys per-user; the format in that case MUST be METADATA=<integer>
, where <integer>
is the limit. For client compatibility, two capabilities draft/metadata
and draft/metadata-notify-2
MUST also be advertised by the server.
The ABNF format of the draft/metadata
capability and value is:
capability ::= 'metadata' ['=' tokens]
tokens ::= token [',' token]*
token ::= key ['=' value]
key ::= <sequence of a-zA-Z0-9_.:- >
value ::= <utf8>
The value keys are defined as follows:
maxsub
: the maximum number of keys a client is allowed in its subscripion list. See the Metadata subscriptions section for more details.maxkey
: the maximum number of keys a client is allowed to set on its own nickname.
Server notification
Clients that issued the METADATA SUB
subcommand MUST be able to handle the METADATA
server notification. After receiving this command, servers MAY send these notifications to clients at any time.
The format of the METADATA
server notication is:
METADATA <Target> <Key> <Visibility> <Value>
Target
MUST be a valid nickname or channel name.
Key
MUST be a valid key name
Visibility
MUST be an asterisk (*
) for keys visible to everyone, or an implementation-defined value which describes the key's visibility status; for instance, it MAY be a permission level or flag. It is not known to be used by any existing implemetation.
Value
MUST be a UTF-8 encoded value.
Client command
The format of the METADATA
client command is:
METADATA <Target> <Subcommand> [<Param 1> ... [<Param n>]]
Target
MUST be a valid nickname or channel name. Clients MAY use the asterisk symbol (*
) when targeting their own nickname.
Subcommand
MUST be one of the following, described in detail along with any Param
further in the document:
Numerics
The following numerics 760 through 775 are reserved for metadata, with these labels and parameters:
No. | Label | Parameters |
---|---|---|
761 | RPL_KEYVALUE |
<Target> <Key> <Visibility>[ :<Value>] |
762 | RPL_METADATAEND |
:end of metadata |
764 | ERR_METADATALIMIT |
<Target> :metadata limit reached |
765 | ERR_TARGETINVALID |
<Target> :invalid metadata target |
766 | ERR_NOMATCHINGKEY |
<Target> <Key> :no matching key |
767 | ERR_KEYINVALID |
:<InvalidKey> |
768 | ERR_KEYNOTSET |
<Target> <Key> :key not set |
769 | ERR_KEYNOPERMISSION |
<Target> <Key> :permission denied |
770 | RPL_METADATASUBOK |
:<Key1> [<Key2> ...] |
771 | RPL_METADATAUNSUBOK |
:<Key1> [<Key2> ...] |
772 | RPL_METADATASUBS |
:<Key1> [<Key2> ...] |
773 | ERR_METADATATOOMANYSUBS |
<Key> |
774 | ERR_METADATASYNCLATER |
<Target> [<RetryAfter>] |
775 | ERR_METADATARATELIMIT |
<Target> <Key> <RetryAfter> :<Value> |
776 | ERR_METADATAINVALIDSUBCOMMAND |
<Subcommand> :invalid metadata subcommand |
Reference table of numerics and the subcommands of METADATA
or any other commands that produce them:
Label | GET | LIST | SET | CLEAR | SUB | UNSUB | SUBS | SYNC | Other |
---|---|---|---|---|---|---|---|---|---|
RPL_KEYVALUE |
* | * | * | * | |||||
RPL_METADATAEND |
* | * | * | * | * | * | |||
ERR_METADATALIMIT |
* | ||||||||
ERR_TARGETINVALID |
* | * | * | * | * | * | * | * | |
ERR_NOMATCHINGKEY |
* | ||||||||
ERR_KEYINVALID |
* | * | * | * | |||||
ERR_KEYNOTSET |
* | ||||||||
ERR_KEYNOPERMISSION |
* | * | * | * | * | ||||
RPL_METADATASUBOK |
* | ||||||||
RPL_METADATAUNSUBOK |
* | ||||||||
RPL_METADATASUBS |
* | ||||||||
ERR_METADATATOOMANYSUBS |
* | ||||||||
ERR_METADATASYNCLATER |
* | * | JOIN |
||||||
ERR_METADATARATELIMIT |
* |
Each subcommand documentation describes the reply and error numerics it expects from the server, but here are brief descriptions of numerics that are used for multiple commands:
Replies:
RPL_KEYVALUE
reports the values of metadata keys.RPL_METADATAEND
delimits the end of a sequence of metadata replies.
Errors:
ERR_TARGETINVALID
when a client refers to an invalid target.ERR_KEYINVALID
when a client refers to an invalid key.ERR_KEYNOPERMISSION
when a client attempts to access or set a key on a target without sufficient permission.ERR_METADATAINVALIDSUBCOMMAND
when a client used aMETADATA
subcommand which is not defined.
Keys and values
Key names MUST be restricted to the ranges A-Z
, a-z
, 0-9
, and _.:-
and are case-insensitive. Key names MUST not start with a colon (:
).
Values are unrestricted, except that they MUST be encoded using UTF-8.
The expected client behaviour of individual metadata keys SHOULD be defined in separate specifications and listed in the IRCv3 extension registry.
Servers MAY impose a limit on the number of keys a client is allowed to set via the maxkey
capability value.
Servers MAY impose a limit on the number of keys a client is allowed in its subscripion list via the maxsub
capability value.
Subcommands
METADATA GET
This command allows lookup of some keys. The format MUST be as follows:
METADATA <Target> GET key1 key2 ...
Multiple keys may be given.
The response will be either RPL_KEYVALUE
, ERR_KEYINVALID
or ERR_NOMATCHINGKEY
for every key in order.
Servers MAY replace certain metadata, which is considered not visible for the requesting user, with ERR_NOMATCHINGKEY
or with ERR_KEYNOPERMISSION
.
Errors: ERR_NOMATCHINGKEY
, ERR_KEYINVALID
, ERR_KEYNOPERMISSION
.
METADATA LIST
The format MUST be as follows:
METADATA <Target> LIST
This subcommand MUST list all currently-set metadata keys along with their values. The response will be zero or more RPL_KEYVALUE
events, followed by a RPL_METADATAEND
event.
Servers MAY omit certain metadata, which is considered not visible for the requesting user, or replace it with ERR_KEYNOPERMISSION
.
In case of invalid target RPL_METADATAEND
MUST NOT be sent.
Errors: ERR_KEYNOPERMISSION
.
METADATA SET
This subcommand is used to set a required key to an optional value. If no value is given, the key is removed; otherwise, the value is assigned to the key. The format of METADATA SET
MUST be as follows:
METADATA <Target> SET <Key> [:Value]
Servers MUST respond to requests to set or remove a key whose name is invalid with only an ERR_KEYINVALID
event and fail the request.
Servers MUST respond to requests to remove a key that has a valid name but is not set with only an ERR_KEYNOTSET
event and fail the request.
Servers MAY respond to certain keys, considered not settable by the requesting user, or otherwise disallowed by the server, with ERR_KEYNOPERMISSION
.
It is an error for users to set keys on targets for which they lack authorization from the server, and the server MUST respond with ERR_KEYNOPERMISSION
and fail the request.
Servers MAY respond with only an ERR_METADATARATELIMIT
event and fail the request. When a client receives an ERR_METADATARATELIMIT
event, it SHOULD retry the METADATA SET
request at a later time. If the ERR_METADATARATELIMIT
event contains the OPTIONAL <RetryAfter>
parameter, the parameter value MUST be a positive integer indicating the minimum number of seconds the client SHOULD wait before retrying the request.
If the request is successful the server MUST carry out the requested change and the response MUST be one RPL_KEYVALUE
event, representing what was actually stored by the server, and one RPL_METADATAEND
event.
Errors: ERR_METADATALIMIT
, ERR_KEYINVALID
, ERR_KEYNOTSET
, ERR_KEYNOPERMISSION
, ERR_METADATARATELIMIT
METADATA CLEAR
This subcommand MUST remove all metadata, equivalently to using METADATA SET
on all currently-set keys with an empty value. The format of METADATA CLEAR
MUST be as follows:
METADATA <Target> CLEAR
The server MUST respond with one RPL_KEYVALUE
event per cleared key and one RPL_METADATAEND
event.
Servers MAY omit certain metadata, which is considered not settable by the requesting user, or replace it with ERR_KEYNOPERMISSION
.
It is an error for users to use this subcommand on targets for which they lack authorization from the server. Servers MAY reject this subcommand for channels, using ERR_KEYNOPERMISSION
with an asterisk (*
) in the <Key>
field.
Errors: ERR_KEYNOPERMISSION
METADATA SUB
This subcommand is used to subscribe to metadata keys.
Syntax:
METADATA * SUB <key1> [<key2> ...]
The server MUST reply with zero or more numerics of the following types in any order: RPL_METADATASUBOK
, ERR_KEYINVALID
, ERR_KEYNOPERMISSION
and zero or one ERR_METADATATOOMANYSUBS
numeric.
The server MUST end the reply with one RPL_METADATAEND
numeric.
The server MUST process the keys in the given order. This is critical when determining which keys the client gets subscribed to in case the server limits the number of keys the client can subscribe to.
If the client is subscribed to too many keys then the server MUST include a ERR_METADATATOOMANYSUBS
numeric in its reply and not process any further keys in the command.
The <key>
parameter of this numeric is the first key that the client was not subscribed to.
If the client successfully subscribes to a key it is not subscribed to then the key MUST appear in a RPL_METADATASUBOK
reply numeric.
If the client tries to subscribe to a key it is already subscribed to then the client remains subscribed to the key. In case such a key is processed in a request the key MUST appear at least once in a RPL_METADATASUBOK
numeric in the reply.
Servers MUST respond to requests to subscribe to a key whose name is invalid with a ERR_KEYINVALID
numeric.
Servers MAY additionally respond to requests to subscribe to a key that the client has no privilege to access with a ERR_KEYNOPERMISSION
numeric. Even if a server does that, the subscription MUST still be successful. This is because in this case the ERR_KEYNOPERMISSION
numeric only serves as a warning, indicating that the client will not receive METADATA events about this key unless it acquires the necessary (implementation defined) privileges later.
METADATA UNSUB
This subcommand is used to unsubscribe from metadata keys.
Syntax:
METADATA * UNSUB <key1> [<key2> ...]
The reply of the server MUST be zero or more numerics of the following types in any order: RPL_METADATAUNSUBOK
, ERR_KEYINVALID
.
Then the server MUST end the reply with one RPL_METADATAEND
numeric.
If a client successfully unsubscribes from a key it is subscribed to then the key MUST appear in a RPL_METADATAUNSUBOK
reply numeric.
If a client tries to unsubscribe from a key that it is not subscribed to then the client remains not subscribed to the key and the key MUST appear at least once in a RPL_METADATAUNSUBOK
numeric in the reply.
Servers MUST respond to requests to subscribe to a key whose name is invalid with a ERR_KEYINVALID
numeric.
METADATA SUBS
This subcommand can be used to get a list of keys which the client is subscribed to.
Syntax:
METADATA * SUBS
The server MUST reply with zero or more RPL_METADATASUBS
numerics and then one RPL_METADATAEND
numeric.
The replied RPL_METADATASUBS
numerics, collectively, MUST contain all keys the client is subscribed to exactly once and MUST NOT contain keys the client is not subscribed to.
The order of the keys is undefined.
METADATA SYNC
This subcommand requests the full synchronization of metadata associated with the given target.
Syntax:
METADATA <Target> SYNC
The result of this subcommand is either zero or more METADATA events on success, or a ERR_METADATASYNCLATER
numeric if the synchronization cannot be performed at this time.
For details, please see the Postponed synchronization subsection of the Metadata notifications section.
Metadata Notifications
A client can either be subscribed to a key, or not subscribed to it.
The server MUST allow a client to subscribe to any valid keys, even to privileged keys when the client has no privilege to access that key at the time of subscription.
If a client is subscribed to a metadata key and has adequate privileges to get notifications about that key then it gets METADATA events about the key as described above.
If a client is not subscribed to a metadata key then it will not get METADATA events about it, however the client can use METADATA GET
, METADATA LIST
or other means available to obtain the value of the key.
By default, the client is not subscribed to any keys.
Managing subscriptions are possible with the protocol described below.
Clients are subscribed to notifications for channels they join. That means both channel metadata, and other users on the channel.
Clients may discontinue notifications for channels by parting the channel. Clients are automatically subscribed to notifications for their own metadata, excluding changes made by the clients themselves.
Notifications use the METADATA
event, the format of which is as follows:
METADATA <Target> <Key> <Visibility>[ :<Value>]
<Target>
refers to the entity which had its metadata changed. <Visibility>
MUST be *
for keys visible to everyone, or a token which describes the key's visibility status in an implementation-defined way; for instance, it may be a permission level or flag.
Clients MUST handle all metadata notifications, whether they explicitly requested them or not.
Metadata propagates to clients automatically under certain conditions:
- Clients SHOULD have current metadata of targets propagated to them upon subscription.
- Clients SHOULD be notified about channel metadata after joining a channel which has set any of the subscribed keys.
- Clients SHOULD be notified about other channel members' metadata after joining a channel.
- Clients SHOULD have new metadata of a client propagated to them when a value of a subscribed key for another client sharing at least one channel is set, unset or changed.
- Clients SHOULD have new metadata of a channel propagated to them when a value of a subscribed key for a channel the client is on is set, unset or changed.
Postponed synchronization
It can happen that a server needs to send a large number of METADATA
events to a client due to the client subscribing to many targets at once. For example, this can happen if the client joins a large channel or when the client is already on some channels and turns on the metadata
capability. In this case the server MAY choose to not propagate the metadata of the newly subscribed targets to the client when the join, the CAP REQ
or the METADATA SUB
subcommand happens, but send a ERR_METADATASYNCLATER
numeric instead.
A server MAY not use the ERR_METADATASYNCLATER
reply, delaying subsequent notifications instead.
ERR_METADATASYNCLATER
Handling ERR_METADATASYNCLATER
signals that the target specified in the numeric has some metadata set that the client SHOULD request synchronization of at a later time.
The client can then use the METADATA SYNC
subcommand to request the synchronization of the metadata of the target.
The [<RetryAfter>]
parameter, if present, indicates the number of seconds the client SHOULD wait before sending the METADATA SYNC
request for the <Target>
.
Examples
These examples show the labels of the numerics (e.g. RPL_METADATASUBOK
) instead of their number (e.g. 775
) in order to aid understanding. In a real implementation, the messages always contain the number of numerics, not a label.
All examples begin with the client not being subscribed to any keys.
Basic subscriping and unsubscribing
C: METADATA * SUB avatar website foo bar
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar website foo bar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * UNSUB foo bar
S: :irc.example.com RPL_METADATAUNSUBOK modernclient :bar foo
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
RPL_METADATASUBOK
numerics in reply to METADATA SUB
Multiple C: METADATA * SUB avatar website foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar website
S: :irc.example.com RPL_METADATASUBOK modernclient :foo
S: :irc.example.com RPL_METADATASUBOK modernclient :bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Invalid key name in reply to subscription
C: METADATA * SUB foo $url bar
S: :irc.example.com RPL_METADATASUBOK modernclient :foo bar
S: :irc.example.com ERR_KEYINVALID modernclient $url :invalid metadata key
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
"Subscribed to too many keys" error in reply to subscription 1
The client first successfully subscribes to some keys and later it tries to subscribe to some more keys, unsuccessfully.
C: METADATA * SUB website avatar foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUB email city
S: :irc.example.com ERR_METADATATOOMANYSUBS modernclient email
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
"Subscribed to too many keys" error in reply to subscription 2
This is like the previous case, except when the second METADATA SUB happens the server accepts the first 2 keys (email
, city
) but not the rest (country
, bar
, baz
).
C: METADATA * SUB website avatar foo
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUB email city country bar baz
S: :irc.example.com ERR_METADATATOOMANYSUBS modernclient country
S: :irc.example.com RPL_METADATASUBOK modernclient :email city
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :website avatar city foo email
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
"Subscribed to too many keys" error in reply to subscription 3
In this case, the client is trying to subscribe to a key that it is already subscribed to (website
), but the key is not processed because the limit imposed by the server on the number of subscribed keys is reached before the website
key is processed by the server. The client, however, successfully subscribes to the foo
key which was also in the second request, but it appeared before the website
key.
C: METADATA * SUB avatar website
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUB foo website avatar
S: :irc.example.com ERR_METADATATOOMANYSUBS modernclient website
S: :irc.example.com RPL_METADATASUBOK modernclient :foo
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Querying the list of subscribed keys 1
The server replies with a single RPL_METADATASUBS
numeric.
C: METADATA * SUB website avatar foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar bar baz foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Querying the list of subscribed keys 2
The server replies with multiple RPL_METADATASUBS
numerics.
C: METADATA * SUB website avatar foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar
S: :irc.example.com RPL_METADATASUBS modernclient :bar baz
S: :irc.example.com RPL_METADATASUBS modernclient :foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Empty list of subscribed keys
In this case, there are no RPL_METADATASUB
numerics sent.
C: METADATA * SUBS
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Unsubscribing
C: METADATA * SUB website avatar foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar bar baz foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * UNSUB bar foo baz
S: :irc.example.com RPL_METADATAUNSUBOK modernclient :baz foo bar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Subscribing to the same key multiple times 1
C: METADATA * SUB website avatar foo bar baz
S: :irc.example.com RPL_METADATASUBOK modernclient :website avatar foo bar baz
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar bar baz foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUB avatar website
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar bar baz foo website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Subscribing to the same key multiple times 2
The client (erroneously) subscribes to the same key twice in the same command. The server is free to include the key being subscribed to in the RPL_METADATASUBOK
numeric once or twice.
In both cases, the key will only appear once in the reply to a following METADATA SUBS
command.
Once:
C: METADATA * SUB avatar avatar
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Twice:
C: METADATA * SUB avatar avatar
S: :irc.example.com RPL_METADATASUBOK modernclient :avatar avatar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :avatar
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Unsubscribing from a non-subscribed key 1
C: METADATA * SUBS
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * UNSUB website
S: :irc.example.com RPL_METADATAUNSUBOK modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUB website
S: :irc.example.com RPL_METADATASUBOK modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Unsubscribing from a non-subscribed key 2
The client (erroneously) unsubscribes from the same key twice in the same
command. The server is free to include the key being unsubscribed from in the
RPL_METADATAUNSUBOK
numeric once or twice.
Once:
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * UNSUB website website
S: :irc.example.com RPL_METADATAUNSUBOK modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Twice:
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * UNSUB website website
S: :irc.example.com RPL_METADATAUNSUBOK modernclient :website website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Subscribing to a key which requires privileges but without privileges
C: METADATA * SUB avatar secretkey website
S: :irc.example.com ERR_KEYNOPERMISSION modernclient modernclient secretkey :permission denied
S: :irc.example.com RPL_METADATASUBOK modernclient :secretkey website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :secretkey website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Subscribing to invalid keys and a key which requires privileges but without privileges
C: METADATA * SUB $invalid1 secretkey1 $invalid2 secretkey2 website
S: :irc.example.com ERR_KEYNOPERMISSION modernclient modernclient secretkey1 :permission denied
S: :irc.example.com ERR_KEYINVALID modernclient $invalid1 :invalid metadata key
S: :irc.example.com ERR_KEYNOPERMISSION modernclient modernclient secretkey2 :permission denied
S: :irc.example.com ERR_KEYINVALID modernclient $invalid2 :invalid metadata key
S: :irc.example.com RPL_METADATASUBOK modernclient :secretkey1 secretkey2 website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
C: METADATA * SUBS
S: :irc.example.com RPL_METADATASUBS modernclient :secretkey1 secretkey2 website
S: :irc.example.com RPL_METADATAEND modernclient :end of metadata
Setting metadata for self:
METADATA * SET url :http://www.example.com
:irc.example.com RPL_KEYVALUE * url * :http://www.example.com
:irc.example.com RPL_METADATAEND :end of metadata
Setting metadata for channel:
METADATA #example SET url :http://www.example.com
:irc.example.com RPL_KEYVALUE #example url * :http://www.example.com
:irc.example.com RPL_METADATAEND :end of metadata
Setting metadata for another user, no permission:
METADATA user1 SET url :http://www.example.com
:irc.example.com ERR_KEYNOPERMISSION user1 url :permission denied
Setting metadata for self, limit reached:
METADATA * SET url :http://www.example.com
:irc.example.com ERR_METADATALIMIT * :metadata limit reached
Setting metadata for an invalid target:
METADATA $a:user SET url :http://www.example.com
:irc.example.com ERR_TARGETINVALID $a:user :invalid metadata target
Setting metadata with an invalid key:
METADATA user1 SET $url$ :http://www.example.com
:irc.example.com ERR_KEYINVALID $url$
Listing metadata, with an implementation-defined visibility field:
METADATA user1 LIST
:irc.example.com RPL_KEYVALUE user1 url * :http://www.example.com
:irc.example.com RPL_KEYVALUE user1 im.xmpp * :user1@xmpp.example.com
:irc.example.com RPL_KEYVALUE user1 bot-likeliness-score visible-only-for-admin :42
:irc.example.com RPL_METADATAEND :end of metadata
Getting several keys of metadata of the same user:
METADATA user1 GET blargh splot im.xmpp
:irc.example.com ERR_NOMATCHINGKEY user1 blargh :no matching key
:irc.example.com ERR_NOMATCHINGKEY user1 splot :no matching key
:irc.example.com RPL_KEYVALUE user1 im.xmpp * :user1@xmpp.example.com
User sets metadata on a channel:
:user1!~user@somewhere.example.com METADATA #example url * :http://www.example.com
External server updates metadata on a channel:
:irc.example.com METADATA #example url * :http://wiki.example.com
External server sets metadata on a user:
:irc.example.com METADATA user1 account * :user1
Server rate limits setting metadata with a RetryAfter value
METADATA * SET url :http://www.example.com
:irc.example.com ERR_METADATARATELIMIT * url 5 :http://www.example.com
Server rate limits setting metadata with no RetryAfter value
METADATA * SET url :http://www.example.com
:irc.example.com ERR_METADATARATELIMIT * url * :http://www.example.com
ERR_METADATASYNCLATER
and requests a sync later
Client joins a channel, gets C: JOIN #bigchan
S: modernclient!modernclient@example.com JOIN #bigchan
S: :irc.example.com 353 modernclient @ #bigchan :user1 user2 user3 user4 user5 ...
S: :irc.example.com 353 modernclient @ #bigchan :user51 user52 user53 user54 ...
S: :irc.example.com 353 modernclient @ #bigchan :user101 user102 user103 user104 ...
S: :irc.example.com 353 modernclient @ #bigchan :user151 user152 user153 user154 ...
S: :irc.example.com 366 modernclient #bigchan :End of /NAMES list.
S: :irc.example.com ERR_METADATASYNCLATER modernclient #bigchan 4
client waits 4 seconds
C: METADATA #bigchan SYNC
S: :irc.example.com ERR_METADATASYNCLATER modernclient #bigchan 6
client waits 6 seconds
C: METADATA #bigchan SYNC
S: :irc.example.com METADATA user52 foo * :example value 1
S: :irc.example.com METADATA user2 bar * :second example value
S: :irc.example.com METADATA user1 foo * :third example value
S: :irc.example.com METADATA user1 bar * :this is another example value
S: :irc.example.com METADATA user152 baz * :Lorem ipsum
S: :irc.example.com METADATA user3 website * :www.example.com
S: :irc.example.com METADATA user152 bar * :dolor sit amet
...and many more metadata messages
Client sending an invalid subcommand
C: METADATA * FOO :bar
S: :irc.example.com ERR_METADATAINVALIDSUBCOMMAND FOO :invalid metadata subcommand
CAP LS
1
Capability value in C: CAP LS 302
S: CAP * LS :userhost-in-names draft/metadata=foo,maxsub=50,bar draft/metadata-notify-2 multi-prefix
CAP LS
2
Capability value in C: CAP LS 302
S: CAP * LS :draft/metadata=maxsub=25 draft/metadata-notify-2 multi-prefix invite-notify