-
Notifications
You must be signed in to change notification settings - Fork 590
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
NIP-22 - Comment #1233
Merged
Merged
NIP-22 - Comment #1233
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
06a1577
Add generic comment
arthurfranca bb08281
Add convention on relay selection
arthurfranca 86f9519
Remove kind:1 mention
arthurfranca df47e12
Add kind to i reference
arthurfranca 1a89617
Update 22.md
arthurfranca f1775e2
Add K tag
arthurfranca 2c3f19b
Add prefixes to help when parsing values
arthurfranca 1436bf9
Add other prefixes
arthurfranca 08c9523
Make o and r tags variadic
arthurfranca 7d48dde
Add nip 73 support
arthurfranca b694d3d
Include :guid to podcast k/K tags
arthurfranca b57e0d2
Make nostr refs first-class citizens
arthurfranca 554393d
Back to positional values
arthurfranca 1fd680d
Simplify text and change r/R to s/S
arthurfranca f03fdaf
Update 22.md
arthurfranca 1653062
Use 'c' tag instead of 'q' and write about 'p' tag
arthurfranca f5f6a30
Use q tag and add example of a generic quote repost
arthurfranca b2f3e34
revert quote reposts
arthurfranca 0ee6aa3
recommend adding p tag set to parent event's author
arthurfranca e104ef0
Change prefixes
arthurfranca f420b17
Add relay hint to p tag
arthurfranca 9b4f721
S/s -> I/i
arthurfranca 2e6f559
point to nip73
arthurfranca 8aea645
remove leftover
arthurfranca File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
NIP-22 | ||
====== | ||
|
||
Comment | ||
------- | ||
|
||
`draft` `optional` | ||
|
||
A comment is a threading note always scoped to a root event or an `I`-tag. | ||
|
||
It uses `kind:1111` with plaintext `.content` (no HTML, Markdown, or other formatting). | ||
|
||
Comments MUST point to the root scope using uppercase tag names (e.g. `K`, `E`, `A` or `I`) | ||
and MUST point to the parent item with lowercase ones (e.g. `k`, `e`, `a` or `i`). | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: '<comment>', | ||
tags: [ | ||
// root scope: event addresses, event ids, or I-tags. | ||
["<A, E, I>", "<address, id or I-value>", "<relay or web page hint>", "<root event's pubkey, if an E tag>"], | ||
// the root kind or type if r. | ||
arthurfranca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
["K", "<root kind>"], | ||
arthurfranca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// parent item: event addresses, event ids, or i-tags. | ||
["<a, e, i>", "<address, id or i-value>", "<relay or web page hint>", "<parent event's pubkey, if an e tag>"], | ||
// parent item kind | ||
["k", "<parent comment kind>"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
Tags `K` and `k` MUST be present to define the event kind of the root and the parent items. | ||
|
||
`I` and `i` tags create scopes for hashtags, geohashes, URLs, and other external identifiers. | ||
|
||
The possible values for `i` tags – and `k` tags, when related to an extenal identity – are listed on [NIP-73](73.md). | ||
Their uppercase versions use the same type of values but relate to the root item instead of the parent one. | ||
|
||
`q` tags MAY be used when citing events in the `.content` with [NIP-21](21.md). | ||
|
||
```json | ||
["q", "<event-id> or <event-address>", "<relay-url>", "<pubkey-if-a-regular-event>"] | ||
``` | ||
|
||
`p` tags SHOULD be used when mentioning pubkeys in the `.content` with [NIP-21](21.md). | ||
If the parent item is an event, a `p` tag set to the parent event's author SHOULD be added. | ||
|
||
```json | ||
["p", "<pubkey>", "<relay-url>"] | ||
``` | ||
|
||
arthurfranca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## Examples | ||
|
||
A comment on a blog post looks like this: | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: 'Great blog post!', | ||
tags: [ | ||
// top-level comments scope to event addresses or ids | ||
["A", "30023:3c9849383bdea883b0bd16fece1ed36d37e37cdde3ce43b17ea4e9192ec11289:f9347ca7", "wss://example.relay"], | ||
// the root kind | ||
["K", "30023"], | ||
|
||
// the parent event address (same as root for top-level comments) | ||
["a", "30023:3c9849383bdea883b0bd16fece1ed36d37e37cdde3ce43b17ea4e9192ec11289:f9347ca7", "wss://example.relay"], | ||
// when the parent event is replaceable or addressable, also include an `e` tag referencing its id | ||
["e", "5b4fc7fed15672fefe65d2426f67197b71ccc82aa0cc8a9e94f683eb78e07651", "wss://example.relay"], | ||
arthurfranca marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// the parent event kind | ||
["k", "30023"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
A comment on a [NIP-94](94.md) file looks like this: | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: 'Great file!', | ||
tags: [ | ||
// top-level comments have the same scope and reply to addresses or ids | ||
["E", "768ac8720cdeb59227cf95e98b66560ef03d8bc9a90d721779e76e68fb42f5e6", "wss://example.relay", "3721e07b079525289877c366ccab47112bdff3d1b44758ca333feb2dbbbbe5bb"], | ||
// the root kind | ||
["K", "1063"], | ||
|
||
// the parent event id (same as root for top-level comments) | ||
["e", "768ac8720cdeb59227cf95e98b66560ef03d8bc9a90d721779e76e68fb42f5e6", "wss://example.relay", "3721e07b079525289877c366ccab47112bdff3d1b44758ca333feb2dbbbbe5bb"], | ||
// the parent kind | ||
["k", "1063"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
A reply to a comment looks like this: | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: 'This is a reply to "Great file!"', | ||
tags: [ | ||
// nip-94 file event id | ||
["E", "768ac8720cdeb59227cf95e98b66560ef03d8bc9a90d721779e76e68fb42f5e6", "wss://example.relay", "fd913cd6fa9edb8405750cd02a8bbe16e158b8676c0e69fdc27436cc4a54cc9a"], | ||
// the root kind | ||
["K", "1063"], | ||
|
||
// the parent event | ||
["e", "5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36", "wss://example.relay", "93ef2ebaaf9554661f33e79949007900bbc535d239a4c801c33a4d67d3e7f546"], | ||
// the parent kind | ||
["k", "1111"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
A comment on a website's url looks like this: | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: 'Nice article!', | ||
tags: [ | ||
// referencing the root url | ||
["I", "https://abc.com/articles/1"], | ||
// the root "kind": for an url, the kind is its domain | ||
["K", "https://abc.com"], | ||
|
||
// the parent reference (same as root for top-level comments) | ||
["i", "https://abc.com/articles/1"], | ||
// the parent "kind": for an url, the kind is its domain | ||
["k", "https://abc.com"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
A podcast comment example: | ||
|
||
```js | ||
{ | ||
id: "80c48d992a38f9c445b943a9c9f1010b396676013443765750431a9004bdac05", | ||
pubkey: "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111", | ||
kind: 1111, | ||
content: "This was a great episode!", | ||
tags: [ | ||
// podcast episode reference | ||
["I", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f", "https://fountain.fm/episode/z1y9TMQRuqXl2awyrQxg"], | ||
// podcast episode type | ||
["K", "podcast:item:guid"], | ||
|
||
// same value as "I" tag above, because it is a top-level comment (not a reply to a comment) | ||
["i", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f", "https://fountain.fm/episode/z1y9TMQRuqXl2awyrQxg"], | ||
["k", "podcast:item:guid"] | ||
] | ||
// other fields | ||
} | ||
``` | ||
|
||
A reply to a podcast comment: | ||
|
||
```js | ||
{ | ||
kind: 1111, | ||
content: "I'm replying to the above comment.", | ||
tags: [ | ||
// podcast episode reference | ||
["I", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f", "https://fountain.fm/episode/z1y9TMQRuqXl2awyrQxg"], | ||
// podcast episode type | ||
["K", "podcast:item:guid"], | ||
|
||
// this is a reference to the above comment | ||
["e", "80c48d992a38f9c445b943a9c9f1010b396676013443765750431a9004bdac05", "wss://example.relay", "252f10c83610ebca1a059c0bae8255eba2f95be4d1d7bcfa89d7248a82d9f111"], | ||
// the parent comment kind | ||
["k", "1111"] | ||
] | ||
// other fields | ||
} | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be a SHOULD instead of a MUST. Clients don't always have access to the root event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If everyone follows the spec from start, the first level thread comments will have root references, then the next level of comments would just copy these references from their parent comment, even if the root event is missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only works when commenting on events that use this spec and you would have to trust the parent author to set the correct root data.
A comment only needs its parent data. Adding root data might be helpful for clients implementing full threads but is burdensome for clients that just want to create a comment. It should be encouraged but not be a requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The root data is not even that useful. Right now you would get the whole thread by querying
E
because most threads are tiny. When threads get bigger you would hit relay restrictions and only receive a subset of the comments many of which will be n-level instead top-level replies, which are not useful for building the thread from the root.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm with you. Going the easy route of loading the full thread (relying on the uppercase
E/A/I
tags) in contrast to lazy loading is bad cause it loads too much events.The uppercase
K
tag being the root item's kind though is very useful to filter by{ authors: [someone], kinds: [1111], "#K": ["30023", ...others kinds this client cares about] }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What should be set when the parent does not set an
E
tag (we shouldn't rely on other people complying) and you also don't know the root?Having the root scope as a MUST requirement doesn't make sense in this case. It should be SHOULD.
I personally don't really care about it as I'm going to disrespect the root scope the same way I disrespect nip10, but when a library dev sees a MUST he will implement it that way and I would like to use a library function instead of building the event myself.