wx2tg-puppet 3.0.5 → 3.0.7

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.
@@ -137,8 +137,7 @@ const say = (content, toWxid, ats) => __awaiter(void 0, void 0, void 0, function
137
137
  case 'other':
138
138
  // 直接从 FileBox 获取文件内容
139
139
  const fileBuffer = yield content.toBuffer();
140
- const fileArrayBuffer = fileBuffer.buffer.slice(fileBuffer.byteOffset, fileBuffer.byteOffset + fileBuffer.byteLength);
141
- const fileBlob = new Blob([fileArrayBuffer], { type: 'application/octet-stream' });
140
+ const fileBlob = new Blob([new Uint8Array(fileBuffer)], { type: 'application/octet-stream' });
142
141
  // 创建 FormData
143
142
  const formData = new FormData();
144
143
  formData.append('wxid', (config === null || config === void 0 ? void 0 : config.wxid) || '');
@@ -9,6 +9,8 @@ declare class ToolsApi {
9
9
  OpenHongBao(body: any): Promise<AxiosResponse<ApiResponse>>;
10
10
  /** 文件下载 */
11
11
  DownloadFile(body: any): Promise<AxiosResponse<ApiResponse>>;
12
+ /** 文件消息下载 */
13
+ DownloadFileMessage(body: any): Promise<AxiosResponse<ApiResponse>>;
12
14
  /** 高清图片下载 */
13
15
  DownloadImg(body: any): Promise<AxiosResponse<ApiResponse>>;
14
16
  /** 视频下载 */
@@ -19,6 +19,10 @@ class ToolsApi {
19
19
  DownloadFile(body) {
20
20
  return axiosInstance_1.axiosInstance.post('/Tools/DownloadFile', body);
21
21
  }
22
+ /** 文件消息下载 */
23
+ DownloadFileMessage(body) {
24
+ return axiosInstance_1.axiosInstance.post('/Tools/DownloadFileMessage', body);
25
+ }
22
26
  /** 高清图片下载 */
23
27
  DownloadImg(body) {
24
28
  return axiosInstance_1.axiosInstance.post('/Tools/DownloadImg', body);
@@ -73,6 +73,9 @@ export declare class Message {
73
73
  * Get the text content of the message.
74
74
  */
75
75
  text(): string;
76
+ private decodeDownloadBuffer;
77
+ private findDownloadBufferSource;
78
+ downloadFileMessage(sourceXml?: string): Promise<FileBox | null>;
76
79
  static getXmlToJson(xml: string): any;
77
80
  static getType(type: number, xml: string): string | undefined;
78
81
  /**
@@ -63,6 +63,7 @@ const GroupApi_1 = require("../api/GroupApi");
63
63
  const contact_service_1 = require("../services/contact.service");
64
64
  const MAX_RETRIES = 3;
65
65
  const RETRY_DELAY = 1000; // 1 second
66
+ const LARGE_FILE_THRESHOLD = 80 * 1024 * 1024;
66
67
  // @ts-ignore - Ignore type errors for the entire function since we're dealing with a mix of old and new axios types
67
68
  function retryDownload(downloadFn) {
68
69
  return __awaiter(this, void 0, void 0, function* () {
@@ -217,6 +218,77 @@ class Message {
217
218
  // TODO: Implement text content retrieval
218
219
  return this.msg.Content;
219
220
  }
221
+ decodeDownloadBuffer(bufferSource) {
222
+ if (Buffer.isBuffer(bufferSource)) {
223
+ return bufferSource;
224
+ }
225
+ if (Array.isArray(bufferSource)) {
226
+ return Buffer.from(bufferSource);
227
+ }
228
+ if (typeof bufferSource === 'string') {
229
+ const base64 = bufferSource.replace(/^data:[^;]+;base64,/, '');
230
+ return Buffer.from(base64, 'base64');
231
+ }
232
+ throw new Error('Unsupported download response format');
233
+ }
234
+ findDownloadBufferSource(value, preferredKeys = []) {
235
+ if (!value) {
236
+ return undefined;
237
+ }
238
+ if (Buffer.isBuffer(value) || Array.isArray(value) || typeof value === 'string') {
239
+ return value;
240
+ }
241
+ if (typeof value !== 'object') {
242
+ return undefined;
243
+ }
244
+ const fallbackKeys = ['Image', 'image', 'Buffer', 'buffer', 'FileData', 'fileData', 'Base64', 'base64'];
245
+ for (const key of [...preferredKeys, ...fallbackKeys]) {
246
+ if (value[key]) {
247
+ const candidate = this.findDownloadBufferSource(value[key]);
248
+ if (candidate) {
249
+ return candidate;
250
+ }
251
+ }
252
+ }
253
+ for (const key of Object.keys(value)) {
254
+ const candidate = this.findDownloadBufferSource(value[key]);
255
+ if (candidate) {
256
+ return candidate;
257
+ }
258
+ }
259
+ return undefined;
260
+ }
261
+ downloadFileMessage(sourceXml) {
262
+ return __awaiter(this, void 0, void 0, function* () {
263
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
264
+ if (this.type() !== MessageType_1.MessageType.File) {
265
+ return null;
266
+ }
267
+ const config = yield config_service_1.configService.get();
268
+ const xml = sourceXml || this.msg.Content;
269
+ const json = Message.getXmlToJson(xml);
270
+ const title = ((_b = (_a = json === null || json === void 0 ? void 0 : json.msg) === null || _a === void 0 ? void 0 : _a.appmsg) === null || _b === void 0 ? void 0 : _b.title) || `${this.msg.MsgId}`;
271
+ const response = yield ToolsApi_1.toolsApi.DownloadFileMessage({
272
+ Wxid: (config === null || config === void 0 ? void 0 : config.wxid) || '',
273
+ Xml: xml,
274
+ SourceXml: xml,
275
+ MsgID: Number(this.msg.MsgId || 0),
276
+ NewMsgID: Number(this.msg.NewMsgId || 0),
277
+ Talker: this.msg.RoomId || this.msg.FromUserName || this.msg.ToUserName || '',
278
+ SenderUserName: this.msg.FromUserName || '',
279
+ MsgType: 49,
280
+ });
281
+ if (((_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.Success) !== true) {
282
+ throw new Error(((_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.Message) || 'DownloadFileMessage failed');
283
+ }
284
+ const bufferSource = (_k = (_g = (_f = (_e = response === null || response === void 0 ? void 0 : response.data) === null || _e === void 0 ? void 0 : _e.Data) === null || _f === void 0 ? void 0 : _f.FileData) !== null && _g !== void 0 ? _g : (_j = (_h = response === null || response === void 0 ? void 0 : response.data) === null || _h === void 0 ? void 0 : _h.Data) === null || _j === void 0 ? void 0 : _j.fileData) !== null && _k !== void 0 ? _k : this.findDownloadBufferSource((_l = response === null || response === void 0 ? void 0 : response.data) === null || _l === void 0 ? void 0 : _l.Data, ['FileData', 'fileData']);
285
+ const buffer = this.decodeDownloadBuffer(bufferSource);
286
+ if (!buffer.length) {
287
+ throw new Error('DownloadFileMessage returned empty buffer');
288
+ }
289
+ return file_box_1.FileBox.fromBuffer(buffer, title);
290
+ });
291
+ }
220
292
  static getXmlToJson(xml) {
221
293
  const parser = new fast_xml_parser_1.XMLParser({
222
294
  ignoreAttributes: false, // 不忽略属性
@@ -484,6 +556,9 @@ class Message {
484
556
  const json = Message.getXmlToJson(xml);
485
557
  const config = yield config_service_1.configService.get();
486
558
  const totalSize = parseInt(json.msg.appmsg.appattach.totallen);
559
+ if (totalSize > LARGE_FILE_THRESHOLD) {
560
+ return yield this.downloadFileMessage();
561
+ }
487
562
  // Get initial chunk size from first request
488
563
  const firstChunk = FileChunkHelper_1.FileChunkHelper.getChunk(totalSize, 0);
489
564
  if (!firstChunk)
@@ -53,7 +53,7 @@ function detectProtocolVersion() {
53
53
  protocolDetected = true;
54
54
  try {
55
55
  const resp = yield exports.axiosInstance.get('/Tools/Version');
56
- if (((_a = resp.data) === null || _a === void 0 ? void 0 : _a.Code) === 0 && ((_b = resp.data) === null || _b === void 0 ? void 0 : _b.Success) && ((_c = resp.data) === null || _c === void 0 ? void 0 : _c.Data)) {
56
+ if (((_a = resp.data) === null || _a === void 0 ? void 0 : _a.Code) === 0 && ((_b = resp.data) === null || _b === void 0 ? void 0 : _b.Success) && String(((_c = resp.data) === null || _c === void 0 ? void 0 : _c.Data) || '') !== '857') {
57
57
  newProtocol = true;
58
58
  console.log(`检测到新协议版本: ${resp.data.Data}`);
59
59
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wx2tg-puppet",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [