|
| 1 | +import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime"; |
1 | 2 | /** |
2 | 3 | * Feishu app registration via OAuth device-code flow. |
3 | 4 | * |
@@ -19,6 +20,8 @@ const LARK_ACCOUNTS_URL = "https://accounts.larksuite.com";
|
19 | 20 | const REGISTRATION_PATH = "/oauth/v1/app/registration"; |
20 | 21 | |
21 | 22 | const REQUEST_TIMEOUT_MS = 10_000; |
| 23 | +const DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS = 5; |
| 24 | +const DEFAULT_REGISTRATION_EXPIRE_SECONDS = 600; |
22 | 25 | |
23 | 26 | // --------------------------------------------------------------------------- |
24 | 27 | // Types |
@@ -151,8 +154,14 @@ export async function beginAppRegistration(domain: FeishuDomain = "feishu"): Pro
|
151 | 154 | deviceCode: res.device_code, |
152 | 155 | qrUrl: qrUrl.toString(), |
153 | 156 | userCode: res.user_code, |
154 | | -interval: res.interval || 5, |
155 | | -expireIn: res.expire_in || 600, |
| 157 | +interval: |
| 158 | +finiteSecondsToTimerSafeMilliseconds(res.interval) === undefined |
| 159 | + ? DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS |
| 160 | + : res.interval, |
| 161 | +expireIn: |
| 162 | +finiteSecondsToTimerSafeMilliseconds(res.expire_in) === undefined |
| 163 | + ? DEFAULT_REGISTRATION_EXPIRE_SECONDS |
| 164 | + : res.expire_in, |
156 | 165 | }; |
157 | 166 | } |
158 | 167 | |
@@ -175,7 +184,11 @@ export async function pollAppRegistration(params: {
|
175 | 184 | let domain: FeishuDomain = initialDomain; |
176 | 185 | let domainSwitched = false; |
177 | 186 | |
178 | | -const deadline = Date.now() + expireIn * 1000; |
| 187 | +const expireInMs = |
| 188 | +finiteSecondsToTimerSafeMilliseconds(expireIn) ?? |
| 189 | +finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_EXPIRE_SECONDS) ?? |
| 190 | +REQUEST_TIMEOUT_MS; |
| 191 | +const deadline = Date.now() + expireInMs; |
179 | 192 | |
180 | 193 | while (Date.now() < deadline) { |
181 | 194 | if (abortSignal?.aborted) { |
@@ -193,7 +206,7 @@ export async function pollAppRegistration(params: {
|
193 | 206 | }); |
194 | 207 | } catch { |
195 | 208 | // Transient network error — keep polling. |
196 | | -await sleep(currentInterval * 1000); |
| 209 | +await sleepRegistrationPollInterval(currentInterval); |
197 | 210 | continue; |
198 | 211 | } |
199 | 212 | |
@@ -239,7 +252,7 @@ export async function pollAppRegistration(params: {
|
239 | 252 | } |
240 | 253 | } |
241 | 254 | |
242 | | -await sleep(currentInterval * 1000); |
| 255 | +await sleepRegistrationPollInterval(currentInterval); |
243 | 256 | } |
244 | 257 | |
245 | 258 | return { status: "timeout" }; |
@@ -329,3 +342,11 @@ export async function getAppOwnerOpenId(params: {
|
329 | 342 | function sleep(ms: number): Promise<void> { |
330 | 343 | return new Promise((resolve) => setTimeout(resolve, ms)); |
331 | 344 | } |
| 345 | + |
| 346 | +function sleepRegistrationPollInterval(intervalSeconds: number): Promise<void> { |
| 347 | +const intervalMs = |
| 348 | +finiteSecondsToTimerSafeMilliseconds(intervalSeconds) ?? |
| 349 | +finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS) ?? |
| 350 | +REQUEST_TIMEOUT_MS; |
| 351 | +return sleep(intervalMs); |
| 352 | +} |