use emojis_rs::EMOJI_MEGAPHONE;
use http::Uri;
use nostr_sdk::prelude::*;
use std::collections::HashSet;
use std::str::FromStr;
use std::time::Duration;
use url::Url;
pub async fn get_user_metadata(
client: &Client,
pubkey: PublicKey,
) -> Option<Metadata> {
let filter_meta = Filter::new().author(pubkey).kind(Kind::Metadata);
match client.database().query(filter_meta).await {
Ok(mevents) => {
if !mevents.is_empty() {
match Metadata::from_json(&mevents.first().unwrap().content) {
Ok(usermeta) => return Some(usermeta.clone()),
Err(_err) => return None,
}
}
}
Err(_err) => {
return None;
}
}
None
}
pub async fn fetch_user_metadata(
client: &Client,
pubk: PublicKey,
) -> Option<Metadata> {
if let Ok(Some(metadata)) =
client.fetch_metadata(pubk, Duration::from_secs(5)).await
{
Some(metadata)
} else {
None
}
}
pub fn notes_filter() -> Filter {
Filter::new()
.kind(Kind::TextNote)
.kind(Kind::LongFormTextNote)
}
pub fn parse_note_urls(event: &Event) -> Vec<(Uri, Uri)> {
let mut vec: Vec<(Uri, Uri)> = Vec::new();
for elem in event.content.split_whitespace() {
if let Ok(url) = Url::parse(elem) {
let scheme = url.scheme();
let Ok(orig_uri) = Uri::from_str(url.as_str()) else {
continue;
};
match scheme {
"nostr" => {
let path = url.path();
if path.is_empty() {
continue;
}
let uri: Uri = if path.starts_with("nevent") {
Uri::builder()
.path_and_query(format!("/note/{}/thread", path))
.build()
.unwrap()
} else {
Uri::from_str(url.as_str()).unwrap()
};
vec.push((orig_uri, uri));
}
_ => {
vec.push((orig_uri.clone(), orig_uri.clone()));
continue;
}
}
}
}
vec
}
pub fn parse_note_ids(event: &Event) -> (Vec<EventId>, Vec<PublicKey>) {
let mut vec_evid: Vec<EventId> = Vec::new();
let mut vec_pk: Vec<PublicKey> = Vec::new();
for elem in event.content.split_whitespace() {
let Ok(url) = Url::parse(elem) else { continue };
let scheme = url.scheme();
match scheme {
"nostr" => {
let urls = url.as_str();
let path = url.path();
if path.starts_with("nevent") {
let Ok(res) = Nip19Event::from_nostr_uri(urls) else {
continue;
};
vec_evid.push(res.event_id);
}
if path.starts_with("npub") {
let Ok(pk) = PublicKey::parse(path) else {
continue;
};
vec_pk.push(pk);
}
}
_ => {
continue;
}
}
}
(vec_evid, vec_pk)
}
pub fn reactions_summary(reaction_events: &Events) -> String {
let mut summary = String::new();
let rlist: HashSet<_> =
reaction_events.iter().map(|e| e.content.clone()).collect();
for emoji in rlist {
let count = reaction_events
.iter()
.filter(|e| e.content == emoji)
.count();
let emojis = if emoji == "+" {
"\u{1F44D}"
} else if let Some(e) = emojis::get_by_shortcode(&emoji) {
e.as_str()
} else {
if emoji.starts_with(":") { "" } else { &emoji }
};
if count == 1 {
summary.push_str(emojis);
} else {
if count > 16 {
summary.push_str(&format!("{} {} ", count, emojis));
} else {
for _ in 0..count {
summary.push_str(&format!("{} ", emojis));
}
}
}
}
summary
}
pub fn reposts_counter(reposts_events: &Events) -> String {
let mut summary = String::new();
let count = reposts_events.iter().count();
if count == 0 {
return summary;
} else if count > 16 {
summary.push_str(&format!(
"{} {} ",
reposts_events.iter().count(),
EMOJI_MEGAPHONE
));
} else {
for _ in 0..count {
summary.push_str(EMOJI_MEGAPHONE);
}
}
summary
}