notecrumbs

a nostr opengraph server build on nostrdb and egui
git clone git://jb55.com/notecrumbs
Log | Files | Refs | README | LICENSE

commit 83fcf805c25d6bbed6b8f321460762dac142fdb0
parent dcbe9fb822c71ec8821a41b0e8c077c0934152f2
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 17 Dec 2023 14:38:45 -0800

initial profile fetching support

Diffstat:
MCargo.toml | 2+-
Msrc/main.rs | 82+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
2 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -13,7 +13,7 @@ hyper-util = { version = "0.1", features = ["full"] } http-body-util = "0.1" log = "0.4.20" env_logger = "0.10.1" -nostrdb = { git = "https://github.com/damus-io/nostrdb-rs.git", rev = "0545571827bf64e06250f094d65775acd2a1165e" } +nostrdb = { git = "https://github.com/damus-io/nostrdb-rs.git", rev = "4f40de4b1458251ad33244fc76bcc2a03d099e49" } nostr-sdk = { git = "https://github.com/damus-io/nostr-sdk.git", rev = "fc0dc7b38f5060f171228b976b9700c0135245d3" } hex = "0.4.3" egui = "0.21.0" diff --git a/src/main.rs b/src/main.rs @@ -7,7 +7,7 @@ use hyper::server::conn::http1; use hyper::service::service_fn; use hyper::{Request, Response, StatusCode}; use hyper_util::rt::TokioIo; -use log::{error, info, warn}; +use log::{debug, info}; use tokio::net::TcpListener; use crate::error::Error; @@ -29,11 +29,18 @@ struct Context { timeout: Duration, } -fn nip19_evid(nip19: &Nip19) -> Option<EventId> { +enum Target { + Profile(XOnlyPublicKey), + Event(EventId), +} + +fn nip19_target(nip19: &Nip19) -> Option<Target> { match nip19 { - Nip19::Event(ev) => Some(ev.event_id), - Nip19::EventId(evid) => Some(*evid), - _ => None, + Nip19::Event(ev) => Some(Target::Event(ev.event_id)), + Nip19::EventId(evid) => Some(Target::Event(*evid)), + Nip19::Profile(prof) => Some(Target::Profile(prof.public_key)), + Nip19::Pubkey(pk) => Some(Target::Profile(*pk)), + Nip19::Secret(_) => None, } } @@ -153,8 +160,8 @@ async fn serve( } }; - let evid = match nip19_evid(&nip19) { - Some(evid) => evid, + let target = match nip19_target(&nip19) { + Some(target) => target, None => { return Ok(Response::builder() .status(StatusCode::NOT_FOUND) @@ -164,31 +171,47 @@ async fn serve( let content = { let mut txn = Transaction::new(&ctx.ndb)?; - ctx.ndb - .get_note_by_id(&mut txn, evid.as_bytes().try_into()?) - .map(|n| { - info!("cache hit {:?}", nip19); - n.content().to_string() - }) + match target { + Target::Profile(pk) => ctx + .ndb + .get_profile_by_pubkey(&mut txn, &pk.serialize()) + .and_then(|n| { + info!("profile cache hit {:?}", nip19); + Ok(n.record + .profile() + .ok_or(nostrdb::Error::NotFound)? + .name() + .ok_or(nostrdb::Error::NotFound)? + .to_string()) + }), + Target::Event(evid) => ctx + .ndb + .get_note_by_id(&mut txn, evid.as_bytes().try_into()?) + .map(|n| { + info!("event cache hit {:?}", nip19); + n.content().to_string() + }), + } }; let content = match content { Ok(content) => content, - Err(nostrdb::Error::NotFound) => match find_note(ctx, &nip19).await { - Ok(note) => { - ctx.ndb - .process_event(&json!(["EVENT", "s", note]).to_string()); - note.content + Err(nostrdb::Error::NotFound) => { + debug!("Finding {:?}", nip19); + match find_note(ctx, &nip19).await { + Ok(note) => { + let _ = ctx + .ndb + .process_event(&json!(["EVENT", "s", note]).to_string()); + note.content + } + Err(_err) => { + return Ok(Response::builder().status(StatusCode::NOT_FOUND).body( + Full::new(Bytes::from(format!("noteid {:?} not found\n", nip19))), + )?); + } } - Err(err) => { - return Ok(Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Full::new(Bytes::from(format!( - "noteid {} not found\n", - ::hex::encode(evid) - ))))?); - } - }, + } Err(err) => { return Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) @@ -220,9 +243,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { let listener = TcpListener::bind(addr).await?; info!("Listening on 127.0.0.1:3000"); - let cfg = Config::new(); + // Since ndk-sdk will verify for us, we don't need to do it on the db side + let mut cfg = Config::new(); + cfg.skip_validation(true); let ndb = Ndb::new(".", &cfg).expect("ndb failed to open"); - //let font_data = egui::FontData::from_static(include_bytes!("../fonts/NotoSans-Regular.ttf")); let keys = Keys::generate(); let timeout = get_env_timeout(); let ctx = Context { ndb, keys, timeout };