Skip to content

Commit

Permalink
algos: introduce last_n_per_pubkey_from_tags
Browse files Browse the repository at this point in the history
This function creates filters for the base our first algo in Damus:

Called "last N note per pubkey". I don't have a better name for it.

This function generates a query in the form:

[
  {"authors": ["author_a"], "limit": 1, "kinds": [1]
, {"authors": ["author_b"], "limit": 1, "kinds": [1]
, {"authors": ["author_c"], "limit": 1, "kinds": [1]
, {"authors": ["author_c"], "limit": 1, "kinds": [1]
  ...
]

Due to an unfortunate restriction currently in nostrdb and strfry, we
can only do about 16 to 20 of these at any given time. I have made
this limit configurable in strfry[1]. I just need to do the same in
nostrdb now.

[1] hoytech/strfry#133

Changelog-Added: Add last_n_per_pubkey_from_tags algo function
  • Loading branch information
jb55 committed Dec 26, 2024
1 parent f569f94 commit 88c9bbd
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions crates/notedeck/src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,60 @@ impl FilteredTags {
}
}

/// Create a "last N notes per pubkey" query.
pub fn last_n_per_pubkey_from_tags(
note: &Note,
kind: u64,
notes_per_pubkey: u64,
) -> Result<Vec<Filter>> {
let mut filters: Vec<Filter> = vec![];

for tag in note.tags() {
// TODO: fix arbitrary MAX_FILTER limit in nostrdb
if filters.len() == 15 {
break;
}

if tag.count() < 2 {
continue;
}

let t = if let Some(t) = tag.get_unchecked(0).variant().str() {
t
} else {
continue;
};

if t == "p" {
let author = if let Some(author) = tag.get_unchecked(1).variant().id() {
author
} else {
continue;
};

let mut filter = Filter::new();
filter.start_authors_field()?;
filter.add_id_element(author)?;
filter.end_field();
filters.push(filter.kinds([kind]).limit(notes_per_pubkey).build());
} else if t == "t" {
let hashtag = if let Some(hashtag) = tag.get_unchecked(1).variant().str() {
hashtag
} else {
continue;
};

let mut filter = Filter::new();
filter.start_tags_field('t')?;
filter.add_str_element(hashtag)?;
filter.end_field();
filters.push(filter.kinds([kind]).limit(notes_per_pubkey).build());
}
}

Ok(filters)
}

/// Create a filter from tags. This can be used to create a filter
/// from a contact list
pub fn filter_from_tags(note: &Note, add_pubkey: Option<&[u8; 32]>) -> Result<FilteredTags> {
Expand Down

0 comments on commit 88c9bbd

Please sign in to comment.