171 lines
4.4 KiB
Rust
171 lines
4.4 KiB
Rust
use std::cmp::Ordering;
|
|
use std::hash::{Hash, Hasher};
|
|
|
|
use gpui::SharedString;
|
|
use nostr_sdk::prelude::*;
|
|
use state::Announcement;
|
|
|
|
/// Person
|
|
#[derive(Debug, Clone)]
|
|
pub struct Person {
|
|
/// Public Key
|
|
public_key: PublicKey,
|
|
/// Metadata (profile)
|
|
metadata: Metadata,
|
|
/// Custom emoji (NIP-30) from the person's emoji list
|
|
emojis: Vec<(String, Url)>,
|
|
/// Dekey (NIP-4e) announcement
|
|
announcement: Option<Announcement>,
|
|
/// Messaging relays
|
|
messaging_relays: Vec<RelayUrl>,
|
|
}
|
|
|
|
impl PartialEq for Person {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.public_key == other.public_key
|
|
}
|
|
}
|
|
|
|
impl Eq for Person {}
|
|
|
|
impl PartialOrd for Person {
|
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl Ord for Person {
|
|
fn cmp(&self, other: &Self) -> Ordering {
|
|
self.name().cmp(&other.name())
|
|
}
|
|
}
|
|
|
|
impl Hash for Person {
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
self.public_key.hash(state)
|
|
}
|
|
}
|
|
|
|
impl Person {
|
|
pub fn new(public_key: PublicKey, metadata: Metadata) -> Self {
|
|
Self {
|
|
public_key,
|
|
metadata,
|
|
emojis: vec![],
|
|
announcement: None,
|
|
messaging_relays: vec![],
|
|
}
|
|
}
|
|
|
|
/// Get profile public key
|
|
pub fn public_key(&self) -> PublicKey {
|
|
self.public_key
|
|
}
|
|
|
|
/// Get profile metadata
|
|
pub fn metadata(&self) -> Metadata {
|
|
self.metadata.clone()
|
|
}
|
|
|
|
/// Custom emoji (NIP-30) as (shortcode, image url) pairs
|
|
pub fn emojis(&self) -> &[(String, Url)] {
|
|
&self.emojis
|
|
}
|
|
|
|
/// Set custom emoji from the person's emoji list
|
|
pub(crate) fn set_emojis(&mut self, emojis: Vec<(String, Url)>) {
|
|
self.emojis = emojis;
|
|
}
|
|
|
|
/// An `emoji` tag for every custom emoji referenced as `:shortcode:` in `content`
|
|
pub fn emoji_tags(&self, content: &str) -> Vec<Tag> {
|
|
let mut tags = Vec::new();
|
|
|
|
for (shortcode, url) in &self.emojis {
|
|
let pattern = format!(":{shortcode}:");
|
|
if content.contains(&pattern) {
|
|
tags.push(Tag::custom("emoji", [shortcode.clone(), url.to_string()]));
|
|
}
|
|
}
|
|
|
|
tags
|
|
}
|
|
|
|
/// Get profile encryption keys announcement
|
|
pub fn announcement(&self) -> Option<Announcement> {
|
|
self.announcement.clone()
|
|
}
|
|
|
|
/// Get profile messaging relays
|
|
pub fn messaging_relays(&self) -> &Vec<RelayUrl> {
|
|
&self.messaging_relays
|
|
}
|
|
|
|
/// Get relay hint for messaging relay list
|
|
pub fn messaging_relay_hint(&self) -> Option<RelayUrl> {
|
|
self.messaging_relays.first().cloned()
|
|
}
|
|
|
|
/// Get profile picture, if the profile has one
|
|
pub fn avatar(&self) -> Option<SharedString> {
|
|
self.metadata()
|
|
.picture
|
|
.as_ref()
|
|
.filter(|picture| !picture.is_empty())
|
|
.map(SharedString::from)
|
|
}
|
|
|
|
/// A stable seed for this profile's generated avatar
|
|
pub fn avatar_seed(&self) -> String {
|
|
self.public_key().to_hex()
|
|
}
|
|
|
|
/// Get profile name
|
|
pub fn name(&self) -> SharedString {
|
|
if let Some(display_name) = self.metadata().display_name.as_ref()
|
|
&& !display_name.is_empty()
|
|
{
|
|
return SharedString::from(display_name.trim());
|
|
}
|
|
|
|
if let Some(name) = self.metadata().name.as_ref()
|
|
&& !name.is_empty()
|
|
{
|
|
return SharedString::from(name.trim());
|
|
}
|
|
|
|
SharedString::from(shorten_pubkey(self.public_key(), 4))
|
|
}
|
|
|
|
/// Set profile metadata
|
|
pub(crate) fn set_metadata(&mut self, metadata: Metadata) {
|
|
self.metadata = metadata;
|
|
}
|
|
|
|
/// Set profile encryption keys announcement
|
|
pub(crate) fn set_announcement(&mut self, announcement: Announcement) {
|
|
self.announcement = Some(announcement);
|
|
}
|
|
|
|
/// Set profile messaging relays
|
|
pub(crate) fn set_messaging_relays<I>(&mut self, relays: I)
|
|
where
|
|
I: IntoIterator<Item = RelayUrl>,
|
|
{
|
|
self.messaging_relays = relays.into_iter().collect();
|
|
}
|
|
}
|
|
|
|
/// Shorten a [`PublicKey`] to a string with the first and last `len` characters
|
|
///
|
|
/// Ex. `00000000:00000002`
|
|
pub fn shorten_pubkey(public_key: PublicKey, len: usize) -> String {
|
|
let Ok(pubkey) = public_key.to_bech32();
|
|
|
|
format!(
|
|
"{}...{}",
|
|
&pubkey[0..(len + 1)],
|
|
&pubkey[pubkey.len() - len..]
|
|
)
|
|
}
|