HouYunFei Codex commited on
Commit
3ad09d8
·
1 Parent(s): 3026da8

Add rate-limited account removal setting

Browse files

Co-Authored-By: Codex <noreply@openai.com>

config.json CHANGED
@@ -2,6 +2,7 @@
2
  "auth-key": "chatgpt2api",
3
  "refresh_account_interval_minute": 60,
4
  "image_retention_days": 15,
 
5
  "auto_remove_invalid_accounts": true,
6
  "log_levels": [
7
  "debug",
 
2
  "auth-key": "chatgpt2api",
3
  "refresh_account_interval_minute": 60,
4
  "image_retention_days": 15,
5
+ "auto_remove_rate_limited_accounts": false,
6
  "auto_remove_invalid_accounts": true,
7
  "log_levels": [
8
  "debug",
services/account_service.py CHANGED
@@ -388,6 +388,11 @@ class AccountService:
388
  account = self._normalize_account({**self._accounts[index], **updates, "access_token": access_token})
389
  if account is None:
390
  return None
 
 
 
 
 
391
  self._accounts[index] = account
392
  self._save_accounts()
393
  log_service.add(LOG_TYPE_ACCOUNT, "更新账号", {"token": anonymize_token(access_token), "status": account.get("status")})
@@ -419,6 +424,11 @@ class AccountService:
419
  account = self._normalize_account(next_item)
420
  if account is None:
421
  return None
 
 
 
 
 
422
  self._accounts[index] = account
423
  self._save_accounts()
424
  return dict(account)
 
388
  account = self._normalize_account({**self._accounts[index], **updates, "access_token": access_token})
389
  if account is None:
390
  return None
391
+ if account.get("status") == "限流" and config.auto_remove_rate_limited_accounts:
392
+ del self._accounts[index]
393
+ self._save_accounts()
394
+ log_service.add(LOG_TYPE_ACCOUNT, "自动移除限流账号", {"token": anonymize_token(access_token)})
395
+ return None
396
  self._accounts[index] = account
397
  self._save_accounts()
398
  log_service.add(LOG_TYPE_ACCOUNT, "更新账号", {"token": anonymize_token(access_token), "status": account.get("status")})
 
424
  account = self._normalize_account(next_item)
425
  if account is None:
426
  return None
427
+ if account.get("status") == "限流" and config.auto_remove_rate_limited_accounts:
428
+ del self._accounts[index]
429
+ self._save_accounts()
430
+ log_service.add(LOG_TYPE_ACCOUNT, "自动移除限流账号", {"token": anonymize_token(access_token)})
431
+ return None
432
  self._accounts[index] = account
433
  self._save_accounts()
434
  return dict(account)
services/config.py CHANGED
@@ -117,6 +117,13 @@ class ConfigStore:
117
  return value.strip().lower() in {"1", "true", "yes", "on"}
118
  return bool(value)
119
 
 
 
 
 
 
 
 
120
  @property
121
  def log_levels(self) -> list[str]:
122
  levels = self.data.get("log_levels")
@@ -166,6 +173,7 @@ class ConfigStore:
166
  data["refresh_account_interval_minute"] = self.refresh_account_interval_minute
167
  data["image_retention_days"] = self.image_retention_days
168
  data["auto_remove_invalid_accounts"] = self.auto_remove_invalid_accounts
 
169
  data["log_levels"] = self.log_levels
170
  data.pop("auth-key", None)
171
  return data
 
117
  return value.strip().lower() in {"1", "true", "yes", "on"}
118
  return bool(value)
119
 
120
+ @property
121
+ def auto_remove_rate_limited_accounts(self) -> bool:
122
+ value = self.data.get("auto_remove_rate_limited_accounts", False)
123
+ if isinstance(value, str):
124
+ return value.strip().lower() in {"1", "true", "yes", "on"}
125
+ return bool(value)
126
+
127
  @property
128
  def log_levels(self) -> list[str]:
129
  levels = self.data.get("log_levels")
 
173
  data["refresh_account_interval_minute"] = self.refresh_account_interval_minute
174
  data["image_retention_days"] = self.image_retention_days
175
  data["auto_remove_invalid_accounts"] = self.auto_remove_invalid_accounts
176
+ data["auto_remove_rate_limited_accounts"] = self.auto_remove_rate_limited_accounts
177
  data["log_levels"] = self.log_levels
178
  data.pop("auth-key", None)
179
  return data
web/src/app/settings/components/config-card.tsx CHANGED
@@ -22,6 +22,7 @@ export function ConfigCard() {
22
  const setRefreshAccountIntervalMinute = useSettingsStore((state) => state.setRefreshAccountIntervalMinute);
23
  const setImageRetentionDays = useSettingsStore((state) => state.setImageRetentionDays);
24
  const setAutoRemoveInvalidAccounts = useSettingsStore((state) => state.setAutoRemoveInvalidAccounts);
 
25
  const setLogLevel = useSettingsStore((state) => state.setLogLevel);
26
  const setProxy = useSettingsStore((state) => state.setProxy);
27
  const setBaseUrl = useSettingsStore((state) => state.setBaseUrl);
@@ -142,6 +143,13 @@ export function ConfigCard() {
142
  />
143
  自动移除异常账号
144
  </label>
 
 
 
 
 
 
 
145
  <div className="space-y-3 rounded-xl border border-stone-200 bg-white px-4 py-3">
146
  <div>
147
  <label className="text-sm text-stone-700">控制台日志级别</label>
 
22
  const setRefreshAccountIntervalMinute = useSettingsStore((state) => state.setRefreshAccountIntervalMinute);
23
  const setImageRetentionDays = useSettingsStore((state) => state.setImageRetentionDays);
24
  const setAutoRemoveInvalidAccounts = useSettingsStore((state) => state.setAutoRemoveInvalidAccounts);
25
+ const setAutoRemoveRateLimitedAccounts = useSettingsStore((state) => state.setAutoRemoveRateLimitedAccounts);
26
  const setLogLevel = useSettingsStore((state) => state.setLogLevel);
27
  const setProxy = useSettingsStore((state) => state.setProxy);
28
  const setBaseUrl = useSettingsStore((state) => state.setBaseUrl);
 
143
  />
144
  自动移除异常账号
145
  </label>
146
+ <label className="flex items-center gap-3 rounded-xl border border-stone-200 bg-white px-4 py-3 text-sm text-stone-700">
147
+ <Checkbox
148
+ checked={Boolean(config?.auto_remove_rate_limited_accounts)}
149
+ onCheckedChange={(checked) => setAutoRemoveRateLimitedAccounts(Boolean(checked))}
150
+ />
151
+ 自动移除限流账号
152
+ </label>
153
  <div className="space-y-3 rounded-xl border border-stone-200 bg-white px-4 py-3">
154
  <div>
155
  <label className="text-sm text-stone-700">控制台日志级别</label>
web/src/app/settings/store.ts CHANGED
@@ -33,6 +33,7 @@ function normalizeConfig(config: SettingsConfig): SettingsConfig {
33
  refresh_account_interval_minute: Number(config.refresh_account_interval_minute || 5),
34
  image_retention_days: Number(config.image_retention_days || 30),
35
  auto_remove_invalid_accounts: Boolean(config.auto_remove_invalid_accounts),
 
36
  log_levels: Array.isArray(config.log_levels) ? config.log_levels : [],
37
  proxy: typeof config.proxy === "string" ? config.proxy : "",
38
  base_url: typeof config.base_url === "string" ? config.base_url : "",
@@ -93,6 +94,7 @@ type SettingsStore = {
93
  setRefreshAccountIntervalMinute: (value: string) => void;
94
  setImageRetentionDays: (value: string) => void;
95
  setAutoRemoveInvalidAccounts: (value: boolean) => void;
 
96
  setLogLevel: (level: string, enabled: boolean) => void;
97
  setProxy: (value: string) => void;
98
  setBaseUrl: (value: string) => void;
@@ -197,6 +199,7 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
197
  refresh_account_interval_minute: Math.max(1, Number(config.refresh_account_interval_minute) || 1),
198
  image_retention_days: Math.max(1, Number(config.image_retention_days) || 30),
199
  auto_remove_invalid_accounts: Boolean(config.auto_remove_invalid_accounts),
 
200
  proxy: config.proxy.trim(),
201
  base_url: String(config.base_url || "").trim(),
202
  });
@@ -233,6 +236,10 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
233
  set((state) => state.config ? { config: { ...state.config, auto_remove_invalid_accounts: value } } : {});
234
  },
235
 
 
 
 
 
236
  setLogLevel: (level, enabled) => {
237
  set((state) => {
238
  if (!state.config) return {};
 
33
  refresh_account_interval_minute: Number(config.refresh_account_interval_minute || 5),
34
  image_retention_days: Number(config.image_retention_days || 30),
35
  auto_remove_invalid_accounts: Boolean(config.auto_remove_invalid_accounts),
36
+ auto_remove_rate_limited_accounts: Boolean(config.auto_remove_rate_limited_accounts),
37
  log_levels: Array.isArray(config.log_levels) ? config.log_levels : [],
38
  proxy: typeof config.proxy === "string" ? config.proxy : "",
39
  base_url: typeof config.base_url === "string" ? config.base_url : "",
 
94
  setRefreshAccountIntervalMinute: (value: string) => void;
95
  setImageRetentionDays: (value: string) => void;
96
  setAutoRemoveInvalidAccounts: (value: boolean) => void;
97
+ setAutoRemoveRateLimitedAccounts: (value: boolean) => void;
98
  setLogLevel: (level: string, enabled: boolean) => void;
99
  setProxy: (value: string) => void;
100
  setBaseUrl: (value: string) => void;
 
199
  refresh_account_interval_minute: Math.max(1, Number(config.refresh_account_interval_minute) || 1),
200
  image_retention_days: Math.max(1, Number(config.image_retention_days) || 30),
201
  auto_remove_invalid_accounts: Boolean(config.auto_remove_invalid_accounts),
202
+ auto_remove_rate_limited_accounts: Boolean(config.auto_remove_rate_limited_accounts),
203
  proxy: config.proxy.trim(),
204
  base_url: String(config.base_url || "").trim(),
205
  });
 
236
  set((state) => state.config ? { config: { ...state.config, auto_remove_invalid_accounts: value } } : {});
237
  },
238
 
239
+ setAutoRemoveRateLimitedAccounts: (value) => {
240
+ set((state) => state.config ? { config: { ...state.config, auto_remove_rate_limited_accounts: value } } : {});
241
+ },
242
+
243
  setLogLevel: (level, enabled) => {
244
  set((state) => {
245
  if (!state.config) return {};
web/src/lib/api.ts CHANGED
@@ -56,6 +56,7 @@ export type SettingsConfig = {
56
  refresh_account_interval_minute?: number | string;
57
  image_retention_days?: number | string;
58
  auto_remove_invalid_accounts?: boolean;
 
59
  log_levels?: string[];
60
  [key: string]: unknown;
61
  };
 
56
  refresh_account_interval_minute?: number | string;
57
  image_retention_days?: number | string;
58
  auto_remove_invalid_accounts?: boolean;
59
+ auto_remove_rate_limited_accounts?: boolean;
60
  log_levels?: string[];
61
  [key: string]: unknown;
62
  };