notedeck

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

kind.rs (4705B)


      1 use crate::error::{Error, FilterError};
      2 use crate::filter;
      3 use crate::filter::FilterState;
      4 use crate::timeline::Timeline;
      5 use enostr::{Filter, Pubkey};
      6 use nostrdb::{Ndb, Transaction};
      7 use std::fmt::Display;
      8 use tracing::{error, warn};
      9 
     10 #[derive(Clone, Debug)]
     11 pub enum PubkeySource {
     12     Explicit(Pubkey),
     13     DeckAuthor,
     14 }
     15 
     16 #[derive(Debug, Clone)]
     17 pub enum ListKind {
     18     Contact(PubkeySource),
     19 }
     20 
     21 ///
     22 /// What kind of timeline is it?
     23 ///   - Follow List
     24 ///   - Notifications
     25 ///   - DM
     26 ///   - filter
     27 ///   - ... etc
     28 ///
     29 #[derive(Debug, Clone)]
     30 pub enum TimelineKind {
     31     List(ListKind),
     32 
     33     Notifications(PubkeySource),
     34 
     35     Profile(PubkeySource),
     36 
     37     Universe,
     38 
     39     /// Generic filter
     40     Generic,
     41 }
     42 
     43 impl Display for TimelineKind {
     44     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
     45         match self {
     46             TimelineKind::List(ListKind::Contact(_src)) => f.write_str("Contacts"),
     47             TimelineKind::Generic => f.write_str("Timeline"),
     48             TimelineKind::Notifications(_) => f.write_str("Notifications"),
     49             TimelineKind::Profile(_) => f.write_str("Profile"),
     50             TimelineKind::Universe => f.write_str("Universe"),
     51         }
     52     }
     53 }
     54 
     55 impl TimelineKind {
     56     pub fn contact_list(pk: PubkeySource) -> Self {
     57         TimelineKind::List(ListKind::Contact(pk))
     58     }
     59 
     60     pub fn profile(pk: PubkeySource) -> Self {
     61         TimelineKind::Profile(pk)
     62     }
     63 
     64     pub fn notifications(pk: PubkeySource) -> Self {
     65         TimelineKind::Notifications(pk)
     66     }
     67 
     68     pub fn into_timeline(self, ndb: &Ndb, default_user: Option<&[u8; 32]>) -> Option<Timeline> {
     69         match self {
     70             TimelineKind::Universe => Some(Timeline::new(
     71                 TimelineKind::Universe,
     72                 FilterState::ready(vec![Filter::new()
     73                     .kinds([1])
     74                     .limit(filter::default_limit())
     75                     .build()]),
     76             )),
     77 
     78             TimelineKind::Generic => {
     79                 warn!("you can't convert a TimelineKind::Generic to a Timeline");
     80                 None
     81             }
     82 
     83             TimelineKind::Profile(pk_src) => {
     84                 let pk = match &pk_src {
     85                     PubkeySource::DeckAuthor => default_user?,
     86                     PubkeySource::Explicit(pk) => pk.bytes(),
     87                 };
     88 
     89                 let filter = Filter::new()
     90                     .authors([pk])
     91                     .kinds([1])
     92                     .limit(filter::default_limit())
     93                     .build();
     94 
     95                 Some(Timeline::new(
     96                     TimelineKind::profile(pk_src),
     97                     FilterState::ready(vec![filter]),
     98                 ))
     99             }
    100 
    101             TimelineKind::Notifications(pk_src) => {
    102                 let pk = match &pk_src {
    103                     PubkeySource::DeckAuthor => default_user?,
    104                     PubkeySource::Explicit(pk) => pk.bytes(),
    105                 };
    106 
    107                 let notifications_filter = Filter::new()
    108                     .pubkeys([pk])
    109                     .kinds([1])
    110                     .limit(crate::filter::default_limit())
    111                     .build();
    112 
    113                 Some(Timeline::new(
    114                     TimelineKind::notifications(pk_src),
    115                     FilterState::ready(vec![notifications_filter]),
    116                 ))
    117             }
    118 
    119             TimelineKind::List(ListKind::Contact(pk_src)) => {
    120                 let pk = match &pk_src {
    121                     PubkeySource::DeckAuthor => default_user?,
    122                     PubkeySource::Explicit(pk) => pk.bytes(),
    123                 };
    124 
    125                 let contact_filter = Filter::new().authors([pk]).kinds([3]).limit(1).build();
    126 
    127                 let txn = Transaction::new(ndb).expect("txn");
    128                 let results = ndb
    129                     .query(&txn, &[contact_filter.clone()], 1)
    130                     .expect("contact query failed?");
    131 
    132                 if results.is_empty() {
    133                     return Some(Timeline::new(
    134                         TimelineKind::contact_list(pk_src),
    135                         FilterState::needs_remote(vec![contact_filter.clone()]),
    136                     ));
    137                 }
    138 
    139                 match Timeline::contact_list(&results[0].note) {
    140                     Err(Error::Filter(FilterError::EmptyContactList)) => Some(Timeline::new(
    141                         TimelineKind::contact_list(pk_src),
    142                         FilterState::needs_remote(vec![contact_filter]),
    143                     )),
    144                     Err(e) => {
    145                         error!("Unexpected error: {e}");
    146                         None
    147                     }
    148                     Ok(tl) => Some(tl),
    149                 }
    150             }
    151         }
    152     }
    153 }