Skip to content

Commit 04ca010

Browse files
nostr: add NIP-C7 support
Pull-Request: #1067
1 parent 0cf8e0f commit 04ca010

File tree

4 files changed

+73
-1
lines changed

4 files changed

+73
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ Learn more about `rust-nostr` at <https://rust-nostr.org>.
129129
|| [B0 - Web Bookmarks](https://github.com/nostr-protocol/nips/blob/master/B0.md) |
130130
|| [B7 - Blossom](https://github.com/nostr-protocol/nips/blob/master/B7.md) |
131131
|| [C0 - Code Snippets](https://github.com/nostr-protocol/nips/blob/master/C0.md) |
132-
| | [C7 - Chats](https://github.com/nostr-protocol/nips/blob/master/C7.md) |
132+
| | [C7 - Chats](https://github.com/nostr-protocol/nips/blob/master/C7.md) |
133133
|| [EE - Messaging using the MLS Protocol](https://github.com/nostr-protocol/nips/blob/master/EE.md) |
134134

135135
## State

crates/nostr/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
### Added
3737

38+
- Add NIP-C7 support (https://github.com/rust-nostr/nostr/pull/1067)
3839
- Implement `ToBech32` trait for `Nip21`
3940
- Add nip47 holdinvoice methods and notification (https://github.com/rust-nostr/nostr/pull/1019)
4041
- Add `TransactionState` to `LookupInvoiceResponse` and `PaymentNotification` (https://github.com/rust-nostr/nostr/pull/1045)

crates/nostr/src/event/builder.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub enum Error {
4949
/// NIP04 error
5050
#[cfg(feature = "nip04")]
5151
NIP04(nip04::Error),
52+
/// NIP21 error
53+
NIP21(nip21::Error),
5254
/// NIP44 error
5355
#[cfg(all(feature = "std", feature = "nip44"))]
5456
NIP44(nip44::Error),
@@ -80,6 +82,7 @@ impl fmt::Display for Error {
8082
Self::NIP03(e) => e.fmt(f),
8183
#[cfg(feature = "nip04")]
8284
Self::NIP04(e) => e.fmt(f),
85+
Self::NIP21(e) => e.fmt(f),
8386
#[cfg(all(feature = "std", feature = "nip44"))]
8487
Self::NIP44(e) => e.fmt(f),
8588
Self::NIP58(e) => e.fmt(f),
@@ -125,6 +128,12 @@ impl From<nip04::Error> for Error {
125128
}
126129
}
127130

131+
impl From<nip21::Error> for Error {
132+
fn from(e: nip21::Error) -> Self {
133+
Self::NIP21(e)
134+
}
135+
}
136+
128137
#[cfg(all(feature = "std", feature = "nip44"))]
129138
impl From<nip44::Error> for Error {
130139
fn from(e: nip44::Error) -> Self {
@@ -1706,6 +1715,67 @@ impl EventBuilder {
17061715
pub fn poll_response(response: PollResponse) -> Self {
17071716
response.to_event_builder()
17081717
}
1718+
1719+
/// Chat message
1720+
///
1721+
/// <https://github.com/nostr-protocol/nips/blob/master/C7.md>
1722+
#[inline]
1723+
pub fn chat_message<S>(content: S) -> Self
1724+
where
1725+
S: Into<String>,
1726+
{
1727+
Self::new(Kind::ChatMessage, content)
1728+
}
1729+
1730+
/// Chat message reply
1731+
///
1732+
/// <https://github.com/nostr-protocol/nips/blob/master/C7.md>
1733+
pub fn chat_message_reply<S>(
1734+
content: S,
1735+
reply_to: &Event,
1736+
relay_url: Option<RelayUrl>,
1737+
) -> Result<Self, Error>
1738+
where
1739+
S: Into<String>,
1740+
{
1741+
let mut content = content.into();
1742+
1743+
if !has_nostr_event_uri(&content, &reply_to.id) {
1744+
let nevent = Nip19Event {
1745+
event_id: reply_to.id,
1746+
author: None,
1747+
kind: None,
1748+
relays: relay_url.clone().into_iter().collect(),
1749+
};
1750+
content = format!("{}\n{content}", nevent.to_nostr_uri()?);
1751+
}
1752+
1753+
Ok(
1754+
Self::new(Kind::ChatMessage, content).tag(Tag::from_standardized_without_cell(
1755+
TagStandard::Quote {
1756+
event_id: reply_to.id,
1757+
relay_url,
1758+
public_key: Some(reply_to.pubkey),
1759+
},
1760+
)),
1761+
)
1762+
}
1763+
}
1764+
1765+
fn has_nostr_event_uri(content: &str, event_id: &EventId) -> bool {
1766+
const OPTS: NostrParserOptions = NostrParserOptions::disable_all().nostr_uris(true);
1767+
1768+
let parser = NostrParser::new().parse(content).opts(OPTS);
1769+
1770+
for token in parser.into_iter() {
1771+
if let Token::Nostr(nip21) = token {
1772+
if nip21.event_id().as_ref() == Some(event_id) {
1773+
return true;
1774+
}
1775+
}
1776+
}
1777+
1778+
false
17091779
}
17101780

17111781
#[cfg(test)]

crates/nostr/src/event/kind.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ kind_variants! {
163163
CodeSnippet => 1337, "Code Snippets", "<https://github.com/nostr-protocol/nips/blob/master/C0.md>",
164164
Poll => 1068, "Poll", "<https://github.com/nostr-protocol/nips/blob/master/88.md>",
165165
PollResponse => 1018, "Poll response", "<https://github.com/nostr-protocol/nips/blob/master/88.md>",
166+
ChatMessage => 9, "Chat Message", "<https://github.com/nostr-protocol/nips/blob/master/C7.md>",
166167
}
167168

168169
impl PartialEq for Kind {

0 commit comments

Comments
 (0)