@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account, ZNS, Consultation Service, Group Messaging, and Social APIs
259 lines • 9.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GroupMessageService = void 0;
/**
* Service for handling Zalo Official Account Group Message Framework (GMF) APIs
*
* CONDITIONS FOR USING ZALO GMF:
*
* 1. OPT-IN CONDITIONS FOR SENDING GROUP MESSAGES:
* - OA must have the group_id of the chat group
* - OA must be added to the chat group by group admin
* - OA must have permission to send messages in the group (granted by group admin)
* - Chat group must be active (not locked or disbanded)
*
* 2. ACCESS PERMISSIONS:
* - Application needs to be granted group chat management permissions
* - Access token must have "manage_group" scope or equivalent
* - OA must be authenticated and have active status
*
* 3. LIMITS AND CONSTRAINTS:
* - Can only send messages to groups that OA has joined
* - Cannot send messages to private groups that OA hasn't been invited to
* - Must comply with Zalo's message sending frequency limits
* - Message content must comply with Zalo's content policy
*
* 4. SUPPORTED MESSAGE TYPES:
* - Text message: Plain text messages
* - Image message: Image messages (JPG, PNG, GIF - max 5MB)
* - File message: File attachments (max 25MB)
* - Sticker message: Stickers from Zalo collection
* - Mention message: Tag/mention specific members
*
* 5. TECHNICAL REQUIREMENTS:
* - Use HTTPS for all API calls
* - Content-Type: application/json for text/mention messages
* - Content-Type: multipart/form-data for file/image uploads
*/
class GroupMessageService {
constructor(client) {
this.client = client;
// Zalo API endpoints - organized by functionality
this.endpoints = {
// Group message endpoints
message: {
group: "https://openapi.zalo.me/v3.0/oa/group/message",
},
// Group management endpoints
group: {
getInfo: "https://openapi.zalo.me/v3.0/oa/group/getinfo",
getMembers: "https://openapi.zalo.me/v3.0/oa/group/getmembers",
},
};
}
/**
* Send text message to group
* @param accessToken OA access token
* @param groupId Group ID
* @param message Text message content
* @returns Send result
*/
async sendTextMessage(accessToken, groupId, message) {
try {
const response = await this.client.apiPost(this.endpoints.message.group, accessToken, {
recipient: {
group_id: groupId,
},
message: {
text: message.text,
},
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to send text message to group");
}
}
/**
* Send image message to group
* @param accessToken OA access token
* @param groupId Group ID
* @param message Image message content
* @returns Send result
*/
async sendImageMessage(accessToken, groupId, message) {
try {
// Validate that either imageUrl or attachmentId is provided
if (!message.imageUrl && !message.attachmentId) {
throw new Error("Either imageUrl or attachmentId must be provided");
}
// Prepare message payload
const messagePayload = {
attachment: {
type: "template",
payload: {
template_type: "media",
elements: [
{
media_type: "image",
...(message.attachmentId
? { attachment_id: message.attachmentId }
: { url: message.imageUrl }),
},
],
},
},
};
// Add text caption if provided (max 2000 characters)
if (message.caption) {
if (message.caption.length > 2000) {
throw new Error("Caption cannot exceed 2000 characters");
}
messagePayload.text = message.caption;
}
const response = await this.client.apiPost(this.endpoints.message.group, accessToken, {
recipient: {
group_id: groupId,
},
message: messagePayload,
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to send image message to group");
}
}
/**
* Send file message to group
* @param accessToken OA access token
* @param groupId Group ID
* @param message File message content
* @returns Send result
*/
async sendFileMessage(accessToken, groupId, message) {
try {
const response = await this.client.apiPost(this.endpoints.message.group, accessToken, {
recipient: {
group_id: groupId,
},
message: {
attachment: {
type: "file",
payload: {
token: message.fileToken,
},
},
},
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to send file message to group");
}
}
/**
* Send sticker message to group
* @param accessToken OA access token
* @param groupId Group ID
* @param message Sticker message content
* @returns Send result
*/
async sendStickerMessage(accessToken, groupId, message) {
try {
const response = await this.client.apiPost(this.endpoints.message.group, accessToken, {
recipient: {
group_id: groupId,
},
message: {
attachment: {
type: "template",
payload: {
template_type: "media",
elements: [
{
media_type: "sticker",
attachment_id: message.stickerId,
},
],
},
},
},
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to send sticker message to group");
}
}
/**
* Send mention message to group
* @param accessToken OA access token
* @param groupId Group ID
* @param message Mention message content
* @returns Send result
*/
async sendMentionMessage(accessToken, groupId, message) {
try {
const response = await this.client.apiPost(this.endpoints.message.group, accessToken, {
recipient: {
group_id: groupId,
},
message: {
text: message.text,
mention: message.mentions,
},
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to send mention message to group");
}
}
/**
* Get group information
* @param accessToken OA access token
* @param groupId Group ID
* @returns Group information
*/
async getGroupInfo(accessToken, groupId) {
try {
const response = await this.client.apiGet(this.endpoints.group.getInfo, accessToken, {
group_id: groupId,
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to get group information");
}
}
/**
* Get group members
* @param accessToken OA access token
* @param groupId Group ID
* @param offset Offset for pagination
* @param count Number of members to retrieve
* @returns Group members list
*/
async getGroupMembers(accessToken, groupId, offset = 0, count = 50) {
try {
const response = await this.client.apiGet(this.endpoints.group.getMembers, accessToken, {
group_id: groupId,
offset,
count,
});
return response;
}
catch (error) {
throw this.handleGroupMessageError(error, "Failed to get group members");
}
}
handleGroupMessageError(error, defaultMessage) {
if (error.response?.data) {
const errorData = error.response.data;
return new Error(`${defaultMessage}: ${errorData.message || errorData.error || "Unknown error"}`);
}
return new Error(`${defaultMessage}: ${error.message || "Unknown error"}`);
}
}
exports.GroupMessageService = GroupMessageService;
//# sourceMappingURL=group-message.service.js.map