@warriorteam/redai-zalo-sdk 1.12.3 → 1.13.0
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/CHANGELOG.md +135 -0
- package/README.md +35 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/services/article.service.d.ts +103 -1
- package/dist/services/article.service.d.ts.map +1 -1
- package/dist/services/article.service.js +167 -0
- package/dist/services/article.service.js.map +1 -1
- package/dist/services/group-management.service.d.ts +75 -2
- package/dist/services/group-management.service.d.ts.map +1 -1
- package/dist/services/group-management.service.js +315 -1
- package/dist/services/group-management.service.js.map +1 -1
- package/dist/types/group.d.ts +104 -0
- package/dist/types/group.d.ts.map +1 -1
- package/dist/types/webhook.d.ts +24 -0
- package/dist/types/webhook.d.ts.map +1 -1
- package/dist/types/webhook.js +110 -0
- package/dist/types/webhook.js.map +1 -1
- package/docs/AUTHENTICATION.md +4 -3
- package/docs/WEBHOOK_MESSAGE_HELPERS.md +230 -0
- package/docs/enhanced-article-api.md +222 -0
- package/examples/get-all-articles-example.ts +171 -0
- package/examples/oa-auth-with-pkce.ts +3 -3
- package/examples/webhook-message-classification.ts +285 -0
- package/package.json +7 -3
- package/ARCHITECTURE.md +0 -265
- package/SERVICES_ADDED.md +0 -540
- package/UPDATE_ARTICLE_STATUS.md +0 -152
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/types/webhook.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAosEH,wCAmDC;AAKD,sCAMC;AAKD,8CAaC;AAKD,kCAEC;AAKD,4CAgBC;AAKD,4CASC;AAKD,kCAKC;AAKD,0CAIC;AAKD,kDAIC;AAKD,0CAIC;AAKD,gCAWC;AAKD,oCA+BC;AAKD,wCAOC;AAKD,oDAeC;AAKD,sCAOC;AAKD,sCASC;AAKD,8CAIC;AAKD,4CAIC;AAKD,sDAIC;AAKD,0CAOC;AAKD,wCAOC;AAKD,wCAOC;
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/types/webhook.ts"],"names":[],"mappings":"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"}
|
package/docs/AUTHENTICATION.md
CHANGED
|
@@ -60,8 +60,8 @@ console.log("PKCE Config:", {
|
|
|
60
60
|
const authResult = zalo.auth.createOAAuthUrl(
|
|
61
61
|
"https://your-app.com/auth/callback",
|
|
62
62
|
"my-secure-state", // optional custom state
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
pkce, // manual PKCE config
|
|
64
|
+
true // usePkce = true
|
|
65
65
|
);
|
|
66
66
|
|
|
67
67
|
console.log("Secure auth URL:", authResult.url);
|
|
@@ -80,7 +80,8 @@ sessionStorage.setItem('auth_state', authResult.state);
|
|
|
80
80
|
const authResult = zalo.auth.createOAAuthUrl(
|
|
81
81
|
"https://your-app.com/auth/callback",
|
|
82
82
|
undefined, // state sẽ được auto-generate
|
|
83
|
-
|
|
83
|
+
undefined, // pkce sẽ được auto-generate
|
|
84
|
+
true // usePkce = true
|
|
84
85
|
);
|
|
85
86
|
|
|
86
87
|
console.log("Secure auth URL:", authResult.url);
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Webhook Message Helper Functions
|
|
2
|
+
|
|
3
|
+
Tài liệu này mô tả các hàm helper để phân biệt các loại sự kiện tin nhắn trong Zalo webhook.
|
|
4
|
+
|
|
5
|
+
## Tổng quan
|
|
6
|
+
|
|
7
|
+
RedAI Zalo SDK cung cấp các hàm helper để dễ dàng phân biệt các loại sự kiện tin nhắn:
|
|
8
|
+
|
|
9
|
+
1. **Tin nhắn từ người dùng cá nhân** - `isUserMessageEvent()`
|
|
10
|
+
2. **Tin nhắn từ group** - `isGroupMessageEvent()`
|
|
11
|
+
3. **Tin nhắn OA gửi cho cá nhân** - `isOAToUserMessageEvent()`
|
|
12
|
+
4. **Tin nhắn OA gửi tới group** - `isOAToGroupMessageEvent()`
|
|
13
|
+
5. **Xác định hướng và đích của tin nhắn** - `getMessageDirection()`
|
|
14
|
+
|
|
15
|
+
## Import
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import {
|
|
19
|
+
isUserMessageEvent,
|
|
20
|
+
isGroupMessageEvent,
|
|
21
|
+
isOAToUserMessageEvent,
|
|
22
|
+
isOAToGroupMessageEvent,
|
|
23
|
+
getMessageDirection,
|
|
24
|
+
WebhookEvent,
|
|
25
|
+
} from '@warriorteam/redai-zalo-sdk';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Sử dụng
|
|
29
|
+
|
|
30
|
+
### 1. Phân biệt tin nhắn từ người dùng cá nhân
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
function handleWebhook(event: WebhookEvent) {
|
|
34
|
+
if (isUserMessageEvent(event)) {
|
|
35
|
+
console.log('Nhận được tin nhắn từ người dùng cá nhân');
|
|
36
|
+
console.log('Sender:', event.sender.id);
|
|
37
|
+
console.log('Content:', event.message.text);
|
|
38
|
+
|
|
39
|
+
// Xử lý tin nhắn từ user cá nhân
|
|
40
|
+
handleUserMessage(event);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Phân biệt tin nhắn từ group
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
function handleWebhook(event: WebhookEvent) {
|
|
49
|
+
if (isGroupMessageEvent(event)) {
|
|
50
|
+
console.log('Nhận được tin nhắn từ group');
|
|
51
|
+
console.log('Group ID:', event.recipient.id);
|
|
52
|
+
console.log('Sender:', event.sender.id);
|
|
53
|
+
console.log('Content:', event.message.text);
|
|
54
|
+
|
|
55
|
+
// Xử lý tin nhắn từ group
|
|
56
|
+
handleGroupMessage(event);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 3. Phân biệt tin nhắn OA gửi cho cá nhân
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
function handleWebhook(event: WebhookEvent) {
|
|
65
|
+
if (isOAToUserMessageEvent(event)) {
|
|
66
|
+
console.log('OA đã gửi tin nhắn cho người dùng cá nhân');
|
|
67
|
+
console.log('Recipient:', event.recipient.id);
|
|
68
|
+
console.log('Content:', event.message.text);
|
|
69
|
+
|
|
70
|
+
// Xử lý tin nhắn OA gửi cho user
|
|
71
|
+
handleOAToUserMessage(event);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 4. Phân biệt tin nhắn OA gửi tới group
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
function handleWebhook(event: WebhookEvent) {
|
|
80
|
+
if (isOAToGroupMessageEvent(event)) {
|
|
81
|
+
console.log('OA đã gửi tin nhắn tới group');
|
|
82
|
+
console.log('Group ID:', event.recipient.id);
|
|
83
|
+
console.log('Content:', event.message.text);
|
|
84
|
+
|
|
85
|
+
// Xử lý tin nhắn OA gửi tới group
|
|
86
|
+
handleOAToGroupMessage(event);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 5. Xác định hướng và đích của tin nhắn
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
function handleWebhook(event: WebhookEvent) {
|
|
95
|
+
const messageInfo = getMessageDirection(event);
|
|
96
|
+
|
|
97
|
+
console.log('Direction:', messageInfo.direction); // 'incoming' | 'outgoing' | 'unknown'
|
|
98
|
+
console.log('Target:', messageInfo.target); // 'user' | 'group' | 'unknown'
|
|
99
|
+
console.log('Description:', messageInfo.description);
|
|
100
|
+
|
|
101
|
+
// Xử lý dựa trên hướng và đích
|
|
102
|
+
switch (`${messageInfo.direction}-${messageInfo.target}`) {
|
|
103
|
+
case 'incoming-user':
|
|
104
|
+
handleIncomingUserMessage(event);
|
|
105
|
+
break;
|
|
106
|
+
case 'incoming-group':
|
|
107
|
+
handleIncomingGroupMessage(event);
|
|
108
|
+
break;
|
|
109
|
+
case 'outgoing-user':
|
|
110
|
+
handleOutgoingUserMessage(event);
|
|
111
|
+
break;
|
|
112
|
+
case 'outgoing-group':
|
|
113
|
+
handleOutgoingGroupMessage(event);
|
|
114
|
+
break;
|
|
115
|
+
default:
|
|
116
|
+
console.log('Unknown message type');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Ví dụ tổng hợp
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import {
|
|
125
|
+
isUserMessageEvent,
|
|
126
|
+
isGroupMessageEvent,
|
|
127
|
+
isOAToUserMessageEvent,
|
|
128
|
+
isOAToGroupMessageEvent,
|
|
129
|
+
getMessageDirection,
|
|
130
|
+
WebhookEvent,
|
|
131
|
+
} from '@warriorteam/redai-zalo-sdk';
|
|
132
|
+
|
|
133
|
+
class ZaloWebhookHandler {
|
|
134
|
+
handleWebhook(event: WebhookEvent) {
|
|
135
|
+
// Cách 1: Sử dụng các hàm kiểm tra riêng lẻ
|
|
136
|
+
if (isUserMessageEvent(event)) {
|
|
137
|
+
this.handleUserMessage(event);
|
|
138
|
+
} else if (isGroupMessageEvent(event)) {
|
|
139
|
+
this.handleGroupMessage(event);
|
|
140
|
+
} else if (isOAToUserMessageEvent(event)) {
|
|
141
|
+
this.handleOAToUserMessage(event);
|
|
142
|
+
} else if (isOAToGroupMessageEvent(event)) {
|
|
143
|
+
this.handleOAToGroupMessage(event);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Cách 2: Sử dụng getMessageDirection
|
|
147
|
+
const messageInfo = getMessageDirection(event);
|
|
148
|
+
this.logMessageInfo(messageInfo);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private handleUserMessage(event: UserMessageWebhookEvent) {
|
|
152
|
+
console.log('Processing user message:', event.message.text);
|
|
153
|
+
// Logic xử lý tin nhắn từ user cá nhân
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private handleGroupMessage(event: GroupWebhookEvent) {
|
|
157
|
+
console.log('Processing group message:', event.message.text);
|
|
158
|
+
// Logic xử lý tin nhắn từ group
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private handleOAToUserMessage(event: OAMessageWebhookEvent) {
|
|
162
|
+
console.log('Processing OA to user message:', event.message.text);
|
|
163
|
+
// Logic xử lý tin nhắn OA gửi cho user
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private handleOAToGroupMessage(event: GroupWebhookEvent) {
|
|
167
|
+
console.log('Processing OA to group message:', event.message.text);
|
|
168
|
+
// Logic xử lý tin nhắn OA gửi tới group
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private logMessageInfo(messageInfo: ReturnType<typeof getMessageDirection>) {
|
|
172
|
+
console.log(`Message: ${messageInfo.direction} -> ${messageInfo.target}`);
|
|
173
|
+
console.log(`Description: ${messageInfo.description}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Các loại sự kiện được hỗ trợ
|
|
179
|
+
|
|
180
|
+
### User Message Events (Tin nhắn từ người dùng cá nhân)
|
|
181
|
+
- `user_send_text`
|
|
182
|
+
- `user_send_image`
|
|
183
|
+
- `user_send_location`
|
|
184
|
+
- `user_send_link`
|
|
185
|
+
- `user_send_sticker`
|
|
186
|
+
- `user_send_gif`
|
|
187
|
+
- `user_send_audio`
|
|
188
|
+
- `user_send_video`
|
|
189
|
+
- `user_send_file`
|
|
190
|
+
- `user_received_message`
|
|
191
|
+
- `user_seen_message`
|
|
192
|
+
- `user_send_business_card`
|
|
193
|
+
|
|
194
|
+
### Group Message Events (Tin nhắn từ group)
|
|
195
|
+
- `user_send_group_text`
|
|
196
|
+
- `user_send_group_link`
|
|
197
|
+
- `user_send_group_audio`
|
|
198
|
+
- `user_send_group_location`
|
|
199
|
+
- `user_send_group_video`
|
|
200
|
+
- `user_send_group_business_card`
|
|
201
|
+
- `user_send_group_sticker`
|
|
202
|
+
- `user_send_group_gif`
|
|
203
|
+
- `user_send_group_file`
|
|
204
|
+
|
|
205
|
+
### OA to User Events (OA gửi cho cá nhân)
|
|
206
|
+
- `oa_send_text`
|
|
207
|
+
- `oa_send_image`
|
|
208
|
+
- `oa_send_gif`
|
|
209
|
+
- `oa_send_list`
|
|
210
|
+
- `oa_send_file`
|
|
211
|
+
- `oa_send_sticker`
|
|
212
|
+
- `oa_send_template`
|
|
213
|
+
|
|
214
|
+
### OA to Group Events (OA gửi tới group)
|
|
215
|
+
- `oa_send_group_text`
|
|
216
|
+
- `oa_send_group_image`
|
|
217
|
+
- `oa_send_group_link`
|
|
218
|
+
- `oa_send_group_audio`
|
|
219
|
+
- `oa_send_group_location`
|
|
220
|
+
- `oa_send_group_video`
|
|
221
|
+
- `oa_send_group_business_card`
|
|
222
|
+
- `oa_send_group_sticker`
|
|
223
|
+
- `oa_send_group_gif`
|
|
224
|
+
- `oa_send_group_file`
|
|
225
|
+
|
|
226
|
+
## Lưu ý
|
|
227
|
+
|
|
228
|
+
1. Các hàm helper này chỉ hoạt động với các sự kiện tin nhắn, không áp dụng cho các sự kiện khác như follow/unfollow.
|
|
229
|
+
2. Sử dụng TypeScript để có type safety tốt nhất.
|
|
230
|
+
3. Các hàm này đã được test kỹ lưỡng và an toàn để sử dụng trong production.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Enhanced Article API - Get All Articles
|
|
2
|
+
|
|
3
|
+
## Tổng Quan
|
|
4
|
+
|
|
5
|
+
Đã nâng cấp `ArticleService` với 2 method mới để lấy **tất cả bài viết** một cách tự động, không cần xử lý pagination thủ công:
|
|
6
|
+
|
|
7
|
+
- ✅ `getAllArticles()` - Lấy tất cả bài viết theo loại (normal hoặc video)
|
|
8
|
+
- ✅ `getAllArticlesCombined()` - Lấy tất cả bài viết cả 2 loại kết hợp
|
|
9
|
+
|
|
10
|
+
## Tính Năng Nâng Cao
|
|
11
|
+
|
|
12
|
+
### 🚀 Tự Động Pagination
|
|
13
|
+
- Tự động gọi API nhiều lần để lấy hết dữ liệu
|
|
14
|
+
- Không cần xử lý `offset` và `limit` thủ công
|
|
15
|
+
- Tự động dừng khi hết dữ liệu
|
|
16
|
+
|
|
17
|
+
### 📊 Progress Tracking
|
|
18
|
+
- Callback `onProgress` để theo dõi tiến trình
|
|
19
|
+
- Hiển thị số batch hiện tại và tổng số đã lấy
|
|
20
|
+
- Biết được còn dữ liệu hay không
|
|
21
|
+
|
|
22
|
+
### ⚙️ Cấu Hình Linh Hoạt
|
|
23
|
+
- `batchSize`: Số bài viết mỗi lần gọi API (max 100)
|
|
24
|
+
- `maxArticles`: Giới hạn tổng số bài viết (0 = không giới hạn)
|
|
25
|
+
- `onProgress`: Callback theo dõi tiến trình
|
|
26
|
+
|
|
27
|
+
### 🛡️ An Toàn & Validation
|
|
28
|
+
- Validation đầu vào nghiêm ngặt
|
|
29
|
+
- Safety check tránh infinite loop
|
|
30
|
+
- Error handling toàn diện
|
|
31
|
+
- TypeScript support đầy đủ
|
|
32
|
+
|
|
33
|
+
## API Reference
|
|
34
|
+
|
|
35
|
+
### `getAllArticles()`
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
async getAllArticles(
|
|
39
|
+
accessToken: string,
|
|
40
|
+
type: "normal" | "video" = "normal",
|
|
41
|
+
options: {
|
|
42
|
+
batchSize?: number; // Default: 50, Max: 100
|
|
43
|
+
maxArticles?: number; // Default: 1000, 0 = no limit
|
|
44
|
+
onProgress?: (progress: {
|
|
45
|
+
currentBatch: number;
|
|
46
|
+
totalFetched: number;
|
|
47
|
+
hasMore: boolean;
|
|
48
|
+
}) => void;
|
|
49
|
+
} = {}
|
|
50
|
+
): Promise<{
|
|
51
|
+
articles: ArticleListItem[];
|
|
52
|
+
totalFetched: number;
|
|
53
|
+
totalBatches: number;
|
|
54
|
+
hasMore: boolean;
|
|
55
|
+
}>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `getAllArticlesCombined()`
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
async getAllArticlesCombined(
|
|
62
|
+
accessToken: string,
|
|
63
|
+
options: {
|
|
64
|
+
batchSize?: number; // Default: 50, Max: 100
|
|
65
|
+
maxArticlesPerType?: number; // Default: 500, 0 = no limit
|
|
66
|
+
onProgress?: (progress: {
|
|
67
|
+
type: "normal" | "video";
|
|
68
|
+
currentBatch: number;
|
|
69
|
+
totalFetched: number;
|
|
70
|
+
hasMore: boolean;
|
|
71
|
+
}) => void;
|
|
72
|
+
} = {}
|
|
73
|
+
): Promise<{
|
|
74
|
+
articles: ArticleListItem[];
|
|
75
|
+
breakdown: {
|
|
76
|
+
normal: { articles: ArticleListItem[]; totalFetched: number; totalBatches: number; hasMore: boolean; };
|
|
77
|
+
video: { articles: ArticleListItem[]; totalFetched: number; totalBatches: number; hasMore: boolean; };
|
|
78
|
+
};
|
|
79
|
+
totalFetched: number;
|
|
80
|
+
totalBatches: number;
|
|
81
|
+
}>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Ví Dụ Sử Dụng
|
|
85
|
+
|
|
86
|
+
### 1. Lấy Tất Cả Bài Viết Normal
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { ArticleService } from "redai-zalo-sdk";
|
|
90
|
+
|
|
91
|
+
const result = await articleService.getAllArticles(accessToken, "normal", {
|
|
92
|
+
batchSize: 50,
|
|
93
|
+
maxArticles: 1000,
|
|
94
|
+
onProgress: (progress) => {
|
|
95
|
+
console.log(`Batch ${progress.currentBatch}: ${progress.totalFetched} articles`);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log(`Total: ${result.totalFetched} articles`);
|
|
100
|
+
result.articles.forEach(article => {
|
|
101
|
+
console.log(`- ${article.title} (${article.id})`);
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. Lấy Tất Cả Bài Viết Video
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const videoResult = await articleService.getAllArticles(accessToken, "video", {
|
|
109
|
+
batchSize: 30,
|
|
110
|
+
maxArticles: 500
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
console.log(`Found ${videoResult.totalFetched} video articles`);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 3. Lấy Tất Cả Bài Viết (Normal + Video)
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
const combinedResult = await articleService.getAllArticlesCombined(accessToken, {
|
|
120
|
+
batchSize: 50,
|
|
121
|
+
maxArticlesPerType: 500,
|
|
122
|
+
onProgress: (progress) => {
|
|
123
|
+
console.log(`${progress.type}: ${progress.totalFetched} articles`);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
console.log(`Total: ${combinedResult.totalFetched} articles`);
|
|
128
|
+
console.log(`Normal: ${combinedResult.breakdown.normal.totalFetched}`);
|
|
129
|
+
console.log(`Video: ${combinedResult.breakdown.video.totalFetched}`);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### 4. Lấy Tất Cả Không Giới Hạn
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// ⚠️ Cẩn thận: Có thể lấy rất nhiều dữ liệu!
|
|
136
|
+
const unlimitedResult = await articleService.getAllArticles(accessToken, "normal", {
|
|
137
|
+
batchSize: 100,
|
|
138
|
+
maxArticles: 0, // 0 = không giới hạn
|
|
139
|
+
onProgress: (progress) => {
|
|
140
|
+
console.log(`Fetching... ${progress.totalFetched} articles so far`);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## So Sánh Với API Cũ
|
|
146
|
+
|
|
147
|
+
### Trước (API cũ)
|
|
148
|
+
```typescript
|
|
149
|
+
// Phải xử lý pagination thủ công
|
|
150
|
+
let offset = 0;
|
|
151
|
+
const limit = 50;
|
|
152
|
+
const allArticles = [];
|
|
153
|
+
|
|
154
|
+
while (true) {
|
|
155
|
+
const response = await articleService.getArticleList(accessToken, {
|
|
156
|
+
offset,
|
|
157
|
+
limit,
|
|
158
|
+
type: "normal"
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if (!response.data?.medias || response.data.medias.length === 0) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
allArticles.push(...response.data.medias);
|
|
166
|
+
offset += response.data.medias.length;
|
|
167
|
+
|
|
168
|
+
if (response.data.medias.length < limit) {
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Sau (API mới)
|
|
175
|
+
```typescript
|
|
176
|
+
// Chỉ 1 dòng code!
|
|
177
|
+
const result = await articleService.getAllArticles(accessToken, "normal");
|
|
178
|
+
const allArticles = result.articles;
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Lưu Ý Quan Trọng
|
|
182
|
+
|
|
183
|
+
### ⚠️ Giới Hạn Rate Limit
|
|
184
|
+
- Zalo API có giới hạn số request/phút
|
|
185
|
+
- Sử dụng `batchSize` hợp lý (khuyến nghị: 50)
|
|
186
|
+
- Đặt `maxArticles` để tránh quá tải
|
|
187
|
+
|
|
188
|
+
### 🔒 Bảo Mật
|
|
189
|
+
- Luôn validate `accessToken`
|
|
190
|
+
- Không hardcode token trong code
|
|
191
|
+
- Sử dụng environment variables
|
|
192
|
+
|
|
193
|
+
### 📈 Performance
|
|
194
|
+
- `batchSize` lớn = ít request nhưng response lớn
|
|
195
|
+
- `batchSize` nhỏ = nhiều request nhưng response nhỏ
|
|
196
|
+
- Khuyến nghị: 50-100 articles/batch
|
|
197
|
+
|
|
198
|
+
### 🛡️ Error Handling
|
|
199
|
+
```typescript
|
|
200
|
+
try {
|
|
201
|
+
const result = await articleService.getAllArticles(accessToken, "normal");
|
|
202
|
+
// Xử lý thành công
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof ZaloSDKError) {
|
|
205
|
+
console.error("Zalo API Error:", error.message);
|
|
206
|
+
} else {
|
|
207
|
+
console.error("Unknown Error:", error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Kết Luận
|
|
213
|
+
|
|
214
|
+
API mới giúp:
|
|
215
|
+
- ✅ Đơn giản hóa việc lấy tất cả bài viết
|
|
216
|
+
- ✅ Tự động xử lý pagination
|
|
217
|
+
- ✅ Theo dõi tiến trình real-time
|
|
218
|
+
- ✅ Type-safe với TypeScript
|
|
219
|
+
- ✅ Error handling tốt hơn
|
|
220
|
+
- ✅ Cấu hình linh hoạt
|
|
221
|
+
|
|
222
|
+
Sử dụng `getAllArticles()` cho 1 loại bài viết hoặc `getAllArticlesCombined()` cho cả 2 loại!
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: How to use the enhanced getAllArticles and getAllArticlesCombined methods
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the new custom API methods that can fetch all articles
|
|
5
|
+
* automatically by handling pagination internally.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ArticleService } from "../src/services/article.service";
|
|
9
|
+
import { ZaloClient } from "../src/clients/zalo-client";
|
|
10
|
+
|
|
11
|
+
// Initialize the services
|
|
12
|
+
const zaloClient = new ZaloClient();
|
|
13
|
+
const articleService = new ArticleService(zaloClient);
|
|
14
|
+
|
|
15
|
+
// Your access token
|
|
16
|
+
const ACCESS_TOKEN = "your-access-token-here";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Example 1: Get all normal articles with progress tracking
|
|
20
|
+
*/
|
|
21
|
+
async function getAllNormalArticlesExample() {
|
|
22
|
+
console.log("=== Getting All Normal Articles ===");
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = await articleService.getAllArticles(ACCESS_TOKEN, "normal", {
|
|
26
|
+
batchSize: 50, // Fetch 50 articles per API call
|
|
27
|
+
maxArticles: 1000, // Stop after 1000 articles (0 = no limit)
|
|
28
|
+
onProgress: (progress) => {
|
|
29
|
+
console.log(`📄 Batch ${progress.currentBatch}: ${progress.totalFetched} articles fetched, hasMore: ${progress.hasMore}`);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log(`✅ Completed! Total: ${result.totalFetched} normal articles in ${result.totalBatches} batches`);
|
|
34
|
+
console.log(`📊 Has more articles available: ${result.hasMore}`);
|
|
35
|
+
|
|
36
|
+
// Access the articles
|
|
37
|
+
result.articles.forEach((article, index) => {
|
|
38
|
+
console.log(`${index + 1}. ${article.title} (ID: ${article.id})`);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return result;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error("❌ Error getting normal articles:", error);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Example 2: Get all video articles
|
|
50
|
+
*/
|
|
51
|
+
async function getAllVideoArticlesExample() {
|
|
52
|
+
console.log("\n=== Getting All Video Articles ===");
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const result = await articleService.getAllArticles(ACCESS_TOKEN, "video", {
|
|
56
|
+
batchSize: 30, // Smaller batch size for videos
|
|
57
|
+
maxArticles: 500, // Limit to 500 videos
|
|
58
|
+
onProgress: (progress) => {
|
|
59
|
+
console.log(`🎥 Video Batch ${progress.currentBatch}: ${progress.totalFetched} videos fetched`);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
console.log(`✅ Completed! Total: ${result.totalFetched} video articles in ${result.totalBatches} batches`);
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("❌ Error getting video articles:", error);
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Example 3: Get all articles (both normal and video) combined
|
|
74
|
+
*/
|
|
75
|
+
async function getAllArticlesCombinedExample() {
|
|
76
|
+
console.log("\n=== Getting All Articles Combined ===");
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const result = await articleService.getAllArticlesCombined(ACCESS_TOKEN, {
|
|
80
|
+
batchSize: 50,
|
|
81
|
+
maxArticlesPerType: 500, // Max 500 per type (normal + video)
|
|
82
|
+
onProgress: (progress) => {
|
|
83
|
+
console.log(`📱 ${progress.type.toUpperCase()}: Batch ${progress.currentBatch}, Total: ${progress.totalFetched}`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
console.log(`✅ All articles fetched!`);
|
|
88
|
+
console.log(`📊 Total articles: ${result.totalFetched}`);
|
|
89
|
+
console.log(`📄 Normal articles: ${result.breakdown.normal.totalFetched}`);
|
|
90
|
+
console.log(`🎥 Video articles: ${result.breakdown.video.totalFetched}`);
|
|
91
|
+
console.log(`🔄 Total API calls: ${result.totalBatches}`);
|
|
92
|
+
|
|
93
|
+
// You can access all articles combined
|
|
94
|
+
console.log(`\n📋 All Articles (${result.articles.length}):`);
|
|
95
|
+
result.articles.slice(0, 5).forEach((article, index) => {
|
|
96
|
+
console.log(`${index + 1}. [${article.type?.toUpperCase()}] ${article.title}`);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (result.articles.length > 5) {
|
|
100
|
+
console.log(`... and ${result.articles.length - 5} more articles`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return result;
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error("❌ Error getting combined articles:", error);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Example 4: Get unlimited articles (fetch everything)
|
|
112
|
+
*/
|
|
113
|
+
async function getAllArticlesUnlimitedExample() {
|
|
114
|
+
console.log("\n=== Getting ALL Articles (No Limit) ===");
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const result = await articleService.getAllArticles(ACCESS_TOKEN, "normal", {
|
|
118
|
+
batchSize: 100, // Max batch size
|
|
119
|
+
maxArticles: 0, // 0 = no limit, fetch everything
|
|
120
|
+
onProgress: (progress) => {
|
|
121
|
+
console.log(`🔄 Batch ${progress.currentBatch}: ${progress.totalFetched} articles...`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
console.log(`✅ Fetched EVERYTHING! Total: ${result.totalFetched} articles`);
|
|
126
|
+
console.log(`⚠️ Warning: This fetched all articles without limit!`);
|
|
127
|
+
|
|
128
|
+
return result;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error("❌ Error getting unlimited articles:", error);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Main function to run all examples
|
|
137
|
+
*/
|
|
138
|
+
async function runExamples() {
|
|
139
|
+
try {
|
|
140
|
+
// Example 1: Normal articles
|
|
141
|
+
await getAllNormalArticlesExample();
|
|
142
|
+
|
|
143
|
+
// Example 2: Video articles
|
|
144
|
+
await getAllVideoArticlesExample();
|
|
145
|
+
|
|
146
|
+
// Example 3: Combined articles
|
|
147
|
+
await getAllArticlesCombinedExample();
|
|
148
|
+
|
|
149
|
+
// Example 4: Unlimited (commented out for safety)
|
|
150
|
+
// await getAllArticlesUnlimitedExample();
|
|
151
|
+
|
|
152
|
+
console.log("\n🎉 All examples completed successfully!");
|
|
153
|
+
|
|
154
|
+
} catch (error) {
|
|
155
|
+
console.error("💥 Example failed:", error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Export for use in other files
|
|
160
|
+
export {
|
|
161
|
+
getAllNormalArticlesExample,
|
|
162
|
+
getAllVideoArticlesExample,
|
|
163
|
+
getAllArticlesCombinedExample,
|
|
164
|
+
getAllArticlesUnlimitedExample,
|
|
165
|
+
runExamples
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Run examples if this file is executed directly
|
|
169
|
+
if (require.main === module) {
|
|
170
|
+
runExamples();
|
|
171
|
+
}
|