@softtynet/zca-js 2.2.1 → 2.2.3
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/README.md +47 -21
- package/dist/apis/cancelPullMobile.d.ts +11 -0
- package/dist/apis/cancelPullMobile.js +33 -0
- package/dist/apis/cancelVoiceCall.d.ts +7 -0
- package/dist/apis/cancelVoiceCall.js +43 -0
- package/dist/apis/decryptGids.d.ts +2 -1
- package/dist/apis/decryptGids.js +2 -0
- package/dist/apis/endVoiceCall.d.ts +5 -0
- package/dist/apis/endVoiceCall.js +41 -0
- package/dist/apis/getNoisedIds.d.ts +9 -0
- package/dist/apis/getNoisedIds.js +67 -0
- package/dist/apis/getSyncData.d.ts +13 -0
- package/dist/apis/getSyncData.js +103 -0
- package/dist/apis/listen.d.ts +11 -3
- package/dist/apis/listen.js +71 -14
- package/dist/apis/preloadConversations.d.ts +20 -2
- package/dist/apis/preloadConversations.js +56 -3
- package/dist/apis/pullMobile.d.ts +15 -0
- package/dist/apis/pullMobile.js +38 -0
- package/dist/apis/requestSyncFromPhone.d.ts +17 -1
- package/dist/apis/requestSyncFromPhone.js +34 -20
- package/dist/apis/sendVoiceCall.d.ts +29 -0
- package/dist/apis/sendVoiceCall.js +105 -0
- package/dist/apis/uploadAttachment.js +6 -1
- package/dist/apis.d.ts +14 -0
- package/dist/apis.js +14 -0
- package/dist/cjs/apis/addReaction.cjs +2 -0
- package/dist/cjs/apis/addUnreadMark.cjs +2 -0
- package/dist/cjs/apis/cancelPullMobile.cjs +38 -0
- package/dist/cjs/apis/cancelVoiceCall.cjs +48 -0
- package/dist/cjs/apis/createReminder.cjs +2 -0
- package/dist/cjs/apis/decryptGids.cjs +2 -0
- package/dist/cjs/apis/deleteChat.cjs +2 -0
- package/dist/cjs/apis/deleteMessage.cjs +2 -0
- package/dist/cjs/apis/editReminder.cjs +2 -0
- package/dist/cjs/apis/endVoiceCall.cjs +46 -0
- package/dist/cjs/apis/findUser.cjs +2 -0
- package/dist/cjs/apis/findUserByUsername.cjs +2 -0
- package/dist/cjs/apis/forwardMessage.cjs +2 -0
- package/dist/cjs/apis/getAllFriends.cjs +2 -0
- package/dist/cjs/apis/getAvatarUrlProfile.cjs +2 -0
- package/dist/cjs/apis/getGroupChatHistory.cjs +2 -0
- package/dist/cjs/apis/getListBoard.cjs +2 -0
- package/dist/cjs/apis/getListReminder.cjs +2 -0
- package/dist/cjs/apis/getMultiUsersByPhones.cjs +2 -0
- package/dist/cjs/apis/getNoisedIds.cjs +72 -0
- package/dist/cjs/apis/getSyncData.cjs +108 -0
- package/dist/cjs/apis/getUserInfo.cjs +2 -0
- package/dist/cjs/apis/listen.cjs +71 -14
- package/dist/cjs/apis/preloadConversations.cjs +69 -3
- package/dist/cjs/apis/pullMobile.cjs +43 -0
- package/dist/cjs/apis/removeReminder.cjs +2 -0
- package/dist/cjs/apis/removeUnreadMark.cjs +2 -0
- package/dist/cjs/apis/requestSyncFromPhone.cjs +33 -19
- package/dist/cjs/apis/sendBankCard.cjs +2 -0
- package/dist/cjs/apis/sendCard.cjs +2 -0
- package/dist/cjs/apis/sendDeliveredEvent.cjs +2 -0
- package/dist/cjs/apis/sendLink.cjs +2 -0
- package/dist/cjs/apis/sendMessage.cjs +2 -0
- package/dist/cjs/apis/sendReport.cjs +2 -0
- package/dist/cjs/apis/sendSeenEvent.cjs +2 -0
- package/dist/cjs/apis/sendSticker.cjs +2 -0
- package/dist/cjs/apis/sendTypingEvent.cjs +2 -0
- package/dist/cjs/apis/sendVideo.cjs +2 -0
- package/dist/cjs/apis/sendVoice.cjs +2 -0
- package/dist/cjs/apis/sendVoiceCall.cjs +110 -0
- package/dist/cjs/apis/setHiddenConversations.cjs +2 -0
- package/dist/cjs/apis/setMute.cjs +2 -0
- package/dist/cjs/apis/setPinnedConversations.cjs +2 -0
- package/dist/cjs/apis/undo.cjs +2 -0
- package/dist/cjs/apis/updateAutoDeleteChat.cjs +2 -0
- package/dist/cjs/apis/uploadAttachment.cjs +8 -1
- package/dist/cjs/apis.cjs +14 -0
- package/dist/cjs/index.cjs +24 -0
- package/dist/cjs/models/CallEvent.cjs +51 -0
- package/dist/cjs/models/ClearUnread.cjs +17 -0
- package/dist/cjs/models/SyncEvent.cjs +54 -0
- package/dist/cjs/utils.cjs +153 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +2 -0
- package/dist/models/CallEvent.d.ts +30 -0
- package/dist/models/CallEvent.js +47 -0
- package/dist/models/ClearUnread.d.ts +22 -0
- package/dist/models/ClearUnread.js +12 -0
- package/dist/models/SyncData.d.ts +35 -0
- package/dist/models/SyncData.js +1 -0
- package/dist/models/SyncEvent.d.ts +83 -0
- package/dist/models/SyncEvent.js +50 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/index.js +4 -0
- package/dist/utils.d.ts +34 -0
- package/dist/utils.js +148 -1
- package/docs/REA_REVERSE_ENGINEERING_PLAN.md +140 -0
- package/package.json +3 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ZaloApiError = require('../Errors/ZaloApiError.cjs');
|
|
4
|
+
var utils = require('../utils.cjs');
|
|
5
|
+
var sendVoiceCall = require('./sendVoiceCall.cjs');
|
|
6
|
+
|
|
7
|
+
const cancelVoiceCallFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const voiceCallService = (_a = api.zpwServiceMap.voice_call) === null || _a === void 0 ? void 0 : _a[0];
|
|
10
|
+
/**
|
|
11
|
+
* Huỷ cuộc gọi đang đổ chuông trước khi người nhận bắt máy (`/api/voicecall/cancel`, command `11305`).
|
|
12
|
+
*
|
|
13
|
+
* @param calleeId User ID của người nhận cuộc gọi
|
|
14
|
+
* @param callId ID của cuộc gọi (nhận từ `sendVoiceCall`)
|
|
15
|
+
* @param options Tuỳ chọn loại cuộc gọi (`callType`) và `status`
|
|
16
|
+
* @throws {ZaloApiError}
|
|
17
|
+
*/
|
|
18
|
+
return async function cancelVoiceCall(calleeId, callId, options = {}) {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
if (!calleeId)
|
|
21
|
+
throw new ZaloApiError.ZaloApiError("Missing calleeId");
|
|
22
|
+
if (!callId)
|
|
23
|
+
throw new ZaloApiError.ZaloApiError("Missing callId");
|
|
24
|
+
if (!voiceCallService)
|
|
25
|
+
throw new ZaloApiError.ZaloApiError("Missing voice_call service URL in zpwServiceMap");
|
|
26
|
+
const numericCalleeId = Number.isNaN(Number(calleeId)) ? calleeId : Number(calleeId);
|
|
27
|
+
const params = {
|
|
28
|
+
callerId: numericCalleeId,
|
|
29
|
+
callId,
|
|
30
|
+
callType: (_a = options.callType) !== null && _a !== void 0 ? _a : sendVoiceCall.CallType.Audio,
|
|
31
|
+
status: (_b = options.status) !== null && _b !== void 0 ? _b : 0,
|
|
32
|
+
imei: ctx.imei,
|
|
33
|
+
};
|
|
34
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
35
|
+
if (!encryptedParams)
|
|
36
|
+
throw new ZaloApiError.ZaloApiError("Failed to encrypt cancelVoiceCall params");
|
|
37
|
+
const url = utils.makeURL(`${voiceCallService}/api/voicecall/cancel`, {
|
|
38
|
+
zpw_type: 24,
|
|
39
|
+
params: encryptedParams,
|
|
40
|
+
});
|
|
41
|
+
const response = await utils.request(url, {
|
|
42
|
+
method: "GET",
|
|
43
|
+
});
|
|
44
|
+
return utils.resolve(response);
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
exports.cancelVoiceCallFactory = cancelVoiceCallFactory;
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
var Reminder = require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const createReminderFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -7,6 +7,7 @@ const decryptGidsFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
|
7
7
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/gid/decrypt`);
|
|
8
8
|
/**
|
|
9
9
|
* Giải mã danh sách Global ID (g_...) ẩn danh thành User ID thật
|
|
10
|
+
* (tương ứng hàm `getUidFromGlobalNoiseId` / command `12054` trên Zalo PC)
|
|
10
11
|
*
|
|
11
12
|
* @param gids Danh sách Global ID (hoặc 1 GID đơn lẻ)
|
|
12
13
|
* @throws {ZaloApiError}
|
|
@@ -17,6 +18,7 @@ const decryptGidsFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
|
17
18
|
if (!Array.isArray(gids))
|
|
18
19
|
gids = [gids];
|
|
19
20
|
const params = {
|
|
21
|
+
globalUids: JSON.stringify(gids),
|
|
20
22
|
gids,
|
|
21
23
|
imei: ctx.imei,
|
|
22
24
|
};
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const deleteChatFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const deleteMessageFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const editReminderFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ZaloApiError = require('../Errors/ZaloApiError.cjs');
|
|
4
|
+
var utils = require('../utils.cjs');
|
|
5
|
+
|
|
6
|
+
const endVoiceCallFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
7
|
+
var _a;
|
|
8
|
+
const voiceCallService = (_a = api.zpwServiceMap.voice_call) === null || _a === void 0 ? void 0 : _a[0];
|
|
9
|
+
/**
|
|
10
|
+
* Kết thúc cuộc gọi thoại / video (`/api/voicecall/endcall`, command `11306`).
|
|
11
|
+
*
|
|
12
|
+
* @param calleeId User ID của đối phương
|
|
13
|
+
* @param callId ID của cuộc gọi
|
|
14
|
+
* @param options Tuỳ chọn mã trạng thái kết thúc (`status`, mặc định `3`)
|
|
15
|
+
* @throws {ZaloApiError}
|
|
16
|
+
*/
|
|
17
|
+
return async function endVoiceCall(calleeId, callId, options = {}) {
|
|
18
|
+
var _a;
|
|
19
|
+
if (!calleeId)
|
|
20
|
+
throw new ZaloApiError.ZaloApiError("Missing calleeId");
|
|
21
|
+
if (!callId)
|
|
22
|
+
throw new ZaloApiError.ZaloApiError("Missing callId");
|
|
23
|
+
if (!voiceCallService)
|
|
24
|
+
throw new ZaloApiError.ZaloApiError("Missing voice_call service URL in zpwServiceMap");
|
|
25
|
+
const numericCalleeId = Number.isNaN(Number(calleeId)) ? calleeId : Number(calleeId);
|
|
26
|
+
const params = {
|
|
27
|
+
uidTo: numericCalleeId,
|
|
28
|
+
callId,
|
|
29
|
+
status: (_a = options.status) !== null && _a !== void 0 ? _a : 3,
|
|
30
|
+
imei: ctx.imei,
|
|
31
|
+
};
|
|
32
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
33
|
+
if (!encryptedParams)
|
|
34
|
+
throw new ZaloApiError.ZaloApiError("Failed to encrypt endVoiceCall params");
|
|
35
|
+
const url = utils.makeURL(`${voiceCallService}/api/voicecall/endcall`, {
|
|
36
|
+
zpw_type: 24,
|
|
37
|
+
params: encryptedParams,
|
|
38
|
+
});
|
|
39
|
+
const response = await utils.request(url, {
|
|
40
|
+
method: "GET",
|
|
41
|
+
});
|
|
42
|
+
return utils.resolve(response);
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
exports.endVoiceCallFactory = endVoiceCallFactory;
|
|
@@ -12,6 +12,8 @@ require('../models/GroupEvent.cjs');
|
|
|
12
12
|
require('../models/Reaction.cjs');
|
|
13
13
|
require('../models/Reminder.cjs');
|
|
14
14
|
require('../models/ZBusiness.cjs');
|
|
15
|
+
require('../models/SyncEvent.cjs');
|
|
16
|
+
require('../models/CallEvent.cjs');
|
|
15
17
|
|
|
16
18
|
const findUserFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
17
19
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/profile/get`);
|
|
@@ -12,6 +12,8 @@ require('../models/GroupEvent.cjs');
|
|
|
12
12
|
require('../models/Reaction.cjs');
|
|
13
13
|
require('../models/Reminder.cjs');
|
|
14
14
|
require('../models/ZBusiness.cjs');
|
|
15
|
+
require('../models/SyncEvent.cjs');
|
|
16
|
+
require('../models/CallEvent.cjs');
|
|
15
17
|
|
|
16
18
|
const findUserByUsernameFactory = utils.apiFactory()((api, _ctx, utils) => {
|
|
17
19
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/search/by-user-name`);
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const forwardMessageFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -12,6 +12,8 @@ require('../models/GroupEvent.cjs');
|
|
|
12
12
|
require('../models/Reaction.cjs');
|
|
13
13
|
require('../models/Reminder.cjs');
|
|
14
14
|
require('../models/ZBusiness.cjs');
|
|
15
|
+
require('../models/SyncEvent.cjs');
|
|
16
|
+
require('../models/CallEvent.cjs');
|
|
15
17
|
|
|
16
18
|
const getAllFriendsFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
17
19
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/getfriends`);
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const getAvatarUrlProfileFactory = utils.apiFactory()((api, _ctx, utils) => {
|
|
@@ -13,6 +13,8 @@ var Message = require('../models/Message.cjs');
|
|
|
13
13
|
require('../models/Reaction.cjs');
|
|
14
14
|
require('../models/Reminder.cjs');
|
|
15
15
|
require('../models/ZBusiness.cjs');
|
|
16
|
+
require('../models/SyncEvent.cjs');
|
|
17
|
+
require('../models/CallEvent.cjs');
|
|
16
18
|
|
|
17
19
|
const getGroupChatHistoryFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
18
20
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group_cloud_message[0]}/api/cm/getrecentv2`);
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const getListBoardFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -11,6 +11,8 @@ require('../models/GroupEvent.cjs');
|
|
|
11
11
|
require('../models/Reaction.cjs');
|
|
12
12
|
require('../models/Reminder.cjs');
|
|
13
13
|
require('../models/ZBusiness.cjs');
|
|
14
|
+
require('../models/SyncEvent.cjs');
|
|
15
|
+
require('../models/CallEvent.cjs');
|
|
14
16
|
var utils = require('../utils.cjs');
|
|
15
17
|
|
|
16
18
|
const getListReminderFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
@@ -12,6 +12,8 @@ require('../models/GroupEvent.cjs');
|
|
|
12
12
|
require('../models/Reaction.cjs');
|
|
13
13
|
require('../models/Reminder.cjs');
|
|
14
14
|
require('../models/ZBusiness.cjs');
|
|
15
|
+
require('../models/SyncEvent.cjs');
|
|
16
|
+
require('../models/CallEvent.cjs');
|
|
15
17
|
|
|
16
18
|
const getMultiUsersByPhonesFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
17
19
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.friend[0]}/api/friend/profile/multiget`);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ZaloApiError = require('../Errors/ZaloApiError.cjs');
|
|
4
|
+
var utils = require('../utils.cjs');
|
|
5
|
+
|
|
6
|
+
const ZWID_ZNOISE_URL = "https://zwid.api.zalo.me/api/znoise";
|
|
7
|
+
function toNumericIds(ids) {
|
|
8
|
+
return ids.map((id) => Number.parseInt(String(id), 10));
|
|
9
|
+
}
|
|
10
|
+
function normalizeNoised(list, expected, stripGroupPrefix) {
|
|
11
|
+
const out = [];
|
|
12
|
+
const arr = Array.isArray(list) ? list : [];
|
|
13
|
+
for (let i = 0; i < expected; i++) {
|
|
14
|
+
let v = arr[i] == null ? "" : String(arr[i]);
|
|
15
|
+
if (stripGroupPrefix && v.startsWith("g"))
|
|
16
|
+
v = v.slice(1);
|
|
17
|
+
out.push(v === "0" ? "" : v);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
const getNoisedIdsFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
22
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/znoise`);
|
|
23
|
+
/**
|
|
24
|
+
* Chuyển đổi danh sách UID cá nhân (`fids`) và GID nhóm (`gids`) dạng số thuần (từ SQLite ZDB4.0 mobile)
|
|
25
|
+
* sang định dạng Noised ID 19 chữ số dùng trên Zalo Web/PC (`getNoisedUids`, command `12390`).
|
|
26
|
+
* Tự động fallback sang `https://zwid.api.zalo.me/api/znoise` nếu profile domain trả về lỗi.
|
|
27
|
+
*
|
|
28
|
+
* @param params Danh sách `fids` và `gids`
|
|
29
|
+
* @throws {ZaloApiError}
|
|
30
|
+
*/
|
|
31
|
+
return async function getNoisedIds({ fids = [], gids = [] }) {
|
|
32
|
+
const payload = {
|
|
33
|
+
fids: toNumericIds(fids),
|
|
34
|
+
gids: toNumericIds(gids),
|
|
35
|
+
};
|
|
36
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(payload));
|
|
37
|
+
if (!encryptedParams)
|
|
38
|
+
throw new ZaloApiError.ZaloApiError("Failed to encrypt params");
|
|
39
|
+
try {
|
|
40
|
+
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
|
41
|
+
method: "GET",
|
|
42
|
+
});
|
|
43
|
+
const data = await utils.resolve(response);
|
|
44
|
+
const raw = (data !== null && data !== void 0 ? data : {});
|
|
45
|
+
return {
|
|
46
|
+
fids: normalizeNoised(raw.fids, fids.length, false),
|
|
47
|
+
gids: normalizeNoised(raw.gids, gids.length, true),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (primaryErr) {
|
|
51
|
+
try {
|
|
52
|
+
const body = new URLSearchParams({ params: encryptedParams }).toString();
|
|
53
|
+
const fallbackUrl = utils.makeURL(ZWID_ZNOISE_URL);
|
|
54
|
+
const response = await utils.request(fallbackUrl, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
body,
|
|
57
|
+
});
|
|
58
|
+
const data = await utils.resolve(response);
|
|
59
|
+
const raw = (data !== null && data !== void 0 ? data : {});
|
|
60
|
+
return {
|
|
61
|
+
fids: normalizeNoised(raw.fids, fids.length, false),
|
|
62
|
+
gids: normalizeNoised(raw.gids, gids.length, true),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (_a) {
|
|
66
|
+
throw primaryErr;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
exports.getNoisedIdsFactory = getNoisedIdsFactory;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('node:fs');
|
|
4
|
+
var path = require('node:path');
|
|
5
|
+
var toughCookie = require('tough-cookie');
|
|
6
|
+
var ZaloApiError = require('../Errors/ZaloApiError.cjs');
|
|
7
|
+
var utils = require('../utils.cjs');
|
|
8
|
+
|
|
9
|
+
const getSyncDataFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
10
|
+
async function downloadFileStream(url) {
|
|
11
|
+
if (!ctx.cookie)
|
|
12
|
+
ctx.cookie = new toughCookie.CookieJar();
|
|
13
|
+
const cookie = ctx.cookie;
|
|
14
|
+
const manualHeaders = {
|
|
15
|
+
"Cache-Control": "no-store, must-revalidate",
|
|
16
|
+
Pragma: "no-cache",
|
|
17
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
18
|
+
"Accept-Language": "en-US",
|
|
19
|
+
"User-Agent": ctx.userAgent || "",
|
|
20
|
+
cookie: await cookie.getCookieString("https://chat.zalo.me/"),
|
|
21
|
+
Expires: "0",
|
|
22
|
+
"Sec-Fetch-Dest": "empty",
|
|
23
|
+
"Sec-Fetch-Mode": "no-cors",
|
|
24
|
+
"Sec-Fetch-Site": "none",
|
|
25
|
+
Connection: "keep-alive",
|
|
26
|
+
};
|
|
27
|
+
const response = await utils.request(url, {
|
|
28
|
+
method: "GET",
|
|
29
|
+
headers: manualHeaders,
|
|
30
|
+
}, true);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new ZaloApiError.ZaloApiError(`Failed to download sync file: HTTP ${response.status}`);
|
|
33
|
+
}
|
|
34
|
+
return response;
|
|
35
|
+
}
|
|
36
|
+
async function downloadFile(url) {
|
|
37
|
+
const response = await downloadFileStream(url);
|
|
38
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
39
|
+
return Buffer.from(arrayBuffer);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Tải xuống file sao lưu tin nhắn từ sự kiện `syncmsg_info` (`.db.crypt`, định dạng `ZDB4.0`)
|
|
43
|
+
* và lưu ra ổ đĩa hoặc trả về `ReadableStream`.
|
|
44
|
+
*
|
|
45
|
+
* @param params Thông tin file sao lưu nhận được từ `SyncEventType.SYNCMSG_INFO`
|
|
46
|
+
* @returns `Promise<SyncDataResponse>`
|
|
47
|
+
*/
|
|
48
|
+
return async function getSyncData({ url, encrypted_key, file_name, file_size, checksum_code, from_seq_id, is_full_transfer, returnStream = false, savePath = "./", }) {
|
|
49
|
+
try {
|
|
50
|
+
if (returnStream) {
|
|
51
|
+
const response = await downloadFileStream(url);
|
|
52
|
+
const syncDataStream = {
|
|
53
|
+
stream: response.body,
|
|
54
|
+
metadata: {
|
|
55
|
+
file_name,
|
|
56
|
+
file_size,
|
|
57
|
+
checksum_code,
|
|
58
|
+
from_seq_id,
|
|
59
|
+
is_full_transfer,
|
|
60
|
+
encrypted_key,
|
|
61
|
+
},
|
|
62
|
+
response: {
|
|
63
|
+
status: response.status,
|
|
64
|
+
statusText: response.statusText,
|
|
65
|
+
url: response.url,
|
|
66
|
+
contentType: response.headers.get("content-type"),
|
|
67
|
+
contentLength: response.headers.get("content-length"),
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
success: true,
|
|
72
|
+
stream: syncDataStream,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const encryptedFileData = await downloadFile(url);
|
|
76
|
+
const fileName = file_name.endsWith(".db.crypt") ? file_name : `${file_name}.db.crypt`;
|
|
77
|
+
const fullPath = path.join(savePath, fileName);
|
|
78
|
+
const dir = path.dirname(fullPath);
|
|
79
|
+
if (!fs.existsSync(dir)) {
|
|
80
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
fs.writeFileSync(fullPath, encryptedFileData);
|
|
83
|
+
const syncData = {
|
|
84
|
+
file_path: fullPath,
|
|
85
|
+
encrypted_key,
|
|
86
|
+
metadata: {
|
|
87
|
+
file_name: fileName,
|
|
88
|
+
file_size,
|
|
89
|
+
checksum_code,
|
|
90
|
+
from_seq_id,
|
|
91
|
+
is_full_transfer,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
success: true,
|
|
96
|
+
data: syncData,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
error: error instanceof Error ? error.message : "Unknown error occurred",
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
exports.getSyncDataFactory = getSyncDataFactory;
|
|
@@ -12,6 +12,8 @@ require('../models/GroupEvent.cjs');
|
|
|
12
12
|
require('../models/Reaction.cjs');
|
|
13
13
|
require('../models/Reminder.cjs');
|
|
14
14
|
require('../models/ZBusiness.cjs');
|
|
15
|
+
require('../models/SyncEvent.cjs');
|
|
16
|
+
require('../models/CallEvent.cjs');
|
|
15
17
|
|
|
16
18
|
const getUserInfoFactory = utils.apiFactory()((api, ctx, utils) => {
|
|
17
19
|
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/getprofiles/v2`);
|
package/dist/cjs/apis/listen.cjs
CHANGED
|
@@ -17,6 +17,9 @@ var SeenMessage = require('../models/SeenMessage.cjs');
|
|
|
17
17
|
var Typing = require('../models/Typing.cjs');
|
|
18
18
|
var Undo = require('../models/Undo.cjs');
|
|
19
19
|
require('../models/ZBusiness.cjs');
|
|
20
|
+
var ClearUnread = require('../models/ClearUnread.cjs');
|
|
21
|
+
var SyncEvent = require('../models/SyncEvent.cjs');
|
|
22
|
+
var CallEvent = require('../models/CallEvent.cjs');
|
|
20
23
|
var utils = require('../utils.cjs');
|
|
21
24
|
var ZaloApiError = require('../Errors/ZaloApiError.cjs');
|
|
22
25
|
|
|
@@ -233,7 +236,7 @@ class Listener extends EventEmitter {
|
|
|
233
236
|
this.emit("error", event);
|
|
234
237
|
};
|
|
235
238
|
ws.onmessage = async (event) => {
|
|
236
|
-
var _a, _b, _c;
|
|
239
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
237
240
|
this.resetWatchdog();
|
|
238
241
|
this.emit("pong"); // Pulse event to notify watchdog that socket is alive
|
|
239
242
|
const { data } = event;
|
|
@@ -355,6 +358,21 @@ class Listener extends EventEmitter {
|
|
|
355
358
|
continue;
|
|
356
359
|
this.emit("friend_event", friendEvent);
|
|
357
360
|
}
|
|
361
|
+
else if (control.content.act_type == "syncmsgmb" ||
|
|
362
|
+
control.content.act_type == "transfer_msg") {
|
|
363
|
+
const syncEventData = typeof control.content.data == "string"
|
|
364
|
+
? JSON.parse(control.content.data)
|
|
365
|
+
: control.content.data;
|
|
366
|
+
const syncEvent = SyncEvent.initializeSyncEvent(syncEventData, control.content.act, control.content.act_type);
|
|
367
|
+
this.emit("sync_event", syncEvent);
|
|
368
|
+
}
|
|
369
|
+
else if (control.content.act_type == "voip") {
|
|
370
|
+
const callEventData = typeof control.content.data == "string"
|
|
371
|
+
? JSON.parse(control.content.data)
|
|
372
|
+
: control.content.data;
|
|
373
|
+
const callEvent = CallEvent.initializeCallEvent(callEventData, control.content.act, control.content.act_type);
|
|
374
|
+
this.emit("call_event", callEvent);
|
|
375
|
+
}
|
|
358
376
|
}
|
|
359
377
|
}
|
|
360
378
|
if (cmd == 612) {
|
|
@@ -382,17 +400,54 @@ class Listener extends EventEmitter {
|
|
|
382
400
|
const reactionObjects = reacts.map((react) => new Reaction.Reaction(this.ctx.uid, react, isGroup));
|
|
383
401
|
this.emit("old_reactions", reactionObjects, isGroup);
|
|
384
402
|
}
|
|
385
|
-
if (cmd == 510 && subCmd == 1) {
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
const
|
|
389
|
-
|
|
403
|
+
if (cmd == 510 && (subCmd == 0 || subCmd == 1)) {
|
|
404
|
+
const decoded = await utils.decodeEventData(parsed, this.cipherKey);
|
|
405
|
+
const parsedData = (_d = decoded === null || decoded === void 0 ? void 0 : decoded.data) !== null && _d !== void 0 ? _d : decoded;
|
|
406
|
+
const msgs = ((_e = parsedData === null || parsedData === void 0 ? void 0 : parsedData.msgs) !== null && _e !== void 0 ? _e : []);
|
|
407
|
+
const responseMsgs = [];
|
|
408
|
+
for (const msg of msgs) {
|
|
409
|
+
if (typeof msg.content == "object" && utils.hasOwn(msg.content, "deleteMsg")) {
|
|
410
|
+
const undoObject = new Undo.Undo(this.ctx.uid, msg, false);
|
|
411
|
+
if (undoObject.isSelf && !this.selfListen)
|
|
412
|
+
continue;
|
|
413
|
+
this.emit("undo", undoObject);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
responseMsgs.push(new Message.UserMessage(this.ctx.uid, msg));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
if (responseMsgs.length > 0 || msgs.length === 0) {
|
|
420
|
+
this.emit("old_messages", responseMsgs, Enum.ThreadType.User, (parsedData === null || parsedData === void 0 ? void 0 : parsedData.more) === 1);
|
|
421
|
+
}
|
|
390
422
|
}
|
|
391
|
-
if (cmd == 511 && subCmd == 1) {
|
|
392
|
-
const
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
|
|
423
|
+
if (cmd == 511 && (subCmd == 0 || subCmd == 1)) {
|
|
424
|
+
const decoded = await utils.decodeEventData(parsed, this.cipherKey);
|
|
425
|
+
const parsedData = (_f = decoded === null || decoded === void 0 ? void 0 : decoded.data) !== null && _f !== void 0 ? _f : decoded;
|
|
426
|
+
const groupMsgs = ((_g = parsedData === null || parsedData === void 0 ? void 0 : parsedData.groupMsgs) !== null && _g !== void 0 ? _g : []);
|
|
427
|
+
const responseMsgs = [];
|
|
428
|
+
for (const msg of groupMsgs) {
|
|
429
|
+
if (typeof msg.content == "object" && utils.hasOwn(msg.content, "deleteMsg")) {
|
|
430
|
+
const undoObject = new Undo.Undo(this.ctx.uid, msg, true);
|
|
431
|
+
if (undoObject.isSelf && !this.selfListen)
|
|
432
|
+
continue;
|
|
433
|
+
this.emit("undo", undoObject);
|
|
434
|
+
}
|
|
435
|
+
else {
|
|
436
|
+
responseMsgs.push(new Message.GroupMessage(this.ctx.uid, msg));
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (responseMsgs.length > 0 || groupMsgs.length === 0) {
|
|
440
|
+
this.emit("old_messages", responseMsgs, Enum.ThreadType.Group, (parsedData === null || parsedData === void 0 ? void 0 : parsedData.more) === 1);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if ((cmd == 504 || cmd == 524) && subCmd == 0) {
|
|
444
|
+
const decoded = await utils.decodeEventData(parsed, this.cipherKey);
|
|
445
|
+
const parsedData = (_h = decoded === null || decoded === void 0 ? void 0 : decoded.data) !== null && _h !== void 0 ? _h : decoded;
|
|
446
|
+
const clearUnreads = ((_j = parsedData === null || parsedData === void 0 ? void 0 : parsedData.clearUnreads) !== null && _j !== void 0 ? _j : []);
|
|
447
|
+
if (Array.isArray(clearUnreads) && clearUnreads.length > 0) {
|
|
448
|
+
const items = clearUnreads.map((item) => new ClearUnread.ClearUnread(item));
|
|
449
|
+
this.emit("unread_cleared", items);
|
|
450
|
+
}
|
|
396
451
|
}
|
|
397
452
|
if (cmd == 602 && subCmd == 0) {
|
|
398
453
|
const parsedData = (await utils.decodeEventData(parsed, this.cipherKey)).data;
|
|
@@ -488,16 +543,18 @@ class Listener extends EventEmitter {
|
|
|
488
543
|
}
|
|
489
544
|
}
|
|
490
545
|
/**
|
|
491
|
-
* Request old messages
|
|
546
|
+
* Request old messages from Zalo WebSocket queue (`cmd 510` for User, `cmd 511` for Group).
|
|
547
|
+
* When `lastMsgId` is `null` or omitted, defaults to `"10000000000000000"` to fetch the latest offline messages.
|
|
492
548
|
*
|
|
493
|
-
* @param
|
|
549
|
+
* @param threadType ThreadType.User or ThreadType.Group
|
|
550
|
+
* @param lastMsgId Optional cursor message ID (`actionId`) for pagination
|
|
494
551
|
*/
|
|
495
552
|
requestOldMessages(threadType, lastMsgId = null) {
|
|
496
553
|
const payload = {
|
|
497
554
|
version: 1,
|
|
498
555
|
cmd: threadType === Enum.ThreadType.User ? 510 : 511,
|
|
499
556
|
subCmd: 1,
|
|
500
|
-
data: { first: true, lastId: lastMsgId, preIds: [] },
|
|
557
|
+
data: { first: true, lastId: lastMsgId !== null && lastMsgId !== void 0 ? lastMsgId : "10000000000000000", preIds: [] },
|
|
501
558
|
};
|
|
502
559
|
this.sendWs(payload);
|
|
503
560
|
}
|