# RedAI Automation Web SDK

TypeScript/JavaScript SDK cho RedAI Automation Web API - Tự động hóa Zalo Personal và messaging.

## 🚀 Tính Năng

- ✅ **Authentication**: QR Code login, Credentials login, Session management
- ✅ **Messaging**: Gửi tin nhắn text, hình ảnh, video, voice, sticker, file, link, card
- ✅ **Webhook Management**: Quản lý webhook listeners, thống kê, event history
- ✅ **Bulk Operations**: Batch check/add accounts to groups (Zalo Seeding)
- ✅ **Group Management**: Quản lý nhóm, thành viên, tạo/rời/giải tán nhóm
- ✅ **Friend Management**: Quản lý bạn bè, gửi/nhận lời mời kết bạn, block/unblock
- ✅ **Conversation Management**: Quản lý cuộc trò chuyện, pin/hide, lịch sử tin nhắn
- ✅ **User Info Management**: Lấy thông tin user, profile, kiểm tra tồn tại
- ✅ **Typed Webhook Events**: Type-safe webhook events với đầy đủ type definitions
- ✅ **Queue Job Types**: Cấu trúc job chuẩn khi đưa vào queue system

## 📦 Cài Đặt

```bash
npm install @redai/automation-web-sdk
```

## 🔧 Sử Dụng Cơ Bản

### Khởi tạo SDK

```typescript
import { AutomationWebClient } from '@redai/automation-web-sdk';

const client = new AutomationWebClient({
  baseUrl: 'http://localhost:3000',
  timeout: 30000,
  logging: true,
});
```

### Authentication

#### QR Code Login

```typescript
// Tạo QR Code
const qrResult = await client.auth.generateQRCode({
  userUuid: 'your-user-uuid',
  timeout: 300, // 5 phút
});

console.log('QR Code:', qrResult.qrCode);

// Chờ đăng nhập
const loginStatus = await client.auth.waitForQRLogin(qrResult.sessionId, {
  timeout: 300,
  pollInterval: 2000,
  onStatusChange: (status) => {
    console.log('Trạng thái:', status.status);
  },
});

if (loginStatus.status === 'success') {
  console.log('Đăng nhập thành công!', loginStatus.userData);
}
```

#### Credentials Login

```typescript
const loginResult = await client.auth.loginWithCredentials({
  userUuid: 'your-user-uuid',
  credentials: {
    cookie: [], // Zalo cookies từ browser
    imei: 'device-imei',
    userAgent: 'browser-user-agent',
    language: 'vi',
  },
  options: {
    selfListen: false,
    autoReconnect: true,
  },
});
```

### Messaging

#### Gửi tin nhắn text

```typescript
import { ThreadType } from '@redai/automation-web-sdk';

const result = await client.messaging.sendMessage({
  sessionId: 'your-session-id',
  threadId: 'target-user-id',
  threadType: ThreadType.USER,
  content: 'Xin chào từ SDK! 👋',
});
```

#### Gửi hình ảnh

```typescript
const result = await client.messaging.sendImage({
  sessionId: 'your-session-id',
  threadId: 'target-user-id',
  threadType: ThreadType.USER,
  imageUrl: 'https://example.com/image.jpg',
  caption: 'Hình ảnh đẹp!',
});
```

#### Gửi video

```typescript
const result = await client.messaging.sendVideo({
  sessionId: 'your-session-id',
  threadId: 'target-user-id',
  threadType: ThreadType.USER,
  videoUrl: 'https://example.com/video.mp4',
  caption: 'Video thú vị!',
});
```

### Webhook Events

```typescript
// Lắng nghe tin nhắn đến
client.onMessageReceived(async (event) => {
  console.log('Tin nhắn mới:', event.data.eventData);
});

// Lắng nghe tin nhắn đã gửi
client.onMessageSent(async (event) => {
  console.log('Đã gửi tin nhắn:', event.data.eventData);
});

// Lắng nghe sự kiện typing
client.onTyping(async (event) => {
  console.log('Đang gõ:', event.data.eventData);
});

// Lắng nghe reaction
client.onMessageReaction(async (event) => {
  console.log('Reaction:', event.data.eventData);
});

// Lắng nghe lỗi
client.onError(async (event) => {
  console.error('Lỗi:', event.data.eventData);
});
```

### Session Management

```typescript
// Lấy danh sách session
const sessions = await client.auth.getSessions('user-uuid');

// Thống kê session
const stats = await client.auth.getSessionStatistics('user-uuid');

// Dọn dẹp session hết hạn
const cleanup = await client.auth.cleanupExpiredSessions('user-uuid');

// Debug session
const debugInfo = await client.auth.debugSession('session-id');

// Refresh session
const refreshed = await client.auth.refreshSession('session-id');
```

