feat: add basic relay management in rust
This commit is contained in:
@@ -60,6 +60,10 @@ fn main() {
|
||||
.add_relay("wss://bostr.nokotaro.work/")
|
||||
.await
|
||||
.expect("Cannot connect to bostr.nokotaro.work, please try again later.");
|
||||
client
|
||||
.add_relay("wss://purplepag.es/")
|
||||
.await
|
||||
.expect("Cannot connect to purplepag.es, please try again later.");
|
||||
|
||||
// Connect
|
||||
client.connect().await;
|
||||
@@ -92,6 +96,10 @@ fn main() {
|
||||
Some(vec![]),
|
||||
))
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
nostr::relay::get_relays,
|
||||
nostr::relay::list_connected_relays,
|
||||
nostr::relay::connect_relay,
|
||||
nostr::relay::remove_relay,
|
||||
nostr::keys::create_keys,
|
||||
nostr::keys::save_key,
|
||||
nostr::keys::get_encrypted_key,
|
||||
@@ -108,7 +116,6 @@ fn main() {
|
||||
nostr::metadata::get_current_user_profile,
|
||||
nostr::metadata::get_profile,
|
||||
nostr::metadata::get_contact_list,
|
||||
nostr::metadata::get_contact_metadata,
|
||||
nostr::metadata::create_profile,
|
||||
nostr::metadata::follow,
|
||||
nostr::metadata::unfollow,
|
||||
|
||||
@@ -118,7 +118,7 @@ pub async fn verify_signer(state: State<'_, Nostr>) -> Result<bool, ()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[tauri::command(async)]
|
||||
pub fn get_encrypted_key(npub: &str, password: &str) -> Result<String, String> {
|
||||
let keyring = Entry::new("Lume Secret Storage", npub).unwrap();
|
||||
|
||||
@@ -190,12 +190,26 @@ pub async fn load_selected_account(npub: &str, state: State<'_, Nostr>) -> Resul
|
||||
if let Some(event) = events.first() {
|
||||
let relay_list = nip65::extract_relay_list(event);
|
||||
for item in relay_list.into_iter() {
|
||||
println!("connecting to relay: {}", item.0);
|
||||
// Add relay to pool
|
||||
println!("connecting to relay: {} - {:?}", item.0, item.1);
|
||||
|
||||
let relay_url = item.0.to_string();
|
||||
let opts = match item.1 {
|
||||
Some(val) => {
|
||||
if val == RelayMetadata::Read {
|
||||
RelayOptions::new().read(true).write(false)
|
||||
} else {
|
||||
RelayOptions::new().write(true).read(false)
|
||||
}
|
||||
}
|
||||
None => RelayOptions::new(),
|
||||
};
|
||||
|
||||
// Add relay to relay pool
|
||||
let _ = client
|
||||
.add_relay(item.0.to_string())
|
||||
.add_relay_with_opts(relay_url, opts)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
// Connect relay
|
||||
client
|
||||
.connect_relay(item.0.to_string())
|
||||
|
||||
@@ -5,12 +5,6 @@ use std::{str::FromStr, time::Duration};
|
||||
use tauri::{Manager, State};
|
||||
use url::Url;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct CacheContact {
|
||||
pubkey: String,
|
||||
profile: Metadata,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn run_notification(accounts: Vec<String>, app: tauri::AppHandle) -> Result<(), ()> {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
@@ -206,28 +200,6 @@ pub async fn get_contact_list(state: State<'_, Nostr>) -> Result<Vec<String>, St
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_contact_metadata(state: State<'_, Nostr>) -> Result<Vec<CacheContact>, String> {
|
||||
let client = &state.client;
|
||||
|
||||
if let Ok(contact_list) = client
|
||||
.get_contact_list_metadata(Some(Duration::from_secs(10)))
|
||||
.await
|
||||
{
|
||||
let list: Vec<CacheContact> = contact_list
|
||||
.into_iter()
|
||||
.map(|(id, metadata)| CacheContact {
|
||||
pubkey: id.to_hex(),
|
||||
profile: metadata,
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(list)
|
||||
} else {
|
||||
Err("Contact list not found".into())
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn create_profile(
|
||||
name: &str,
|
||||
|
||||
@@ -2,11 +2,81 @@ use crate::Nostr;
|
||||
use nostr_sdk::prelude::*;
|
||||
use tauri::State;
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
pub struct Relays {
|
||||
connected: Vec<String>,
|
||||
read: Option<Vec<String>>,
|
||||
write: Option<Vec<String>>,
|
||||
both: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, ()> {
|
||||
let client = &state.client;
|
||||
|
||||
// Get connected relays
|
||||
let list = client.relays().await;
|
||||
let connected_relays: Vec<String> = list.into_iter().map(|(url, _)| url.to_string()).collect();
|
||||
|
||||
// Get NIP-65 relay list
|
||||
let signer = client.signer().await.unwrap();
|
||||
let public_key = signer.public_key().await.unwrap();
|
||||
let filter = Filter::new()
|
||||
.author(public_key)
|
||||
.kind(Kind::RelayList)
|
||||
.limit(1);
|
||||
|
||||
match client.get_events_of(vec![filter], None).await {
|
||||
Ok(events) => {
|
||||
if let Some(event) = events.first() {
|
||||
let nip65_list = nip65::extract_relay_list(event);
|
||||
let read: Vec<String> = nip65_list
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|i| matches!(&i.1, Some(y) if *y == RelayMetadata::Read))
|
||||
.map(|(url, _)| url.to_string())
|
||||
.collect();
|
||||
let write: Vec<String> = nip65_list
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|i| matches!(&i.1, Some(y) if *y == RelayMetadata::Write))
|
||||
.map(|(url, _)| url.to_string())
|
||||
.collect();
|
||||
let both: Vec<String> = nip65_list
|
||||
.into_iter()
|
||||
.filter(|i| i.1.is_none())
|
||||
.map(|(url, _)| url.to_string())
|
||||
.collect();
|
||||
|
||||
Ok(Relays {
|
||||
connected: connected_relays,
|
||||
read: Some(read),
|
||||
write: Some(write),
|
||||
both: Some(both),
|
||||
})
|
||||
} else {
|
||||
Ok(Relays {
|
||||
connected: connected_relays,
|
||||
read: None,
|
||||
write: None,
|
||||
both: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
Err(_) => Ok(Relays {
|
||||
connected: connected_relays,
|
||||
read: None,
|
||||
write: None,
|
||||
both: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_connected_relays(state: State<'_, Nostr>) -> Result<Vec<Url>, ()> {
|
||||
let client = &state.client;
|
||||
let relays = client.relays().await;
|
||||
let list: Vec<Url> = relays.into_keys().collect();
|
||||
let connected_relays = client.relays().await;
|
||||
let list = connected_relays.into_keys().collect();
|
||||
|
||||
Ok(list)
|
||||
}
|
||||
@@ -15,6 +85,7 @@ pub async fn list_connected_relays(state: State<'_, Nostr>) -> Result<Vec<Url>,
|
||||
pub async fn connect_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, ()> {
|
||||
let client = &state.client;
|
||||
if let Ok(_) = client.add_relay(relay).await {
|
||||
let _ = client.connect_relay(relay);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
@@ -25,6 +96,7 @@ pub async fn connect_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool,
|
||||
pub async fn remove_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, ()> {
|
||||
let client = &state.client;
|
||||
if let Ok(_) = client.remove_relay(relay).await {
|
||||
let _ = client.disconnect_relay(relay);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
|
||||
Reference in New Issue
Block a user