-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
subscription print better, nicer output
- it is recommended to put all subscriptions also into the contacts for having nicer aliases
- Loading branch information
8go
committed
Dec 8, 2022
1 parent
a48cbae
commit e6ef452
Showing
5 changed files
with
185 additions
and
26 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,7 +29,7 @@ can find the project more easily :heart:. | |
|
||
# What's in the name? | ||
|
||
nostr-command*(lin)*er. A word play. | ||
nostr-command(lin)er. A word play. | ||
|
||
# Audience, Use cases | ||
|
||
|
@@ -57,6 +57,63 @@ nostr-command*(lin)*er. A word play. | |
- Once program is compiled, the executable will be available in target/release/nostr-commander-rs. | ||
- `./target/release/nostr-commander-rs --version # run it and get version` | ||
|
||
# Config File | ||
|
||
You don't need to know any of this. This is just for the curious ones. | ||
|
||
The config file looks something like this. If you want to do some quick testing, | ||
you can copy and paste this config file to get going real fast. | ||
|
||
``` | ||
{ | ||
"secret_key_bech32": "nsec1yljk9us0e3whjnzysu6pqjhnw5wglkr6hvx4vj376fs0sfaxze6qvx5f5x", | ||
"public_key_bech32": "npub1af7ep6s5esrgtc2c7tlvd3v4jpna44qf6nhan8tek6h505nwrvgq38nwz6", | ||
"relays": [ | ||
"wss://relay.nostr.info/", | ||
"wss://nostr.ono.re/", | ||
"wss://nostr.rocks/", | ||
"wss://nostr-pub.wellorder.net/", | ||
"wss://nostr.semisol.dev/", | ||
"wss://nostr-relay.wlvs.space/" | ||
], | ||
"metadata": { | ||
"name": "James Jones", | ||
"display_name": "Jim", | ||
"about": "tech nerd and nostr lover" | ||
}, | ||
"contacts": [ | ||
{ | ||
"pk": "887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072", | ||
"relay_url": "wss://nostr.openchain.fr/", | ||
"alias": "HackerNews" | ||
}, | ||
{ | ||
"pk": "6b0d4c8d9dc59e110d380b0429a02891f1341a0fa2ba1b1cf83a3db4d47e3964", | ||
"relay_url": "wss://nostr.openchain.fr/", | ||
"alias": "dergigi" | ||
}, | ||
{ | ||
"pk": "3235036bd0957dfb27ccda02d452d7c763be40c91a1ac082ba6983b25238388c", | ||
"relay_url": "wss://nostr.openchain.fr/", | ||
"alias": "vishalxl" | ||
}, | ||
{ | ||
"pk": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245", | ||
"relay_url": "wss://nostr.openchain.fr/", | ||
"alias": "jb55.com" | ||
} | ||
], | ||
"subscribed_authors": [ | ||
"6b0d4c8d9dc59e110d380b0429a02891f1341a0fa2ba1b1cf83a3db4d47e3964", | ||
"3235036bd0957dfb27ccda02d452d7c763be40c91a1ac082ba6983b25238388c" | ||
], | ||
"subscribed_pubkeys": [ | ||
"887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072", | ||
"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245" | ||
] | ||
} | ||
``` | ||
|
||
# Example Usage | ||
|
||
``` | ||
|
@@ -65,8 +122,10 @@ $ nostr-commander-rs --create-user --name "James Jones" \ | |
--picture "https://i.imgur.com/mIcObyL.jpeg" \ | ||
--nip05 [email protected] \ | ||
--add-relay "wss://nostr.openchain.fr" "wss://relay.damus.io" # first time only | ||
$ nostr-commander-rs --add-contact --key "887645fef0ce0c3c1218d2f5d8e6132a19304cdc57cd20281d082f38cfea0072" --alias HackerNews --relay "wss://nostr.openchain.fr/" | ||
$ nostr-commander-rs --publish "Love this protocol" | ||
$ nostr-commander-rs --dm joe "How about pizza tonight?" | ||
$ nostr-commander-rs --subscribe-author npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s | ||
``` | ||
|
||
# Usage | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.0.6 | ||
0.0.7 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,19 +8,13 @@ | |
//! Please help improve the code and add features :pray: :clap: | ||
//! | ||
//! Usage: | ||
//! - nostr-commander-rs --create-user --name "James Jones" \ | ||
//! --display-name Jimmy --about "tech and pizza lover" \ | ||
//! --picture "https://i.imgur.com/mIcObyL.jpeg" \ | ||
//! --nip05 [email protected] \ | ||
//! --add-relay "wss://nostr.openchain.fr" "wss://relay.damus.io" # first time only | ||
//! - nostr-commander-rs --publish "Love this protocol" | ||
//! - nostr-commander-rs --dm [email protected] "How about pizza tonight?" | ||
//! | ||
//! For more information, see the README.md | ||
//! - run `nostr-commander-rs --help` | ||
//! | ||
//! For more information, see read the README.md | ||
//! <https://github.com/8go/nostr-commander-rs/blob/main/README.md> | ||
//! file. | ||
// #![allow(dead_code)] // crate-level allow // Todo | ||
#![allow(dead_code)] // crate-level allow // Todo | ||
#![allow(unused_variables)] // Todo | ||
#![allow(unused_imports)] // Todo | ||
|
||
|
@@ -43,7 +37,10 @@ use update_informer::{registry, Check}; | |
use url::Url; | ||
|
||
use nostr_sdk::{ | ||
nostr::contact::Contact, | ||
nostr::event::kind::Kind, | ||
nostr::event::kind::KindBase, | ||
nostr::contact::Contact, | ||
nostr::event::tag::TagKind, | ||
nostr::key::XOnlyPublicKey, | ||
nostr::key::{FromBech32, KeyError, Keys, ToBech32}, | ||
nostr::message::relay::RelayMessage, | ||
|
@@ -1396,12 +1393,69 @@ pub(crate) async fn cli_dm(client: &Client, ap: &mut Args) -> Result<(), Error> | |
} | ||
} | ||
|
||
/// Is key in subscribed_authors list? | ||
pub(crate) fn is_subscribed_author(ap: &Args, pkey: &XOnlyPublicKey) -> bool { | ||
ap.creds.subscribed_authors.contains(pkey) | ||
} | ||
|
||
/// Get contact for given alias. | ||
/// Returns None if alias does not exist in contact list. | ||
pub(crate) fn get_contact(ap: &Args, alias: &str) -> Option<Contact> { | ||
pub(crate) fn get_contact_by_alias(ap: &Args, alias: &str) -> Option<Contact> { | ||
ap.creds.contacts.iter().find(|s| s.alias == alias).cloned() | ||
} | ||
|
||
/// Get contact for given pubkey. | ||
/// Returns None if pubkey does not exist in contact list. | ||
pub(crate) fn get_contact_by_key(ap: &Args, pkey: XOnlyPublicKey) -> Option<Contact> { | ||
ap.creds.contacts.iter().find(|s| s.pk == pkey).cloned() | ||
} | ||
|
||
/// Get contact alias for given pubkey, or if not in contacts return given pubkey. | ||
/// Returns alias if contact with this pubkey exists. | ||
/// Returns input pubkey if no contact with this pubkey exists. | ||
pub(crate) fn get_contact_alias_or_keystr_by_key(ap: &Args, pkey: XOnlyPublicKey) -> String { | ||
match get_contact_by_key(ap, pkey) { | ||
Some(c) => c.alias, | ||
None => pkey.to_string(), | ||
} | ||
} | ||
|
||
/// Get contact alias for given pubkey, or if not in contacts return None. | ||
/// Returns Some(alias) if contact with this pubkey exists. | ||
/// Returns None if no contact with this pubkey exists. | ||
pub(crate) fn get_contact_alias_by_key(ap: &Args, pkey: XOnlyPublicKey) -> Option<String> { | ||
match get_contact_by_key(ap, pkey) { | ||
Some(c) => Some(c.alias), | ||
None => None, | ||
} | ||
} | ||
|
||
/// Get contact alias for given pubkey string (string of XOnlyPublicKey), or if not in contacts return given pubkey. | ||
/// Returns alias if contact with this pubkey exists. | ||
/// Returns input pubkey if no contact with this pubkey exists. | ||
pub(crate) fn get_contact_alias_or_keystr_by_keystr(ap: &Args, pkeystr: &str) -> String { | ||
match XOnlyPublicKey::from_str(pkeystr) { | ||
Ok(pkey) => match get_contact_by_key(ap, pkey) { | ||
Some(c) => c.alias, | ||
None => pkey.to_string(), | ||
}, | ||
Err(_) => pkeystr.to_string(), | ||
} | ||
} | ||
|
||
/// Get contact alias for given pubkey string (string of XOnlyPublicKey), or if not in contacts return None. | ||
/// Returns Some(alias) if contact with this pubkey exists. | ||
/// Returns None if no contact with this pubkey exists. | ||
pub(crate) fn get_contact_alias_by_keystr(ap: &Args, pkeystr: &str) -> Option<String> { | ||
match XOnlyPublicKey::from_str(pkeystr) { | ||
Ok(pkey) => match get_contact_by_key(ap, pkey) { | ||
Some(c) => Some(c.alias), | ||
None => None, | ||
}, | ||
Err(_) => None, | ||
} | ||
} | ||
|
||
/// Handle the --add-conect CLI argument, write contacts from CLI args into creds data structure | ||
pub(crate) async fn cli_add_contact(client: &Client, ap: &mut Args) -> Result<(), Error> { | ||
let mut err_count = 0usize; | ||
|
@@ -1423,7 +1477,7 @@ pub(crate) async fn cli_add_contact(client: &Client, ap: &mut Args) -> Result<() | |
i += 1; | ||
continue; | ||
} | ||
if get_contact(ap, ap.alias[i].trim()).is_some() { | ||
if get_contact_by_alias(ap, ap.alias[i].trim()).is_some() { | ||
error!("Invalid user alias. Alias already exists. Alias must be unique. Skipping this contact."); | ||
err_count += 1; | ||
i += 1; | ||
|
@@ -1513,7 +1567,7 @@ pub(crate) async fn cli_subscribe_author(client: &mut Client, ap: &mut Args) -> | |
/// Convert npub1... Bech32 key or Hex key or contact alias into a XOnlyPublicKey | ||
/// Returns Error if neither valid Bech32, nor Hex key, nor contact alias. | ||
pub(crate) fn cstr_to_pubkey(ap: &Args, s: &str) -> Result<XOnlyPublicKey, Error> { | ||
match get_contact(ap, s) { | ||
match get_contact_by_alias(ap, s) { | ||
Some(c) => Ok(c.pk), | ||
None => str_to_pubkey(s), | ||
} | ||
|
@@ -1937,24 +1991,70 @@ async fn main() -> Result<(), Error> { | |
// Handle notifications | ||
match client | ||
.handle_notifications(|notification| { | ||
debug!("Notification: {:?}", notification); | ||
// debug!("Notification: {:?}", notification); | ||
match notification { | ||
ReceivedEvent(ev) => { | ||
debug!("Event: {:?}", ev); | ||
debug!("Event-Event: content {:?}, kind {:?}", ev.content, ev.kind); | ||
} | ||
ReceivedMessage(msg) => { | ||
debug!("Message: {:?}", msg); | ||
// Notification: ReceivedMessage(Ok { event_id: 123, status: true, message: "" }) | ||
// confirmation of notice having been relayed | ||
// debug!("Message: {:?}", msg); | ||
match msg { | ||
RelayMessage::Ok {event_id, status, message } => { | ||
println!("OK: Notice or DM was relayed. Event id is {:?}. Status is {:?} and message is {:?}. You can investigate this event by looking it up on https://nostr.com/e/{}", event_id, status, message, event_id.to_string()); | ||
// Notification: ReceivedMessage(Ok { event_id: 123, status: true, message: "" }) | ||
// confirmation of notice having been relayed | ||
info!("Message-OK: Notice or DM was relayed. Event id is {:?}. Status is {:?} and message is {:?}. You can investigate this event by looking it up on https://nostr.com/e/{}", event_id, status, message, event_id.to_string()); | ||
println!("Message-OK: Notice or DM was relayed. Event id is {:?}. Status is {:?} and message is {:?}. You can investigate this event by looking it up on https://nostr.com/e/{}", event_id, status, message, event_id.to_string()); | ||
}, | ||
RelayMessage::Notice { message } => { | ||
debug!("Notice: {:?}", message); | ||
debug!("Message-Notice: {:?}", message); | ||
} | ||
RelayMessage::Event {event, subscription_id}=> { | ||
// kind: Base(ChannelMessage) and Base(TextNote) and Base(Reaction) | ||
let mut tags = "".to_owned(); | ||
let mut first = true; | ||
for t in &event.tags { | ||
match t.kind() { | ||
Ok(TagKind::P) => { | ||
match t.content() { | ||
Some(c) => { | ||
debug!("tag: {:?}", get_contact_alias_or_keystr_by_keystr(&ap, c)); | ||
match get_contact_alias_by_keystr(&ap, c) { | ||
Some(a) => { | ||
if !first { tags += ", "; }; | ||
tags += &a; | ||
first = false; | ||
}, | ||
_ => () | ||
} | ||
} | ||
None => () | ||
} | ||
}, | ||
Ok(TagKind::E) => (), | ||
Ok(TagKind::Nonce) => (), | ||
Err(_) => () | ||
} | ||
} | ||
info!("Message-Event: content {:?}, kind {:?}, from pubkey {:?}, with tags {:?}", event.content, event.kind, get_contact_alias_or_keystr_by_key(&ap, event.pubkey), event.tags); | ||
let mut key_author = "key"; | ||
if is_subscribed_author(&ap, &event.pubkey) { | ||
key_author = "author"; | ||
tags = get_contact_alias_or_keystr_by_key(&ap, event.pubkey); | ||
}; | ||
match event.kind { | ||
Kind::Base(KindBase::ContactList) => (), | ||
Kind::Base(KindBase::Reaction) => (), | ||
Kind::Base(KindBase::TextNote) => { | ||
println!("Subscription by {} ({}): content {:?}, kind {:?}, from pubkey {:?}", key_author, tags, event.content, event.kind, get_contact_alias_or_keystr_by_key(&ap, event.pubkey)); | ||
}, | ||
Kind::Base(KindBase::ChannelMessage) => { | ||
println!("Subscription by {} ({}): content {:?}, kind {:?}, from pubkey {:?}", key_author, tags, event.content, event.kind, get_contact_alias_or_keystr_by_key(&ap, event.pubkey)); | ||
}, | ||
_ => () | ||
} | ||
}, | ||
RelayMessage::Empty => (), | ||
_ => (), | ||
RelayMessage::EndOfStoredEvents {subscription_id} => (), | ||
} | ||
} | ||
} | ||
|