mirror of https://github.com/MedzikUser/imgurs
check CHANGELOG.md for a list of variables
This commit is contained in:
parent
b83847ff20
commit
b1bfe52a4c
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -8,6 +8,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
<!-- next-header -->
|
||||
|
||||
## [Unreleased]
|
||||
### CLI
|
||||
- completions: changed type from String to Shell
|
||||
- removed `&` from `cli.commands` (line 54 in [parse.rs](./src/cli/parse.rs))
|
||||
|
||||
### Library
|
||||
- removed `.map_err(anyhow::Error::new)` when function returns error
|
||||
|
||||
### Added
|
||||
- commands in the code
|
||||
- api functions to `impl` in `ImgurClient`
|
||||
|
||||
### Breaking Changes
|
||||
- lib: moved everything to the main package with api submodules (before `imgurs::api::ImgurClient`, after `imgurs::api::ImgurClient`)
|
||||
|
||||
## [0.6.0] - 2022-03-14
|
||||
### CLI
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
macro_rules! api_url (
|
||||
($path: expr) => (
|
||||
format!("{}{}", "https://api.imgur.com/3/", $path)
|
||||
);
|
||||
);
|
||||
|
||||
use std::{fmt, fs, io, path::Path};
|
||||
|
||||
use anyhow::Error;
|
||||
pub(crate) use api_url;
|
||||
use reqwest::Client;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct ImgurClient {
|
||||
pub client_id: String,
|
||||
pub client: Client,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ImgurClient {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "ImgurClient - client_id: {}", self.client_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl ImgurClient {
|
||||
pub fn new(client_id: String) -> Self {
|
||||
let client = Client::new();
|
||||
ImgurClient { client_id, client }
|
||||
}
|
||||
|
||||
pub async fn upload_image(&self, path: String) -> Result<ImageInfo, Error> {
|
||||
let mut image: String = path.clone();
|
||||
|
||||
// check if the specified file exists if not then check if it is a url
|
||||
if Path::new(&path).exists() {
|
||||
image = fs::read_to_string(&path)
|
||||
.map_err(|err| err.to_string())
|
||||
.expect("read file");
|
||||
} else if !validator::validate_url(&path) {
|
||||
let err = io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("{path} is not url or file path"),
|
||||
);
|
||||
|
||||
Err(anyhow::Error::from(err))?
|
||||
}
|
||||
|
||||
upload_image(self, image).await
|
||||
}
|
||||
|
||||
pub async fn delete_image(&self, delete_hash: String) -> Result<(), Error> {
|
||||
delete_image(self, delete_hash).await
|
||||
}
|
||||
|
||||
pub async fn rate_limit(&self) -> Result<RateLimitInfo, Error> {
|
||||
rate_limit(self).await
|
||||
}
|
||||
|
||||
pub async fn image_info(&self, id: String) -> Result<ImageInfo, Error> {
|
||||
get_image(self, id).await
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
use reqwest::Client;
|
||||
use std::fmt;
|
||||
|
||||
macro_rules! api_url (
|
||||
($path: expr) => (
|
||||
format!("{}{}", "https://api.imgur.com/3/", $path)
|
||||
);
|
||||
);
|
||||
|
||||
pub(crate) use api_url;
|
||||
|
||||
pub struct ImgurClient {
|
||||
pub client_id: String,
|
||||
pub client: Client,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ImgurClient {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "ImgurClient - client_id: {}", self.client_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl ImgurClient {
|
||||
pub fn new(client_id: String) -> Self {
|
||||
let client = Client::new();
|
||||
ImgurClient { client_id, client }
|
||||
}
|
||||
}
|
|
@ -1,29 +1,35 @@
|
|||
use super::send_api_request;
|
||||
use crate::api::configuration::{api_url, ImgurClient};
|
||||
use std::io;
|
||||
|
||||
use anyhow::Error;
|
||||
use reqwest::Method;
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
||||
pub async fn delete_image(c: ImgurClient, delete_hash: String) -> Result<String, anyhow::Error> {
|
||||
use super::{client::api_url, send_api_request, ImgurClient};
|
||||
|
||||
pub async fn delete_image(client: &ImgurClient, delete_hash: String) -> Result<(), Error> {
|
||||
// get imgur api url
|
||||
let uri = api_url!(format!("image/{delete_hash}"));
|
||||
let res = send_api_request(&c, Method::DELETE, uri, None).await?;
|
||||
|
||||
// send request to imgur api
|
||||
let res = send_api_request(client, Method::DELETE, uri, None).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 mut body = res.text().await.map_err(anyhow::Error::new)?;
|
||||
let mut body = res.text().await?;
|
||||
|
||||
if body.chars().count() > 30 {
|
||||
body = "body is too length".to_string()
|
||||
}
|
||||
|
||||
let err = Error::new(
|
||||
ErrorKind::Other,
|
||||
let err = io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("server returned non-successful status code = {status}, body = {body}"),
|
||||
);
|
||||
|
||||
Err(anyhow::Error::from(err))
|
||||
} else {
|
||||
Ok("If the delete hash was correct the image was deleted!".to_string())
|
||||
Err(err)?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
use super::send_api_request;
|
||||
use crate::api::configuration::{api_url, ImgurClient};
|
||||
use crate::api::ImageInfo;
|
||||
use std::io;
|
||||
|
||||
use anyhow::Error;
|
||||
use reqwest::Method;
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
||||
pub async fn get_image(c: ImgurClient, image: &str) -> Result<ImageInfo, anyhow::Error> {
|
||||
use super::{client::api_url, send_api_request, ImageInfo, ImgurClient};
|
||||
|
||||
pub async fn get_image(client: &ImgurClient, image: String) -> Result<ImageInfo, Error> {
|
||||
// get imgur api url
|
||||
let uri = api_url!(format!("image/{image}"));
|
||||
let res = send_api_request(&c, Method::GET, uri, None).await?;
|
||||
|
||||
// send request to imgur api
|
||||
let res = send_api_request(client, Method::GET, uri, None).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 err = Error::new(
|
||||
ErrorKind::Other,
|
||||
let err = io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("server returned non-successful status code = {status}"),
|
||||
);
|
||||
|
||||
Err(anyhow::Error::from(err))
|
||||
Err(err)?
|
||||
} else {
|
||||
let content: ImageInfo = res.json().await.map_err(anyhow::Error::new)?;
|
||||
let content: ImageInfo = res.json().await?;
|
||||
Ok(content)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use serde_derive::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ImageInfo {
|
||||
pub data: ImageInfoData,
|
||||
pub success: bool,
|
||||
pub status: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ImageInfoData {
|
||||
pub id: String,
|
||||
pub title: Option<String>,
|
||||
|
|
|
@ -1,41 +1,56 @@
|
|||
mod delete_image;
|
||||
mod get_image;
|
||||
mod image_type;
|
||||
mod rate_limit;
|
||||
mod upload_image;
|
||||
|
||||
pub mod configuration;
|
||||
pub mod delete_image;
|
||||
pub mod get_image;
|
||||
pub mod rate_limit;
|
||||
pub mod upload_image;
|
||||
pub mod client;
|
||||
|
||||
pub use configuration::ImgurClient;
|
||||
pub use client::ImgurClient;
|
||||
pub use delete_image::*;
|
||||
pub use get_image::*;
|
||||
pub use image_type::*;
|
||||
pub use rate_limit::*;
|
||||
pub use upload_image::*;
|
||||
|
||||
use reqwest::Method;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use reqwest::{Response, Method};
|
||||
use anyhow::Error;
|
||||
|
||||
// send request to imgur api
|
||||
pub async fn send_api_request(
|
||||
config: &ImgurClient,
|
||||
method: Method,
|
||||
uri: String,
|
||||
form: Option<HashMap<&str, String>>,
|
||||
) -> Result<reqwest::Response, anyhow::Error> {
|
||||
) -> Result<Response, Error> {
|
||||
// get request client
|
||||
let client = &config.client;
|
||||
|
||||
// create request buidler
|
||||
let mut req = client.request(method, uri.as_str());
|
||||
|
||||
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
||||
// get program version
|
||||
let version: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
||||
let version = 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.unwrap_or("unknown")),
|
||||
format!("Imgur/{:?}", version),
|
||||
);
|
||||
|
||||
// if exists add hashmap to request
|
||||
if form != None {
|
||||
req = req.form(&form.unwrap())
|
||||
}
|
||||
|
||||
// build request
|
||||
let req = req.build()?;
|
||||
|
||||
client.execute(req).await.map_err(anyhow::Error::from)
|
||||
// send request
|
||||
Ok(client.execute(req).await?)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
use super::send_api_request;
|
||||
use crate::api::configuration::{api_url, ImgurClient};
|
||||
use std::io;
|
||||
|
||||
use anyhow::Error;
|
||||
use reqwest::Method;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use std::io::{Error, ErrorKind};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{client::api_url, send_api_request, ImgurClient};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct RateLimitInfo {
|
||||
|
@ -26,22 +27,28 @@ pub struct RateLimitData {
|
|||
pub client_remaining: i32,
|
||||
}
|
||||
|
||||
pub async fn rate_limit(c: ImgurClient) -> Result<RateLimitInfo, anyhow::Error> {
|
||||
pub async fn rate_limit(client: &ImgurClient) -> Result<RateLimitInfo, Error> {
|
||||
// get imgur api url
|
||||
let uri = api_url!("credits");
|
||||
let res = send_api_request(&c, Method::GET, uri, None).await?;
|
||||
|
||||
// send request to imgur api
|
||||
let res = send_api_request(client, Method::GET, uri, None).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.map_err(anyhow::Error::new)?;
|
||||
let err = Error::new(
|
||||
ErrorKind::Other,
|
||||
let body = res.text().await?;
|
||||
|
||||
let err = io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("server returned non-successful status code = {status}, body = {body}"),
|
||||
);
|
||||
|
||||
Err(anyhow::Error::from(err))
|
||||
Err(err)?
|
||||
} else {
|
||||
let content: RateLimitInfo = res.json().await.map_err(anyhow::Error::new)?;
|
||||
let content = res.json::<RateLimitInfo>().await?;
|
||||
Ok(content)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,40 +1,41 @@
|
|||
use super::send_api_request;
|
||||
use crate::api::{
|
||||
configuration::{api_url, ImgurClient},
|
||||
ImageInfo,
|
||||
};
|
||||
use std::{collections::HashMap, io};
|
||||
|
||||
use anyhow::Error;
|
||||
use reqwest::Method;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Error, ErrorKind},
|
||||
};
|
||||
|
||||
pub async fn upload_image(c: ImgurClient, image: &str) -> Result<ImageInfo, anyhow::Error> {
|
||||
use super::{client::api_url, send_api_request, ImageInfo, ImgurClient};
|
||||
|
||||
pub async fn upload_image(c: &ImgurClient, image: String) -> Result<ImageInfo, Error> {
|
||||
// create http form (hashmap)
|
||||
let mut form = HashMap::new();
|
||||
// insert image to form
|
||||
form.insert("image", image);
|
||||
|
||||
form.insert("image", image.to_string());
|
||||
|
||||
// get imgur api url
|
||||
let uri = api_url!("image");
|
||||
|
||||
// send request to imgur api
|
||||
let res = send_api_request(&c, Method::POST, uri, Some(form)).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 mut body = res.text().await.map_err(anyhow::Error::new)?;
|
||||
let mut body = res.text().await?;
|
||||
|
||||
if body.chars().count() > 30 {
|
||||
body = "body is too length".to_string()
|
||||
if body.chars().count() > 200 {
|
||||
body = "server returned too long".to_string()
|
||||
}
|
||||
|
||||
let err = Error::new(
|
||||
ErrorKind::Other,
|
||||
let err = io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("server returned non-successful status code = {status}, body = {body}"),
|
||||
);
|
||||
|
||||
Err(anyhow::Error::from(err))
|
||||
Err(err)?
|
||||
} else {
|
||||
let content: ImageInfo = res.json().await.map_err(anyhow::Error::new)?;
|
||||
let content: ImageInfo = res.json().await?;
|
||||
Ok(content)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,25 +2,20 @@
|
|||
unix,
|
||||
not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
|
||||
))]
|
||||
fn is_program_in_path(program: &str) -> bool {
|
||||
use std::{env, fs};
|
||||
|
||||
if let Ok(path) = env::var("PATH") {
|
||||
for p in path.split(':') {
|
||||
let p_str = format!("{}/{}", p, program);
|
||||
if fs::metadata(p_str).is_ok() {
|
||||
return true;
|
||||
// use xclip (or a similar program that is installed) because the kernel deletes the clipboard after the process ends
|
||||
pub fn set_clipboard(content: String) {
|
||||
fn is_program_in_path(program: &str) -> bool {
|
||||
if let Ok(path) = std::env::var("PATH") {
|
||||
for p in path.split(':') {
|
||||
let p_str = format!("{}/{}", p, program);
|
||||
if std::fs::metadata(p_str).is_ok() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
|
||||
))]
|
||||
pub fn set_clipboard(content: String) {
|
||||
use std::{
|
||||
io::Write,
|
||||
process::{Command, Stdio},
|
||||
|
@ -38,6 +33,7 @@ pub fn set_clipboard(content: String) {
|
|||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("execute command xsel")
|
||||
|
||||
// xclip
|
||||
} else if is_program_in_path("xclip") {
|
||||
child = Command::new("xclip")
|
||||
|
@ -47,41 +43,43 @@ pub fn set_clipboard(content: String) {
|
|||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("execute command xclip")
|
||||
|
||||
// termux
|
||||
} else if is_program_in_path("termux-clipboard-set") {
|
||||
child = Command::new("termux-clipboard-set")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("execute command termux-clipboard-set")
|
||||
|
||||
// the above programs responsible for the clipboard were not found
|
||||
} else {
|
||||
println!(
|
||||
"{} {}",
|
||||
"WARN".yellow(),
|
||||
"command for clipboard not found".magenta()
|
||||
);
|
||||
return;
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// copy the content (send it to stdin command)
|
||||
child
|
||||
.stdin
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.write_all(content.as_bytes())
|
||||
.expect("execute command");
|
||||
child.wait_with_output().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
unix,
|
||||
not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
|
||||
)))]
|
||||
use arboard::Clipboard;
|
||||
child
|
||||
.wait_with_output()
|
||||
.expect("wait for clipboard command output");
|
||||
}
|
||||
|
||||
#[cfg(not(all(
|
||||
unix,
|
||||
not(any(target_os = "macos", target_os = "android", target_os = "emscripten"))
|
||||
)))]
|
||||
pub fn set_clipboard(content: String) {
|
||||
let mut clipboard = Clipboard::new().unwrap();
|
||||
clipboard.set_text(content).unwrap();
|
||||
let mut clipboard = arboard::Clipboard::new().unwrap();
|
||||
clipboard.set_text(content).execute(format!("set clipboard to '{content}'"));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use chrono::{prelude::DateTime, Utc};
|
||||
use colored::Colorize;
|
||||
use imgurs::api::{rate_limit::rate_limit, ImgurClient};
|
||||
use imgurs::ImgurClient;
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
pub async fn credits(client: ImgurClient) {
|
||||
let i = rate_limit(client).await.expect("send api request");
|
||||
// get client ratelimit from imgur api
|
||||
let i = client
|
||||
.rate_limit()
|
||||
.await
|
||||
.expect("send request to imgur api");
|
||||
|
||||
// format image upload date
|
||||
let date = UNIX_EPOCH + Duration::from_secs(i.data.user_reset.try_into().unwrap());
|
||||
let datetime = DateTime::<Utc>::from(date);
|
||||
let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
use colored::Colorize;
|
||||
|
||||
use imgurs::api::{delete_image::delete_image as del_img, ImgurClient};
|
||||
use imgurs::ImgurClient;
|
||||
|
||||
pub async fn delete_image(client: ImgurClient, delete_hash: String) {
|
||||
let i = del_img(client, delete_hash)
|
||||
// delete image from imgur
|
||||
client
|
||||
.delete_image(delete_hash)
|
||||
.await
|
||||
.expect("send api request");
|
||||
|
||||
println!("{}", i.magenta());
|
||||
println!(
|
||||
"{}",
|
||||
"If Delete Hash was correct the image was deleted!".magenta()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
use imgurs::api::{get_image::get_image, ImgurClient};
|
||||
use imgurs::ImgurClient;
|
||||
|
||||
use super::print_image_info;
|
||||
|
||||
pub async fn image_info(client: ImgurClient, id: &str) {
|
||||
let info = get_image(client, id).await.expect("send api request");
|
||||
pub async fn image_info(client: ImgurClient, id: String) {
|
||||
// get a image info from imgur
|
||||
let info = client
|
||||
.image_info(id)
|
||||
.await
|
||||
.expect("send request to imfur api");
|
||||
|
||||
// print image information from imgur
|
||||
print_image_info(info);
|
||||
}
|
||||
|
|
|
@ -8,14 +8,17 @@ pub mod webhook;
|
|||
|
||||
use chrono::{prelude::DateTime, Utc};
|
||||
use colored::Colorize;
|
||||
use imgurs::api::ImageInfo;
|
||||
use imgurs::ImageInfo;
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
|
||||
// print image information from imgur
|
||||
pub fn print_image_info(i: ImageInfo) {
|
||||
// format image upload date
|
||||
let d = UNIX_EPOCH + Duration::from_secs(i.data.datetime.try_into().unwrap());
|
||||
let datetime = DateTime::<Utc>::from(d);
|
||||
let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
|
||||
// image title
|
||||
if i.data.title != None {
|
||||
println!(
|
||||
"{} {}",
|
||||
|
@ -26,6 +29,8 @@ pub fn print_image_info(i: ImageInfo) {
|
|||
.magenta()
|
||||
);
|
||||
}
|
||||
|
||||
// image description
|
||||
if i.data.description != None {
|
||||
println!(
|
||||
"{} {}",
|
||||
|
@ -36,6 +41,8 @@ pub fn print_image_info(i: ImageInfo) {
|
|||
.magenta()
|
||||
);
|
||||
}
|
||||
|
||||
// image deletehas
|
||||
if i.data.deletehash != None {
|
||||
println!(
|
||||
"{} {}",
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use clap::{Command, IntoApp, Parser, Subcommand};
|
||||
use clap_complete::{generate, Generator, Shell};
|
||||
use imgurs::api::ImgurClient;
|
||||
use imgurs::ImgurClient;
|
||||
use std::io::{self, stdout};
|
||||
|
||||
use crate::cli::{credits::*, delete_image::*, info_image::*, upload_image::*};
|
||||
|
||||
// get program name and varsion from Cargo.toml
|
||||
const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION");
|
||||
const NAME: Option<&str> = option_env!("CARGO_PKG_NAME");
|
||||
|
||||
|
@ -21,7 +22,7 @@ struct Cli {
|
|||
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
#[clap(about = "Print API Rate Limit", display_order = 1)]
|
||||
#[clap(about = "Print Client Rate Limit", display_order = 1)]
|
||||
Credits,
|
||||
|
||||
#[clap(about = "Upload image to Imgur", display_order = 2)]
|
||||
|
@ -37,7 +38,7 @@ enum Commands {
|
|||
about = "Generate completion file for a shell [bash, elvish, fish, powershell, zsh]",
|
||||
display_order = 5
|
||||
)]
|
||||
Completions { shell: String },
|
||||
Completions { shell: Shell },
|
||||
|
||||
#[clap(about = "Generate man page", display_order = 6)]
|
||||
Manpage,
|
||||
|
@ -50,41 +51,26 @@ fn print_completions<G: Generator>(gen: G, app: &mut Command) {
|
|||
pub async fn parse(client: ImgurClient) {
|
||||
let args = Cli::parse();
|
||||
|
||||
match &args.command {
|
||||
Commands::Credits => {
|
||||
credits(client).await;
|
||||
}
|
||||
match args.command {
|
||||
Commands::Credits => credits(client).await,
|
||||
|
||||
Commands::Upload { path } => {
|
||||
upload_image(client, path).await;
|
||||
}
|
||||
Commands::Upload { path } => upload_image(client, path.to_string()).await,
|
||||
|
||||
Commands::Delete { delete_hash } => {
|
||||
delete_image(client, delete_hash.to_string()).await;
|
||||
}
|
||||
Commands::Delete { delete_hash } => delete_image(client, delete_hash.to_string()).await,
|
||||
|
||||
Commands::Info { id } => {
|
||||
image_info(client, id).await;
|
||||
}
|
||||
Commands::Info { id } => image_info(client, id.to_string()).await,
|
||||
|
||||
Commands::Completions { shell } => {
|
||||
let mut app = Cli::command();
|
||||
|
||||
match shell.as_str() {
|
||||
"bash" => print_completions(Shell::Bash, &mut app),
|
||||
"elvish" => print_completions(Shell::Elvish, &mut app),
|
||||
"fish" => print_completions(Shell::Fish, &mut app),
|
||||
"powershell" => print_completions(Shell::PowerShell, &mut app),
|
||||
"zsh" => print_completions(Shell::Zsh, &mut app),
|
||||
|
||||
_ => panic!("Completions to shell `{shell}`, not found!"),
|
||||
}
|
||||
print_completions(shell, &mut app)
|
||||
}
|
||||
|
||||
Commands::Manpage => {
|
||||
let clap_app = Cli::command();
|
||||
let man = clap_mangen::Man::new(clap_app);
|
||||
man.render(&mut io::stdout()).unwrap();
|
||||
|
||||
man.render(&mut io::stdout()).expect("generate manpage")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
use super::clipboard::set_clipboard;
|
||||
use imgurs::api::{upload_image::upload_image as upload_img, ImgurClient};
|
||||
use imgurs::ImgurClient;
|
||||
use notify_rust::Notification;
|
||||
|
||||
use crate::{cli::webhook::send_discord_webhook, config::toml};
|
||||
|
||||
use super::print_image_info;
|
||||
|
||||
use base64::encode as base64_encode;
|
||||
use std::{fs::read as fs_read, path::Path};
|
||||
|
||||
// show notification
|
||||
macro_rules! notify (
|
||||
($notification: expr) => (
|
||||
if toml::parse().notification.enabled {
|
||||
|
@ -17,43 +15,39 @@ macro_rules! notify (
|
|||
);
|
||||
);
|
||||
|
||||
pub async fn upload_image(client: ImgurClient, path: &str) {
|
||||
let mut image: String = path.to_string();
|
||||
|
||||
pub async fn upload_image(client: ImgurClient, path: String) {
|
||||
// parse configuration file
|
||||
let config = toml::parse();
|
||||
|
||||
if Path::new(path).exists() {
|
||||
let bytes = fs_read(path)
|
||||
.map_err(|err| err.to_string())
|
||||
.expect("read file");
|
||||
image = base64_encode(bytes);
|
||||
} else if !validator::validate_url(path) {
|
||||
panic!("{path} is not a url")
|
||||
}
|
||||
|
||||
let mut i = upload_img(client, &image).await.unwrap_or_else(|err| {
|
||||
// upload a image to imgur
|
||||
let mut i = client.upload_image(path).await.unwrap_or_else(|err| {
|
||||
notify!(Notification::new()
|
||||
.summary("Error!")
|
||||
.body(&format!("Error: {}", &err.to_string()))
|
||||
.appname("Imgurs")); // I don't think you can set it to error
|
||||
|
||||
panic!("{}", err)
|
||||
panic!("send request to imagur api: {}", err)
|
||||
});
|
||||
|
||||
// change domain to proxy (to be set in config)
|
||||
if config.imgur.image_cdn != "i.imgur.com" {
|
||||
i.data.link = i.data.link.replace("i.imgur.com", "cdn.magicuser.cf")
|
||||
i.data.link = i.data.link.replace("i.imgur.com", &config.imgur.image_cdn)
|
||||
}
|
||||
|
||||
// print image information from imgur
|
||||
print_image_info(i.clone());
|
||||
|
||||
let body = format!("Uploaded {}", i.data.link);
|
||||
|
||||
notify!(Notification::new().summary("Imgurs").body(&body));
|
||||
// send notification that the image has been uploaded
|
||||
notify!(Notification::new()
|
||||
.summary("Imgurs")
|
||||
.body(&format!("Uploaded {}", i.data.link)));
|
||||
|
||||
// if enabled copy link to clipboard
|
||||
if config.clipboard.enabled {
|
||||
set_clipboard(i.data.link.clone())
|
||||
}
|
||||
|
||||
// if enabled send embed with link and deletehash to discord (something like logger)
|
||||
if config.discord_webhook.enabled {
|
||||
send_discord_webhook(i.data.link, i.data.deletehash.unwrap())
|
||||
.await
|
||||
|
|
|
@ -3,13 +3,21 @@ use std::error::Error;
|
|||
|
||||
use crate::config::toml;
|
||||
|
||||
// send embed with link and deletehash to discord (something like logger)
|
||||
pub async fn send_discord_webhook(
|
||||
link: String,
|
||||
deletehash: String,
|
||||
) -> Result<bool, Box<dyn Error + Send + Sync>> {
|
||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||
// get discord webhook uri from config
|
||||
let url = toml::parse().discord_webhook.uri;
|
||||
|
||||
// create WebhookClient
|
||||
let client: WebhookClient = WebhookClient::new(&url);
|
||||
|
||||
// get program version
|
||||
let version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
|
||||
|
||||
// send discord webhook
|
||||
client
|
||||
.send(|message| {
|
||||
message.username("Imgurs").embed(|embed| {
|
||||
|
@ -17,14 +25,10 @@ pub async fn send_discord_webhook(
|
|||
.title(&link)
|
||||
.description(&format!("Delete Hash ||{deletehash}||"))
|
||||
.image(&link)
|
||||
.footer(
|
||||
&format!(
|
||||
"Imgurs v{}",
|
||||
option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")
|
||||
),
|
||||
None,
|
||||
)
|
||||
.footer(&format!("Imgurs v{version}"), None)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
pub mod api;
|
||||
mod api;
|
||||
|
||||
pub use api::*;
|
||||
|
|
|
@ -2,7 +2,7 @@ mod cli;
|
|||
mod config;
|
||||
|
||||
use cli::parse::parse;
|
||||
use imgurs::api::ImgurClient;
|
||||
use imgurs::ImgurClient;
|
||||
|
||||
use simple_logger::SimpleLogger;
|
||||
|
||||
|
|
Loading…
Reference in New Issue