NIP-35 ====== Member List ----------- `draft` `optional` `author:arthurfranca` Groups, channels, communities and the like may use status events to dynamically build a member list. ## Motivation An user may never send a message to a group but still want to be on a group member list for receiving DMs. Also one may want to discover his friends' groups. ## Status Event It is a kind `34549` parameterized replaceable event (PRE) with: - `d` tag which is a reference to the group creation event as `::` if PRE or `:` if replaceable or `` if regular event; - `k` tag as `` for discoverability; - optional `status` tag (see ["Custom Status" section](#custom-status)); - [NIP-40](40.md) `expiration` tag that should be by default 60 days ahead of the `created_at` tag value; - `.content` as stringified author kind 0 event JSON for fast lookup. The event by default MUST be replaced by clients from time to time (usually at a frequency lower than 10 minutes window so that the user is not considered `away` - see ["Basic Status" section](#basic-status)). If the `created_at` tag age (`now - created_at`) is higher than 10 minutes, the client should consider the `.content` stale for important things such as zap address. ```js { "id": "<32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>", "pubkey": "<32-bytes lowercase hex-encoded public key of the event creator>", "created_at": "", "kind": 34549, "tags": [ ["d", "f39e9b451a73d62abc5016cffdd294b1a904e2f34536a208874fe5e22bbd47cf"], ["k", "40"], ["status", "Feeling gOoOod"] ["expiration", ""] ], "content": "{}" "sig": "<64-bytes hex of the signature of the sha256 hash of the serialized event data>" } ``` ## Basic Status Basic status don't rely on `status` tags. Clients find out the user status by the following rules regarding status event's `created_at` age: | Status Event Age | User Status | | -------------------------------------- | ------------------------------ | | (now - created_at) < 0 | *invalid status, not a member* | | 0 <= (now - created_at) < 10 min | online | | 10 min <= (now - created_at) < 30 min | away | | 30 min <= (now - created_at) < 5 days | offline | | 5 days <= (now - created_at) < 60 days | inactive | | 60 days <= (now - created_at)` | *not a member* | Clients by default MUST update the status event every 7 minutes user is browsing a group. An user is considered `invisible` if it deletes the status event or had never published it. The `invisible` status should be the default for most use cases when joining (browsing) a group. ### Special Case Some group NIPs may define bespoke status event update frequency along with expiration tag value and basic status tables. | NIP | Name | Configuration | | ------------- | --------------- | ------------------------------------ | | [102](102.md) | Live Activities | [#live-activities](#live-activities) | ## Custom Status Clients can choose to support extra custom status that may override the basic ones by using `status` tags; even multiple `status` tags at once. For example, a client may add a tag `["status", "offline"]` right after user leaves a group view. The following are the standardized `status` tag values: - "online" - "away" - "offline" - "inactive" - "busy" - "free-for-chat" ## Live Activities When joining a NIP-102 Live Activity the default status is `online` instead of `invisible`. | User Role | Status Event Update Frequency | Status Event NIP-40 Epiration Tag | | -------------- | ------------------------------ | --------------------------------- | | Host / Speaker | 1 min 30 s | created_at + 10 min | | Participant | 5 min 15 s | created_at + 10 min | | Status Event Age | User Role | User Status | | ----------------------------------------- | -------------- | ----------------------------------- | | (now - created_at) < 0 | *All* | *invalid status, not participating* | | 0 <= (now - created_at) < 2 min 15 s | Host / Speaker | online | | 2 min 15 s <= (now - created_at) < 10 min | Host / Speaker | offline | | 10 min <= (now - created_at) | Host / Speaker | *not participating* | | 0 <= (now - created_at) < 6 min | Participant | online | | 6 <= (now - created_at) < 10 min | Participant | offline | | 10 min <= (now - created_at) | Participant | *not participating* |