refactor: improve relay management code structure (#220)
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
use std::{
|
|
||||||
fs,
|
|
||||||
io::{self, BufRead, Write},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::Nostr;
|
use crate::Nostr;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use specta::Type;
|
use specta::Type;
|
||||||
|
use std::{
|
||||||
|
fs::OpenOptions,
|
||||||
|
io::{self, BufRead, Write},
|
||||||
|
};
|
||||||
use tauri::{path::BaseDirectory, Manager, State};
|
use tauri::{path::BaseDirectory, Manager, State};
|
||||||
|
|
||||||
#[derive(Serialize, Type)]
|
#[derive(Serialize, Type)]
|
||||||
@@ -22,13 +21,16 @@ pub struct Relays {
|
|||||||
pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, String> {
|
pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, String> {
|
||||||
let client = &state.client;
|
let client = &state.client;
|
||||||
|
|
||||||
// Get connected relays
|
let connected_relays = client
|
||||||
let list = client.relays().await;
|
.relays()
|
||||||
let connected_relays: Vec<String> = list.into_keys().map(|url| url.to_string()).collect();
|
.await
|
||||||
|
.into_keys()
|
||||||
|
.map(|url| url.to_string())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Get NIP-65 relay list
|
|
||||||
let signer = client.signer().await.map_err(|e| e.to_string())?;
|
let signer = client.signer().await.map_err(|e| e.to_string())?;
|
||||||
let public_key = signer.public_key().await.map_err(|e| e.to_string())?;
|
let public_key = signer.public_key().await.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let filter = Filter::new()
|
let filter = Filter::new()
|
||||||
.author(public_key)
|
.author(public_key)
|
||||||
.kind(Kind::RelayList)
|
.kind(Kind::RelayList)
|
||||||
@@ -38,22 +40,35 @@ pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, String> {
|
|||||||
Ok(events) => {
|
Ok(events) => {
|
||||||
if let Some(event) = events.first() {
|
if let Some(event) = events.first() {
|
||||||
let nip65_list = nip65::extract_relay_list(event);
|
let nip65_list = nip65::extract_relay_list(event);
|
||||||
let read: Vec<String> = nip65_list
|
let read = nip65_list
|
||||||
.clone()
|
.iter()
|
||||||
.into_iter()
|
.filter_map(|(url, meta)| {
|
||||||
.filter(|i| matches!(&i.1, Some(y) if *y == RelayMetadata::Read))
|
if let Some(RelayMetadata::Read) = meta {
|
||||||
.map(|(url, _)| url.to_string())
|
Some(url.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let write: Vec<String> = nip65_list
|
let write = nip65_list
|
||||||
.clone()
|
.iter()
|
||||||
.into_iter()
|
.filter_map(|(url, meta)| {
|
||||||
.filter(|i| matches!(&i.1, Some(y) if *y == RelayMetadata::Write))
|
if let Some(RelayMetadata::Write) = meta {
|
||||||
.map(|(url, _)| url.to_string())
|
Some(url.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let both: Vec<String> = nip65_list
|
let both = nip65_list
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter(|i| i.1.is_none())
|
.filter_map(|(url, meta)| {
|
||||||
.map(|(url, _)| url.to_string())
|
if meta.is_none() {
|
||||||
|
Some(url.to_string())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Relays {
|
Ok(Relays {
|
||||||
@@ -79,31 +94,30 @@ pub async fn get_relays(state: State<'_, Nostr>) -> Result<Relays, String> {
|
|||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn connect_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, String> {
|
pub async fn connect_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||||
let client = &state.client;
|
let client = &state.client;
|
||||||
match client.add_relay(relay).await {
|
let status = client.add_relay(relay).await.map_err(|e| e.to_string())?;
|
||||||
Ok(status) => {
|
|
||||||
if status {
|
if status {
|
||||||
println!("connecting to relay: {}", relay);
|
println!("Connecting to relay: {}", relay);
|
||||||
let _ = client.connect_relay(relay).await;
|
client
|
||||||
Ok(true)
|
.connect_relay(relay)
|
||||||
} else {
|
.await
|
||||||
Ok(false)
|
.map_err(|e| e.to_string())?;
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => Err(e.to_string()),
|
|
||||||
}
|
}
|
||||||
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub async fn remove_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, String> {
|
pub async fn remove_relay(relay: &str, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||||
let client = &state.client;
|
let client = &state.client;
|
||||||
match client.remove_relay(relay).await {
|
client
|
||||||
Ok(_) => {
|
.remove_relay(relay)
|
||||||
let _ = client.disconnect_relay(relay).await;
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
client
|
||||||
|
.disconnect_relay(relay)
|
||||||
|
.await
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
|
||||||
Err(e) => Err(e.to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -115,15 +129,12 @@ pub fn get_bootstrap_relays(app: tauri::AppHandle) -> Result<Vec<String>, String
|
|||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let file = std::fs::File::open(relays_path).map_err(|e| e.to_string())?;
|
let file = std::fs::File::open(relays_path).map_err(|e| e.to_string())?;
|
||||||
let lines = io::BufReader::new(file).lines();
|
let reader = io::BufReader::new(file);
|
||||||
|
|
||||||
let mut relays = Vec::new();
|
reader
|
||||||
|
.lines()
|
||||||
for line in lines.map_while(Result::ok) {
|
.collect::<Result<Vec<String>, io::Error>>()
|
||||||
relays.push(line.to_string())
|
.map_err(|e| e.to_string())
|
||||||
}
|
|
||||||
|
|
||||||
Ok(relays)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -134,13 +145,10 @@ pub fn save_bootstrap_relays(relays: &str, app: tauri::AppHandle) -> Result<(),
|
|||||||
.resolve("resources/relays.txt", BaseDirectory::Resource)
|
.resolve("resources/relays.txt", BaseDirectory::Resource)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let mut file = fs::OpenOptions::new()
|
let mut file = OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
.open(relays_path)
|
.open(relays_path)
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
match file.write_all(relays.as_bytes()) {
|
file.write_all(relays.as_bytes()).map_err(|e| e.to_string())
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(e) => Err(e.to_string()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ use std::collections::HashSet;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use linkify::LinkFinder;
|
use linkify::LinkFinder;
|
||||||
use nostr_sdk::{Alphabet, Event, EventId, FromBech32, PublicKey, SingleLetterTag, Tag, TagKind};
|
|
||||||
use nostr_sdk::prelude::Nip19Event;
|
use nostr_sdk::prelude::Nip19Event;
|
||||||
|
use nostr_sdk::{Alphabet, Event, EventId, FromBech32, PublicKey, SingleLetterTag, Tag, TagKind};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use specta::Type;
|
use specta::Type;
|
||||||
@@ -47,7 +47,7 @@ const IMAGES: [&str; 7] = ["jpg", "jpeg", "gif", "png", "webp", "avif", "tiff"];
|
|||||||
const VIDEOS: [&str; 5] = ["mp4", "mov", "avi", "webm", "mkv"];
|
const VIDEOS: [&str; 5] = ["mp4", "mov", "avi", "webm", "mkv"];
|
||||||
|
|
||||||
pub fn get_latest_event(events: &[Event]) -> Option<&Event> {
|
pub fn get_latest_event(events: &[Event]) -> Option<&Event> {
|
||||||
events.iter().max_by_key(|event| event.created_at())
|
events.iter().next()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dedup_event(events: &[Event]) -> Vec<Event> {
|
pub fn dedup_event(events: &[Event]) -> Vec<Event> {
|
||||||
|
|||||||
Reference in New Issue
Block a user