icloud 0.1.0

基于当前公网IP位置,返回就近的 Apple iCloud 存储服务器地址(域名与解析IP)。
Documentation
use std::net::ToSocketAddrs;

use serde::Deserialize;

#[derive(Debug, Clone, Deserialize)]
pub struct IpInfo {
    pub ip: Option<String>,
    pub city: Option<String>,
    pub region: Option<String>,
    pub country: Option<String>,
}

#[derive(Debug, Clone)]
pub struct IcloudStorageAddress {
    pub address: String,              // 如 https://content.icloud.com
    pub resolved_ip: Option<String>,  // DNS 解析得到的就近CDN IP
    pub ip: Option<String>,           // 当前公网IP
    pub country_code: Option<String>, // 国家/地区代码,例如 CN/US
    pub region: Option<String>,       // 省/州
    pub city: Option<String>,         // 城市
    pub note: Option<String>,         // 说明/免责声明
}

/// 返回基于当前公网IP位置的 iCloud 存储服务器地址(域名与解析IP)。
///
/// 实现思路:
/// - 调用 ipinfo.io 获取当前公网IP及地理位置(城市/区域/国家)。
/// - 选取 iCloud 内容域名 `content.icloud.com` 作为存储服务入口(常用于照片/文件内容分发)。
/// - 通过系统 DNS 解析该域名并返回首个解析IP,作为“就近节点”的近似结果。
/// - 注意:实际数据托管与调度由苹果与CDN动态决定,此结果仅供近似参考。
pub fn storage_address() -> IcloudStorageAddress {
    let host = "content.icloud.com";
    let address = format!("https://{}", host);

    // 1) 获取 IP 地理信息(容错处理)
    let ipinfo: Option<IpInfo> = match reqwest::blocking::get("https://ipinfo.io/json") {
        Ok(resp) => match resp.text() {
            Ok(text) => serde_json::from_str::<IpInfo>(&text).ok(),
            Err(_) => None,
        },
        Err(_) => None,
    };

    // 2) DNS 解析得到就近的 IP(容错处理)
    let resolved_ip = (host, 443)
        .to_socket_addrs()
        .ok()
        .and_then(|mut iter| iter.next())
        .map(|addr| addr.ip().to_string());

    // 3) 免责声明/说明
    let note = ipinfo
        .as_ref()
        .and_then(|i| i.country.clone())
        .map(|cc| {
            if cc == "CN" {
                String::from(
                    "中国大陆用户的 iCloud 数据由云上贵州(GCBD)托管;域名解析与实际存储位置由苹果与CDN动态调度,此地址为近似参考。",
                )
            } else {
                String::from(
                    "该地址为基于DNS解析的就近节点近似结果;实际数据位置和访问路径由苹果与CDN动态决定。",
                )
            }
        });

    IcloudStorageAddress {
        address,
        resolved_ip,
        ip: ipinfo.as_ref().and_then(|i| i.ip.clone()),
        country_code: ipinfo.as_ref().and_then(|i| i.country.clone()),
        region: ipinfo.as_ref().and_then(|i| i.region.clone()),
        city: ipinfo.as_ref().and_then(|i| i.city.clone()),
        note,
    }
}

/// 简单的离线回退:在无法联网或解析失败时,可返回固定域名。
pub fn storage_address_offline() -> IcloudStorageAddress {
    IcloudStorageAddress {
        address: "https://content.icloud.com".to_string(),
        resolved_ip: None,
        ip: None,
        country_code: None,
        region: None,
        city: None,
        note: Some(String::from("离线回退:未能获取IP或DNS解析,返回固定入口域名。")),
    }
}

pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}