From 3fb0033d7755d643613ac7855d7d109774ce1276 Mon Sep 17 00:00:00 2001 From: Tilo-K Date: Mon, 23 Oct 2023 19:47:57 +0200 Subject: [PATCH] Fixed creating and deleting --- Cargo.lock | 22 +++++++++++ Cargo.toml | 3 +- src/main.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++--- src/pastebin.rs | 81 ++++++++++++++++++++++++++----------- 4 files changed, 180 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31f7e8f..5043242 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -634,6 +634,7 @@ dependencies = [ "clap", "home", "reqwest", + "rpassword", "tokio", ] @@ -726,6 +727,27 @@ dependencies = [ "winreg", ] +[[package]] +name = "rpassword" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" +dependencies = [ + "libc", + "rtoolbox", + "winapi", +] + +[[package]] +name = "rtoolbox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index 6490d5a..e09be79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ edition = "2021" [dependencies] clap = { version = "4.4.6", features = ["derive"] } home = "0.5.5" -reqwest = "0.11.22" +reqwest = { version = "0.11.22", features = ["json"] } +rpassword = "7.2.0" tokio = { version = "1.33.0", features = ["full"] } diff --git a/src/main.rs b/src/main.rs index 00bfe8d..1b69bc6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,14 @@ use clap::{Parser, Subcommand}; +use rpassword::read_password; use std::fs; use std::io; +use std::io::Write; +use std::path::PathBuf; use std::sync::Mutex; - mod pastebin; static API_KEY: Mutex = Mutex::new(String::new()); +static USER_KEY: Mutex = Mutex::new(String::new()); fn get_api_key() { let home_dir = match home::home_dir() { @@ -22,7 +25,9 @@ fn get_api_key() { if key == "" { let mut input = String::new(); - println!("Pastebin API key: "); + print!("Pastebin API key: "); + io::stdout().lock().flush().unwrap(); + io::stdin() .read_line(&mut input) .expect("Error reading API_KEY"); @@ -37,6 +42,45 @@ fn get_api_key() { API_KEY.lock().unwrap().push_str(&key); } +async fn get_user_key() { + let home_dir = match home::home_dir() { + Some(path) => path, + None => panic!("Impossible to get your home dir!"), + }; + + let key_file = home_dir.join(".pastebin_userkey"); + let key = match fs::read_to_string(&key_file) { + Ok(d) => d, + Err(_) => "".to_owned(), + }; + + if key == "" { + let mut username = String::new(); + let mut password = String::new(); + + print!("Username: "); + io::stdout().lock().flush().unwrap(); + io::stdin() + .read_line(&mut username) + .expect("Error reading Username"); + + print!("Password: "); + io::stdout().lock().flush().unwrap(); + password = read_password().unwrap(); + + let key = pastebin::get_user_key(&API_KEY.lock().unwrap(), username, password) + .await + .unwrap(); + USER_KEY.lock().unwrap().push_str(&key); + + fs::write(key_file, key).expect("Error writing API KEY"); + + return; + } + + USER_KEY.lock().unwrap().push_str(&key); +} + #[derive(Parser, Debug, Clone)] #[command(author, version, about, long_about= None)] struct Cli { @@ -61,15 +105,62 @@ enum Action { #[tokio::main] async fn main() { get_api_key(); + get_user_key().await; let args = Cli::parse(); match args.action { - Action::Create { file_path } => todo!(), - Action::Delete { paste_id } => todo!(), + Action::Create { file_path } => create(file_path).await, + Action::Delete { paste_id } => delete(paste_id).await, Action::Edit { paste_id, file_path, - } => todo!(), - } + } => edit(paste_id, file_path).await, + }; +} + +async fn create(file_path: PathBuf) { + let file_name = file_path.file_name().unwrap().to_str().unwrap(); + let file_content = fs::read_to_string(&file_path).unwrap(); + + let paste_id = pastebin::create_paste( + &API_KEY.lock().unwrap(), + &USER_KEY.lock().unwrap(), + file_name.to_owned(), + file_content, + None, + ) + .await + .unwrap(); + + println!("{}", paste_id); +} + +async fn delete(paste_id: String) { + let resp = pastebin::delete_paste( + &API_KEY.lock().unwrap(), + &USER_KEY.lock().unwrap(), + paste_id, + ) + .await + .unwrap(); + + println!("{}", resp); +} + +async fn edit(paste_id: String, file_path: PathBuf) { + let file_name = file_path.file_name().unwrap().to_str().unwrap(); + let file_content = fs::read_to_string(&file_path).unwrap(); + + let resp = pastebin::create_paste( + &API_KEY.lock().unwrap(), + &USER_KEY.lock().unwrap(), + file_name.to_owned(), + file_content, + Some(paste_id), + ) + .await + .unwrap(); + + println!("{}", resp); } diff --git a/src/pastebin.rs b/src/pastebin.rs index e2bbd9f..576b53d 100644 --- a/src/pastebin.rs +++ b/src/pastebin.rs @@ -1,51 +1,88 @@ -use std::error::Error; +use std::{collections::HashMap, error::Error}; pub async fn create_paste( api_key: &str, + user_key: &str, name: String, content: String, paste_id: Option, ) -> Result> { let client = reqwest::Client::new(); + + let mut map = HashMap::new(); + map.insert("api_dev_key", api_key.trim().to_owned()); + map.insert("api_user_key", user_key.trim().to_owned()); + map.insert("api_option", "paste".to_owned()); + map.insert("api_paste_code", content); + map.insert("api_paste_private", "0".to_owned()); + map.insert("api_paste_expire_date", "1W".to_owned()); + + if paste_id.is_some() { + let id = paste_id.unwrap(); + map.insert("api_paste_key", id); + } + let mut req = client .post("https://pastebin.com/api/api_post.php") - .query(&[ - ("api_dev_key", api_key), - ("api_option", "paste"), - ("api_paste_code", &content), - ("api_paste_private", "1"), - ("api_paste_expire_date", "1W"), - ("api_paste_name", &name), - ]); - - if (paste_id.is_some()) { - req = req.query(&[("api_paste_key", &paste_id.unwrap())]); - } + .form(&map); let resp = req.send().await?; if resp.status() == 200 { let resp_body = resp.text().await?; return Ok(resp_body); } - - return Ok(resp.status().to_string()); + return Ok(resp.status().to_string() + "\n" + &resp.text().await?); } -pub async fn delete_paste(api_key: &str, paste_id: String) -> Result> { +pub async fn delete_paste( + api_key: &str, + user_key: &str, + paste_id: String, +) -> Result> { let client = reqwest::Client::new(); + + let mut map = HashMap::new(); + map.insert("api_dev_key", api_key.trim().to_owned()); + map.insert("api_user_key", user_key.trim().to_owned()); + map.insert("api_option", "delete".to_owned()); + map.insert("api_paste_key", paste_id); + let req = client .post("https://pastebin.com/api/api_post.php") - .query(&[ - ("api_dev_key", api_key), - ("api_option", "delete"), - ("api_paste_key", &paste_id), - ]) + .form(&map) .send() .await?; if req.status() == 200 { return Ok("Deleted".to_owned()); } + dbg!(&req); - Ok(req.status().to_string()) + Ok(req.status().to_string() + "\n" + &req.text().await?) +} + +pub async fn get_user_key( + api_key: &str, + username: String, + password: String, +) -> Result> { + let client = reqwest::Client::new(); + + let mut map = HashMap::new(); + map.insert("api_dev_key", api_key.trim().to_owned()); + map.insert("api_user_name", username.trim().to_owned()); + map.insert("api_user_password", password.trim().to_owned()); + + let req = client + .post("https://pastebin.com/api/api_login.php") + .form(&map) + .send() + .await?; + + if req.status() == 200 { + return Ok(req.text().await?); + } + dbg!(&req); + println!("{}", req.text().await?); + panic!("Error logging in."); }