Compare commits

...

19 Commits

Author SHA1 Message Date
arkinox
47824611e3
Merge 802019ed80 into a1ca7a194b 2024-12-12 17:29:01 +01:00
Jon Staab
a1ca7a194b Change strategy for naming groups 2024-12-10 19:25:28 -03:00
Jesus Christ
e942427f8f
nip17: specify order (#1637)
Order specificity is implied better.
2024-12-09 12:13:59 -03:00
Josh Brown
624b989f9f clarify that Standard lists and Sets are both types of lists with heading level 2024-12-09 12:13:20 -03:00
hodlbod
b35dd7d294
Merge pull request #1635 from AsaiToshiya/update-breaking
Update BREAKING.md
2024-12-09 06:30:47 -08:00
Asai Toshiya
b94ad00ac7 BREAKING.md: add NIP-46 change 2024-12-09 13:29:10 +09:00
Asai Toshiya
d71887a8e2 BREAKING.md: merge duplicate lines 2024-12-09 13:19:16 +09:00
Asai Toshiya
33cad5108e
Merge pull request #1633 from Gudnessuche/patch-5
Update 90.md
2024-12-08 21:37:37 +09:00
Jesus Christ
b04922586e
Update 90.md
Added a period to show the end of "Protocol Flow" explanation
2024-12-08 12:34:34 +00:00
Asai Toshiya
d857cfb1b8
Merge pull request #1631 from TsukemonoGit/master
add Event Kinds kind:20 Picture NIP-68
2024-12-07 08:15:06 +09:00
mono
a2be191ecd
Update README.md 2024-12-07 07:45:25 +09:00
mono
936616b3c0
Update README.md
add Event Kinds  
kind:20  Picture-first feeds
2024-12-07 07:43:52 +09:00
小原晴太
a92d2e2edd Clarify the units 2024-12-06 08:48:11 -03:00
fiatjaf
6d16019e9e nip46: abandon nip04 entirely and just use nip44. 2024-12-05 20:14:02 -03:00
hodlbod
2ac43aa3f1
Merge pull request #1627 from AsaiToshiya/AsaiToshiya-patch-34
add `P` tag to README.
2024-12-05 08:37:32 -08:00
Asai Toshiya
2776a2aa14
add P tag to README. 2024-12-06 00:58:50 +09:00
arkinox
802019ed80
add clarifications 2024-09-09 12:41:51 -05:00
arkinox
31fc23d166
Update reference to NIP-73 2024-08-31 13:51:19 -05:00
arkin0x
d396f40314 nostr verified podcast nip 2024-08-31 10:44:32 -05:00
9 changed files with 127 additions and 25 deletions

2
17.md
View File

@ -133,7 +133,7 @@ When sending a message to anyone, clients must then connect to the relays in the
This example sends the message `Hola, que tal?` from `nsec1w8udu59ydjvedgs3yv5qccshcj8k05fh3l60k9x57asjrqdpa00qkmr89m` to `nsec12ywtkplvyq5t6twdqwwygavp5lm4fhuang89c943nf2z92eez43szvn4dt`. This example sends the message `Hola, que tal?` from `nsec1w8udu59ydjvedgs3yv5qccshcj8k05fh3l60k9x57asjrqdpa00qkmr89m` to `nsec12ywtkplvyq5t6twdqwwygavp5lm4fhuang89c943nf2z92eez43szvn4dt`.
The two final GiftWraps, one to the receiver and the other to the sender, are: The two final GiftWraps, one to the receiver and the other to the sender, respectively, are:
```json ```json
{ {

4
29.md
View File

@ -30,8 +30,6 @@ When encountering just the `<host>` without the `'<group-id>`, clients MAY infer
Events sent by users to groups (chat messages, text notes, moderation events etc) MUST have an `h` tag with the value set to the group _id_. Events sent by users to groups (chat messages, text notes, moderation events etc) MUST have an `h` tag with the value set to the group _id_.
`h` tags MAY include the group's name as the second argument. This allows `unmanaged` groups to be assigned human-readable names without relay support.
## Timeline references ## Timeline references
In order to not be used out of context, events sent to these groups may contain references to previous events seen from the same relay in the `previous` tag. The choice of which previous events to pick belongs to the clients. The references are to be made using the first 8 characters (4 bytes) of any event in the last 50 events seen by the user in the relay, excluding events by themselves. There can be any number of references (including zero), but it's recommended that clients include at least 3 and that relays enforce this. In order to not be used out of context, events sent to these groups may contain references to previous events seen from the same relay in the `previous` tag. The choice of which previous events to pick belongs to the clients. The references are to be made using the first 8 characters (4 bytes) of any event in the last 50 events seen by the user in the relay, excluding events by themselves. There can be any number of references (including zero), but it's recommended that clients include at least 3 and that relays enforce this.
@ -242,3 +240,5 @@ A definition for `kind:10009` was included in [NIP-51](51.md) that allows client
### Using `unmanaged` relays ### Using `unmanaged` relays
To prevent event leakage, when using `unmanaged` relays, clients should include the [NIP-70](70.md) `-` tag, as just the `previous` tag won't be checked by other `unmanaged` relays. To prevent event leakage, when using `unmanaged` relays, clients should include the [NIP-70](70.md) `-` tag, as just the `previous` tag won't be checked by other `unmanaged` relays.
Groups MAY be named without relay support by adding a `name` to the corresponding tag in a user's `kind 10009` group list.

6
44.md
View File

@ -86,7 +86,7 @@ NIP-44 version 2 has the following design characteristics:
- Content must be encoded from UTF-8 into byte array - Content must be encoded from UTF-8 into byte array
- Validate plaintext length. Minimum is 1 byte, maximum is 65535 bytes - Validate plaintext length. Minimum is 1 byte, maximum is 65535 bytes
- Padding format is: `[plaintext_length: u16][plaintext][zero_bytes]` - Padding format is: `[plaintext_length: u16][plaintext][zero_bytes]`
- Padding algorithm is related to powers-of-two, with min padded msg size of 32 - Padding algorithm is related to powers-of-two, with min padded msg size of 32bytes
- Plaintext length is encoded in big-endian as first 2 bytes of the padded blob - Plaintext length is encoded in big-endian as first 2 bytes of the padded blob
5. Encrypt padded content 5. Encrypt padded content
- Use ChaCha20, with key and nonce from step 3 - Use ChaCha20, with key and nonce from step 3
@ -148,8 +148,8 @@ validation rules, refer to BIP-340.
- `x[i:j]`, where `x` is a byte array and `i, j <= 0` returns a `(j - i)`-byte array with a copy of the - `x[i:j]`, where `x` is a byte array and `i, j <= 0` returns a `(j - i)`-byte array with a copy of the
`i`-th byte (inclusive) to the `j`-th byte (exclusive) of `x`. `i`-th byte (inclusive) to the `j`-th byte (exclusive) of `x`.
- Constants `c`: - Constants `c`:
- `min_plaintext_size` is 1. 1b msg is padded to 32b. - `min_plaintext_size` is 1. 1bytes msg is padded to 32bytes.
- `max_plaintext_size` is 65535 (64kb - 1). It is padded to 65536. - `max_plaintext_size` is 65535 (64kB - 1). It is padded to 65536bytes.
- Functions - Functions
- `base64_encode(string)` and `base64_decode(bytes)` are Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648), with padding) - `base64_encode(string)` and `base64_decode(bytes)` are Base64 ([RFC 4648](https://datatracker.ietf.org/doc/html/rfc4648), with padding)
- `concat` refers to byte array concatenation - `concat` refers to byte array concatenation

14
46.md
View File

@ -72,12 +72,12 @@ _user_ passes this token to _remote-signer_, which then sends `connect` *respons
{ {
"kind": 24133, "kind": 24133,
"pubkey": <local_keypair_pubkey>, "pubkey": <local_keypair_pubkey>,
"content": <nip04(<request>)>, "content": <nip44(<request>)>,
"tags": [["p", <remote-signer-pubkey>]], "tags": [["p", <remote-signer-pubkey>]],
} }
``` ```
The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted and has the following structure: The `content` field is a JSON-RPC-like message that is [NIP-44](44.md) encrypted and has the following structure:
```jsonc ```jsonc
{ {
@ -109,7 +109,7 @@ Each of the following are methods that the _client_ sends to the _remote-signer_
### Requested permissions ### Requested permissions
The `connect` method may be provided with `optional_requested_permissions` for user convenience. The permissions are a comma-separated list of `method[:params]`, i.e. `nip04_encrypt,sign_event:4` meaning permissions to call `nip04_encrypt` and to call `sign_event` with `kind:4`. Optional parameter for `sign_event` is the kind number, parameters for other methods are to be defined later. Same permission format may be used for `perms` field of `metadata` in `nostrconnect://` string. The `connect` method may be provided with `optional_requested_permissions` for user convenience. The permissions are a comma-separated list of `method[:params]`, i.e. `nip44_encrypt,sign_event:4` meaning permissions to call `nip44_encrypt` and to call `sign_event` with `kind:4`. Optional parameter for `sign_event` is the kind number, parameters for other methods are to be defined later. Same permission format may be used for `perms` field of `metadata` in `nostrconnect://` string.
## Response Events `kind:24133` ## Response Events `kind:24133`
@ -118,13 +118,13 @@ The `connect` method may be provided with `optional_requested_permissions` for u
"id": <id>, "id": <id>,
"kind": 24133, "kind": 24133,
"pubkey": <remote-signer-pubkey>, "pubkey": <remote-signer-pubkey>,
"content": <nip04(<response>)>, "content": <nip44(<response>)>,
"tags": [["p", <client-pubkey>]], "tags": [["p", <client-pubkey>]],
"created_at": <unix timestamp in seconds> "created_at": <unix timestamp in seconds>
} }
``` ```
The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted and has the following structure: The `content` field is a JSON-RPC-like message that is [NIP-44](44.md) encrypted and has the following structure:
```json ```json
{ {
@ -150,7 +150,7 @@ The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted
{ {
"kind": 24133, "kind": 24133,
"pubkey": "eff37350d839ce3707332348af4549a96051bd695d3223af4aabce4993531d86", "pubkey": "eff37350d839ce3707332348af4549a96051bd695d3223af4aabce4993531d86",
"content": nip04({ "content": nip44({
"id": <random_string>, "id": <random_string>,
"method": "sign_event", "method": "sign_event",
"params": [json_stringified(<{ "params": [json_stringified(<{
@ -170,7 +170,7 @@ The `content` field is a JSON-RPC-like message that is [NIP-04](04.md) encrypted
{ {
"kind": 24133, "kind": 24133,
"pubkey": "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52", "pubkey": "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52",
"content": nip04({ "content": nip44({
"id": <random_string>, "id": <random_string>,
"result": json_stringified(<signed-event>) "result": json_stringified(<signed-event>)
}), }),

8
51.md
View File

@ -14,7 +14,7 @@ When new items are added to an existing list, clients SHOULD append them to the
## Types of lists ## Types of lists
## Standard lists ### Standard lists
Standard lists use normal replaceable events, meaning users may only have a single list of each kind. They have special meaning and clients may rely on them to augment a user's profile or browsing experience. Standard lists use normal replaceable events, meaning users may only have a single list of each kind. They have special meaning and clients may rely on them to augment a user's profile or browsing experience.
@ -29,14 +29,14 @@ For example, _mute list_ can contain the public keys of spammers and bad actors
| Public chats | 10005 | [NIP-28](28.md) chat channels the user is in | `"e"` (kind:40 channel definitions) | | Public chats | 10005 | [NIP-28](28.md) chat channels the user is in | `"e"` (kind:40 channel definitions) |
| Blocked relays | 10006 | relays clients should never connect to | `"relay"` (relay URLs) | | Blocked relays | 10006 | relays clients should never connect to | `"relay"` (relay URLs) |
| Search relays | 10007 | relays clients should use when performing search queries | `"relay"` (relay URLs) | | Search relays | 10007 | relays clients should use when performing search queries | `"relay"` (relay URLs) |
| Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL), `"r"` for each relay in use | | Simple groups | 10009 | [NIP-29](29.md) groups the user is in | `"group"` ([NIP-29](29.md) group id + relay URL + optional group name), `"r"` for each relay in use |
| Interests | 10015 | topics a user may be interested in and pointers | `"t"` (hashtags) and `"a"` (kind:30015 interest set) | | Interests | 10015 | topics a user may be interested in and pointers | `"t"` (hashtags) and `"a"` (kind:30015 interest set) |
| Emojis | 10030 | user preferred emojis and pointers to emoji sets | `"emoji"` (see [NIP-30](30.md)) and `"a"` (kind:30030 emoji set) | | Emojis | 10030 | user preferred emojis and pointers to emoji sets | `"emoji"` (see [NIP-30](30.md)) and `"a"` (kind:30030 emoji set) |
| DM relays | 10050 | Where to receive [NIP-17](17.md) direct messages | `"relay"` (see [NIP-17](17.md)) | | DM relays | 10050 | Where to receive [NIP-17](17.md) direct messages | `"relay"` (see [NIP-17](17.md)) |
| Good wiki authors | 10101 | [NIP-54](54.md) user recommended wiki authors | `"p"` (pubkeys) | | Good wiki authors | 10101 | [NIP-54](54.md) user recommended wiki authors | `"p"` (pubkeys) |
| Good wiki relays | 10102 | [NIP-54](54.md) relays deemed to only host useful articles | `"relay"` (relay URLs) | | Good wiki relays | 10102 | [NIP-54](54.md) relays deemed to only host useful articles | `"relay"` (relay URLs) |
## Sets ### Sets
Sets are lists with well-defined meaning that can enhance the functionality and the UI of clients that rely on them. Unlike standard lists, users are expected to have more than one set of each kind, therefore each of them must be assigned a different `"d"` identifier. Sets are lists with well-defined meaning that can enhance the functionality and the UI of clients that rely on them. Unlike standard lists, users are expected to have more than one set of each kind, therefore each of them must be assigned a different `"d"` identifier.
@ -56,7 +56,7 @@ Aside from their main identifier, the `"d"` tag, sets can optionally have a `"ti
| Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) | | Emoji sets | 30030 | categorized emoji groups | `"emoji"` (see [NIP-30](30.md)) |
| Release artifact sets | 30063 | groups of files of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"i"` (application identifier, typically reverse domain notation), `"version"` | | Release artifact sets | 30063 | groups of files of a software release | `"e"` (kind:1063 [file metadata](94.md) events), `"i"` (application identifier, typically reverse domain notation), `"version"` |
## Deprecated standard lists ### Deprecated standard lists
Some clients have used these lists in the past, but they should work on transitioning to the [standard formats](#standard-lists) above. Some clients have used these lists in the past, but they should work on transitioning to the [standard formats](#standard-lists) above.

2
90.md
View File

@ -185,7 +185,7 @@ Any job feedback event MIGHT include results in the `.content` field, as describ
* Customer publishes a job request (e.g. `kind:5000` speech-to-text). * Customer publishes a job request (e.g. `kind:5000` speech-to-text).
* Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.). * Service Providers MAY submit `kind:7000` job-feedback events (e.g. `payment-required`, `processing`, `error`, etc.).
* Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event. * Upon completion, the service provider publishes the result of the job with a `kind:6000` job-result event.
* At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user * At any point, if there is an `amount` pending to be paid as instructed by the service provider, the user can pay the included `bolt11` or zap the job result event the service provider has sent to the user.
Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers MUST use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent. Job feedback (`kind:7000`) and Job Results (`kind:6000-6999`) events MAY include an `amount` tag, this can be interpreted as a suggestion to pay. Service Providers MUST use the `payment-required` feedback event to signal that a payment is required and no further actions will be performed until the payment is sent.

View File

@ -5,6 +5,7 @@ reverse chronological order.
| Date | Commit | NIP | Change | | Date | Commit | NIP | Change |
| ----------- | --------- | -------- | ------ | | ----------- | --------- | -------- | ------ |
| 2024-12-05 | [6d16019e](https://github.com/nostr-protocol/nips/commit/6d16019e) | [46](46.md) | message encryption was changed to NIP-44 |
| 2024-11-12 | [2838e3bd](https://github.com/nostr-protocol/nips/commit/2838e3bd) | [29](29.md) | `kind: 12` and `kind: 10` were removed (use `kind: 1111` instead) | | 2024-11-12 | [2838e3bd](https://github.com/nostr-protocol/nips/commit/2838e3bd) | [29](29.md) | `kind: 12` and `kind: 10` were removed (use `kind: 1111` instead) |
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | NIP-05 login was removed | | 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | NIP-05 login was removed |
| 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | `create_account` method was removed | | 2024-11-12 | [926a51e7](https://github.com/nostr-protocol/nips/commit/926a51e7) | [46](46.md) | `create_account` method was removed |
@ -30,8 +31,7 @@ reverse chronological order.
| 2024-02-07 | [d3dad114](https://github.com/nostr-protocol/nips/commit/d3dad114) | [46](46.md) | Connection token format was changed | | 2024-02-07 | [d3dad114](https://github.com/nostr-protocol/nips/commit/d3dad114) | [46](46.md) | Connection token format was changed |
| 2024-01-30 | [1a2b21b6](https://github.com/nostr-protocol/nips/commit/1a2b21b6) | [59](59.md) | 'p' tag became optional | | 2024-01-30 | [1a2b21b6](https://github.com/nostr-protocol/nips/commit/1a2b21b6) | [59](59.md) | 'p' tag became optional |
| 2023-01-27 | [c2f34817](https://github.com/nostr-protocol/nips/commit/c2f34817) | [47](47.md) | optional expiration tag should be honored | | 2023-01-27 | [c2f34817](https://github.com/nostr-protocol/nips/commit/c2f34817) | [47](47.md) | optional expiration tag should be honored |
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [02](02.md) | list entries should be chronological | | 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [02](02.md), [51](51.md) | list entries should be chronological |
| 2024-01-10 | [3d8652ea](https://github.com/nostr-protocol/nips/commit/3d8652ea) | [51](51.md) | list entries should be chronological |
| 2023-12-30 | [29869821](https://github.com/nostr-protocol/nips/commit/29869821) | [52](52.md) | 'name' tag was removed (use 'title' tag instead) | | 2023-12-30 | [29869821](https://github.com/nostr-protocol/nips/commit/29869821) | [52](52.md) | 'name' tag was removed (use 'title' tag instead) |
| 2023-12-27 | [17c67ef5](https://github.com/nostr-protocol/nips/commit/17c67ef5) | [94](94.md) | 'aes-256-gcm' tag was removed | | 2023-12-27 | [17c67ef5](https://github.com/nostr-protocol/nips/commit/17c67ef5) | [94](94.md) | 'aes-256-gcm' tag was removed |
| 2023-12-03 | [0ba45895](https://github.com/nostr-protocol/nips/commit/0ba45895) | [01](01.md) | WebSocket status code `4000` was replaced by 'CLOSED' message | | 2023-12-03 | [0ba45895](https://github.com/nostr-protocol/nips/commit/0ba45895) | [01](01.md) | WebSocket status code `4000` was replaced by 'CLOSED' message |
@ -46,10 +46,7 @@ reverse chronological order.
| 2023-08-21 | [89915e02](https://github.com/nostr-protocol/nips/commit/89915e02) | [11](11.md) | 'min_prefix' was removed | | 2023-08-21 | [89915e02](https://github.com/nostr-protocol/nips/commit/89915e02) | [11](11.md) | 'min_prefix' was removed |
| 2023-08-20 | [37c4375e](https://github.com/nostr-protocol/nips/commit/37c4375e) | [01](01.md) | replaceable events with same timestamp should be retained event with lowest id | | 2023-08-20 | [37c4375e](https://github.com/nostr-protocol/nips/commit/37c4375e) | [01](01.md) | replaceable events with same timestamp should be retained event with lowest id |
| 2023-08-15 | [88ee873c](https://github.com/nostr-protocol/nips/commit/88ee873c) | [15](15.md) | 'countries' tag was renamed to 'regions' | | 2023-08-15 | [88ee873c](https://github.com/nostr-protocol/nips/commit/88ee873c) | [15](15.md) | 'countries' tag was renamed to 'regions' |
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [12](12.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 | | 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [12](12.md), [16](16.md), [20](20.md), [33](33.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [16](16.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [20](20.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
| 2023-08-14 | [72bb8a12](https://github.com/nostr-protocol/nips/commit/72bb8a12) | [33](33.md) | NIP-12, 16, 20 and 33 were merged into NIP-01 |
| 2023-08-11 | [d87f8617](https://github.com/nostr-protocol/nips/commit/d87f8617) | [25](25.md) | empty `content` should be considered as "+" | | 2023-08-11 | [d87f8617](https://github.com/nostr-protocol/nips/commit/d87f8617) | [25](25.md) | empty `content` should be considered as "+" |
| 2023-08-01 | [5d63b157](https://github.com/nostr-protocol/nips/commit/5d63b157) | [57](57.md) | 'zap' tag was changed | | 2023-08-01 | [5d63b157](https://github.com/nostr-protocol/nips/commit/5d63b157) | [57](57.md) | 'zap' tag was changed |
| 2023-07-15 | [d1814405](https://github.com/nostr-protocol/nips/commit/d1814405) | [01](01.md) | `since` and `until` filters should be `since <= created_at <= until` | | 2023-07-15 | [d1814405](https://github.com/nostr-protocol/nips/commit/d1814405) | [01](01.md) | `since` and `until` filters should be `since <= created_at <= until` |

View File

@ -119,6 +119,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `14` | Direct Message | [17](17.md) | | `14` | Direct Message | [17](17.md) |
| `16` | Generic Repost | [18](18.md) | | `16` | Generic Repost | [18](18.md) |
| `17` | Reaction to a website | [25](25.md) | | `17` | Reaction to a website | [25](25.md) |
| `20` | Picture | [68](68.md) |
| `40` | Channel Creation | [28](28.md) | | `40` | Channel Creation | [28](28.md) |
| `41` | Channel Metadata | [28](28.md) | | `41` | Channel Metadata | [28](28.md) |
| `42` | Channel Message | [28](28.md) | | `42` | Channel Message | [28](28.md) |
@ -282,6 +283,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos
| `L` | label namespace | -- | [32](32.md) | | `L` | label namespace | -- | [32](32.md) |
| `m` | MIME type | -- | [94](94.md) | | `m` | MIME type | -- | [94](94.md) |
| `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) | | `p` | pubkey (hex) | relay URL, petname | [01](01.md), [02](02.md) |
| `P` | pubkey (hex) | -- | [57](57.md) |
| `q` | event id (hex) | relay URL, pubkey (hex) | [18](18.md) | | `q` | event id (hex) | relay URL, pubkey (hex) | [18](18.md) |
| `r` | a reference (URL, etc) | -- | [24](24.md), [25](25.md) | | `r` | a reference (URL, etc) | -- | [24](24.md), [25](25.md) |
| `r` | relay url | marker | [65](65.md) | | `r` | relay url | marker | [65](65.md) |

103
XX.md Normal file
View File

@ -0,0 +1,103 @@
NIP-XX: Nostr Verified Podcasts
======
`draft` `optional`
## Abstract
This NIP defines a method for podcast owners to announce and verify their podcasts on the Nostr network, enabling better discovery and integration of traditional RSS-based podcasts with nostr and mixing of Nostr-native podcast episodes with RSS-based podcast episodes.
## Introduction
While [NIP-XX Audio Track](https://github.com/nostr-protocol/nips/pull/1043) defines kind 31338 for podcast tracks, many traditional podcasts do not publish these events, making them undiscoverable on the Nostr network. This NIP addresses this issue by introducing podcast announcements and a verification mechanism.
Announcing podcasts on nostr allows nostr to serve as a decentralized index of podcasts which may ease dependence on centralized APIs like iTunes or Podcastindex.
Additionally, when an npub becomes a verified owner of an RSS feed, any kind `31338` podcast events owned by that npub may be directly associated with the verified RSS feed in podcasting clients. In this way, the verification creates a bridge between traditional RSS feeds and nostr-based podcast publishing.
## Podcast Announcements
A podcast owner can publish an announcement on Nostr to make their podcast discoverable:
```json
{
"kind": 1338,
"tags": [
["i", "podcast:guid:78ae77a3-b180-5cfa-a7ba-31ac82df8ba9", "https://example.com/podcast/feed.xml"]
],
"content": ""
}
```
Clients can request kind 1338 to discover RSS feeds without the need of an API like podcastindex. The RSS feed URI can be fetched directly to obtain the podcast's data. The podcast announcement event MUST specify the podcast guid ([NIP-73](https://github.com/nostr-protocol/nips/blob/master/73.md)) and MUST specify the direct feed URI.
The `i` tag follows the External Content IDs format as defined in [NIP-73](https://github.com/nostr-protocol/nips/blob/master/73.md).
## Nostr Podcast Verification
To verify ownership of a podcast, the owner should include the full signed kind 1338 event in the `<content>` tag of their RSS feed:
```xml
<podcast:txt purpose="nostr">
<![CDATA[
{
"id": "...",
"pubkey": "...",
"created_at": ...,
"kind": 1338,
"tags": [
["i", "podcast:guid:78ae77a3-b180-5cfa-a7ba-31ac82df8ba9", "https://example.com/podcast/feed.xml"],
["relays", "wss://example.com", "wss://optional.com"]
],
"content": "",
"sig": "..."
}
]]>
</podcast:txt>
```
This verification should ideally be published in the RSS feed before publishing the kind 1338 announcement event to relays.
## Client Behavior
### Podcast Discovery
Clients may filter for kind `1338` to obtain direct URIs to podcast RSS feeds. These feeds may then be fetched and parsed to display and play podcasts in the client UI.
Without this, podcast clients would need to rely on centralized APIs such as iTunes or Podcastindex to fetch podcast RSS feeds. Typically these APIs require a search query to return results, which doesn't help a client bootstrap it's homepage for a first-time visitors. Those APIs can serve "trending" or "recently updated" lists of podcasts but those algorithms may not be suitable for every client and they aren't always open source.
Without any user input, nostr clients can show "recently announced" podcasts by querying kind `1338` events. Deduplication and web-of-trust may be overlayed on this to curate podcast announcements further.
Note that anyone could publish a kind `1338` to relays for a podcast they do not own; this isn't necessarily a bad thing as people can simply seed nostr with podcasts they like for nostr-based podcasting clients to pick up and recommend. Simple client-side verification will fix common issues that may arise from this. See below.
### Podcast Episodes on Nostr
Clients may also filter for kind `31338` podcast tracks and inspect them for a [NIP-73](https://github.com/nostr-protocol/nips/blob/master/73.md) `i` tag referencing a podcast RSS feed. Just as above, the feeds may be fetched and parsed to display and play podcasts in the UI. If the fetched RSS feed contains Nostr Verification and the kind `31338` event was published by the verified npub, then the episode may be shown as an official episode of that podcast.
In this way, a kind `31338` podcast track with a NIP-73 `i` tag is functionally equivalent to a kind `1338` found on relays. However, the kind `1338` is still necessary as it enables Nostr Verification for podcasters who do not wish to publish on nostr.
### Comments, Zaps, and Interacting with a Discovered Podcast
User events that should reference a podcast or a podcast episode, such as a comment or review, should utilize [NIP-73](https://github.com/nostr-protocol/nips/blob/master/73.md) rather than referencing the kind `1338` event.
For zaps, the client should fetch the RSS feed and check it for the `<podcast:txt purpose="nostr">` tag which will contain a kind `1338` signed by the podcast owner's npub. After verifying the signature of the event, the zap can be sent to that npub.
### Npub Ownership
Having a nostr verified podcast allows for nostr podcasting clients to definitively associate an npub with a podcast (RSS feed). This allows nostr content to be layered on top of traditional podcast 2.0 data in any way clients desire.
When a podcast RSS feed is encountered which contains the `<podcast:txt purpose="nostr">` tag, the client should verify the signature of the kind `1338` event in the tag.
Once verified, the client may choose to associate whatever content from that npub it deems relevant with the podcast. For example:
- A feed of the npub's kind `1` notes could be displayed with the podcast as "official updates".
- Kind `31338` podcast episodes from the verified npub with the same `i` tag may be displayed intermingled with RSS episodes in the podcast's content feed.
- The most basic example would be to simply have a link to the npub's profile page from the podcast page.
The result of podcast verification MAY be cached for a reasonable duration (24 hours).
## Notes about Podcast Track Kind `31338`
- Kind `31338` episodes may be published without an associated podcast RSS feed. In this case, they will be shown as belonging to the pubkey.
- Kind `31338` episodes can be shown as "part" of an RSS feed if the feed has Nostr Verification, the kind `31338` episodes reference the RSS feed (using the same `i` tag as in the kind `1338` event), and the kind `31338` episodes are published by the verified npub.
- Publishing a kind `31338` podcast with an `i` tag referencing the podcast is functionally equivalent to a kind `1338` podcast announcement event, but if the pubkey won't be publishing Nostr-based episodes, the kind 1338 event is still necessary.