@softtynet/zca-js 2.3.2 → 2.3.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.
- package/README.md +63 -21
- package/dist/apis/auth/exportSession.d.ts +7 -0
- package/dist/apis/auth/exportSession.js +17 -0
- package/dist/apis/chat/getDirectMessageStatus.d.ts +14 -0
- package/dist/apis/chat/getDirectMessageStatus.js +52 -0
- package/dist/apis/chat/getSuggestedConversations.d.ts +5 -0
- package/dist/apis/chat/getSuggestedConversations.js +24 -0
- package/dist/apis/chat/updatePinConversations.d.ts +24 -0
- package/dist/apis/chat/updatePinConversations.js +40 -0
- package/dist/apis/friend/getFriendProfilesV2.d.ts +26 -0
- package/dist/apis/friend/getFriendProfilesV2.js +38 -0
- package/dist/apis/friend/getFriendsActivePCWeb.d.ts +6 -0
- package/dist/apis/friend/getFriendsActivePCWeb.js +15 -0
- package/dist/apis/friend/verifyFriend.d.ts +11 -0
- package/dist/apis/friend/verifyFriend.js +37 -0
- package/dist/apis/group/analyseGroup.d.ts +4 -0
- package/dist/apis/group/analyseGroup.js +28 -0
- package/dist/apis/group/checkQuotaCommunityMember.d.ts +6 -0
- package/dist/apis/group/checkQuotaCommunityMember.js +34 -0
- package/dist/apis/group/getE2eeGroupList.d.ts +7 -0
- package/dist/apis/group/getE2eeGroupList.js +15 -0
- package/dist/apis/group/getGroupChatHistory.d.ts +37 -6
- package/dist/apis/group/getGroupChatHistory.js +41 -19
- package/dist/apis/group/getGroupCloudMessagePath.d.ts +19 -0
- package/dist/apis/group/getGroupCloudMessagePath.js +51 -0
- package/dist/apis/group/getGroupHistoryLegacy.d.ts +7 -0
- package/dist/apis/group/getGroupHistoryLegacy.js +62 -0
- package/dist/apis/group/getGroupInfoV2.d.ts +30 -0
- package/dist/apis/group/getGroupInfoV2.js +48 -0
- package/dist/apis/group/getGroupListV3.d.ts +19 -0
- package/dist/apis/group/getGroupListV3.js +29 -0
- package/dist/apis/group/getGroupMessageStatus.d.ts +26 -0
- package/dist/apis/group/getGroupMessageStatus.js +77 -0
- package/dist/apis/group/getMultiGroupCloudMessages.d.ts +5 -0
- package/dist/apis/group/getMultiGroupCloudMessages.js +29 -0
- package/dist/apis/media/getConversationMedia.d.ts +10 -0
- package/dist/apis/media/getPersonalMedia.d.ts +8 -0
- package/dist/apis/media/getPersonalMedia.js +31 -0
- package/dist/apis/media/getPersonalMediaPreview.d.ts +3 -0
- package/dist/apis/media/getPersonalMediaPreview.js +24 -0
- package/dist/apis/media/removePersonalMedia.d.ts +9 -0
- package/dist/apis/media/removePersonalMedia.js +28 -0
- package/dist/apis.d.ts +57 -0
- package/dist/apis.js +95 -0
- package/dist/cjs/apis/auth/exportSession.cjs +22 -0
- package/dist/cjs/apis/chat/getDirectMessageStatus.cjs +58 -0
- package/dist/cjs/apis/chat/getSuggestedConversations.cjs +29 -0
- package/dist/cjs/apis/chat/updatePinConversations.cjs +45 -0
- package/dist/cjs/apis/friend/getFriendProfilesV2.cjs +43 -0
- package/dist/cjs/apis/friend/getFriendsActivePCWeb.cjs +20 -0
- package/dist/cjs/apis/friend/verifyFriend.cjs +42 -0
- package/dist/cjs/apis/group/analyseGroup.cjs +33 -0
- package/dist/cjs/apis/group/checkQuotaCommunityMember.cjs +39 -0
- package/dist/cjs/apis/group/getE2eeGroupList.cjs +20 -0
- package/dist/cjs/apis/group/getGroupChatHistory.cjs +41 -18
- package/dist/cjs/apis/group/getGroupCloudMessagePath.cjs +69 -0
- package/dist/cjs/apis/group/getGroupHistoryLegacy.cjs +80 -0
- package/dist/cjs/apis/group/getGroupInfoV2.cjs +53 -0
- package/dist/cjs/apis/group/getGroupListV3.cjs +34 -0
- package/dist/cjs/apis/group/getGroupMessageStatus.cjs +83 -0
- package/dist/cjs/apis/group/getMultiGroupCloudMessages.cjs +34 -0
- package/dist/cjs/apis/media/getPersonalMedia.cjs +36 -0
- package/dist/cjs/apis/media/getPersonalMediaPreview.cjs +29 -0
- package/dist/cjs/apis/media/removePersonalMedia.cjs +33 -0
- package/dist/cjs/apis.cjs +95 -0
- package/dist/cjs/constants/endpoints.cjs +13 -0
- package/dist/cjs/constants/protocol.cjs +1 -1
- package/dist/cjs/context.cjs +20 -2
- package/dist/cjs/core/zcloud-client.cjs +1 -2
- package/dist/cjs/crypto/ws-cipher.cjs +66 -2
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/realtime/listener.cjs +18 -6
- package/dist/cjs/update.cjs +10 -1
- package/dist/cjs/utils.cjs +22 -5
- package/dist/constants/endpoints.d.ts +13 -0
- package/dist/constants/endpoints.js +13 -0
- package/dist/constants/protocol.d.ts +1 -1
- package/dist/constants/protocol.js +1 -1
- package/dist/context.d.ts +10 -0
- package/dist/context.js +20 -2
- package/dist/crypto/ws-cipher.d.ts +7 -0
- package/dist/crypto/ws-cipher.js +64 -2
- package/dist/index.d.ts +22 -3
- package/dist/index.js +1 -1
- package/dist/realtime/listener.d.ts +1 -0
- package/dist/realtime/listener.js +18 -6
- package/dist/update.js +10 -1
- package/dist/utils.js +17 -4
- package/index.d.ts +1 -1
- package/package.json +15 -5
package/README.md
CHANGED
|
@@ -2,10 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
<p align="left">
|
|
4
4
|
<a href="https://www.npmjs.com/package/@softtynet/zca-js"><img src="https://img.shields.io/npm/v/@softtynet/zca-js.svg?label=%40softtynet%2Fzca-js&color=0068ff" alt="npm version" /></a>
|
|
5
|
+
<a href="https://softtyos.github.io/zca-js-docs/"><img src="https://img.shields.io/badge/Docs-VitePress-646cff.svg" alt="Documentation" /></a>
|
|
5
6
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-green.svg" alt="License: MIT" /></a>
|
|
6
7
|
</p>
|
|
7
8
|
|
|
8
|
-
**`@softtynet/zca-js`** là bộ thư viện
|
|
9
|
+
**`@softtynet/zca-js`** là bộ thư viện SDK kết nối và tương tác Zalo dành cho **Node.js**, **TypeScript** và **Bun**, được phát triển và duy trì bởi **Softtynet Co., Ltd.** dựa trên phân tích giao thức Zalo PC `26.7.10`.
|
|
10
|
+
|
|
11
|
+
- **Trang tài liệu chính thức (Documentation)**: [**https://softtyos.github.io/zca-js-docs/**](https://softtyos.github.io/zca-js-docs/)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Điểm nổi bật
|
|
16
|
+
|
|
17
|
+
- **Kiến trúc 12 Domains (`224 API nguyên bản`)**: Tổ chức trực quan qua `api.auth`, `api.chat`, `api.group`, `api.friend`, `api.profile`, `api.sync`, `api.zcloud`, `api.call`, `api.media`, `api.sticker`, `api.board`, `api.business` (vẫn hỗ trợ gọi phẳng `api.<method>` tương thích ngược 100%).
|
|
18
|
+
- **Đồng bộ lịch sử Mobile (`ZDB 4.0`) & Catch-up Sync**: Hỗ trợ đầy đủ luồng `requestSyncFromPhone` $\rightarrow$ `getSyncData` (giải mã RSA-2048 OAEP/PKCS1 + ZDB 4.0 64KB multi-chunk AES-256-CBC + Deflate) & `pullMobile`.
|
|
19
|
+
- **ZCloud, MediaStore & Bảo toàn Số nguyên 64-bit (`preParseJsonIds`)**: Tự động giữ nguyên độ chính xác chuỗi 19 chữ số cho `owner_id`, `group_id`, `globalMsgId`, `cliMsgId` trước khi `JSON.parse()` và tích hợp bộ mã hóa `98yS` AES-256-CBC cho ZCloud/ZFamily.
|
|
20
|
+
- **Tín hiệu Gọi Thoại & Video Call 1-1**: Điều khiển trọn vẹn vòng đời cuộc gọi (`11300` $\rightarrow$ `11306`: `sendVoiceCall`, `cancelVoiceCall`, `endVoiceCall`) và lắng nghe `call_event` thời gian thực.
|
|
9
21
|
|
|
10
22
|
---
|
|
11
23
|
|
|
@@ -19,8 +31,6 @@ bun add @softtynet/zca-js
|
|
|
19
31
|
|
|
20
32
|
### Cấu hình `imageMetadataGetter` (Tùy chọn khi gửi ảnh từ file nội bộ)
|
|
21
33
|
|
|
22
|
-
Nếu ứng dụng cần gửi ảnh hoặc GIF từ đường dẫn file trên máy, bạn có thể truyền hàm `imageMetadataGetter` (ví dụ sử dụng `sharp`):
|
|
23
|
-
|
|
24
34
|
```ts
|
|
25
35
|
import { Zalo } from "@softtynet/zca-js";
|
|
26
36
|
import sharp from "sharp";
|
|
@@ -41,6 +51,27 @@ const zalo = new Zalo({ imageMetadataGetter });
|
|
|
41
51
|
|
|
42
52
|
---
|
|
43
53
|
|
|
54
|
+
## Kiến trúc 12 Phân hệ (Domains)
|
|
55
|
+
|
|
56
|
+
| Phân hệ | Namespace | Số lượng API | Tài liệu chi tiết |
|
|
57
|
+
| :--- | :--- | :---: | :--- |
|
|
58
|
+
| **Xác thực & Phiên** | `api.auth` | 8 | [`docs/api/auth.md`](docs/api/auth.md) |
|
|
59
|
+
| **Tin nhắn & Hội thoại** | `api.chat` | 35 | [`docs/api/chat.md`](docs/api/chat.md) |
|
|
60
|
+
| **Nhóm & Cộng đồng** | `api.group` | 48 | [`docs/api/group.md`](docs/api/group.md) |
|
|
61
|
+
| **Bạn bè & Danh bạ** | `api.friend` | 26 | [`docs/api/friend.md`](docs/api/friend.md) |
|
|
62
|
+
| **Hồ sơ cá nhân** | `api.profile` | 18 | [`docs/api/profile.md`](docs/api/profile.md) |
|
|
63
|
+
| **Đồng bộ Mobile ZDB 4.0** | `api.sync` | 5 | [`docs/api/sync.md`](docs/api/sync.md) |
|
|
64
|
+
| **Đám mây ZCloud & ZFamily** | `api.zcloud` | 9 | [`docs/api/zcloud.md`](docs/api/zcloud.md) |
|
|
65
|
+
| **Gọi thoại & Video 1-1** | `api.call` | 3 | [`docs/api/call.md`](docs/api/call.md) |
|
|
66
|
+
| **Kho lưu trữ & Voice-to-Text** | `api.media` | 7 | [`docs/api/media.md`](docs/api/media.md) |
|
|
67
|
+
| **Nhãn dán & Biểu cảm** | `api.sticker` | 8 | [`docs/api/sticker.md`](docs/api/sticker.md) |
|
|
68
|
+
| **Bảng tin, Bình chọn & Lịch hẹn** | `api.board` | 16 | [`docs/api/board.md`](docs/api/board.md) |
|
|
69
|
+
| **Zalo Business & Danh mục** | `api.business` | 41 | [`docs/api/business.md`](docs/api/business.md) |
|
|
70
|
+
|
|
71
|
+
> Xem tổng quan toàn bộ tài liệu tại [`docs/api/index.md`](docs/api/index.md) hoặc chạy trang tài liệu VitePress cục bộ bằng lệnh `npm run docs:dev`.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
44
75
|
## Sử dụng cơ bản
|
|
45
76
|
|
|
46
77
|
### 1. Đăng nhập bằng mã QR
|
|
@@ -53,7 +84,7 @@ const api = await zalo.loginQR();
|
|
|
53
84
|
console.log("Đã đăng nhập:", api.getOwnId());
|
|
54
85
|
```
|
|
55
86
|
|
|
56
|
-
### 2. Lắng nghe
|
|
87
|
+
### 2. Lắng nghe sự kiện WebSocket thời gian thực
|
|
57
88
|
|
|
58
89
|
```ts
|
|
59
90
|
import { Zalo, ThreadType } from "@softtynet/zca-js";
|
|
@@ -74,25 +105,36 @@ api.listener.on("message", (message) => {
|
|
|
74
105
|
api.listener.start({ retryOnClose: true });
|
|
75
106
|
```
|
|
76
107
|
|
|
77
|
-
### 3.
|
|
108
|
+
### 3. Gọi API theo Domain Namespace
|
|
78
109
|
|
|
79
110
|
```ts
|
|
80
|
-
//
|
|
81
|
-
await api.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
// Nhóm & Lịch sử tin nhắn Cloud
|
|
112
|
+
const groupInfo = await api.group.getGroupInfo("888999000");
|
|
113
|
+
const history = await api.group.getGroupChatHistory("888999000", { count: 50, cursor: 0 });
|
|
114
|
+
const msgStatus = await api.group.getGroupMessageStatus("888999000", ["1000000000000000001"]);
|
|
115
|
+
|
|
116
|
+
// Kho lưu trữ Media / File / Link
|
|
117
|
+
const mediaPreview = await api.media.getMediaStorePreview("888999000", 50);
|
|
118
|
+
const mediaList = await api.media.getConversationMedia({
|
|
119
|
+
groupId: "888999000",
|
|
120
|
+
mediaType: "media",
|
|
121
|
+
limit: 50,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Giải mã thông tin thành viên hàng loạt
|
|
125
|
+
const profiles = await api.group.getGroupMembersInfo(["1000000000000000001"]);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Chạy trang Tài liệu (VitePress Docs)
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Khởi chạy máy chủ tài liệu VitePress cục bộ (http://localhost:5173)
|
|
134
|
+
npm run docs:dev
|
|
135
|
+
|
|
136
|
+
# Sinh lại tài liệu từ mã nguồn src/apis/* và đóng gói tĩnh
|
|
137
|
+
npm run docs:build
|
|
96
138
|
```
|
|
97
139
|
|
|
98
140
|
---
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type toughCookie from "tough-cookie";
|
|
2
|
+
import type { Credentials } from "../../zalo.js";
|
|
3
|
+
export type ExportedSession = Credentials & {
|
|
4
|
+
uid: string;
|
|
5
|
+
cookie: toughCookie.SerializedCookie[];
|
|
6
|
+
};
|
|
7
|
+
export declare const exportSessionFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => () => ExportedSession;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { apiFactory } from "../../utils.js";
|
|
2
|
+
export const exportSessionFactory = apiFactory()((_api, ctx) => {
|
|
3
|
+
/**
|
|
4
|
+
* Xuất toàn bộ thông tin phiên đăng nhập hiện tại (`uid`, `imei`, `userAgent`, `language`, `cookie`)
|
|
5
|
+
* dưới định dạng chuẩn `Credentials` để lưu trữ (JSON/Database) và truyền trực tiếp vào `zalo.login(session)`.
|
|
6
|
+
*/
|
|
7
|
+
return function exportSession() {
|
|
8
|
+
const serializedJar = ctx.cookie?.toJSON();
|
|
9
|
+
return {
|
|
10
|
+
uid: ctx.uid,
|
|
11
|
+
imei: ctx.imei,
|
|
12
|
+
userAgent: ctx.userAgent,
|
|
13
|
+
language: ctx.language || "vi",
|
|
14
|
+
cookie: serializedJar?.cookies ?? [],
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DirectMessageStatusItem = {
|
|
2
|
+
tId: string;
|
|
3
|
+
seen?: string | number;
|
|
4
|
+
deliver?: string | number;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type GetDirectMessageStatusResponse = {
|
|
8
|
+
statusInfos: DirectMessageStatusItem[];
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
export declare const getDirectMessageStatusFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (data: Array<string | {
|
|
12
|
+
tId: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}>) => Promise<GetDirectMessageStatusResponse>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory, preParseJsonIds } from "../../utils.js";
|
|
3
|
+
export const getDirectMessageStatusFactory = apiFactory()((api, _ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.chat[0]}/api/message/getStatusMsg`);
|
|
5
|
+
/**
|
|
6
|
+
* Truy vấn trạng thái Đã nhận (`deliver`) và Đã xem (`seen`) tin nhắn trong các hội thoại cá nhân 1-1 (command 12016)
|
|
7
|
+
*
|
|
8
|
+
* @param data Danh sách UID hoặc đối tượng truy vấn `{ tId }`
|
|
9
|
+
* @throws {ZaloApiError}
|
|
10
|
+
*/
|
|
11
|
+
return async function getDirectMessageStatus(data) {
|
|
12
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
13
|
+
throw new ZaloApiError("Missing data");
|
|
14
|
+
}
|
|
15
|
+
const formattedData = data.map((item) => (typeof item === "string" ? { tId: item } : item));
|
|
16
|
+
const params = {
|
|
17
|
+
param: JSON.stringify({
|
|
18
|
+
data: formattedData,
|
|
19
|
+
}),
|
|
20
|
+
};
|
|
21
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
22
|
+
if (!encryptedParams) {
|
|
23
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
24
|
+
}
|
|
25
|
+
const response = await utils.request(serviceURL, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
body: new URLSearchParams({
|
|
28
|
+
params: encryptedParams,
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
return utils.resolve(response, (result) => {
|
|
32
|
+
let rawData = result.data;
|
|
33
|
+
if (typeof rawData === "string" && rawData.length > 0) {
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(preParseJsonIds(rawData));
|
|
36
|
+
rawData = "data" in parsed && parsed.data ? parsed.data : parsed;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Giữ nguyên nếu không phải chuỗi JSON lồng
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (rawData && typeof rawData === "object") {
|
|
43
|
+
const obj = rawData;
|
|
44
|
+
return {
|
|
45
|
+
...obj,
|
|
46
|
+
statusInfos: Array.isArray(obj.statusInfos) ? obj.statusInfos : [],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { statusInfos: [] };
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type GetSuggestedConversationsResponse = {
|
|
2
|
+
conversations?: unknown[];
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
};
|
|
5
|
+
export declare const getSuggestedConversationsFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (language?: string) => Promise<GetSuggestedConversationsResponse>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const getSuggestedConversationsFactory = apiFactory()((api, ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.conversation[0]}/api/suggestconvers/list`);
|
|
5
|
+
/**
|
|
6
|
+
* Lấy danh sách các cuộc hội thoại được gợi ý (command 11233)
|
|
7
|
+
*
|
|
8
|
+
* @param language Ngôn ngữ hiển thị (mặc định theo `ctx.language` hoặc `"vi"`)
|
|
9
|
+
* @throws {ZaloApiError}
|
|
10
|
+
*/
|
|
11
|
+
return async function getSuggestedConversations(language) {
|
|
12
|
+
const params = {
|
|
13
|
+
language: language ?? ctx.language ?? "vi",
|
|
14
|
+
};
|
|
15
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
16
|
+
if (!encryptedParams) {
|
|
17
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
18
|
+
}
|
|
19
|
+
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
|
20
|
+
method: "GET",
|
|
21
|
+
});
|
|
22
|
+
return utils.resolve(response);
|
|
23
|
+
};
|
|
24
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type UpdatePinConversationsOptions = {
|
|
2
|
+
/**
|
|
3
|
+
* Danh sách ID hội thoại cần ghim / bỏ ghim (prefix `g` cho nhóm hoặc UID cho cá nhân).
|
|
4
|
+
*/
|
|
5
|
+
conversations: string[];
|
|
6
|
+
/**
|
|
7
|
+
* Loại thao tác khi dùng V2 (`1`: ghim, `2`: bỏ ghim). Nếu truyền `actionType`, API sẽ gọi `/api/pinconvers/updatev2` (cmd 12122).
|
|
8
|
+
*/
|
|
9
|
+
actionType?: number;
|
|
10
|
+
/**
|
|
11
|
+
* Tab hội thoại khi dùng V2 (tùy chọn).
|
|
12
|
+
*/
|
|
13
|
+
tab?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Phiên bản danh sách ghim khi dùng V1 (`/api/pinconvers/update`, cmd 12121, mặc định: `0`).
|
|
16
|
+
*/
|
|
17
|
+
version?: number;
|
|
18
|
+
};
|
|
19
|
+
export type UpdatePinConversationsResponse = {
|
|
20
|
+
version?: number;
|
|
21
|
+
conversations?: string[];
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
export declare const updatePinConversationsFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (options: UpdatePinConversationsOptions) => Promise<UpdatePinConversationsResponse>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const updatePinConversationsFactory = apiFactory()((api, _ctx, utils) => {
|
|
4
|
+
const v1ServiceURL = utils.makeURL(`${api.zpwServiceMap.conversation[0]}/api/pinconvers/update`);
|
|
5
|
+
const v2ServiceURL = utils.makeURL(`${api.zpwServiceMap.conversation[0]}/api/pinconvers/updatev2`);
|
|
6
|
+
/**
|
|
7
|
+
* Cập nhật danh sách hội thoại ghim qua `/api/pinconvers/update` (command 12121) hoặc `/api/pinconvers/updatev2` (command 12122)
|
|
8
|
+
*
|
|
9
|
+
* @param options Cấu hình danh sách hội thoại ghim
|
|
10
|
+
* @throws {ZaloApiError}
|
|
11
|
+
*/
|
|
12
|
+
return async function updatePinConversations(options) {
|
|
13
|
+
if (!options || !Array.isArray(options.conversations)) {
|
|
14
|
+
throw new ZaloApiError("Missing conversations");
|
|
15
|
+
}
|
|
16
|
+
const useV2 = options.actionType !== undefined;
|
|
17
|
+
const targetURL = useV2 ? v2ServiceURL : v1ServiceURL;
|
|
18
|
+
const params = useV2
|
|
19
|
+
? {
|
|
20
|
+
actionType: options.actionType,
|
|
21
|
+
conversations: options.conversations,
|
|
22
|
+
tab: options.tab,
|
|
23
|
+
}
|
|
24
|
+
: {
|
|
25
|
+
version: options.version ?? 0,
|
|
26
|
+
conversations: options.conversations,
|
|
27
|
+
};
|
|
28
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
29
|
+
if (!encryptedParams) {
|
|
30
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
31
|
+
}
|
|
32
|
+
const response = await utils.request(targetURL, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
body: new URLSearchParams({
|
|
35
|
+
params: encryptedParams,
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
return utils.resolve(response);
|
|
39
|
+
};
|
|
40
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GroupMemberProfile } from "../group/getGroupMembersInfo.js";
|
|
2
|
+
export type GetFriendProfilesV2Options = {
|
|
3
|
+
/**
|
|
4
|
+
* Phiên bản danh bạ (mặc định: `0`).
|
|
5
|
+
*/
|
|
6
|
+
phonebookVersion?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Kích thước ảnh đại diện (mặc định: `120`).
|
|
9
|
+
*/
|
|
10
|
+
avatarSize?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Ngôn ngữ (mặc định: `"vi"`).
|
|
13
|
+
*/
|
|
14
|
+
language?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Trả kèm trạng thái online của bạn bè (mặc định: `true`).
|
|
17
|
+
*/
|
|
18
|
+
showOnlineStatus?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export type GetFriendProfilesV2Response = {
|
|
21
|
+
profiles: Record<string, GroupMemberProfile>;
|
|
22
|
+
unchangeds_profile?: string[];
|
|
23
|
+
phonebook_version?: number;
|
|
24
|
+
[key: string]: unknown;
|
|
25
|
+
};
|
|
26
|
+
export declare const getFriendProfilesV2Factory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (friendIds: string | string[], options?: GetFriendProfilesV2Options) => Promise<GetFriendProfilesV2Response>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const getFriendProfilesV2Factory = apiFactory()((api, ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/getprofiles/v2`);
|
|
5
|
+
/**
|
|
6
|
+
* Lấy hàng loạt hồ sơ chi tiết của danh sách bạn bè kèm trạng thái online qua `/api/social/friend/getprofiles/v2` (command 11140)
|
|
7
|
+
*
|
|
8
|
+
* @param friendIds Mảng UID cần lấy hồ sơ (có thể kèm hậu tố `_version` hoặc truyền UID thuần)
|
|
9
|
+
* @param options Tùy chọn truy vấn
|
|
10
|
+
* @throws {ZaloApiError}
|
|
11
|
+
*/
|
|
12
|
+
return async function getFriendProfilesV2(friendIds, options = {}) {
|
|
13
|
+
const rawIds = Array.isArray(friendIds) ? friendIds : [friendIds];
|
|
14
|
+
if (rawIds.length === 0) {
|
|
15
|
+
throw new ZaloApiError("Missing friendIds");
|
|
16
|
+
}
|
|
17
|
+
const friendPversionMap = rawIds.map((id) => (id.includes("_") ? id : `${id}_0`));
|
|
18
|
+
const params = {
|
|
19
|
+
phonebook_version: options.phonebookVersion ?? 0,
|
|
20
|
+
friend_pversion_map: friendPversionMap,
|
|
21
|
+
avatar_size: options.avatarSize ?? 120,
|
|
22
|
+
language: options.language ?? ctx.language ?? "vi",
|
|
23
|
+
show_online_status: options.showOnlineStatus !== false ? 1 : 0,
|
|
24
|
+
imei: ctx.imei,
|
|
25
|
+
};
|
|
26
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
27
|
+
if (!encryptedParams) {
|
|
28
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
29
|
+
}
|
|
30
|
+
const response = await utils.request(serviceURL, {
|
|
31
|
+
method: "POST",
|
|
32
|
+
body: new URLSearchParams({
|
|
33
|
+
params: encryptedParams,
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
return utils.resolve(response);
|
|
37
|
+
};
|
|
38
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type GetFriendsActivePCWebResponse = {
|
|
2
|
+
uids?: string[];
|
|
3
|
+
activeUsers?: unknown[];
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
export declare const getFriendsActivePCWebFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => () => Promise<GetFriendsActivePCWebResponse>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { apiFactory } from "../../utils.js";
|
|
2
|
+
export const getFriendsActivePCWebFactory = apiFactory()((api, _ctx, utils) => {
|
|
3
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/active-pcweb`);
|
|
4
|
+
/**
|
|
5
|
+
* Lấy danh sách bạn bè đang hoạt động trên Zalo PC / Web qua `/api/social/friend/active-pcweb` (command 12072)
|
|
6
|
+
*
|
|
7
|
+
* @throws {ZaloApiError}
|
|
8
|
+
*/
|
|
9
|
+
return async function getFriendsActivePCWeb() {
|
|
10
|
+
const response = await utils.request(serviceURL, {
|
|
11
|
+
method: "GET",
|
|
12
|
+
});
|
|
13
|
+
return utils.resolve(response);
|
|
14
|
+
};
|
|
15
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type VerifyFriendOptions = {
|
|
2
|
+
phonebookVersion?: number;
|
|
3
|
+
avatarSize?: number;
|
|
4
|
+
language?: string;
|
|
5
|
+
};
|
|
6
|
+
export type VerifyFriendResponse = {
|
|
7
|
+
profiles?: Record<string, unknown>;
|
|
8
|
+
unchangeds_profile?: string[];
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
export declare const verifyFriendFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (friendIds: string | string[], options?: VerifyFriendOptions) => Promise<VerifyFriendResponse>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const verifyFriendFactory = apiFactory()((api, ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.profile[0]}/api/social/friend/verify`);
|
|
5
|
+
/**
|
|
6
|
+
* Kiểm tra và xác thực danh sách bạn bè qua `/api/social/friend/verify` (command 11138)
|
|
7
|
+
*
|
|
8
|
+
* @param friendIds Danh sách UID bạn bè cần xác thực
|
|
9
|
+
* @param options Tùy chọn truy vấn
|
|
10
|
+
* @throws {ZaloApiError}
|
|
11
|
+
*/
|
|
12
|
+
return async function verifyFriend(friendIds, options = {}) {
|
|
13
|
+
const rawIds = Array.isArray(friendIds) ? friendIds : [friendIds];
|
|
14
|
+
if (rawIds.length === 0) {
|
|
15
|
+
throw new ZaloApiError("Missing friendIds");
|
|
16
|
+
}
|
|
17
|
+
const friendPversionMap = rawIds.map((id) => (id.includes("_") ? id : `${id}_0`));
|
|
18
|
+
const params = {
|
|
19
|
+
phonebook_version: options.phonebookVersion ?? 0,
|
|
20
|
+
friend_pversion_map: friendPversionMap,
|
|
21
|
+
avatar_size: options.avatarSize ?? 120,
|
|
22
|
+
language: options.language ?? ctx.language ?? "vi",
|
|
23
|
+
imei: ctx.imei,
|
|
24
|
+
};
|
|
25
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
26
|
+
if (!encryptedParams) {
|
|
27
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
28
|
+
}
|
|
29
|
+
const response = await utils.request(serviceURL, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
body: new URLSearchParams({
|
|
32
|
+
params: encryptedParams,
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
return utils.resolve(response);
|
|
36
|
+
};
|
|
37
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const analyseGroupFactory = apiFactory()((api, _ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/analyse`);
|
|
5
|
+
/**
|
|
6
|
+
* Lấy dữ liệu phân tích/thống kê của nhóm qua `/api/group/analyse` (command 12407)
|
|
7
|
+
*
|
|
8
|
+
* @param groupId ID của nhóm
|
|
9
|
+
* @throws {ZaloApiError}
|
|
10
|
+
*/
|
|
11
|
+
return async function analyseGroup(groupId) {
|
|
12
|
+
if (!groupId) {
|
|
13
|
+
throw new ZaloApiError("Missing groupId");
|
|
14
|
+
}
|
|
15
|
+
const cleanGroupId = groupId.startsWith("g") ? groupId.slice(1) : groupId;
|
|
16
|
+
const params = {
|
|
17
|
+
grid: cleanGroupId,
|
|
18
|
+
};
|
|
19
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
20
|
+
if (!encryptedParams) {
|
|
21
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
22
|
+
}
|
|
23
|
+
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
|
24
|
+
method: "GET",
|
|
25
|
+
});
|
|
26
|
+
return utils.resolve(response);
|
|
27
|
+
};
|
|
28
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type CheckQuotaCommunityMemberResponse = {
|
|
2
|
+
status?: number;
|
|
3
|
+
canUpgrade?: boolean | number;
|
|
4
|
+
[key: string]: unknown;
|
|
5
|
+
};
|
|
6
|
+
export declare const checkQuotaCommunityMemberFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (groupId: string, uid: string) => Promise<CheckQuotaCommunityMemberResponse>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ZaloApiError } from "../../Errors/ZaloApiError.js";
|
|
2
|
+
import { apiFactory } from "../../utils.js";
|
|
3
|
+
export const checkQuotaCommunityMemberFactory = apiFactory()((api, ctx, utils) => {
|
|
4
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/quota/members-comm`);
|
|
5
|
+
/**
|
|
6
|
+
* Kiểm tra điều kiện/hạn mức thành viên Cộng đồng đối với một thành viên cụ thể trong nhóm (command 12182)
|
|
7
|
+
*
|
|
8
|
+
* @param groupId ID của nhóm
|
|
9
|
+
* @param uid UID của thành viên cần kiểm tra
|
|
10
|
+
* @throws {ZaloApiError}
|
|
11
|
+
*/
|
|
12
|
+
return async function checkQuotaCommunityMember(groupId, uid) {
|
|
13
|
+
if (!groupId) {
|
|
14
|
+
throw new ZaloApiError("Missing groupId");
|
|
15
|
+
}
|
|
16
|
+
if (!uid) {
|
|
17
|
+
throw new ZaloApiError("Missing uid");
|
|
18
|
+
}
|
|
19
|
+
const cleanGroupId = groupId.startsWith("g") ? groupId.slice(1) : groupId;
|
|
20
|
+
const params = {
|
|
21
|
+
language: ctx.language || "vi",
|
|
22
|
+
grId: cleanGroupId,
|
|
23
|
+
uid: String(uid),
|
|
24
|
+
};
|
|
25
|
+
const encryptedParams = utils.encodeAES(JSON.stringify(params));
|
|
26
|
+
if (!encryptedParams) {
|
|
27
|
+
throw new ZaloApiError("Failed to encrypt params");
|
|
28
|
+
}
|
|
29
|
+
const response = await utils.request(utils.makeURL(serviceURL, { params: encryptedParams }), {
|
|
30
|
+
method: "GET",
|
|
31
|
+
});
|
|
32
|
+
return utils.resolve(response);
|
|
33
|
+
};
|
|
34
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type GetE2eeGroupListResponse = {
|
|
2
|
+
version?: number;
|
|
3
|
+
gridVerMap?: Record<string, string>;
|
|
4
|
+
e2eeGroups?: string[];
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
};
|
|
7
|
+
export declare const getE2eeGroupListFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => () => Promise<GetE2eeGroupListResponse>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { apiFactory } from "../../utils.js";
|
|
2
|
+
export const getE2eeGroupListFactory = apiFactory()((api, _ctx, utils) => {
|
|
3
|
+
const serviceURL = utils.makeURL(`${api.zpwServiceMap.group[0]}/api/group/getlg/e2ee`);
|
|
4
|
+
/**
|
|
5
|
+
* Lấy danh sách các nhóm đang bật mã hóa đầu cuối E2EE (command 12146)
|
|
6
|
+
*
|
|
7
|
+
* @throws {ZaloApiError}
|
|
8
|
+
*/
|
|
9
|
+
return async function getE2eeGroupList() {
|
|
10
|
+
const response = await utils.request(serviceURL, {
|
|
11
|
+
method: "GET",
|
|
12
|
+
});
|
|
13
|
+
return utils.resolve(response);
|
|
14
|
+
};
|
|
15
|
+
});
|
|
@@ -1,18 +1,49 @@
|
|
|
1
1
|
import { GroupMessage } from "../../models/index.js";
|
|
2
|
+
export type GetGroupChatHistoryOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Số lượng tin nhắn cần tải (mặc định: `50`).
|
|
5
|
+
*/
|
|
6
|
+
count?: number;
|
|
7
|
+
/**
|
|
8
|
+
* Con trỏ `globalMsgId` (`lastMsgId` của trang trước) để phân trang lùi sâu về quá khứ (mặc định: `0`).
|
|
9
|
+
*/
|
|
10
|
+
cursor?: number | string;
|
|
11
|
+
/**
|
|
12
|
+
* Số trang tối đa được phép gọi trong một lần thực thi.
|
|
13
|
+
*/
|
|
14
|
+
maxPages?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Sử dụng endpoint `/api/cm/getoldv2` (command 12507) thay vì `/api/cm/getrecentv2` (command 12506).
|
|
17
|
+
*/
|
|
18
|
+
useOldEndpoint?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Danh sách `msgIds` cục bộ bổ sung (mặc định: `[]`).
|
|
21
|
+
*/
|
|
22
|
+
msgIds?: Array<string | number>;
|
|
23
|
+
/**
|
|
24
|
+
* Nguồn truy vấn (mặc định: `3`).
|
|
25
|
+
*/
|
|
26
|
+
src?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Cờ hội thoại OA (tùy chọn).
|
|
29
|
+
*/
|
|
30
|
+
isOA?: boolean;
|
|
31
|
+
};
|
|
2
32
|
export type GetGroupChatHistoryResponse = {
|
|
3
33
|
error?: number;
|
|
4
|
-
lastMsgId?: number;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
34
|
+
lastMsgId?: number | string;
|
|
35
|
+
nextCursor?: number | string;
|
|
36
|
+
minMsgId?: number | string;
|
|
37
|
+
maxMsgId?: number | string;
|
|
38
|
+
msgJumpId?: number | string;
|
|
8
39
|
hasMore?: boolean;
|
|
9
40
|
isOld?: boolean;
|
|
10
41
|
isFiltered?: boolean;
|
|
11
|
-
rootMsgId?: number;
|
|
42
|
+
rootMsgId?: number | string;
|
|
12
43
|
isRootDel?: boolean;
|
|
13
44
|
groupMsgs: GroupMessage[];
|
|
14
45
|
tsJoinGroup?: number;
|
|
15
46
|
isFilteredByPhase?: boolean;
|
|
16
47
|
isFilteredByTimeJoin?: boolean;
|
|
17
48
|
};
|
|
18
|
-
export declare const getGroupChatHistoryFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (groupId: string,
|
|
49
|
+
export declare const getGroupChatHistoryFactory: (ctx: import("../../context.js").ContextBase, api: import("../../apis.js").API) => (groupId: string, countOrOptions?: number | GetGroupChatHistoryOptions) => Promise<GetGroupChatHistoryResponse>;
|