add cli client
This commit is contained in:
parent
62b5baf69e
commit
3268518cbd
6 changed files with 179 additions and 0 deletions
|
@ -1,4 +1,5 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"tokencracker",
|
||||
"cli",
|
||||
]
|
||||
|
|
21
cli/Cargo.toml
Normal file
21
cli/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "cli"
|
||||
version = "0.1.0"
|
||||
authors = ["LordMZTE <lord@mzte.de>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[[bin]]
|
||||
name = "jm"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.34"
|
||||
clap = "2.33.3"
|
||||
opener = "0.4.1"
|
||||
reqwest = { version = "0.10.9", features = ["stream"] }
|
||||
serde = { version = "1.0.117", features = ["derive"] }
|
||||
serde_json = "1.0.60"
|
||||
structopt = "0.3.21"
|
||||
tokio = { version = "0.2.23", features = ["macros", "fs", "process"] }
|
6
cli/src/api.rs
Normal file
6
cli/src/api.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UpResp {
|
||||
pub files: Vec<String>,
|
||||
}
|
83
cli/src/main.rs
Normal file
83
cli/src/main.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use anyhow::Result;
|
||||
use reqwest::Client;
|
||||
use structopt::StructOpt;
|
||||
|
||||
mod api;
|
||||
mod up;
|
||||
mod util;
|
||||
|
||||
const CATEGORIES: &[&str] = &[
|
||||
"toilet",
|
||||
"jens",
|
||||
"random",
|
||||
"hendrik",
|
||||
"realtox",
|
||||
"chat",
|
||||
"code",
|
||||
"minecraft",
|
||||
"jonas",
|
||||
"server",
|
||||
"uff",
|
||||
"shithost",
|
||||
"itbyhf",
|
||||
"test",
|
||||
];
|
||||
|
||||
#[derive(StructOpt)]
|
||||
struct Opts {
|
||||
#[structopt(subcommand)]
|
||||
cmd: Cmd,
|
||||
}
|
||||
|
||||
#[derive(StructOpt)]
|
||||
enum Cmd {
|
||||
#[structopt(help = "uploads a meme")]
|
||||
Up {
|
||||
file: String,
|
||||
category: String,
|
||||
|
||||
#[structopt(
|
||||
env = "JM_TOKEN",
|
||||
short,
|
||||
long,
|
||||
hide_env_values = true,
|
||||
help = "token to use in order to upload"
|
||||
)]
|
||||
token: String,
|
||||
|
||||
#[structopt(
|
||||
long,
|
||||
short,
|
||||
help = "the name the file should have. defaults to the name of the chosen file"
|
||||
)]
|
||||
name: Option<String>,
|
||||
|
||||
#[structopt(long, short, help = "open the files in the browser")]
|
||||
open: bool,
|
||||
},
|
||||
|
||||
#[structopt(help = "lists the available categories")]
|
||||
Cats,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let Opts { cmd } = Opts::from_args();
|
||||
let http = Client::new();
|
||||
|
||||
match cmd {
|
||||
Cmd::Up {
|
||||
file,
|
||||
category,
|
||||
token,
|
||||
name,
|
||||
open,
|
||||
} => {
|
||||
let name = name.unwrap_or_else(|| file.clone());
|
||||
up::run(&http, token, file, name, category, open).await?;
|
||||
},
|
||||
Cmd::Cats => CATEGORIES.iter().for_each(|c| println!("{}", c)),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
56
cli/src/up.rs
Normal file
56
cli/src/up.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use anyhow::{bail, Result};
|
||||
use reqwest::{
|
||||
multipart::{Form, Part},
|
||||
Body,
|
||||
Client,
|
||||
};
|
||||
use tokio::{fs::File, io::reader_stream};
|
||||
|
||||
use crate::{api::UpResp, util::open_link, CATEGORIES};
|
||||
|
||||
pub async fn run(
|
||||
http: &Client,
|
||||
token: String,
|
||||
path: String,
|
||||
name: String,
|
||||
category: String,
|
||||
open: bool,
|
||||
) -> Result<()> {
|
||||
if !CATEGORIES.contains(&category.as_ref()) {
|
||||
bail!(r#"category is invalid. use "cats" to list categories"#);
|
||||
}
|
||||
|
||||
let res = http
|
||||
.post("https://data.tilera.xyz/api/jensmemes/upload")
|
||||
.multipart(
|
||||
Form::new()
|
||||
.text("category", category)
|
||||
.text("token", token)
|
||||
.part(
|
||||
"file",
|
||||
Part::stream(Body::wrap_stream(reader_stream(File::open(path).await?)))
|
||||
.file_name(name),
|
||||
),
|
||||
)
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
let status = res.status();
|
||||
let res = serde_json::from_slice::<UpResp>(&res.bytes().await?)?;
|
||||
|
||||
println!("Server responded with code {}", status);
|
||||
|
||||
if !open {
|
||||
println!();
|
||||
}
|
||||
|
||||
for f in res.files {
|
||||
if open {
|
||||
open_link(&f).await?;
|
||||
} else {
|
||||
println!("{}", f);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
12
cli/src/util.rs
Normal file
12
cli/src/util.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use tokio::process::Command;
|
||||
|
||||
pub async fn open_link(url: &str) -> anyhow::Result<()> {
|
||||
match std::env::var_os("BROWSER") {
|
||||
Some(browser) => {
|
||||
Command::new(&browser).arg(url).status().await?;
|
||||
},
|
||||
None => opener::open(&url)?,
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue