tina-core 0.0.2

Tina platform
Documentation
//! 地址工具
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 {
    /// 获取IP地址所在地
    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";