upgrade url string to RelaySpec for [read|write] markers
I think RelaySpec wants to move to enostr so the RelayPool can support read and write relays ...
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::{
|
||||
KeyStorageResponse, KeyStorageType, MuteFun, Muted, SingleUnkIdAction, UnknownIds, UserAccount,
|
||||
KeyStorageResponse, KeyStorageType, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds,
|
||||
UserAccount,
|
||||
};
|
||||
use enostr::{ClientMessage, FilledKeypair, Keypair, RelayPool};
|
||||
use nostrdb::{Filter, Ndb, Note, NoteKey, Subscription, Transaction};
|
||||
@@ -38,8 +39,8 @@ pub struct AccountRelayData {
|
||||
filter: Filter,
|
||||
subid: String,
|
||||
sub: Option<Subscription>,
|
||||
local: BTreeSet<String>, // used locally but not advertised
|
||||
advertised: BTreeSet<String>, // advertised via NIP-65
|
||||
local: BTreeSet<RelaySpec>, // used locally but not advertised
|
||||
advertised: BTreeSet<RelaySpec>, // advertised via NIP-65
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -107,7 +108,7 @@ impl AccountRelayData {
|
||||
}
|
||||
}
|
||||
|
||||
fn harvest_nip65_relays(ndb: &Ndb, txn: &Transaction, nks: &[NoteKey]) -> Vec<String> {
|
||||
fn harvest_nip65_relays(ndb: &Ndb, txn: &Transaction, nks: &[NoteKey]) -> Vec<RelaySpec> {
|
||||
let mut relays = Vec::new();
|
||||
for nk in nks.iter() {
|
||||
if let Ok(note) = ndb.get_note_by_key(txn, *nk) {
|
||||
@@ -115,7 +116,17 @@ impl AccountRelayData {
|
||||
match tag.get(0).and_then(|t| t.variant().str()) {
|
||||
Some("r") => {
|
||||
if let Some(url) = tag.get(1).and_then(|f| f.variant().str()) {
|
||||
relays.push(Self::canonicalize_url(url));
|
||||
let has_read_marker = tag
|
||||
.get(2)
|
||||
.map_or(false, |m| m.variant().str() == Some("read"));
|
||||
let has_write_marker = tag
|
||||
.get(2)
|
||||
.map_or(false, |m| m.variant().str() == Some("write"));
|
||||
relays.push(RelaySpec::new(
|
||||
Self::canonicalize_url(url),
|
||||
has_read_marker,
|
||||
has_write_marker,
|
||||
));
|
||||
}
|
||||
}
|
||||
Some("alt") => {
|
||||
@@ -236,8 +247,8 @@ pub struct Accounts {
|
||||
accounts: Vec<UserAccount>,
|
||||
key_store: KeyStorageType,
|
||||
account_data: BTreeMap<[u8; 32], AccountData>,
|
||||
forced_relays: BTreeSet<String>,
|
||||
bootstrap_relays: BTreeSet<String>,
|
||||
forced_relays: BTreeSet<RelaySpec>,
|
||||
bootstrap_relays: BTreeSet<RelaySpec>,
|
||||
needs_relay_config: bool,
|
||||
}
|
||||
|
||||
@@ -251,9 +262,9 @@ impl Accounts {
|
||||
|
||||
let currently_selected_account = get_selected_index(&accounts, &key_store);
|
||||
let account_data = BTreeMap::new();
|
||||
let forced_relays: BTreeSet<String> = forced_relays
|
||||
let forced_relays: BTreeSet<RelaySpec> = forced_relays
|
||||
.into_iter()
|
||||
.map(|u| AccountRelayData::canonicalize_url(&u))
|
||||
.map(|u| RelaySpec::new(AccountRelayData::canonicalize_url(&u), false, false))
|
||||
.collect();
|
||||
let bootstrap_relays = [
|
||||
"wss://relay.damus.io",
|
||||
@@ -264,7 +275,7 @@ impl Accounts {
|
||||
]
|
||||
.iter()
|
||||
.map(|&url| url.to_string())
|
||||
.map(|u| AccountRelayData::canonicalize_url(&u))
|
||||
.map(|u| RelaySpec::new(AccountRelayData::canonicalize_url(&u), false, false))
|
||||
.collect();
|
||||
|
||||
Accounts {
|
||||
@@ -526,20 +537,26 @@ impl Accounts {
|
||||
debug!("current relays: {:?}", pool.urls());
|
||||
debug!("desired relays: {:?}", desired_relays);
|
||||
|
||||
let add: BTreeSet<String> = desired_relays.difference(&pool.urls()).cloned().collect();
|
||||
let mut sub: BTreeSet<String> = pool.urls().difference(&desired_relays).cloned().collect();
|
||||
let pool_specs = pool
|
||||
.urls()
|
||||
.iter()
|
||||
.map(|url| RelaySpec::new(url.clone(), false, false))
|
||||
.collect();
|
||||
let add: BTreeSet<RelaySpec> = desired_relays.difference(&pool_specs).cloned().collect();
|
||||
let mut sub: BTreeSet<RelaySpec> =
|
||||
pool_specs.difference(&desired_relays).cloned().collect();
|
||||
if !add.is_empty() {
|
||||
debug!("configuring added relays: {:?}", add);
|
||||
let _ = pool.add_urls(add, wakeup);
|
||||
let _ = pool.add_urls(add.iter().map(|r| r.url.clone()).collect(), wakeup);
|
||||
}
|
||||
if !sub.is_empty() {
|
||||
debug!("removing unwanted relays: {:?}", sub);
|
||||
|
||||
// certain relays are persistent like the multicast relay,
|
||||
// although we should probably have a way to explicitly
|
||||
// disable it
|
||||
sub.remove("multicast");
|
||||
pool.remove_urls(&sub);
|
||||
sub.remove(&RelaySpec::new("multicast", false, false));
|
||||
|
||||
debug!("removing unwanted relays: {:?}", sub);
|
||||
pool.remove_urls(&sub.iter().map(|r| r.url.clone()).collect());
|
||||
}
|
||||
|
||||
debug!("current relays: {:?}", pool.urls());
|
||||
@@ -591,6 +608,7 @@ impl Accounts {
|
||||
}
|
||||
|
||||
pub fn add_advertised_relay(&mut self, relay_to_add: &str) {
|
||||
let relay_to_add = AccountRelayData::canonicalize_url(relay_to_add);
|
||||
info!("add advertised relay \"{}\"", relay_to_add);
|
||||
match self.currently_selected_account {
|
||||
None => error!("no account is currently selected."),
|
||||
@@ -607,7 +625,7 @@ impl Accounts {
|
||||
// iniitialize with the bootstrapping set.
|
||||
advertised.extend(self.bootstrap_relays.iter().cloned());
|
||||
}
|
||||
advertised.insert(relay_to_add.to_string());
|
||||
advertised.insert(RelaySpec::new(relay_to_add, false, false));
|
||||
self.needs_relay_config = true;
|
||||
// FIXME - need to publish the advertised set
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ mod muted;
|
||||
pub mod note;
|
||||
mod notecache;
|
||||
mod persist;
|
||||
pub mod relayspec;
|
||||
mod result;
|
||||
pub mod storage;
|
||||
mod style;
|
||||
@@ -33,6 +34,7 @@ pub use muted::{MuteFun, Muted};
|
||||
pub use note::{NoteRef, RootIdError, RootNoteId, RootNoteIdBuf};
|
||||
pub use notecache::{CachedNote, NoteCache};
|
||||
pub use persist::*;
|
||||
pub use relayspec::RelaySpec;
|
||||
pub use result::Result;
|
||||
pub use storage::{
|
||||
DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType,
|
||||
|
||||
90
crates/notedeck/src/relayspec.rs
Normal file
90
crates/notedeck/src/relayspec.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
|
||||
// A Relay specification includes NIP-65 defined "markers" which
|
||||
// indicate if the relay should be used for reading or writing (or
|
||||
// both).
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RelaySpec {
|
||||
pub url: String,
|
||||
pub has_read_marker: bool,
|
||||
pub has_write_marker: bool,
|
||||
}
|
||||
|
||||
impl RelaySpec {
|
||||
pub fn new(
|
||||
url: impl Into<String>,
|
||||
mut has_read_marker: bool,
|
||||
mut has_write_marker: bool,
|
||||
) -> Self {
|
||||
// if both markers are set turn both off ...
|
||||
if has_read_marker && has_write_marker {
|
||||
has_read_marker = false;
|
||||
has_write_marker = false;
|
||||
}
|
||||
RelaySpec {
|
||||
url: url.into(),
|
||||
has_read_marker,
|
||||
has_write_marker,
|
||||
}
|
||||
}
|
||||
|
||||
// The "marker" fields are a little counter-intuitive ... from NIP-65:
|
||||
//
|
||||
// "The event MUST include a list of r tags with relay URIs and a read
|
||||
// or write marker. Relays marked as read / write are called READ /
|
||||
// WRITE relays, respectively. If the marker is omitted, the relay is
|
||||
// used for both purposes."
|
||||
//
|
||||
pub fn is_readable(&self) -> bool {
|
||||
!self.has_write_marker // only "write" relays are not readable
|
||||
}
|
||||
pub fn is_writable(&self) -> bool {
|
||||
!self.has_read_marker // only "read" relays are not writable
|
||||
}
|
||||
}
|
||||
|
||||
// just the url part
|
||||
impl fmt::Display for RelaySpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.url)
|
||||
}
|
||||
}
|
||||
|
||||
// add the read and write markers if present
|
||||
impl fmt::Debug for RelaySpec {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "\"{}\"", self)?;
|
||||
if self.has_read_marker {
|
||||
write!(f, " [r]")?;
|
||||
}
|
||||
if self.has_write_marker {
|
||||
write!(f, " [w]")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// For purposes of set arithmetic only the url is considered, two
|
||||
// RelaySpec which differ only in markers are the same ...
|
||||
|
||||
impl PartialEq for RelaySpec {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.url == other.url
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for RelaySpec {}
|
||||
|
||||
impl PartialOrd for RelaySpec {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.url.cmp(&other.url))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for RelaySpec {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.url.cmp(&other.url)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user