@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs
340 lines • 14.2 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
* - Lấy danh sách cuộc hội thoại
* - Upload file và hình ảnh
* - Quản lý trạng thái tin nhắn
*
* ĐIỀU KIỆN SỬ DỤNG:
*
* 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:
* - Chỉ có thể lấy tin nhắn trong vòng 7 ngày gần nhất
* - Tối đa 50 tin nhắn mỗi lần gọi API
*
* 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
* @param accessToken Access token của Official Account
* @param userId ID của người dùng Zalo
* @param offset Vị trí bắt đầu lấy tin nhắn (mặc định: 0)
* @param count Số lượng tin nhắn cần lấy (mặc định: 20, tối đa: 50)
* @returns Danh sách tin nhắn và thông tin phân trang
*/
async getConversationMessages(accessToken, userId, offset = 0, count = 20) {
try {
if (count > 50) {
throw new common_1.ZaloSDKError("Số lượng tin nhắn tối đa là 50", -1);
}
const result = await this.client.apiGet(this.endpoints.message.conversation, accessToken, {
user_id: userId,
offset,
count,
});
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);
}
return {
messages: result.data.messages,
pagination: {
offset,
count,
total: result.data.total,
},
};
}
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 cuộc hội thoại gần đây
* @param accessToken Access token của Official Account
* @param offset Vị trí bắt đầu lấy cuộc hội thoại (mặc định: 0)
* @param count Số lượng cuộc hội thoại cần lấy (mặc định: 20, tối đa: 50)
* @returns Danh sách cuộc hội thoại và thông tin phân trang
*/
async getRecentConversations(accessToken, offset = 0, count = 20) {
try {
if (count > 50) {
throw new common_1.ZaloSDKError("Số lượng cuộc hội thoại tối đa là 50", -1);
}
const result = await this.client.apiGet(this.endpoints.message.recentConversations, accessToken, {
offset,
count,
});
if (result.error !== 0) {
throw new common_1.ZaloSDKError(result.message || "Failed to get recent conversations", result.error, result);
}
if (!result.data) {
throw new common_1.ZaloSDKError("No conversations data received", -1);
}
return {
conversations: result.data.conversations,
pagination: {
offset,
count,
total: result.data.total,
},
};
}
catch (error) {
if (error instanceof common_1.ZaloSDKError) {
throw error;
}
throw new common_1.ZaloSDKError(`Failed to get recent conversations: ${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);
}
const formData = new FormData();
if (typeof fileData === "string") {
const buffer = Buffer.from(fileData, "base64");
formData.append("file", new Blob([new Uint8Array(buffer)]), fileName);
}
else {
formData.append("file", new Blob([new Uint8Array(fileData)]), fileName);
}
const result = await this.client.apiPost(this.endpoints.upload.file, accessToken, formData);
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 format (only JPG and PNG)
const allowedExtensions = ['.jpg', '.jpeg', '.png'];
const fileExt = fileName.toLowerCase().substring(fileName.lastIndexOf('.'));
if (!allowedExtensions.includes(fileExt)) {
throw new common_1.ZaloSDKError("Chỉ hỗ trợ hình ảnh JPG và PNG", -1);
}
// 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);
}
const formData = new FormData();
if (typeof imageData === "string") {
const buffer = Buffer.from(imageData, "base64");
formData.append("file", new Blob([new Uint8Array(buffer)]), fileName);
}
else {
formData.append("file", new Blob([new Uint8Array(imageData)]), fileName);
}
const result = await this.client.apiPost(this.endpoints.upload.image, accessToken, formData);
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);
}
const formData = new FormData();
if (typeof gifData === "string") {
const buffer = Buffer.from(gifData, "base64");
formData.append("file", new Blob([new Uint8Array(buffer)]), fileName);
}
else {
formData.append("file", new Blob([new Uint8Array(gifData)]), fileName);
}
const result = await this.client.apiPost(this.endpoints.upload.gif, accessToken, formData);
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