## 📚 API Reference

### AutomationWebClient

#### Constructor

```typescript
new AutomationWebClient(config: AutomationWebConfig)
```

**Config Options:**
- `baseUrl`: URL của automation-web API
- `timeout`: Timeout cho requests (ms)
- `retryCount`: Số lần retry khi lỗi
- `retryDelay`: Delay giữa các retry (ms)
- `apiKey`: API key (nếu cần)
- `userAgent`: Custom user agent
- `logging`: Bật/tắt logging

#### Services

- `client.auth`: Authentication service
- `client.messaging`: Messaging service
- `client.webhook`: Webhook management service
- `client.bulk`: Bulk operations service (Zalo Seeding)
- `client.groups`: Group management
- `client.friends`: Friend management
- `client.conversations`: Conversation management
- `client.userInfo`: User info management
- `client.profile`: Profile & Account management

### AuthService

#### Methods

- `generateQRCode(request)`: Tạo QR Code đăng nhập
- `getLoginStatus(sessionId, timeout?)`: Kiểm tra trạng thái đăng nhập
- `waitForQRLogin(sessionId, options)`: Chờ QR Code được scan
- `loginWithCredentials(request)`: Đăng nhập bằng credentials
- `getSessions(userUuid)`: Lấy danh sách session
- `deleteSession(sessionId)`: Xóa session
- `bulkDeleteSessions(request)`: Xóa nhiều session
- `debugSession(sessionId)`: Debug thông tin session
- `refreshSession(sessionId)`: Refresh session
- `getSessionStatistics(userUuid)`: Thống kê session
- `cleanupExpiredSessions(userUuid)`: Dọn dẹp session hết hạn

### MessagingService

#### Methods

- `sendMessage(request)`: Gửi tin nhắn text
- `sendImage(request)`: Gửi hình ảnh
- `sendVideo(request)`: Gửi video
- `sendVoice(request)`: Gửi voice
- `sendSticker(request)`: Gửi sticker
- `sendFile(request)`: Gửi file
- `sendLink(request)`: Gửi link
- `forwardMessage(request)`: Forward tin nhắn
- `deleteMessage(request)`: Xóa tin nhắn
- `undoMessage(request)`: Undo tin nhắn
- `addReaction(request)`: Thêm reaction
- `markAsDelivered(request)`: Đánh dấu đã nhận
- `markAsSeen(request)`: Đánh dấu đã xem

## 🔧 Configuration

### Environment Variables

```bash
AUTOMATION_WEB_BASE_URL=http://localhost:3000
AUTOMATION_WEB_TIMEOUT=30000
AUTOMATION_WEB_RETRY_COUNT=3
AUTOMATION_WEB_LOGGING=true
```

### TypeScript Configuration

SDK được viết bằng TypeScript và cung cấp đầy đủ type definitions.

```typescript
import { 
  AutomationWebClient,
  ThreadType,
  Urgency,
  WebhookEventType,
  LoginStatus,
  MessageType 
} from '@redai/automation-web-sdk';
```

## 🚨 Error Handling

```typescript
import { HttpError, ValidationError } from '@redai/automation-web-sdk';

try {
  await client.messaging.sendMessage(request);
} catch (error) {
  if (error instanceof HttpError) {
    console.error('HTTP Error:', error.status, error.message);
  } else if (error instanceof ValidationError) {
    console.error('Validation Error:', error.field, error.message);
  } else {
    console.error('Unknown Error:', error);
  }
}
```

## 📝 Examples

Xem thêm examples trong thư mục `/examples`:

- [Basic Usage](./examples/basic-usage.ts)
- [Messaging Examples](./examples/messaging.ts)
- [Webhook Handling](./examples/webhook-handling.ts)

### GroupService

#### Methods

- `getAllGroups(request)`: Lấy tất cả groups của user
- `getGroupInfo(request)`: Lấy thông tin chi tiết của group
- `createGroup(request)`: Tạo group mới
- `addMembersToGroup(request)`: Thêm members vào group
- `removeMemberFromGroup(request)`: Remove member khỏi group
- `changeGroupName(request)`: Đổi tên group
- `getGroupMembers(request)`: Lấy danh sách members của group
- `leaveGroup(request)`: Rời nhóm
- `disperseGroup(request)`: Giải tán nhóm (chỉ owner)
- `joinGroup(request)`: Tham gia nhóm qua link

#### Example

