diff --git a/crates/api/src/handler/avatar.rs b/crates/api/src/handler/avatar.rs index 0894334..478ff72 100644 --- a/crates/api/src/handler/avatar.rs +++ b/crates/api/src/handler/avatar.rs @@ -1,7 +1,10 @@ -use std::hash::{DefaultHasher, Hash, Hasher}; +use crate::libs::{ + http::AppState, + redis::{get_value, set_value}, +}; use actix_web::{get, web, Error, HttpResponse}; -use crate::libs::{http::AppState, redis::{set_value, get_value}}; use gen_avatar_lib::{AvatarBuilder, AvatarResult}; +use std::hash::{DefaultHasher, Hash, Hasher}; #[derive(Debug, serde::Deserialize)] pub struct AvatarParams { @@ -19,11 +22,7 @@ fn calculate_hash(t: &T) -> u64 { s.finish() } -fn avatar( - name: String, - font_color: String, - background_color: String, -) -> AvatarResult { +fn avatar(name: String, font_color: String, background_color: String) -> AvatarResult { AvatarBuilder::new(&name) .with_font_color(&font_color)? .with_background_color(&background_color)? @@ -52,10 +51,7 @@ fn hsl_to_rgb(h: f32, s: f32, l: f32) -> (f32, f32, f32) { ((r + m) * 255.0, (g + m) * 255.0, (b + m) * 255.0) } -fn generate_color( - name_hash: u64, - theme: &str, -) -> String { +fn generate_color(name_hash: u64, theme: &str) -> String { // Pick a random color for hue using the hash let hue = name_hash as f32 % 360.0; @@ -75,14 +71,17 @@ fn generate_color( let background_color = hsl_to_rgb(hue, saturation, lightness); - format!("#{:02x}{:02x}{:02x}", background_color.0 as u8, background_color.1 as u8, background_color.2 as u8) + format!( + "#{:02x}{:02x}{:02x}", + background_color.0 as u8, background_color.1 as u8, background_color.2 as u8 + ) } #[get("/avatar/{name}")] pub async fn generate_avatar( path: web::Path, query: web::Query, - data: web::Data + data: web::Data, ) -> Result { let query = query.into_inner(); let param_input = path.into_inner(); @@ -94,46 +93,64 @@ pub async fn generate_avatar( let hash = calculate_hash(¶m_input.name); - let background_color = generate_color( - hash, - theme.as_str() - ); + let background_color = generate_color(hash, theme.as_str()); let font_color = match theme.as_str() { "dark" => "#ffffff", _ => "#ffffff", }; - println!("Generated avatar for: {} with theme: {}, {}", param_input.name, font_color, background_color); + println!( + "Generated avatar for: {} with theme: {}, {}", + param_input.name, font_color, background_color + ); // Check if the avatar is in the cache let cached_avatar = get_value( - &mut data.redis_client.get_multiplexed_async_connection().await.unwrap(), - format!("avatar:{}:{}", hash, theme).as_str() - ).await; + &mut data + .redis_client + .get_multiplexed_async_connection() + .await + .unwrap(), + format!("avatar:{}:{}", hash, theme).as_str(), + ) + .await; if !cached_avatar.is_empty() { - return Ok(HttpResponse::Ok().content_type("image/png").body(cached_avatar)); + return Ok(HttpResponse::Ok() + .content_type("image/png") + .body(cached_avatar)); } - let avatar_image = avatar(param_input.name.clone(), font_color.to_string(), background_color.to_string()) - .unwrap(); + let avatar_image = avatar( + param_input.name.clone(), + font_color.to_string(), + background_color.to_string(), + ) + .unwrap(); let avatar_image = avatar_image.draw(); let mut buffer = std::io::Cursor::new(Vec::new()); - avatar_image.write_to(&mut buffer, image::ImageFormat::Png).unwrap(); + avatar_image + .write_to(&mut buffer, image::ImageFormat::Png) + .unwrap(); let buffer = buffer.into_inner(); let _ = set_value( - &mut data.redis_client.get_multiplexed_async_connection().await.unwrap(), - format!("avatar:{}:{}", hash, theme).as_str(), - &buffer - ).await; + &mut data + .redis_client + .get_multiplexed_async_connection() + .await + .unwrap(), + format!("avatar:{}:{}", hash, theme).as_str(), + &buffer, + ) + .await; Ok(HttpResponse::Ok().content_type("image/png").body(buffer)) } pub fn init_avatar_routes(config: &mut web::ServiceConfig) { config.service(generate_avatar); -} \ No newline at end of file +} diff --git a/crates/api/src/handler/health.rs b/crates/api/src/handler/health.rs index f56ca1c..83aea37 100644 --- a/crates/api/src/handler/health.rs +++ b/crates/api/src/handler/health.rs @@ -7,4 +7,4 @@ pub async fn health() -> Result { pub fn init_health_routes(config: &mut web::ServiceConfig) { config.service(health); -} \ No newline at end of file +} diff --git a/crates/api/src/handler/mod.rs b/crates/api/src/handler/mod.rs index ac424b9..c20023a 100644 --- a/crates/api/src/handler/mod.rs +++ b/crates/api/src/handler/mod.rs @@ -1,2 +1,2 @@ pub mod avatar; -pub mod health; \ No newline at end of file +pub mod health; diff --git a/crates/api/src/libs/http.rs b/crates/api/src/libs/http.rs index 5b57f29..c8f4110 100644 --- a/crates/api/src/libs/http.rs +++ b/crates/api/src/libs/http.rs @@ -1,8 +1,8 @@ use crate::handler::{avatar, health}; -use listenfd::ListenFd; use actix_web::{web, App, HttpServer}; use env_logger::Env; +use listenfd::ListenFd; use tracing_actix_web::TracingLogger; #[derive(Clone)] @@ -11,45 +11,39 @@ pub struct AppState { } #[actix_web::main] -pub async fn start_web_server( -) -> std::io::Result<()> { +pub async fn start_web_server() -> std::io::Result<()> { let env_config: crate::utils::config::AppConfig = crate::env_config(); - let redis_client: redis::Client = crate::libs::redis::connection_to_redis( - &env_config.redis_url - ).await; + let redis_client: redis::Client = + crate::libs::redis::connection_to_redis(&env_config.redis_url).await; let app_state: AppState = AppState { redis_client: redis_client.clone(), }; - env_logger::init_from_env(Env::default().default_filter_or( - env_config.log_level - )); + env_logger::init_from_env(Env::default().default_filter_or(env_config.log_level)); let mut listenfd: ListenFd = ListenFd::from_env(); - let mut server = HttpServer::new( - move || App::new() + let mut server = HttpServer::new(move || { + App::new() .app_data(web::Data::new(app_state.clone())) .wrap(TracingLogger::default()) .configure(avatar::init_avatar_routes) .configure(health::init_health_routes) - ); + }); server = match listenfd.take_tcp_listener(0)? { Some(listener) => server.listen(listener)?, None => { let host: &str = "0.0.0.0"; let port: u16 = env_config.web_server_port; - + println!("Web Server started at http://{}:{}", host, port); server.bind(format!("{}:{}", host, port))? } }; - server.workers( - env_config.num_workers - ).run().await -} \ No newline at end of file + server.workers(env_config.num_workers).run().await +} diff --git a/crates/api/src/libs/mod.rs b/crates/api/src/libs/mod.rs index 2c1a397..8a1b37a 100644 --- a/crates/api/src/libs/mod.rs +++ b/crates/api/src/libs/mod.rs @@ -1,2 +1,2 @@ pub mod http; -pub mod redis; \ No newline at end of file +pub mod redis; diff --git a/crates/api/src/libs/redis.rs b/crates/api/src/libs/redis.rs index 239ec22..e7b9f5d 100644 --- a/crates/api/src/libs/redis.rs +++ b/crates/api/src/libs/redis.rs @@ -1,26 +1,28 @@ use redis::AsyncCommands; -pub async fn connection_to_redis( - redis_url: &str, -) -> redis::Client { +pub async fn connection_to_redis(redis_url: &str) -> redis::Client { let client: redis::Client = redis::Client::open(redis_url).unwrap(); client } pub async fn get_value(connection: &mut redis::aio::MultiplexedConnection, key: &str) -> String { let value = connection.get(key).await; - + match value { Ok(value) => value, Err(_) => "".to_string(), } } -pub async fn set_value(connection: &mut redis::aio::MultiplexedConnection, key: &str, value: &Vec) -> String { +pub async fn set_value( + connection: &mut redis::aio::MultiplexedConnection, + key: &str, + value: &Vec, +) -> String { let value = connection.set(key, value).await; - + match value { Ok(value) => value, Err(_) => "".to_string(), } -} \ No newline at end of file +} diff --git a/crates/api/src/main.rs b/crates/api/src/main.rs index 75d60db..02cc50a 100644 --- a/crates/api/src/main.rs +++ b/crates/api/src/main.rs @@ -1,5 +1,5 @@ -mod libs; mod handler; +mod libs; mod utils; use confik::{Configuration as _, EnvSource}; @@ -27,4 +27,4 @@ async fn main() { }) .await .unwrap(); -} \ No newline at end of file +} diff --git a/crates/api/src/utils/config.rs b/crates/api/src/utils/config.rs index db6f969..2e29709 100644 --- a/crates/api/src/utils/config.rs +++ b/crates/api/src/utils/config.rs @@ -6,4 +6,4 @@ pub struct AppConfig { pub redis_url: String, pub num_workers: usize, pub log_level: String, -} \ No newline at end of file +} diff --git a/crates/api/src/utils/mod.rs b/crates/api/src/utils/mod.rs index a105933..ef68c36 100644 --- a/crates/api/src/utils/mod.rs +++ b/crates/api/src/utils/mod.rs @@ -1 +1 @@ -pub mod config; \ No newline at end of file +pub mod config; diff --git a/crates/gen-avatar/src/avatar.rs b/crates/gen-avatar/src/avatar.rs index da6e828..601c047 100644 --- a/crates/gen-avatar/src/avatar.rs +++ b/crates/gen-avatar/src/avatar.rs @@ -225,8 +225,6 @@ impl AvatarBuilder { } } - - // apply gaussian blur to the image if specified if let Some(b) = self.blur { imageops::blur(&image, b) @@ -234,4 +232,4 @@ impl AvatarBuilder { image } } -} \ No newline at end of file +} diff --git a/crates/gen-avatar/src/error.rs b/crates/gen-avatar/src/error.rs index 823bf83..04c429a 100644 --- a/crates/gen-avatar/src/error.rs +++ b/crates/gen-avatar/src/error.rs @@ -1,18 +1,15 @@ -use std::num::ParseIntError; use std::io; +use std::num::ParseIntError; /// Custom Error type for Avatar #[derive(Debug)] pub enum Error { /// Invalid hex string - InvalidHexFormat { - actual: String, - expected: String, - }, + InvalidHexFormat { actual: String, expected: String }, /// Parse error Parse(ParseIntError), /// IO read/write error - IO(io::Error) + IO(io::Error), } impl From for Error { @@ -25,4 +22,4 @@ impl From for Error { fn from(error: io::Error) -> Self { Error::IO(error) } -} \ No newline at end of file +} diff --git a/crates/gen-avatar/src/lib.rs b/crates/gen-avatar/src/lib.rs index adcf337..3d11d10 100644 --- a/crates/gen-avatar/src/lib.rs +++ b/crates/gen-avatar/src/lib.rs @@ -10,4 +10,4 @@ pub mod error; pub use avatar::AvatarBuilder; pub use avatar::AvatarResult; -pub use error::Error; \ No newline at end of file +pub use error::Error;