#!/usr/bin/env runrs //! ```cargo //! [dependencies] //! base64 = "0.21.0" //! clap = { version = "4.1.8", features = ["derive"] } //! reqwest = { version = "0.11.14", features = ["blocking", "json"] } //! rust_util = "0.6.41" //! serde = { version = "1.0.152", features = ["derive"] } //! serde_json = "1.0.93" //! ``` use std::collections::HashMap; use std::fs; use std::path::PathBuf; use base64::Engine; use clap::{arg, Parser}; use rust_util::{debugging, failure_and_exit, information, success}; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None, bin_name = "post.rs")] struct Args { /// Access Token, or from environment: POST_RS_TOKEN #[arg(short, long)] token: Option, /// FileName #[arg(short, long)] file_name: Option, /// Content Type #[arg(short, long)] content_type: Option, /// Description #[arg(short, long)] description: Option, /// Available after create, default 7d, 10m(10 minutes), 1h(1 hour), 1d(1 day), 1M(1 month), 1y(1 year) #[arg(long)] available_after_create: Option, /// Available after decrypt, default 10m, 10m(10 minutes), 1h(1 hour), 1d(1 day), 1M(1 month), 1y(1 year) #[arg(long)] available_after_decrypt: Option, /// Password #[arg(short, long)] pass: Option, #[arg(required = true)] file: PathBuf, } fn main() { let args: Args = Args::parse(); let token = args.token.unwrap_or_else( || std::env::var("POST_RS_TOKEN").unwrap_or_else( |_| failure_and_exit!("Token is required!"))); let file = args.file; if !file.is_file() { failure_and_exit!("File: {:?} not exists or it not a file.", file) } let file_name = args.file_name.unwrap_or_else( || file.file_name().map( |f| f.to_str().map(ToString::to_string)) .flatten().unwrap_or_else(|| "unnamed".to_string())); let content_type = args.content_type.unwrap_or_else(|| get_content_type(&file_name)); let description = args.description.unwrap_or_else(|| "n/a".to_string()); let available_after_create = args.available_after_create.unwrap_or_else(|| "7d".to_string()); let available_after_decrypt = args.available_after_decrypt.unwrap_or_else(|| "10m".to_string()); let password = args.pass; let file_base64 = { let file_bytes = fs::read(&file).unwrap_or_else(|e| { failure_and_exit!("Read file: {:?} failed: {}", file, e) }); base64::engine::general_purpose::STANDARD.encode(&file_bytes) }; information!("Sending file: {}", file_name); let mut params = HashMap::new(); params.insert("pretty", "true"); params.insert("token", &token); params.insert("dataBase64", &file_base64); params.insert("fileName", &file_name); params.insert("contentType", &content_type); params.insert("description", &description); params.insert("availableAfterCreate", &available_after_create); params.insert("availableAfterDecrypt", &available_after_decrypt); debugging!("Params: {:?}", serde_json::to_string_pretty(¶ms)); if let Some(pass) = &password { params.insert("pass", pass); } let client = reqwest::blocking::Client::new(); let post_result = client.post("https://hatter.ink/secfile/post.json") .form(¶ms) .send(); match post_result { Err(e) => failure_and_exit!("Post file: {} failed: {}",file_name, e), Ok(response) => match response.text() { Err(e) => failure_and_exit!("Post file: {} response failed: {}", file_name, e), Ok(text) => success!("Post file: {} succeed: {}", file_name, text), } } } fn get_content_type(file_name: &str) -> String { let file_name = file_name.to_ascii_lowercase(); if file_name.ends_with(".txt") { "text/plain".into() } else if file_name.ends_with(".aac") { "audio/aac".into() } else if file_name.ends_with(".avi") { "video/x-msvideo".into() } else if file_name.ends_with(".css") { "text/css".into() } else if file_name.ends_with(".csv") { "text/csv".into() } else if file_name.ends_with(".doc") { "application/msword".into() } else if file_name.ends_with(".docx") { "application/vnd.openxmlformats-officedocument.wordprocessingml.document".into() } else if file_name.ends_with(".eot") { "application/vnd.ms-fontobject".into() } else if file_name.ends_with(".epub") { "application/epub+zip".into() } else if file_name.ends_with(".gz") { "application/gzip".into() } else if file_name.ends_with(".dif") { "image/gif".into() } else if file_name.ends_with(".htm") || file_name.ends_with(".html") { "text/html".into() } else if file_name.ends_with(".ico") { "image/vnd.microsoft.icon".into() } else if file_name.ends_with(".jar") { "application/java-archive".into() } else if file_name.ends_with(".jpe") || file_name.ends_with(".jpg") || file_name.ends_with(".jpeg") { "image/jpeg".into() } else if file_name.ends_with(".js") { "text/javascript".into() } else if file_name.ends_with(".json") { "application/json".into() } else if file_name.ends_with(".jsonld") { "application/ld+json".into() } else if file_name.ends_with(".mid") || file_name.ends_with(".midi") { "audio/midi".into() } else if file_name.ends_with(".mp3") { "audio/mpeg".into() } else if file_name.ends_with(".mp4") { "video/mp4".into() } else if file_name.ends_with(".mpeg") { "video/mpeg".into() } else if file_name.ends_with(".mpkg") { "application/vnd.apple.installer+xml".into() } else if file_name.ends_with(".odp") { "application/vnd.oasis.opendocument.presentation".into() } else if file_name.ends_with(".ods") { "application/vnd.oasis.opendocument.spreadsheet".into() } else if file_name.ends_with(".odt") { "application/vnd.oasis.opendocument.text".into() } else if file_name.ends_with(".oga") { "audio/ogg".into() } else if file_name.ends_with(".ogv") { "video/ogg".into() } else if file_name.ends_with(".ogg") { "application/ogg".into() } else if file_name.ends_with(".otf") { "font/otf".into() } else if file_name.ends_with(".png") { "image/png".into() } else if file_name.ends_with(".pdf") { "application/pdf".into() } else if file_name.ends_with(".ppt") { "application/vnd.ms-powerpoint".into() } else if file_name.ends_with(".pptx") { "application/vnd.openxmlformats-officedocument.presentationml.presentation".into() } else if file_name.ends_with(".rar") { "application/vnd.rar".into() } else if file_name.ends_with(".rtf") { "application/rtf".into() } else if file_name.ends_with(".sh") { "application/x-sh".into() } else if file_name.ends_with(".svg") { "image/svg+xml".into() } else if file_name.ends_with(".tar") { "application/x-tar".into() } else if file_name.ends_with(".tif") || file_name.ends_with(".tiff") { "image/tiff".into() } else if file_name.ends_with(".ts") { "video/mp2t".into() } else if file_name.ends_with(".ttf") { "font/ttf".into() } else if file_name.ends_with(".wav") { "audio/wav".into() } else if file_name.ends_with(".weba") { "audio/webm".into() } else if file_name.ends_with(".webm") { "video/webm".into() } else if file_name.ends_with(".webp") { "image/webp".into() } else if file_name.ends_with(".woff") { "font/woff".into() } else if file_name.ends_with(".woff2") { "font/woff2".into() } else if file_name.ends_with(".xhtml") { "application/xhtml+xml".into() } else if file_name.ends_with(".xls") { "application/vnd.ms-excel".into() } else if file_name.ends_with(".xlsx") { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".into() } else if file_name.ends_with(".xml") { "application/xml".into() } else if file_name.ends_with(".zip") { "application/zip".into() } else if file_name.ends_with(".3gp") { "video/3gpp".into() } else if file_name.ends_with(".7z") { "application/x-7z-compressed".into() } else { "application/octet-stream".into() } }