@satorijs/adapter-dingtalk 2.5.0 → 2.5.1

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.
Files changed (3) hide show
  1. package/lib/index.cjs +19 -1
  2. package/package.json +1 -1
  3. package/src/ws.ts +20 -1
package/lib/index.cjs CHANGED
@@ -282,6 +282,9 @@ var WsClient = class extends import_core4.Adapter.WsClient {
282
282
  }
283
283
  accept() {
284
284
  this.bot.online();
285
+ const handledMessageIds = /* @__PURE__ */ new Set();
286
+ const handledMessageQueue = [];
287
+ const handledMessageLimit = 100;
285
288
  this.socket.addEventListener("message", async ({ data }) => {
286
289
  const parsed = JSON.parse(data.toString());
287
290
  this.bot.logger.debug(parsed);
@@ -297,7 +300,21 @@ var WsClient = class extends import_core4.Adapter.WsClient {
297
300
  } else if (parsed.type === "CALLBACK") {
298
301
  this.bot.logger.debug(JSON.parse(parsed.data));
299
302
  const session = await decodeMessage(this.bot, JSON.parse(parsed.data));
300
- if (session) this.bot.dispatch(session);
303
+ if (session) {
304
+ const messageId = session.messageId;
305
+ if (messageId && handledMessageIds.has(messageId)) {
306
+ this.bot.logger.debug("duplicate message %s, skipped", messageId);
307
+ } else {
308
+ this.bot.dispatch(session);
309
+ if (messageId) {
310
+ handledMessageIds.add(messageId);
311
+ handledMessageQueue.push(messageId);
312
+ if (handledMessageQueue.length > handledMessageLimit) {
313
+ handledMessageIds.delete(handledMessageQueue.shift());
314
+ }
315
+ }
316
+ }
317
+ }
301
318
  this.bot.logger.debug(session);
302
319
  }
303
320
  });
@@ -314,6 +331,7 @@ var Internal = class _Internal {
314
331
  constructor(bot) {
315
332
  this.bot = bot;
316
333
  }
334
+ bot;
317
335
  static {
318
336
  __name(this, "Internal");
319
337
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@satorijs/adapter-dingtalk",
3
3
  "description": "DingTalk (钉钉) Adapter for Satorijs",
4
- "version": "2.5.0",
4
+ "version": "2.5.1",
5
5
  "type": "module",
6
6
  "main": "lib/index.cjs",
7
7
  "typings": "lib/index.d.ts",
package/src/ws.ts CHANGED
@@ -25,6 +25,11 @@ export class WsClient<C extends Context = Context> extends Adapter.WsClient<C, D
25
25
 
26
26
  accept() {
27
27
  this.bot.online()
28
+ // DingTalk Stream API may redeliver the same event within a short window to avoid delivery loss.
29
+ // Keep a small in-memory dedup window per connection as a minimal idempotency guard.
30
+ const handledMessageIds = new Set<string>()
31
+ const handledMessageQueue: string[] = []
32
+ const handledMessageLimit = 100
28
33
  this.socket.addEventListener('message', async ({ data }) => {
29
34
  const parsed = JSON.parse(data.toString())
30
35
  this.bot.logger.debug(parsed)
@@ -40,7 +45,21 @@ export class WsClient<C extends Context = Context> extends Adapter.WsClient<C, D
40
45
  } else if (parsed.type === 'CALLBACK') {
41
46
  this.bot.logger.debug(JSON.parse(parsed.data))
42
47
  const session = await decodeMessage(this.bot, JSON.parse(parsed.data))
43
- if (session) this.bot.dispatch(session)
48
+ if (session) {
49
+ const messageId = session.messageId
50
+ if (messageId && handledMessageIds.has(messageId)) {
51
+ this.bot.logger.debug('duplicate message %s, skipped', messageId)
52
+ } else {
53
+ this.bot.dispatch(session)
54
+ if (messageId) {
55
+ handledMessageIds.add(messageId)
56
+ handledMessageQueue.push(messageId)
57
+ if (handledMessageQueue.length > handledMessageLimit) {
58
+ handledMessageIds.delete(handledMessageQueue.shift()!)
59
+ }
60
+ }
61
+ }
62
+ }
44
63
  this.bot.logger.debug(session)
45
64
  }
46
65
  })