notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit ad9c8f959cfba10713b1b7b90d2dad051578e825
parent ca09dc1675d1fc281d4006c463e3d9fae7d83ad1
Author: William Casarin <jb55@jb55.com>
Date:   Mon,  2 Sep 2024 18:29:21 -0700

columns: add --notifications{,:pubkey} argcolumn

This allows you to add notification columns pretty easily:

$ notedeck --sec $SEC -c contacts -c notifications -c notifications:$CORP_ACCT

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Msrc/args.rs | 23++++++++++++++++++++---
Msrc/column.rs | 35+++++++++++++++++++++++++++++++----
2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/src/args.rs b/src/args.rs @@ -3,7 +3,7 @@ use crate::filter::FilterState; use crate::timeline::Timeline; use enostr::{Filter, Keypair, Pubkey, SecretKey}; use nostrdb::Ndb; -use tracing::{error, info}; +use tracing::{debug, error, info}; pub struct Args { pub columns: Vec<ArgColumn>, @@ -117,18 +117,35 @@ impl Args { if let Some(rest) = column_name.strip_prefix("contacts:") { if let Ok(pubkey) = Pubkey::parse(rest) { - info!("got contact column for user {}", pubkey.hex()); + info!("contact column for user {}", pubkey.hex()); res.columns.push(ArgColumn::Column(ColumnKind::contact_list( PubkeySource::Explicit(pubkey), ))) } else { - error!("error parsing contacts pubkey {}", &column_name[9..]); + error!("error parsing contacts pubkey {}", rest); continue; } } else if column_name == "contacts" { res.columns.push(ArgColumn::Column(ColumnKind::contact_list( PubkeySource::DeckAuthor, ))) + } else if let Some(notif_pk_str) = column_name.strip_prefix("notifications:") { + if let Ok(pubkey) = Pubkey::parse(notif_pk_str) { + info!("got notifications column for user {}", pubkey.hex()); + res.columns + .push(ArgColumn::Column(ColumnKind::notifications( + PubkeySource::Explicit(pubkey), + ))) + } else { + error!("error parsing notifications pubkey {}", notif_pk_str); + continue; + } + } else if column_name == "notifications" { + debug!("got notification column for default user"); + res.columns + .push(ArgColumn::Column(ColumnKind::notifications( + PubkeySource::DeckAuthor, + ))) } } else if arg == "--filter-file" || arg == "-f" { i += 1; diff --git a/src/column.rs b/src/column.rs @@ -1,5 +1,6 @@ use crate::error::FilterError; use crate::filter::FilterState; +use crate::filter; use crate::{timeline::Timeline, Error}; use enostr::Pubkey; use nostrdb::{Filter, Ndb, Transaction}; @@ -27,6 +28,9 @@ pub enum ListKind { #[derive(Debug)] pub enum ColumnKind { List(ListKind), + + Notifications(PubkeySource), + Universe, /// Generic filter @@ -38,6 +42,7 @@ impl Display for ColumnKind { match self { ColumnKind::List(ListKind::Contact(_src)) => f.write_str("Contacts"), ColumnKind::Generic => f.write_str("Timeline"), + ColumnKind::Notifications(_) => f.write_str("Notifications"), ColumnKind::Universe => f.write_str("Universe"), } } @@ -48,6 +53,10 @@ impl ColumnKind { ColumnKind::List(ListKind::Contact(pk)) } + pub fn notifications(pk: PubkeySource) -> Self { + ColumnKind::Notifications(pk) + } + pub fn into_timeline(self, ndb: &Ndb, default_user: Option<&[u8; 32]>) -> Option<Timeline> { match self { ColumnKind::Universe => Some(Timeline::new( @@ -60,8 +69,26 @@ impl ColumnKind { None } - ColumnKind::List(ListKind::Contact(ref pk_src)) => { - let pk = match pk_src { + ColumnKind::Notifications(pk_src) => { + let pk = match &pk_src { + PubkeySource::DeckAuthor => default_user?, + PubkeySource::Explicit(pk) => pk.bytes(), + }; + + let notifications_filter = Filter::new() + .pubkeys([pk]) + .kinds([1]) + .limit(filter::default_limit()) + .build(); + + Some(Timeline::new( + ColumnKind::notifications(pk_src), + FilterState::ready(vec![notifications_filter]), + )) + } + + ColumnKind::List(ListKind::Contact(pk_src)) => { + let pk = match &pk_src { PubkeySource::DeckAuthor => default_user?, PubkeySource::Explicit(pk) => pk.bytes(), }; @@ -75,14 +102,14 @@ impl ColumnKind { if results.is_empty() { return Some(Timeline::new( - ColumnKind::contact_list(pk_src.to_owned()), + ColumnKind::contact_list(pk_src), FilterState::needs_remote(vec![contact_filter.clone()]), )); } match Timeline::contact_list(&results[0].note) { Err(Error::Filter(FilterError::EmptyContactList)) => Some(Timeline::new( - ColumnKind::contact_list(pk_src.to_owned()), + ColumnKind::contact_list(pk_src), FilterState::needs_remote(vec![contact_filter]), )), Err(e) => {