From 087362c3f94781c6d5ad1c634eb57cf643e9685f Mon Sep 17 00:00:00 2001 From: shiluan Date: Wed, 7 Jan 2026 22:54:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(api):=20=E6=94=AF=E6=8C=81=2088code=20?= =?UTF-8?q?=E6=89=80=E6=9C=89=E9=95=9C=E5=83=8F=E7=AB=99=E5=B9=B6=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E6=9E=84=E9=80=A0=20API=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除硬编码的 88code.org 和 88code.ai 域名 - 改用通配符 "88code" 匹配所有 88code 镜像站(如 88code.wu.ren) - 智能处理不同格式的 ANTHROPIC_BASE_URL: - /api 结尾 → /api/usage - /v1 结尾 → /api/usage - 无后缀 → /api/usage - 自动推断 subscription_url,确保与 usage_url 使用同一域名 - 修复跨域访问问题,提升 API 配置灵活性 --- Cargo.lock | 2 +- src/api/mod.rs | 17 ++++++++++++++--- src/core/segments/byebyecode_subscription.rs | 13 +++++++++++-- src/core/segments/byebyecode_usage.rs | 12 +++++++++--- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff7c8b6..e4d320c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,7 +185,7 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "byebyecode" -version = "1.1.25" +version = "1.1.26" dependencies = [ "ansi-to-tui", "ansi_term", diff --git a/src/api/mod.rs b/src/api/mod.rs index d8a5513..cc19012 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -56,8 +56,7 @@ impl ApiConfig { /// 判断是否是 88code 系列中转站 /// 88code 使用特定的 API 格式(POST + ResponseDTO 包装) pub fn is_88code(&self) -> bool { - self.usage_url.contains("88code.org") - || self.usage_url.contains("88code.ai") + self.usage_url.contains("88code") || self.usage_url.contains("rainapp.top") } @@ -506,7 +505,19 @@ pub fn get_usage_url_from_claude_settings() -> Option { Some("https://www.packyapi.com/api/usage/token/".to_string()) } else if base_url.contains("88code") { // 88code 中转站:只要 URL 包含 "88code" 就识别 - Some("https://www.88code.ai/api/usage".to_string()) + // 保持原域名,因为不同的 88code 镜像站可能有不同的域名 + let base = base_url.trim_end_matches('/'); + // 如果已经以 /api 结尾,直接加 /usage + // 如果以 /v1 结尾,替换为 /api/usage + if base.ends_with("/api") { + Some(format!("{}/usage", base)) + } else if base.ends_with("/v1") { + let base = base.trim_end_matches("/v1"); + Some(format!("{}/api/usage", base)) + } else { + // 没有后缀,添加 /api/usage + Some(format!("{}/api/usage", base)) + } } else { // 其他中转站:基于 base_url 构造 usage URL // 假设 API 路径为 /api/usage/token/(与 Packy 兼容) diff --git a/src/core/segments/byebyecode_subscription.rs b/src/core/segments/byebyecode_subscription.rs index 54d2493..011af8d 100644 --- a/src/core/segments/byebyecode_subscription.rs +++ b/src/core/segments/byebyecode_subscription.rs @@ -85,16 +85,25 @@ pub fn collect(config: &Config, input: &InputData) -> Option { // 实时获取数据,不使用缓存 // 传入 model 参数以获取正确的套餐信息 let model_id = &input.model.id; - let subscriptions = fetch_subscriptions_sync(&api_key, Some(model_id))?; + let subscriptions = fetch_subscriptions_sync(&api_key, &usage_url, Some(model_id))?; fn fetch_subscriptions_sync( api_key: &str, + usage_url: &str, model: Option<&str>, ) -> Option> { + // 根据 usage_url 自动推断 subscription_url + let subscription_url = if usage_url.contains("88code") { + usage_url.replace("/usage", "/subscription") + } else { + "https://www.88code.ai/api/subscription".to_string() + }; + let api_config = ApiConfig { enabled: true, api_key: api_key.to_string(), - ..Default::default() + usage_url: usage_url.to_string(), + subscription_url, }; let client = ApiClient::new(api_config).ok()?; diff --git a/src/core/segments/byebyecode_usage.rs b/src/core/segments/byebyecode_usage.rs index 5e4c3b8..578e3fb 100644 --- a/src/core/segments/byebyecode_usage.rs +++ b/src/core/segments/byebyecode_usage.rs @@ -42,8 +42,7 @@ pub fn collect(config: &Config, input: &InputData) -> Option { .unwrap_or_else(|| "https://www.88code.ai/api/usage".to_string()); // 根据 usage_url 判断是哪个服务,并设置动态图标 - let service_name = if usage_url.contains("88code.org") - || usage_url.contains("88code.ai") + let service_name = if usage_url.contains("88code") || usage_url.contains("rainapp.top") { "88code" @@ -87,7 +86,14 @@ pub fn collect(config: &Config, input: &InputData) -> Option { .get("subscription_url") .and_then(|v| v.as_str()) .map(|s| s.to_string()) - .unwrap_or_else(|| "https://www.88code.ai/api/subscription".to_string()); + .unwrap_or_else(|| { + // 根据 usage_url 自动推断 subscription_url + if usage_url.contains("88code") { + usage_url.replace("/usage", "/subscription") + } else { + "https://www.88code.ai/api/subscription".to_string() + } + }); // 从输入数据获取当前使用的模型 let model_id = &input.model.id;