@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account v3.0, ZNS with Full Type Safety, Consultation Service, Broadcast Service, Group Messaging with List APIs, Social APIs, Enhanced Article Management, Promotion Service v3.0 with Multip
404 lines • 16.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageManagementService = void 0;
const common_1 = require("../types/common");
/**
* Service xử lý các API quản lý tin nhắn của Zalo Official Account
*
* Bao gồm các chức năng:
* - Kiểm tra hạn mức gửi tin nhắn
* - Lấy danh sách tin nhắn trong cuộc hội thoại với user cụ thể
* - Lấy thông tin tin nhắn gần nhất
* - Upload file và hình ảnh
*
* ĐIỀU KIỆN SỮCDNG:
*
* 1. KIỂM TRA HẠN MỨC:
* - Cần quyền truy cập thông tin quota từ Zalo
* - Quota được reset hàng ngày vào 00:00 GMT+7
*
* 2. LẤY TIN NHẮN:
* - API hỗ trợ lấy thông tin tin nhắn giữa OA và một người dùng cụ thể
* - Mỗi request lấy tối đa được 10 tin nhắn
* - Tin nhắn gần nhất có thứ tự là 0
*
* 3. UPLOAD FILE:
* - Kích thước tối đa 5MB
* - Hỗ trợ các định dạng: PDF, DOC, DOCX
* - Quota: 5000 request/tháng
*
* 4. UPLOAD HÌNH ẢNH:
* - Dung lượng tối đa 1MB
* - Hỗ trợ các định dạng: JPG và PNG
* - Ảnh sẽ được lưu trên server tối đa 7 ngày
* - Quota: 5000 request/tháng
*
* 5. UPLOAD ẢNH GIF:
* - Kích thước tối đa 5MB
* - Chỉ hỗ trợ định dạng GIF
* - Ảnh GIF được lưu trên server tối đa 7 ngày
* - Quota: 5000 request/tháng
*/
class MessageManagementService {
constructor(client) {
this.client = client;
// Zalo API endpoints - organized by functionality
this.endpoints = {
// Message management endpoints
message: {
quota: "https://openapi.zalo.me/v2.0/oa/quota",
conversation: "https://openapi.zalo.me/v2.0/oa/conversation",
recentConversations: "https://openapi.zalo.me/v2.0/oa/listrecentchat",
},
// Upload endpoints
upload: {
file: "https://openapi.zalo.me/v2.0/oa/upload/file",
image: "https://openapi.zalo.me/v2.0/oa/upload/image",
gif: "https://openapi.zalo.me/v2.0/oa/upload/gif",
},
};
}
/**
* Kiểm tra hạn mức gửi tin nhắn đến user cụ thể
* @param accessToken Access token của Official Account
* @param userId ID của người dùng Zalo
* @returns Thông tin hạn mức gửi tin nhắn
*/
async checkMessageQuota(accessToken, userId) {
try {
const result = await this.client.apiGet(this.endpoints.message.quota, accessToken, { user_id: userId });
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to check message quota", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No quota data received", -1);
}
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to check message quota: ${error.message}`, -1, error);
}
}
/**
* Lấy danh sách tin nhắn trong cuộc hội thoại với user
*
* API hỗ trợ lấy thông tin tin nhắn giữa OA và một người dùng cụ thể.
*
* @param accessToken Access token của Official Account
* @param userId ID của người dùng Zalo cần lấy danh sách hội thoại
* @param offset Thứ tự của tin nhắn đầu tiên trong danh sách trả về (tin nhắn gần nhất có thứ tự là 0)
* @param count Số lượng tin nhắn cần lấy (mỗi request lấy tối đa 10 tin nhắn)
* @returns Danh sách tin nhắn
*
* @example
* ```typescript
* const messages = await messageService.getConversationMessages(
* accessToken,
* '2512523625412515',
* 0,
* 5
* );
* ```
*/
async getConversationMessages(accessToken, userId, offset = 0, count = 10) {
try {
// Validate count theo docs: mỗi request lấy tối đa 10 tin nhắn
if (count > 10) {
throw new common_1.ZaloSDKError("Mỗi request lấy tối đa được 10 tin nhắn", -1);
}
// Theo docs Zalo: params phải được wrap trong object data dạng JSON string
const params = {
data: JSON.stringify({
user_id: userId,
offset,
count,
}),
};
const result = await this.client.apiGet(this.endpoints.message.conversation, accessToken, params);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to get conversation messages", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No conversation data received", -1);
}
// Response trả về mảng trực tiếp trong data
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to get conversation messages: ${error.message}`, -1, error);
}
}
/**
* Lấy danh sách tin nhắn trong cuộc hội thoại với user (sử dụng POST method)
*
* API hỗ trợ lấy thông tin tin nhắn giữa OA và một người dùng cụ thể sử dụng phương thức POST.
*
* @param accessToken Access token của Official Account
* @param userId ID của người dùng Zalo cần lấy danh sách hội thoại
* @param offset Thứ tự của tin nhắn đầu tiên trong danh sách trả về (tin nhắn gần nhất có thứ tự là 0)
* @param count Số lượng tin nhắn cần lấy (mỗi request lấy tối đa 10 tin nhắn)
* @returns Danh sách tin nhắn
*
* @example
* ```typescript
* const messages = await messageService.postConversationMessages(
* accessToken,
* '2512523625412515',
* 0,
* 5
* );
* ```
*/
async postConversationMessages(accessToken, userId, offset = 0, count = 10) {
try {
// Validate count theo docs: mỗi request lấy tối đa 10 tin nhắn
if (count > 10) {
throw new common_1.ZaloSDKError("Mỗi request lấy tối đa được 10 tin nhắn", -1);
}
// Body format for POST request - gửi trực tiếp các tham số
const body = {
user_id: userId,
offset,
count,
};
const result = await this.client.apiPost(this.endpoints.message.conversation, accessToken, body);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to get conversation messages", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No conversation data received", -1);
}
// Response trả về mảng trực tiếp trong data
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to get conversation messages: ${error.message}`, -1, error);
}
}
/**
* Lấy thông tin tin nhắn gần nhất
*
* API hỗ trợ lấy thông tin tối đa 10 tin nhắn gần nhất giữa OA và người dùng.
*
* @param accessToken Access token của Official Account
* @param offset Thứ tự của tin nhắn đầu tiên trong danh sách trả về (tin nhắn gần nhất có thứ tự là 0)
* @param count Số lượng tin nhắn muốn lấy (mỗi request lấy tối đa 10 tin nhắn)
* @returns Danh sách tin nhắn gần nhất
*
* @example
* ```typescript
* const recentMessages = await messageService.getRecentConversations(
* accessToken,
* 0,
* 5
* );
* ```
*/
async getRecentConversations(accessToken, offset = 0, count = 10) {
try {
// Validate count theo docs: mỗi request lấy tối đa 10 tin nhắn
if (count > 10) {
throw new common_1.ZaloSDKError("Mỗi request lấy tối đa 10 tin nhắn", -1);
}
// Theo docs Zalo: params phải được wrap trong object data dạng JSON string
const params = {
data: JSON.stringify({
offset,
count,
}),
};
const result = await this.client.apiGet(this.endpoints.message.recentConversations, accessToken, params);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to get recent messages", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No recent messages data received", -1);
}
// Response trả về mảng trực tiếp trong data
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to get recent messages: ${error.message}`, -1, error);
}
}
/**
* Upload file để sử dụng trong tin nhắn
* @param accessToken Access token của Official Account
* @param fileData Dữ liệu file (base64 hoặc buffer)
* @param fileName Tên file
* @returns Token của file đã upload
*
* Lưu ý:
* - Chỉ hỗ trợ file PDF/DOC/DOCX
* - Dung lượng file không vượt quá 5MB
* - File sẽ được lưu trên server tối đa 7 ngày
* - Quota: 5000 request/tháng
*/
async uploadFile(accessToken, fileData, fileName) {
try {
// Validate file format (only PDF/DOC/DOCX)
const allowedExtensions = ['.pdf', '.doc', '.docx'];
const fileExt = fileName.toLowerCase().substring(fileName.lastIndexOf('.'));
if (!allowedExtensions.includes(fileExt)) {
throw new common_1.ZaloSDKError("Chỉ hỗ trợ file PDF, DOC, DOCX", -1);
}
// Validate file size (max 5MB)
const maxSize = 5 * 1024 * 1024; // 5MB
let fileSize;
if (typeof fileData === "string") {
// Base64 string
fileSize = Buffer.from(fileData, "base64").length;
}
else {
// Buffer
fileSize = fileData.length;
}
if (fileSize > maxSize) {
throw new common_1.ZaloSDKError("Kích thước file không được vượt quá 5MB", -1);
}
let buffer;
if (typeof fileData === "string") {
buffer = Buffer.from(fileData, "base64");
}
else {
buffer = fileData;
}
const result = await this.client.apiUploadFile(this.endpoints.upload.file, accessToken, buffer, fileName);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to upload file", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No upload result received", -1);
}
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to upload file: ${error.message}`, -1, error);
}
}
/**
* Upload hình ảnh để sử dụng trong tin nhắn
* @param accessToken Access token của Official Account
* @param imageData Dữ liệu hình ảnh (base64 hoặc buffer)
* @param fileName Tên file hình ảnh
* @returns ID của ảnh đã upload
*
* Lưu ý:
* - Hỗ trợ các định dạng: JPG và PNG
* - Dung lượng tối đa: 1MB
* - Ảnh sẽ được lưu trên server tối đa 7 ngày
* - Quota: 5000 request/tháng
*/
async uploadImage(accessToken, imageData, fileName) {
try {
// Validate image size (max 1MB)
const maxSize = 1 * 1024 * 1024; // 1MB
let imageSize;
if (typeof imageData === "string") {
// Base64 string
imageSize = Buffer.from(imageData, "base64").length;
}
else {
// Buffer
imageSize = imageData.length;
}
if (imageSize > maxSize) {
throw new common_1.ZaloSDKError("Kích thước hình ảnh không được vượt quá 1MB", -1);
}
let buffer;
if (typeof imageData === "string") {
buffer = Buffer.from(imageData, "base64");
}
else {
buffer = imageData;
}
const result = await this.client.apiUploadFile(this.endpoints.upload.image, accessToken, buffer, fileName);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to upload image", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No upload result received", -1);
}
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to upload image: ${error.message}`, -1, error);
}
}
/**
* Upload ảnh GIF để sử dụng trong tin nhắn
* @param accessToken Access token của Official Account
* @param gifData Dữ liệu ảnh GIF (base64 hoặc buffer)
* @param fileName Tên file ảnh GIF
* @returns Thông tin ảnh GIF đã upload
*
* Lưu ý:
* - Dung lượng tối đa: 5MB
* - Ảnh GIF sẽ được lưu trên server tối đa 7 ngày
* - Quota: 5000 request/tháng
* - Định dạng hỗ trợ: GIF
*/
async uploadGif(accessToken, gifData, fileName) {
try {
// Validate GIF size (max 5MB)
const maxSize = 5 * 1024 * 1024; // 5MB
let gifSize;
if (typeof gifData === "string") {
// Base64 string
gifSize = Buffer.from(gifData, "base64").length;
}
else {
// Buffer
gifSize = gifData.length;
}
if (gifSize > maxSize) {
throw new common_1.ZaloSDKError("Kích thước ảnh GIF không được vượt quá 5MB", -1);
}
// Validate file extension
if (!fileName.toLowerCase().endsWith(".gif")) {
throw new common_1.ZaloSDKError("File phải có định dạng GIF", -1);
}
let buffer;
if (typeof gifData === "string") {
buffer = Buffer.from(gifData, "base64");
}
else {
buffer = gifData;
}
const result = await this.client.apiUploadFile(this.endpoints.upload.gif, accessToken, buffer, fileName);
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to upload GIF", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No upload result received", -1);
}
return result.data;
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to upload GIF: ${error.message}`, -1, error);
}
}
}
exports.MessageManagementService = MessageManagementService;
//# sourceMappingURL=message-management.service.js.map