mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-29 16:31:18 +00:00
109 lines
3.6 KiB
Rust
109 lines
3.6 KiB
Rust
use crate::globals::GLOBALS;
|
|
use nostr_types::{Event, EventKind, PublicKey, Unixtime};
|
|
use sha2::Digest;
|
|
|
|
/// This represents a DM (direct message) channel which includes a set
|
|
/// of participants (usually just one, but can be a small group).
|
|
// internally the pubkeys are kept sorted so they can be compared
|
|
// that is why we don't expose the inner field directly.
|
|
//
|
|
// The pubkey of the gossip user is not included. If they send themselves
|
|
// a note, that channel has an empty vec.
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct DmChannel(Vec<PublicKey>);
|
|
|
|
impl DmChannel {
|
|
pub fn new(public_keys: &[PublicKey]) -> DmChannel {
|
|
let mut vec = public_keys.to_owned();
|
|
vec.sort();
|
|
vec.dedup();
|
|
DmChannel(vec)
|
|
}
|
|
|
|
pub fn keys(&self) -> &[PublicKey] {
|
|
&self.0
|
|
}
|
|
|
|
pub fn name(&self) -> String {
|
|
if self.0.is_empty() {
|
|
return match GLOBALS.identity.public_key() {
|
|
Some(pk) => crate::names::best_name_from_pubkey_lookup(&pk),
|
|
None => "[NOBODY]".to_string(),
|
|
};
|
|
}
|
|
|
|
let mut output = String::new();
|
|
let mut first = true;
|
|
for pubkey in &self.0 {
|
|
if first {
|
|
first = false;
|
|
} else {
|
|
output.push_str(", ");
|
|
}
|
|
|
|
let name = crate::names::best_name_from_pubkey_lookup(pubkey);
|
|
output.push_str(&name);
|
|
}
|
|
output
|
|
}
|
|
|
|
pub fn unique_id(&self) -> String {
|
|
let mut hasher = sha2::Sha256::new();
|
|
for pk in &self.0 {
|
|
hasher.update(pk.as_bytes());
|
|
}
|
|
hex::encode(hasher.finalize())
|
|
}
|
|
|
|
pub fn from_event(event: &Event, my_pubkey: Option<PublicKey>) -> Option<DmChannel> {
|
|
let my_pubkey = match my_pubkey {
|
|
Some(pk) => pk,
|
|
None => match GLOBALS.identity.public_key() {
|
|
Some(pk) => pk,
|
|
None => return None,
|
|
},
|
|
};
|
|
|
|
if event.kind == EventKind::EncryptedDirectMessage {
|
|
let mut people: Vec<PublicKey> = event.people().iter().map(|(pk, _, _)| *pk).collect();
|
|
people.push(event.pubkey);
|
|
people.retain(|p| *p != my_pubkey);
|
|
if people.len() > 1 {
|
|
None
|
|
} else {
|
|
Some(Self::new(&people))
|
|
}
|
|
} else if event.kind == EventKind::GiftWrap {
|
|
if let Ok(rumor) = GLOBALS.identity.unwrap_giftwrap(event) {
|
|
let rumor_event = rumor.into_event_with_bad_signature();
|
|
let mut people: Vec<PublicKey> =
|
|
rumor_event.people().iter().map(|(pk, _, _)| *pk).collect();
|
|
people.push(rumor_event.pubkey); // include author too
|
|
people.retain(|p| *p != my_pubkey);
|
|
Some(Self::new(&people))
|
|
} else {
|
|
None
|
|
}
|
|
} else if event.kind == EventKind::DmChat {
|
|
// unwrapped rumor
|
|
let mut people: Vec<PublicKey> = event.people().iter().map(|(pk, _, _)| *pk).collect();
|
|
people.push(event.pubkey); // include author too
|
|
people.retain(|p| *p != my_pubkey);
|
|
Some(Self::new(&people))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Data about a DM channel such as when the latest message occured, how many massages
|
|
/// it has, and how many are unread.
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
pub struct DmChannelData {
|
|
pub dm_channel: DmChannel,
|
|
pub latest_message_created_at: Unixtime,
|
|
pub latest_message_content: Option<String>,
|
|
pub message_count: usize,
|
|
pub unread_message_count: usize,
|
|
}
|