mirror of
https://github.com/router-for-me/Cli-Proxy-API-Management-Center.git
synced 2026-09-24 16:04:35 +08:00
feat(quota): add subscription expiry handling and improve UI elements
This commit is contained in:
@@ -4,11 +4,24 @@
|
||||
|
||||
import type { AuthFileItem } from '@/types';
|
||||
import {
|
||||
normalizeNumberValue,
|
||||
normalizeStringValue,
|
||||
normalizePlanType,
|
||||
parseIdTokenPayload
|
||||
parseIdTokenPayload,
|
||||
} from './parsers';
|
||||
|
||||
const toRecord = (value: unknown): Record<string, unknown> | null => {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
||||
return value as Record<string, unknown>;
|
||||
};
|
||||
|
||||
const resolveCodexAuthInfo = (value: unknown): Record<string, unknown> | null => {
|
||||
const payload = parseIdTokenPayload(value);
|
||||
if (!payload) return null;
|
||||
const nested = toRecord(payload['https://api.openai.com/auth']);
|
||||
return nested ?? payload;
|
||||
};
|
||||
|
||||
export function extractCodexChatgptAccountId(value: unknown): string | null {
|
||||
const payload = parseIdTokenPayload(value);
|
||||
if (!payload) return null;
|
||||
@@ -67,7 +80,7 @@ export function resolveCodexPlanType(file: AuthFileItem): string | null {
|
||||
metadataIdToken?.planType,
|
||||
attributes?.plan_type,
|
||||
attributes?.planType,
|
||||
attributes?.id_token
|
||||
attributes?.id_token,
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
@@ -78,6 +91,61 @@ export function resolveCodexPlanType(file: AuthFileItem): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalizeDateLikeValue = (value: unknown): string | number | null => {
|
||||
const numberValue = normalizeNumberValue(value);
|
||||
if (numberValue === 0) return null;
|
||||
if (numberValue !== null) return numberValue;
|
||||
|
||||
const stringValue = normalizeStringValue(value);
|
||||
if (!stringValue || stringValue === '0') return null;
|
||||
return stringValue;
|
||||
};
|
||||
|
||||
export function resolveCodexSubscriptionActiveUntil(file: AuthFileItem): string | number | null {
|
||||
const metadata = toRecord(file.metadata);
|
||||
const attributes = toRecord(file.attributes);
|
||||
const idToken = resolveCodexAuthInfo(file.id_token);
|
||||
const metadataIdToken = resolveCodexAuthInfo(metadata?.id_token);
|
||||
const attributesIdToken = resolveCodexAuthInfo(attributes?.id_token);
|
||||
const subscription = toRecord(file.subscription);
|
||||
const metadataSubscription = toRecord(metadata?.subscription);
|
||||
const attributesSubscription = toRecord(attributes?.subscription);
|
||||
|
||||
const candidates = [
|
||||
file.chatgpt_subscription_active_until,
|
||||
file.chatgptSubscriptionActiveUntil,
|
||||
file.subscription_active_until,
|
||||
file.subscriptionActiveUntil,
|
||||
subscription?.active_until,
|
||||
subscription?.activeUntil,
|
||||
idToken?.chatgpt_subscription_active_until,
|
||||
idToken?.chatgptSubscriptionActiveUntil,
|
||||
metadata?.chatgpt_subscription_active_until,
|
||||
metadata?.chatgptSubscriptionActiveUntil,
|
||||
metadata?.subscription_active_until,
|
||||
metadata?.subscriptionActiveUntil,
|
||||
metadataSubscription?.active_until,
|
||||
metadataSubscription?.activeUntil,
|
||||
metadataIdToken?.chatgpt_subscription_active_until,
|
||||
metadataIdToken?.chatgptSubscriptionActiveUntil,
|
||||
attributes?.chatgpt_subscription_active_until,
|
||||
attributes?.chatgptSubscriptionActiveUntil,
|
||||
attributes?.subscription_active_until,
|
||||
attributes?.subscriptionActiveUntil,
|
||||
attributesSubscription?.active_until,
|
||||
attributesSubscription?.activeUntil,
|
||||
attributesIdToken?.chatgpt_subscription_active_until,
|
||||
attributesIdToken?.chatgptSubscriptionActiveUntil,
|
||||
];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const value = normalizeDateLikeValue(candidate);
|
||||
if (value !== null) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function extractGeminiCliProjectId(value: unknown): string | null {
|
||||
if (typeof value !== 'string') return null;
|
||||
const matches = Array.from(value.matchAll(/\(([^()]+)\)/g));
|
||||
@@ -96,12 +164,7 @@ export function resolveGeminiCliProjectId(file: AuthFileItem): string | null {
|
||||
? (file.attributes as Record<string, unknown>)
|
||||
: null;
|
||||
|
||||
const candidates = [
|
||||
file.account,
|
||||
file['account'],
|
||||
metadata?.account,
|
||||
attributes?.account
|
||||
];
|
||||
const candidates = [file.account, file['account'], metadata?.account, attributes?.account];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const projectId = extractGeminiCliProjectId(candidate);
|
||||
|
||||
Reference in New Issue
Block a user