```typescript
// Lấy tất cả groups
const allGroups = await client.groups.getAllGroups({ sessionId });

// Tạo group mới
const newGroup = await client.groups.createGroup({
  sessionId,
  groupName: 'Test Group',
  memberIds: ['friend-id-1', 'friend-id-2'],
});

// Thêm members
await client.groups.addMembersToGroup({
  sessionId,
  groupId: newGroup.result.groupId,
  memberIds: ['friend-id-3'],
});
```

### FriendService

#### Methods

- `getAllFriends(request)`: Lấy tất cả friends
- `searchFriends(request)`: Tìm kiếm friends theo keyword
- `getFriendsInfo(request)`: Lấy thông tin chi tiết friends
- `getOnlineFriends(request)`: Lấy friends đang online
- `getFriendsStats(request)`: Lấy thống kê friends
- `sendFriendRequest(request)`: Gửi lời mời kết bạn
- `acceptFriendRequest(request)`: Chấp nhận lời mời kết bạn
- `getReceivedFriendRequests(request)`: Lấy lời mời nhận được
- `getSentFriendRequests(request)`: Lấy lời mời đã gửi
- `undoFriendRequest(request)`: Hủy lời mời đã gửi
- `removeFriend(request)`: Xóa bạn bè
- `findUser(request)`: Tìm user theo số điện thoại
- `blockUser(request)`: Chặn user
- `unblockUser(request)`: Bỏ chặn user
- `changeFriendAlias(request)`: Thay đổi biệt danh
- `removeFriendAlias(request)`: Xóa biệt danh
- `getAliasList(request)`: Lấy danh sách biệt danh
- `getLastOnline(request)`: Lấy thông tin last online
- `getOwnId(request)`: Lấy ID của chính mình
- `fetchAccountInfo(request)`: Lấy thông tin tài khoản

#### Example

```typescript
// Lấy tất cả friends
const friends = await client.friends.getAllFriends({ sessionId });

// Gửi lời mời kết bạn
await client.friends.sendFriendRequest({
  sessionId,
  userId: 'target-user-id',
  message: 'Xin chào! Kết bạn nhé!',
});

// Lấy thống kê friends
const stats = await client.friends.getFriendsStats({ sessionId });
console.log(`Total friends: ${stats.result.totalFriends}`);
```

### ConversationService

#### Methods

- `getConversations(request)`: Lấy danh sách conversations
- `getMessageHistory(request)`: Lấy lịch sử tin nhắn
- `pinConversation(request)`: Pin/Unpin conversation
- `hideConversation(request)`: Hide/Unhide conversation
- `deleteChat(request)`: Xóa chat

#### Example

```typescript
// Lấy tất cả conversations
const conversations = await client.conversations.getConversations({
  sessionId,
  limit: 20,
  type: ConversationType.ALL,
});

// Lấy lịch sử tin nhắn
const history = await client.conversations.getMessageHistory({
  sessionId,
  threadId: 'conversation-id',
  limit: 50,
});

// Pin conversation
await client.conversations.pinConversation({
  sessionId,
  threadId: 'conversation-id',
  type: ThreadType.USER,
  isPinned: true,
});
```

### UserInfoService

#### Methods

- `getUserInfo(request)`: Lấy thông tin user (POST)
- `getSingleUserInfo(request)`: Lấy thông tin user đơn lẻ (GET)
- `getBasicUserInfo(request)`: Lấy thông tin cơ bản
- `checkUserExists(request)`: Kiểm tra user có tồn tại
- `getMultipleUsersInfo(request)`: Lấy thông tin nhiều users

#### Example

```typescript
// Lấy thông tin user
const userInfo = await client.userInfo.getUserInfo({
  sessionId,
  userId: 'target-user-id',
});

// Kiểm tra user có tồn tại
const exists = await client.userInfo.checkUserExists({
  sessionId,
  userId: 'target-user-id',
});

// Lấy thông tin nhiều users
const multipleUsers = await client.userInfo.getMultipleUsersInfo({
  sessionId,
  userIds: ['user1', 'user2', 'user3'],
});
```

### ProfileService

#### Methods

- `fetchAccountInfo(request)`: Lấy thông tin tài khoản
- `changeAccountAvatar(request)`: Thay đổi avatar tài khoản
- `deleteAvatar(request)`: Xóa avatar
- `reuseAvatar(request)`: Sử dụng lại avatar
- `getAvatarList(request)`: Lấy danh sách avatar
- `updateProfile(request)`: Cập nhật profile

#### Example

