add cli client

This commit is contained in:
LordMZTE 2020-12-05 12:08:24 +01:00
parent 62b5baf69e
commit 3268518cbd
6 changed files with 179 additions and 0 deletions

View file

@ -1,4 +1,5 @@
[workspace]
members = [
"tokencracker",
"cli",
]

21
cli/Cargo.toml Normal file
View 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
View file

@ -0,0 +1,6 @@
use serde::Deserialize;
#[derive(Deserialize)]
pub struct UpResp {
pub files: Vec<String>,
}

83
cli/src/main.rs Normal file
View 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
View 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
View 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(())
}