From acf8eadf4707b607ce0d18e99dcb82db5e53665c Mon Sep 17 00:00:00 2001 From: Mahesh Bansod Date: Wed, 3 Nov 2021 12:41:38 +0530 Subject: [PATCH] Switched CLI to use single session + made it work with the new restructured api --- Cargo.lock | 193 +++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 +- cli/src/error.rs | 6 ++ cli/src/main.rs | 156 ++++++++++++++++++-------------------- cli/src/utils.rs | 70 +---------------- 5 files changed, 277 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9178a55..6980452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,26 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -20,6 +40,15 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -65,6 +94,35 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "cli" +version = "0.1.0" +dependencies = [ + "rpassword", + "serde", + "serde_json", + "shellexpand", + "socialvoid", + "socialvoid_rawclient", + "structopt", + "tokio", +] + [[package]] name = "core-foundation" version = "0.9.1" @@ -99,6 +157,27 @@ dependencies = [ "generic-array", ] +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "encoding_rs" version = "0.8.28" @@ -300,6 +379,15 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.19" @@ -692,6 +780,30 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -818,6 +930,16 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -863,6 +985,16 @@ dependencies = [ "winreg", ] +[[package]] +name = "rpassword" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "rust-crypto" version = "0.2.36" @@ -993,6 +1125,15 @@ dependencies = [ "sha2", ] +[[package]] +name = "shellexpand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83bdb7831b2d85ddf4a7b148aa19d0587eddbe8671a436b7bd1182eaad0f2829" +dependencies = [ + "dirs-next", +] + [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -1019,6 +1160,7 @@ name = "socialvoid" version = "0.1.0" dependencies = [ "base32", + "bincode", "byteorder", "pad", "rand 0.8.4", @@ -1065,6 +1207,36 @@ dependencies = [ "winapi", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "structopt" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +dependencies = [ + "clap", + "lazy_static", + "structopt-derive", +] + +[[package]] +name = "structopt-derive" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "syn" version = "1.0.76" @@ -1090,6 +1262,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "time" version = "0.1.43" @@ -1232,6 +1413,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" + [[package]] name = "unicode-width" version = "0.1.9" @@ -1262,6 +1449,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.3" diff --git a/Cargo.toml b/Cargo.toml index 428a60d..6821567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,6 @@ members = [ "client", "types", "rawclient", - "jsonrpc2-client" + "jsonrpc2-client", + "cli" ] diff --git a/cli/src/error.rs b/cli/src/error.rs index ea01aab..2c572e8 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -9,6 +9,12 @@ impl std::convert::From for MyFriendlyError { } } +impl std::convert::From for MyFriendlyError { + fn from(err: socialvoid_rawclient::Error) -> Self { + Self(err.into()) + } +} + impl std::fmt::Display for MyFriendlyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.0 { diff --git a/cli/src/main.rs b/cli/src/main.rs index 5623b1e..2a44eb9 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,5 +1,6 @@ use socialvoid as sv_client; use socialvoid::session::RegisterRequest; +use socialvoid::session::SessionHolder; use structopt::StructOpt; mod error; @@ -13,34 +14,53 @@ use error::MyFriendlyError; async fn main() { let args = Cli::from_args(); let config = load_config(); - let mut sv = sv_client::new_empty_client(); - sv.reset_cdn_url().await.unwrap(); //set proper CDN url - let mut current_session: usize = std::env::var("SV_CURRENT_SESSION") - .unwrap_or_else(|_| config.current_session.to_string()) - .parse() - .expect("The environment variable should SV_CURRENT_SESSION should contain an integer >=0"); + + // initialize sv client - + // If session_file has a valid session holder, then use that session otherwise try to create a new one. + // let sv = match Socialvoid::load_session_or_default(config.session_file).await { + // }; + let sv = match std::fs::read(&config.session_file) { + Ok(bytes) => match sv_client::new(SessionHolder::deserialize(bytes)).await { + Ok(client) => client, + Err(_) => panic!( + "The session file may be corrupt. try deleting it to have a new session created." + ), + }, + Err(err) => { + println!( + "There was a problem while reading the session file.\n{}", + err + ); + // TODO: give the user the option to either quit or to change the path of the session file + // also look into taking the path of the config and session from the command line + println!("Creating new session."); + match sv_client::new_with_defaults().await { + Ok(client) => client, + Err(err) => panic!( + "There was an error while trying to establish a new session.\n{}", + MyFriendlyError::from(err) + ), + } + } + }; if let Some(cmd) = args.commands { match cmd { SocialVoidCommand::Login { username } => { - setup_sessions(&config, &mut sv, &mut current_session).await; + if sv.session.authenticated() { + panic!( + "Already logged in. You should log out before logging into a new account." + ) + } + let username = if let Some(username) = username { username } else { prompt_stdin("Your username on [network url here?]: ") }; - let sk = if sv.is_authenticated().unwrap() { - sv.new_session() - .await - .expect("Couldn't create a new session.") - } else { - current_session - }; - current_session = sk; - sv.set_current_session(current_session).unwrap(); let password = prompt_password("Enter password: "); //TODO: add OTP support - match sv.authenticate_user(username, password, None).await { + match sv.session.authenticate_user(username, password, None).await { Err(err) => { println!( "Couldn't authenticate the user.\n{}", @@ -53,13 +73,10 @@ async fn main() { } } SocialVoidCommand::Register => { - setup_sessions(&config, &mut sv, &mut current_session).await; - if sv.is_authenticated().unwrap() { - current_session = sv - .new_session() - .await - .expect("Couldn't create a new session"); - sv.set_current_session(current_session).unwrap(); + if sv.session.authenticated() { + panic!( + "Already logged in. You should log out before logging into a new account." + ) } let first_name = prompt_stdin("First name: "); let last_name = { @@ -84,9 +101,11 @@ async fn main() { } }; let tos = sv + .help .get_terms_of_service() .await .expect("Couldn't get the terms of service."); + //TODO: find a better way to show this println!("{}", tos.get_plain_text()); let accept_tos = prompt_stdin("Have you read these terms of service and accept them?[y/N] ") @@ -94,8 +113,9 @@ async fn main() { .next(); if let Some(accept_tos) = accept_tos { if accept_tos == 'y' || accept_tos == 'Y' { - sv.accept_tos(tos).unwrap(); + sv.session.accept_terms_of_service(tos); match sv + .session .register(RegisterRequest { username, password, @@ -118,66 +138,33 @@ async fn main() { println!("You need to accept the terms of service to register to SocialVoid"); } } - SocialVoidCommand::Config { field, value } => { - match field { - ConfigField::Sessions => { - setup_sessions(&config, &mut sv, &mut current_session).await; - //Gets the sessions if value is none, other wise sets to a session key that is valid - if let Some(sesh_key) = value { - if let Ok(sesh_key) = sesh_key.parse::() { - match sv.set_current_session(sesh_key) { - Ok(_) => { - current_session = sesh_key; - println!("Changed session to {}\n", sesh_key); - } - Err(err) => println!("{}", MyFriendlyError::from(err)), - } - } else { - println!("Enter the session index for it to switch to a session"); - println!("There are {} sessions.", sv.sessions.len()); + SocialVoidCommand::Config { .. } => { + println!("WIP"); + } + SocialVoidCommand::GetMe => match sv.network.get_me().await { + Ok(response) => println!("{:#?}", response), + Err(err) => println!("{}", MyFriendlyError::from(err)), + }, + SocialVoidCommand::SetProfile { field, value } => match field { + ProfileField::Pic => { + if let Some(filepath) = value { + match sv.account.set_profile_picture(filepath).await { + Ok(doc) => { + println!("Profile picture updated successfully.\n{:?}", doc); + } + Err(err) => { + println!( + "An error occurred while setting the profile picture.\n{}", + MyFriendlyError::from(err) + ); } - } else { - println!( - "There are {} session(s).\nCurrent session: {}", - sv.sessions.len(), - current_session - ); } + } else { + println!("You need to specify the path to the picture to upload"); } } - } - SocialVoidCommand::GetMe => { - setup_sessions(&config, &mut sv, &mut current_session).await; - - match sv.get_me().await { - Ok(response) => println!("{:#?}", response), - Err(err) => println!("{}", MyFriendlyError::from(err)), - } - } - SocialVoidCommand::SetProfile { field, value } => { - setup_sessions(&config, &mut sv, &mut current_session).await; - match field { - ProfileField::Pic => { - if let Some(filepath) = value { - match sv.set_profile_picture(filepath).await { - Ok(doc) => { - println!("Profile picture updated successfully.\n{:?}", doc); - } - Err(err) => { - println!( - "An error occurred while setting the profile picture.\n{}", - MyFriendlyError::from(err) - ); - } - } - } else { - println!("You need to specify the path to the picture to upload"); - } - } - } - } + }, SocialVoidCommand::GetProfile { field } => { - setup_sessions(&config, &mut sv, &mut current_session).await; match field { Some(field) => match field { ProfileField::Pic => { @@ -188,7 +175,7 @@ async fn main() { }, None => { // The full profile - match sv.get_my_profile().await { + match sv.network.get_profile(None).await { Ok(profile) => println!("{}", profile), Err(err) => println!( "An error occurred while trying to get the profile.\n{}", @@ -202,9 +189,10 @@ async fn main() { } } - sv.save_sessions(&config.sessions_file) - .expect("Couldn't save the sessions"); - save_config(current_session, &config).expect("Couldn't save the config"); + // sv.save_session(&config.sessions_file) + // .expect("Couldn't save the session"); + std::fs::write(&config.session_file, sv.session.serialize()).unwrap(); + save_config(&config).expect("Couldn't save the config"); } #[derive(Debug, StructOpt)] diff --git a/cli/src/utils.rs b/cli/src/utils.rs index 79b475b..3d63e79 100644 --- a/cli/src/utils.rs +++ b/cli/src/utils.rs @@ -1,72 +1,12 @@ use rpassword::read_password; use serde::{Deserialize, Serialize}; -use socialvoid as sv_client; -use socialvoid::SocialvoidError; -use socialvoid_rawclient::{AuthenticationError, ErrorKind}; use std::io::{stdin, stdout, Write}; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Config { - pub sessions_file: String, + pub session_file: String, pub base_path: String, pub config_path: String, - pub current_session: usize, -} - -//document this function -pub async fn setup_sessions(config: &Config, sv: &mut sv_client::Client, sesh_key: &mut usize) { - if let Err(err) = sv.load_sessions(&config.sessions_file) { - if err.kind() == std::io::ErrorKind::NotFound { - sv.new_session() - .await - .expect("Couldn't create a new session."); - } else { - panic!("Couldn't load sessions from the config\n{:?}", err); - } - } - - if sv.sessions.is_empty() { - sv.new_session() - .await - .expect("Couldn't create a new session."); - } - - if sv.sessions.len() <= *sesh_key { - *sesh_key = sv.sessions.len() - 1; - } - - sv.set_current_session(*sesh_key).unwrap(); - - match sv.get_session().await { - Ok(_) => {} - Err(err) => match err { - SocialvoidError::RawClient(err) => match err.kind { - ErrorKind::Authentication(AuthenticationError::SessionExpired) - | ErrorKind::Authentication(AuthenticationError::SessionNotFound) => { - println!("This session either didn't exist or is expired.\nDeleting it and creating a new one."); - sv.delete_session().unwrap(); - let new_sesh_key = sv - .new_session() - .await - .expect("Couldn't create a new session."); - sv.set_current_session(new_sesh_key).unwrap(); - *sesh_key = new_sesh_key; - } - _ => { - panic!( - "Couldn't `get` session. The session is probably corrupt. -Either delete the sessions file or fix the corrupt session." - ); - } - }, - _ => { - panic!( - "Couldn't `get` session. The session is probably corrupt. -Either delete the sessions file or fix the corrupt session." - ); - } - }, - } } pub fn load_config() -> Config { @@ -89,17 +29,15 @@ pub fn load_config() -> Config { } }, Err(_err) => Config { - sessions_file: format!("{}/sessions", base_path), + session_file: format!("{}/session", base_path), base_path, config_path, - current_session: 0, }, } } -pub fn save_config(sesh_key: usize, config: &Config) -> Result<(), std::io::Error> { - let mut config = config.clone(); - config.current_session = sesh_key; +pub fn save_config(config: &Config) -> Result<(), std::io::Error> { + // let mut config = config.clone(); std::fs::write(&config.config_path, serde_json::to_string(&config).unwrap())?; Ok(()) }