Skip to content
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

Adding ability to have expiring mutelist items #987

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

fishcharlie
Copy link

I’m working on implementing mutelists in Damus, and users are asking for the ability to have mute list items expire.

After talking with @jb55, one important design decision here is that tags in a kind:10000 mute list do not have the same parameters as kind1 events. For example, we do not include relay URL or petname as those do not make sense in this context. Instead the 3rd element (index: 2) will be the expiration time.

This is something that I’m currently developing for Damus, and wanted to submit this proposal before I get too far into the implementation to gather feedback.

I’m working on implementing mutelists in Damus, and users are asking for the ability to have mute list items expire.

After talking with @jb55, one important design decision here is that tags in a kind:10000 mute list do not have the same parameters as kind1 events. For example, we do not include relay URL or petname as those do not make sense in this context. Instead the 3rd element (index: 2) will be the expiration time.

This is something that I’m currently developing for Damus, and wanted to submit this proposal before I get too far into the implementation to gather feedback.

Signed-off-by: Charlie Fish <contact@charlie.fish>
@fiatjaf
Copy link
Member

fiatjaf commented Jan 12, 2024

Sounds pretty good to me, but I have never implemented this kind of stuff, so I don't know.

@staab @vitorpamplona @rabble @mmalmi

"created_at": 1699597889,
"kind": 10000,
"tags": [
["p", "07caba282f76441955b695551c3c5c742e5b9202a3784780f8086fdcdc1da3a9", "1735689600"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second index in a "p" tag should always be the relay hint. so id say you could either move the timestamp to the third index or maybe it might make sense to use an additional tag so it dose not clash with anything else clients might be doing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hzrd149 I talked with @jb55 about this. And left the reasoning in the original post of this PR.

@jb55 might be able to comment further here.

But one key question I would have is what is the purpose of having a relay URL in a mute list? It makes sense in the context of notes. For mute lists however the relay URL is irrelevant. The user should be muted across all relay URLs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think tag items can have different meaning depending on the context -- but maybe our heads will explode if we do that, not sure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, I think tag items can have different meaning depending on the context -- but maybe our heads will explode if we do that, not sure.

I think the earlier we shake the idea that we have to use the same parameters across each kind type the better. tag params for ubiquitous things like p will inevitably have different contextual parameters across many different kinds. I doubt we need pet names in mute lists or all future lists.

I noticed there's a table in the nips repo that tries to document these parameters but they are not scoped by kind, so that will be a large source of confusion going forward. contextual tag params should be described by the NIP describing the kind like this one.

@vitorpamplona
Copy link
Collaborator

I am not sure if it's worth doing this expiration by tag. Relays can't do anything about the expiration. Clients must manually respect the setting and remove expired keys in the first opportunity. At that point, a tool to review your block list afterwards (like checking if the key is still active) could be more interesting than setting an arbitrary expiration date at the block time.

@fishcharlie
Copy link
Author

@vitorpamplona Couple of things.

Relays can't do anything about the expiration

There are a lot of current tags that relays can't do anything about. For nostr, shifting responsibility to clients from relays is not an uncommon task. Relays on nostr aren't servers in the traditional sense where they are responsible for a lot of the complexity. They are basically only responsible for storage & filtering.

So I'm not sure why this is relevant?

At that point, a tool to review your block list afterwards

This is for mute list, not block list. Maybe you are using them interchangeably here? But just wanna make sure we are on the same page.

(like checking if the key is still active) could be more interesting than setting an arbitrary expiration date at the block time

That is not the primary use case here. The goal is to let users set an expiration date for muted items. It has nothing to do if the key is still active. It has to do with letting users decide when an item should be unmuted automatically, at the time they mute it.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jan 12, 2024

On the relay use, my point is that this is not similar to the usual expiration tag that both relays and clients work with. Besides having the same name, this one is much less effective in actually expiring because in the other one, relays would just delete the event automatically. Clients don't need to do much. This one doesn't "automatically work" for clients like the other one does.

Yep, sorry, mute list.

On the use case, my point is that letting users set arbitrary dates to unmute doesn't make much sense to me. Either clients implement a review screen before unmuting keys to get the user authorization or clients do it automatically and users start to see crappy content (for instance porn) they have muted but forgot about it. And if clients have to implement review screens, I believe they can also collect more interesting information that would lead to unmuting or not of keys. The date itself is somewhat irrelevant to the user decision

@fishcharlie
Copy link
Author

@vitorpamplona

or clients do it automatically and users start to see crappy content (for instance porn) they have muted but forgot about it

Not quite. At least with the planned implementation for Damus, I'm planning on making the default indefinite. With an option for a user to select a duration for the mute.

So users maintain full control, and for that type of content, they can mute it forever (until they manually delete it). That would be represented by not having that field at all.

For content they want to mute for a specific duration, that is where this proposal comes in.

I am also planning on making this automatic like you mentioned in the planned implementation for Damus.


Key part in this PR:

If no expiration timestamp is provided, clients SHOULD assume the mute item is indefinite (until a more recent mute list is relayed).

Which is just like the current behavior of mute lists.

The "forgot about it" scenario I'm not sure I understand.

@jb55
Copy link
Contributor

jb55 commented Jan 12, 2024 via email

@vitorpamplona
Copy link
Collaborator

The "forgot about it" scenario I'm not sure I understand.

Most of my users heavily mute people everywhere. It's not difficult to find 500+ keys in their mute lists. The problem of such use is that they can't be expected to remember why they muted certain keys. The list then gets extremely large and a review of the entire list is periodically needed. Because it's hard to remember, they end up either deleting everything or using tools to give them an idea of what keys they should keep. Those tools, if enhanced to account for the needs of this PR, could replace the need to pre-schedule an arbitrary expiration, saving us some bytes in the process.

While you could say: "well they could then just make everything expire in one year" to constantly rotate the list, that doesn't actually solve it. In a year, most of the list will be made of inactive/temporary keys, so it is very easy to clean them all up. And the active keys are very likely to stay muted (usually it's scams, porn, child trafficking and other types of unwanted content/comments).

We are then left with the mute for a couple days because this particular user I otherwise like is being annoying. That use case seems to be very rare and more associated with specific threads than to whole keys.

But maybe you are seeing something different that makes this use case more valid.

I am not sure if automatically unmuting keys is a good idea. Our experience with expiration of reports (regular expiration tags in 1984s) tells me that people don't like when things come back to annoy them even if they were the ones setting the "coming back" up in the first place. We ended up disabling it. Like I said, people don't remember what they set up. They just get mad with complaints when it happens.

@jb55
Copy link
Contributor

jb55 commented Jan 12, 2024 via email

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jan 12, 2024

It's not difficult to see. Users always want everything configurable. This definitely fits the norm. I just think these types of muted are extremely rare.

My point is not that the feature shouldn't exist. Just that there could be better ways to do it in post processing.

@alexgleason
Copy link
Member

Expiring mutes is a commonly requested feature and a lot of ActivityPub software has it.

I think you have to query the user's mute list every time you render events anyway. You should keep the whole thing in memory. And if you're going to loop it every time, it's not hard to check mute expiration.

You don't have to automatically republish the event when mutes expire. You can just filter out expired ones next time a new mute list is published.

The only potential downside I see is that filtering mute events by #p filters would become ambiguous, especially in COUNT commands. And I wish that filters could have negative clauses.

Otherwise, seems fine.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Jan 12, 2024

Not only the filters by #p and #e become ambiguous but it creates a precedent for tags that shouldn't count at certain times.

We can do follow lists with expirations, for instance: I'd like to follow a conference account until the date of the conference. After that my client shouldn't show anything.

It's a good feature, but I hope you can all see how the continuing use of contextually/time-activated tags can make things more complicated than it seems at first glance.

@alexgleason
Copy link
Member

Interesting point about expiring follows.

A different way to fix it would be to use atomic events like #349 instead of big lists, and stick a NIP-40 timestamp on it.

Now we're full circle.

@vitorpamplona
Copy link
Collaborator

I am always in favor of killing all types of lists. :)