```typescript
import { Gender } from '@redai/automation-web-sdk';

// Lấy thông tin tài khoản
const accountInfo = await client.profile.fetchAccountInfo({
  sessionId,
});

// Cập nhật profile
const updateResult = await client.profile.updateProfile({
  sessionId,
  name: 'Tên mới',
  dob: '1990-01-01',
  gender: Gender.Male,
});

// Thay đổi avatar
const changeAvatarResult = await client.profile.changeAccountAvatar({
  sessionId,
  avatarSource: {
    data: 'base64-image-data',
    filename: 'avatar.jpg',
    metadata: {
      width: 200,
      height: 200,
      size: 15000,
      type: 'image/jpeg',
    },
  },
});

// Lấy danh sách avatar
const avatarList = await client.profile.getAvatarList({
  sessionId,
});

// Sử dụng lại avatar cũ
const reuseResult = await client.profile.reuseAvatar({
  sessionId,
  avatarId: 'avatar-id',
});
```

### Typed Webhook Events

SDK cung cấp type-safe webhook events 100% tương thích với `@warriorteam/zalo-personal`:

#### Event Types

- `Message`: Tin nhắn (UserMessage | GroupMessage)
- `Typing`: Sự kiện đang gõ
- `Reaction`: Phản ứng tin nhắn
- `SeenMessage`: Tin nhắn đã xem
- `DeliveredMessage`: Tin nhắn đã gửi
- `FriendEvent`: Sự kiện bạn bè
- `GroupEvent`: Sự kiện nhóm
- `Undo`: Sự kiện thu hồi tin nhắn

#### Typed Event Handlers

```typescript
import {
  AutomationWebClient,
  Message,
  Typing,
  Reaction,
  ThreadType,
  FriendEventType,
  GroupEventType,
  Reactions,
} from 'redai-automation-web-sdk';

const client = new AutomationWebClient({
  baseURL: 'http://localhost:3000',
});

// Message events với type safety
client.onTypedMessage((message: Message) => {
  console.log(`Message from ${message.data.uidFrom}: ${message.data.content}`);
  console.log(`Thread type: ${message.type === ThreadType.USER ? 'User' : 'Group'}`);
  console.log(`Is self: ${message.isSelf}`);
});

// Typing events
client.onTypedTyping((typing: Typing) => {
  console.log(`${typing.data.uid} is typing in ${typing.threadId}`);
});

// Reaction events với emoji decoding
client.onTypedReaction((reaction: Reaction) => {
  const reactionName = Object.entries(Reactions)
    .find(([_, value]) => value === reaction.data.content.rIcon)?.[0];
  console.log(`Reaction: ${reactionName} from ${reaction.data.uidFrom}`);
});

// Friend events với type discrimination
client.onTypedFriendEvent((friendEvent: FriendEvent) => {
  switch (friendEvent.type) {
    case FriendEventType.REQUEST:
      console.log('Friend request received');
      break;
    case FriendEventType.ADD:
      console.log('Friend added');
      break;
    // ... other cases
  }
});

// Group events với detailed data
client.onTypedGroupEvent((groupEvent: GroupEvent) => {
  switch (groupEvent.type) {
    case GroupEventType.JOIN:
      console.log('Member joined group');
      break;
    case GroupEventType.LEAVE:
      console.log('Member left group');
      break;
    // ... other cases
  }
});
```

#### Enums & Constants

```typescript
// Thread types
ThreadType.USER = 0
ThreadType.GROUP = 1

// Friend event types
FriendEventType.ADD = 0
FriendEventType.REMOVE = 1
FriendEventType.REQUEST = 2
// ... và nhiều hơn

// Group event types
GroupEventType.JOIN = 1
GroupEventType.LEAVE = 2
GroupEventType.REMOVE_MEMBER = 3
// ... và nhiều hơn

// Reaction emojis
Reactions.HEART = "/-heart"
Reactions.LIKE = "/-strong"
Reactions.HAHA = ":>"
// ... và nhiều hơn
```

### Queue Job Types

SDK cung cấp cấu trúc job chuẩn 100% tương thích với automation-web queue system:

#### Job Structure

```typescript
import {
  ZaloWebhookEvent,
  ZaloWebhookEventType,
  WebhookQueueJob,
  MessageQueueJob,
  JobPriority,
  JobStatus,
} from 'redai-automation-web-sdk';

// Base webhook event structure
interface BaseZaloWebhookEvent {
  sessionId: string;
  userUuid: string;
  timestamp: number;
  eventType: ZaloWebhookEventType;
  metadata?: Record<string, any>;
}

// Queue job structure
interface BaseQueueJob<T = any> {
  id?: string;
  name: string;
  data: T;
  opts?: {
    priority?: JobPriority;
    delay?: number;
    attempts?: number;
    backoff?: {
      type: 'fixed' | 'exponential';
      delay: number;
    };
    removeOnComplete?: number | boolean;
    removeOnFail?: number | boolean;
  };
}
```

