accounts: move mute stuff to own module
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -1,14 +1,12 @@
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::account::mute::AccountMutedData;
|
||||
use crate::account::relay::AccountRelayData;
|
||||
use crate::{
|
||||
AccountStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount,
|
||||
};
|
||||
use crate::{AccountStorage, MuteFun, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount};
|
||||
use enostr::{ClientMessage, FilledKeypair, Keypair, Pubkey, RelayPool};
|
||||
use nostrdb::{Filter, Ndb, Note, NoteKey, Subscription, Transaction};
|
||||
use nostrdb::{Ndb, Note, Transaction};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use uuid::Uuid;
|
||||
|
||||
// TODO: remove this
|
||||
use std::sync::Arc;
|
||||
@@ -46,120 +44,6 @@ pub struct AddAccountAction {
|
||||
pub unk_id_action: SingleUnkIdAction,
|
||||
}
|
||||
|
||||
pub struct AccountMutedData {
|
||||
filter: Filter,
|
||||
subid: Option<String>,
|
||||
sub: Option<Subscription>,
|
||||
muted: Arc<Muted>,
|
||||
}
|
||||
|
||||
impl AccountMutedData {
|
||||
pub fn new(ndb: &Ndb, pubkey: &[u8; 32]) -> Self {
|
||||
// Construct a filter for the user's NIP-51 muted list
|
||||
let filter = Filter::new()
|
||||
.authors([pubkey])
|
||||
.kinds([10000])
|
||||
.limit(1)
|
||||
.build();
|
||||
|
||||
// Query the ndb immediately to see if the user's muted list is already there
|
||||
let txn = Transaction::new(ndb).expect("transaction");
|
||||
let lim = filter.limit().unwrap_or(crate::filter::default_limit()) as i32;
|
||||
let nks = ndb
|
||||
.query(&txn, &[filter.clone()], lim)
|
||||
.expect("query user muted results")
|
||||
.iter()
|
||||
.map(|qr| qr.note_key)
|
||||
.collect::<Vec<NoteKey>>();
|
||||
let muted = Self::harvest_nip51_muted(ndb, &txn, &nks);
|
||||
debug!("pubkey {}: initial muted {:?}", hex::encode(pubkey), muted);
|
||||
|
||||
AccountMutedData {
|
||||
filter,
|
||||
subid: None,
|
||||
sub: None,
|
||||
muted: Arc::new(muted),
|
||||
}
|
||||
}
|
||||
|
||||
// make this account the current selected account
|
||||
pub fn activate(&mut self, ndb: &Ndb, pool: &mut RelayPool) {
|
||||
debug!("activating muted sub {}", self.filter.json().unwrap());
|
||||
assert_eq!(self.subid, None, "subid already exists");
|
||||
assert_eq!(self.sub, None, "sub already exists");
|
||||
|
||||
// local subscription
|
||||
let sub = ndb
|
||||
.subscribe(&[self.filter.clone()])
|
||||
.expect("ndb muted subscription");
|
||||
|
||||
// remote subscription
|
||||
let subid = Uuid::new_v4().to_string();
|
||||
pool.subscribe(subid.clone(), vec![self.filter.clone()]);
|
||||
|
||||
self.sub = Some(sub);
|
||||
self.subid = Some(subid);
|
||||
}
|
||||
|
||||
// this account is no longer the selected account
|
||||
pub fn deactivate(&mut self, ndb: &mut Ndb, pool: &mut RelayPool) {
|
||||
debug!("deactivating muted sub {}", self.filter.json().unwrap());
|
||||
assert_ne!(self.subid, None, "subid doesn't exist");
|
||||
assert_ne!(self.sub, None, "sub doesn't exist");
|
||||
|
||||
// remote subscription
|
||||
pool.unsubscribe(self.subid.as_ref().unwrap().clone());
|
||||
|
||||
// local subscription
|
||||
ndb.unsubscribe(self.sub.unwrap())
|
||||
.expect("ndb muted unsubscribe");
|
||||
|
||||
self.sub = None;
|
||||
self.subid = None;
|
||||
}
|
||||
|
||||
fn harvest_nip51_muted(ndb: &Ndb, txn: &Transaction, nks: &[NoteKey]) -> Muted {
|
||||
let mut muted = Muted::default();
|
||||
for nk in nks.iter() {
|
||||
if let Ok(note) = ndb.get_note_by_key(txn, *nk) {
|
||||
for tag in note.tags() {
|
||||
match tag.get(0).and_then(|t| t.variant().str()) {
|
||||
Some("p") => {
|
||||
if let Some(id) = tag.get(1).and_then(|f| f.variant().id()) {
|
||||
muted.pubkeys.insert(*id);
|
||||
}
|
||||
}
|
||||
Some("t") => {
|
||||
if let Some(str) = tag.get(1).and_then(|f| f.variant().str()) {
|
||||
muted.hashtags.insert(str.to_string());
|
||||
}
|
||||
}
|
||||
Some("word") => {
|
||||
if let Some(str) = tag.get(1).and_then(|f| f.variant().str()) {
|
||||
muted.words.insert(str.to_string());
|
||||
}
|
||||
}
|
||||
Some("e") => {
|
||||
if let Some(id) = tag.get(1).and_then(|f| f.variant().id()) {
|
||||
muted.threads.insert(*id);
|
||||
}
|
||||
}
|
||||
Some("alt") => {
|
||||
// maybe we can ignore these?
|
||||
}
|
||||
Some(x) => error!("query_nip51_muted: unexpected tag: {}", x),
|
||||
None => error!(
|
||||
"query_nip51_muted: bad tag value: {:?}",
|
||||
tag.get_unchecked(0).variant()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
muted
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AccountData {
|
||||
pub(crate) relay: AccountRelayData,
|
||||
pub(crate) muted: AccountMutedData,
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod accounts;
|
||||
pub mod mute;
|
||||
pub mod relay;
|
||||
|
||||
122
crates/notedeck/src/account/mute.rs
Normal file
122
crates/notedeck/src/account/mute.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use enostr::RelayPool;
|
||||
use nostrdb::{Filter, Ndb, NoteKey, Subscription, Transaction};
|
||||
use tracing::{debug, error};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::Muted;
|
||||
|
||||
pub(crate) struct AccountMutedData {
|
||||
pub filter: Filter,
|
||||
pub subid: Option<String>,
|
||||
pub sub: Option<Subscription>,
|
||||
pub muted: Arc<Muted>,
|
||||
}
|
||||
|
||||
impl AccountMutedData {
|
||||
pub fn new(ndb: &Ndb, pubkey: &[u8; 32]) -> Self {
|
||||
// Construct a filter for the user's NIP-51 muted list
|
||||
let filter = Filter::new()
|
||||
.authors([pubkey])
|
||||
.kinds([10000])
|
||||
.limit(1)
|
||||
.build();
|
||||
|
||||
// Query the ndb immediately to see if the user's muted list is already there
|
||||
let txn = Transaction::new(ndb).expect("transaction");
|
||||
let lim = filter.limit().unwrap_or(crate::filter::default_limit()) as i32;
|
||||
let nks = ndb
|
||||
.query(&txn, &[filter.clone()], lim)
|
||||
.expect("query user muted results")
|
||||
.iter()
|
||||
.map(|qr| qr.note_key)
|
||||
.collect::<Vec<NoteKey>>();
|
||||
let muted = Self::harvest_nip51_muted(ndb, &txn, &nks);
|
||||
debug!("pubkey {}: initial muted {:?}", hex::encode(pubkey), muted);
|
||||
|
||||
AccountMutedData {
|
||||
filter,
|
||||
subid: None,
|
||||
sub: None,
|
||||
muted: Arc::new(muted),
|
||||
}
|
||||
}
|
||||
|
||||
// make this account the current selected account
|
||||
pub fn activate(&mut self, ndb: &Ndb, pool: &mut RelayPool) {
|
||||
debug!("activating muted sub {}", self.filter.json().unwrap());
|
||||
assert_eq!(self.subid, None, "subid already exists");
|
||||
assert_eq!(self.sub, None, "sub already exists");
|
||||
|
||||
// local subscription
|
||||
let sub = ndb
|
||||
.subscribe(&[self.filter.clone()])
|
||||
.expect("ndb muted subscription");
|
||||
|
||||
// remote subscription
|
||||
let subid = Uuid::new_v4().to_string();
|
||||
pool.subscribe(subid.clone(), vec![self.filter.clone()]);
|
||||
|
||||
self.sub = Some(sub);
|
||||
self.subid = Some(subid);
|
||||
}
|
||||
|
||||
// this account is no longer the selected account
|
||||
pub fn deactivate(&mut self, ndb: &mut Ndb, pool: &mut RelayPool) {
|
||||
debug!("deactivating muted sub {}", self.filter.json().unwrap());
|
||||
assert_ne!(self.subid, None, "subid doesn't exist");
|
||||
assert_ne!(self.sub, None, "sub doesn't exist");
|
||||
|
||||
// remote subscription
|
||||
pool.unsubscribe(self.subid.as_ref().unwrap().clone());
|
||||
|
||||
// local subscription
|
||||
ndb.unsubscribe(self.sub.unwrap())
|
||||
.expect("ndb muted unsubscribe");
|
||||
|
||||
self.sub = None;
|
||||
self.subid = None;
|
||||
}
|
||||
|
||||
pub(crate) fn harvest_nip51_muted(ndb: &Ndb, txn: &Transaction, nks: &[NoteKey]) -> Muted {
|
||||
let mut muted = Muted::default();
|
||||
for nk in nks.iter() {
|
||||
if let Ok(note) = ndb.get_note_by_key(txn, *nk) {
|
||||
for tag in note.tags() {
|
||||
match tag.get(0).and_then(|t| t.variant().str()) {
|
||||
Some("p") => {
|
||||
if let Some(id) = tag.get(1).and_then(|f| f.variant().id()) {
|
||||
muted.pubkeys.insert(*id);
|
||||
}
|
||||
}
|
||||
Some("t") => {
|
||||
if let Some(str) = tag.get(1).and_then(|f| f.variant().str()) {
|
||||
muted.hashtags.insert(str.to_string());
|
||||
}
|
||||
}
|
||||
Some("word") => {
|
||||
if let Some(str) = tag.get(1).and_then(|f| f.variant().str()) {
|
||||
muted.words.insert(str.to_string());
|
||||
}
|
||||
}
|
||||
Some("e") => {
|
||||
if let Some(id) = tag.get(1).and_then(|f| f.variant().id()) {
|
||||
muted.threads.insert(*id);
|
||||
}
|
||||
}
|
||||
Some("alt") => {
|
||||
// maybe we can ignore these?
|
||||
}
|
||||
Some(x) => error!("query_nip51_muted: unexpected tag: {}", x),
|
||||
None => error!(
|
||||
"query_nip51_muted: bad tag value: {:?}",
|
||||
tag.get_unchecked(0).variant()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
muted
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user