update LICENSE and README and new hashtag filter

This commit is contained in:
2026-01-31 12:44:28 +01:00
parent 7cebc490ca
commit 7b644785ee
12 changed files with 186 additions and 205 deletions

209
README.md
View File

@@ -1,18 +1,40 @@
# EasyNostr
# 🌌 EasyNostr
A simple and functional Rust crate for building Nostr applications. This library handles the complexity of keys, relays, and protocol details (NIPs), giving you easy-to-use functions for a social media app.
[![Rust](https://img.shields.io/badge/rust-stable-brightgreen.svg)](https://www.rust-lang.org/)
[![Nostr](https://img.shields.io/badge/nostr-protocol-purple.svg)](https://nostr.com/)
## Features
- **Identity**: Easy management of keys (nsec/npub).
- **Social Feed**: View timeline of friends or global random posts.
- **Posting**: Publish text notes (Kind 1).
- **Contacts**: Follow users and retrieve your contact list.
- **Direct Messages**: Send and receive encrypted private messages (NIP-17 & NIP-04).
**EasyNostr** is a high-level, developer-friendly Rust library designed to simplify the development of Nostr applications. It wraps the powerful `nostr-sdk` to provide a clean, intuitive API for common operations like identity management, social feeds, and encrypted messaging.
## Getting Started
---
### 1. Initialize the Client
First, you need to create an instance of `EasyNostr` using your secret key (nsec).
## 🚀 Key Features
* **Identity Management**: Simple handling of keys (nsec/npub).
* **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.
* **Extensible Architecture**: Clean separation between protocol logic (NIPs) and high-level functions.
---
## 📦 Installation
Add `easy-nostr` and its core dependencies to your `Cargo.toml`:
```toml
[dependencies]
easy-nostr = { path = "." } # Use the crate path
tokio = { version = "1.48.0", features = ["full"] }
anyhow = "1.0.100"
```
---
## 🛠️ Usage Guide
### 1. Initialization & Connection
Create a new instance and connect to your preferred relays.
```rust
use easy_nostr::EasyNostr;
@@ -20,127 +42,100 @@ use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
// Your secret key (nsec)
let my_secret_key = "nsec1...";
// Initialize with your private key (nsec)
let secret_key = "nsec1...";
let en = EasyNostr::new(secret_key).await?;
// Initialize client
let client = EasyNostr::new(my_secret_key).await?;
// Connect to Relays
client.add_relays(vec![
// Add relays to connect to the network
en.add_relays(vec![
"wss://relay.damus.io",
"wss://nos.lol",
"wss://relay.primal.net"
]).await?;
println!("Connected and ready!");
println!("Connected to Nostr!");
Ok(())
}
```
---
### 📝 Publishing Content
## Capabilities & Usage
### 📝 Publishing Posts
Post a simple text message to the network.
Post a simple text note (Kind 1) to the network.
```rust
let event_id = client.post_text("Hello Nostr world!").await?;
println!("Posted! ID: {}", event_id.to_bech32()?);
let event_id = en.post_text("Building with EasyNostr is awesome!").await?;
println!("Successfully posted! Event ID: {}", event_id);
```
### 📰 Reading Feeds
You can read posts from people you follow (Timeline) or random posts from the network.
### 📰 Social Feeds
#### Timeline (Followed Users)
Fetch posts from a specific list of public keys.
**Get Timeline (Followed Users):**
```rust
// List of public keys (npubs) you want to see posts from
let following = vec!["npub1...", "npub1..."];
let posts = client.get_timeline(following).await?;
for post in posts {
println!("@{} wrote: {}", post.author.to_bech32()?, post.content);
}
```
**Get Global Feed (Random/Recent):**
```rust
let random_posts = client.get_random_posts().await?;
for post in random_posts {
println!("New Post: {}", post.content);
}
```
**The `Post` Structure:**
When you get posts, you receive a `Post` struct:
- `post.id`: The unique Event ID.
- `post.author`: The PublicKey of the author.
- `post.content`: The text content.
- `post.created_at`: The timestamp.
---
### 👥 Managing Contacts (Followers)
Manage who you follow.
**Follow a User:**
```rust
let jack_dorsey = "npub1sg6plzptd64u62a878hep2kd8856nmmhd0x479jp6bir725uqqks698teq";
// Context: (NPub, Optional Nickname)
client.create_contact(jack_dorsey, Some("Jack".to_string())).await?;
```
**Get Your Contact List:**
```rust
let my_contacts = client.get_contacts().await?;
for contact in my_contacts {
println!("Following: {:?}", contact.public_key.to_bech32()?);
if let Some(alias) = &contact.alias {
println!(" - Alias: {}", alias);
let follow_list = vec!["npub1...".to_string(), "npub2...".to_string()];
match en.get_timeline(follow_list).await {
Ok(posts) => {
for post in posts {
println!("@{} says: {}", post.author, post.content);
}
}
Err(e) => eprintln!("Failed to load timeline: {}", e),
}
```
#### Discovery (Global Feed)
Get recent random posts from connected relays.
```rust
let global_posts = en.get_random_posts().await?;
```
#### Hashtag Search (NIP-12)
Search for posts containing specific hashtags.
```rust
let tags = vec!["bitcoin".to_string(), "rust".to_string()];
let filtered_posts = en.get_posts_by_hashtags(tags).await?;
```
### 👥 Contacts & Following
#### Follow a User
```rust
en.create_contact("npub1...", Some("Alice".to_string())).await?;
```
#### Retrieve Contact List
```rust
let contacts = en.get_contacts().await?;
```
### 🔒 Private Messaging (NIP-17)
#### Send a Message
```rust
en.send_private_message("npub1...", "Hello, this is a secret!").await?;
```
#### Retrieve Conversations
```rust
let history = en.get_private_messages("npub1...").await?;
```
---
### 🔒 Direct Messages (DMs)
Send and receive encrypted private chats. Supports modern GiftWraps (NIP-17).
## 📂 Project Structure
**Send a DM:**
```rust
let friend_npub = "npub1...";
client.send_private_message(friend_npub, "Hey, this is secret!").await?;
```
**Read DMs:**
```rust
let friend_npub = "npub1...";
let messages = client.get_private_messages(friend_npub).await?;
for msg in messages {
let direction = if msg.is_incoming { "Received" } else { "Sent" };
println!("[{}] {}", direction, msg.content);
}
```
**The `Message` Structure:**
- `msg.sender`: PublicKey of the sender.
- `msg.content`: Decrypted text.
- `msg.is_incoming`: `true` if you received it, `false` if you sent it.
- `msg.created_at`: Use `msg.created_at.as_secs()` to get the unix timestamp.
| Directory | Purpose |
| :--- | :--- |
| `src/lib.rs` | Main entry point and public `EasyNostr` interface. |
| `src/functions/` | Implementation of high-level features (feeds, messaging, etc.). |
| `src/nips/` | Protocol-level logic and data structures categorized by NIP. |
| `src/bin/` | Utility binaries and examples. |
---
## Dependencies
Ensure you have the following in your `Cargo.toml`. `easy-nostr` re-exports most things you need, but you might need `anyhow` and `tokio`.
## ⚖️ License
```toml
[dependencies]
nostr-sdk = { version = "0.44.1", features = ["all-nips", "nip44"] }
tokio = { version = "1.48.0", features = ["full"] }
anyhow = "1.0.100"
```
Distributed under the MIT License. See `LICENSE` for more information.