zalo-toolkit 1.0.2 → 1.0.4

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.
@@ -122,6 +122,7 @@ exports.PingType = void 0;
122
122
  PingType[PingType["SwitchToBackground"] = 3] = "SwitchToBackground";
123
123
  PingType[PingType["BackgroundKeepAlive"] = 4] = "BackgroundKeepAlive";
124
124
  })(exports.PingType || (exports.PingType = {}));
125
+ const DEFAULT_RETRY_DELAYS = [1000, 10000, 30000, 60000];
125
126
  exports.EventTypes = void 0;
126
127
  (function (EventTypes) {
127
128
  EventTypes["GOT_CLEAR_UNREADS"] = "GOT_CLEAR_UNREADS";
@@ -132,3 +133,34 @@ exports.EventTypes = void 0;
132
133
  EventTypes["SOCKET_STATE_CHANGED"] = "ON_SOCKET_STT_CHANGED";
133
134
  EventTypes["DONE_CHECK_OVERFLOW"] = "DONE_CHECK_OVERFLOW";
134
135
  })(exports.EventTypes || (exports.EventTypes = {}));
136
+ const MessageTypes = {
137
+ '516': 'SESSION_OFFLINE',
138
+ '517': 'SESSION_OFFLINE',
139
+ '518': 'OFFLINE_ACK_ONE_ONE',
140
+ '519': 'OFFLINE_ACK_GROUP',
141
+ '543': 'INIT_SESSION',
142
+ '544': 'ACK_INIT_SESSION',
143
+ '545': 'INIT_SESSION',
144
+ '546': 'RECEIVE_ACK_GROUP_SESSIONS_STALE',
145
+ '548': 'NOTIFY_DELETE_KEY',
146
+ '549': 'REQUEST_PREKEYS',
147
+ '559': 'RECEIVE_ACK_PROCESS_INIT_GROUP_FAILED',
148
+ '561': 'INIT_SESSION_GROUP',
149
+ '580': 'DISABLE_E2EE',
150
+ '581': 'ENABLE_E2EE',
151
+ '582': 'RECEIVE_DOWNGRADE_E2EE_GROUP',
152
+ };
153
+ const SignalCommands = {
154
+ INIT: {
155
+ OFFLINE_ACK_GROUP: 519},
156
+ ACK: {
157
+ DELETE_QUEUE_ACK_ONEONE: 557,
158
+ DELETE_QUEUE_ACK_GROUP: 558,
159
+ },
160
+ };
161
+ const MAX_CHUNK_WS = 5;
162
+
163
+ exports.DEFAULT_RETRY_DELAYS = DEFAULT_RETRY_DELAYS;
164
+ exports.MAX_CHUNK_WS = MAX_CHUNK_WS;
165
+ exports.MessageTypes = MessageTypes;
166
+ exports.SignalCommands = SignalCommands;
@@ -0,0 +1,203 @@
1
+ 'use strict';
2
+
3
+ var Listen = require('../models/Listen.cjs');
4
+ var WebSocket = require('ws');
5
+
6
+ class ConfigSocket {
7
+ constructor(ws, features, ctx, listen) {
8
+ this.overflowTracker = {};
9
+ this.offlineCmds = new Map();
10
+ this.offlineWaiter = new Map();
11
+ this.pollId = {};
12
+ this.isDoneOffline = false;
13
+ this.emitter = ws;
14
+ this.features = features;
15
+ this.ctx = ctx;
16
+ this.listen = listen;
17
+ }
18
+ getLastActionIdsForSocket(socketKey) {
19
+ const defaultResult = { lastId: 1, preIds: [] };
20
+ if (this.pollId.hasOwnProperty(socketKey)) {
21
+ const { lastId } = this.pollId[socketKey];
22
+ const preIds = this.pollId[socketKey].control.getLastActionIdsArray(lastId).slice(0, 10);
23
+ return { lastId, preIds };
24
+ }
25
+ return defaultResult;
26
+ }
27
+ immediateDoNextOfflineReq(cmd) {
28
+ var _a;
29
+ return !((_a = this.features.socket.none_ids_queue) === null || _a === void 0 ? void 0 : _a.includes(cmd + ''));
30
+ }
31
+ getSocketState() {
32
+ return this.emitter ? this.emitter.readyState : -1;
33
+ }
34
+ sendWs(payload) {
35
+ if (this.emitter && this.getSocketState() === WebSocket.WebSocket.OPEN) {
36
+ const encodedData = new TextEncoder().encode(JSON.stringify(payload.data));
37
+ const dataLength = encodedData.length;
38
+ const data = new DataView(Buffer.alloc(4 + dataLength).buffer);
39
+ data.setUint8(0, payload.version);
40
+ data.setInt32(1, payload.cmd, true);
41
+ data.setInt8(3, payload.subCmd);
42
+ encodedData.forEach((e, i) => {
43
+ data.setUint8(4 + i, e);
44
+ });
45
+ this.emitter.send(data);
46
+ }
47
+ }
48
+ async doGetOffline(cmd, subCmd, first, lastActionId) {
49
+ var _a;
50
+ if (typeof cmd !== 'number' || typeof subCmd !== 'number') {
51
+ return;
52
+ }
53
+ const requestPayload = {
54
+ cmd,
55
+ subCmd,
56
+ data: {
57
+ first,
58
+ reqId: this.listen.genNextReqId(),
59
+ lastId: 1,
60
+ preIds: [],
61
+ },
62
+ version: 1,
63
+ };
64
+ if (!((_a = this.features.socket.none_ids_queue) === null || _a === void 0 ? void 0 : _a.includes(`${cmd}`))) {
65
+ const trackerKey = `${cmd}_${subCmd}`;
66
+ this.offlineWaiter.set(trackerKey, this.createOfflineWaiter());
67
+ const { lastId, preIds } = this.getLastActionIdsForSocket(`${cmd}_${subCmd}`);
68
+ requestPayload.data.lastId = lastActionId !== undefined ? lastActionId : lastId;
69
+ requestPayload.data.preIds = preIds;
70
+ }
71
+ this.sendWs(requestPayload);
72
+ }
73
+ createOfflineWaiter() {
74
+ const waiter = { resolve: null, reject: null, promise: null };
75
+ const promise = new Promise((resolve, reject) => {
76
+ waiter.resolve = resolve;
77
+ waiter.reject = reject;
78
+ });
79
+ waiter.promise = promise;
80
+ return waiter;
81
+ }
82
+ ackOfflineQueue(isGroup, data) {
83
+ const command = isGroup ? Listen.SignalCommands.ACK.DELETE_QUEUE_ACK_GROUP : Listen.SignalCommands.ACK.DELETE_QUEUE_ACK_ONEONE;
84
+ return this.requestAsyncV2({
85
+ cmd: command,
86
+ data: { data },
87
+ });
88
+ }
89
+ isValidSendPayload(payload) {
90
+ if (!payload || !payload.cmd || payload.data == null) {
91
+ return false;
92
+ }
93
+ return true;
94
+ }
95
+ getReqId(e) {
96
+ return [Listen.MessageCommand.PingActive].includes(e) ? `cmd_${e}` : this.listen.genNextReqId();
97
+ }
98
+ addCommonParams(payload) {
99
+ const reqId = this.getReqId(payload.cmd);
100
+ return Object.assign(Object.assign({}, payload), { data: Object.assign(Object.assign({}, payload.data), { reqId }) });
101
+ }
102
+ requestAsyncV2(payload) {
103
+ return new Promise((resolve, reject) => {
104
+ if (!this.isValidSendPayload(payload)) {
105
+ return reject('Invalid params');
106
+ }
107
+ const requestData = this.addCommonParams(payload);
108
+ this.sendWs(requestData);
109
+ });
110
+ }
111
+ async onOfflineData(cmd, subCmd, data, options = { isLastQueue: false }) {
112
+ var _a;
113
+ if (this.features.e2ee.debug.make_slow_pull_offline && this.features.e2ee.debug.enable) {
114
+ await new Promise((resolve) => setTimeout(resolve, 5000));
115
+ }
116
+ if (((_a = this.features.socket.none_ids_queue) === null || _a === void 0 ? void 0 : _a.includes(`${cmd}`)) && data.data.delivereds.length) {
117
+ const delivereds = [...data.data.delivereds];
118
+ const isAckGroup = cmd === Listen.SignalCommands.INIT.OFFLINE_ACK_GROUP;
119
+ const chunkPromises = [];
120
+ while (delivereds.length > 0) {
121
+ const chunk = delivereds.splice(0, Listen.MAX_CHUNK_WS);
122
+ chunkPromises.push(this.ackOfflineQueue(isAckGroup, { delivereds: chunk }));
123
+ }
124
+ await Promise.all(chunkPromises).catch((error) => console.log(['Error when deleting queue offline {}'], error));
125
+ }
126
+ }
127
+ async onGotOffline(cmd, subCmd, data) {
128
+ var _a;
129
+ if (data && data.data) {
130
+ // this.webStartUp.onPollData(`${cmd}_${subCmd}`, data);
131
+ // this.checkQueueOverflow(cmd, subCmd, data);
132
+ if (data.data.more) {
133
+ const lastActionId = (_a = data.data) === null || _a === void 0 ? void 0 : _a.lastActionId;
134
+ if (this.immediateDoNextOfflineReq(cmd)) {
135
+ await this.doGetOffline(cmd, subCmd, false, lastActionId);
136
+ this.onOfflineData(cmd, subCmd, data, { isLastQueue: false });
137
+ }
138
+ else {
139
+ await this.onOfflineData(cmd, subCmd, data, { isLastQueue: false });
140
+ await this.doGetOffline(cmd, subCmd, false, lastActionId);
141
+ }
142
+ }
143
+ else {
144
+ const trackerKey = `${cmd}_${subCmd}`;
145
+ const isLastQueue = this.offlineWaiter.size === 1;
146
+ // this.webStartUp.onEndPoll(trackerKey, data.data.lastActionId);
147
+ this.onOfflineData(cmd, subCmd, data, { isLastQueue });
148
+ this.onDoneOfflineQueue(trackerKey);
149
+ }
150
+ }
151
+ }
152
+ checkQueueOverflow(cmd, subCmd, data) {
153
+ var _a, _b, _c;
154
+ const trackerKey = `${cmd}_${subCmd}`;
155
+ if (this.overflowTracker[trackerKey] !== undefined)
156
+ return;
157
+ if (!this.offlineCmds.has(cmd))
158
+ return;
159
+ const isEvicted = ((_c = (_b = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.queueStatus) === null || _b === void 0 ? void 0 : _b[trackerKey]) === null || _c === void 0 ? void 0 : _c.evict) === 1;
160
+ this.overflowTracker[trackerKey] = isEvicted;
161
+ const trackerKeys = Object.keys(this.overflowTracker);
162
+ if (this.offlineCmds.size === trackerKeys.length) {
163
+ const overflowedKeys = trackerKeys.filter((key) => this.overflowTracker[key]);
164
+ this.emitter.emit(Listen.EventTypes.DONE_CHECK_OVERFLOW, overflowedKeys);
165
+ }
166
+ }
167
+ handleSocketMsg(cmd, payload) {
168
+ if (!this.features.e2ee.enable && this.features.e2ee.skip_on_disabled) {
169
+ return;
170
+ }
171
+ const actionHandler = Listen.MessageTypes[cmd];
172
+ if (!actionHandler) {
173
+ throw new Error(`Unsupported action type: ${cmd}`);
174
+ }
175
+ return this.emitter.emit(actionHandler, {
176
+ cmd,
177
+ payload,
178
+ });
179
+ }
180
+ onDoneOfflineQueue(queueId) {
181
+ const waiter = this.offlineWaiter.get(queueId);
182
+ if (waiter) {
183
+ // Resolve the waiter and remove it from the map
184
+ waiter.resolve(true);
185
+ this.offlineWaiter.delete(queueId);
186
+ // If all waiters are done, process the completion of all offline tasks
187
+ if (this.offlineWaiter.size === 0) {
188
+ this.onDoneOfflineAll();
189
+ // this.processPending(null);
190
+ }
191
+ }
192
+ }
193
+ onDoneOfflineAll() {
194
+ this.isDoneOffline = true;
195
+ // Clear offline timer if it's set
196
+ if (this.offlineTimer) {
197
+ clearTimeout(this.offlineTimer);
198
+ this.offlineTimer = null;
199
+ }
200
+ }
201
+ }
202
+
203
+ exports.ConfigSocket = ConfigSocket;
@@ -1,18 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  var cryptojs = require('crypto-js');
4
- require('json-bigint');
4
+ var JSONBig = require('json-bigint');
5
5
  var crypto = require('node:crypto');
