nostr-protocol / nips

Nostr Implementation Possibilities
2.39k stars 582 forks source link

Feeds #1554

Open staab opened 3 weeks ago

staab commented 3 weeks ago

Adds custom feeds that can (mostly) compile to filters, for content-addressable, user-customizable feeds, useful for clients with bandwidth limitations. Implemented by Coracle.

vitorpamplona commented 3 weeks ago

I am currently coding custom feeds on Amethyst and I think we need to break this down into a few kinds. Not every client will be able to offer DVM and WOT feeds, so what should they do for records that have those? To me different kinds solve this issue because Clients can just filter by the supported feed definition events.

The group instructions: Intersection, difference, union should be a separate kind as well because they require a processing stage after the relay has sent their stuff.

But largely, I am convinced that every client needs a "FeedStructure definition" like this one. But I am less convinced if it is interoperable between clients.

staab commented 3 weeks ago

we need to break this down into a few kinds

That's reasonable, I see what you're saying. Unfortunately, my implementation took about 4 weeks to build as it is, and this would introduce a fair amount of complexity. Why can't clients offer dvm or wot feeds? Wot might be a no-op with a warning, and dvms seem pretty straightforward. Another, software way of doing what you're describing might be to add tags that indicate what feed types are used, and clients can filter down to only feeds they support.

vitorpamplona commented 3 weeks ago

Why can't clients offer dvm or wot feeds?

Many clients don't need to. Others simple are not ready for it. As of now, the only way to ship custom feeds is if you implement WOT + DVM + Labels + Replaceables + Lists + Scores + Search at the same time. The kind was made by a super app and only super apps can use it.

To me, for instance, a Global Feed kind and a Kind3 follows kind should be separate. Some apps might just do Global feeds others might not support global at all. Kind3 requires outbox and cannot have relays added to it because it should be dynamically computed.

staab commented 3 weeks ago

only super apps can use it

Not at all, any app can use nip 89 handlers for unrecognized kinds. This nip isn't limited to feed-based UIs either, although the welshman loader is opinionated in how notes are requested.

Kind3 requires outbox and cannot have relays added to it because it should be dynamically computed.

Not exactly true, you might want to know what your follows are saying about cats, by requesting notes by follows only from the cats relay. This is a valid use case a particular client might follow, by adding their own criteria or enhancement to existing feeds. There's nothing that says the feed needs to return the same notes in every implementation.

Some apps might just do Global feeds others might not support global at all.

There will always be a kind that is a superset of the feeds spec because of feed composition, and clients will always have to validate the feed for support. If you prefer to explicitly support some subset of the spec we can add new kinds that do that (which would actually allow all kinds to be interpreted the same way). But I have the feeling this isn't related to Amethyst's implementation, but is more of a theoretical point?

vitorpamplona commented 3 weeks ago

All I am saying is that I think this NIP would benefit from modularization so that apps can gradually implement it or implement only the things they intend to support instead of having to filter out what they can't manage.

staab commented 3 weeks ago

Ok, thinking aloud what that might look like.

Assume we add 13 new kinds, one for each feed type. union and intersection can combine many feed types without requiring additional requests. E.g. ["intersection", ["authors", "<pubkey>"], ["kinds", 1]] can be compiled to {"authors": [<pubkey>], "kinds": [1]}, and ["union", ["authors", "<pubkey>"], ["kinds", 1]] can be compiled to [{"authors": [<pubkey>]}, {"kinds": [1]}]. In this case, set functions are not very complicated, and in fact without them you would have a less powerful abstraction than a regular nostr filter.

On the other hand, as you mentioned certain feed types require clients to do stuff. scope=follows requires downloading the user's kind 3, scope=followers requires downloading an indeterminate number of follow lists. So a single feed type varies widely in complexity and difficulty of implementation for different values. Similarly, ["kinds", 1] might be easy for some clients and hard for others, while ["kinds", 31990] will be easy for a different set of clients.