@jb55
Copy link
Contributor

jb55 commented Jan 12, 2024 via email

@vitorpamplona
Copy link
Collaborator

Since when has NIP feedback come down to something you wouldn't personally use? This is tiresome.

I didn't even mention if I would personally use it or not. We are just debating the idea... as we MUST. Maybe you forgot how collaborations on a common spec work, but every NIP goes through this. Pages and pages of debates. If after the debate people still see merits in the approach, it should be used and published. What can't happen is the lack of any critical feedback.

Yes, it is tiresome. Get used to it, like everybody else does.

@jb55
Copy link
Contributor

jb55 commented Jan 13, 2024 via email

@staab
Copy link
Member

staab commented Jan 13, 2024

I haven't read any of the conversation, but I would suggest a new kind for "expiring mute list" so that clients that don't support this new format don't nuke the new entries.

@jb55
Copy link
Contributor

jb55 commented Jan 13, 2024

clients should try not to nuke anything ideally

@staab
Copy link
Member

staab commented Jan 13, 2024

Hard to avoid it if the spec changes

@fishcharlie
Copy link
Author

but I would suggest a new kind for "expiring mute list"

I actually did think about this. Similar to the expiring notes concept in NIP-40.

However, this doesn't actual solve the use case we are trying to solve. Users don't want an entire list to have a set duration/expiration. Users want specific items within their mute list to have a set duration/expiration.

