use std::collections::HashMap;
pub struct ApiClient {
user_id: String,
license_key: String,
client: reqwest::Client,
}
impl ApiClient {
pub fn new_client(user_id: String, license_key: String) -> ApiClient {
let client = reqwest::Client::new();
ApiClient {
user_id,
license_key,
client,
}
}
#[tokio::main]
async fn make_request(
&self,
prefix: String,
ip_address: String,
) -> Result<Response, Box<dyn std::error::Error>> {
let url = format!("{}/{}", prefix, ip_address);
let resp = self
.client
.get(url)
.basic_auth(&self.user_id, Some(&self.license_key))
.send()
.await?
.json::<Response>()
.await?;
Ok(resp)
}
pub fn get_country(&self, ip_address: String) -> Result<Response, Box<dyn std::error::Error>> {
self.make_request(
String::from("https://geoip.maxmind.com/geoip/v2.1/country/"),
ip_address,
)
}
pub fn get_city(&self, ip_address: String) -> Result<Response, Box<dyn std::error::Error>> {
self.make_request(
String::from("https://geoip.maxmind.com/geoip/v2.1/city/"),
ip_address,
)
}
pub fn get_insights(&self, ip_address: String) -> Result<Response, Box<dyn std::error::Error>> {
self.make_request(
String::from("https://geoip.maxmind.com/geoip/v2.1/insights/"),
ip_address,
)
}
}
#[derive(serde::Deserialize)]
pub struct City {
pub confidence: Option<i64>,
pub geno_name_id: Option<i64>,
pub names: Option<HashMap<String, String>>,
}
#[derive(serde::Deserialize)]
pub struct Continent {
pub code: Option<String>,
pub geno_name_id: Option<i64>,
pub names: Option<HashMap<String, String>>,
}
#[derive(serde::Deserialize)]
pub struct Country {
pub confidence: Option<i64>,
pub geo_name_id: Option<i64>,
pub iso_code: Option<String>,
pub names: Option<HashMap<String, String>>,
}
#[derive(serde::Deserialize)]
pub struct Location {
pub accuracy_radius: Option<i64>,
pub average_income: Option<i64>,
pub latitude: Option<f64>,
pub longitude: Option<f64>,
pub metro_code: Option<i64>,
pub population_density: Option<i64>,
pub time_zone: Option<String>,
}
#[derive(serde::Deserialize)]
pub struct Postal {
pub code: Option<String>,
pub confidence: Option<i64>,
}
#[derive(serde::Deserialize)]
pub struct RegisteredCountry {
pub geo_name_id: Option<i64>,
pub iso_code: Option<String>,
pub names: Option<HashMap<String, String>>,
}
#[derive(serde::Deserialize)]
pub struct RepresentedCountry {
pub geo_name_id: Option<i64>,
pub iso_code: Option<String>,
pub names: Option<HashMap<String, String>>,
pub r#type: Option<String>,
}
#[derive(serde::Deserialize)]
pub struct Subdivision {
pub confidence: Option<i64>,
pub geo_name_id: Option<i64>,
pub iso_code: Option<String>,
pub names: Option<HashMap<String, String>>,
}
#[derive(serde::Deserialize)]
pub struct Traits {
pub autonomous_system_number: Option<i64>,
pub autonomous_system_organization: Option<String>,
pub domain: Option<String>,
pub is_anonymous_proxy: Option<bool>,
pub is_satellite_provider: Option<bool>,
pub isp: Option<String>,
pub ip_address: Option<String>,
pub organization: Option<String>,
pub user_type: Option<String>,
}
#[derive(serde::Deserialize)]
pub struct MaxMind {
pub queries_remaining: Option<i64>,
}
#[derive(serde::Deserialize)]
pub struct Response {
city: Option<City>,
continent: Option<Continent>,
country: Option<Country>,
location: Option<Location>,
postal: Option<Postal>,
registered_country: Option<RegisteredCountry>,
represented_country: Option<RepresentedCountry>,
subdivisions: Option<Vec<Subdivision>>,
traits: Option<Traits>,
maxmind: Option<MaxMind>,
}