commit 9f673e9e59a27336cb98037730802e92f18a7bac
parent 270b64d5782668c9cda9107332c35845bc765ffe
Author: triesap <137732411+triesap@users.noreply.github.com>
Date: Sat, 12 Apr 2025 19:14:14 +0000
Adds file based configuration interface and initial schema for Nostr kind 0 metadata.
Diffstat:
7 files changed, 429 insertions(+), 33 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -11,4 +11,5 @@ notes*.txt
.DS_Store
*.pem
-*keys*.json
-\ No newline at end of file
+*keys*.json
+*rhi*.toml
diff --git a/Cargo.lock b/Cargo.lock
@@ -93,12 +93,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
+name = "arraydeque"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
+
+[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
+name = "async-trait"
+version = "0.1.88"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "async-utility"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -158,6 +175,12 @@ dependencies = [
[[package]]
name = "base64"
+version = "0.21.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
+[[package]]
+name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
@@ -223,6 +246,9 @@ name = "bitflags"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+dependencies = [
+ "serde",
+]
[[package]]
name = "block-buffer"
@@ -360,6 +386,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
+name = "config"
+version = "0.15.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "595aae20e65c3be792d05818e8c63025294ac3cb7e200f11459063a352a6ef80"
+dependencies = [
+ "async-trait",
+ "convert_case",
+ "json5",
+ "pathdiff",
+ "ron",
+ "rust-ini",
+ "serde",
+ "serde_json",
+ "toml",
+ "winnow",
+ "yaml-rust2",
+]
+
+[[package]]
+name = "const-random"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
+dependencies = [
+ "const-random-macro",
+]
+
+[[package]]
+name = "const-random-macro"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
+dependencies = [
+ "getrandom 0.2.15",
+ "once_cell",
+ "tiny-keccak",
+]
+
+[[package]]
+name = "convert_case"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -369,6 +443,12 @@ dependencies = [
]
[[package]]
+name = "crunchy"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
+
+[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -408,12 +488,36 @@ dependencies = [
]
[[package]]
+name = "dlv-list"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
+dependencies = [
+ "const-random",
+]
+
+[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "equivalent"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
+
+[[package]]
name = "errno"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -436,6 +540,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
+name = "foldhash"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+
+[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -563,6 +673,30 @@ dependencies = [
]
[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+dependencies = [
+ "foldhash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
+dependencies = [
+ "hashbrown 0.15.2",
+]
+
+[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -749,6 +883,16 @@ dependencies = [
]
[[package]]
+name = "indexmap"
+version = "2.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
+dependencies = [
+ "equivalent",
+ "hashbrown 0.15.2",
+]
+
+[[package]]
name = "inout"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -793,6 +937,17 @@ dependencies = [
]
[[package]]
+name = "json5"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
+dependencies = [
+ "pest",
+ "pest_derive",
+ "serde",
+]
+
+[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -882,7 +1037,7 @@ version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f900ddcdc28395759fcd44b18a03255e7deee8858551bfe5d5d5a07311d82ea"
dependencies = [
- "base64",
+ "base64 0.22.1",
"bech32",
"bip39",
"bitcoin_hashes 0.14.0",
@@ -975,6 +1130,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
+name = "ordered-multimap"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
+dependencies = [
+ "dlv-list",
+ "hashbrown 0.14.5",
+]
+
+[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1015,6 +1180,12 @@ dependencies = [
]
[[package]]
+name = "pathdiff"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
+
+[[package]]
name = "pbkdf2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1031,6 +1202,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
+name = "pest"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6"
+dependencies = [
+ "memchr",
+ "thiserror 2.0.12",
+ "ucd-trie",
+]
+
+[[package]]
+name = "pest_derive"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5"
+dependencies = [
+ "pest",
+ "pest_generator",
+]
+
+[[package]]
+name = "pest_generator"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841"
+dependencies = [
+ "pest",
+ "pest_meta",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "pest_meta"
+version = "2.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0"
+dependencies = [
+ "once_cell",
+ "pest",
+ "sha2",
+]
+
+[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1190,6 +1406,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"clap",
+ "config",
"nostr",
"nostr-sdk",
"serde",
@@ -1217,6 +1434,29 @@ dependencies = [
]
[[package]]
+name = "ron"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
+dependencies = [
+ "base64 0.21.7",
+ "bitflags",
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "rust-ini"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f"
+dependencies = [
+ "cfg-if",
+ "ordered-multimap",
+ "trim-in-place",
+]
+
+[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1358,6 +1598,15 @@ dependencies = [
]
[[package]]
+name = "serde_spanned"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1532,6 +1781,15 @@ dependencies = [
]
[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
+[[package]]
name = "tinystr"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1624,6 +1882,40 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.8.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1681,6 +1973,12 @@ dependencies = [
]
[[package]]
+name = "trim-in-place"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc"
+
+[[package]]
name = "tungstenite"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1706,6 +2004,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
+name = "ucd-trie"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
+
+[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1721,6 +2025,12 @@ dependencies = [
]
[[package]]
+name = "unicode-segmentation"
+version = "1.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2003,6 +2313,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
+name = "winnow"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2024,6 +2343,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
[[package]]
+name = "yaml-rust2"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "818913695e83ece1f8d2a1c52d54484b7b46d0f9c06beeb2649b9da50d9b512d"
+dependencies = [
+ "arraydeque",
+ "encoding_rs",
+ "hashlink",
+]
+
+[[package]]
name = "yoke"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
@@ -9,6 +9,7 @@ description = "rhizome is a Nostr data vending machine (NIP-90)"
[dependencies]
anyhow = "1.0"
clap = { version = "4", features = ["derive"] }
+config = "0.15"
nostr = "0.40.0"
nostr-sdk = "0.40.0"
serde = "1.0"
diff --git a/config.toml b/config.toml
@@ -0,0 +1,29 @@
+# rhizome Nostr data vending machine configuration
+
+[metadata]
+# The name shown on the profile
+name = "rhi"
+
+# A full display name that can include emojis or symbols
+# display_name = ""
+
+# A profile biography or description
+# about = ""
+
+# URL of profile picture
+# picture = ""
+
+# URL of banner image
+# banner = ""
+
+# URL of website
+# banner = ""
+
+# Profile mapping to DNS-based internet identifier
+# nip05 = ""
+
+# Lightning address LNURL format
+# lud06 = ""
+
+# Lightning address internet identifiers format
+# lud16 = ""
diff --git a/src/config.rs b/src/config.rs
@@ -0,0 +1,54 @@
+use anyhow::Result;
+use config::{Config, ConfigError, File};
+use nostr::Metadata;
+use serde::{Deserialize, Serialize};
+use thiserror::Error;
+use tracing::{error, warn};
+
+#[derive(Debug, Error)]
+pub enum SettingsError {
+ #[error("Configuration loading failed: {0}")]
+ Load(#[from] ConfigError),
+}
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct Settings {
+ pub metadata: Metadata,
+}
+
+impl Settings {
+ pub fn load(config_path: &Option<String>) -> Result<Self, SettingsError> {
+ let default = Self::default();
+
+ match Self::load_from_file(config_path) {
+ Ok(settings) => Ok(settings),
+ Err(err) if config_path.is_none() => {
+ warn!("Could not read config file: {err}. Using default configuration.",);
+ Ok(default)
+ }
+ Err(err) => Err(err),
+ }
+ }
+
+ fn load_from_file(config_path: &Option<String>) -> Result<Self, SettingsError> {
+ let path = config_path.as_deref().unwrap_or("config.toml");
+
+ let config = Config::builder()
+ .add_source(File::with_name(path).required(false))
+ .build()?
+ .try_deserialize::<Settings>()?;
+
+ Ok(config)
+ }
+}
+
+impl Default for Settings {
+ fn default() -> Self {
+ Self {
+ metadata: Metadata {
+ name: Some("rhi".to_string()),
+ ..Default::default()
+ },
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
@@ -1,3 +1,4 @@
+pub mod config;
pub mod keys;
pub const KIND_JOB_REQUEST: u16 = 5300;
diff --git a/src/main.rs b/src/main.rs
@@ -1,16 +1,11 @@
use anyhow::Result;
use clap::Parser;
-use nostr::{Filter, Keys, Kind, Timestamp, event::Event, nips::nip01::Metadata};
+use nostr::{Filter, Keys, Kind, Timestamp, event::Event};
use nostr_sdk::{Client, RelayPoolNotification};
-use rhi::{KIND_JOB_REQUEST, keys::KeyProfile};
+use rhi::{KIND_JOB_REQUEST, config::Settings, keys::KeyProfile};
use tokio::signal::unix::{SignalKind, signal};
use tracing::{error, info};
-struct ConfigMetadata {
- name: String,
- nip_05: Option<String>,
-}
-
fn init_tracing() {
tracing_subscriber::fmt::init();
}
@@ -56,15 +51,15 @@ async fn subscribe(keys: Keys, relays: Vec<String>) -> Result<()> {
version = env!("CARGO_PKG_VERSION")
)]
pub struct Args {
- #[arg(long, help = "Adds the keys profiles file path.", required = true)]
+ #[arg(long, help = "Adds the keys profiles file path", required = true)]
pub keys: String,
- #[arg(long, help = "Adds nostr relays to the subscription.", required = true)]
+ #[arg(long, help = "Adds nostr relays to the subscription", required = true)]
pub relays: Vec<String>,
#[arg(
long,
- help = "(Optional) Sets flag to generate keys if none are found.",
+ help = "(Optional) Sets flag to generate keys if none are found",
required = false
)]
pub generate_keys: bool,
@@ -78,10 +73,10 @@ pub struct Args {
#[arg(
long,
- help = "(Optional) Adds the domain name (NIP-05) to metadata",
+ help = "(Optional) Adds the config file path. Defaults to 'config.toml'",
required = false
)]
- pub nip05_domain: Option<String>,
+ pub config: Option<String>,
}
#[tokio::main]
@@ -89,6 +84,8 @@ async fn main() -> Result<()> {
init_tracing();
let args = Args::parse();
+ let config = Settings::load(&args.config)?;
+
let relays = args.relays.clone();
info!("Starting");
@@ -97,21 +94,7 @@ async fn main() -> Result<()> {
let keys = key_profile.keys()?;
- let config = ConfigMetadata {
- name: "rhi".to_string(),
- nip_05: args.nip05_domain,
- };
-
- let metadata = Metadata {
- name: Some(config.name.clone()),
- display_name: None,
- picture: None,
- nip05: config
- .nip_05
- .as_ref()
- .map(|domain| format!("{}@{}", config.name, domain)),
- ..Default::default()
- };
+ let metadata = config.metadata.clone();
let mut events: Vec<Event> = vec![];
@@ -131,9 +114,7 @@ async fn main() -> Result<()> {
client.connect().await;
for event in events {
client.send_event(&event).await?;
- info!("Sent kind {} event for key profile", {
- event.clone().kind
- })
+ info!("Sent kind {} event for key profile", { event.clone().kind })
}
client.disconnect().await;
}