feat: Add gossip model (#232)

* feat: enable gossip

* chore: remove deprecated functions

* chore: use upstream rust nostr

* fix
This commit is contained in:
雨宮蓮
2024-09-11 11:10:11 +07:00
committed by GitHub
parent e5e290c0c3
commit ac7ce726c5
9 changed files with 144 additions and 177 deletions

View File

@@ -127,7 +127,7 @@ pub async fn connect_account(uri: String, state: State<'_, Nostr>) -> Result<Str
Ok(bunker_uri) => {
// Local user
let app_keys = Keys::generate();
let app_secret = app_keys.secret_key().to_string();
let app_secret = app_keys.secret_key().to_secret_hex();
// Get remote user
let remote_user = bunker_uri.signer_public_key().unwrap();

View File

@@ -247,7 +247,7 @@ pub async fn get_events_from_contacts(
.until(as_of)
.authors(authors);
match client.database().query(vec![filter], Order::Desc).await {
match client.database().query(vec![filter]).await {
Ok(events) => {
let fils = filter_converstation(events);
let futures = fils.iter().map(|ev| async move {
@@ -449,7 +449,9 @@ pub async fn publish(
// Create unsigned event
let unsigned_event = match difficulty {
Some(num) => EventBuilder::text_note(content, tags).to_unsigned_pow_event(public_key, num),
Some(num) => EventBuilder::text_note(content, tags)
.pow(num)
.to_unsigned_event(public_key),
None => EventBuilder::text_note(content, tags).to_unsigned_event(public_key),
};
@@ -479,14 +481,11 @@ pub async fn reply(
let reply_id = EventId::parse(&to).map_err(|err| err.to_string())?;
match database
.query(vec![Filter::new().id(reply_id)], Order::Desc)
.await
{
match database.query(vec![Filter::new().id(reply_id)]).await {
Ok(events) => {
if let Some(event) = events.first() {
let relay_hint = if let Some(relays) = database
.event_seen_on_relays(event.id)
.event_seen_on_relays(&event.id)
.await
.map_err(|err| err.to_string())?
{
@@ -515,13 +514,10 @@ pub async fn reply(
Err(_) => return Err("Event is not valid.".into()),
};
if let Ok(events) = database
.query(vec![Filter::new().id(root_id)], Order::Desc)
.await
{
if let Ok(events) = database.query(vec![Filter::new().id(root_id)]).await {
if let Some(event) = events.first() {
let relay_hint = if let Some(relays) = database
.event_seen_on_relays(event.id)
.event_seen_on_relays(&event.id)
.await
.map_err(|err| err.to_string())?
{
@@ -579,7 +575,7 @@ pub async fn event_to_bech32(id: String, state: State<'_, Nostr>) -> Result<Stri
let seens = client
.database()
.event_seen_on_relays(event_id)
.event_seen_on_relays(&event_id)
.await
.map_err(|err| err.to_string())?;

View File

@@ -382,7 +382,7 @@ pub async fn copy_friend(npub: &str, state: State<'_, Nostr>) -> Result<bool, St
.await
{
for event in contact_list_events.into_iter() {
for tag in event.into_iter_tags() {
for tag in event.tags.into_iter() {
if let Some(TagStandard::PublicKey {
public_key,
relay_url,
@@ -405,74 +405,6 @@ pub async fn copy_friend(npub: &str, state: State<'_, Nostr>) -> Result<bool, St
}
}
pub async fn get_following(
state: State<'_, Nostr>,
public_key: &str,
) -> Result<Vec<String>, String> {
let client = &state.client;
let public_key = PublicKey::parse(public_key).map_err(|e| e.to_string())?;
let filter = Filter::new().kind(Kind::ContactList).author(public_key);
let events = match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => events,
Err(err) => return Err(err.to_string()),
};
let mut ret: Vec<String> = vec![];
if let Some(latest_event) = events.iter().max_by_key(|event| event.created_at()) {
ret.extend(latest_event.tags().iter().filter_map(|tag| {
if let Some(TagStandard::PublicKey {
uppercase: false, ..
}) = <nostr_sdk::Tag as Clone>::clone(tag).to_standardized()
{
tag.content().map(String::from)
} else {
None
}
}));
}
Ok(ret)
}
pub async fn get_followers(
state: State<'_, Nostr>,
public_key: &str,
) -> Result<Vec<String>, String> {
let client = &state.client;
let public_key = PublicKey::parse(public_key).map_err(|e| e.to_string())?;
let filter = Filter::new().kind(Kind::ContactList).custom_tag(
SingleLetterTag::lowercase(Alphabet::P),
vec![public_key.to_hex()],
);
let events = match client
.get_events_of(
vec![filter],
EventSource::both(Some(Duration::from_secs(5))),
)
.await
{
Ok(events) => events,
Err(err) => return Err(err.to_string()),
};
let ret: Vec<String> = events
.into_iter()
.map(|event| event.author().to_hex())
.collect();
Ok(ret)
// TODO: get more than 500 events
}
#[tauri::command]
#[specta::specta]
pub async fn get_notifications(state: State<'_, Nostr>) -> Result<Vec<String>, String> {
@@ -491,11 +423,7 @@ pub async fn get_notifications(state: State<'_, Nostr>) -> Result<Vec<String>, S
])
.limit(200);
match client
.database()
.query(vec![filter], Order::default())
.await
{
match client.database().query(vec![filter]).await {
Ok(events) => Ok(events.into_iter().map(|ev| ev.as_json()).collect()),
Err(err) => Err(err.to_string()),
}

View File

@@ -288,7 +288,7 @@ pub async fn init_nip65(client: &Client) {
Some(_) => RelayOptions::new().write(true).read(false),
None => RelayOptions::default(),
};
if let Err(e) = client.add_relay_with_opts(&url.to_string(), opts).await {
if let Err(e) = client.pool().add_relay(&url.to_string(), opts).await {
eprintln!("Failed to add relay {}: {:?}", url, e);
}
if let Err(e) = client.connect_relay(url.to_string()).await {

View File

@@ -193,16 +193,16 @@ fn main() {
let dir = handle
.path()
.app_config_dir()
.expect("App config directory not found.");
let _ = fs::create_dir_all(dir.clone());
.expect("Error: app config directory not found.");
let _ = fs::create_dir_all(&dir);
// Setup database
let database = SQLiteDatabase::open(dir.join("nostr.db"))
.await
.expect("Database error.");
let database = NostrLMDB::open(dir.join("nostr-lmdb"))
.expect("Error: cannot create database.");
// Config
let opts = Options::new()
.gossip(true)
.max_avg_latency(Duration::from_millis(500))
.automatic_authentication(true)
.connection_timeout(Some(Duration::from_secs(5)))
@@ -232,7 +232,7 @@ fn main() {
} else {
RelayOptions::new().write(true).read(false)
};
let _ = client.add_relay_with_opts(relay, opts).await;
let _ = client.pool().add_relay(relay, opts).await;
}
Err(_) => {
let _ = client.add_relay(relay).await;
@@ -242,6 +242,14 @@ fn main() {
}
}
if let Err(e) = client.add_discovery_relay("wss://purplepag.es/").await {
println!("Add discovery relay failed: {}", e)
}
if let Err(e) = client.add_discovery_relay("wss://directory.yabu.me/").await {
println!("Add discovery relay failed: {}", e)
}
// Connect
client.connect().await;
@@ -327,7 +335,10 @@ fn main() {
// Send native notification
if allow_notification {
let author = client
.metadata(event.pubkey)
.fetch_metadata(
event.pubkey,
Some(Duration::from_secs(5)),
)
.await
.unwrap_or_else(|_| Metadata::new());
@@ -393,7 +404,7 @@ fn prevent_default() -> tauri::plugin::TauriPlugin<tauri::Wry> {
}
fn send_notification(event: &Event, author: Metadata, handle: &tauri::AppHandle) {
match event.kind() {
match event.kind {
Kind::TextNote => {
if let Err(e) = handle
.notification()