@hashimkarim/usagestat-linux-x64-gnu 2.0.0-alpha.1 → 2.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/native-manifest.json +365 -77
- package/package.json +49 -1
- package/plugins/UPSTREAM-LICENSES.md +109 -0
- package/plugins/abacus-ai/icon.svg +0 -0
- package/plugins/abacus-ai/plugin.js +0 -0
- package/plugins/abacus-ai/plugin.json +0 -0
- package/plugins/aiand/icon.svg +6 -0
- package/plugins/aiand/plugin.js +108 -0
- package/plugins/aiand/plugin.json +22 -0
- package/plugins/alibaba/icon-color.svg +0 -0
- package/plugins/alibaba/icon.svg +0 -0
- package/plugins/alibaba/plugin.js +0 -0
- package/plugins/alibaba/plugin.json +0 -0
- package/plugins/alibaba-token-plan/icon-color.svg +0 -0
- package/plugins/alibaba-token-plan/icon.svg +0 -0
- package/plugins/alibaba-token-plan/plugin.js +0 -0
- package/plugins/alibaba-token-plan/plugin.json +0 -0
- package/plugins/amp/icon-color.svg +0 -0
- package/plugins/amp/icon-conflict.svg +0 -0
- package/plugins/amp/icon.svg +0 -0
- package/plugins/amp/plugin.js +0 -0
- package/plugins/amp/plugin.json +0 -0
- package/plugins/antigravity/icon-color.svg +0 -0
- package/plugins/antigravity/icon-conflict.svg +0 -0
- package/plugins/antigravity/icon.svg +0 -0
- package/plugins/antigravity/plugin.js +0 -0
- package/plugins/antigravity/plugin.json +0 -0
- package/plugins/antigravity-cli/icon.svg +0 -0
- package/plugins/antigravity-cli/plugin.js +0 -0
- package/plugins/antigravity-cli/plugin.json +0 -0
- package/plugins/antigravity-ide/icon.svg +0 -0
- package/plugins/antigravity-ide/plugin.js +0 -0
- package/plugins/antigravity-ide/plugin.json +0 -0
- package/plugins/augment/icon.svg +0 -0
- package/plugins/augment/plugin.js +0 -0
- package/plugins/augment/plugin.json +0 -0
- package/plugins/aws-bedrock/icon-color.svg +0 -0
- package/plugins/aws-bedrock/icon.svg +0 -0
- package/plugins/aws-bedrock/plugin.js +0 -0
- package/plugins/aws-bedrock/plugin.json +0 -0
- package/plugins/azure-openai/icon-color.svg +0 -0
- package/plugins/azure-openai/icon.svg +0 -0
- package/plugins/azure-openai/plugin.js +0 -0
- package/plugins/azure-openai/plugin.json +0 -0
- package/plugins/chutes/icon.svg +0 -0
- package/plugins/chutes/plugin.js +0 -0
- package/plugins/chutes/plugin.json +0 -0
- package/plugins/claude/icon-color.svg +0 -0
- package/plugins/claude/icon.svg +0 -0
- package/plugins/claude/plugin.js +70 -23
- package/plugins/claude/plugin.json +0 -0
- package/plugins/clawrouter/icon.svg +7 -0
- package/plugins/clawrouter/plugin.js +45 -0
- package/plugins/clawrouter/plugin.json +22 -0
- package/plugins/clinepass/icon.svg +4 -0
- package/plugins/clinepass/plugin.js +71 -0
- package/plugins/clinepass/plugin.json +23 -0
- package/plugins/codebuddy/plugin.js +331 -0
- package/plugins/codebuddy/plugin.json +30 -0
- package/plugins/codebuff/icon.svg +0 -0
- package/plugins/codebuff/plugin.js +0 -0
- package/plugins/codebuff/plugin.json +0 -0
- package/plugins/codex/icon-color.svg +0 -0
- package/plugins/codex/icon.svg +0 -0
- package/plugins/codex/plugin.js +7 -2
- package/plugins/codex/plugin.json +0 -0
- package/plugins/command-code/icon.svg +0 -0
- package/plugins/command-code/plugin.js +7 -0
- package/plugins/command-code/plugin.json +0 -0
- package/plugins/copilot/icon-color.svg +0 -0
- package/plugins/copilot/icon.svg +0 -0
- package/plugins/copilot/plugin.js +61 -9
- package/plugins/copilot/plugin.json +4 -1
- package/plugins/crof/icon.svg +0 -0
- package/plugins/crof/plugin.js +0 -0
- package/plugins/crof/plugin.json +0 -0
- package/plugins/crofai/icon.svg +0 -0
- package/plugins/crofai/plugin.js +0 -0
- package/plugins/crofai/plugin.json +0 -0
- package/plugins/cursor/icon-conflict.svg +0 -0
- package/plugins/cursor/icon.svg +0 -0
- package/plugins/cursor/plugin.js +46 -9
- package/plugins/cursor/plugin.json +3 -2
- package/plugins/cursor-nightly/icon.png +0 -0
- package/plugins/cursor-nightly/plugin.js +45 -8
- package/plugins/cursor-nightly/plugin.json +3 -2
- package/plugins/deepgram/icon.svg +0 -0
- package/plugins/deepgram/plugin.js +0 -0
- package/plugins/deepgram/plugin.json +0 -0
- package/plugins/deepinfra/icon.svg +4 -0
- package/plugins/deepinfra/plugin.js +97 -0
- package/plugins/deepinfra/plugin.json +28 -0
- package/plugins/deepseek/icon-color.svg +0 -0
- package/plugins/deepseek/icon.svg +0 -0
- package/plugins/deepseek/plugin.js +0 -0
- package/plugins/deepseek/plugin.json +0 -0
- package/plugins/devin/icon.svg +0 -0
- package/plugins/devin/plugin.js +111 -0
- package/plugins/devin/plugin.json +2 -1
- package/plugins/doubao/icon-color.svg +0 -0
- package/plugins/doubao/icon.svg +0 -0
- package/plugins/doubao/plugin.js +0 -0
- package/plugins/doubao/plugin.json +0 -0
- package/plugins/droid/icon.svg +0 -0
- package/plugins/droid/plugin.json +2 -1
- package/plugins/elevenlabs/icon.svg +0 -0
- package/plugins/elevenlabs/plugin.js +17 -2
- package/plugins/elevenlabs/plugin.json +0 -0
- package/plugins/factory/icon-conflict.svg +0 -0
- package/plugins/factory/icon.svg +0 -0
- package/plugins/factory/plugin.js +38 -14
- package/plugins/factory/plugin.json +2 -1
- package/plugins/fireworks-ai/icon.svg +0 -0
- package/plugins/fireworks-ai/plugin.js +0 -0
- package/plugins/fireworks-ai/plugin.json +0 -0
- package/plugins/gemini/icon-color.svg +0 -0
- package/plugins/gemini/icon.svg +0 -0
- package/plugins/gemini/plugin.js +0 -0
- package/plugins/gemini/plugin.json +0 -0
- package/plugins/grok/icon.svg +0 -0
- package/plugins/grok/plugin.js +30 -5
- package/plugins/grok/plugin.json +3 -1
- package/plugins/groqcloud/icon.svg +0 -0
- package/plugins/groqcloud/plugin.js +0 -0
- package/plugins/groqcloud/plugin.json +0 -0
- package/plugins/ibmbob/icon.svg +23 -0
- package/plugins/ibmbob/plugin.js +61 -0
- package/plugins/ibmbob/plugin.json +22 -0
- package/plugins/jetbrains-ai-assistant/icon-color.svg +0 -0
- package/plugins/jetbrains-ai-assistant/icon-conflict.svg +0 -0
- package/plugins/jetbrains-ai-assistant/icon.svg +0 -0
- package/plugins/jetbrains-ai-assistant/plugin.js +0 -0
- package/plugins/jetbrains-ai-assistant/plugin.json +0 -0
- package/plugins/kilo/icon.svg +0 -0
- package/plugins/kilo/plugin.js +0 -0
- package/plugins/kilo/plugin.json +0 -0
- package/plugins/kimi/icon-color.svg +0 -0
- package/plugins/kimi/icon-conflict.svg +0 -0
- package/plugins/kimi/icon.svg +0 -0
- package/plugins/kimi/plugin.js +122 -141
- package/plugins/kimi/plugin.json +5 -2
- package/plugins/kimi-k2/icon-color.svg +0 -0
- package/plugins/kimi-k2/icon.svg +0 -0
- package/plugins/kimi-k2/plugin.js +0 -0
- package/plugins/kimi-k2/plugin.json +0 -0
- package/plugins/kiro/icon-color.svg +0 -0
- package/plugins/kiro/icon-conflict.svg +0 -0
- package/plugins/kiro/icon.svg +0 -0
- package/plugins/kiro/plugin.js +49 -10
- package/plugins/kiro/plugin.json +3 -1
- package/plugins/litellm/icon.svg +0 -0
- package/plugins/litellm/plugin.js +0 -0
- package/plugins/litellm/plugin.json +0 -0
- package/plugins/llm-proxy/icon.svg +0 -0
- package/plugins/llm-proxy/plugin.js +0 -0
- package/plugins/llm-proxy/plugin.json +0 -0
- package/plugins/longcat/icon.svg +4 -0
- package/plugins/longcat/plugin.js +182 -0
- package/plugins/longcat/plugin.json +23 -0
- package/plugins/manus/icon.svg +0 -0
- package/plugins/manus/plugin.js +0 -0
- package/plugins/manus/plugin.json +0 -0
- package/plugins/mimo/icon.svg +0 -0
- package/plugins/mimo/plugin.js +0 -0
- package/plugins/mimo/plugin.json +0 -0
- package/plugins/minimax/icon-color.svg +0 -0
- package/plugins/minimax/icon-conflict.svg +0 -0
- package/plugins/minimax/icon.svg +0 -0
- package/plugins/minimax/plugin.js +25 -31
- package/plugins/minimax/plugin.json +0 -0
- package/plugins/mistral/icon-color.svg +0 -0
- package/plugins/mistral/icon.svg +0 -0
- package/plugins/mistral/plugin.js +0 -0
- package/plugins/mistral/plugin.json +0 -0
- package/plugins/moonshot/icon.svg +0 -0
- package/plugins/moonshot/plugin.js +8 -6
- package/plugins/moonshot/plugin.json +0 -0
- package/plugins/nanogpt/icon-color.svg +0 -0
- package/plugins/nanogpt/icon.svg +0 -0
- package/plugins/nanogpt/plugin.js +0 -0
- package/plugins/nanogpt/plugin.json +0 -0
- package/plugins/neuralwatt/icon.svg +0 -0
- package/plugins/neuralwatt/plugin.js +0 -0
- package/plugins/neuralwatt/plugin.json +0 -0
- package/plugins/notion/icon.svg +1 -0
- package/plugins/notion/plugin.js +282 -0
- package/plugins/notion/plugin.json +29 -0
- package/plugins/ollama/icon.svg +0 -0
- package/plugins/ollama/plugin.js +257 -56
- package/plugins/ollama/plugin.json +6 -3
- package/plugins/openai-api/icon.svg +0 -0
- package/plugins/openai-api/plugin.js +0 -0
- package/plugins/openai-api/plugin.json +0 -0
- package/plugins/opencode/icon.svg +0 -0
- package/plugins/opencode/plugin.js +0 -0
- package/plugins/opencode/plugin.json +0 -0
- package/plugins/opencode-go/icon-conflict.svg +0 -0
- package/plugins/opencode-go/icon.svg +0 -0
- package/plugins/opencode-go/plugin.js +78 -10
- package/plugins/opencode-go/plugin.json +5 -2
- package/plugins/openrouter/icon.svg +0 -0
- package/plugins/openrouter/plugin.js +371 -114
- package/plugins/openrouter/plugin.json +6 -0
- package/plugins/perplexity/icon-color.svg +0 -0
- package/plugins/perplexity/icon-conflict.svg +0 -0
- package/plugins/perplexity/icon.svg +0 -0
- package/plugins/perplexity/plugin.js +0 -0
- package/plugins/perplexity/plugin.json +0 -0
- package/plugins/poe/icon.svg +0 -0
- package/plugins/poe/plugin.js +24 -18
- package/plugins/poe/plugin.json +2 -0
- package/plugins/qoder/icon.svg +3 -0
- package/plugins/qoder/plugin.js +227 -0
- package/plugins/qoder/plugin.json +23 -0
- package/plugins/qwencloud/icon.svg +4 -0
- package/plugins/qwencloud/plugin.js +677 -0
- package/plugins/qwencloud/plugin.json +29 -0
- package/plugins/sakana/icon.svg +5 -0
- package/plugins/sakana/plugin.js +156 -0
- package/plugins/sakana/plugin.json +23 -0
- package/plugins/stepfun/icon-color.svg +0 -0
- package/plugins/stepfun/icon.svg +0 -0
- package/plugins/stepfun/plugin.js +0 -0
- package/plugins/stepfun/plugin.json +0 -0
- package/plugins/sub2api/icon.svg +4 -0
- package/plugins/sub2api/plugin.js +191 -0
- package/plugins/sub2api/plugin.json +16 -0
- package/plugins/synthetic/icon-conflict.svg +0 -0
- package/plugins/synthetic/icon.svg +0 -0
- package/plugins/synthetic/plugin.js +0 -0
- package/plugins/synthetic/plugin.json +0 -0
- package/plugins/t3chat/icon-color.svg +0 -0
- package/plugins/t3chat/icon.svg +0 -0
- package/plugins/t3chat/plugin.js +0 -0
- package/plugins/t3chat/plugin.json +0 -0
- package/plugins/venice/icon-color.svg +0 -0
- package/plugins/venice/icon.svg +0 -0
- package/plugins/venice/plugin.js +0 -0
- package/plugins/venice/plugin.json +0 -0
- package/plugins/vertex-ai/icon-color.svg +0 -0
- package/plugins/vertex-ai/icon.svg +0 -0
- package/plugins/vertex-ai/plugin.js +0 -0
- package/plugins/vertex-ai/plugin.json +0 -0
- package/plugins/warp/icon-color.svg +0 -0
- package/plugins/warp/icon.svg +0 -0
- package/plugins/warp/plugin.js +0 -0
- package/plugins/warp/plugin.json +0 -0
- package/plugins/wayfinder/icon.svg +5 -0
- package/plugins/wayfinder/plugin.js +47 -0
- package/plugins/wayfinder/plugin.json +16 -0
- package/plugins/windsurf/icon-conflict.svg +0 -0
- package/plugins/windsurf/icon.svg +0 -0
- package/plugins/windsurf/plugin.js +0 -0
- package/plugins/windsurf/plugin.json +0 -0
- package/plugins/xai/icon.svg +7 -0
- package/plugins/xai/plugin.js +162 -0
- package/plugins/xai/plugin.json +28 -0
- package/plugins/zai/icon-conflict.svg +0 -0
- package/plugins/zai/icon.svg +0 -0
- package/plugins/zai/plugin.js +111 -161
- package/plugins/zai/plugin.json +4 -1
- package/plugins/zed/icon.svg +0 -0
- package/plugins/zed/plugin.js +0 -0
- package/plugins/zed/plugin.json +0 -0
- package/plugins/zenmux/icon.svg +3 -0
- package/plugins/zenmux/plugin.js +102 -0
- package/plugins/zenmux/plugin.json +23 -0
- package/plugins/zoommate/icon.svg +1 -0
- package/plugins/zoommate/plugin.js +244 -0
- package/plugins/zoommate/plugin.json +29 -0
- package/usagestat +0 -0
- package/usagestatd +0 -0
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
var GATEWAY_BASE_URL = "https://home.qwencloud.com";
|
|
3
|
+
var DATA_GATEWAY_BASE_URL = "https://cs-data.qwencloud.com";
|
|
4
|
+
var DASHBOARD_URL = "https://home.qwencloud.com/billing/subscription/token-plan-individual";
|
|
5
|
+
var PRODUCT_CODE = "sfm_tokenplansolo_public_intl";
|
|
6
|
+
var CONSOLE_PRODUCT = "sfm_bailian";
|
|
7
|
+
var CONSOLE_ACTION = "IntlBroadScopeAspnGateway";
|
|
8
|
+
var USAGE_API = "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/usage";
|
|
9
|
+
var SUBSCRIPTION_API = "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/subscription";
|
|
10
|
+
var QUOTA_CONFIG_API = "zeldaHttp.apikeyMgr./tokenplan/personal/api/v2/quota-config";
|
|
11
|
+
var REGION = "ap-southeast-1";
|
|
12
|
+
var LANGUAGE = "en-US";
|
|
13
|
+
var USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36";
|
|
14
|
+
var FIVE_HOUR_MS = 5 * 60 * 60 * 1000;
|
|
15
|
+
var WEEKLY_MS = 7 * 24 * 60 * 60 * 1000;
|
|
16
|
+
var LEGACY_MS = 30 * 24 * 60 * 60 * 1000;
|
|
17
|
+
|
|
18
|
+
var PLAN_NAME_KEYS = [
|
|
19
|
+
"planName", "plan_name", "packageName", "package_name", "commodityName", "commodity_name",
|
|
20
|
+
"instanceName", "instance_name", "displayName", "display_name", "name", "title",
|
|
21
|
+
"planType", "plan_type", "ProductName", "productName", "InstanceCode",
|
|
22
|
+
];
|
|
23
|
+
var USED_QUOTA_KEYS = [
|
|
24
|
+
"usedQuota", "used_quota", "usedCredits", "usedCredit", "consumedCredits", "usage", "used",
|
|
25
|
+
"usedAmount", "consumeAmount", "usedValue", "UsedValue", "consumedValue", "ConsumedValue",
|
|
26
|
+
];
|
|
27
|
+
var TOTAL_QUOTA_KEYS = [
|
|
28
|
+
"totalQuota", "total_quota", "totalCredits", "totalCredit", "quota", "creditLimit",
|
|
29
|
+
"creditsTotal", "monthlyTotalQuota", "amount", "totalValue", "TotalValue", "CycleTotalValue",
|
|
30
|
+
"cycleTotalValue", "subscriptionTotalNumber", "SubscriptionTotalNumber",
|
|
31
|
+
];
|
|
32
|
+
var REMAINING_QUOTA_KEYS = [
|
|
33
|
+
"remainingQuota", "remainQuota", "remainingCredits", "remainingCredit", "availableCredits",
|
|
34
|
+
"balance", "remaining", "availableAmount", "remainAmount", "totalSurplusValue",
|
|
35
|
+
"TotalSurplusValue", "surplusValue", "SurplusValue", "CycleSurplusValue", "cycleSurplusValue",
|
|
36
|
+
];
|
|
37
|
+
var RESET_DATE_KEYS = [
|
|
38
|
+
"nextRefreshTime", "resetTime", "periodEndTime", "billingCycleEnd", "billCycleEndTime",
|
|
39
|
+
"expireTime", "expirationTime", "endTime", "EndTime", "validEndTime", "instanceEndTime",
|
|
40
|
+
"nearestExpireDate", "NearestExpireDate",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
function trim(value) {
|
|
44
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function clean(value) {
|
|
48
|
+
var text = trim(value);
|
|
49
|
+
if (!text) return null;
|
|
50
|
+
if ((text[0] === "\"" && text[text.length - 1] === "\"") || (text[0] === "'" && text[text.length - 1] === "'")) text = text.slice(1, -1).trim();
|
|
51
|
+
return text || null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function env(ctx, name) {
|
|
55
|
+
try {
|
|
56
|
+
return clean(ctx.host.env.get(name));
|
|
57
|
+
} catch (_) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function setting(ctx, names) {
|
|
63
|
+
var settings = ctx.provider && ctx.provider.settings ? ctx.provider.settings : {};
|
|
64
|
+
for (var i = 0; i < names.length; i++) {
|
|
65
|
+
var value = clean(settings[names[i]]);
|
|
66
|
+
if (value) return value;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function normalizeCookie(raw) {
|
|
72
|
+
var text = clean(raw);
|
|
73
|
+
if (!text) return null;
|
|
74
|
+
if (text.slice(0, 7).toLowerCase() === "cookie:") text = text.slice(7).trim();
|
|
75
|
+
return text && text.indexOf("=") >= 0 ? text : null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function cookieHeader(ctx) {
|
|
79
|
+
var value = normalizeCookie(ctx.provider && ctx.provider.cookieHeader) ||
|
|
80
|
+
normalizeCookie(setting(ctx, ["cookieHeader", "cookie"])) ||
|
|
81
|
+
normalizeCookie(env(ctx, "QWEN_CLOUD_COOKIE")) ||
|
|
82
|
+
normalizeCookie(env(ctx, "QWEN_CLOUD_COOKIE_HEADER"));
|
|
83
|
+
if (!value) throw "Qwen Cloud session not configured. Set QWEN_CLOUD_COOKIE or provider cookieHeader.";
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function cookieValue(name, cookie) {
|
|
88
|
+
var parts = String(cookie || "").split(";");
|
|
89
|
+
for (var i = 0; i < parts.length; i++) {
|
|
90
|
+
var idx = parts[i].indexOf("=");
|
|
91
|
+
if (idx < 0) continue;
|
|
92
|
+
var key = parts[i].slice(0, idx).trim();
|
|
93
|
+
var value = parts[i].slice(idx + 1).trim();
|
|
94
|
+
if (key.toLowerCase() === name.toLowerCase() && value) return value;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function extractSecToken(html) {
|
|
100
|
+
var patterns = [
|
|
101
|
+
/"secToken"\s*:\s*"([^"]+)"/,
|
|
102
|
+
/"sec_token"\s*:\s*"([^"]+)"/,
|
|
103
|
+
/secToken['"]?\s*[:=]\s*['"]([^'"]+)['"]/,
|
|
104
|
+
/sec_token['"]?\s*[:=]\s*['"]([^'"]+)['"]/,
|
|
105
|
+
/csrfToken['"]?\s*[:=]\s*['"]([^'"]+)['"]/,
|
|
106
|
+
];
|
|
107
|
+
for (var i = 0; i < patterns.length; i++) {
|
|
108
|
+
var match = patterns[i].exec(String(html || ""));
|
|
109
|
+
if (match && match[1] && match[1].trim()) return match[1].trim();
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function looksLikeLogin(text) {
|
|
115
|
+
var lower = String(text || "").toLowerCase();
|
|
116
|
+
return lower.indexOf("passport.alibabacloud.com") >= 0 ||
|
|
117
|
+
lower.indexOf("signin.aliyun.com") >= 0 ||
|
|
118
|
+
lower.indexOf("account.alibabacloud.com/login") >= 0 ||
|
|
119
|
+
lower.indexOf("login.qwencloud.com") >= 0 ||
|
|
120
|
+
(lower.indexOf("login") >= 0 && lower.indexOf("password") >= 0 && lower.indexOf("sign in") >= 0);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function expandJsonStrings(value) {
|
|
124
|
+
if (Array.isArray(value)) return value.map(expandJsonStrings);
|
|
125
|
+
if (value && typeof value === "object") {
|
|
126
|
+
var out = {};
|
|
127
|
+
Object.keys(value).forEach(function (key) { out[key] = expandJsonStrings(value[key]); });
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
if (typeof value === "string") {
|
|
131
|
+
var text = value.trim();
|
|
132
|
+
if ((text[0] === "{" && text[text.length - 1] === "}") || (text[0] === "[" && text[text.length - 1] === "]")) {
|
|
133
|
+
try {
|
|
134
|
+
return expandJsonStrings(JSON.parse(text));
|
|
135
|
+
} catch (_) {}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function findFirstString(value, keys) {
|
|
142
|
+
if (Array.isArray(value)) {
|
|
143
|
+
for (var i = 0; i < value.length; i++) {
|
|
144
|
+
var found = findFirstString(value[i], keys);
|
|
145
|
+
if (found) return found;
|
|
146
|
+
}
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
if (!value || typeof value !== "object") return null;
|
|
150
|
+
for (var k = 0; k < keys.length; k++) {
|
|
151
|
+
var raw = value[keys[k]];
|
|
152
|
+
if (typeof raw === "string" && raw.trim()) return raw.trim();
|
|
153
|
+
}
|
|
154
|
+
var names = Object.keys(value);
|
|
155
|
+
for (var j = 0; j < names.length; j++) {
|
|
156
|
+
var nested = findFirstString(value[names[j]], keys);
|
|
157
|
+
if (nested) return nested;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function resolveSecToken(ctx, cookie) {
|
|
163
|
+
try {
|
|
164
|
+
var response = ctx.util.request({
|
|
165
|
+
method: "GET",
|
|
166
|
+
url: DASHBOARD_URL,
|
|
167
|
+
headers: {
|
|
168
|
+
Cookie: cookie,
|
|
169
|
+
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
170
|
+
"User-Agent": USER_AGENT,
|
|
171
|
+
},
|
|
172
|
+
timeoutMs: 10000,
|
|
173
|
+
});
|
|
174
|
+
if (response.status >= 200 && response.status < 300 && !looksLikeLogin(response.bodyText)) {
|
|
175
|
+
var token = extractSecToken(response.bodyText);
|
|
176
|
+
if (token) return token;
|
|
177
|
+
}
|
|
178
|
+
} catch (_) {}
|
|
179
|
+
|
|
180
|
+
var fromCookie = cookieValue("sec_token", cookie);
|
|
181
|
+
if (fromCookie) return fromCookie;
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
var userInfo = ctx.util.requestJson({
|
|
185
|
+
method: "GET",
|
|
186
|
+
url: GATEWAY_BASE_URL + "/tool/user/info.json",
|
|
187
|
+
headers: {
|
|
188
|
+
Cookie: cookie,
|
|
189
|
+
Accept: "application/json, text/plain, */*",
|
|
190
|
+
"User-Agent": USER_AGENT,
|
|
191
|
+
},
|
|
192
|
+
timeoutMs: 10000,
|
|
193
|
+
});
|
|
194
|
+
if (userInfo.resp.status >= 200 && userInfo.resp.status < 300 && userInfo.json) {
|
|
195
|
+
var expanded = expandJsonStrings(userInfo.json);
|
|
196
|
+
return findFirstString(expanded, ["secToken", "sec_token", "csrfToken", "token"]);
|
|
197
|
+
}
|
|
198
|
+
} catch (_) {}
|
|
199
|
+
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function apiUrl(api) {
|
|
204
|
+
return DATA_GATEWAY_BASE_URL + "/data/api.json?action=" + encodeURIComponent(CONSOLE_ACTION) +
|
|
205
|
+
"&product=" + encodeURIComponent(CONSOLE_PRODUCT) +
|
|
206
|
+
"&api=" + encodeURIComponent(api) +
|
|
207
|
+
"&_v=undefined";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function randomId() {
|
|
211
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (ch) {
|
|
212
|
+
var r = Math.floor(Math.random() * 16);
|
|
213
|
+
var v = ch === "x" ? r : (r & 3) | 8;
|
|
214
|
+
return v.toString(16);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function paramsJson(api, data, cookie) {
|
|
219
|
+
data = data || {};
|
|
220
|
+
data.cornerstoneParam = {
|
|
221
|
+
feTraceId: randomId(),
|
|
222
|
+
feURL: DASHBOARD_URL,
|
|
223
|
+
protocol: "V2",
|
|
224
|
+
console: "ONE_CONSOLE",
|
|
225
|
+
productCode: "p_efm",
|
|
226
|
+
domain: "home.qwencloud.com",
|
|
227
|
+
consoleSite: "QWENCLOUD",
|
|
228
|
+
userNickName: "",
|
|
229
|
+
userPrincipalName: "",
|
|
230
|
+
xsp_lang: LANGUAGE,
|
|
231
|
+
};
|
|
232
|
+
var cna = cookieValue("cna", cookie);
|
|
233
|
+
if (cna) data.cornerstoneParam["X-Anonymous-Id"] = cna;
|
|
234
|
+
return JSON.stringify({ Api: api, V: "1.0", Data: data });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function formBody(parts) {
|
|
238
|
+
return parts.map(function (part) {
|
|
239
|
+
return encodeURIComponent(part[0]) + "=" + encodeURIComponent(part[1]);
|
|
240
|
+
}).join("&");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function postApi(ctx, api, data, secToken, cookie, optional) {
|
|
244
|
+
var headers = {
|
|
245
|
+
Cookie: cookie,
|
|
246
|
+
Accept: "application/json, text/plain, */*",
|
|
247
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
248
|
+
Origin: GATEWAY_BASE_URL,
|
|
249
|
+
Referer: DASHBOARD_URL,
|
|
250
|
+
"User-Agent": USER_AGENT,
|
|
251
|
+
"X-Requested-With": "XMLHttpRequest",
|
|
252
|
+
};
|
|
253
|
+
var csrf = cookieValue("login_aliyunid_csrf", cookie) || cookieValue("csrf", cookie);
|
|
254
|
+
if (csrf) {
|
|
255
|
+
headers["x-xsrf-token"] = csrf;
|
|
256
|
+
headers["x-csrf-token"] = csrf;
|
|
257
|
+
}
|
|
258
|
+
var result = ctx.util.request({
|
|
259
|
+
method: "POST",
|
|
260
|
+
url: apiUrl(api),
|
|
261
|
+
headers: headers,
|
|
262
|
+
bodyText: formBody([
|
|
263
|
+
["product", CONSOLE_PRODUCT],
|
|
264
|
+
["action", CONSOLE_ACTION],
|
|
265
|
+
["sec_token", secToken],
|
|
266
|
+
["region", REGION],
|
|
267
|
+
["language", LANGUAGE],
|
|
268
|
+
["params", paramsJson(api, data, cookie)],
|
|
269
|
+
]),
|
|
270
|
+
timeoutMs: 20000,
|
|
271
|
+
});
|
|
272
|
+
if (ctx.util.isAuthStatus(result.status)) throw "Qwen Cloud login required.";
|
|
273
|
+
if (result.status < 200 || result.status >= 300) {
|
|
274
|
+
if (optional) return null;
|
|
275
|
+
throw "Qwen Cloud API error: HTTP " + result.status + ".";
|
|
276
|
+
}
|
|
277
|
+
var json = ctx.util.tryParseJson(result.bodyText);
|
|
278
|
+
if (!json) {
|
|
279
|
+
var lower = String(result.bodyText || "").toLowerCase();
|
|
280
|
+
if (lower.indexOf("<html") >= 0 && (lower.indexOf("login") >= 0 || lower.indexOf("sign in") >= 0 || lower.indexOf("signin") >= 0)) {
|
|
281
|
+
throw "Qwen Cloud login required.";
|
|
282
|
+
}
|
|
283
|
+
if (optional) return null;
|
|
284
|
+
throw "Invalid Qwen Cloud JSON response.";
|
|
285
|
+
}
|
|
286
|
+
return expandJsonStrings(json);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function parseNumber(value) {
|
|
290
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
291
|
+
if (typeof value === "string" && value.trim()) {
|
|
292
|
+
var parsed = Number(value.replace(/,/g, ""));
|
|
293
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
294
|
+
}
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function directNumber(obj, keys) {
|
|
299
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return null;
|
|
300
|
+
for (var i = 0; i < keys.length; i++) {
|
|
301
|
+
var value = parseNumber(obj[keys[i]]);
|
|
302
|
+
if (value !== null) return value;
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function directString(obj, keys) {
|
|
308
|
+
if (!obj || typeof obj !== "object" || Array.isArray(obj)) return null;
|
|
309
|
+
for (var i = 0; i < keys.length; i++) {
|
|
310
|
+
var value = obj[keys[i]];
|
|
311
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function parseBool(value) {
|
|
317
|
+
if (typeof value === "boolean") return value;
|
|
318
|
+
if (typeof value === "number") return value !== 0;
|
|
319
|
+
if (typeof value === "string") {
|
|
320
|
+
var lower = value.trim().toLowerCase();
|
|
321
|
+
if (/^(true|1|yes|active|valid|normal)$/.test(lower)) return true;
|
|
322
|
+
if (/^(false|0|no|inactive|invalid|expired)$/.test(lower)) return false;
|
|
323
|
+
}
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function findFirstNumber(value, keys) {
|
|
328
|
+
if (Array.isArray(value)) {
|
|
329
|
+
for (var i = 0; i < value.length; i++) {
|
|
330
|
+
var inArray = findFirstNumber(value[i], keys);
|
|
331
|
+
if (inArray !== null) return inArray;
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (!value || typeof value !== "object") return null;
|
|
336
|
+
var direct = directNumber(value, keys);
|
|
337
|
+
if (direct !== null) return direct;
|
|
338
|
+
var names = Object.keys(value);
|
|
339
|
+
for (var j = 0; j < names.length; j++) {
|
|
340
|
+
var nested = findFirstNumber(value[names[j]], keys);
|
|
341
|
+
if (nested !== null) return nested;
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function findFirstBool(value, keys) {
|
|
347
|
+
if (Array.isArray(value)) {
|
|
348
|
+
for (var i = 0; i < value.length; i++) {
|
|
349
|
+
var inArray = findFirstBool(value[i], keys);
|
|
350
|
+
if (inArray !== null) return inArray;
|
|
351
|
+
}
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
if (!value || typeof value !== "object") return null;
|
|
355
|
+
for (var k = 0; k < keys.length; k++) {
|
|
356
|
+
var direct = parseBool(value[keys[k]]);
|
|
357
|
+
if (direct !== null) return direct;
|
|
358
|
+
}
|
|
359
|
+
var names = Object.keys(value);
|
|
360
|
+
for (var j = 0; j < names.length; j++) {
|
|
361
|
+
var nested = findFirstBool(value[names[j]], keys);
|
|
362
|
+
if (nested !== null) return nested;
|
|
363
|
+
}
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function throwIfErrorPayload(value) {
|
|
368
|
+
var code = findFirstNumber(value, ["statusCode", "status_code", "code"]);
|
|
369
|
+
if (code !== null && code !== 0 && code !== 200) {
|
|
370
|
+
if (code === 401 || code === 403) throw "Qwen Cloud login required.";
|
|
371
|
+
throw "Qwen Cloud API error: " + (findFirstString(value, ["statusMessage", "status_msg", "message", "msg"]) || "status code " + code);
|
|
372
|
+
}
|
|
373
|
+
var success = findFirstBool(value, ["success", "Success", "successResponse"]);
|
|
374
|
+
if (success === false) {
|
|
375
|
+
var message = findFirstString(value, ["message", "msg", "Message", "errorMessage"]) || "request failed";
|
|
376
|
+
var lower = message.toLowerCase();
|
|
377
|
+
if (lower.indexOf("login") >= 0 || lower.indexOf("unauthorized") >= 0) throw "Qwen Cloud login required.";
|
|
378
|
+
throw "Qwen Cloud API error: " + message;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function parseDate(ctx, value) {
|
|
383
|
+
var n = parseNumber(value);
|
|
384
|
+
if (n !== null && n > 1000000000) return ctx.util.toIso(n);
|
|
385
|
+
var text = trim(value);
|
|
386
|
+
if (!text) return null;
|
|
387
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(text)) return ctx.util.toIso(text + "T00:00:00Z");
|
|
388
|
+
if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}/.test(text)) return ctx.util.toIso(text.replace(" ", "T") + "Z");
|
|
389
|
+
return ctx.util.toIso(text);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function findFirstDate(ctx, value, keys) {
|
|
393
|
+
if (Array.isArray(value)) {
|
|
394
|
+
for (var i = 0; i < value.length; i++) {
|
|
395
|
+
var inArray = findFirstDate(ctx, value[i], keys);
|
|
396
|
+
if (inArray) return inArray;
|
|
397
|
+
}
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
if (!value || typeof value !== "object") return null;
|
|
401
|
+
for (var k = 0; k < keys.length; k++) {
|
|
402
|
+
var direct = parseDate(ctx, value[keys[k]]);
|
|
403
|
+
if (direct) return direct;
|
|
404
|
+
}
|
|
405
|
+
var names = Object.keys(value);
|
|
406
|
+
for (var j = 0; j < names.length; j++) {
|
|
407
|
+
var nested = findFirstDate(ctx, value[names[j]], keys);
|
|
408
|
+
if (nested) return nested;
|
|
409
|
+
}
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function findObjectContaining(value, keys) {
|
|
414
|
+
if (Array.isArray(value)) {
|
|
415
|
+
for (var i = 0; i < value.length; i++) {
|
|
416
|
+
var found = findObjectContaining(value[i], keys);
|
|
417
|
+
if (found) return found;
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
if (!value || typeof value !== "object") return null;
|
|
422
|
+
for (var k = 0; k < keys.length; k++) {
|
|
423
|
+
if (Object.prototype.hasOwnProperty.call(value, keys[k])) return value;
|
|
424
|
+
}
|
|
425
|
+
var names = Object.keys(value);
|
|
426
|
+
for (var j = 0; j < names.length; j++) {
|
|
427
|
+
var nested = findObjectContaining(value[names[j]], keys);
|
|
428
|
+
if (nested) return nested;
|
|
429
|
+
}
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function findObjectByKeys(value, keys) {
|
|
434
|
+
if (Array.isArray(value)) {
|
|
435
|
+
for (var i = 0; i < value.length; i++) {
|
|
436
|
+
var found = findObjectByKeys(value[i], keys);
|
|
437
|
+
if (found) return found;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
if (!value || typeof value !== "object") return null;
|
|
442
|
+
for (var k = 0; k < keys.length; k++) {
|
|
443
|
+
if (value[keys[k]] && typeof value[keys[k]] === "object" && !Array.isArray(value[keys[k]])) return value[keys[k]];
|
|
444
|
+
}
|
|
445
|
+
var names = Object.keys(value);
|
|
446
|
+
for (var j = 0; j < names.length; j++) {
|
|
447
|
+
var nested = findObjectByKeys(value[names[j]], keys);
|
|
448
|
+
if (nested) return nested;
|
|
449
|
+
}
|
|
450
|
+
return null;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function findArrayByKeys(value, keys) {
|
|
454
|
+
if (Array.isArray(value)) {
|
|
455
|
+
for (var i = 0; i < value.length; i++) {
|
|
456
|
+
var found = findArrayByKeys(value[i], keys);
|
|
457
|
+
if (found) return found;
|
|
458
|
+
}
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
if (!value || typeof value !== "object") return null;
|
|
462
|
+
for (var k = 0; k < keys.length; k++) {
|
|
463
|
+
if (Array.isArray(value[keys[k]])) return value[keys[k]];
|
|
464
|
+
}
|
|
465
|
+
var names = Object.keys(value);
|
|
466
|
+
for (var j = 0; j < names.length; j++) {
|
|
467
|
+
var nested = findArrayByKeys(value[names[j]], keys);
|
|
468
|
+
if (nested) return nested;
|
|
469
|
+
}
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function activeSignalScore(obj) {
|
|
474
|
+
var status = String(directString(obj, ["status", "instanceStatus", "state", "Status"]) || "").toUpperCase();
|
|
475
|
+
if (/^(VALID|ACTIVE|NORMAL)$/.test(status)) return 3;
|
|
476
|
+
if (/^(EXPIRED|INVALID|INACTIVE|DISABLED|TERMINATED|STOPPED)$/.test(status)) return -1;
|
|
477
|
+
var active = parseBool(obj && (obj.isActive !== undefined ? obj.isActive : obj.active));
|
|
478
|
+
return active === null ? 0 : active ? 3 : -1;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function findTokenPlanInstance(value) {
|
|
482
|
+
var object = findObjectByKeys(value, ["tokenPlanInstanceInfo", "token_plan_instance_info", "instanceInfo", "instance_info"]);
|
|
483
|
+
if (object) return object;
|
|
484
|
+
var array = findArrayByKeys(value, ["tokenPlanInstanceInfos", "token_plan_instance_infos", "instanceInfos", "instances", "EquityList", "Data", "data", "successResponse"]);
|
|
485
|
+
if (!array) return null;
|
|
486
|
+
var best = null;
|
|
487
|
+
var bestScore = -999;
|
|
488
|
+
for (var i = 0; i < array.length; i++) {
|
|
489
|
+
if (!array[i] || typeof array[i] !== "object" || Array.isArray(array[i])) continue;
|
|
490
|
+
var score = activeSignalScore(array[i]);
|
|
491
|
+
if (!best || score > bestScore) {
|
|
492
|
+
best = array[i];
|
|
493
|
+
bestScore = score;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return best;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function findObjectWithQuotaKeys(value) {
|
|
500
|
+
if (Array.isArray(value)) {
|
|
501
|
+
for (var i = 0; i < value.length; i++) {
|
|
502
|
+
var found = findObjectWithQuotaKeys(value[i]);
|
|
503
|
+
if (found) return found;
|
|
504
|
+
}
|
|
505
|
+
return null;
|
|
506
|
+
}
|
|
507
|
+
if (!value || typeof value !== "object") return null;
|
|
508
|
+
var all = USED_QUOTA_KEYS.concat(TOTAL_QUOTA_KEYS).concat(REMAINING_QUOTA_KEYS);
|
|
509
|
+
for (var k = 0; k < all.length; k++) {
|
|
510
|
+
if (Object.prototype.hasOwnProperty.call(value, all[k])) return value;
|
|
511
|
+
}
|
|
512
|
+
var names = Object.keys(value);
|
|
513
|
+
for (var j = 0; j < names.length; j++) {
|
|
514
|
+
var nested = findObjectWithQuotaKeys(value[names[j]]);
|
|
515
|
+
if (nested) return nested;
|
|
516
|
+
}
|
|
517
|
+
return null;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function planNameFromResponse(value) {
|
|
521
|
+
var plan = findObjectContaining(value, ["specCode", "spec_code", "planName", "plan_name"]);
|
|
522
|
+
if (!plan) return null;
|
|
523
|
+
var code = directString(plan, ["specCode", "spec_code", "planName", "plan_name"]);
|
|
524
|
+
if (!code) return null;
|
|
525
|
+
var lower = code.toLowerCase();
|
|
526
|
+
if (lower === "lite") return "Lite";
|
|
527
|
+
if (lower === "standard") return "Standard";
|
|
528
|
+
if (lower === "pro") return "Pro";
|
|
529
|
+
if (lower === "max") return "Max";
|
|
530
|
+
return code;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function quotaTotalsForPlan(quotaConfig, planName) {
|
|
534
|
+
if (!quotaConfig || !planName) return { five: null, weekly: null };
|
|
535
|
+
var target = planName.toLowerCase();
|
|
536
|
+
var found = findFirstValueForKey(quotaConfig, target);
|
|
537
|
+
if (!found || typeof found !== "object") return { five: null, weekly: null };
|
|
538
|
+
return {
|
|
539
|
+
five: parseNumber(found.five_hour) || parseNumber(found.fiveHour),
|
|
540
|
+
weekly: parseNumber(found.weekly),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function findFirstValueForKey(value, key) {
|
|
545
|
+
if (Array.isArray(value)) {
|
|
546
|
+
for (var i = 0; i < value.length; i++) {
|
|
547
|
+
var found = findFirstValueForKey(value[i], key);
|
|
548
|
+
if (found !== null) return found;
|
|
549
|
+
}
|
|
550
|
+
return null;
|
|
551
|
+
}
|
|
552
|
+
if (!value || typeof value !== "object") return null;
|
|
553
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) return value[key];
|
|
554
|
+
var names = Object.keys(value);
|
|
555
|
+
for (var j = 0; j < names.length; j++) {
|
|
556
|
+
var nested = findFirstValueForKey(value[names[j]], key);
|
|
557
|
+
if (nested !== null) return nested;
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function percentagePoints(value) {
|
|
563
|
+
var n = parseNumber(value);
|
|
564
|
+
if (n === null) return null;
|
|
565
|
+
return Math.max(0, Math.min(100, Math.max(0, Math.min(1, n)) * 100));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function usedPercent(used, total, remaining) {
|
|
569
|
+
if (total === null || total <= 0) return null;
|
|
570
|
+
if (used === null && remaining !== null) used = total - remaining;
|
|
571
|
+
if (used === null) return null;
|
|
572
|
+
return Math.max(0, Math.min(100, Math.max(0, Math.min(total, used)) / total * 100));
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function parseCurrent(ctx, usage, subscription, quotaConfig) {
|
|
576
|
+
var record = findObjectContaining(usage, ["per5HourPercentage", "per1WeekPercentage"]);
|
|
577
|
+
if (!record) return null;
|
|
578
|
+
var five = percentagePoints(record.per5HourPercentage);
|
|
579
|
+
var weekly = percentagePoints(record.per1WeekPercentage);
|
|
580
|
+
if (five === null && weekly === null) return null;
|
|
581
|
+
var plan = subscription ? planNameFromResponse(subscription) : null;
|
|
582
|
+
var totals = quotaConfig ? quotaTotalsForPlan(quotaConfig, plan) : { five: null, weekly: null };
|
|
583
|
+
return {
|
|
584
|
+
planName: plan,
|
|
585
|
+
fivePercent: five,
|
|
586
|
+
fiveTotal: totals.five,
|
|
587
|
+
fiveReset: parseDate(ctx, record.per5HourResetTime),
|
|
588
|
+
weeklyPercent: weekly,
|
|
589
|
+
weeklyTotal: totals.weekly,
|
|
590
|
+
weeklyReset: parseDate(ctx, record.per1WeekResetTime),
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function parseLegacy(ctx, payload) {
|
|
595
|
+
var instance = findTokenPlanInstance(payload);
|
|
596
|
+
var scope = instance || payload;
|
|
597
|
+
var quota = findObjectByKeys(scope, ["quotaInfo", "quota_info", "tokenPlanQuotaInfo", "token_plan_quota_info"]) ||
|
|
598
|
+
findObjectWithQuotaKeys(scope) ||
|
|
599
|
+
findObjectWithQuotaKeys(payload);
|
|
600
|
+
var used = quota ? directNumber(quota, USED_QUOTA_KEYS) : null;
|
|
601
|
+
var total = quota ? directNumber(quota, TOTAL_QUOTA_KEYS) : null;
|
|
602
|
+
var remaining = quota ? directNumber(quota, REMAINING_QUOTA_KEYS) : null;
|
|
603
|
+
if (used === null) used = findFirstNumber(scope, USED_QUOTA_KEYS);
|
|
604
|
+
if (total === null) total = findFirstNumber(scope, TOTAL_QUOTA_KEYS);
|
|
605
|
+
if (remaining === null) remaining = findFirstNumber(scope, REMAINING_QUOTA_KEYS);
|
|
606
|
+
var percent = usedPercent(used, total, remaining);
|
|
607
|
+
if (percent === null) throw "Qwen Cloud has no active token-plan subscription.";
|
|
608
|
+
return {
|
|
609
|
+
planName: directString(scope, PLAN_NAME_KEYS) || findFirstString(payload, PLAN_NAME_KEYS),
|
|
610
|
+
used: used,
|
|
611
|
+
total: total,
|
|
612
|
+
remaining: remaining,
|
|
613
|
+
percent: percent,
|
|
614
|
+
reset: findFirstDate(ctx, scope, RESET_DATE_KEYS) || findFirstDate(ctx, payload, RESET_DATE_KEYS),
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
function formatQuota(value) {
|
|
619
|
+
if (!Number.isFinite(value)) return "";
|
|
620
|
+
var rounded = Math.round(value);
|
|
621
|
+
if (Math.abs(rounded - value) < 0.000001) return String(rounded).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
622
|
+
return value.toFixed(2).replace(/\.?0+$/, "").replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function quotaDetail(percent, total) {
|
|
626
|
+
if (!total || total <= 0) return null;
|
|
627
|
+
return formatQuota(total * percent / 100) + " / " + formatQuota(total) + " credits used";
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
function progress(ctx, label, percent, periodMs, reset, detail) {
|
|
631
|
+
var opts = {
|
|
632
|
+
label: label,
|
|
633
|
+
used: Math.max(0, Math.min(100, percent)),
|
|
634
|
+
limit: 100,
|
|
635
|
+
format: { kind: "percent" },
|
|
636
|
+
periodDurationMs: periodMs,
|
|
637
|
+
};
|
|
638
|
+
if (reset) opts.resetsAt = reset;
|
|
639
|
+
if (detail) opts.detail = detail;
|
|
640
|
+
return ctx.line.progress(opts);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function snapshotToResult(ctx, snapshot) {
|
|
644
|
+
var lines = [];
|
|
645
|
+
if (snapshot.fivePercent !== undefined) {
|
|
646
|
+
if (snapshot.fivePercent !== null) {
|
|
647
|
+
lines.push(progress(ctx, "5-hour", snapshot.fivePercent, FIVE_HOUR_MS, snapshot.fiveReset, quotaDetail(snapshot.fivePercent, snapshot.fiveTotal)));
|
|
648
|
+
} else if (snapshot.percent !== null && snapshot.percent !== undefined) {
|
|
649
|
+
lines.push(progress(ctx, "Credits", snapshot.percent, LEGACY_MS, snapshot.reset, snapshot.used !== null && snapshot.total !== null ? formatQuota(snapshot.used) + " / " + formatQuota(snapshot.total) + " credits used" : null));
|
|
650
|
+
}
|
|
651
|
+
if (snapshot.weeklyPercent !== null && snapshot.weeklyPercent !== undefined) {
|
|
652
|
+
lines.push(progress(ctx, "Weekly", snapshot.weeklyPercent, WEEKLY_MS, snapshot.weeklyReset, quotaDetail(snapshot.weeklyPercent, snapshot.weeklyTotal)));
|
|
653
|
+
}
|
|
654
|
+
} else {
|
|
655
|
+
lines.push(progress(ctx, "Credits", snapshot.percent, LEGACY_MS, snapshot.reset, snapshot.used !== null && snapshot.total !== null ? formatQuota(snapshot.used) + " / " + formatQuota(snapshot.total) + " credits used" : null));
|
|
656
|
+
}
|
|
657
|
+
if (!lines.length && snapshot.weeklyPercent !== null && snapshot.weeklyPercent !== undefined) {
|
|
658
|
+
lines.push(progress(ctx, "Weekly", snapshot.weeklyPercent, WEEKLY_MS, snapshot.weeklyReset, quotaDetail(snapshot.weeklyPercent, snapshot.weeklyTotal)));
|
|
659
|
+
}
|
|
660
|
+
if (!lines.length) throw "Qwen Cloud usage windows missing.";
|
|
661
|
+
return { displayName: "Qwen Cloud", source: "web", plan: snapshot.planName, lines: lines };
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function probe(ctx) {
|
|
665
|
+
var cookie = cookieHeader(ctx);
|
|
666
|
+
var secToken = resolveSecToken(ctx, cookie);
|
|
667
|
+
if (!secToken) throw "Qwen Cloud login required.";
|
|
668
|
+
var usage = postApi(ctx, USAGE_API, {}, secToken, cookie, false);
|
|
669
|
+
throwIfErrorPayload(usage);
|
|
670
|
+
var subscription = postApi(ctx, SUBSCRIPTION_API, { commodityCode: PRODUCT_CODE }, secToken, cookie, true);
|
|
671
|
+
var quotaConfig = postApi(ctx, QUOTA_CONFIG_API, {}, secToken, cookie, true);
|
|
672
|
+
var snapshot = parseCurrent(ctx, usage, subscription, quotaConfig) || parseLegacy(ctx, usage);
|
|
673
|
+
return snapshotToResult(ctx, snapshot);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
globalThis.__openusage_plugin = { id: "qwencloud", probe: probe };
|
|
677
|
+
})();
|