#### Event Types (100+ events)

```typescript
// Message events (44 events)
ZaloWebhookEventType.TEXT_MESSAGE_SENT_TO_USER
ZaloWebhookEventType.TEXT_MESSAGE_RECEIVED_FROM_GROUP
ZaloWebhookEventType.IMAGE_MESSAGE_SENT_TO_USER
// ... và nhiều hơn

// Friend events (13 events)
ZaloWebhookEventType.FRIEND_EVENT_ADD
ZaloWebhookEventType.FRIEND_EVENT_REQUEST
ZaloWebhookEventType.FRIEND_EVENT_BLOCK
// ... và nhiều hơn

// Group events (23 events)
ZaloWebhookEventType.GROUP_EVENT_JOIN
ZaloWebhookEventType.GROUP_EVENT_LEAVE
ZaloWebhookEventType.GROUP_EVENT_ADD_ADMIN
// ... và nhiều hơn

// System events (17 events)
ZaloWebhookEventType.CONNECTION_STATUS_CONNECTED
ZaloWebhookEventType.ERROR_SYSTEM
ZaloWebhookEventType.UPLOAD_ATTACHMENT_COMPLETED
// ... và nhiều hơn
```

#### Usage Example

```typescript
import {
  Message,
  ZaloTextMessageEvent,
  MessageQueueJob,
  JobPriority,
  isMessageEvent,
  getEventCategory,
} from 'redai-automation-web-sdk';

// Tạo message event job
function createMessageJob(message: Message): MessageQueueJob {
  const messageEvent: ZaloTextMessageEvent = {
    sessionId: 'session123',
    userUuid: 'user-uuid-123',
    timestamp: Date.now(),
    eventType: ZaloWebhookEventType.TEXT_MESSAGE_RECEIVED_FROM_USER,
    data: message, // Sử dụng trực tiếp Message từ SDK
  };

  return {
    name: 'message-event',
    data: messageEvent,
    opts: {
      priority: JobPriority.NORMAL,
      attempts: 3,
      backoff: {
        type: 'exponential',
        delay: 2000,
      },
    },
  };
}

// Xử lý job với type guards
function processJob(job: WebhookQueueJob): void {
  const event = job.data;

  if (isMessageEvent(event)) {
    const message = event.data; // Trực tiếp Message từ SDK
    console.log(`Message: ${message.data.content}`);
    console.log(`Thread: ${message.threadId}`);
    console.log(`Is Self: ${message.isSelf}`);
  }

  console.log(`Category: ${getEventCategory(event.eventType)}`);
}
```

#### Helper Functions

```typescript
// Type guards
isMessageEvent(event) // Check if message event
isTypingEvent(event)  // Check if typing event
isFriendEvent(event)  // Check if friend event
isGroupEvent(event)   // Check if group event
isSystemEvent(event)  // Check if system event

// Event analysis
getEventCategory(eventType)      // Get event category
getThreadTypeFromEvent(eventType) // Get thread type (user/group)
getActorTypeFromEvent(eventType)  // Get actor type (self/other)
```

## 🤝 Contributing

1. Fork repository
2. Tạo feature branch: `git checkout -b feature/amazing-feature`
3. Commit changes: `git commit -m 'Add amazing feature'`
4. Push to branch: `git push origin feature/amazing-feature`
5. Tạo Pull Request

## 📄 License

MIT License - xem [LICENSE](LICENSE) file.

## 🆘 Support

- GitHub Issues: [https://github.com/redai/automation-web-sdk/issues](https://github.com/redai/automation-web-sdk/issues)
- Documentation: [https://docs.redai.com/automation-web-sdk](https://docs.redai.com/automation-web-sdk)
- Discord: [https://discord.gg/redai](https://discord.gg/redai)

## 🗺️ Roadmap

- [x] Authentication & Session Management
- [x] Basic Messaging
- [x] Webhook Events
- [x] Group Management
- [x] Friend Management
- [x] Bulk Operations
- [x] Conversation Management
- [x] User Info Management
- [x] Typed Webhook Events (100% tương thích với zalo-personal-sdk)
- [x] Queue Job Types (100% tương thích với automation-web queue system)
- [ ] File Upload Support
- [ ] Rate Limiting
- [ ] Retry Mechanisms
- [ ] Browser Support
- [ ] React Native Support

---

Made with ❤️ by RedAI Team
