@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
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,141 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.13.0] - 2025-01-17
|
|
9
|
+
|
|
10
|
+
### 🚀 NEW FEATURES
|
|
11
|
+
|
|
12
|
+
#### Enhanced Article API - Get All Articles
|
|
13
|
+
- **ADDED**: `getAllArticles()` - Lấy tất cả bài viết theo loại với tự động pagination
|
|
14
|
+
- **ADDED**: `getAllArticlesCombined()` - Lấy tất cả bài viết cả 2 loại (normal + video) kết hợp
|
|
15
|
+
- **ENHANCED**: Automatic pagination handling - không cần xử lý offset/limit thủ công
|
|
16
|
+
- **ADDED**: Progress tracking với callback `onProgress` để theo dõi tiến trình real-time
|
|
17
|
+
- **ADDED**: Flexible configuration với `batchSize`, `maxArticles`, và safety limits
|
|
18
|
+
|
|
19
|
+
#### Advanced Features
|
|
20
|
+
- **SAFETY**: Built-in safety checks để tránh infinite loops (max 100 batches)
|
|
21
|
+
- **PERFORMANCE**: Configurable batch sizes (1-100 articles per request)
|
|
22
|
+
- **CONTROL**: Giới hạn tổng số articles (`maxArticles`, 0 = unlimited)
|
|
23
|
+
- **MONITORING**: Real-time progress callbacks với detailed metrics
|
|
24
|
+
- **TYPE-SAFE**: Full TypeScript support với `ArticleListItem[]` return types
|
|
25
|
+
|
|
26
|
+
#### Smart Response Handling
|
|
27
|
+
- **ROBUST**: Handles both `ZaloResponse<T>` và direct response formats
|
|
28
|
+
- **FLEXIBLE**: Supports cả `response.data.medias` và `response.medias` structures
|
|
29
|
+
- **ERROR-SAFE**: Comprehensive error handling với `ZaloSDKError` integration
|
|
30
|
+
|
|
31
|
+
### 📚 DOCUMENTATION
|
|
32
|
+
|
|
33
|
+
#### New Documentation Files
|
|
34
|
+
- **ADDED**: `docs/enhanced-article-api.md` - Comprehensive guide cho enhanced article APIs
|
|
35
|
+
- **ADDED**: `examples/get-all-articles-example.ts` - Practical usage examples với 4 scenarios
|
|
36
|
+
- **DETAILED**: API reference với parameters, return types, và best practices
|
|
37
|
+
- **EXAMPLES**: Real-world usage patterns và performance recommendations
|
|
38
|
+
|
|
39
|
+
#### Developer Experience
|
|
40
|
+
- **ENHANCED**: Detailed JSDoc comments với @example blocks
|
|
41
|
+
- **IMPROVED**: IntelliSense support với comprehensive type definitions
|
|
42
|
+
- **ADDED**: Progress tracking examples và error handling patterns
|
|
43
|
+
- **GUIDES**: Performance tuning và rate limiting recommendations
|
|
44
|
+
|
|
45
|
+
### 🔧 TECHNICAL IMPROVEMENTS
|
|
46
|
+
|
|
47
|
+
#### Code Quality
|
|
48
|
+
- **TYPE-SAFE**: Full TypeScript compliance với proper interface definitions
|
|
49
|
+
- **VALIDATED**: Input validation với `ARTICLE_CONSTRAINTS` integration
|
|
50
|
+
- **OPTIMIZED**: Efficient pagination logic với smart batch management
|
|
51
|
+
- **TESTED**: Comprehensive error scenarios và edge case handling
|
|
52
|
+
|
|
53
|
+
#### API Design
|
|
54
|
+
- **CONSISTENT**: Follows existing SDK patterns và naming conventions
|
|
55
|
+
- **EXTENSIBLE**: Modular design cho future enhancements
|
|
56
|
+
- **BACKWARD-COMPATIBLE**: Không breaking changes cho existing `getArticleList()`
|
|
57
|
+
- **PERFORMANCE**: Optimized cho large datasets với configurable limits
|
|
58
|
+
|
|
59
|
+
### 💡 USAGE EXAMPLES
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// Simple: Get all normal articles
|
|
63
|
+
const result = await articleService.getAllArticles(accessToken, "normal");
|
|
64
|
+
|
|
65
|
+
// Advanced: With progress tracking và limits
|
|
66
|
+
const result = await articleService.getAllArticles(accessToken, "normal", {
|
|
67
|
+
batchSize: 50,
|
|
68
|
+
maxArticles: 1000,
|
|
69
|
+
onProgress: (progress) => console.log(`${progress.totalFetched} articles`)
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Combined: Get both normal và video articles
|
|
73
|
+
const combined = await articleService.getAllArticlesCombined(accessToken, {
|
|
74
|
+
maxArticlesPerType: 500
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## [1.12.1] - 2025-01-17
|
|
79
|
+
|
|
80
|
+
### 🔧 MAINTENANCE
|
|
81
|
+
|
|
82
|
+
- **Cập nhật**: Tối ưu tài liệu, ví dụ và xuất bản bản vá nhỏ.
|
|
83
|
+
- **Cải thiện**: Đồng bộ hoá typings và mô tả package để phát hành ổn định.
|
|
84
|
+
- **Build**: Đảm bảo `prepublishOnly` chạy `clean` + `build` trước khi publish.
|
|
85
|
+
|
|
86
|
+
## [1.12.0] - 2025-01-17
|
|
87
|
+
|
|
88
|
+
### 🎯 NEW FEATURES
|
|
89
|
+
|
|
90
|
+
#### Webhook Message Classification Helpers
|
|
91
|
+
- **ADDED**: `isUserMessageEvent()` - Phân biệt tin nhắn từ người dùng cá nhân gửi tới OA
|
|
92
|
+
- **ADDED**: `isGroupMessageEvent()` - Phân biệt tin nhắn từ người dùng trong group
|
|
93
|
+
- **ADDED**: `isOAToUserMessageEvent()` - Phân biệt tin nhắn OA gửi cho người dùng cá nhân
|
|
94
|
+
- **ADDED**: `isOAToGroupMessageEvent()` - Phân biệt tin nhắn OA gửi tới group
|
|
95
|
+
- **ADDED**: `getMessageDirection()` - Xác định hướng và đích của tin nhắn với mô tả chi tiết
|
|
96
|
+
|
|
97
|
+
#### Enhanced Type Safety
|
|
98
|
+
- **IMPROVED**: Better type guards cho webhook message classification
|
|
99
|
+
- **ENHANCED**: Comprehensive support cho 38+ message event types
|
|
100
|
+
- **ADDED**: Direction và target classification với Vietnamese descriptions
|
|
101
|
+
|
|
102
|
+
### 📚 DOCUMENTATION
|
|
103
|
+
|
|
104
|
+
#### New Documentation Files
|
|
105
|
+
- **ADDED**: `docs/WEBHOOK_MESSAGE_HELPERS.md` - Comprehensive guide cho message classification
|
|
106
|
+
- **ADDED**: `examples/webhook-message-classification.ts` - Practical usage examples
|
|
107
|
+
- **UPDATED**: README.md với message classification helpers section
|
|
108
|
+
|
|
109
|
+
#### Developer Experience
|
|
110
|
+
- **ENHANCED**: IntelliSense support với detailed JSDoc comments
|
|
111
|
+
- **ADDED**: 13 comprehensive test cases cho message classification helpers
|
|
112
|
+
- **IMPROVED**: Better error handling và unknown event detection
|
|
113
|
+
|
|
114
|
+
### 🔧 TECHNICAL IMPROVEMENTS
|
|
115
|
+
|
|
116
|
+
#### Code Organization
|
|
117
|
+
- **ENHANCED**: Exported helper functions từ main index.ts
|
|
118
|
+
- **IMPROVED**: Type safety với proper TypeScript interfaces
|
|
119
|
+
- **ADDED**: Comprehensive test coverage cho all helper functions
|
|
120
|
+
|
|
121
|
+
#### Supported Event Types
|
|
122
|
+
- **User Message Events** (12 types): `user_send_text`, `user_send_image`, etc.
|
|
123
|
+
- **Group Message Events** (9 types): `user_send_group_text`, `user_send_group_image`, etc.
|
|
124
|
+
- **OA to User Events** (7 types): `oa_send_text`, `oa_send_image`, etc.
|
|
125
|
+
- **OA to Group Events** (10 types): `oa_send_group_text`, `oa_send_group_image`, etc.
|
|
126
|
+
|
|
127
|
+
## [1.11.1] - 2025-01-11
|
|
128
|
+
|
|
129
|
+
### 🔧 API IMPROVEMENTS
|
|
130
|
+
|
|
131
|
+
#### Method Signature Enhancement
|
|
132
|
+
- **IMPROVED**: `createOAAuthUrl()` method signature với better parameter order
|
|
133
|
+
- Changed from: `(redirectUri, state?, usePkce?, pkce?)`
|
|
134
|
+
- Changed to: `(redirectUri, state?, pkce?, usePkce?)`
|
|
135
|
+
- **ENHANCED**: More intuitive API design với PKCE config trước usePkce flag
|
|
136
|
+
- **UPDATED**: All examples và documentation để phù hợp với signature mới
|
|
137
|
+
- **ADDED**: Comprehensive test coverage cho new signature
|
|
138
|
+
|
|
139
|
+
#### Developer Experience
|
|
140
|
+
- **IMPROVED**: Better IntelliSense support với clearer parameter ordering
|
|
141
|
+
- **ENHANCED**: More logical API flow cho PKCE implementation
|
|
142
|
+
|
|
8
143
|
## [1.11.0] - 2025-01-11
|
|
9
144
|
|
|
10
145
|
### 🔐 SECURITY ENHANCEMENTS
|
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ A comprehensive TypeScript/JavaScript SDK for Zalo APIs, providing easy-to-use i
|
|
|
9
9
|
- **Group Message Framework (GMF)** - Send messages to Zalo groups
|
|
10
10
|
- **User Management** - Comprehensive user profile and tag management
|
|
11
11
|
- **Content Management** - Upload and manage media content (images, files, articles)
|
|
12
|
+
- **Enhanced Article Management** - Get all articles with auto-pagination and progress tracking
|
|
12
13
|
- **Video Upload** - Upload and manage video content with processing
|
|
13
14
|
- **Tag Management** - User tagging and segmentation
|
|
14
15
|
- **Webhook handling** - Process Zalo webhook events
|
|
@@ -22,6 +23,7 @@ A comprehensive TypeScript/JavaScript SDK for Zalo APIs, providing easy-to-use i
|
|
|
22
23
|
- 🛡️ **Error Handling** - Detailed error information and handling
|
|
23
24
|
- 📦 **Zero Dependencies** - Only requires axios and form-data
|
|
24
25
|
- 🎯 **Promise-based** - Modern async/await support
|
|
26
|
+
- 🔄 **Auto-Pagination** - Automatically fetch all articles with progress tracking
|
|
25
27
|
|
|
26
28
|
## Installation
|
|
27
29
|
|
|
@@ -584,7 +586,39 @@ const handlers: WebhookHandlers = {
|
|
|
584
586
|
- **Anonymous Events** (4 types): Anonymous chat support
|
|
585
587
|
- **Shop Events** (1 type): Order management
|
|
586
588
|
|
|
587
|
-
|
|
589
|
+
### 🎯 Message Classification Helpers
|
|
590
|
+
|
|
591
|
+
The SDK provides helper functions to easily classify webhook message events:
|
|
592
|
+
|
|
593
|
+
```typescript
|
|
594
|
+
import {
|
|
595
|
+
isUserMessageEvent,
|
|
596
|
+
isGroupMessageEvent,
|
|
597
|
+
isOAToUserMessageEvent,
|
|
598
|
+
isOAToGroupMessageEvent,
|
|
599
|
+
getMessageDirection,
|
|
600
|
+
} from "@warriorteam/redai-zalo-sdk";
|
|
601
|
+
|
|
602
|
+
function handleWebhook(event: WebhookEvent) {
|
|
603
|
+
if (isUserMessageEvent(event)) {
|
|
604
|
+
console.log("Message from individual user");
|
|
605
|
+
} else if (isGroupMessageEvent(event)) {
|
|
606
|
+
console.log("Message from group");
|
|
607
|
+
} else if (isOAToUserMessageEvent(event)) {
|
|
608
|
+
console.log("OA sent message to user");
|
|
609
|
+
} else if (isOAToGroupMessageEvent(event)) {
|
|
610
|
+
console.log("OA sent message to group");
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// Or use the unified helper
|
|
614
|
+
const { direction, target, description } = getMessageDirection(event);
|
|
615
|
+
console.log(`${direction} message to ${target}: ${description}`);
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
For complete webhook documentation, see:
|
|
620
|
+
- **[Webhook Events Guide](./docs/WEBHOOK_EVENTS.md)** - Complete guide for all 70+ webhook event types
|
|
621
|
+
- **[Message Classification Helpers](./docs/WEBHOOK_MESSAGE_HELPERS.md)** - Helper functions for message classification
|
|
588
622
|
|
|
589
623
|
## Changelog
|
|
590
624
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,8 +17,9 @@ export * from "./types/article";
|
|
|
17
17
|
export * from "./constants/zns.constants";
|
|
18
18
|
export type { BaseMessage, TextMessage, ImageMessage, FileMessage, StickerMessage, TemplateMessage as MessageTemplateMessage, ReactionMessage as MessageReactionMessage, Message, MessageRecipient, SendMessageRequest, SendMessageResponse, UploadFileResponse, MessageStatus, MessageEvent, ConsultationTextMessage, ConsultationImageMessage, ConsultationFileMessage, ConsultationStickerMessage, ConsultationQuoteMessage, ConsultationRequestInfoMessage, TransactionMessage, PromotionMessage, AnonymousTextMessage, AnonymousImageMessage, AnonymousFileMessage, AnonymousStickerMessage, MiniAppMessage, ExtendedMessage, } from "./types/message";
|
|
19
19
|
export * from "./types/webhook";
|
|
20
|
-
export { UserGroupMessageEvent, isUserSendGroupTextEvent, isUserSendGroupImageEvent, isUserSendGroupVideoEvent, isUserSendGroupAudioEvent, isUserSendGroupFileEvent, isUserGroupMessageEvent, isOASendTextEvent, isOASendImageEvent, isOASendFileEvent, isOASendStickerEvent, isOASendGifEvent, isOASendGroupTextEvent, isOASendGroupImageEvent, isOASendGroupFileEvent, isOASendGroupStickerEvent, isOASendGroupGifEvent,
|
|
21
|
-
export
|
|
20
|
+
export { UserGroupMessageEvent, isUserSendGroupTextEvent, isUserSendGroupImageEvent, isUserSendGroupVideoEvent, isUserSendGroupAudioEvent, isUserSendGroupFileEvent, isUserGroupMessageEvent, isOASendTextEvent, isOASendImageEvent, isOASendFileEvent, isOASendStickerEvent, isOASendGifEvent, isOASendGroupTextEvent, isOASendGroupImageEvent, isOASendGroupFileEvent, isOASendGroupStickerEvent, isOASendGroupGifEvent, isFromGroup, isFromPersonal, } from "./utils/type-guards";
|
|
21
|
+
export { isUserMessageEvent, isGroupMessageEvent, isOAToUserMessageEvent, isOAToGroupMessageEvent, getMessageDirection, } from "./types/webhook";
|
|
22
|
+
export type { GroupMessage, GroupTextMessage, GroupImageMessage, GroupFileMessage, GroupStickerMessage, GroupMentionMessage, GroupMessageResult, GroupInfo as GroupManagementInfo, GroupMember, GroupMemberList, GroupSettings, GroupJoinRequest, GroupJoinRequestList, GroupInvitation, GroupActivity, GroupActivityList, GroupStatistics, GroupMessageTemplate, GroupMessageSchedule, GroupBroadcast, GroupPermission, GroupWebhookEvent as GroupManagementWebhookEvent, GroupApiResponse, GroupCreateResponse, GroupUpdateResponse, GroupDeleteResponse, GroupMemberActionResponse, GroupCreateRequest, GroupCreateResult, GroupUpdateRequest, GroupAvatarUpdateRequest, GroupMemberInviteRequest, GroupMemberActionRequest, GroupAdminActionRequest, GroupDeleteRequest, GroupPendingMember, GroupQuota, GroupQuotaAsset, GroupRecentChat, GroupConversationMessage, GroupsOfOAResponse, GroupDetailResponse, GroupPendingMembersResponse, GroupAcceptPendingMembersRequest, GroupAcceptPendingMembersResponse, GroupRemoveMembersRequest, GroupRemoveMembersResponse, GroupMembersResponse, GroupQuotaMessageRequest, GroupQuotaMessageResponse, AllGroupMembersResponse, GetAllMembersProgress, EnhancedGroupMember, AllGroupMembersWithDetailsResponse, GetAllMembersWithDetailsProgress, } from "./types/group";
|
|
22
23
|
export type { UserProfile as UserManagementProfile, UserList as UserManagementList, UserTag, UserTagList, UserNote, UserInteraction, UserAnalytics, UserSegment, UserCustomField, UserCustomFieldValue, UserBehavior, UserJourney, UserPreference, UserActivity, UserExport, UserImport, UserSearch, UserSearchResult, BulkUserOperation, } from "./types/user-management";
|
|
23
24
|
export { BaseClient } from "./clients/base-client";
|
|
24
25
|
export { ZaloClient } from "./clients/zalo-client";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,2BAA2B,CAAC;AAG1C,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,IAAI,sBAAsB,EACzC,eAAe,IAAI,sBAAsB,EACzC,OAAO,EACP,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,8BAA8B,EAC9B,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,EACvB,cAAc,EACd,eAAe,GAChB,MAAM,iBAAiB,CAAC;AAGzB,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
24
24
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
25
25
|
};
|
|
26
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
-
exports.default = exports.ZaloSDK = exports.MessageManagementService = exports.GeneralMessageService = exports.PromotionService = exports.TransactionService = exports.ConsultationService = exports.VideoUploadService = exports.ArticleService = exports.GroupManagementService = exports.GroupMessageService = exports.ZNSService = exports.UserService = exports.OAService = exports.AuthService = exports.ZaloClient = exports.BaseClient = exports.
|
|
27
|
+
exports.default = exports.ZaloSDK = exports.MessageManagementService = exports.GeneralMessageService = exports.PromotionService = exports.TransactionService = exports.ConsultationService = exports.VideoUploadService = exports.ArticleService = exports.GroupManagementService = exports.GroupMessageService = exports.ZNSService = exports.UserService = exports.OAService = exports.AuthService = exports.ZaloClient = exports.BaseClient = exports.getMessageDirection = exports.isOAToGroupMessageEvent = exports.isOAToUserMessageEvent = exports.isGroupMessageEvent = exports.isUserMessageEvent = exports.isFromPersonal = exports.isFromGroup = exports.isOASendGroupGifEvent = exports.isOASendGroupStickerEvent = exports.isOASendGroupFileEvent = exports.isOASendGroupImageEvent = exports.isOASendGroupTextEvent = exports.isOASendGifEvent = exports.isOASendStickerEvent = exports.isOASendFileEvent = exports.isOASendImageEvent = exports.isOASendTextEvent = exports.isUserGroupMessageEvent = exports.isUserSendGroupFileEvent = exports.isUserSendGroupAudioEvent = exports.isUserSendGroupVideoEvent = exports.isUserSendGroupImageEvent = exports.isUserSendGroupTextEvent = void 0;
|
|
28
28
|
// Export types
|
|
29
29
|
__exportStar(require("./types/common"), exports);
|
|
30
30
|
__exportStar(require("./types/auth"), exports);
|
|
@@ -54,9 +54,15 @@ Object.defineProperty(exports, "isOASendGroupImageEvent", { enumerable: true, ge
|
|
|
54
54
|
Object.defineProperty(exports, "isOASendGroupFileEvent", { enumerable: true, get: function () { return type_guards_1.isOASendGroupFileEvent; } });
|
|
55
55
|
Object.defineProperty(exports, "isOASendGroupStickerEvent", { enumerable: true, get: function () { return type_guards_1.isOASendGroupStickerEvent; } });
|
|
56
56
|
Object.defineProperty(exports, "isOASendGroupGifEvent", { enumerable: true, get: function () { return type_guards_1.isOASendGroupGifEvent; } });
|
|
57
|
-
Object.defineProperty(exports, "isUserMessageEvent", { enumerable: true, get: function () { return type_guards_1.isUserMessageEvent; } });
|
|
58
57
|
Object.defineProperty(exports, "isFromGroup", { enumerable: true, get: function () { return type_guards_1.isFromGroup; } });
|
|
59
58
|
Object.defineProperty(exports, "isFromPersonal", { enumerable: true, get: function () { return type_guards_1.isFromPersonal; } });
|
|
59
|
+
// Export webhook helper functions
|
|
60
|
+
var webhook_1 = require("./types/webhook");
|
|
61
|
+
Object.defineProperty(exports, "isUserMessageEvent", { enumerable: true, get: function () { return webhook_1.isUserMessageEvent; } });
|
|
62
|
+
Object.defineProperty(exports, "isGroupMessageEvent", { enumerable: true, get: function () { return webhook_1.isGroupMessageEvent; } });
|
|
63
|
+
Object.defineProperty(exports, "isOAToUserMessageEvent", { enumerable: true, get: function () { return webhook_1.isOAToUserMessageEvent; } });
|
|
64
|
+
Object.defineProperty(exports, "isOAToGroupMessageEvent", { enumerable: true, get: function () { return webhook_1.isOAToGroupMessageEvent; } });
|
|
65
|
+
Object.defineProperty(exports, "getMessageDirection", { enumerable: true, get: function () { return webhook_1.getMessageDirection; } });
|
|
60
66
|
// Export clients
|
|
61
67
|
var base_client_1 = require("./clients/base-client");
|
|
62
68
|
Object.defineProperty(exports, "BaseClient", { enumerable: true, get: function () { return base_client_1.BaseClient; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;AAEH,eAAe;AACf,iDAA+B;AAC/B,+CAA6B;AAC7B,6CAA2B;AAC3B,+CAA6B;AAC7B,8CAA4B;AAC5B,kDAAgC;AAEhC,mCAAmC;AACnC,4DAA0C;AAkC1C,yEAAyE;AACzE,kDAAgC;AAEhC,yEAAyE;AACzE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;;;;;;;;;;;;;AAEH,eAAe;AACf,iDAA+B;AAC/B,+CAA6B;AAC7B,6CAA2B;AAC3B,+CAA6B;AAC7B,8CAA4B;AAC5B,kDAAgC;AAEhC,mCAAmC;AACnC,4DAA0C;AAkC1C,yEAAyE;AACzE,kDAAgC;AAEhC,yEAAyE;AACzE,mDAoB6B;AAlB3B,uHAAA,wBAAwB,OAAA;AACxB,wHAAA,yBAAyB,OAAA;AACzB,wHAAA,yBAAyB,OAAA;AACzB,wHAAA,yBAAyB,OAAA;AACzB,uHAAA,wBAAwB,OAAA;AACxB,sHAAA,uBAAuB,OAAA;AACvB,gHAAA,iBAAiB,OAAA;AACjB,iHAAA,kBAAkB,OAAA;AAClB,gHAAA,iBAAiB,OAAA;AACjB,mHAAA,oBAAoB,OAAA;AACpB,+GAAA,gBAAgB,OAAA;AAChB,qHAAA,sBAAsB,OAAA;AACtB,sHAAA,uBAAuB,OAAA;AACvB,qHAAA,sBAAsB,OAAA;AACtB,wHAAA,yBAAyB,OAAA;AACzB,oHAAA,qBAAqB,OAAA;AACrB,0GAAA,WAAW,OAAA;AACX,6GAAA,cAAc,OAAA;AAEhB,kCAAkC;AAClC,2CAMyB;AALvB,6GAAA,kBAAkB,OAAA;AAClB,8GAAA,mBAAmB,OAAA;AACnB,iHAAA,sBAAsB,OAAA;AACtB,kHAAA,uBAAuB,OAAA;AACvB,8GAAA,mBAAmB,OAAA;AAoFrB,iBAAiB;AACjB,qDAAmD;AAA1C,yGAAA,UAAU,OAAA;AACnB,qDAAmD;AAA1C,yGAAA,UAAU,OAAA;AAEnB,kBAAkB;AAClB,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AACpB,oDAAkD;AAAzC,uGAAA,SAAS,OAAA;AAClB,2GAA2G;AAC3G,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AACpB,+DAA+D;AAC/D,sDAAoD;AAA3C,yGAAA,UAAU,OAAA;AACnB,0EAAuE;AAA9D,4HAAA,mBAAmB,OAAA;AAC5B,gFAA6E;AAApE,kIAAA,sBAAsB,OAAA;AAC/B,8DAA4D;AAAnD,iHAAA,cAAc,OAAA;AACvB,wEAAqE;AAA5D,0HAAA,kBAAkB,OAAA;AAE3B,iDAAiD;AACjD,wEAAsE;AAA7D,2HAAA,mBAAmB,OAAA;AAC5B,sEAAoE;AAA3D,yHAAA,kBAAkB,OAAA;AAC3B,kEAAgE;AAAvD,qHAAA,gBAAgB,OAAA;AACzB,8EAA2E;AAAlE,gIAAA,qBAAqB,OAAA;AAC9B,oFAQ+C;AAP7C,sIAAA,wBAAwB,OAAA;AAS1B,wBAAwB;AACxB,uCAAqC;AAA5B,mGAAA,OAAO,OAAA;AAEhB,iBAAiB;AACjB,uCAAgD;AAAvC,mGAAA,OAAO,OAAW"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ZaloClient } from "../clients/zalo-client";
|
|
2
|
-
import { ArticleRequest, ArticleNormalRequest, ArticleVideoRequest, ArticleResponse, ArticleProcessResponse, ArticleVerifyResponse, ArticleDetail, ArticleListRequest, ArticleListResponse, ArticleRemoveResponse, ArticleUpdateRequest, ArticleUpdateNormalRequest, ArticleUpdateVideoRequest, ArticleUpdateResponse, ArticleStatus, CommentStatus } from "../types/article";
|
|
2
|
+
import { ArticleRequest, ArticleNormalRequest, ArticleVideoRequest, ArticleResponse, ArticleProcessResponse, ArticleVerifyResponse, ArticleDetail, ArticleListRequest, ArticleListResponse, ArticleListItem, ArticleRemoveResponse, ArticleUpdateRequest, ArticleUpdateNormalRequest, ArticleUpdateVideoRequest, ArticleUpdateResponse, ArticleStatus, CommentStatus } from "../types/article";
|
|
3
3
|
/**
|
|
4
4
|
* Service for handling Zalo Official Account Article Management APIs
|
|
5
5
|
*
|
|
@@ -82,6 +82,108 @@ export declare class ArticleService {
|
|
|
82
82
|
* @returns Article list
|
|
83
83
|
*/
|
|
84
84
|
getArticleList(accessToken: string, request: ArticleListRequest): Promise<ArticleListResponse>;
|
|
85
|
+
/**
|
|
86
|
+
* Get all articles by automatically fetching all pages
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* // Get all normal articles with progress tracking
|
|
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 fetched`);
|
|
96
|
+
* }
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* console.log(`Total: ${result.totalFetched} articles in ${result.totalBatches} batches`);
|
|
100
|
+
* console.log(`Has more: ${result.hasMore}`);
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @param accessToken OA access token
|
|
104
|
+
* @param type Article type ("normal" or "video")
|
|
105
|
+
* @param options Configuration options for fetching
|
|
106
|
+
* @returns All articles with pagination info
|
|
107
|
+
*/
|
|
108
|
+
getAllArticles(accessToken: string, type?: "normal" | "video", options?: {
|
|
109
|
+
/** Number of articles to fetch per request (default: 50, max: 100) */
|
|
110
|
+
batchSize?: number;
|
|
111
|
+
/** Maximum number of articles to fetch (default: 1000, 0 = no limit) */
|
|
112
|
+
maxArticles?: number;
|
|
113
|
+
/** Optional callback to track progress */
|
|
114
|
+
onProgress?: (progress: {
|
|
115
|
+
currentBatch: number;
|
|
116
|
+
totalFetched: number;
|
|
117
|
+
hasMore: boolean;
|
|
118
|
+
}) => void;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
/** Array of all fetched articles */
|
|
121
|
+
articles: ArticleListItem[];
|
|
122
|
+
/** Total number of articles fetched */
|
|
123
|
+
totalFetched: number;
|
|
124
|
+
/** Number of API calls made */
|
|
125
|
+
totalBatches: number;
|
|
126
|
+
/** Whether there are more articles available */
|
|
127
|
+
hasMore: boolean;
|
|
128
|
+
}>;
|
|
129
|
+
/**
|
|
130
|
+
* Get all articles of both types (normal and video) combined
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* // Get all articles (both normal and video)
|
|
135
|
+
* const result = await articleService.getAllArticlesCombined(accessToken, {
|
|
136
|
+
* batchSize: 50,
|
|
137
|
+
* maxArticlesPerType: 500,
|
|
138
|
+
* onProgress: (progress) => {
|
|
139
|
+
* console.log(`${progress.type}: Batch ${progress.currentBatch}, Total: ${progress.totalFetched}`);
|
|
140
|
+
* }
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* console.log(`Total articles: ${result.totalFetched}`);
|
|
144
|
+
* console.log(`Normal articles: ${result.breakdown.normal.totalFetched}`);
|
|
145
|
+
* console.log(`Video articles: ${result.breakdown.video.totalFetched}`);
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @param accessToken OA access token
|
|
149
|
+
* @param options Configuration options for fetching
|
|
150
|
+
* @returns All articles (normal + video) with combined pagination info
|
|
151
|
+
*/
|
|
152
|
+
getAllArticlesCombined(accessToken: string, options?: {
|
|
153
|
+
/** Number of articles to fetch per request for each type (default: 50, max: 100) */
|
|
154
|
+
batchSize?: number;
|
|
155
|
+
/** Maximum number of articles to fetch per type (default: 500, 0 = no limit) */
|
|
156
|
+
maxArticlesPerType?: number;
|
|
157
|
+
/** Optional callback to track progress */
|
|
158
|
+
onProgress?: (progress: {
|
|
159
|
+
type: "normal" | "video";
|
|
160
|
+
currentBatch: number;
|
|
161
|
+
totalFetched: number;
|
|
162
|
+
hasMore: boolean;
|
|
163
|
+
}) => void;
|
|
164
|
+
}): Promise<{
|
|
165
|
+
/** Array of all fetched articles (normal + video) */
|
|
166
|
+
articles: ArticleListItem[];
|
|
167
|
+
/** Breakdown by type */
|
|
168
|
+
breakdown: {
|
|
169
|
+
normal: {
|
|
170
|
+
articles: ArticleListItem[];
|
|
171
|
+
totalFetched: number;
|
|
172
|
+
totalBatches: number;
|
|
173
|
+
hasMore: boolean;
|
|
174
|
+
};
|
|
175
|
+
video: {
|
|
176
|
+
articles: ArticleListItem[];
|
|
177
|
+
totalFetched: number;
|
|
178
|
+
totalBatches: number;
|
|
179
|
+
hasMore: boolean;
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
/** Total number of articles fetched */
|
|
183
|
+
totalFetched: number;
|
|
184
|
+
/** Total number of API calls made */
|
|
185
|
+
totalBatches: number;
|
|
186
|
+
}>;
|
|
85
187
|
/**
|
|
86
188
|
* Remove article
|
|
87
189
|
* @param accessToken OA access token
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"article.service.d.ts","sourceRoot":"","sources":["../../src/services/article.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EAGb,kBAAkB,EAClB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"article.service.d.ts","sourceRoot":"","sources":["../../src/services/article.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -238,6 +238,173 @@ class ArticleService {
|
|
|
238
238
|
throw this.handleArticleError(error, "Failed to get article list");
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Get all articles by automatically fetching all pages
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* // Get all normal articles with progress tracking
|
|
247
|
+
* const result = await articleService.getAllArticles(accessToken, "normal", {
|
|
248
|
+
* batchSize: 50,
|
|
249
|
+
* maxArticles: 1000,
|
|
250
|
+
* onProgress: (progress) => {
|
|
251
|
+
* console.log(`Batch ${progress.currentBatch}: ${progress.totalFetched} articles fetched`);
|
|
252
|
+
* }
|
|
253
|
+
* });
|
|
254
|
+
*
|
|
255
|
+
* console.log(`Total: ${result.totalFetched} articles in ${result.totalBatches} batches`);
|
|
256
|
+
* console.log(`Has more: ${result.hasMore}`);
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @param accessToken OA access token
|
|
260
|
+
* @param type Article type ("normal" or "video")
|
|
261
|
+
* @param options Configuration options for fetching
|
|
262
|
+
* @returns All articles with pagination info
|
|
263
|
+
*/
|
|
264
|
+
async getAllArticles(accessToken, type = "normal", options = {}) {
|
|
265
|
+
try {
|
|
266
|
+
const { batchSize = 50, maxArticles = 1000, onProgress } = options;
|
|
267
|
+
// Validate parameters
|
|
268
|
+
if (batchSize <= 0 || batchSize > article_1.ARTICLE_CONSTRAINTS.LIST_MAX_LIMIT) {
|
|
269
|
+
throw new common_1.ZaloSDKError(`Batch size must be between 1 and ${article_1.ARTICLE_CONSTRAINTS.LIST_MAX_LIMIT}`, -1);
|
|
270
|
+
}
|
|
271
|
+
if (maxArticles < 0) {
|
|
272
|
+
throw new common_1.ZaloSDKError("Max articles must be >= 0 (0 = no limit)", -1);
|
|
273
|
+
}
|
|
274
|
+
if (!["normal", "video"].includes(type)) {
|
|
275
|
+
throw new common_1.ZaloSDKError('Type must be "normal" or "video"', -1);
|
|
276
|
+
}
|
|
277
|
+
const allArticles = [];
|
|
278
|
+
let offset = 0;
|
|
279
|
+
let currentBatch = 0;
|
|
280
|
+
let hasMore = true;
|
|
281
|
+
while (hasMore) {
|
|
282
|
+
currentBatch++;
|
|
283
|
+
// Calculate limit for this batch
|
|
284
|
+
let currentLimit = batchSize;
|
|
285
|
+
if (maxArticles > 0) {
|
|
286
|
+
const remaining = maxArticles - allArticles.length;
|
|
287
|
+
if (remaining <= 0)
|
|
288
|
+
break;
|
|
289
|
+
currentLimit = Math.min(batchSize, remaining);
|
|
290
|
+
}
|
|
291
|
+
// Fetch current batch
|
|
292
|
+
const response = await this.getArticleList(accessToken, {
|
|
293
|
+
offset,
|
|
294
|
+
limit: currentLimit,
|
|
295
|
+
type
|
|
296
|
+
});
|
|
297
|
+
// Add articles to collection
|
|
298
|
+
// Check if response is successful and has data
|
|
299
|
+
if ('data' in response && response.data?.medias && response.data.medias.length > 0) {
|
|
300
|
+
allArticles.push(...response.data.medias);
|
|
301
|
+
offset += response.data.medias.length;
|
|
302
|
+
// Check if we have more data
|
|
303
|
+
hasMore = response.data.medias.length === currentLimit;
|
|
304
|
+
// Stop if we've reached max articles
|
|
305
|
+
if (maxArticles > 0 && allArticles.length >= maxArticles) {
|
|
306
|
+
hasMore = false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else if ('medias' in response && response.medias && response.medias.length > 0) {
|
|
310
|
+
// Handle direct response format (fallback)
|
|
311
|
+
allArticles.push(...response.medias);
|
|
312
|
+
offset += response.medias.length;
|
|
313
|
+
// Check if we have more data
|
|
314
|
+
hasMore = response.medias.length === currentLimit;
|
|
315
|
+
// Stop if we've reached max articles
|
|
316
|
+
if (maxArticles > 0 && allArticles.length >= maxArticles) {
|
|
317
|
+
hasMore = false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
hasMore = false;
|
|
322
|
+
}
|
|
323
|
+
// Call progress callback if provided
|
|
324
|
+
if (onProgress) {
|
|
325
|
+
onProgress({
|
|
326
|
+
currentBatch,
|
|
327
|
+
totalFetched: allArticles.length,
|
|
328
|
+
hasMore
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
// Safety check to prevent infinite loops
|
|
332
|
+
if (currentBatch > 100) {
|
|
333
|
+
console.warn("Reached maximum batch limit (100), stopping fetch");
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return {
|
|
338
|
+
articles: allArticles,
|
|
339
|
+
totalFetched: allArticles.length,
|
|
340
|
+
totalBatches: currentBatch,
|
|
341
|
+
hasMore: hasMore && (maxArticles === 0 || allArticles.length < maxArticles)
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
throw this.handleArticleError(error, "Failed to get all articles");
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Get all articles of both types (normal and video) combined
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```typescript
|
|
353
|
+
* // Get all articles (both normal and video)
|
|
354
|
+
* const result = await articleService.getAllArticlesCombined(accessToken, {
|
|
355
|
+
* batchSize: 50,
|
|
356
|
+
* maxArticlesPerType: 500,
|
|
357
|
+
* onProgress: (progress) => {
|
|
358
|
+
* console.log(`${progress.type}: Batch ${progress.currentBatch}, Total: ${progress.totalFetched}`);
|
|
359
|
+
* }
|
|
360
|
+
* });
|
|
361
|
+
*
|
|
362
|
+
* console.log(`Total articles: ${result.totalFetched}`);
|
|
363
|
+
* console.log(`Normal articles: ${result.breakdown.normal.totalFetched}`);
|
|
364
|
+
* console.log(`Video articles: ${result.breakdown.video.totalFetched}`);
|
|
365
|
+
* ```
|
|
366
|
+
*
|
|
367
|
+
* @param accessToken OA access token
|
|
368
|
+
* @param options Configuration options for fetching
|
|
369
|
+
* @returns All articles (normal + video) with combined pagination info
|
|
370
|
+
*/
|
|
371
|
+
async getAllArticlesCombined(accessToken, options = {}) {
|
|
372
|
+
try {
|
|
373
|
+
const { batchSize = 50, maxArticlesPerType = 500, onProgress } = options;
|
|
374
|
+
// Fetch normal articles
|
|
375
|
+
const normalResult = await this.getAllArticles(accessToken, "normal", {
|
|
376
|
+
batchSize,
|
|
377
|
+
maxArticles: maxArticlesPerType,
|
|
378
|
+
onProgress: onProgress ? (progress) => onProgress({
|
|
379
|
+
type: "normal",
|
|
380
|
+
...progress
|
|
381
|
+
}) : undefined
|
|
382
|
+
});
|
|
383
|
+
// Fetch video articles
|
|
384
|
+
const videoResult = await this.getAllArticles(accessToken, "video", {
|
|
385
|
+
batchSize,
|
|
386
|
+
maxArticles: maxArticlesPerType,
|
|
387
|
+
onProgress: onProgress ? (progress) => onProgress({
|
|
388
|
+
type: "video",
|
|
389
|
+
...progress
|
|
390
|
+
}) : undefined
|
|
391
|
+
});
|
|
392
|
+
// Combine results
|
|
393
|
+
const allArticles = [...normalResult.articles, ...videoResult.articles];
|
|
394
|
+
return {
|
|
395
|
+
articles: allArticles,
|
|
396
|
+
breakdown: {
|
|
397
|
+
normal: normalResult,
|
|
398
|
+
video: videoResult
|
|
399
|
+
},
|
|
400
|
+
totalFetched: allArticles.length,
|
|
401
|
+
totalBatches: normalResult.totalBatches + videoResult.totalBatches
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
catch (error) {
|
|
405
|
+
throw this.handleArticleError(error, "Failed to get all articles combined");
|
|
406
|
+
}
|
|
407
|
+
}
|
|
241
408
|
/**
|
|
242
409
|
* Remove article
|
|
243
410
|
* @param accessToken OA access token
|