feat: add post-rs

This commit is contained in:
2023-03-05 00:39:13 +08:00
parent 6dca80b8c5
commit b2d46bf5a2
3 changed files with 1392 additions and 0 deletions

1264
post-rs/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
post-rs/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "post-rs"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[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"

114
post-rs/src/main.rs Normal file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env runrs
//! ```cargo
//! [dependencies]
//! clap = "4.1.8"
//! 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)]
struct Args {
/// Access Token, or from environment: POST_RS_TOKEN
#[arg(short, long)]
token: Option<String>,
/// FileName
#[arg(short, long)]
file_name: Option<String>,
/// Content Type
#[arg(short, long)]
content_type: Option<String>,
/// Description
#[arg(short, long)]
description: Option<String>,
/// 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<String>,
/// 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<String>,
/// Password
#[arg(short, long)]
pass: Option<String>,
#[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_bytes = fs::read(&file).unwrap_or_else(|e| {
failure_and_exit!("Read file: {:?} failed: {}", file, e)
});
let file_base64 = 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(&params));
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(&params)
.send();
match post_result {
Err(e) => failure_and_exit!("Post file: {} failed: {}",file_name, e),
Ok(respone) => match respone.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 {
if file_name.ends_with(".txt") {
"text/plain".into()
} else {
"application/octet-stream".into()
}
}