update nostr sdk

This commit is contained in:
2026-05-17 14:38:07 +07:00
parent 6d60726f27
commit d2a17e54c4
19 changed files with 630 additions and 612 deletions

View File

@@ -373,10 +373,7 @@ impl ChatRegistry {
}
/// Get all messages for the provided signer
fn get_messages<T>(&mut self, signer: T, cx: &mut Context<Self>)
where
T: NostrSigner + 'static,
{
fn get_messages(&mut self, signer: Arc<dyn AsyncNostrSigner>, cx: &mut Context<Self>) {
let task = self.subscribe_gift_wrap_events(signer, cx);
self.tasks.push(cx.spawn(async move |this, cx| {
@@ -421,7 +418,7 @@ impl ChatRegistry {
while let Some((_url, res)) = stream.next().await {
if let Ok(event) = res {
let urls: Vec<RelayUrl> = nip17::extract_owned_relay_list(event).collect();
let urls: Vec<RelayUrl> = nip17::extract_relay_list(&event).collect();
return Ok(urls);
}
}
@@ -431,10 +428,11 @@ impl ChatRegistry {
}
/// Continuously get gift wrap events for the signer
fn subscribe_gift_wrap_events<T>(&self, signer: T, cx: &App) -> Task<Result<(), Error>>
where
T: NostrSigner + 'static,
{
fn subscribe_gift_wrap_events(
&self,
signer: Arc<dyn AsyncNostrSigner>,
cx: &App,
) -> Task<Result<(), Error>> {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let urls = self.get_messaging_relays(cx);
@@ -579,10 +577,9 @@ impl ChatRegistry {
I: Into<Room> + 'static,
{
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
cx.spawn(async move |this, cx| {
let signer = client.signer()?;
let public_key = signer.get_public_key().await.ok()?;
let room: Room = room.into().organize(&public_key);
@@ -712,9 +709,9 @@ impl ChatRegistry {
fn get_rooms_from_database(&self, cx: &App) -> Task<Result<HashSet<Room>, Error>> {
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
cx.background_spawn(async move {
let signer = client.signer().context("Signer not found")?;
let public_key = signer.get_public_key().await?;
// Get contacts
@@ -871,10 +868,10 @@ async fn try_unwrap(signer: &Arc<CoopSigner>, gift_wrap: &Event) -> Result<Unwra
}
/// Attempts to unwrap a gift wrap event with a given signer.
async fn try_unwrap_with<T>(gift_wrap: &Event, signer: &T) -> Result<UnwrappedGift, Error>
where
T: NostrSigner + 'static,
{
async fn try_unwrap_with(
gift_wrap: &Event,
signer: &Arc<dyn AsyncNostrSigner>,
) -> Result<UnwrappedGift, Error> {
// Get the sealed event
let seal = signer
.nip44_decrypt(&gift_wrap.pubkey, &gift_wrap.content)
@@ -906,26 +903,17 @@ async fn set_rumor(client: &Client, id: EventId, rumor: &UnsignedEvent) -> Resul
tags.push(Tag::identifier(id));
// Add a reference to the rumor's author
tags.push(Tag::custom(
TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::A)),
[author],
));
tags.push(Tag::custom("a", [author]));
// Add a conversation id
tags.push(Tag::custom(
TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::C)),
[conversation.to_string()],
));
tags.push(Tag::custom("c", [conversation.to_string()]));
// Add a reference to the rumor's id
tags.push(Tag::event(rumor_id));
// Add references to the rumor's participants
for receiver in rumor.tags.public_keys().copied() {
tags.push(Tag::custom(
TagKind::SingleLetter(SingleLetterTag::lowercase(Alphabet::P)),
[receiver],
));
for receiver in rumor.tags.public_keys() {
tags.push(Tag::public_key(receiver));
}
// Convert rumor to json
@@ -934,7 +922,7 @@ async fn set_rumor(client: &Client, id: EventId, rumor: &UnsignedEvent) -> Resul
// Construct the event
let event = EventBuilder::new(Kind::ApplicationSpecificData, content)
.tags(tags)
.sign(&Keys::generate())
.sign_async(&Keys::generate())
.await?;
// Save the event to the database
@@ -960,7 +948,7 @@ async fn get_rumor(client: &Client, gift_wrap: EventId) -> Result<UnsignedEvent,
/// Get the conversation ID for a given rumor (message).
fn conversation_id(rumor: &UnsignedEvent) -> u64 {
let mut hasher = DefaultHasher::new();
let mut pubkeys: Vec<PublicKey> = rumor.tags.public_keys().copied().collect();
let mut pubkeys: Vec<PublicKey> = rumor.tags.public_keys().collect();
pubkeys.push(rumor.pubkey);
pubkeys.sort();
pubkeys.dedup();

View File

@@ -242,13 +242,13 @@ fn extract_mentions(content: &str) -> Vec<Mention> {
fn extract_reply_ids(inner: &Tags) -> Vec<EventId> {
let mut replies_to = vec![];
for tag in inner.filter(TagKind::e()) {
for tag in inner.iter().filter(|tag| tag.kind() == "e") {
if let Some(id) = tag.content().and_then(|id| EventId::parse(id).ok()) {
replies_to.push(id);
}
}
for tag in inner.filter(TagKind::q()) {
for tag in inner.iter().filter(|tag| tag.kind() == "q") {
if let Some(id) = tag.content().and_then(|id| EventId::parse(id).ok()) {
replies_to.push(id);
}

View File

@@ -1,15 +1,16 @@
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
use std::time::Duration;
use anyhow::{Error, anyhow};
use anyhow::Error;
use common::EventExt;
use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
use itertools::Itertools;
use nostr_sdk::prelude::*;
use person::{Person, PersonRegistry};
use settings::{RoomConfig, SignerKind};
use state::{NostrRegistry, TIMEOUT};
use state::{CoopSigner, NostrRegistry, TIMEOUT};
use crate::NewMessage;
@@ -171,7 +172,8 @@ impl From<&UnsignedEvent> for Room {
let members = val.extract_public_keys();
let subject = val
.tags
.find(TagKind::Subject)
.iter()
.find(|tag| tag.kind() == "subject")
.and_then(|tag| tag.content().map(|s| s.to_owned().into()));
Room {
@@ -440,9 +442,7 @@ impl Room {
// Add subject tag if present
if let Some(value) = self.subject.as_ref() {
tags.push(Tag::from_standardized_without_cell(TagStandard::Subject(
value.to_string(),
)));
tags.push(Tag::custom("subject", vec![value.to_string()]));
}
// Add all reply tags
@@ -452,14 +452,13 @@ impl Room {
// Add all receiver tags
for member in members.into_iter() {
tags.push(Tag::from_standardized_without_cell(
TagStandard::PublicKey {
tags.push(
Nip01Tag::PublicKey {
public_key: member.public_key(),
relay_url: member.messaging_relay_hint(),
alias: None,
uppercase: false,
},
));
relay_hint: member.messaging_relay_hint(),
}
.to_tag(),
);
}
// Construct a direct message rumor event
@@ -474,9 +473,9 @@ impl Room {
/// Send rumor event to all members's messaging relays
pub fn send(&self, rumor: UnsignedEvent, cx: &App) -> Option<Task<Vec<SendReport>>> {
let config = self.config.clone();
let persons = PersonRegistry::global(cx);
let nostr = NostrRegistry::global(cx);
let client = nostr.read(cx).client();
let signer = nostr.read(cx).signer();
@@ -484,6 +483,8 @@ impl Room {
let public_key = nostr.read(cx).signer().public_key()?;
let sender = persons.read(cx).get(&public_key, cx);
let config = self.config.clone();
// Get all members (excluding sender)
let members: Vec<Person> = self
.members
@@ -492,12 +493,10 @@ impl Room {
.map(|member| persons.read(cx).get(member, cx))
.collect();
Some(cx.background_spawn(async move {
Some(cx.spawn(async move |_cx| {
let signer_kind = config.signer_kind();
let backup = config.backup();
let user_signer = signer.get().await;
let encryption_signer = signer.get_encryption_signer().await;
let has_encryption_signer = signer.has_encryption_signer().await;
let mut sents = 0;
let mut reports = Vec::new();
@@ -516,33 +515,21 @@ impl Room {
}
// Sender didn't set up a decoupled encryption key
if encryption_signer.is_none() {
if !has_encryption_signer {
reports.push(SendReport::new(sender.public_key()).error(USER_NO_DEKEY));
continue;
}
}
// Determine the signer to use
let signer = match signer_kind {
SignerKind::Auto => {
if announcement.is_some()
&& let Some(encryption_signer) = encryption_signer.clone()
{
// Safe to unwrap due to earlier checks
encryption_signer
} else {
user_signer.clone()
}
}
SignerKind::Encryption => {
// Safe to unwrap due to earlier checks
encryption_signer.as_ref().unwrap().clone()
}
SignerKind::User => user_signer.clone(),
let use_encryption = match signer_kind {
SignerKind::Auto => announcement.is_some() && has_encryption_signer,
SignerKind::Encryption => true,
SignerKind::User => false,
};
// Send the gift wrap event and collect the report
match send_gift_wrap(&client, &signer, &member, &rumor, signer_kind).await {
match send_gift_wrap(&client, &signer, &member, &rumor, use_encryption).await {
Ok(report) => {
reports.push(report);
sents += 1;
@@ -559,25 +546,13 @@ impl Room {
let public_key = sender.public_key();
// Determine the signer to use
let signer = match signer_kind {
SignerKind::Auto => {
if sender.announcement().is_some()
&& let Some(encryption_signer) = encryption_signer.clone()
{
// Safe to unwrap due to earlier checks
encryption_signer
} else {
user_signer.clone()
}
}
SignerKind::Encryption => {
// Safe to unwrap due to earlier checks
encryption_signer.as_ref().unwrap().clone()
}
SignerKind::User => user_signer.clone(),
let use_encryption = match signer_kind {
SignerKind::Auto => sender.announcement().is_some() && has_encryption_signer,
SignerKind::Encryption => true,
SignerKind::User => false,
};
match send_gift_wrap(&client, &signer, &sender, &rumor, signer_kind).await {
match send_gift_wrap(&client, &signer, &sender, &rumor, use_encryption).await {
Ok(report) => reports.push(report),
Err(error) => {
let report = SendReport::new(public_key).error(error.to_string());
@@ -592,22 +567,19 @@ impl Room {
}
// Helper function to send a gift-wrapped event
async fn send_gift_wrap<T>(
async fn send_gift_wrap(
client: &Client,
signer: &T,
signer: &Arc<CoopSigner>,
receiver: &Person,
rumor: &UnsignedEvent,
config: &SignerKind,
) -> Result<SendReport, Error>
where
T: NostrSigner + 'static,
{
let k_tag = Tag::custom(TagKind::k(), vec!["14"]);
encryption: bool,
) -> Result<SendReport, Error> {
let k_tag = Tag::custom("k", vec!["14"]);
let mut extra_tags = vec![k_tag];
// Determine the receiver public key based on the config
let receiver = match config {
SignerKind::Auto => {
let receiver = match encryption {
true => {
if let Some(announcement) = receiver.announcement().as_ref() {
extra_tags.push(Tag::public_key(receiver.public_key()));
announcement.public_key()
@@ -615,19 +587,20 @@ where
receiver.public_key()
}
}
SignerKind::Encryption => {
if let Some(announcement) = receiver.announcement().as_ref() {
extra_tags.push(Tag::public_key(receiver.public_key()));
announcement.public_key()
} else {
return Err(anyhow!("User has no encryption announcement"));
}
}
SignerKind::User => receiver.public_key(),
false => receiver.public_key(),
};
// Construct the gift wrap event
let event = EventBuilder::gift_wrap(signer, &receiver, rumor.clone(), extra_tags).await?;
let event = match encryption {
true => {
let signer = signer.get_encryption_signer().await.unwrap();
EventBuilder::gift_wrap_async(&signer, &receiver, rumor.clone(), extra_tags).await?
}
false => {
let signer = signer.get().await;
EventBuilder::gift_wrap_async(&signer, &receiver, rumor.clone(), extra_tags).await?
}
};
// Send the gift wrap event and collect the report
let report = client