wot has similar requirements as scope, list requires downloading lists in advance, dvm requires special logic. But basically all of the more complex feed types share the same characteristic of needing one or more network requests in order to dereference terms in order to compile the feed to filters that can be sent to relays.

So the only meaningful distinction I think we can come up with here is "simple" feeds (created_at, kind, etc) vs "feeds with dependencies". That describes difficulty of implementation, but really nothing to do with use case from the standpoint of the end user. Maybe some clients would only care to implement the created_at feed because of the value prop they're offering, but then I don't see much benefit to shareable feeds based on created_at. authors would be more useful, but then you could just use lists. Same with dvm, just use dvm handler events instead.

So in other words, I think there's almost no utility to individual feed types. All of them are mapping parts of standard filters, existing nostr event kinds, or static string terms to the feeds concept for the purpose of composition.

Sorry for the long post, just trying to take your point seriously. But I don't think what you're suggesting is needed, or would really work.

vitorpamplona commented 3 weeks ago

Picture this. I want to offer different simple feeds. Users can have a "Global" feed for relays A and B and another "Global" feed for relays C and D. They should be able to easily swap between the two. They can have hashtag feeds for relay A and another feed for the same hashtag but from relay B. Same for geolocation or any combination of these attributes.

NIP-29 groups for instance, could be just different SimpleFeeds with a relay and kinds attached to them directly.

So, I think simple feeds are a thing. I don't know if every app will code them, but those who do could share the same feed setup among them.

Now there is another problem: over specification of the feed. If Coracle has.. say 5 default feeds.. and Amethyst has 7 default feeds and they are just slightly different (imagine a few extra event kinds listed in each), would users like to see 12 feeds with similar names when they log into both? Or should Amethyst just load Amethyst feeds and Coracle only load Coracle feeds?

staab commented 3 weeks ago

So, I think simple feeds are a thing.

That's fair. We could easily add new kinds as new subsets become recognized as useful.

Or should Amethyst just load Amethyst feeds and Coracle only load Coracle feeds?

Coracle currently has 2 default feeds, but they are not implicitly published on behalf of the user, which seems like what you're suggesting. Feeds should be user-generated, not client-generated, especially since they're shareable. Publishing the same 5 feeds for each user would result in many many duplicates. Feeds are meant to be shared, favorited, and forked.

vitorpamplona commented 3 weeks ago

If clients shouldn't share their feeds, how we need to hard code the basic ones we provide?

staab commented 3 weeks ago

I'm not quite sure what you're asking, but coracle just hard codes the basic feeds. It uses the same format as the event, it just doesn't publish the feed. I'm not sure how to de-duplicate the defaults with similar feeds the user has favorited or created, but that's just a UX question.

vitorpamplona commented 3 weeks ago

Can users customize the default feeds that coracle doesn't publish? If so, then do you publish?

I am wondering because Amethyst users might have multiple installs and might need to see the same "hardcoded" feeds in all Amethyst instances they have running.

staab commented 3 weeks ago

Can users customize the default feeds that coracle doesn't publish? If so, then do you publish?

Yes, if you click the "filters" button in coracle you can edit the feed. Whether you edit or not, you can click "Would you like to save this feed?" They can then name it and add a description and it'll be published as one of their feeds. If it's an exact duplicate of the defaults, coracle will automatically de-duplicate. If it's just similar, a new feed item will be visible and the hardcoded one will remain.

I am wondering because Amethyst users might have multiple installs and might need to see the same "hardcoded" feeds in all Amethyst instances they have running.

I don't understand, if it's hardcoded then it would just always be there regardless.

vitorpamplona commented 3 weeks ago

I don't understand, if it's hardcoded then it would just always be there regardless.

It wouldn't be hardcoded. I am switching it all to custom feeds that the user can change and access them from anywhere. I can publish them as your new kind here or as a NIP-78 object. Just pondering.

staab commented 3 weeks ago

I see. If the user is customizing them, I would use this NIP. Unless you don't want feeds to be public, in which case we could add an encrypted version of this NIP.