mirror of
https://github.com/aljazceru/notedeck.git
synced 2025-12-19 09:34:19 +01:00
add onboarding 'manager'
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -18,6 +18,7 @@ pub mod login_manager;
|
|||||||
mod media_upload;
|
mod media_upload;
|
||||||
mod multi_subscriber;
|
mod multi_subscriber;
|
||||||
mod nav;
|
mod nav;
|
||||||
|
mod onboarding;
|
||||||
pub mod options;
|
pub mod options;
|
||||||
mod post;
|
mod post;
|
||||||
mod profile;
|
mod profile;
|
||||||
|
|||||||
150
crates/notedeck_columns/src/onboarding.rs
Normal file
150
crates/notedeck_columns/src/onboarding.rs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
use enostr::{Pubkey, RelayPool};
|
||||||
|
use nostrdb::{Filter, Ndb, NoteKey, Transaction};
|
||||||
|
use notedeck::{create_nip51_set, filter::default_limit, Nip51SetCache, UnknownIds};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::subscriptions::Subscriptions;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum OnboardingState {
|
||||||
|
AwaitingTrustedPksList(Vec<Filter>),
|
||||||
|
HaveFollowPacks(Nip51SetCache),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manages the onboarding process. Responsible for retriving the kind 30000 list of trusted pubkeys
|
||||||
|
/// and then retrieving all follow packs from the trusted pks updating when new ones arrive
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Onboarding {
|
||||||
|
state: Option<Result<OnboardingState, OnboardingError>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Onboarding {
|
||||||
|
pub fn get_follow_packs(&self) -> Option<&Nip51SetCache> {
|
||||||
|
let Some(Ok(OnboardingState::HaveFollowPacks(packs))) = &self.state else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(packs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_follow_packs_mut(&mut self) -> Option<&mut Nip51SetCache> {
|
||||||
|
let Some(Ok(OnboardingState::HaveFollowPacks(packs))) = &mut self.state else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(packs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn process(
|
||||||
|
&mut self,
|
||||||
|
pool: &mut RelayPool,
|
||||||
|
ndb: &Ndb,
|
||||||
|
subs: &mut Subscriptions,
|
||||||
|
unknown_ids: &mut UnknownIds,
|
||||||
|
) {
|
||||||
|
match &self.state {
|
||||||
|
Some(res) => {
|
||||||
|
let Ok(OnboardingState::AwaitingTrustedPksList(filter)) = res else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let txn = Transaction::new(ndb).expect("txns");
|
||||||
|
let Ok(res) = ndb.query(&txn, filter, 1) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if res.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let key = res.first().expect("checked empty").note_key;
|
||||||
|
|
||||||
|
let new_state = get_trusted_authors(ndb, &txn, key).and_then(|trusted_pks| {
|
||||||
|
let pks: Vec<&[u8; 32]> = trusted_pks.iter().map(|f| f.bytes()).collect();
|
||||||
|
Nip51SetCache::new(pool, ndb, &txn, unknown_ids, vec![follow_packs_filter(pks)])
|
||||||
|
.map(OnboardingState::HaveFollowPacks)
|
||||||
|
.ok_or(OnboardingError::InvalidNip51Set)
|
||||||
|
});
|
||||||
|
|
||||||
|
self.state = Some(new_state);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let filter = vec![trusted_pks_list_filter()];
|
||||||
|
|
||||||
|
let subid = Uuid::new_v4().to_string();
|
||||||
|
pool.subscribe(subid.clone(), filter.clone());
|
||||||
|
subs.subs
|
||||||
|
.insert(subid, crate::subscriptions::SubKind::OneShot);
|
||||||
|
|
||||||
|
let new_state = Some(Ok(OnboardingState::AwaitingTrustedPksList(filter)));
|
||||||
|
self.state = new_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsubscribe and clear state
|
||||||
|
pub fn end_onboarding(&mut self, pool: &mut RelayPool, ndb: &mut Ndb) {
|
||||||
|
let Some(Ok(OnboardingState::HaveFollowPacks(state))) = &mut self.state else {
|
||||||
|
self.state = None;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let unified = &state.sub;
|
||||||
|
|
||||||
|
pool.unsubscribe(unified.remote.clone());
|
||||||
|
let _ = ndb.unsubscribe(unified.local);
|
||||||
|
|
||||||
|
self.state = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum OnboardingError {
|
||||||
|
InvalidNip51Set,
|
||||||
|
InvalidTrustedPksListKind,
|
||||||
|
NdbCouldNotFindNote,
|
||||||
|
}
|
||||||
|
|
||||||
|
// author providing the list of trusted follow pack authors
|
||||||
|
const FOLLOW_PACK_AUTHOR: [u8; 32] = [
|
||||||
|
0x89, 0x5c, 0x2a, 0x90, 0xa8, 0x60, 0xac, 0x18, 0x43, 0x4a, 0xa6, 0x9e, 0x7b, 0x0d, 0xa8, 0x46,
|
||||||
|
0x57, 0x21, 0x21, 0x6f, 0xa3, 0x6e, 0x42, 0xc0, 0x22, 0xe3, 0x93, 0x57, 0x9c, 0x48, 0x6c, 0xba,
|
||||||
|
];
|
||||||
|
|
||||||
|
fn trusted_pks_list_filter() -> Filter {
|
||||||
|
Filter::new()
|
||||||
|
.kinds([30000])
|
||||||
|
.limit(1)
|
||||||
|
.authors(&[FOLLOW_PACK_AUTHOR])
|
||||||
|
.tags(["test"], 'd') // TODO(kernelkind): replace with actual d tag
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn follow_packs_filter(pks: Vec<&[u8; 32]>) -> Filter {
|
||||||
|
Filter::new()
|
||||||
|
.kinds([39089])
|
||||||
|
.limit(default_limit())
|
||||||
|
.authors(pks)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// gets the pubkeys from a kind 30000 follow set
|
||||||
|
fn get_trusted_authors(
|
||||||
|
ndb: &Ndb,
|
||||||
|
txn: &Transaction,
|
||||||
|
key: NoteKey,
|
||||||
|
) -> Result<Vec<Pubkey>, OnboardingError> {
|
||||||
|
let Ok(note) = ndb.get_note_by_key(txn, key) else {
|
||||||
|
return Result::Err(OnboardingError::NdbCouldNotFindNote);
|
||||||
|
};
|
||||||
|
|
||||||
|
if note.kind() != 30000 {
|
||||||
|
return Result::Err(OnboardingError::InvalidTrustedPksListKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(nip51set) = create_nip51_set(note) else {
|
||||||
|
return Result::Err(OnboardingError::InvalidNip51Set);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(nip51set.pks)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user