@warriorteam/zalo-personal
Version:
Unofficial Zalo Personal API for JavaScript - A powerful library for interacting with Zalo personal accounts with URL attachment support
543 lines (407 loc) • 12.3 kB
Markdown
# Hướng Dẫn Sử Dụng Zalo Personal SDK
## Tổng quan
Zalo Personal SDK là một thư viện JavaScript/TypeScript mạnh mẽ cho phép tương tác với Zalo thông qua các API không chính thức. SDK hỗ trợ đầy đủ các chức năng như gửi tin nhắn, quản lý bạn bè, quản lý nhóm, và nhiều tính năng khác.
## Cài Đặt
```bash
npm install zalo-personal-sdk
```
## Khởi Tạo và Đăng Nhập
### 1. Đăng nhập bằng Cookie
```typescript
import { Zalo } from 'zalo-personal-sdk';
const zalo = new Zalo();
// Thông tin đăng nhập
const credentials = {
imei: 'your-device-imei',
cookie: [
// Cookie array từ browser
],
userAgent: 'Mozilla/5.0...',
language: 'vi' // Optional
};
const api = await zalo.login(credentials);
```
### 2. Đăng nhập bằng QR Code
```typescript
const api = await zalo.loginQR({
userAgent: 'Mozilla/5.0...',
language: 'vi',
qrPath: './qr-code.png' // Optional: đường dẫn lưu QR code
}, (event) => {
switch (event.type) {
case LoginQRCallbackEventType.QrCodeGenerated:
console.log('QR Code được tạo:', event.data.qrCodePath);
break;
case LoginQRCallbackEventType.LoggedIn:
console.log('Đăng nhập thành công!');
break;
case LoginQRCallbackEventType.GotLoginInfo:
console.log('Thông tin đăng nhập:', event.data);
break;
}
});
```
## Gửi Tin Nhắn
### 1. Gửi Tin Nhắn Văn Bản Đơn Giản
```typescript
import { ThreadType } from 'zalo-personal-sdk';
// Gửi tin nhắn cho người dùng
await api.sendMessage('Xin chào!', 'user-id', ThreadType.User);
// Gửi tin nhắn cho nhóm
await api.sendMessage('Hello group!', 'group-id', ThreadType.Group);
```
### 2. Gửi Tin Nhắn Với Định Dạng Văn Bản
```typescript
import { TextStyle, Urgency } from 'zalo-personal-sdk';
const messageContent = {
msg: 'Tin nhắn có định dạng',
styles: [
{ start: 0, len: 3, st: TextStyle.Bold }, // In đậm
{ start: 4, len: 4, st: TextStyle.Italic }, // In nghiêng
{ start: 9, len: 2, st: TextStyle.Red } // Màu đỏ
],
urgency: Urgency.Important
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
### 3. Gửi Tin Nhắn Có Mention (trong nhóm)
```typescript
const messageContent = {
msg: '@user1 @user2 Chào các bạn!',
mentions: [
{ pos: 0, len: 6, uid: 'user1-id' },
{ pos: 7, len: 6, uid: 'user2-id' }
]
};
await api.sendMessage(messageContent, 'group-id', ThreadType.Group);
```
### 4. Gửi Tin Nhắn Trả Lời (Quote)
```typescript
// Lấy tin nhắn để trả lời từ listener hoặc API khác
const originalMessage = {
content: 'Nội dung tin nhắn gốc',
msgType: 'webchat',
uidFrom: 'sender-id',
msgId: 123456,
cliMsgId: 'client-msg-id',
ts: Date.now(),
ttl: 0,
propertyExt: {}
};
const replyContent = {
msg: 'Đây là câu trả lời',
quote: originalMessage
};
await api.sendMessage(replyContent, 'user-id', ThreadType.User);
```
### 5. Gửi Tin Nhắn Với File Đính Kèm
#### Gửi từ đường dẫn file local:
```typescript
const messageContent = {
msg: 'Ảnh đẹp không?',
attachments: '/path/to/image.jpg'
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
#### Gửi từ URL:
```typescript
const messageContent = {
msg: 'Hình ảnh từ internet',
attachments: {
url: 'https://example.com/image.jpg',
filename: 'downloaded-image.jpg',
headers: { 'User-Agent': 'MyBot' } // Optional
}
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
#### Gửi từ Buffer:
```typescript
const fileBuffer = fs.readFileSync('./image.jpg');
const messageContent = {
msg: 'Hình từ buffer',
attachments: {
data: fileBuffer,
filename: 'buffer-image.jpg',
metadata: {
totalSize: fileBuffer.length,
width: 1920,
height: 1080
}
}
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
#### Gửi nhiều file:
```typescript
const messageContent = {
msg: 'Gửi nhiều hình',
attachments: [
'/path/to/image1.jpg',
'/path/to/image2.png',
{
url: 'https://example.com/image3.gif',
filename: 'animated.gif'
}
]
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
### 6. Gửi Tin Nhắn Tự Hủy (TTL)
```typescript
const messageContent = {
msg: 'Tin nhắn này sẽ tự hủy sau 60 giây',
ttl: 60000 // TTL tính bằng milliseconds
};
await api.sendMessage(messageContent, 'user-id', ThreadType.User);
```
### 7. Các Loại Tin Nhắn Đặc Biệt
#### Gửi Sticker:
```typescript
await api.sendSticker('sticker-id', 'user-id', ThreadType.User, 'sticker-category-id');
```
#### Gửi Link:
```typescript
const linkOptions = {
url: 'https://example.com',
title: 'Tiêu đề link',
description: 'Mô tả link',
thumbnail: 'https://example.com/thumb.jpg'
};
await api.sendLink(linkOptions, 'user-id', ThreadType.User);
```
#### Gửi Card/Danh thiếp:
```typescript
const cardOptions = {
userId: 'target-user-id'
};
await api.sendCard(cardOptions, 'recipient-id', ThreadType.User);
```
#### Gửi Video:
```typescript
const videoOptions = {
filePath: '/path/to/video.mp4',
duration: 30, // seconds
width: 1920,
height: 1080
};
await api.sendVideo(videoOptions, 'user-id', ThreadType.User);
```
#### Gửi Voice:
```typescript
const voiceOptions = {
filePath: '/path/to/audio.m4a',
duration: 15 // seconds
};
await api.sendVoice(voiceOptions, 'user-id', ThreadType.User);
```
## Quản Lý Bạn Bè
### Lấy danh sách bạn bè
```typescript
const friends = await api.getAllFriends();
console.log(friends);
```
### Tìm kiếm người dùng
```typescript
const users = await api.findUser('tên người dùng');
console.log(users);
```
### Gửi lời mời kết bạn
```typescript
await api.sendFriendRequest('user-id', 'Lời nhắn kèm theo');
```
### Chấp nhận lời mời kết bạn
```typescript
await api.acceptFriendRequest('user-id');
```
### Hủy lời mời kết bạn
```typescript
await api.undoFriendRequest('user-id');
```
### Xóa bạn bè
```typescript
await api.removeFriend('user-id');
```
### Chặn/bỏ chặn người dùng
```typescript
// Chặn
await api.blockUser('user-id');
// Bỏ chặn
await api.unblockUser('user-id');
```
## Quản Lý Nhóm
### Lấy danh sách nhóm
```typescript
const groups = await api.getAllGroups();
console.log(groups);
```
### Tạo nhóm mới
```typescript
const groupOptions = {
name: 'Tên nhóm',
members: ['user-id-1', 'user-id-2']
};
const newGroup = await api.createGroup(groupOptions);
```
### Thêm thành viên vào nhóm
```typescript
await api.addUserToGroup('group-id', ['user-id-1', 'user-id-2']);
```
### Xóa thành viên khỏi nhóm
```typescript
await api.removeUserFromGroup('group-id', 'user-id');
```
### Rời nhóm
```typescript
await api.leaveGroup('group-id');
```
### Thay đổi tên nhóm
```typescript
await api.changeGroupName('group-id', 'Tên mới');
```
### Thay đổi avatar nhóm
```typescript
await api.changeGroupAvatar('group-id', '/path/to/avatar.jpg');
```
### Chuyển quyền quản trị nhóm
```typescript
await api.changeGroupOwner('group-id', 'new-owner-id');
```
## Lắng Nghe Sự Kiện (Listener)
### Khởi tạo listener
```typescript
// Bắt đầu lắng nghe
await api.listener.start();
// Xử lý tin nhắn mới
api.listener.on('message', (message) => {
console.log('Tin nhắn mới:', message);
// Trả lời tự động
if (message.data.content === 'hello') {
api.sendMessage('Xin chào!', message.threadId, message.threadType);
}
});
// Xử lý sự kiện nhóm
api.listener.on('group_event', (event) => {
console.log('Sự kiện nhóm:', event);
});
// Xử lý sự kiện bạn bè
api.listener.on('friend_event', (event) => {
console.log('Sự kiện bạn bè:', event);
});
// Dừng lắng nghe
await api.listener.stop();
```
### Xử lý các loại sự kiện
```typescript
api.listener.on('message', (message) => {
switch (message.type) {
case 'text':
console.log('Tin nhắn văn bản:', message.data.content);
break;
case 'image':
console.log('Hình ảnh:', message.data.href);
break;
case 'video':
console.log('Video:', message.data.href);
break;
case 'file':
console.log('File:', message.data.fileName);
break;
}
});
```
## Tính Năng Nâng Cao
### Upload file đính kèm
```typescript
const uploadResult = await api.uploadAttachment(['/path/to/file.jpg'], 'thread-id', ThreadType.User);
console.log(uploadResult);
```
### Xem trước link
```typescript
const linkPreview = await api.parseLink('https://example.com');
console.log(linkPreview);
```
### Tạo poll/bình chọn
```typescript
const pollOptions = {
question: 'Bạn thích màu gì?',
options: ['Đỏ', 'Xanh', 'Vàng'],
multipleChoice: false
};
await api.createPoll(pollOptions, 'group-id');
```
### Tạo reminder
```typescript
const reminderOptions = {
content: 'Nhắc nhở họp',
time: new Date('2024-12-31T15:00:00'),
members: ['user-id-1', 'user-id-2']
};
await api.createReminder(reminderOptions, 'group-id');
```
### Reaction tin nhắn
```typescript
await api.addReaction('😍', {
messageId: 'message-id',
threadId: 'thread-id',
threadType: ThreadType.User
});
```
## Xử Lý Lỗi
```typescript
import { ZaloApiError } from 'zalo-personal-sdk';
try {
await api.sendMessage('Hello', 'user-id', ThreadType.User);
} catch (error) {
if (error instanceof ZaloApiError) {
console.error('Lỗi Zalo API:', error.message);
} else {
console.error('Lỗi khác:', error);
}
}
```
## Cấu Hình Nâng Cao
### Tùy chỉnh options
```typescript
const zalo = new Zalo({
selfListen: true, // Lắng nghe tin nhắn của chính mình
logLevel: 'info', // Mức độ log
apiVersion: 'v1' // Phiên bản API
});
```
### Custom API call
```typescript
const customResult = await api.custom({
url: '/custom/endpoint',
method: 'POST',
params: { custom: 'data' }
});
```
## Lưu Ý Quan Trọng
1. **Rate Limiting**: Không gửi quá nhiều tin nhắn trong thời gian ngắn để tránh bị Zalo chặn
2. **File Size**: Kiểm tra kích thước file trước khi gửi (max ~25MB)
3. **Cookie Expiry**: Cookie có thể hết hạn, cần xử lý việc đăng nhập lại
4. **Error Handling**: Luôn wrap API calls trong try-catch
5. **Thread Safety**: SDK không thread-safe, tránh gọi API đồng thời
## Ví Dụ Bot Đơn Giản
```typescript
import { Zalo, ThreadType } from 'zalo-personal-sdk';
const zalo = new Zalo();
const api = await zalo.login(credentials);
await api.listener.start();
api.listener.on('message', async (message) => {
const { threadId, threadType, data } = message;
if (data.content) {
const text = data.content.toLowerCase();
if (text === '/help') {
await api.sendMessage('Các lệnh có sẵn:\n/time - Xem giờ\n/weather - Xem thời tiết', threadId, threadType);
} else if (text === '/time') {
await api.sendMessage(`Bây giờ là: ${new Date().toLocaleString()}`, threadId, threadType);
} else if (text.startsWith('/weather')) {
await api.sendMessage('Chức năng thời tiết đang phát triển...', threadId, threadType);
}
}
});
console.log('Bot đang chạy...');
```
Đây là hướng dẫn cơ bản để sử dụng Zalo Personal SDK. Tham khao thêm các file example trong thư mục `examples/` để hiểu rõ hơn cách sử dụng.