Skip to main content

cc_switch_lib/services/provider/
endpoints.rs

1use std::time::{SystemTime, UNIX_EPOCH};
2
3use crate::app_config::AppType;
4use crate::error::AppError;
5use crate::provider::ProviderMeta;
6use crate::settings::CustomEndpoint;
7use crate::store::AppState;
8
9use super::ProviderService;
10
11impl ProviderService {
12    /// 获取自定义端点列表
13    pub fn get_custom_endpoints(
14        state: &AppState,
15        app_type: AppType,
16        provider_id: &str,
17    ) -> Result<Vec<CustomEndpoint>, AppError> {
18        let cfg = state.config.read().map_err(AppError::from)?;
19        let manager = cfg
20            .get_manager(&app_type)
21            .ok_or_else(|| Self::app_not_found(&app_type))?;
22
23        let Some(provider) = manager.providers.get(provider_id) else {
24            return Ok(vec![]);
25        };
26        let Some(meta) = provider.meta.as_ref() else {
27            return Ok(vec![]);
28        };
29        if meta.custom_endpoints.is_empty() {
30            return Ok(vec![]);
31        }
32
33        let mut result: Vec<_> = meta.custom_endpoints.values().cloned().collect();
34        result.sort_by(|a, b| b.added_at.cmp(&a.added_at));
35        Ok(result)
36    }
37
38    /// 新增自定义端点
39    pub fn add_custom_endpoint(
40        state: &AppState,
41        app_type: AppType,
42        provider_id: &str,
43        url: String,
44    ) -> Result<(), AppError> {
45        let normalized = url.trim().trim_end_matches('/').to_string();
46        if normalized.is_empty() {
47            return Err(AppError::localized(
48                "provider.endpoint.url_required",
49                "URL 不能为空",
50                "URL cannot be empty",
51            ));
52        }
53
54        {
55            let mut cfg = state.config.write().map_err(AppError::from)?;
56            let manager = cfg
57                .get_manager_mut(&app_type)
58                .ok_or_else(|| Self::app_not_found(&app_type))?;
59            let provider = manager.providers.get_mut(provider_id).ok_or_else(|| {
60                AppError::localized(
61                    "provider.not_found",
62                    format!("供应商不存在: {provider_id}"),
63                    format!("Provider not found: {provider_id}"),
64                )
65            })?;
66            let meta = provider.meta.get_or_insert_with(ProviderMeta::default);
67
68            let endpoint = CustomEndpoint {
69                url: normalized.clone(),
70                added_at: now_millis(),
71                last_used: None,
72            };
73            meta.custom_endpoints.insert(normalized, endpoint);
74        }
75
76        state.save()?;
77        Ok(())
78    }
79
80    /// 删除自定义端点
81    pub fn remove_custom_endpoint(
82        state: &AppState,
83        app_type: AppType,
84        provider_id: &str,
85        url: String,
86    ) -> Result<(), AppError> {
87        let normalized = url.trim().trim_end_matches('/').to_string();
88
89        {
90            let mut cfg = state.config.write().map_err(AppError::from)?;
91            if let Some(manager) = cfg.get_manager_mut(&app_type) {
92                if let Some(provider) = manager.providers.get_mut(provider_id) {
93                    if let Some(meta) = provider.meta.as_mut() {
94                        meta.custom_endpoints.remove(&normalized);
95                    }
96                }
97            }
98        }
99
100        state.save()?;
101        Ok(())
102    }
103
104    /// 更新端点最后使用时间
105    pub fn update_endpoint_last_used(
106        state: &AppState,
107        app_type: AppType,
108        provider_id: &str,
109        url: String,
110    ) -> Result<(), AppError> {
111        let normalized = url.trim().trim_end_matches('/').to_string();
112
113        {
114            let mut cfg = state.config.write().map_err(AppError::from)?;
115            if let Some(manager) = cfg.get_manager_mut(&app_type) {
116                if let Some(provider) = manager.providers.get_mut(provider_id) {
117                    if let Some(meta) = provider.meta.as_mut() {
118                        if let Some(endpoint) = meta.custom_endpoints.get_mut(&normalized) {
119                            endpoint.last_used = Some(now_millis());
120                        }
121                    }
122                }
123            }
124        }
125
126        state.save()?;
127        Ok(())
128    }
129}
130
131fn now_millis() -> i64 {
132    SystemTime::now()
133        .duration_since(UNIX_EPOCH)
134        .unwrap_or_default()
135        .as_millis() as i64
136}