nostr-protocol / nips

Nostr Implementation Possibilities
2.27k stars 545 forks source link

We need a way to request direct replies to a note #267

Closed arthurfranca closed 1 year ago

arthurfranca commented 1 year ago

EDIT: Hello client authors, please skip to this comment to read the tl;dr of the last version of this proposal.

Currently, if we use the filter { kinds: [1], #e: ['note id'] }, it won't bring only the direct replies to the note, making it hard (impossible?) to lazily (e.g. infinite scroll) build a thread, specially the ones with lots of engagement.

This is because of:

There is no way to fetch just the direct replies (that would be the NIP-10 with the root marker OR the NIP-10 with the reply marker; it depends).

Currently, nostr expects clients to fetch all thread at once (which will probably get limited by relays when the thread is big). It gets really difficult when you use limit on the request filter as it will sort by created_at desc, so it may retrieve latest non-direct replies or mentions. E.g.: { kinds: [1], #e: ['root note id'], limit: 10 } may bring 2 mentions and 8 replies not directed to the root note

So i think we need to add a tag denoting direct reply. Maybe an R tag (just one max per event).

What do you think of adding it so that a client can use the following filter? { kinds: [1], #R: ['note id or long form content address'], limit: 10 }

And this should supersede NIP-10 reply marker.

monlovesmango commented 1 year ago

again, just to reiterate, the only posts that you currently cannot request direct replies from is the root event. with the current model you can already request direct replies of any event that is not the root event. your new proposed strategy would break this ability for clients that don't adopt l tag, and add a ton of metadata to replies that are deeper in the thread.

I am STRONGLY AGAINST adding a whole list of e tags for every single ancestor.

However, I think you have changed my mind about the level l tag. for the root event (which is the ONLY event we currently cannot request direct replies for) I actually do agree the level l could solve this and add a lot more flexibility to querying replies.

If we keep NIP-10 as is and just add the l tag to denote the thread depth, this would:

what do you think? if you still think we need all ancestors listed as e tags in an event please provide an example use case of when that's needed.

arthurfranca commented 1 year ago

@monlovesmango considering the following reply tree with three brances (R A B C D, R W X Y Z and R W X N): (root) R - A - B - C - D              \ W _ X _ Y _ Z                            \ N

If i'm reading the R event view, I can get the root direct replies by subscribing to { '#e': [R], '#l': ['1'] } (returns A and W). If i'm reading the W event view, I CAN'T get the W direct replies filtering by { '#e': [R], '#l': ['2'] } (returns B and X instead of just X).

That's why we need to have all ancestors, so that in the second example we can instead use { '#e': [W], '#l': ['2'] } (returning X instead of nothing), cause X would have W (and R) as an e tag.

We can safely get X direct replies with { '#e': [X], '#l': ['3'] } (Y and N)

Considering the screenshot examples, we can also get non-immediate descendants deeper in a branch to unlock said use cases.

Just to make it clear, Y for example would have the following e tags: R, W and X. So just the ancestors of same branch, not bloated.

monlovesmango commented 1 year ago

in current state, you CAN get the W direct replies filtering by { '#e': [W] }. however with your proposal you wouldn't be able to. I acknowledge that mentions will be mixed in as well, and am open to discussions on how to adapt the mention functionality to fix this.

Considering the screenshot examples, we can also get non-immediate descendants deeper in a branch to unlock said use cases.

I don't think this is useful enough to warrant listing all ancestors as e tags. even your screenshots only needed this for the root event, not decedents. as you get deeper in a thread the usefulness of getting non-immediate replies drops off considerably.

arthurfranca commented 1 year ago

in current state, you CAN get the W direct replies filtering by { '#e': [W] }. however with your proposal you wouldn't be able to.

I was took by surprise when you first said that some clients are fetching direct replies of non-root events, because if I were to build a nostr client I would use just one strategy, if possible, no matter if loading a root note view or a non-root one.

So currently the only strategy in common would be using { '#e': ['root-event-id'] }, even for non-root event view loading.

So my goal when starting this gh issue was to present an alternative strategy, shareable by root and non-root views, that would allow for fetching just direct replies, while letting clients still use the previous strategy if they wish.

It could be done with a capital P, for "parent", tag addition always present inside non-root events (at the start of the discussion it was a capital R). This would allow the missing { '#P': ['root-event-id'] } for getting root event direct replies. Or could be done by making it possible to fetch by the e tag which has the reply marker (if also adding the e-marker in cases where today there is just the e-root), which I think is the hardest change.

The "all ancestors plus the l tag" approach seems to me a step further, as:

So as you can see, the "all ancestors plus the l tag" approach would enable the birth of different clients (I think higher quality clients, pushing spam to the bottom, but some people may not agree).

Though at this point, I'm skeptical that any of these solutions will get picked. The majority of client authors seem to be comfortable with the current way of handling event replies as things are already coded. Unfortunately just you @monlovesmango and me kept interest in this discussion.

arthurfranca commented 1 year ago

I'm closing to keep repo lean as this was a lost battle =)