@openclaw/synology-chat 2026.5.22 → 2026.5.24-beta.2

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/dist/api.js CHANGED
@@ -1,3 +1,3 @@
1
- import { n as setSynologyRuntime, t as synologyChatPlugin } from "./channel-QNW5XjB7.js";
1
+ import { n as setSynologyRuntime, t as synologyChatPlugin } from "./channel-bDcSUMFI.js";
2
2
  import { t as collectSynologyChatSecurityAuditFindings } from "./security-audit-DIsaxIaB.js";
3
3
  export { collectSynologyChatSecurityAuditFindings, setSynologyRuntime, synologyChatPlugin };
@@ -46,6 +46,7 @@ const synologyChatApprovalAuth = createResolvedApproverActionAuthAdapter({
46
46
  */
47
47
  const MIN_SEND_INTERVAL_MS = 500;
48
48
  let lastSendTime = 0;
49
+ let sendQueue = Promise.resolve();
49
50
  const ChatUserSchema = z.object({
50
51
  user_id: z.number(),
51
52
  username: z.string().optional(),
@@ -74,15 +75,12 @@ const CACHE_TTL_MS = 300 * 1e3;
74
75
  */
75
76
  async function sendMessage(incomingUrl, text, userId, allowInsecureSsl = false) {
76
77
  const body = buildWebhookBody({ text }, userId);
77
- const elapsed = Date.now() - lastSendTime;
78
- if (elapsed < MIN_SEND_INTERVAL_MS) await sleep(MIN_SEND_INTERVAL_MS - elapsed);
79
78
  const maxRetries = 3;
80
79
  const baseDelay = 300;
81
80
  for (let attempt = 0; attempt < maxRetries; attempt++) {
82
81
  try {
83
- const ok = await doPost(incomingUrl, body, allowInsecureSsl);
84
- lastSendTime = Date.now();
85
- if (ok) return true;
82
+ await waitForSendSlot();
83
+ if (await doPost(incomingUrl, body, allowInsecureSsl)) return true;
86
84
  } catch {}
87
85
  if (attempt < maxRetries - 1) await sleep(baseDelay * 2 ** attempt);
88
86
  }
@@ -94,11 +92,8 @@ async function sendMessage(incomingUrl, text, userId, allowInsecureSsl = false)
94
92
  async function sendFileUrl(incomingUrl, fileUrl, userId, allowInsecureSsl = false) {
95
93
  try {
96
94
  const body = buildWebhookBody({ file_url: await assertSafeWebhookFileUrl(fileUrl) }, userId);
97
- const elapsed = Date.now() - lastSendTime;
98
- if (elapsed < MIN_SEND_INTERVAL_MS) await sleep(MIN_SEND_INTERVAL_MS - elapsed);
99
- const ok = await doPost(incomingUrl, body, allowInsecureSsl);
100
- lastSendTime = Date.now();
101
- return ok;
95
+ await waitForSendSlot();
96
+ return await doPost(incomingUrl, body, allowInsecureSsl);
102
97
  } catch {
103
98
  return false;
104
99
  }
@@ -116,17 +111,23 @@ async function fetchChatUsers(incomingUrl, allowInsecureSsl = false, log) {
116
111
  const cached = chatUserCache.get(listUrl);
117
112
  if (cached && now - cached.cachedAt < CACHE_TTL_MS) return cached.users;
118
113
  return new Promise((resolve) => {
114
+ let settled = false;
115
+ const finish = (users) => {
116
+ if (settled) return;
117
+ settled = true;
118
+ resolve(users);
119
+ };
119
120
  let parsedUrl;
120
121
  try {
121
122
  parsedUrl = new URL(listUrl);
122
123
  } catch {
123
124
  log?.warn("fetchChatUsers: invalid user_list URL, using cached data");
124
- resolve(cached?.users ?? []);
125
+ finish(cached?.users ?? []);
125
126
  return;
126
127
  }
127
128
  const transport = parsedUrl.protocol === "https:" ? https : http;
128
129
  const requestOptions = parsedUrl.protocol === "https:" ? { rejectUnauthorized: !allowInsecureSsl } : {};
129
- transport.get(listUrl, requestOptions, (res) => {
130
+ const req = transport.get(listUrl, requestOptions, (res) => {
130
131
  let data = "";
131
132
  res.on("data", (c) => {
132
133
  data += c.toString();
@@ -135,7 +136,7 @@ async function fetchChatUsers(incomingUrl, allowInsecureSsl = false, log) {
135
136
  const result = safeParseJsonWithSchema(ChatUserListResponseSchema, data);
136
137
  if (!result) {
137
138
  log?.warn("fetchChatUsers: failed to parse user_list response");
138
- resolve(cached?.users ?? []);
139
+ finish(cached?.users ?? []);
139
140
  return;
140
141
  }
141
142
  if (result.success) {
@@ -144,18 +145,32 @@ async function fetchChatUsers(incomingUrl, allowInsecureSsl = false, log) {
144
145
  users,
145
146
  cachedAt: now
146
147
  });
147
- resolve(users);
148
+ finish(users);
148
149
  return;
149
150
  }
150
151
  log?.warn(`fetchChatUsers: API returned success=${result.success}, using cached data`);
151
- resolve(cached?.users ?? []);
152
+ finish(cached?.users ?? []);
152
153
  });
153
154
  }).on("error", (err) => {
154
155
  log?.warn(`fetchChatUsers: HTTP error — ${err instanceof Error ? err.message : err}`);
155
- resolve(cached?.users ?? []);
156
+ finish(cached?.users ?? []);
157
+ });
158
+ req.setTimeout?.(15e3, () => {
159
+ log?.warn("fetchChatUsers: request timed out, using cached data");
160
+ req.destroy?.();
161
+ finish(cached?.users ?? []);
156
162
  });
157
163
  });
158
164
  }
165
+ async function waitForSendSlot() {
166
+ const next = sendQueue.then(async () => {
167
+ const elapsed = Date.now() - lastSendTime;
168
+ if (elapsed < MIN_SEND_INTERVAL_MS) await sleep(MIN_SEND_INTERVAL_MS - elapsed);
169
+ lastSendTime = Date.now();
170
+ });
171
+ sendQueue = next.catch(() => {});
172
+ await next;
173
+ }
159
174
  async function assertSafeWebhookFileUrl(fileUrl) {
160
175
  let parsed;
161
176
  try {
@@ -1,2 +1,2 @@
1
- import { t as synologyChatPlugin } from "./channel-QNW5XjB7.js";
1
+ import { t as synologyChatPlugin } from "./channel-bDcSUMFI.js";
2
2
  export { synologyChatPlugin };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/synology-chat",
3
- "version": "2026.5.22",
3
+ "version": "2026.5.24-beta.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/synology-chat",
9
- "version": "2026.5.22",
9
+ "version": "2026.5.24-beta.2",
10
10
  "dependencies": {
11
11
  "zod": "4.4.3"
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/synology-chat",
3
- "version": "2026.5.22",
3
+ "version": "2026.5.24-beta.2",
4
4
  "description": "Synology Chat channel plugin for OpenClaw",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,10 +27,10 @@
27
27
  "minHostVersion": ">=2026.4.10"
28
28
  },
29
29
  "compat": {
30
- "pluginApi": ">=2026.5.22"
30
+ "pluginApi": ">=2026.5.24-beta.2"
31
31
  },
32
32
  "build": {
33
- "openclawVersion": "2026.5.22"
33
+ "openclawVersion": "2026.5.24-beta.2"
34
34
  },
35
35
  "release": {
36
36
  "publishToClawHub": true,
@@ -50,7 +50,7 @@
50
50
  "npm-shrinkwrap.json"
51
51
  ],
52
52
  "peerDependencies": {
53
- "openclaw": ">=2026.5.22"
53
+ "openclaw": ">=2026.5.24-beta.2"
54
54
  },
55
55
  "peerDependenciesMeta": {
56
56
  "openclaw": {