Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Learn more about `rust-nostr` at <https://rust-nostr.org>.
| ✅ | [98 - HTTP Auth](https://github.com/nostr-protocol/nips/blob/master/98.md) |
| ❌ | [99 - Classified Listings](https://github.com/nostr-protocol/nips/blob/master/99.md) |
| ✅ | [A0 - Voice Messages](https://github.com/nostr-protocol/nips/blob/master/A0.md) |
| | [B0 - Web Bookmarks](https://github.com/nostr-protocol/nips/blob/master/B0.md) |
| | [B0 - Web Bookmarks](https://github.com/nostr-protocol/nips/blob/master/B0.md) |
| ✅ | [B7 - Blossom](https://github.com/nostr-protocol/nips/blob/master/B7.md) |
| ✅ | [C0 - Code Snippets](https://github.com/nostr-protocol/nips/blob/master/C0.md) |
| ✅ | [C7 - Chats](https://github.com/nostr-protocol/nips/blob/master/C7.md) |
Expand Down
1 change: 1 addition & 0 deletions crates/nostr/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

### Added

- Add NIP-B0 support (https://github.com/rust-nostr/nostr/pull/1077)
- Add NIP-7D support (https://github.com/rust-nostr/nostr/pull/1071)
- Add NIP-C7 support (https://github.com/rust-nostr/nostr/pull/1067)
- Implement `ToBech32` trait for `Nip21`
Expand Down
8 changes: 8 additions & 0 deletions crates/nostr/src/event/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,14 @@ impl EventBuilder {

Self::new(Kind::Comment, content).tags(tags)
}

/// Web Bookmark
///
/// <https://github.com/nostr-protocol/nips/blob/master/B0.md>
#[inline]
pub fn web_bookmark(web_bookmark: WebBookmark) -> Self {
web_bookmark.to_event_builder()
}
}

fn has_nostr_event_uri(content: &str, event_id: &EventId) -> bool {
Expand Down
1 change: 1 addition & 0 deletions crates/nostr/src/event/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ kind_variants! {
PollResponse => 1018, "Poll response", "<https://github.com/nostr-protocol/nips/blob/master/88.md>",
ChatMessage => 9, "Chat Message", "<https://github.com/nostr-protocol/nips/blob/master/C7.md>",
Thread => 11, "Thread", "<https://github.com/nostr-protocol/nips/blob/master/7D.md>",
WebBookmark => 39701, "Web Bookmark", "<https://github.com/nostr-protocol/nips/blob/master/B0.md>",
}

impl PartialEq for Kind {
Expand Down
1 change: 1 addition & 0 deletions crates/nostr/src/nips/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ pub mod nip94;
pub mod nip96;
#[cfg(feature = "nip98")]
pub mod nip98;
pub mod nipb0;
pub mod nipc0;
94 changes: 94 additions & 0 deletions crates/nostr/src/nips/nipb0.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) 2022-2023 Yuki Kishimoto
// Copyright (c) 2023-2025 Rust Nostr Developers
// Distributed under the MIT software license

//! NIPB0: Web Bookmarks
//!
//! <https://github.com/nostr-protocol/nips/blob/master/B0.md>

use alloc::string::String;
use alloc::vec::Vec;

use crate::{EventBuilder, Kind, Tag, TagStandard, Timestamp};

/// Web Bookmark
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WebBookmark {
/// Description of the web bookmark.
pub description: String,
/// URL of the web bookmark.
pub url: String,
/// Timestamp when the web bookmark was first published.
pub published_at: Option<Timestamp>,
/// Title of the web bookmark.
pub title: Option<String>,
/// Hashtags for the web bookmark.
pub hashtags: Vec<String>,
}

impl WebBookmark {
/// Create a new web bookmark
#[inline]
pub fn new<T>(description: T, url: T) -> Self
where
T: Into<String>,
{
Self {
description: description.into(),
url: url.into(),
published_at: None,
title: None,
hashtags: Vec::new(),
}
}

/// Set the title.
#[inline]
pub fn title<T>(mut self, title: T) -> Self
where
T: Into<String>,
{
self.title = Some(title.into());
self
}

/// Set the timestamp at which the web bookmark was published.
#[inline]
pub fn published_at(mut self, timestamp: Timestamp) -> Self {
self.published_at = Some(timestamp);
self
}

/// Add a hashtag/tag.
pub fn hashtags<T>(mut self, hashtag: T) -> Self
where
T: Into<String>,
{
let hashtag = hashtag.into().to_lowercase();
if !self.hashtags.contains(&hashtag) {
self.hashtags.push(hashtag);
}
self
}

/// Convert the web bookmark to an event builder
#[allow(clippy::wrong_self_convention)]
pub(crate) fn to_event_builder(self) -> EventBuilder {
let mut tags: Vec<Tag> = vec![TagStandard::Identifier(self.url).into()];

let mut add_if_some = |tag: Option<TagStandard>| {
if let Some(tag) = tag {
tags.push(tag.into());
}
};

add_if_some(self.published_at.map(TagStandard::PublishedAt));
add_if_some(self.title.map(TagStandard::Title));

for hashtag in self.hashtags.into_iter() {
tags.push(TagStandard::Hashtag(hashtag).into());
}

EventBuilder::new(Kind::WebBookmark, self.description).tags(tags)
}
}
1 change: 1 addition & 0 deletions crates/nostr/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub use crate::nips::nip94::{self, *};
pub use crate::nips::nip96::{self, *};
#[cfg(feature = "nip98")]
pub use crate::nips::nip98::{self, *};
pub use crate::nips::nipb0::{self, *};
pub use crate::nips::nipc0::{self, *};
pub use crate::parser::{self, *};
pub use crate::signer::{self, *};
Expand Down
Loading