use crate::Url;
use crate::nips::nip96;
use crate::relays::blossom_servers;
use gnostr_types::{ContentSegment, ShatteredContent};
use nostr::Keys;
use nostr_blossom::{bud02::BlobDescriptor, client::BlossomClient};
use nostr_sdk::prelude::*;
use openssl::hash::MessageDigest;
use openssl::x509::X509;
use rand::seq::SliceRandom;
use std::sync::Arc;
use windmark_titanesque::context::{RouteContext, TitanResource};
pub fn decode_query(ctx: &RouteContext) -> Option<String> {
ctx.url
.query()
.and_then(|url| urlencoding::decode(url).ok().map(|s| s.into()))
}
pub fn fingerprint(cert: &X509) -> Option<String> {
use std::fmt::Write;
match cert.digest(MessageDigest::sha256()) {
Ok(dbytes) => {
let digest: String =
dbytes.iter().fold(String::new(), |mut out, x| {
let _ = write!(out, "{:02x}", x);
out
});
Some(digest)
}
Err(_error) => None,
}
}
pub async fn titan96(
titan_rsc: Option<TitanResource>,
keys: &Keys,
) -> Option<Url> {
if let Some(titan) = titan_rsc {
(nip96::upload_file_data(None, titan.content, titan.mime, keys).await)
.ok()
} else {
None
}
}
pub async fn titan_to_blossom(
titan: TitanResource,
signer: Arc<dyn NostrSigner>,
) -> Result<BlobDescriptor, nostr_blossom::error::Error> {
let mime = tree_magic_mini::from_u8(&titan.content);
let servers = blossom_servers();
let server_url = match servers.choose(&mut rand::thread_rng()) {
Some(u) => u.to_owned(),
None => Url::parse("https://blossom.nostr.build").unwrap(),
};
let blossom = BlossomClient::new(server_url);
blossom
.upload_blob(titan.content, Some(mime.into()), None, Some(&signer))
.await
}
pub fn extract_first_words(event: &Event) -> Option<String> {
let shattered_content = ShatteredContent::new(event.content.clone());
let text = shattered_content
.segments
.iter()
.filter_map(|seg| {
if let ContentSegment::Plain(span) = seg
&& let Some(slice) = shattered_content.slice(span)
&& !slice.is_empty()
{
Some(
slice
.lines()
.filter(|s| !s.is_empty())
.collect::<Vec<_>>()
.join("\n"),
)
} else {
None
}
})
.collect::<Vec<_>>()
.join("\n");
text.lines().map(str::to_string).next()
}