()
| 263 | } |
| 264 | |
| 265 | protected override async openConnection(): Promise<void> { |
| 266 | const token = await this.refreshTokenIfNeeded(); |
| 267 | if (!token) { |
| 268 | this.readiness = 'configured'; |
| 269 | this.emitStatusChange(); |
| 270 | this.scheduleReconnect(); |
| 271 | return; |
| 272 | } |
| 273 | try { |
| 274 | const response = await proxiedFetch(`${DINGTALK_API}/v1.0/gateway/connections/open`, { |
| 275 | method: 'POST', |
| 276 | headers: { |
| 277 | 'Content-Type': 'application/json', |
| 278 | 'x-acs-dingtalk-access-token': token, |
| 279 | }, |
| 280 | body: JSON.stringify({ |
| 281 | clientId: this.settings.appId?.trim(), |
| 282 | clientSecret: this.settings.appSecret?.trim(), |
| 283 | subscriptions: [ |
| 284 | { type: 'EVENT', topic: '*' }, |
| 285 | { type: 'CALLBACK', topic: DINGTALK_TOPIC_BOT_MESSAGES }, |
| 286 | ], |
| 287 | ua: 'Maka/0.1', |
| 288 | localIp: '127.0.0.1', |
| 289 | }), |
| 290 | timeoutMs: 10_000, |
| 291 | }); |
| 292 | const json = (await response |
| 293 | .json() |
| 294 | .catch(() => null)) as DingTalkConnectionOpenResponse | null; |
| 295 | if ( |
| 296 | !response.ok || |
| 297 | !json || |
| 298 | typeof json.endpoint !== 'string' || |
| 299 | typeof json.ticket !== 'string' |
| 300 | ) { |
| 301 | this.reason = `connections-open-${response.status}`; |
| 302 | this.readiness = 'configured'; |
| 303 | this.emitStatusChange(); |
| 304 | this.scheduleReconnect(); |
| 305 | return; |
| 306 | } |
| 307 | this.connect(`${json.endpoint}?ticket=${encodeURIComponent(json.ticket)}`); |
| 308 | } catch (error) { |
| 309 | this.reason = error instanceof Error ? error.message : String(error); |
| 310 | this.readiness = 'configured'; |
| 311 | this.emitStatusChange(); |
| 312 | this.scheduleReconnect(); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | protected override handleWsMessage(raw: string): void { |
| 317 | let frame: DingTalkStreamFrame; |
no test coverage detected