use super::route_prelude::*;
use std::collections::HashSet;
#[derive(Template, Clone)]
#[template(path = "nostriches_list.gmi", escape = "txt")]
struct UserListTemplate {
meta_events: Vec<Event>,
}
#[derive(Template, Clone)]
#[template(path = "nostriches_search.gmi", escape = "txt")]
struct UserSearchTemplate {
meta_events: Events,
}
pub async fn nostriches_list_all(
_ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let meta_filter = Filter::new().kind(Kind::Metadata);
let Ok(meta_events) = user.client.database().query(meta_filter).await
else {
return Response::temporary_failure("db");
};
Response::success(WindTemplate::render(UserListTemplate {
meta_events: meta_events.into_iter().collect(),
}))
}
pub async fn nostriches_list_recent(
_ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let recent_notes_filter = Filter::new()
.kind(Kind::TextNote)
.since(Timestamp::now() - duration_str::parse("1w").unwrap());
let meta_filter = Filter::new().kind(Kind::Metadata);
let Ok(events) = user.fetch_quick(recent_notes_filter).await else {
return Response::temporary_failure("ev");
};
let recent_pubkeys: HashSet<PublicKey> =
events.into_iter().map(|event| event.pubkey).collect();
let Ok(metas) = user.client.database().query(meta_filter).await else {
return Response::temporary_failure("db");
};
let meta_events: Vec<Event> = metas
.into_iter()
.filter(|ev| recent_pubkeys.contains(&ev.pubkey))
.collect();
Response::success(WindTemplate::render(UserListTemplate { meta_events }))
}
pub async fn nostriches_search(
ctx: RouteContext,
user: &'static mut CaracalUser,
) -> Response {
let Some(input) = ctx.url.query() else {
return Response::input(t!("input_nostr_name"));
};
let Ok(input) = urlencoding::decode(input) else {
return Response::input(t!("input_nostr_name"));
};
let meta_filter = Filter::new().kind(Kind::Metadata);
let Ok(all_meta) = user.client.database().query(meta_filter).await else {
return Response::temporary_failure("db");
};
let events = all_meta
.iter()
.filter_map(|ev| {
if let Ok(meta) = Metadata::try_from(ev) {
Some((ev, meta))
} else {
None
}
})
.filter_map(|(ev, meta)| {
if let Some(name) = meta.name
&& name.contains(&input.to_string())
{
Some(ev.clone())
} else {
None
}
});
Response::success(WindTemplate::render(UserSearchTemplate {
meta_events: Events::from_iter(events),
}))
}