@wu529778790/open-im 1.11.4-beta.17 → 1.11.4-beta.19

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.
@@ -12,7 +12,8 @@ import { createLogger } from '../logger.js';
12
12
  import { jitteredDelay, isFatalReconnectError, SLOW_PROBE_MS } from '../shared/reconnect.js';
13
13
  import { cacheContextToken } from './message-sender.js';
14
14
  import { setClawbotContextToken, clearClawbotContextToken } from '../shared/active-chats.js';
15
- import { decryptAes256CbcMedia, createMediaTargetPath } from '../shared/media-storage.js';
15
+ import { createMediaTargetPath } from '../shared/media-storage.js';
16
+ import { createDecipheriv } from 'node:crypto';
16
17
  import { CLAWBOT_POLL_INTERVAL_MS } from '../constants.js';
17
18
  const log = createLogger('ClawBot');
18
19
  const RECONNECT_DELAYS_MS = [3000, 5000, 10000, 20000, 30000];
@@ -261,37 +262,48 @@ async function extractImages(msg) {
261
262
  log.warn('Image item missing full_url/cdn_url');
262
263
  continue;
263
264
  }
264
- // AES key: media.aes_key 是 base64 编码,decodeAesKey 会解码为 32 字节
265
- const aesKey = media?.aes_key;
266
265
  try {
267
- // Download from CDN
266
+ // 直接从 full_url 下载图片(CDN 返回的是已解密的图片数据)
268
267
  const response = await fetch(imageUrl, { signal: AbortSignal.timeout(30_000) });
269
268
  if (!response.ok) {
270
269
  log.warn(`Image download failed: HTTP ${response.status}`);
271
270
  continue;
272
271
  }
273
272
  const buffer = Buffer.from(await response.arrayBuffer());
274
- // 解密:使用 media.aes_key(base64 编码的 32 字节密钥)
275
- let decrypted;
276
- if (aesKey) {
277
- try {
278
- decrypted = decryptAes256CbcMedia(buffer, aesKey);
279
- }
280
- catch {
281
- // AES-256 解密失败,直接用原始数据
282
- log.info('AES decryption failed, using raw image data');
283
- decrypted = buffer;
284
- }
273
+ // 检查是否是有效图片
274
+ const first4 = buffer.subarray(0, 4).toString('hex');
275
+ const isJpeg = first4 === 'ffd8ffe0' || first4 === 'ffd8ffe1';
276
+ const isPng = first4 === '89504e47';
277
+ let finalBuffer;
278
+ if (isJpeg || isPng) {
279
+ // CDN 返回的是有效图片,直接使用
280
+ finalBuffer = buffer;
285
281
  }
286
282
  else {
287
- decrypted = buffer;
283
+ // CDN 返回的是加密数据,尝试解密
284
+ const aesKeyHex = imageItem?.aeskey;
285
+ if (aesKeyHex && aesKeyHex.length === 32) {
286
+ try {
287
+ const keyBuf = Buffer.from(aesKeyHex, 'hex');
288
+ const iv = keyBuf.subarray(0, 16);
289
+ const decipher = createDecipheriv('aes-128-cbc', keyBuf, iv);
290
+ finalBuffer = Buffer.concat([decipher.update(buffer), decipher.final()]);
291
+ }
292
+ catch {
293
+ log.info('AES decryption failed, using raw image data');
294
+ finalBuffer = buffer;
295
+ }
296
+ }
297
+ else {
298
+ finalBuffer = buffer;
299
+ }
288
300
  }
289
301
  // Save to disk
290
302
  const targetPath = createMediaTargetPath('.jpg', `clawbot-${Date.now()}`);
291
303
  const { writeFile } = await import('node:fs/promises');
292
304
  const { mkdir } = await import('node:fs/promises');
293
305
  await mkdir('/tmp/t/open-im-images', { recursive: true });
294
- await writeFile(targetPath, decrypted);
306
+ await writeFile(targetPath, finalBuffer);
295
307
  paths.push(targetPath);
296
308
  log.info(`ClawBot image saved: ${targetPath}`);
297
309
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wu529778790/open-im",
3
- "version": "1.11.4-beta.17",
3
+ "version": "1.11.4-beta.19",
4
4
  "description": "Your AI coding assistant, in every chat app. Multi-platform IM bridge for Claude Code, Codex, and CodeBuddy.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",