From 228e1a9c2d44c9670b62669bffe7e177a457de61 Mon Sep 17 00:00:00 2001 From: Asone Date: Fri, 19 May 2023 19:36:52 +0200 Subject: [PATCH 1/3] feat(cli): key validation with teests --- Cargo.lock | 2 + nostrss-cli/Cargo.toml | 3 +- nostrss-cli/src/commands/feed.rs | 5 +- nostrss-cli/src/commands/mod.rs | 6 +- nostrss-cli/src/commands/profile.rs | 74 +++++++++++++++++- nostrss-cli/src/input/formatter.rs | 7 ++ nostrss-cli/src/input/input.rs | 66 ++++++++++++++++ nostrss-core/src/grpc/feed_request.rs | 70 ++++++++--------- nostrss-core/src/grpc/grpc_service.rs | 83 ++++---------------- nostrss-core/src/grpc/profile_request.rs | 99 +++++++++++++++++++----- nostrss-core/src/main.rs | 2 +- nostrss-grpc/protos/nostrss.proto | 1 + nostrss-grpc/src/nostrss.rs | 76 ++++++++++++++++++ 13 files changed, 360 insertions(+), 134 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92eb842..997fb55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1574,11 +1574,13 @@ dependencies = [ name = "nostrss-cli" version = "0.4.0-alpha" dependencies = [ + "bech32", "clap", "cron", "dotenv", "log", "nostrss_grpc", + "secp256k1", "serde", "tabled", "tokio", diff --git a/nostrss-cli/Cargo.toml b/nostrss-cli/Cargo.toml index 3f44cda..95a3807 100644 --- a/nostrss-cli/Cargo.toml +++ b/nostrss-cli/Cargo.toml @@ -13,7 +13,8 @@ tonic = "0.9.2" tabled = "0.12.0" url = "2.3.1" cron = "0.12.0" - +secp256k1 = "0.27.0" +bech32 = "0.9.1" [dependencies.nostrss_grpc] path = "../nostrss-grpc" diff --git a/nostrss-cli/src/commands/feed.rs b/nostrss-cli/src/commands/feed.rs index 6fff7ec..373bf34 100644 --- a/nostrss-cli/src/commands/feed.rs +++ b/nostrss-cli/src/commands/feed.rs @@ -1,15 +1,12 @@ #![allow(dead_code)] -use std::str::FromStr; - use clap::{Parser, ValueEnum}; use nostrss_grpc::grpc::{ nostrss_grpc_client::NostrssGrpcClient, AddFeedRequest, DeleteFeedRequest, FeedInfoRequest, FeedItem, FeedsListRequest, }; -use tabled::{Table, Tabled}; +use tabled::Tabled; use tonic::{async_trait, transport::Channel}; -use url::Url; use crate::input::{formatter::InputFormatter, input::InputValidators}; diff --git a/nostrss-cli/src/commands/mod.rs b/nostrss-cli/src/commands/mod.rs index 62aa9d8..7fa29e0 100644 --- a/nostrss-cli/src/commands/mod.rs +++ b/nostrss-cli/src/commands/mod.rs @@ -14,14 +14,14 @@ pub trait CommandsHandler { _ = stdin().read_line(&mut data); match validator { - Some(validator) => match validator(data.clone()) { - true => data, + Some(validator) => match validator(data.clone().trim().to_string()) { + true => data.trim().to_string(), false => { println!("Invalid value provided."); self.get_input(label, Some(validator)) } }, - None => data, + None => data.trim().to_string(), } } diff --git a/nostrss-cli/src/commands/profile.rs b/nostrss-cli/src/commands/profile.rs index 3fc3fe2..4abd2c1 100644 --- a/nostrss-cli/src/commands/profile.rs +++ b/nostrss-cli/src/commands/profile.rs @@ -2,12 +2,14 @@ use clap::{Parser, ValueEnum}; use nostrss_grpc::grpc::{ - nostrss_grpc_client::NostrssGrpcClient, DeleteProfileRequest, ProfileInfoRequest, ProfileItem, - ProfilesListRequest, + nostrss_grpc_client::NostrssGrpcClient, AddProfileRequest, DeleteProfileRequest, + NewProfileItem, ProfileInfoRequest, ProfileItem, ProfilesListRequest, }; use tabled::{Table, Tabled}; use tonic::{async_trait, transport::Channel}; +use crate::input::{formatter::InputFormatter, input::InputValidators}; + use super::CommandsHandler; #[derive(Clone, PartialEq, Parser, Debug, ValueEnum)] @@ -148,7 +150,7 @@ impl CommandsHandler for ProfileCommandsHandler {} impl ProfileCommandsHandler { pub async fn handle(&mut self, action: ProfileActions) { match action { - ProfileActions::Add => self.add(), + ProfileActions::Add => self.add().await, ProfileActions::Delete => self.delete().await, ProfileActions::List => self.list().await, ProfileActions::Info => self.info().await, @@ -178,7 +180,71 @@ impl ProfileCommandsHandler { } } - fn add(&self) {} + async fn add(&mut self) { + println!("=== Add a profile ==="); + let id = self.get_input("Id: ", Some(InputValidators::required_input_validator)); + let private_key: String = self + .get_input( + "Private key (hex or bech32): ", + Some(InputValidators::key_validator), + ) + .trim() + .to_string(); + let name: Option = + InputFormatter::string_nullifier(self.get_input("(optional) Name: ", None)); + let relays = InputFormatter::input_to_vec( + self.get_input("(optional) Relays ids (separated with coma):", None), + ); + let display_name: Option = + InputFormatter::string_nullifier(self.get_input("(optional) Display name: ", None)); + let description: Option = + InputFormatter::string_nullifier(self.get_input("(optional) Description: ", None)); + let picture: Option = InputFormatter::string_nullifier( + self.get_input("(optional) Profile picture URL: ", None), + ); + let banner: Option = InputFormatter::string_nullifier( + self.get_input("(optional) Banner picture URL: ", None), + ); + let nip05: Option = + InputFormatter::string_nullifier(self.get_input("(optional) NIP-05: ", None)); + let lud16: Option = + InputFormatter::string_nullifier(self.get_input("(optional) Lud16: ", None)); + let pow_level: String = self.get_input("(optional) Publishing PoW level: ", None); + let pow_level = pow_level.parse().unwrap_or(0); + + let recommended_relays: Vec = InputFormatter::input_to_vec(self.get_input( + "(optional) Recommended relays ids (seperated with coma): ", + None, + )); + + let request = tonic::Request::new(AddProfileRequest { + profile: NewProfileItem { + id, + private_key, + name, + relays, + display_name, + description, + picture, + banner, + nip05, + lud16, + pow_level: Some(pow_level), + recommended_relays, + }, + }); + + let response = self.client.add_profile(request).await; + + match response { + Ok(_) => { + println!("Profile successfuly added"); + } + Err(e) => { + println!("Error: {}: {}", e.code(), e.message()); + } + } + } async fn delete(&mut self) { let id = self.get_input("Id: ", None); diff --git a/nostrss-cli/src/input/formatter.rs b/nostrss-cli/src/input/formatter.rs index 5701f35..611bce3 100644 --- a/nostrss-cli/src/input/formatter.rs +++ b/nostrss-cli/src/input/formatter.rs @@ -4,6 +4,13 @@ impl InputFormatter { pub fn input_to_vec(value: String) -> Vec { value.split(',').map(|e| e.trim().to_string()).collect() } + + pub fn string_nullifier(value: String) -> Option { + match value.len() > 0 { + true => Some(value.trim().to_string()), + false => None, + } + } } #[cfg(test)] diff --git a/nostrss-cli/src/input/input.rs b/nostrss-cli/src/input/input.rs index 9d42135..144903f 100644 --- a/nostrss-cli/src/input/input.rs +++ b/nostrss-cli/src/input/input.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use bech32::FromBase32; use url::Url; pub struct InputValidators {} @@ -30,6 +31,38 @@ impl InputValidators { Err(_) => false, } } + + pub fn key_validator(value: String) -> bool { + let decoded = bech32::decode(value.trim()); + + match decoded { + Ok(result) => { + if let Ok(bytes) = Vec::::from_base32(&result.1) { + // Check if the decoded bytes have the expected length + if bytes.len() != 32 { + return false; + } + } + } + Err(_) => { + let key_bytes = value.trim().as_bytes(); + + // Validate key length + if key_bytes.len() != 64 { + return false; + } + + // Validate key contains only hexadecimal characters + for &byte in key_bytes.iter() { + if !byte.is_ascii_hexdigit() { + return false; + } + } + } + }; + + true + } } #[cfg(test)] @@ -79,4 +112,37 @@ mod tests { assert_eq!(result, false); } + + #[test] + fn key_validator_test() { + let value = "6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef012345".to_string(); + + let result = InputValidators::key_validator(value); + + assert_eq!(result, true); + + let value = "6789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".to_string(); + + let result = InputValidators::key_validator(value); + + assert_eq!(result, false); + + let value = "6789abcdef0123456789abcdef0123456789abcdef0123456789abkdef012345".to_string(); + + let result = InputValidators::key_validator(value); + + assert_eq!(result, false); + + let value = "nsec14uuscmj9ac0f3lqfq33cuq6mu8q7sscvpyyhsjn5r8q9w5pdafgq0qrj8a".to_string(); + + let result = InputValidators::key_validator(value); + + assert_eq!(result, true); + + let value = "nsec14uuscmj9ac0f3lqfq33cuq6mu8q7sscvpyyhsjn5r8q9w5pdafgq0qrj8d".to_string(); + + let result = InputValidators::key_validator(value); + + assert_eq!(result, false); + } } diff --git a/nostrss-core/src/grpc/feed_request.rs b/nostrss-core/src/grpc/feed_request.rs index 2fa236d..232eaaf 100644 --- a/nostrss-core/src/grpc/feed_request.rs +++ b/nostrss-core/src/grpc/feed_request.rs @@ -2,7 +2,7 @@ use nostrss_grpc::grpc::{ self, AddFeedRequest, AddFeedResponse, DeleteFeedRequest, DeleteFeedResponse, FeedInfoRequest, FeedInfoResponse, FeedItem, FeedsListRequest, FeedsListResponse, }; -use std::{ops::Index, sync::Arc}; +use std::sync::Arc; use tokio::sync::{Mutex, MutexGuard}; use tonic::{Code, Request, Response, Status}; @@ -25,6 +25,40 @@ impl FeedRequestHandler { Ok(Response::new(grpc::FeedsListResponse { feeds })) } + pub async fn feed_info( + app: MutexGuard<'_, App>, + request: Request, + ) -> Result, Status> { + let id = &request.into_inner().id; + match app.rss.feeds.clone().into_iter().find(|f| &f.id == id) { + Some(feed) => Ok(Response::new(FeedInfoResponse { + feed: FeedItem::from(feed), + })), + None => { + return Err(Status::new(Code::NotFound, "Feed not found")); + } + } + } + + pub async fn add_feed( + mut app: MutexGuard<'_, App>, + request: Request, + ) -> Result, Status> { + let data = request.into_inner(); + let feed = Feed::from(data); + let map = Arc::new(Mutex::new(app.feeds_map.clone())); + let clients = Arc::new(Mutex::new(app.clients.clone())); + + app.rss.feeds.push(feed.clone()); + + let job = schedule(feed.schedule.clone().as_str(), feed.clone(), map, clients).await; + + _ = app.rss.feeds_jobs.insert(feed.id.clone(), job.guid()); + _ = app.rss.scheduler.add(job).await; + + Ok(Response::new(AddFeedResponse {})) + } + // Interface to delete a feed on instance pub async fn delete_feed( mut app: MutexGuard<'_, App>, @@ -56,40 +90,6 @@ impl FeedRequestHandler { _ = app.scheduler.remove(job_uuid.unwrap()).await; Ok(Response::new(grpc::DeleteFeedResponse {})) } - - pub async fn add_feed( - mut app: MutexGuard<'_, App>, - request: Request, - ) -> Result, Status> { - let data = request.into_inner(); - let feed = Feed::from(data); - let map = Arc::new(Mutex::new(app.feeds_map.clone())); - let clients = Arc::new(Mutex::new(app.clients.clone())); - - app.rss.feeds.push(feed.clone()); - - let job = schedule(feed.schedule.clone().as_str(), feed.clone(), map, clients).await; - - _ = app.rss.feeds_jobs.insert(feed.id.clone(), job.guid()); - _ = app.rss.scheduler.add(job).await; - - Ok(Response::new(AddFeedResponse {})) - } - - pub async fn feed_info( - app: MutexGuard<'_, App>, - request: Request, - ) -> Result, Status> { - let id = &request.into_inner().id; - match app.rss.feeds.clone().into_iter().find(|f| &f.id == id) { - Some(feed) => Ok(Response::new(FeedInfoResponse { - feed: FeedItem::from(feed), - })), - None => { - return Err(Status::new(Code::NotFound, "Feed not found")); - } - } - } } #[cfg(test)] diff --git a/nostrss-core/src/grpc/grpc_service.rs b/nostrss-core/src/grpc/grpc_service.rs index 3fd199c..8fb4508 100644 --- a/nostrss-core/src/grpc/grpc_service.rs +++ b/nostrss-core/src/grpc/grpc_service.rs @@ -9,11 +9,12 @@ use nostr_sdk::{ use crate::rss::config::Feed; use nostrss_grpc::grpc::{ - self, nostrss_grpc_server::NostrssGrpc, AddFeedRequest, AddFeedResponse, DeleteFeedRequest, - DeleteFeedResponse, DeleteProfileRequest, DeleteProfileResponse, FeedInfoRequest, - FeedInfoResponse, FeedItem, FeedsListRequest, FeedsListResponse, ProfileInfoRequest, - ProfileInfoResponse, ProfileItem, ProfilesListRequest, ProfilesListResponse, StartJobRequest, - StartJobResponse, StateRequest, StateResponse, StopJobRequest, StopJobResponse, + self, nostrss_grpc_server::NostrssGrpc, AddFeedRequest, AddFeedResponse, AddProfileRequest, + AddProfileResponse, DeleteFeedRequest, DeleteFeedResponse, DeleteProfileRequest, + DeleteProfileResponse, FeedInfoRequest, FeedInfoResponse, FeedItem, FeedsListRequest, + FeedsListResponse, ProfileInfoRequest, ProfileInfoResponse, ProfileItem, ProfilesListRequest, + ProfilesListResponse, StartJobRequest, StartJobResponse, StateRequest, StateResponse, + StopJobRequest, StopJobResponse, }; use reqwest::Url; use tokio::sync::{Mutex, MutexGuard}; @@ -175,6 +176,14 @@ impl NostrssGrpc for NostrssServerService { ProfileRequestHandler::profile_info(self.get_app_lock().await, request).await } + // Interface to delete a profile on instance + async fn add_profile( + &self, + request: Request, + ) -> Result, Status> { + ProfileRequestHandler::add_profile(self.get_app_lock().await, request).await + } + // Interface to delete a profile on instance async fn delete_profile( &self, @@ -210,72 +219,10 @@ impl NostrssGrpc for NostrssServerService { #[cfg(test)] mod tests { - use std::collections::HashMap; use super::*; - use crate::{ - app::app::AppConfig, - nostr::nostr::NostrInstance, - rss::{ - config::{Feed, RssConfig}, - rss::RssInstance, - }, - scheduler::scheduler::schedule, - }; - use dotenv::from_filename; + use crate::rss::config::Feed; use nostrss_grpc::grpc::AddFeedRequest; - async fn mock_app() -> App { - from_filename(".env.test").ok(); - let rss_path = Some("./src/fixtures/rss.yaml".to_string()); - let rss_config = RssConfig::new(rss_path); - - let rss = RssInstance::new(rss_config).await; - - let default_profile = Profile { - ..Default::default() - }; - - let test_profile = Profile { - id: "test".to_string(), - ..Default::default() - }; - - let mut profiles = HashMap::new(); - - profiles.insert(default_profile.id.clone(), default_profile); - profiles.insert(test_profile.id.clone(), test_profile); - - let mut clients = HashMap::new(); - - for profile in profiles.clone() { - let client = NostrInstance::new(profile.1).await; - clients.insert(profile.0.clone(), client); - } - - let scheduler = tokio_cron_scheduler::JobScheduler::new().await.unwrap(); - let mut app = App { - rss, - scheduler: Arc::new(scheduler), - clients, - profiles: profiles, - feeds_jobs: HashMap::new(), - feeds_map: HashMap::new(), - }; - - for feed in app.rss.feeds.clone() { - let job = schedule( - feed.clone().schedule.as_str(), - feed.clone(), - Arc::new(Mutex::new(app.feeds_map.clone())), - Arc::new(Mutex::new(app.clients.clone())), - ) - .await; - - _ = &app.rss.feeds_jobs.insert(feed.id, job.guid()); - } - - app - } #[test] fn feed_from_add_feed_request_test() { diff --git a/nostrss-core/src/grpc/profile_request.rs b/nostrss-core/src/grpc/profile_request.rs index 88e3d26..aa54c4d 100644 --- a/nostrss-core/src/grpc/profile_request.rs +++ b/nostrss-core/src/grpc/profile_request.rs @@ -1,11 +1,37 @@ use nostrss_grpc::grpc::{ - self, DeleteProfileRequest, DeleteProfileResponse, ProfileInfoRequest, ProfileInfoResponse, - ProfileItem, ProfilesListRequest, ProfilesListResponse, + self, AddProfileRequest, AddProfileResponse, DeleteProfileRequest, DeleteProfileResponse, + NewProfileItem, ProfileInfoRequest, ProfileInfoResponse, ProfileItem, ProfilesListRequest, + ProfilesListResponse, }; use tokio::sync::MutexGuard; use tonic::{Code, Request, Response, Status}; -use crate::app::app::App; +use crate::{app::app::App, nostr::nostr::NostrInstance, profiles::config::Profile}; + +impl From for Profile { + fn from(value: NewProfileItem) -> Self { + let pow_level = match value.pow_level { + Some(value) => value as u8, + None => 0, + }; + + Self { + id: value.id, + private_key: value.private_key, + relays: Vec::new(), + about: value.description.clone(), + name: value.name, + display_name: value.display_name, + description: value.description, + picture: value.picture, + banner: value.banner, + nip05: value.nip05, + lud16: value.lud16, + pow_level: pow_level, + recommended_relays: Some(value.recommended_relays), + } + } +} pub struct ProfileRequestHandler {} @@ -24,21 +50,6 @@ impl ProfileRequestHandler { Ok(Response::new(grpc::ProfilesListResponse { profiles })) } - // Interface to delete a profile on instance - pub async fn delete_profile( - mut app: MutexGuard<'_, App>, - request: Request, - ) -> Result, Status> { - let profile_id = &request.into_inner().id; - let client = app.clients.remove(profile_id.trim()); - - if client.is_none() { - return Err(Status::new(Code::NotFound, "No profile with that id found")); - } - - Ok(Response::new(grpc::DeleteProfileResponse {})) - } - // Interface to retrieve the detailed configuration of a single profile on instance pub async fn profile_info( app: MutexGuard<'_, App>, @@ -54,6 +65,36 @@ impl ProfileRequestHandler { } } } + + pub async fn add_profile( + mut app: MutexGuard<'_, App>, + request: Request, + ) -> Result, Status> { + let new_profile_item = request.into_inner().profile; + + let profile = Profile::from(new_profile_item); + + let client = NostrInstance::new(profile.clone()).await; + app.profiles.insert(profile.id.clone(), profile.clone()); + app.clients.insert(profile.id.clone(), client); + + Ok(Response::new(grpc::AddProfileResponse {})) + } + + // Interface to delete a profile on instance + pub async fn delete_profile( + mut app: MutexGuard<'_, App>, + request: Request, + ) -> Result, Status> { + let profile_id = &request.into_inner().id; + let client = app.clients.remove(profile_id.trim()); + + if client.is_none() { + return Err(Status::new(Code::NotFound, "No profile with that id found")); + } + + Ok(Response::new(grpc::DeleteProfileResponse {})) + } } #[cfg(test)] @@ -63,6 +104,7 @@ mod tests { use std::sync::Arc; use crate::grpc::grpctest_utils::mock_app; + use dotenv::from_filename; use nostrss_grpc::grpc::{AddProfileRequest, NewProfileItem}; use tokio::sync::Mutex; use tonic::Request; @@ -74,11 +116,32 @@ mod tests { let add_profile_request = AddProfileRequest { profile: NewProfileItem { id: "added".to_string(), + private_key: "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" + .to_string(), ..Default::default() }, }; let request = Request::new(add_profile_request); + + let profile_add_request_result = { + let app_lock = app.lock().await; + ProfileRequestHandler::add_profile(app_lock, request).await + }; + + assert_eq!(profile_add_request_result.is_ok(), true); + + let profiles_list_request = ProfilesListRequest {}; + let request = Request::new(profiles_list_request); + + let profiles_list_request_result = { + let app_lock = app.lock().await; + ProfileRequestHandler::profiles_list(app_lock, request).await + }; + + let response = profiles_list_request_result.unwrap().into_inner(); + + assert_eq!(response.profiles.len(), 3); } #[tokio::test] diff --git a/nostrss-core/src/main.rs b/nostrss-core/src/main.rs index 2afad05..eae3a3d 100644 --- a/nostrss-core/src/main.rs +++ b/nostrss-core/src/main.rs @@ -91,7 +91,7 @@ async fn main() -> Result<()> { // need to be able to lock it again later. _ = { let app_lock = global_app_arc.lock().await; - _ = &app_lock.rss.scheduler.start().await; + // _ = &app_lock.rss.scheduler.start().await; }; // GRPC server diff --git a/nostrss-grpc/protos/nostrss.proto b/nostrss-grpc/protos/nostrss.proto index 3ef23a9..1caf3c0 100644 --- a/nostrss-grpc/protos/nostrss.proto +++ b/nostrss-grpc/protos/nostrss.proto @@ -8,6 +8,7 @@ service NostrssGRPC { rpc ProfilesList (ProfilesListRequest) returns (ProfilesListResponse); rpc ProfileInfo (ProfileInfoRequest) returns (ProfileInfoResponse); rpc DeleteProfile (DeleteProfileRequest) returns (DeleteProfileResponse); + rpc AddProfile (AddProfileRequest) returns (AddProfileResponse); rpc FeedsList (FeedsListRequest) returns (FeedsListResponse); rpc FeedInfo (FeedInfoRequest) returns (FeedInfoResponse); diff --git a/nostrss-grpc/src/nostrss.rs b/nostrss-grpc/src/nostrss.rs index b603f3f..f375a4e 100644 --- a/nostrss-grpc/src/nostrss.rs +++ b/nostrss-grpc/src/nostrss.rs @@ -385,6 +385,31 @@ pub mod nostrss_grpc_client { .insert(GrpcMethod::new("nostrss.NostrssGRPC", "DeleteProfile")); self.inner.unary(req, path, codec).await } + pub async fn add_profile( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/nostrss.NostrssGRPC/AddProfile", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("nostrss.NostrssGRPC", "AddProfile")); + self.inner.unary(req, path, codec).await + } pub async fn feeds_list( &mut self, request: impl tonic::IntoRequest, @@ -569,6 +594,13 @@ pub mod nostrss_grpc_server { tonic::Response, tonic::Status, >; + async fn add_profile( + &self, + request: tonic::Request, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + >; async fn feeds_list( &self, request: tonic::Request, @@ -865,6 +897,50 @@ pub mod nostrss_grpc_server { }; Box::pin(fut) } + "/nostrss.NostrssGRPC/AddProfile" => { + #[allow(non_camel_case_types)] + struct AddProfileSvc(pub Arc); + impl< + T: NostrssGrpc, + > tonic::server::UnaryService + for AddProfileSvc { + type Response = super::AddProfileResponse; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { (*inner).add_profile(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = AddProfileSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/nostrss.NostrssGRPC/FeedsList" => { #[allow(non_camel_case_types)] struct FeedsListSvc(pub Arc); From cb30be5129be64430070f133d6bc9f2abcb489d3 Mon Sep 17 00:00:00 2001 From: Asone Date: Fri, 19 May 2023 19:39:35 +0200 Subject: [PATCH 2/3] fix(main): restore main scheduler start command --- nostrss-core/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nostrss-core/src/main.rs b/nostrss-core/src/main.rs index eae3a3d..2afad05 100644 --- a/nostrss-core/src/main.rs +++ b/nostrss-core/src/main.rs @@ -91,7 +91,7 @@ async fn main() -> Result<()> { // need to be able to lock it again later. _ = { let app_lock = global_app_arc.lock().await; - // _ = &app_lock.rss.scheduler.start().await; + _ = &app_lock.rss.scheduler.start().await; }; // GRPC server From fd5f1fa38ec48016586e600a0a68728df77dacf2 Mon Sep 17 00:00:00 2001 From: Asone Date: Fri, 19 May 2023 20:20:51 +0200 Subject: [PATCH 3/3] chore(doc): update cli doc according last features implementations --- nostrss-cli/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nostrss-cli/README.md b/nostrss-cli/README.md index db3ff01..bf85ba6 100644 --- a/nostrss-cli/README.md +++ b/nostrss-cli/README.md @@ -16,7 +16,7 @@ Please, do note that any operation performed through CLI will be currently lost | Command | Description | |-|-| | nostrss-cli profile list | Lists the profiles | -| nostrss-cli profile add | Add a new profile (not implemented yet) | +| nostrss-cli profile add | Add a new profile | | nostrss-cli profile delete | Remove a profile | | nostrss-cli profile info | Get info of a specific profile | @@ -25,6 +25,6 @@ Please, do note that any operation performed through CLI will be currently lost | Command | Description | |-|-| | nostrss-cli feed list | Lists the feeds | -| nostrss-cli feed add | Add a new feed (not implemented yet) | +| nostrss-cli feed add | Add a new feed | | nostrss-cli feed delete | Remove a feed | | nostrss-cli feed info | Get info of a specific feed |