use crate::tina::data::json::JsonToString;
use crate::tina::data::AppResult;
use crate::tina::i18n::message::system_message::SystemMessage;
use crate::tina::server::application::Application;
use crate::tina::util::ip::IpUtil;
use crate::tina::util::json::JsonUtil;
use crate::{app_error_from, i18n_string};
use indexmap::IndexMap;
use reqwest_middleware::ClientWithMiddleware;
use serde_json::Value;
use tracing::error;
pub struct AddressUtil;
impl AddressUtil {
pub async fn get_real_address_by_ip(application: &Application, locale: &str, ip: &str) -> AppResult<String> {
if IpUtil::internal_ip(ip) {
return Ok(i18n_string!(SystemMessage::MESSAGE_ADDRESS_INTERNAL).get_string(locale));
}
if !application.get_server_config()?.enable_address_query {
return Ok(UNKOWN.to_string());
}
match &application.http_client {
None => Ok(UNKOWN.to_string()),
Some(http_client) => match query_ip(http_client, ip).await {
Ok(address) => Ok(address),
Err(err) => {
error!("获取地理位置异常: {}", err);
Ok(UNKOWN.to_string())
}
},
}
}
}
async fn query_ip(client: &ClientWithMiddleware, ip: &str) -> AppResult<String> {
let url = format!("{}?ip={}&json=true", IP_URL, ip);
let res = client.get(url).send().await.map_err(app_error_from!())?;
let res_text = res.text().await.map_err(app_error_from!())?;
let mut obj = JsonUtil::parse_json_string::<IndexMap<String, Value>>(res_text.as_str())?;
let region = obj.remove("pro").unwrap_or_else(|| Value::Null);
let city = obj.remove("city").unwrap_or_else(|| Value::Null);
Ok(format!("{} {}", region.to_string_value(), city.to_string_value()))
}
const IP_URL: &str = "http://whois.pconline.com.cn/ipJson.jsp";
const UNKOWN: &str = "XX XX";