From 08f6bd1224f05c63774d217f9c6fcedd745a5dd2 Mon Sep 17 00:00:00 2001 From: Mike Dilger Date: Thu, 22 Dec 2022 08:55:38 +1300 Subject: [PATCH] Refresh metadata on start (in globals and database) --- src/db/event.rs | 32 ++++++++++++++++++++++++++++++++ src/db/person.rs | 26 +++++++++++++++++++++++++- src/overlord/mod.rs | 37 +++++++++++++++++++++++++++++++++---- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/src/db/event.rs b/src/db/event.rs index 54bcee0e..70cfbb4b 100644 --- a/src/db/event.rs +++ b/src/db/event.rs @@ -52,6 +52,38 @@ impl DbEvent { output } + pub async fn fetch_latest_metadata() -> Result, Error> { + // THIS SQL MIGHT WORK, NEEDS REVIEW + let sql = "SELECT id, LAST_VALUE(raw) OVER (ORDER BY created_at desc) as last_raw, pubkey, LAST_VALUE(created_at) OVER (ORDER BY created_at desc), kind, content, ots FROM event WHERE kind=0".to_owned(); + + let output: Result, Error> = spawn_blocking(move || { + let maybe_db = GLOBALS.db.blocking_lock(); + let db = maybe_db.as_ref().unwrap(); + + let mut stmt = db.prepare(&sql)?; + let rows = stmt.query_map([], |row| { + Ok(DbEvent { + id: IdHex(row.get(0)?), + raw: row.get(1)?, + pubkey: PublicKeyHex(row.get(2)?), + created_at: row.get(3)?, + kind: row.get(4)?, + content: row.get(5)?, + ots: row.get(6)?, + }) + })?; + + let mut output: Vec = Vec::new(); + for row in rows { + output.push(row?); + } + Ok(output) + }) + .await?; + + output + } + pub async fn insert(event: DbEvent) -> Result<(), Error> { let sql = "INSERT OR IGNORE INTO event (id, raw, pubkey, created_at, kind, content, ots) \ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)"; diff --git a/src/db/person.rs b/src/db/person.rs index 8e89e423..af3fdecb 100644 --- a/src/db/person.rs +++ b/src/db/person.rs @@ -1,6 +1,6 @@ use crate::error::Error; use crate::globals::GLOBALS; -use nostr_proto::PublicKeyHex; +use nostr_proto::{Metadata, PublicKeyHex, Unixtime}; use serde::{Deserialize, Serialize}; use tokio::task::spawn_blocking; @@ -135,6 +135,30 @@ impl DbPerson { Ok(()) } + pub async fn update_metadata(pubkey: PublicKeyHex, metadata: Metadata, created_at: Unixtime) -> Result<(), Error> { + let sql = + "UPDATE person SET name=?, about=?, picture=?, dns_id=?, metadata_at=? WHERE pubkey=?"; + + spawn_blocking(move || { + let maybe_db = GLOBALS.db.blocking_lock(); + let db = maybe_db.as_ref().unwrap(); + + let mut stmt = db.prepare(sql)?; + stmt.execute(( + &metadata.name, + &metadata.about, + &metadata.picture, + &metadata.nip05, + &created_at.0, + &pubkey.0, + ))?; + Ok::<(), Error>(()) + }) + .await??; + + Ok(()) + } + #[allow(dead_code)] pub async fn delete(criteria: &str) -> Result<(), Error> { let sql = format!("DELETE FROM person WHERE {}", criteria); diff --git a/src/overlord/mod.rs b/src/overlord/mod.rs index bc8e8f7d..77f9fc36 100644 --- a/src/overlord/mod.rs +++ b/src/overlord/mod.rs @@ -99,6 +99,37 @@ impl Overlord { } } + // Load latest metadata per person and update their metadata + { + let db_events = DbEvent::fetch_latest_metadata().await?; + for dbevent in db_events.iter() { + let e: Event = match serde_json::from_str(&dbevent.raw) { + Ok(e) => e, + Err(_) => { + error!("Bad raw event: id={}, raw={}", dbevent.id, dbevent.raw); + continue; + } + }; + let metadata: Metadata = match serde_json::from_str(&dbevent.content) { + Ok(e) => e, + Err(_) => { + error!("Bad metadata: id={}, content={}", dbevent.id, dbevent.content); + continue; + } + }; + + // Update in globals + crate::globals::update_person_from_event_metadata( + e.pubkey, e.created_at, metadata.clone() + ).await; + + // Update in database + DbPerson::update_metadata(PublicKeyHex(e.pubkey.as_hex_string()), + metadata, + e.created_at).await?; + } + } + // Load feed-related events from database and process (TextNote, EventDeletion, Reaction) { let now = Unixtime::now().unwrap(); @@ -230,8 +261,6 @@ impl Overlord { "new_event" => { let event: Event = serde_json::from_str(&bus_message.json_payload)?; - debug!("new event arrived: {}...", event.id.as_hex_string()); - // If feed-related, send to the feed event processor if event.kind == EventKind::TextNote || event.kind == EventKind::EncryptedDirectMessage @@ -240,10 +269,10 @@ impl Overlord { { crate::globals::add_event(&event).await?; - debug!("Received new feed event"); + debug!("new feed event arrived: {}...", event.id.as_hex_string()); } else { // Not Feed Related: Metadata, RecommendRelay, ContactList - debug!("Received new non-feed event"); + debug!("new non-feed event arrived: {}...", event.id.as_hex_string()); if event.kind == EventKind::Metadata { let metadata: Metadata = serde_json::from_str(&event.content)?;