From c50e10aa21798f1c85bf7718109d3939c119b854 Mon Sep 17 00:00:00 2001 From: jiftechnify Date: Sat, 15 Jul 2023 10:57:31 +0900 Subject: [PATCH 1/6] fix: keep up with the latest specs for since/until filter --- src/repo/postgres.rs | 4 ++-- src/repo/sqlite.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/repo/postgres.rs b/src/repo/postgres.rs index 8fc46eb..cc899e8 100644 --- a/src/repo/postgres.rs +++ b/src/repo/postgres.rs @@ -904,7 +904,7 @@ fn query_from_filter(f: &ReqFilter) -> Option> { } push_and = true; query - .push("e.created_at > ") + .push("e.created_at >= ") .push_bind(Utc.timestamp_opt(f.since.unwrap() as i64, 0).unwrap()); } @@ -915,7 +915,7 @@ fn query_from_filter(f: &ReqFilter) -> Option> { } push_and = true; query - .push("e.created_at < ") + .push("e.created_at <= ") .push_bind(Utc.timestamp_opt(f.until.unwrap() as i64, 0).unwrap()); } diff --git a/src/repo/sqlite.rs b/src/repo/sqlite.rs index 87d8556..8f5b798 100644 --- a/src/repo/sqlite.rs +++ b/src/repo/sqlite.rs @@ -1083,13 +1083,13 @@ fn query_from_filter(f: &ReqFilter) -> (String, Vec>, Option {}", f.since.unwrap()); + since_clause = format!("AND created_at >= {}", f.since.unwrap()); } else { since_clause = String::new(); }; // Query for timestamp if f.until.is_some() { - until_clause = format!("AND created_at < {}", f.until.unwrap()); + until_clause = format!("AND created_at <= {}", f.until.unwrap()); } else { until_clause = String::new(); }; @@ -1107,12 +1107,12 @@ fn query_from_filter(f: &ReqFilter) -> (String, Vec>, Option {}", f.since.unwrap()); + let created_clause = format!("created_at >= {}", f.since.unwrap()); filter_components.push(created_clause); } // Query for timestamp if f.until.is_some() { - let until_clause = format!("created_at < {}", f.until.unwrap()); + let until_clause = format!("created_at <= {}", f.until.unwrap()); filter_components.push(until_clause); } // never display hidden events From 70dfcb6a0419196ef9000848a0a7bed4bd105e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Navr=C3=A1til?= Date: Sat, 15 Jul 2023 21:47:02 +0200 Subject: [PATCH 2/6] feat(NIP-11): relay_icon option added --- config.toml | 3 +++ src/config.rs | 2 ++ src/info.rs | 3 +++ 3 files changed, 8 insertions(+) diff --git a/config.toml b/config.toml index ef5f68d..6a78aba 100644 --- a/config.toml +++ b/config.toml @@ -20,6 +20,9 @@ description = "A newly created nostr-rs-relay.\n\nCustomize this with your own i # ICO format. #favicon = "favicon.ico" +# URL of Relay's icon. +#relay_icon = "https://example.test/img.png" + [diagnostics] # Enable tokio tracing (for use with tokio-console) #tracing = false diff --git a/src/config.rs b/src/config.rs index 03cc243..c5ead74 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,7 @@ pub struct Info { pub pubkey: Option, pub contact: Option, pub favicon: Option, + pub relay_icon: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -268,6 +269,7 @@ impl Default for Settings { pubkey: None, contact: None, favicon: None, + relay_icon: None, }, diagnostics: Diagnostics { tracing: false }, database: Database { diff --git a/src/info.rs b/src/info.rs index d2233ca..35f6430 100644 --- a/src/info.rs +++ b/src/info.rs @@ -45,6 +45,8 @@ pub struct RelayInfo { #[serde(skip_serializing_if = "Option::is_none")] pub contact: Option, #[serde(skip_serializing_if = "Option::is_none")] + pub icon: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub supported_nips: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub software: Option, @@ -124,6 +126,7 @@ impl From for RelayInfo { limitation: Some(limitations), payment_url, fees, + icon: i.relay_icon, } } } From 4adad4c3a99c1454952e46478d42c838e2730e6f Mon Sep 17 00:00:00 2001 From: Greg Heartsfield Date: Sun, 16 Jul 2023 11:41:47 -0500 Subject: [PATCH 3/6] fix: update since/until semantics for subscriptions --- src/subscription.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/subscription.rs b/src/subscription.rs index 822df44..17aaceb 100644 --- a/src/subscription.rs +++ b/src/subscription.rs @@ -319,8 +319,8 @@ impl ReqFilter { pub fn interested_in_event(&self, event: &Event) -> bool { // self.id.as_ref().map(|v| v == &event.id).unwrap_or(true) self.ids_match(event) - && self.since.map_or(true, |t| event.created_at > t) - && self.until.map_or(true, |t| event.created_at < t) + && self.since.map_or(true, |t| event.created_at >= t) + && self.until.map_or(true, |t| event.created_at <= t) && self.kind_match(event.kind) && (self.authors_match(event) || self.delegated_authors_match(event)) && self.tag_match(event) From 34f497a650c7ed9926027e0f469e833962e77e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Navr=C3=A1til?= Date: Mon, 17 Jul 2023 18:25:14 +0200 Subject: [PATCH 4/6] docs: example SQL to delete old events Added SQL Query example to delete events older than 30 days. --- docs/database-maintenance.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/database-maintenance.md b/docs/database-maintenance.md index e475918..f68cc90 100644 --- a/docs/database-maintenance.md +++ b/docs/database-maintenance.md @@ -112,7 +112,8 @@ seen" policy. ```console PRAGMA foreign_keys = ON; -TODO! + +DELETE FROM event WHERE first_seen < CAST(strftime('%s', date('now', '-30 day')) AS INT); ``` ### Delete Profile Events with No Recent Events From edf7af1573d0469a02ecb4d8f7d2274f9cc935f9 Mon Sep 17 00:00:00 2001 From: Iru Sensei Date: Sun, 23 Jul 2023 15:22:42 +0200 Subject: [PATCH 5/6] feat: verify config file exists and can be read --- src/main.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main.rs b/src/main.rs index 6e8994e..41a904b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,9 @@ use nostr_rs_relay::server::start_server; use std::sync::mpsc as syncmpsc; use std::sync::mpsc::{Receiver as MpscReceiver, Sender as MpscSender}; use std::thread; +use std::path::Path; +use std::fs; +use std::process; #[cfg(not(target_env = "msvc"))] use tikv_jemallocator::Jemalloc; use tracing::info; @@ -24,6 +27,31 @@ fn main() { // get config file name from args let config_file_arg = args.config; + // Quits if config file path is unreadable or does not exist + let config_file_path = config_file_arg.as_ref().map(|x| &**x).unwrap(); + let path = Path::new(&config_file_path); + + if !path.exists() { + eprintln!("Config file not found: {}", &config_file_path); + process::exit(1); + } + + if !path.is_file() { + eprintln!("Invalid config file path: {}", &config_file_path); + process::exit(1); + } + + if let Err(err) = fs::metadata(&path) { + eprintln!("Error while accessing file metadata: {}", err); + process::exit(1); + } + + if let Err(err) = fs::File::open(&path) { + eprintln!("Config file is not readable: {}", err); + process::exit(1); + } + + let mut _log_guard: Option = None; // configure settings from the config file (defaults to config.toml) From eab522dc397169048957441308fb0b86ef695c15 Mon Sep 17 00:00:00 2001 From: Greg Heartsfield Date: Sat, 29 Jul 2023 08:30:10 -0500 Subject: [PATCH 6/6] feat: warn or exit on config file parse errors The relay will now fail to start if an invalid config file is explicitly provided. If the file was read implicitly from the current directory, a warning will be provided, but the relay will still startup. --- src/bin/bulkloader.rs | 2 +- src/config.rs | 20 +++++++++------- src/main.rs | 53 +++++++++++++++++++++---------------------- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/bin/bulkloader.rs b/src/bin/bulkloader.rs index af276ea..77d9e74 100644 --- a/src/bin/bulkloader.rs +++ b/src/bin/bulkloader.rs @@ -20,7 +20,7 @@ pub fn main() -> Result<()> { let _trace_sub = tracing_subscriber::fmt::try_init(); println!("Nostr-rs-relay Bulk Loader"); // check for a database file, or create one. - let settings = config::Settings::new(&None); + let settings = config::Settings::new(&None)?; if !Path::new(&settings.database.data_directory).is_dir() { info!("Database directory does not exist"); return Err(Error::DatabaseDirError); diff --git a/src/config.rs b/src/config.rs index c5ead74..9222821 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,8 @@ //! Configuration file and settings management +use crate::payment::Processor; use config::{Config, ConfigError, File}; use serde::{Deserialize, Serialize}; use std::time::Duration; -use tracing::warn; - -use crate::payment::Processor; #[derive(Debug, Serialize, Deserialize, Clone)] #[allow(unused)] @@ -193,17 +191,23 @@ pub struct Settings { } impl Settings { - #[must_use] - pub fn new(config_file_name: &Option) -> Self { + pub fn new(config_file_name: &Option) -> Result { let default_settings = Self::default(); // attempt to construct settings with file let from_file = Self::new_from_default(&default_settings, config_file_name); match from_file { - Ok(f) => f, Err(e) => { - warn!("Error reading config file ({:?})", e); - default_settings + // pass up the parse error if the config file was specified, + // otherwise use the default config (with a warning). + if config_file_name.is_some() { + Err(e) + } else { + eprintln!("Error reading config file ({:?})", e); + eprintln!("WARNING: Default configuration settings will be used"); + Ok(default_settings) + } } + ok => ok, } } diff --git a/src/main.rs b/src/main.rs index 41a904b..ee92534 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,12 +4,12 @@ use console_subscriber::ConsoleLayer; use nostr_rs_relay::cli::CLIArgs; use nostr_rs_relay::config; use nostr_rs_relay::server::start_server; +use std::fs; +use std::path::Path; +use std::process; use std::sync::mpsc as syncmpsc; use std::sync::mpsc::{Receiver as MpscReceiver, Sender as MpscSender}; use std::thread; -use std::path::Path; -use std::fs; -use std::process; #[cfg(not(target_env = "msvc"))] use tikv_jemallocator::Jemalloc; use tracing::info; @@ -27,36 +27,35 @@ fn main() { // get config file name from args let config_file_arg = args.config; - // Quits if config file path is unreadable or does not exist - let config_file_path = config_file_arg.as_ref().map(|x| &**x).unwrap(); - let path = Path::new(&config_file_path); - - if !path.exists() { - eprintln!("Config file not found: {}", &config_file_path); - process::exit(1); + // Ensure the config file is readable if it was explicitly set + if let Some(config_path) = config_file_arg.as_ref() { + let path = Path::new(&config_path); + if !path.exists() { + eprintln!("Config file not found: {}", &config_path); + process::exit(1); + } + if !path.is_file() { + eprintln!("Invalid config file path: {}", &config_path); + process::exit(1); + } + if let Err(err) = fs::metadata(path) { + eprintln!("Error while accessing file metadata: {}", err); + process::exit(1); + } + if let Err(err) = fs::File::open(path) { + eprintln!("Config file is not readable: {}", err); + process::exit(1); + } } - if !path.is_file() { - eprintln!("Invalid config file path: {}", &config_file_path); - process::exit(1); - } - - if let Err(err) = fs::metadata(&path) { - eprintln!("Error while accessing file metadata: {}", err); - process::exit(1); - } - - if let Err(err) = fs::File::open(&path) { - eprintln!("Config file is not readable: {}", err); - process::exit(1); - } - - let mut _log_guard: Option = None; // configure settings from the config file (defaults to config.toml) // replace default settings with those read from the config file - let mut settings = config::Settings::new(&config_file_arg); + let mut settings = config::Settings::new(&config_file_arg).unwrap_or_else(|e| { + eprintln!("Error reading config file ({:?})", e); + process::exit(1); + }); // setup tracing if settings.diagnostics.tracing {