Compare commits
1 Commits
1becf76264
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9845dd025d |
19
README.md
19
README.md
@@ -13,6 +13,7 @@
|
||||
* **Social Connectivity**: Follow users and manage contact lists.
|
||||
* **Rich Feeds**: Access follow-based timelines, global discovery, and hashtag-based searches.
|
||||
* **Encrypted Messaging**: Secure NIP-17 direct messages.
|
||||
* **Profile Management**: Update account metadata (Kind 0) with support for standard and custom fields.
|
||||
* **Extensible Architecture**: Clean separation between protocol logic (NIPs) and high-level functions.
|
||||
|
||||
---
|
||||
@@ -67,6 +68,24 @@ let event_id = en.post_text("Building with EasyNostr is awesome!").await?;
|
||||
println!("Successfully posted! Event ID: {}", event_id);
|
||||
```
|
||||
|
||||
### 👤 Profile & Metadata
|
||||
|
||||
Update account information (NIP-01) including support for custom fields (e.g., bot, birthday).
|
||||
|
||||
```rust
|
||||
en.set_metadata(
|
||||
Some("user_name".to_string()),
|
||||
Some("Display Name".to_string()),
|
||||
Some("About me...".to_string()),
|
||||
Some("user@domain.com".to_string()), // NIP-05
|
||||
Some("user@getalby.com".to_string()), // LUD-16
|
||||
Some("https://website.com".to_string()),
|
||||
Some("https://banner.com/img.png".to_string()),
|
||||
Some(false), // bot (custom field)
|
||||
Some("1990-01-01".to_string()), // birthday (custom field)
|
||||
).await?;
|
||||
```
|
||||
|
||||
### 📰 Social Feeds
|
||||
|
||||
#### Timeline (Followed Users)
|
||||
|
||||
@@ -112,6 +112,26 @@ async fn main() -> anyhow::Result<()> {
|
||||
println!(" [WARN] No posts found for tags (depends on relay traffic).");
|
||||
}
|
||||
|
||||
// 10. Metadata Update (Kind 0)
|
||||
println!("\n[STEP 8] Testing Profile Metadata Update...");
|
||||
let metadata_id = ez
|
||||
.set_metadata(
|
||||
Some("EasyNostr Test Bot".to_string()),
|
||||
Some("EasyNostr".to_string()),
|
||||
Some("Automated test for metadata updates".to_string()),
|
||||
None, // NIP-05
|
||||
None, // LUD-16
|
||||
Some("https://github.com/Bytemalte/easy-nostr".to_string()),
|
||||
Some(
|
||||
"https://raw.githubusercontent.com/Bytemalte/easy-nostr/main/banner.png"
|
||||
.to_string(),
|
||||
),
|
||||
Some(true), // bot
|
||||
Some("2024-01-31".to_string()), // birthday
|
||||
)
|
||||
.await?;
|
||||
println!(" [OK] Metadata updated: {}", metadata_id.to_bech32()?);
|
||||
|
||||
println!("\n=== Test Complete ===");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
64
src/functions/metadata.rs
Normal file
64
src/functions/metadata.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use crate::nips::nip01;
|
||||
use anyhow::{Result, bail};
|
||||
use nostr_sdk::prelude::*;
|
||||
|
||||
/// Updates the metadata of the current account.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `client` - The Nostr client.
|
||||
/// * `name` - Optional name.
|
||||
/// * `display_name` - Optional display name.
|
||||
/// * `about` - Optional about description.
|
||||
/// * `nip05` - Optional NIP-05 identifier.
|
||||
/// * `lud16` - Optional LDP-16 (Lightning Address).
|
||||
/// * `website` - Optional website URL.
|
||||
/// * `banner` - Optional banner image URL.
|
||||
/// * `bot` - Optional boolean identifying if the account is a bot.
|
||||
/// * `birthday` - Optional birthday string.
|
||||
pub async fn set_metadata(
|
||||
client: &Client,
|
||||
name: Option<String>,
|
||||
display_name: Option<String>,
|
||||
about: Option<String>,
|
||||
nip05: Option<String>,
|
||||
lud16: Option<String>,
|
||||
website: Option<String>,
|
||||
banner: Option<String>,
|
||||
bot: Option<bool>,
|
||||
birthday: Option<String>,
|
||||
) -> Result<EventId> {
|
||||
// Basic validation for NIP-05 and LUD-16
|
||||
if let Some(ref n05) = nip05 {
|
||||
if !n05.contains('@') {
|
||||
bail!("Invalid NIP-05 format: must contain '@'");
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref l16) = lud16 {
|
||||
if !l16.contains('@') {
|
||||
bail!("Invalid LUD-16 format: must contain '@'");
|
||||
}
|
||||
}
|
||||
|
||||
// Parse URLs if provided
|
||||
let website_url = website.map(|w| Url::parse(&w)).transpose()?;
|
||||
let banner_url = banner.map(|b| Url::parse(&b)).transpose()?;
|
||||
|
||||
// Delegate creation of metadata struct to nip01
|
||||
let metadata = nip01::create_metadata(
|
||||
name,
|
||||
display_name,
|
||||
about,
|
||||
nip05,
|
||||
lud16,
|
||||
website_url,
|
||||
banner_url,
|
||||
bot,
|
||||
birthday,
|
||||
);
|
||||
|
||||
// Send the metadata event (Kind 0)
|
||||
let event_id = client.set_metadata(&metadata).await?;
|
||||
|
||||
Ok(*event_id)
|
||||
}
|
||||
@@ -3,6 +3,7 @@ pub mod feed;
|
||||
pub mod get_contacts;
|
||||
pub mod hashtags;
|
||||
pub mod messages;
|
||||
pub mod metadata;
|
||||
pub mod new;
|
||||
pub mod publish;
|
||||
pub mod relays;
|
||||
|
||||
30
src/lib.rs
30
src/lib.rs
@@ -6,7 +6,7 @@ use nostr_sdk::prelude::*;
|
||||
|
||||
// Wir importieren die Funktionen, um Tipparbeit zu sparen
|
||||
use crate::functions::{
|
||||
create_contact, feed, get_contacts, hashtags, messages, new, publish, relays,
|
||||
create_contact, feed, get_contacts, hashtags, messages, metadata, new, publish, relays,
|
||||
};
|
||||
use crate::nips::nip01::Post;
|
||||
use crate::nips::nip17::Message;
|
||||
@@ -70,4 +70,32 @@ impl EasyNostr {
|
||||
pub async fn get_posts_by_hashtags(&self, hashtags: Vec<String>) -> Result<Vec<Post>> {
|
||||
hashtags::get_posts_by_hashtags(&self.client, hashtags).await
|
||||
}
|
||||
|
||||
/// Aktualisiert das Profil-Metadaten (Kind 0)
|
||||
pub async fn set_metadata(
|
||||
&self,
|
||||
name: Option<String>,
|
||||
display_name: Option<String>,
|
||||
about: Option<String>,
|
||||
nip05: Option<String>,
|
||||
lud16: Option<String>,
|
||||
website: Option<String>,
|
||||
banner: Option<String>,
|
||||
bot: Option<bool>,
|
||||
birthday: Option<String>,
|
||||
) -> Result<EventId> {
|
||||
metadata::set_metadata(
|
||||
&self.client,
|
||||
name,
|
||||
display_name,
|
||||
about,
|
||||
nip05,
|
||||
lud16,
|
||||
website,
|
||||
banner,
|
||||
bot,
|
||||
birthday,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,3 +17,48 @@ pub async fn publish_text(client: &Client, content: &str) -> Result<EventId> {
|
||||
let output = client.send_event_builder(builder).await?;
|
||||
Ok(*output.id())
|
||||
}
|
||||
|
||||
/// Creates a Metadata object for updating profile (Kind 0)
|
||||
pub fn create_metadata(
|
||||
name: Option<String>,
|
||||
display_name: Option<String>,
|
||||
about: Option<String>,
|
||||
nip05: Option<String>,
|
||||
lud16: Option<String>,
|
||||
website: Option<Url>,
|
||||
banner: Option<Url>,
|
||||
bot: Option<bool>,
|
||||
birthday: Option<String>,
|
||||
) -> Metadata {
|
||||
let mut metadata = Metadata::new();
|
||||
|
||||
if let Some(val) = name {
|
||||
metadata = metadata.name(val);
|
||||
}
|
||||
if let Some(val) = display_name {
|
||||
metadata = metadata.display_name(val);
|
||||
}
|
||||
if let Some(val) = about {
|
||||
metadata = metadata.about(val);
|
||||
}
|
||||
if let Some(val) = nip05 {
|
||||
metadata = metadata.nip05(val);
|
||||
}
|
||||
if let Some(val) = lud16 {
|
||||
metadata = metadata.lud16(val);
|
||||
}
|
||||
if let Some(val) = website {
|
||||
metadata = metadata.website(val);
|
||||
}
|
||||
if let Some(val) = banner {
|
||||
metadata = metadata.banner(val);
|
||||
}
|
||||
if let Some(val) = bot {
|
||||
metadata = metadata.custom_field("bot", val);
|
||||
}
|
||||
if let Some(val) = birthday {
|
||||
metadata = metadata.custom_field("birthday", val);
|
||||
}
|
||||
|
||||
metadata
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user