dimgup-cli/src/main.rs

118 lines
3 KiB
Rust

#![allow(unused_macros)]
use anyhow::bail;
use clap::Parser;
use clipboard_ext::prelude::*;
use clipboard_ext::x11_bin::ClipboardContext;
use directories::ProjectDirs;
use std::fs::File;
use std::io::Write;
use std::io::{Read, Seek, SeekFrom};
use std::path::Path;
use std::path::PathBuf;
mod discord;
const MAXBUF: u64 = 8_380_416;
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
struct Args {
/// The file to upload to the API
#[arg(required = true)]
filename: PathBuf,
/// Sets the webhook to use and stores it for later uses.
#[arg(short, long)]
set_webhook: Option<String>,
#[arg(short, long)]
copy: bool,
}
macro_rules! loop_try {
($e:expr) => {
match $e {
Ok(v) => v,
Err(_) => continue,
}
};
}
macro_rules! try_or_return {
($e:expr) => {
match $e {
Ok(v) => v,
Err(_) => return,
}
};
}
fn get_config_file() -> PathBuf {
let proj_dirs = ProjectDirs::from("xyz", "karx", "dimgup-cli").unwrap();
let mut b = proj_dirs.config_dir().to_path_buf();
b.push("webhook");
b
}
fn get_webhook() -> anyhow::Result<String> {
let path = get_config_file();
Ok(std::fs::read_to_string(path)?)
}
fn set_webhook(webhook: &str) -> anyhow::Result<()> {
let path = get_config_file();
let parent = path.parent().unwrap();
std::fs::create_dir_all(&parent)?;
let mut file = File::create(&path)?;
file.write_all(webhook.as_bytes())?;
Ok(())
}
fn get_file_info(path: &Path) -> anyhow::Result<(File, u64, String)> {
let filename = path.file_name().unwrap().to_str().unwrap();
let mut handle = File::open(path)?;
let filesize = handle.seek(SeekFrom::End(0))?;
handle.seek(SeekFrom::Start(0))?;
if filesize > MAXBUF {
bail!("File is too big.")
} else {
Ok((handle, filesize, filename.to_string()))
}
}
fn do_upload(mut file: File, size: u64, name: &str, webhook: &str) -> anyhow::Result<String> {
let mut buffer = vec![0u8; size as usize];
file.read_exact(&mut *buffer)?;
let progress_update = |bytes: f64| {
let chars = ['\\', '|', '/', '-'];
print!("{} \r", chars[((bytes * 100.0) as usize) % chars.len()]);
try_or_return!(std::io::stdout().flush());
};
discord::upload(name, &buffer, webhook, progress_update)
}
fn main() -> anyhow::Result<()> {
let args = Args::parse();
let filename = args.filename;
if let Some(ref webhook) = args.set_webhook {
set_webhook(&webhook)?;
println!("Webhook set successfully");
}
let webhook = match get_webhook() {
Ok(w) => w,
Err(_) => bail!("Please set your webhook. See `dimgup-cli --help` for more info."),
};
let (handle, size, name) = get_file_info(&filename)?;
let url = do_upload(handle, size, &name, &webhook)?;
println!("{}", url);
if args.copy {
let mut ctx = ClipboardContext::new().unwrap();
ctx.set_contents(url).unwrap();
println!("Copied!");
}
Ok(())
}