use image::load_from_memory; use reqwest::blocking::Client; use serde::Deserialize; use std::fmt; use crate::model::alliance::Alliance; use crate::model::character::Character; use crate::model::corporation::Corporation; use crate::model::ship::Ship; impl EsiClient { pub fn new() -> Self { let client = Client::builder() .user_agent("killpaper-hw,oli1111@web.de") .gzip(true) .brotli(true) .build() .unwrap(); Self { reqwest_client: client, } } pub fn get_alliance(&self, id: u32) -> Result { #[derive(Deserialize)] struct AllianceInfo { name: String, ticker: String, } let info_url = format!("https://esi.evetech.net/latest/alliances/{id}/"); println!("REQ ESI{}", info_url); let info: AllianceInfo = self.reqwest_client.get(&info_url).send()?.json()?; let logo_url = format!("https://images.evetech.net/alliances/{id}/logo?size=64"); println!("REQ ESI{}", logo_url); let bytes = self.reqwest_client.get(&logo_url).send()?.bytes()?; let img = load_from_memory(&bytes)?.to_rgb8(); Ok(Alliance { alliance_id: id, name: info.name, short: info.ticker, logo: img, }) } pub fn get_corporation(&self, id: u32) -> Result { #[derive(Deserialize)] struct CorporationInfo { name: String, ticker: String, } let info_url = format!("https://esi.evetech.net/latest/corporations/{id}/"); println!("REQ ESI{}", info_url); let info: CorporationInfo = self.reqwest_client.get(&info_url).send()?.json()?; let logo_url = format!("https://images.evetech.net/corporations/{id}/logo?size=64"); println!("REQ ESI{}", logo_url); let bytes = self.reqwest_client.get(&logo_url).send()?.bytes()?; let img = load_from_memory(&bytes)?.to_rgb8(); Ok(Corporation { corporation_id: id, name: info.name, short: info.ticker, logo: img, }) } pub fn get_character(&self, id: u32) -> Result { #[derive(Deserialize)] struct CharacterInfo { name: String, } let info_url = format!("https://esi.evetech.net/latest/characters/{id}/"); println!("REQ ESI{}", info_url); let info: CharacterInfo = self.reqwest_client.get(&info_url).send()?.json()?; let portrait_url = format!("https://images.evetech.net/characters/{id}/portrait?size=64"); println!("REQ ESI{}", portrait_url); let bytes = self.reqwest_client.get(&portrait_url).send()?.bytes()?; let img = load_from_memory(&bytes)?.to_rgb8(); Ok(Character { character_id: id, name: info.name, portrait: img, }) } pub fn get_ship(&self, id: u32) -> Result { #[derive(Deserialize)] struct ShipInfo { name: String, } let info_url = format!("https://esi.evetech.net/latest/universe/types/{id}/"); println!("REQ ESI{}", info_url); let info: ShipInfo = self.reqwest_client.get(&info_url).send()?.json()?; let icon_url = format!("https://images.evetech.net/types/{id}/icon?size=64"); println!("REQ ESI{}", icon_url); let bytes = self.reqwest_client.get(&icon_url).send()?.bytes()?; let img = load_from_memory(&bytes)?.to_rgb8(); Ok(Ship { ship_id: id, name: info.name, icon: img, }) } pub fn get_system(&self, id: u32) -> Result { #[derive(Deserialize)] struct SystemInfo { name: String, } let url = format!("https://esi.evetech.net/latest/universe/systems/{id}/"); println!("REQ ESI{}", url); let info: SystemInfo = self.reqwest_client.get(&url).send()?.json()?; Ok(info.name) } } #[derive(Debug)] pub enum EsiError { Http(reqwest::Error), Image(image::ImageError), Json(serde_json::Error), } impl fmt::Display for EsiError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { EsiError::Http(e) => write!(f, "HTTP request error: {}", e), EsiError::Image(e) => write!(f, "Image decoding error: {}", e), EsiError::Json(e) => write!(f, "JSON parsing error: {}", e), } } } // Conversions so we can use `?` impl From for EsiError { fn from(e: reqwest::Error) -> Self { EsiError::Http(e) } } impl From for EsiError { fn from(e: image::ImageError) -> Self { EsiError::Image(e) } } impl From for EsiError { fn from(e: serde_json::Error) -> Self { EsiError::Json(e) } } impl std::error::Error for EsiError {} pub struct EsiClient { pub(crate) reqwest_client: Client, } #[cfg(test)] mod tests { use super::*; #[test] fn test_get_alliance() -> Result<(), EsiError> { let esi = EsiClient::new(); let alliance = esi.get_alliance(99002685)?; assert_eq!(alliance.alliance_id, 99002685); println!("Alliance name: {:?}", alliance.name); println!("Alliance ticker: {:?}", alliance.short); println!("image {} {}", alliance.logo.width(), alliance.logo.height()); assert!(alliance.logo.width() > 0); assert!(alliance.logo.height() > 0); Ok(()) } #[test] fn test_get_corporation() -> Result<(), EsiError> { let esi = EsiClient::new(); let corp = esi.get_corporation(98330748)?; assert_eq!(corp.corporation_id, 98330748); println!("Corporation name: {:?}", corp.name); println!("Corporation ticker: {:?}", corp.short); println!("image {} {}", corp.logo.width(), corp.logo.height()); assert!(corp.logo.width() > 0); assert!(corp.logo.height() > 0); Ok(()) } #[test] fn test_get_character() -> Result<(), EsiError> { let esi = EsiClient::new(); let character = esi.get_character(90951867)?; assert_eq!(character.character_id, 90951867); println!("Character name: {:?}", character.name); println!( "image {} {}", character.portrait.width(), character.portrait.height() ); assert!(character.portrait.width() > 0); assert!(character.portrait.height() > 0); Ok(()) } #[test] fn test_get_ship() -> Result<(), EsiError> { let esi = EsiClient::new(); let ship = esi.get_ship(587)?; // Rifter assert_eq!(ship.ship_id, 587); println!("Ship: {}", ship.name); println!("image {} {}", ship.icon.width(), ship.icon.height()); assert!(ship.icon.width() > 0); assert!(ship.icon.height() > 0); Ok(()) } #[test] fn test_get_system() -> Result<(), EsiError> { let esi = EsiClient::new(); let system_name = esi.get_system(30000142)?; // Jita assert_eq!(system_name, "Jita"); println!("System name: {}", system_name); Ok(()) } }