HouYunFei Codex commited on
Commit ·
3ad09d8
1
Parent(s): 3026da8
Add rate-limited account removal setting
Browse filesCo-Authored-By: Codex <noreply@openai.com>
- config.json +1 -0
- services/account_service.py +10 -0
- services/config.py +8 -0
- web/src/app/settings/components/config-card.tsx +8 -0
- web/src/app/settings/store.ts +7 -0
- web/src/lib/api.ts +1 -0
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 |
};
|