From 7a4ca71d5a2f65baab3e1acda1471033b5b7b39e Mon Sep 17 00:00:00 2001 From: MedzikUser Date: Sun, 23 Jan 2022 13:05:32 +0100 Subject: [PATCH] add image info, update code --- Cargo.toml | 1 - src/api/get_image.rs | 29 +++++++++++++++++++++++++++ src/api/image_type.rs | 25 ++++++++++++++++++++++++ src/api/mod.rs | 4 ++++ src/api/rate_limit.rs | 2 ++ src/api/upload_image.rs | 26 +------------------------ src/cli/info_image.rs | 26 +++++++++++++++++++++++++ src/cli/mod.rs | 43 +++++++++++++++++++++++++++++++++++++++++ src/cli/parse.rs | 22 ++++++++++++++------- src/cli/upload_image.rs | 24 +++-------------------- src/main.rs | 7 ++++++- 11 files changed, 154 insertions(+), 55 deletions(-) create mode 100644 src/api/get_image.rs create mode 100644 src/api/image_type.rs create mode 100644 src/cli/info_image.rs diff --git a/Cargo.toml b/Cargo.toml index 824e26c..25b7a33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ serde_derive = "1.0.134" toml = "0.5.8" serde_json = "1.0.75" chrono = "0.4.19" -#anyhow = "1.0.53" base64 = "0.13.0" [dependencies.clap] diff --git a/src/api/get_image.rs b/src/api/get_image.rs new file mode 100644 index 0000000..4cb10b6 --- /dev/null +++ b/src/api/get_image.rs @@ -0,0 +1,29 @@ +use crate::api::configuration::{api_url, ImgurHandle}; +use crate::api::ImageInfo; + +pub async fn get_image(c: ImgurHandle, image: &str) -> Result { + const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION"); + + let res = c + .client + .get(api_url!(format!("image/{image}"))) + .header("Authorization", format!("Client-ID {}", c.client_id)) + .header( + "User-Agent", + format!("Imgurs/{:?}", VERSION.unwrap_or("unknown")), + ) + .send() + .await + .map_err(|err| err.to_string())?; + + let status = res.status(); + + if status.is_client_error() || status.is_server_error() { + Err(format!( + "server returned non-successful status code = {status}." + )) + } else { + let content: ImageInfo = res.json().await.map_err(|err| err.to_string())?; + Ok(content) + } +} diff --git a/src/api/image_type.rs b/src/api/image_type.rs new file mode 100644 index 0000000..5f46c13 --- /dev/null +++ b/src/api/image_type.rs @@ -0,0 +1,25 @@ +use serde_derive::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct ImageInfo { + pub data: ImageInfoData, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ImageInfoData { + pub id: String, + pub title: Option, + pub description: Option, + pub datetime: i32, + #[serde(rename = "type")] + pub img_type: String, + pub animated: bool, + pub width: i32, + pub height: i32, + pub size: i32, + pub views: i32, + pub bandwidth: i64, + pub favorite: bool, + pub deletehash: Option, + pub link: String, +} diff --git a/src/api/mod.rs b/src/api/mod.rs index 06b8308..3732aab 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,6 +1,10 @@ +mod image_type; + pub mod configuration; pub mod delete_image; +pub mod get_image; pub mod rate_limit; pub mod upload_image; pub use configuration::ImgurHandle; +pub use image_type::*; diff --git a/src/api/rate_limit.rs b/src/api/rate_limit.rs index def8f15..4eec875 100644 --- a/src/api/rate_limit.rs +++ b/src/api/rate_limit.rs @@ -5,6 +5,8 @@ use serde_derive::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct RateLimitInfo { pub data: RateLimitData, + pub success: bool, + pub status: i8, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/api/upload_image.rs b/src/api/upload_image.rs index 7aa1aec..ed73065 100644 --- a/src/api/upload_image.rs +++ b/src/api/upload_image.rs @@ -1,32 +1,8 @@ use crate::api::configuration::{api_url, ImgurHandle}; +use crate::api::ImageInfo; -use serde_derive::{Deserialize, Serialize}; use std::collections::HashMap; -#[derive(Debug, Serialize, Deserialize)] -pub struct ImageInfo { - pub data: ImageInfoData, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct ImageInfoData { - pub id: String, - pub title: Option, - pub description: Option, - pub datetime: i32, - #[serde(rename = "type")] - pub img_type: String, - pub animated: bool, - pub width: i32, - pub height: i32, - pub size: i32, - pub views: i32, - pub bandwidth: i64, - pub favorite: bool, - pub deletehash: String, - pub link: String, -} - pub async fn upload_image(c: ImgurHandle, image: &str) -> Result { const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION"); diff --git a/src/cli/info_image.rs b/src/cli/info_image.rs new file mode 100644 index 0000000..0cda2d6 --- /dev/null +++ b/src/cli/info_image.rs @@ -0,0 +1,26 @@ +use imgurs::api::{configuration::ImgurHandle, get_image::get_image}; + +use super::print_image_info; + +use base64; +use log::error; +use std::fs; +use std::path::Path; + +pub async fn image_info(client: ImgurHandle, path: &str) { + let mut image: String = path.to_string(); + + if Path::new(path).exists() { + let bytes = fs::read(path).map_err(|err| err.to_string()).unwrap(); + + image = base64::encode(bytes); + } + + match get_image(client, &image).await { + Ok(i) => print_image_info(i), + + Err(e) => { + error!("{e}"); + } + } +} diff --git a/src/cli/mod.rs b/src/cli/mod.rs index dab7edc..f165d7d 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,47 @@ pub mod credits; pub mod delete_image; +pub mod info_image; pub mod parse; pub mod upload_image; + +use chrono::prelude::DateTime; +use chrono::Utc; +use log::info; +use std::time::{Duration, UNIX_EPOCH}; + +use imgurs::api::ImageInfo; + +pub fn print_image_info(i: ImageInfo) { + let d = UNIX_EPOCH + Duration::from_secs(i.data.datetime.try_into().unwrap()); + let datetime = DateTime::::from(d); + let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string(); + + if i.data.title != None { + info!( + "Title {}", + i.data.title.unwrap_or("unknown".to_string()) + ); + } + if i.data.description != None { + info!( + "Description {}", + i.data.description.unwrap_or("unknown".to_string()) + ); + } + if i.data.deletehash != None { + info!( + "Deletehash {}", + i.data.deletehash.unwrap_or("unknown".to_string()) + ); + } + + info!("ID {}", i.data.id); + info!("Upload Date {} (UTC)", timestamp_str); + info!("Type {}", i.data.img_type); + info!("Width {}", i.data.width); + info!("Height {}", i.data.height); + info!("File Size {} KB", i.data.size / 1000); + info!("Views {}", i.data.views); + info!("Bandwidth {}", i.data.bandwidth); + info!("Link {}", i.data.link); +} diff --git a/src/cli/parse.rs b/src/cli/parse.rs index 65b10c8..9ce8e86 100644 --- a/src/cli/parse.rs +++ b/src/cli/parse.rs @@ -2,13 +2,14 @@ use clap::{AppSettings, Parser, Subcommand}; use imgurs::api::configuration::ImgurHandle; -use crate::cli::*; +use crate::cli::{credits::*, delete_image::*, info_image::*, upload_image::*}; const VERSION: Option<&str> = option_env!("CARGO_PKG_VERSION"); +const NAME: Option<&str> = option_env!("CARGO_PKG_NAME"); #[derive(Parser, Debug)] #[clap( - name = "imgur", + name = NAME.unwrap_or("unknown"), about = "Imgur API CLI", long_about = None, version = VERSION.unwrap_or("unknown") )] @@ -19,7 +20,7 @@ struct Cli { #[derive(Subcommand, Debug)] enum Commands { - #[clap(about = "Get API Rate Limit")] + #[clap(about = "Get API ratelimit")] Credits, #[clap( @@ -30,9 +31,12 @@ enum Commands { #[clap( setting(AppSettings::ArgRequiredElseHelp), - about = "Upload image to imgur" + about = "Delete image from imgur" )] Delete { delete_hash: String }, + + #[clap(setting(AppSettings::ArgRequiredElseHelp), about = "Print image info")] + Info { id: String }, } pub async fn parse(client: ImgurHandle) { @@ -40,15 +44,19 @@ pub async fn parse(client: ImgurHandle) { match &args.command { Commands::Credits => { - credits::credits(client).await; + credits(client).await; } Commands::Upload { path } => { - upload_image::upload_image(client, path).await; + upload_image(client, path).await; } Commands::Delete { delete_hash } => { - delete_image::delete_image(client, delete_hash.to_string()).await; + delete_image(client, delete_hash.to_string()).await; + } + + Commands::Info { id } => { + image_info(client, id).await; } } } diff --git a/src/cli/upload_image.rs b/src/cli/upload_image.rs index 87808e7..6b7eb85 100644 --- a/src/cli/upload_image.rs +++ b/src/cli/upload_image.rs @@ -1,14 +1,11 @@ +use super::print_image_info; use imgurs::api::configuration::ImgurHandle; use base64; -use log::{error, info}; +use log::error; use std::fs; use std::path::Path; -use chrono::prelude::DateTime; -use chrono::Utc; -use std::time::{Duration, UNIX_EPOCH}; - pub async fn upload_image(client: ImgurHandle, path: &str) { let mut image: String = path.to_string(); @@ -19,22 +16,7 @@ pub async fn upload_image(client: ImgurHandle, path: &str) { } match imgurs::api::upload_image::upload_image(client, &image).await { - Ok(i) => { - let d = UNIX_EPOCH + Duration::from_secs(i.data.datetime.try_into().unwrap()); - let datetime = DateTime::::from(d); - let timestamp_str = datetime.format("%Y-%m-%d %H:%M:%S").to_string(); - - info!("ID {}", i.data.id); - info!("Upload Date {} (UTC)", timestamp_str); - info!("Type {}", i.data.img_type); - info!("Width {}", i.data.width); - info!("Height {}", i.data.height); - info!("File Size {} KB", i.data.size / 1000); - info!("Views {}", i.data.views); - info!("Bandwidth {}", i.data.bandwidth); - info!("Delete Hash {}", i.data.deletehash); - info!("Link {}", i.data.link); - } + Ok(i) => print_image_info(i), Err(e) => { error!("{e}"); diff --git a/src/main.rs b/src/main.rs index 6c2109b..6ab3068 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,9 @@ mod config; use cli::parse::parse; +use log::error; use simple_logger::SimpleLogger; +use std::process::exit; use imgurs::api::ImgurHandle; @@ -11,7 +13,10 @@ use imgurs::api::ImgurHandle; async fn main() { SimpleLogger::new().init().unwrap(); - let config = config::toml::parse().unwrap(); + let config = config::toml::parse().unwrap_or_else(|error| { + error!("Parse toml config: {}", error); + exit(1); + }); let client = ImgurHandle::new((&config.imgur.id).to_string());