Which makes a mute list wide expiration not practical.

so that clients that don't support this new format don't nuke the new entries

I'd argue that if clients are modifying the entires tags array, they are doing it wrong. If a client supports a mute list, and a user mutes a new item, it should be as simple as taking their existing mute list, appending an item to the array, and relaying that. That client doesn't need to support expiring mute items. And it shouldn't modify existing expiring mute items. It's simply an appending to the existing array. No need to modify existing data.

@mikedilger
Copy link
Contributor

so that clients that don't support this new format don't nuke the new entries

I'd argue that if clients are modifying the entires tags array, they are doing it wrong. If a client supports a mute list, and a user mutes a new item, it should be as simple as taking their existing mute list, appending an item to the array, and relaying that. That client doesn't need to support expiring mute items. And it shouldn't modify existing expiring mute items. It's simply an appending to the existing array. No need to modify existing data.

You are presuming a lot about how clients manage data. They may not be generating mute lists from the previous event, but from data imported from the previous event into faster data structures, and that imported data might not include this expiry data because the client wasn't aware of such a field. I can say for sure that the gossip client will be clobbering these unless and until I change it, and that people will be running old clients that will just keep clobbering these until they upgrade. But if we have to go this way, we will eventually get past the "epoch of mute expiration clobbers". I can "fix" my code to try to preserve tags exactly, even unknown parts, but old gossips won't have this code.

@jb55
Copy link
Contributor

jb55 commented Jan 15, 2024 via email

@mikedilger
Copy link
Contributor

There should be a general NIP about treating nostr notes as dynamic objects and not static ones. Static typing doesn't make sense in an open network where there is no single type for things. In the early days I've seen peoples lightning addresses get wiped out as well as profile properties, just because clients decide its ok to parse fields and write them out again (it's not!). For highly shared types like mute lists, profiles, contact lists, etc: you should be respectful of data that might be there that you are not aware of. If you're not respectful, well, I will warn my users to not use your client or risk data corruption.

I strongly agree that clients need to preserve data they do not understand so as to not impede changes to the protocol. That goes for tags they don't understand, but also extra strings at the ends of tags which they think they do understand (but don't). And I support having some statement like that written into NIP-01.

I have little opinion on this NIP itself, I just thought I should let everybody know the situation with these kinds of changes. I fucked up, and I'm guessing other client developers probably fucked up too.

BTW: This can be done with static typing, it doesn't require dynamic typing. Vectors of strings are dynamic enough. Gossip has always preserved all metadata it didn't understand, and it has not clobbered follow lists. I think I have a good history of not making this kind of mistake. But unfortunately this time I did, I'm sorry, and I thought you should be aware of it.

@staab
Copy link
Member

staab commented Jan 16, 2024

I also frequently stomp stuff I don't recognize in coracle. And I agree the ideal is to preserve whatever weird stuff is in tag lists, but the real question is will developers do that? I think we have enough evidence that the answer is usually no. So we should probably design the protocol to be resilient to poor implementations.

@fishcharlie
Copy link
Author

The Damus implementation of this has been merged: damus-io/damus@f341a37

cc/ @jb55

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants