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]]
|
[[package]]
|
||||||
name = "imgurs"
|
name = "imgurs"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"notify-rust",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"validator",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imgurs-cli"
|
||||||
|
version = "0.8.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"arboard",
|
"arboard",
|
||||||
"base64",
|
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -863,16 +876,13 @@ dependencies = [
|
||||||
"clap_mangen",
|
"clap_mangen",
|
||||||
"colored",
|
"colored",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"imgurs",
|
||||||
"log",
|
"log",
|
||||||
"notify-rust",
|
"notify-rust",
|
||||||
"reqwest",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"validator",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1619,6 +1629,7 @@ dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"colored",
|
"colored",
|
||||||
"log",
|
"log",
|
||||||
|
"time 0.3.11",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1787,10 +1798,18 @@ version = "0.3.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
checksum = "72c91f41dcb2f096c05f0873d667dceec1087ce5bcf984ec8ffb19acddbb3217"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
"libc",
|
"libc",
|
||||||
"num_threads",
|
"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]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
|
30
Cargo.toml
30
Cargo.toml
|
@ -1,17 +1,25 @@
|
||||||
|
[workspace]
|
||||||
|
members = ["imgurs-cli"]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "imgurs"
|
name = "imgurs"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
description = "API and CLI for Imgur"
|
description = "API for Imgur"
|
||||||
license = "BSD-3-Clause"
|
license = "BSD-3-Clause"
|
||||||
readme = "README.md"
|
|
||||||
authors = ["MedzikUser <nivua1fn@duck.com>"]
|
authors = ["MedzikUser <nivua1fn@duck.com>"]
|
||||||
homepage = "https://github.com/MedzikUser/imgurs"
|
homepage = "https://github.com/MedzikUser/imgurs"
|
||||||
repository = "https://github.com/MedzikUser/imgurs.git"
|
repository = "https://github.com/MedzikUser/imgurs.git"
|
||||||
keywords = ["imgur", "imgur-api", "image", "image-upload"]
|
keywords = ["imgur", "imgur-api", "image", "image-upload"]
|
||||||
categories = ["command-line-utilities"]
|
|
||||||
rust-version = "1.58"
|
rust-version = "1.58"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["imgur"]
|
||||||
|
full = ["imgur", "null_pointer"]
|
||||||
|
imgur = []
|
||||||
|
null_pointer = []
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
panic = 'abort'
|
panic = 'abort'
|
||||||
|
@ -19,25 +27,13 @@ opt-level = 'z'
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dirs = "4.0.0"
|
|
||||||
toml = "0.5.9"
|
|
||||||
chrono = "0.4.22"
|
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
notify-rust = "4.5.8"
|
notify-rust = "4.5.8"
|
||||||
clap_complete = "3.2.4"
|
|
||||||
anyhow = "1.0.62"
|
|
||||||
better-panic = "0.3.0"
|
|
||||||
validator = "0.16.0"
|
validator = "0.16.0"
|
||||||
colored = "2.0.0"
|
|
||||||
clap_mangen = "0.1.10"
|
|
||||||
thiserror = "1.0.32"
|
thiserror = "1.0.32"
|
||||||
serde_json = "1.0.85"
|
serde_json = "1.0.85"
|
||||||
serde = { version = "1.0.144", features = ["derive"] }
|
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"] }
|
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]
|
[dev-dependencies]
|
||||||
arboard = "2.1.1"
|
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");
|
.expect("failed to read line");
|
||||||
|
|
||||||
if value.to_lowercase() != "n\n" {
|
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 sys_config_dir = config_dir().expect("find config dir");
|
||||||
let config_dir = format!("{}{CONFIG_DIR}", sys_config_dir.to_string_lossy());
|
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 use self::{clipboard::*, credits::*, delete_image::*, info_image::*, upload_image::*};
|
||||||
pub mod credits;
|
|
||||||
pub mod delete_image;
|
|
||||||
pub mod info_image;
|
|
||||||
pub mod upload_image;
|
|
||||||
|
|
||||||
pub use parse::*;
|
|
||||||
|
|
||||||
use chrono::{prelude::DateTime, Utc};
|
use chrono::{prelude::DateTime, Utc};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
|
@ -2,8 +2,8 @@ use imgurs::ImgurClient;
|
||||||
use notify_rust::Notification;
|
use notify_rust::Notification;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::{clipboard::set_clipboard, print_image_info},
|
|
||||||
config::toml,
|
config::toml,
|
||||||
|
imgur::{clipboard::set_clipboard, print_image_info},
|
||||||
};
|
};
|
||||||
|
|
||||||
// show notification
|
// 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 clap_complete::{generate, Generator, Shell};
|
||||||
use imgurs::ImgurClient;
|
use imgurs::ImgurClient;
|
||||||
use std::io::{self, stdout};
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
use crate::cli::{credits::*, delete_image::*, info_image::*, upload_image::*};
|
mod config;
|
||||||
|
mod imgur;
|
||||||
// get version from Cargo.toml
|
|
||||||
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(
|
#[clap(
|
||||||
name = "imgurs",
|
name = "imgurs",
|
||||||
about = "Imgur API CLI", long_about = None,
|
about = "Imgur API CLI", long_about = None,
|
||||||
version = VERSION.unwrap_or("unknown")
|
version = env!("CARGO_PKG_VERSION"),
|
||||||
)]
|
)]
|
||||||
struct Cli {
|
enum Cli {
|
||||||
#[clap(subcommand)]
|
|
||||||
command: Commands,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
|
||||||
enum Commands {
|
|
||||||
#[clap(about = "Print Client Rate Limit", display_order = 1)]
|
#[clap(about = "Print Client Rate Limit", display_order = 1)]
|
||||||
Credits,
|
Credits,
|
||||||
|
|
||||||
|
@ -43,34 +38,44 @@ enum Commands {
|
||||||
Manpage,
|
Manpage,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_completions<G: Generator>(gen: G, app: &mut Command) {
|
|
||||||
generate(gen, app, app.get_name().to_string(), &mut stdout())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[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();
|
let args = Cli::parse();
|
||||||
|
|
||||||
match args.command {
|
match args {
|
||||||
Commands::Credits => credits(client).await,
|
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();
|
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)
|
print_completions(shell, &mut app)
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands::Manpage => {
|
Cli::Manpage => {
|
||||||
let clap_app = Cli::command();
|
let clap_app = Cli::command();
|
||||||
let man = clap_mangen::Man::new(clap_app);
|
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 client;
|
||||||
mod error;
|
|
||||||
mod image_type;
|
mod image_type;
|
||||||
mod requests;
|
mod requests;
|
||||||
mod send_api_request;
|
mod send_api_request;
|
||||||
|
|
||||||
pub(crate) use client::api_url;
|
pub(crate) use client::api_url;
|
||||||
pub use client::ImgurClient;
|
pub use client::ImgurClient;
|
||||||
pub use error::*;
|
|
||||||
pub use image_type::*;
|
pub use image_type::*;
|
||||||
pub use send_api_request::*;
|
pub use send_api_request::*;
|
||||||
|
|
||||||
|
use crate::{Error, Result};
|
||||||
|
|
||||||
impl ImgurClient {
|
impl ImgurClient {
|
||||||
/// Create a new Imgur Client
|
/// Create a new Imgur Client
|
||||||
/// ```
|
/// ```
|
|
@ -17,13 +17,13 @@ pub async fn send_api_request(
|
||||||
// create Request buidler
|
// create Request buidler
|
||||||
let mut req = client.request(method, uri.as_str());
|
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
|
// add `Authorization` and `User-Agent` to Request
|
||||||
req = req
|
req = req
|
||||||
.header("Authorization", format!("Client-ID {}", config.client_id))
|
.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 exists add HashMap to Request
|
||||||
if form != None {
|
if form != None {
|
15
src/lib.rs
15
src/lib.rs
|
@ -91,6 +91,17 @@
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![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