mirror of https://github.com/MedzikUser/imgurs
feat: move cli to other crate and add The Null Pointer (0x0.st)
This commit is contained in:
parent
be73023511
commit
ad117bf3ec
|
@ -852,10 +852,23 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "imgurs"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"notify-rust",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imgurs-cli"
|
||||
version = "0.8.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arboard",
|
||||
"base64",
|
||||
"better-panic",
|
||||
"chrono",
|
||||
"clap",
|
||||
|
@ -863,16 +876,13 @@ dependencies = [
|
|||
"clap_mangen",
|
||||
"colored",
|
||||
"dirs",
|
||||
"imgurs",
|
||||
"log",
|
||||
"notify-rust",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simple_logger",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"toml",
|
||||
"validator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1619,6 +1629,7 @@ dependencies = [
|
|||
"atty",
|
||||
"colored",
|
||||
"log",
|
||||
"time 0.3.11",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
|
@ -1787,10 +1798,18 @@ version = "0.3.11"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.6.0"
|
||||
|
|
30
Cargo.toml
30
Cargo.toml
|
@ -1,17 +1,25 @@
|
|||
[workspace]
|
||||
members = ["imgurs-cli"]
|
||||
resolver = "2"
|
||||
|
||||
[package]
|
||||
name = "imgurs"
|
||||
version = "0.8.1"
|
||||
description = "API and CLI for Imgur"
|
||||
description = "API for Imgur"
|
||||
license = "BSD-3-Clause"
|
||||
readme = "README.md"
|
||||
authors = ["MedzikUser <nivua1fn@duck.com>"]
|
||||
homepage = "https://github.com/MedzikUser/imgurs"
|
||||
repository = "https://github.com/MedzikUser/imgurs.git"
|
||||
keywords = ["imgur", "imgur-api", "image", "image-upload"]
|
||||
categories = ["command-line-utilities"]
|
||||
rust-version = "1.58"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["imgur"]
|
||||
full = ["imgur", "null_pointer"]
|
||||
imgur = []
|
||||
null_pointer = []
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
panic = 'abort'
|
||||
|
@ -19,25 +27,13 @@ opt-level = 'z'
|
|||
codegen-units = 1
|
||||
|
||||
[dependencies]
|
||||
dirs = "4.0.0"
|
||||
toml = "0.5.9"
|
||||
chrono = "0.4.22"
|
||||
base64 = "0.13.0"
|
||||
notify-rust = "4.5.8"
|
||||
clap_complete = "3.2.4"
|
||||
anyhow = "1.0.62"
|
||||
better-panic = "0.3.0"
|
||||
validator = "0.16.0"
|
||||
colored = "2.0.0"
|
||||
clap_mangen = "0.1.10"
|
||||
thiserror = "1.0.32"
|
||||
serde_json = "1.0.85"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
clap = { version = "3.2.17", features = ["derive"] }
|
||||
log = { version = "0.4.17", features = ["release_max_level_info", "max_level_debug"] }
|
||||
simple_logger = { version = "2.3.0", default-features = false, features = ["colors"] }
|
||||
reqwest = { version = "0.11.11", default-features = false, features = ["json", "rustls-tls"] }
|
||||
tokio = { version = "1.20.1", features = ["macros", "rt-multi-thread"] }
|
||||
|
||||
[target.'cfg(not(all(unix, not(any(target_os="macos", target_os="android", target_os="emscripten")))))'.dependencies]
|
||||
arboard = "2.1.1"
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.20.1", features = ["macros", "rt-multi-thread"] }
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "imgurs-cli"
|
||||
version = "0.8.1"
|
||||
description = "CLI for Imgur"
|
||||
license = "BSD-3-Clause"
|
||||
authors = ["MedzikUser <nivua1fn@duck.com>"]
|
||||
homepage = "https://github.com/MedzikUser/imgurs"
|
||||
repository = "https://github.com/MedzikUser/imgurs.git"
|
||||
keywords = ["imgur", "imgur-api", "image", "image-upload"]
|
||||
categories = ["command-line-utilities"]
|
||||
rust-version = "1.58"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "imgurs"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.62"
|
||||
clap = { version = "3.2.17", features = ["derive"] }
|
||||
clap_complete = "3.2.4"
|
||||
clap_mangen = "0.1.10"
|
||||
chrono = "0.4.22"
|
||||
colored = "2.0.0"
|
||||
notify-rust = "4.5.8"
|
||||
better-panic = "0.3.0"
|
||||
dirs = "4.0.0"
|
||||
log = "0.4.17"
|
||||
simple_logger = "2.3.0"
|
||||
toml = "0.5.9"
|
||||
serde = { version = "1.0.144", features = ["derive"] }
|
||||
tokio = { version = "1.20.1", features = ["macros", "rt-multi-thread"] }
|
||||
imgurs = { path = "..", features = ["full"] }
|
||||
|
||||
[target.'cfg(not(all(unix, not(any(target_os="macos", target_os="android", target_os="emscripten")))))'.dependencies]
|
||||
arboard = "2.1.1"
|
|
@ -28,9 +28,9 @@ pub fn parse() -> Config {
|
|||
.expect("failed to read line");
|
||||
|
||||
if value.to_lowercase() != "n\n" {
|
||||
warn!("Parse toml config: {err}! Creating config file...");
|
||||
warn!("Parse toml config error: {err}! Creating config file...");
|
||||
|
||||
let default_config = include_str!(concat!("../../config.toml"));
|
||||
let default_config = include_str!(concat!("../../../config.toml"));
|
||||
|
||||
let sys_config_dir = config_dir().expect("find config dir");
|
||||
let config_dir = format!("{}{CONFIG_DIR}", sys_config_dir.to_string_lossy());
|
|
@ -1,12 +1,10 @@
|
|||
mod parse;
|
||||
mod clipboard;
|
||||
mod credits;
|
||||
mod delete_image;
|
||||
mod info_image;
|
||||
mod upload_image;
|
||||
|
||||
pub mod clipboard;
|
||||
pub mod credits;
|
||||
pub mod delete_image;
|
||||
pub mod info_image;
|
||||
pub mod upload_image;
|
||||
|
||||
pub use parse::*;
|
||||
pub use self::{clipboard::*, credits::*, delete_image::*, info_image::*, upload_image::*};
|
||||
|
||||
use chrono::{prelude::DateTime, Utc};
|
||||
use colored::Colorize;
|
|
@ -2,8 +2,8 @@ use imgurs::ImgurClient;
|
|||
use notify_rust::Notification;
|
||||
|
||||
use crate::{
|
||||
cli::{clipboard::set_clipboard, print_image_info},
|
||||
config::toml,
|
||||
imgur::{clipboard::set_clipboard, print_image_info},
|
||||
};
|
||||
|
||||
// show notification
|
|
@ -1,26 +1,21 @@
|
|||
use clap::{Command, IntoApp, Parser, Subcommand};
|
||||
use std::io::stdout;
|
||||
|
||||
use crate::imgur::*;
|
||||
use clap::{Command, CommandFactory, Parser};
|
||||
use clap_complete::{generate, Generator, Shell};
|
||||
use imgurs::ImgurClient;
|
||||
use std::io::{self, stdout};
|
||||
use simple_logger::SimpleLogger;
|
||||
|
||||
use crate::cli::{credits::*, delete_image::*, info_image::*, upload_image::*};
|
||||
|
||||
// get version from Cargo.toml
|
||||
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
||||
mod config;
|
||||
mod imgur;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(
|
||||
name = "imgurs",
|
||||
about = "Imgur API CLI", long_about = None,
|
||||
version = VERSION.unwrap_or("unknown")
|
||||
version = env!("CARGO_PKG_VERSION"),
|
||||
)]
|
||||
struct Cli {
|
||||
#[clap(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
enum Cli {
|
||||
#[clap(about = "Print Client Rate Limit", display_order = 1)]
|
||||
Credits,
|
||||
|
||||
|
@ -43,34 +38,44 @@ enum Commands {
|
|||
Manpage,
|
||||
}
|
||||
|
||||
fn print_completions<G: Generator>(gen: G, app: &mut Command) {
|
||||
generate(gen, app, app.get_name().to_string(), &mut stdout())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn parse(client: ImgurClient) {
|
||||
async fn main() {
|
||||
SimpleLogger::new().init().unwrap();
|
||||
better_panic::install();
|
||||
|
||||
// parse config file
|
||||
let config = config::toml::parse();
|
||||
|
||||
// create imgur client
|
||||
let client = ImgurClient::new(&config.imgur.id);
|
||||
|
||||
let args = Cli::parse();
|
||||
|
||||
match args.command {
|
||||
Commands::Credits => credits(client).await,
|
||||
match args {
|
||||
Cli::Credits => credits(client).await,
|
||||
|
||||
Commands::Upload { path } => upload_image(client, path.to_string()).await,
|
||||
Cli::Upload { path } => upload_image(client, path.to_string()).await,
|
||||
|
||||
Commands::Delete { delete_hash } => delete_image(client, delete_hash.to_string()).await,
|
||||
Cli::Delete { delete_hash } => delete_image(client, delete_hash.to_string()).await,
|
||||
|
||||
Commands::Info { id } => image_info(client, id.to_string()).await,
|
||||
Cli::Info { id } => image_info(client, id.to_string()).await,
|
||||
|
||||
Commands::Completions { shell } => {
|
||||
Cli::Completions { shell } => {
|
||||
let mut app = Cli::command();
|
||||
|
||||
fn print_completions<G: Generator>(gen: G, app: &mut Command) {
|
||||
generate(gen, app, app.get_name().to_string(), &mut stdout())
|
||||
}
|
||||
|
||||
print_completions(shell, &mut app)
|
||||
}
|
||||
|
||||
Commands::Manpage => {
|
||||
Cli::Manpage => {
|
||||
let clap_app = Cli::command();
|
||||
let man = clap_mangen::Man::new(clap_app);
|
||||
|
||||
man.render(&mut io::stdout()).expect("generate manpage")
|
||||
man.render(&mut stdout())
|
||||
.expect("failed to generate man page");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
mod client;
|
||||
mod error;
|
||||
mod image_type;
|
||||
mod requests;
|
||||
mod send_api_request;
|
||||
|
||||
pub(crate) use client::api_url;
|
||||
pub use client::ImgurClient;
|
||||
pub use error::*;
|
||||
pub use image_type::*;
|
||||
pub use send_api_request::*;
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
impl ImgurClient {
|
||||
/// Create a new Imgur Client
|
||||
/// ```
|
|
@ -17,13 +17,13 @@ pub async fn send_api_request(
|
|||
// create Request buidler
|
||||
let mut req = client.request(method, uri.as_str());
|
||||
|
||||
// get imgurs version
|
||||
let version: &str = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
|
||||
|
||||
// add `Authorization` and `User-Agent` to Request
|
||||
req = req
|
||||
.header("Authorization", format!("Client-ID {}", config.client_id))
|
||||
.header("User-Agent", format!("Imgur/{:?}", version));
|
||||
.header(
|
||||
"User-Agent",
|
||||
format!("Imgur/{:?}", env!("CARGO_PKG_VERSION")),
|
||||
);
|
||||
|
||||
// if exists add HashMap to Request
|
||||
if form != None {
|
15
src/lib.rs
15
src/lib.rs
|
@ -91,6 +91,17 @@
|
|||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
mod api;
|
||||
mod error;
|
||||
pub use error::*;
|
||||
|
||||
pub use api::*;
|
||||
#[cfg(feature = "imgur")]
|
||||
mod imgur;
|
||||
|
||||
#[cfg(feature = "imgur")]
|
||||
pub use imgur::*;
|
||||
|
||||
#[cfg(feature = "null_pointer")]
|
||||
mod null_pointer;
|
||||
|
||||
#[cfg(feature = "null_pointer")]
|
||||
pub use null_pointer::*;
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -1,21 +0,0 @@
|
|||
use imgurs::ImgurClient;
|
||||
use simple_logger::SimpleLogger;
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
|
||||
fn main() {
|
||||
// init logger
|
||||
SimpleLogger::new().init().expect("init SimpleLogger");
|
||||
// init better_panic
|
||||
better_panic::install();
|
||||
|
||||
// parse config file
|
||||
let config = config::toml::parse();
|
||||
|
||||
// create imgur client
|
||||
let client = ImgurClient::new(&config.imgur.id);
|
||||
|
||||
// parse cli
|
||||
cli::parse(client)
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use reqwest::{Client, Method};
|
||||
|
||||
use crate::{Error, Result};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// The Null Pointer instance for https://0x0.st
|
||||
pub struct NullPointer {
|
||||
client: Client,
|
||||
url: String,
|
||||
}
|
||||
|
||||
impl NullPointer {
|
||||
/// Create a new [NullPointer] instance.
|
||||
/// ```rs
|
||||
/// use imgurs::NullPointer;
|
||||
///
|
||||
/// let client = NullPointer::new("https://0x0.st");
|
||||
/// ```
|
||||
pub fn new(url: &str) -> Self {
|
||||
let client = reqwest::Client::new();
|
||||
Self {
|
||||
client,
|
||||
url: url.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Upload image to Imgur
|
||||
/// ```no_run
|
||||
/// use imgurs::NullPointer;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() {
|
||||
/// let client = NullPointer::new("https://0x0.st");
|
||||
///
|
||||
/// client.upload("path/to/file.png").await.expect("failed to upload image");
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn upload(&self, path: &str) -> Result<String> {
|
||||
// create http form (hashmap)
|
||||
let mut form = HashMap::new();
|
||||
|
||||
// check if the specified file exists if not then check if it is a url
|
||||
if std::path::Path::new(path).exists() {
|
||||
let bytes = std::fs::read(path)?;
|
||||
|
||||
form.insert("file", bytes);
|
||||
}
|
||||
// validate url adress
|
||||
else {
|
||||
Err(Error::InvalidUrlOrFile(path.to_string()))?;
|
||||
}
|
||||
|
||||
// send request to imgur api
|
||||
// get http client
|
||||
let client = &self.client;
|
||||
|
||||
// create Request buidler
|
||||
let mut req = client.request(Method::POST, &self.url);
|
||||
|
||||
// add `Authorization` and `User-Agent` to Request
|
||||
req = req.header(
|
||||
"User-Agent",
|
||||
format!("Imgur/{:?}", env!("CARGO_PKG_VERSION")),
|
||||
);
|
||||
|
||||
req = req.form(&form);
|
||||
|
||||
// build Request
|
||||
let req = req.build()?;
|
||||
|
||||
// send Request
|
||||
let res = client.execute(req).await?;
|
||||
|
||||
// get response http code
|
||||
let status = res.status();
|
||||
|
||||
// check if an error has occurred
|
||||
if status.is_client_error() || status.is_server_error() {
|
||||
let body = res.text().await?;
|
||||
|
||||
return Err(Error::ApiError(status.as_u16(), body));
|
||||
}
|
||||
|
||||
Ok(res.json().await?)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue