@@ -6,10 +6,12 @@
|
6 | 6 | * globals, fully supporting multi-account concurrent operation. |
7 | 7 | */ |
8 | 8 | |
| 9 | +import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime"; |
9 | 10 | import type { EngineLogger } from "../types.js"; |
10 | 11 | import { formatErrorMessage } from "../utils/format.js"; |
11 | 12 | |
12 | 13 | const TOKEN_URL = "https://bots.qq.com/app/getAppAccessToken"; |
| 14 | +const DEFAULT_TOKEN_EXPIRES_IN_SECONDS = 7200; |
13 | 15 | |
14 | 16 | interface CachedToken { |
15 | 17 | token: string; |
@@ -24,6 +26,17 @@ interface BackgroundRefreshOptions {
|
24 | 26 | retryDelayMs?: number; |
25 | 27 | } |
26 | 28 | |
| 29 | +function resolveTokenExpiresInSeconds(value: unknown): number { |
| 30 | +const parsed = parseStrictPositiveInteger(value); |
| 31 | +if (parsed !== undefined) { |
| 32 | +return parsed; |
| 33 | +} |
| 34 | +if (value == null || (typeof value === "number" && !Number.isFinite(value))) { |
| 35 | +return DEFAULT_TOKEN_EXPIRES_IN_SECONDS; |
| 36 | +} |
| 37 | +return 0; |
| 38 | +} |
| 39 | + |
27 | 40 | /** |
28 | 41 | * Per-appId token manager with caching, singleflight, and background refresh. |
29 | 42 | * |
@@ -239,7 +252,7 @@ export class TokenManager {
|
239 | 252 | const logBody = rawBody.replace(/"access_token"\s*:\s*"[^"]+"/g, '"access_token": "***"'); |
240 | 253 | this.logger?.debug?.(`[qqbot:token:${appId}] <<< Body: ${logBody}`); |
241 | 254 | |
242 | | -let data: { access_token?: string; expires_in?: number }; |
| 255 | +let data: { access_token?: string; expires_in?: unknown }; |
243 | 256 | try { |
244 | 257 | data = JSON.parse(rawBody); |
245 | 258 | } catch { |
@@ -250,7 +263,7 @@ export class TokenManager {
|
250 | 263 | throw new Error(`Failed to get access_token: ${JSON.stringify(data)}`); |
251 | 264 | } |
252 | 265 | |
253 | | -const expiresAt = Date.now() + (data.expires_in ?? 7200) * 1000; |
| 266 | +const expiresAt = Date.now() + resolveTokenExpiresInSeconds(data.expires_in) * 1000; |
254 | 267 | this.cache.set(appId, { token: data.access_token, expiresAt, appId }); |
255 | 268 | this.logger?.debug?.( |
256 | 269 | `[qqbot:token:${appId}] Cached, expires at: ${new Date(expiresAt).toISOString()}`, |
|