6
6
  require('node:fs');
7
7
  var path = require('node:path');
8
- require('pako');
8
+ var pako = require('pako');
9
9
  var SparkMD5 = require('spark-md5');
10
10
  var ToughCookie = require('tough-cookie');
11
11
  var sharp = require('sharp');
12
12
  var context = require('./context.cjs');
13
13
  var ZaloApiError = require('./Errors/ZaloApiError.cjs');
14
- require('./models/FriendEvent.cjs');
15
- require('./models/GroupEvent.cjs');
14
+ var FriendEvent = require('./models/FriendEvent.cjs');
15
+ var GroupEvent = require('./models/GroupEvent.cjs');
16
16
 
17
17
  // export const isBun = typeof Bun !== "undefined";
18
18
  function hasOwn(obj, key) {
@@ -192,6 +192,17 @@ function decodeRespAES(key, data) {
192
192
  padding: cryptojs.pad.Pkcs7,
193
193
  }).toString(cryptojs.enc.Utf8);
194
194
  }
195
+ function decodeBase64ToBuffer(data) {
196
+ return Buffer.from(data, 'base64');
197
+ }
198
+ function decodeUnit8Array(data) {
199
+ try {
200
+ return new TextDecoder().decode(data);
201
+ }
202
+ catch (_a) {
203
+ return null;
204
+ }
205
+ }
195
206
  function encodeAES(secretKey, data, t = 0) {
196
207
  try {
197
208
  const key = cryptojs.enc.Base64.parse(secretKey);
@@ -295,6 +306,41 @@ async function getGifMetaData(file) {
295
306
  height: gifData.height,
296
307
  };
297
308
  }
309
+ async function decodeEventData(parsed, cipherKey) {
310
+ if (typeof parsed.data !== 'string')
311
+ throw new ZaloApiError.ZaloApiError(`Invalid data, expected string but got ${typeof parsed.data}`);
312
+ if (typeof parsed.encrypt !== 'number')
313
+ throw new ZaloApiError.ZaloApiError(`Invalid encrypt type, expected number but got ${typeof parsed.encrypt}`);
314
+ if (parsed.encrypt < 0 || parsed.encrypt > 3)
315
+ throw new ZaloApiError.ZaloApiError(`Invalid encrypt type, expected 0-3 but got ${parsed.encrypt}`);
316
+ const rawData = parsed.data;
317
+ const encryptType = parsed.encrypt;
318
+ if (encryptType === 0)
319
+ return JSON.parse(rawData);
320
+ const decodedBuffer = decodeBase64ToBuffer(encryptType === 1 ? rawData : decodeURIComponent(rawData));
321
+ let decryptedBuffer = decodedBuffer;
322
+ if (encryptType !== 1) {
323
+ if (cipherKey && decodedBuffer.length >= 48) {
324
+ const algorithm = {
325
+ name: 'AES-GCM',
326
+ iv: decodedBuffer.subarray(0, 16),
327
+ tagLength: 128,
328
+ additionalData: decodedBuffer.subarray(16, 32),
329
+ };
330
+ const dataSource = decodedBuffer.subarray(32);
331
+ const cryptoKey = await crypto.subtle.importKey('raw', decodeBase64ToBuffer(cipherKey), algorithm, false, ['decrypt']);
332
+ decryptedBuffer = await crypto.subtle.decrypt(algorithm, cryptoKey, dataSource);
333
+ }
334
+ else {
335
+ throw new ZaloApiError.ZaloApiError('Invalid data length or missing cipher key');
336
+ }
337
+ }
338
+ const decompressedBuffer = encryptType === 3 ? new Uint8Array(decryptedBuffer) : pako.inflate(decryptedBuffer);
339
+ const decodedData = decodeUnit8Array(decompressedBuffer);
340
+ if (!decodedData)
341
+ return;
342
+ return JSONBig.parse(decodedData);
343
+ }
298
344
  function getMd5LargeFileObject(file) {
299
345
  return new Promise(async (resolve, reject) => {
300
346
  let chunkSize = 2097152, // Read in chunks of 2MB
@@ -409,6 +455,80 @@ function removeUndefinedKeys(e) {
409
455
  delete e[t];
410
456
  return e;
411
457
  }
458
+ function getGroupEventType(act) {
459
+ if (act == 'join_request')
460
+ return GroupEvent.GroupEventType.JOIN_REQUEST;
461
+ if (act == 'join')
462
+ return GroupEvent.GroupEventType.JOIN;
463
+ if (act == 'leave')
464
+ return GroupEvent.GroupEventType.LEAVE;
465
+ if (act == 'remove_member')
466
+ return GroupEvent.GroupEventType.REMOVE_MEMBER;
467
+ if (act == 'block_member')
468
+ return GroupEvent.GroupEventType.BLOCK_MEMBER;
469
+ if (act == 'update_setting')
470
+ return GroupEvent.GroupEventType.UPDATE_SETTING;
471
+ if (act == 'update_avatar')
472
+ return GroupEvent.GroupEventType.UPDATE_AVATAR;
473
+ if (act == 'update')
474
+ return GroupEvent.GroupEventType.UPDATE;
475
+ if (act == 'new_link')
476
+ return GroupEvent.GroupEventType.NEW_LINK;
477
+ if (act == 'add_admin')
478
+ return GroupEvent.GroupEventType.ADD_ADMIN;
479
+ if (act == 'remove_admin')
480
+ return GroupEvent.GroupEventType.REMOVE_ADMIN;
481
+ if (act == 'new_pin_topic')
482
+ return GroupEvent.GroupEventType.NEW_PIN_TOPIC;
483
+ if (act == 'update_pin_topic')
484
+ return GroupEvent.GroupEventType.UPDATE_PIN_TOPIC;
485
+ if (act == 'update_topic')
486
+ return GroupEvent.GroupEventType.UPDATE_TOPIC;
487
+ if (act == 'update_board')
488
+ return GroupEvent.GroupEventType.UPDATE_BOARD;
489
+ if (act == 'remove_board')
490
+ return GroupEvent.GroupEventType.REMOVE_BOARD;
491
+ if (act == 'reorder_pin_topic')
492
+ return GroupEvent.GroupEventType.REORDER_PIN_TOPIC;
493
+ if (act == 'unpin_topic')
494
+ return GroupEvent.GroupEventType.UNPIN_TOPIC;
495
+ if (act == 'remove_topic')
496
+ return GroupEvent.GroupEventType.REMOVE_TOPIC;
497
+ if (act == 'accept_remind')
498
+ return GroupEvent.GroupEventType.ACCEPT_REMIND;
499
+ if (act == 'reject_remind')
500
+ return GroupEvent.GroupEventType.REJECT_REMIND;
501
+ if (act == 'remind_topic')
502
+ return GroupEvent.GroupEventType.REMIND_TOPIC;
503
+ return GroupEvent.GroupEventType.UNKNOWN;
504
+ }
505
+ function getFriendEventType(act) {
506
+ if (act == 'add')
507
+ return FriendEvent.FriendEventType.ADD;
508
+ if (act == 'remove')
509
+ return FriendEvent.FriendEventType.REMOVE;
510
+ if (act == 'block')
511
+ return FriendEvent.FriendEventType.BLOCK;
512
+ if (act == 'unblock')
513
+ return FriendEvent.FriendEventType.UNBLOCK;
514
+ if (act == 'block_call')
515
+ return FriendEvent.FriendEventType.BLOCK_CALL;
516
+ if (act == 'unblock_call')
517
+ return FriendEvent.FriendEventType.UNBLOCK_CALL;
518
+ if (act == 'req_v2')
519
+ return FriendEvent.FriendEventType.REQUEST;
520
+ if (act == 'reject')
521
+ return FriendEvent.FriendEventType.REJECT_REQUEST;
522
+ if (act == 'undo_req')
523
+ return FriendEvent.FriendEventType.UNDO_REQUEST;
524
+ if (act == 'seen_fr_req')
525
+ return FriendEvent.FriendEventType.SEEN_FRIEND_REQUEST;
526
+ if (act == 'pin_unpin')
527
+ return FriendEvent.FriendEventType.PIN_UNPIN;
528
+ if (act == 'pin_create')
529
+ return FriendEvent.FriendEventType.PIN_CREATE;
530
+ return FriendEvent.FriendEventType.UNKNOWN;
531
+ }
412
532
  async function handleZaloResponse(ctx, response, isEncrypted = true) {
413
533
  const result = {
414
534
  data: null,
@@ -511,16 +631,73 @@ function getSecChUaPlatform(userAgent = '') {
511
631
  }
512
632
  return '"Unknown"';
513
633
  }
634
+ class FibonacciRetry {
635
+ constructor(maxItem = 2000, delta = 10, saltRange = 0.2) {
636
+ this.caches = [1, 2];
637
+ this.maxItem = maxItem;
638
+ this.delta = delta;
639
+ this.saltRange = saltRange;
640
+ }
641
+ /**
642
+ * Lấy giá trị Fibonacci tại index e (1-based)
643
+ * @param index - Thứ tự Fibonacci cần lấy (1-based)
644
+ * @returns Giá trị Fibonacci tương ứng
645
+ */
646
+ getFibo(index) {
647
+ if (index <= 0)
648
+ throw new Error('Index must be greater than 0');
649
+ if (this.caches.length >= index) {
650
+ return this.caches[index - 1];
651
+ }
652
+ let next = 1;
653
+ for (let i = this.caches.length; i < index; i++) {
654
+ const len = this.caches.length;
655
+ next = this.caches[len - 1] + this.caches[len - 2];
656
+ this.caches.push(next);
657
+ }
658
+ if (this.caches.length > this.maxItem + this.delta) {
659
+ this.caches = this.caches.slice(0, this.maxItem);
660
+ }
661
+ return next;
662
+ }
663
+ /**
664
+ * Tính toán thời gian retry tiếp theo dựa vào số lần retry hiện tại
665
+ * @param count - Lần retry thứ mấy (1-based)
666
+ * @param multiplier - Hệ số nhân (delay mỗi lần retry)
667
+ * @param maxDelay - Giới hạn tối đa delay (ms)
668
+ * @returns Số mili giây cần chờ trước khi retry tiếp theo
669
+ */
670
+ getNextRetry(count, multiplier, maxDelay) {
671
+ if (count <= 0)
672
+ throw new Error('Count must be greater than 0');
673
+ if (multiplier <= 0)
674
+ throw new Error('Multiplier must be greater than 0');
675
+ const fiboValue = this.getFibo(count);
676
+ const baseDelay = fiboValue * multiplier;
677
+ const randomFactor = 1 + this.saltRange * Math.random();
678
+ if (maxDelay !== undefined && baseDelay > maxDelay) {
679
+ return maxDelay * randomFactor;
680
+ }
681
+ return baseDelay * randomFactor;
682
+ }
683
+ }
514
684
  function handleQueueStatus(queueStatus) {
515
685
  for (const key in queueStatus) {
516
686
  delete queueStatus[key].ids;
517
687
  }
518
688
  return queueStatus;
519
689
  }
690
+ function looksLikeJson(str) {
691
+ return /^[\[{].*[\]}]$/.test(str.trim());
692
+ }
520
693
 
694
+ exports.FibonacciRetry = FibonacciRetry;
521
695
  exports.ParamsEncryptor = ParamsEncryptor;
522
696
  exports.apiFactory = apiFactory;
523
697
  exports.decodeAES = decodeAES;
698
+ exports.decodeBase64ToBuffer = decodeBase64ToBuffer;
699
+ exports.decodeEventData = decodeEventData;
700
+ exports.decodeUnit8Array = decodeUnit8Array;
524
701
  exports.decryptResp = decryptResp;
525
702
  exports.encodeAES = encodeAES;
526
703
  exports.encryptPin = encryptPin;
@@ -529,8 +706,10 @@ exports.generateZaloUUID = generateZaloUUID;
529
706
  exports.getClientMessageType = getClientMessageType;
530
707
  exports.getDefaultHeaders = getDefaultHeaders;
531
708
  exports.getFileExtension = getFileExtension;
709
+ exports.getFriendEventType = getFriendEventType;
532
710
  exports.getFullTimeFromMillisecond = getFullTimeFromMillisecond;
533
711
  exports.getGifMetaData = getGifMetaData;
712
+ exports.getGroupEventType = getGroupEventType;
534
713
  exports.getImageMetaData = getImageMetaData;
535
714
  exports.getMd5LargeFileObject = getMd5LargeFileObject;
536
715
  exports.getSecChUaPlatform = getSecChUaPlatform;
@@ -539,6 +718,7 @@ exports.handleQueueStatus = handleQueueStatus;
539
718
  exports.handleZaloResponse = handleZaloResponse;
540
719
  exports.hasOwn = hasOwn;
541
720
  exports.logger = logger;
721
+ exports.looksLikeJson = looksLikeJson;
542
722
  exports.makeURL = makeURL;
543
723
  exports.removeUndefinedKeys = removeUndefinedKeys;
544
724
  exports.request = request;
package/dist/cjs/zalo.cjs CHANGED
@@ -7,6 +7,7 @@ var context = require('./context.cjs');
7
7
  var ZaloApiError = require('./Errors/ZaloApiError.cjs');
8
8
  var utils = require('./utils.cjs');
9
9
  var apis = require('./apis.cjs');
10
+ var listen = require('./apis/listen.cjs');
10
11
 
11
12
  function _interopNamespaceDefault(e) {
12
13
  var n = Object.create(null);
@@ -133,6 +134,9 @@ class Zalo {
133
134
  async getUserInfo(ctx) {
134
135
  return await loginQR.getUserInfo(ctx);
135
136
  }
137
+ listener(api) {
138
+ return new listen.Listener(api);
139
+ }
136
140
  }
137
141
 
138
142
  exports.Zalo = Zalo;
package/dist/zalo.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as ToughCookie from 'tough-cookie';
2
2
  import { type ContextBase, type Options, type ServerInfo } from './context.js';
3
3
  import { ZaloAPI, type ZaloAPIOptions } from './apis.js';
4
+ import { Listener } from './apis/listen.js';
4
5
  export type Credentials = {
5
6
  imei: string;
6
7
  cookie: ToughCookie.Cookie[] | ToughCookie.SerializedCookie[] | {
@@ -68,4 +69,5 @@ export declare class Zalo {
68
69
  error_code: number;
69
70
  error_message: string;
70
71
  } | undefined>;
72
+ listener(api: ZaloAPI): Listener;
71
73
  }
package/dist/zalo.js CHANGED
@@ -5,6 +5,7 @@ import { createContext, isContextSession } from './context.js';
5
5
  import { ZaloApiError } from './Errors/ZaloApiError.js';
6
6
  import { generateZaloUUID, logger } from './utils.js';
7
7
  import { ZaloAPI } from './apis.js';
8
+ import { Listener } from './apis/listen.js';
8
9
  export class Zalo {
9
10
  constructor(options = {}) {
10
11
  this.options = options;
@@ -111,4 +112,7 @@ export class Zalo {
111
112
  async getUserInfo(ctx) {
112
113
  return await getUserInfo(ctx);
113
114
  }
115
+ listener(api) {
116
+ return new Listener(api);
117
+ }
114
118
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zalo-toolkit",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Unofficial Zalo API for JavaScript",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",