# Đối chiếu tính năng: zca-js 2.1.2 vs. worker hiện tại

Dựa trên mã nguồn thật của `zca-js@2.1.2` (giải nén gói npm, không phải chỉ đọc docs) và tài
liệu https://tdung.gitbook.io/zca-js. So sánh với những gì `worker/src/zalo` đang gọi tới
(`zalo-session.ts`, `session-manager.ts`, `http/routes/account.route.ts`).

> **Cập nhật 03/08/2026**: đã triển khai xong đợt 1 các mục ưu tiên ở mục 3 (cũ) - xem
> "Đã triển khai đợt 2" ngay dưới đây. Phần "1. Đã tận dụng" và "2. Chưa dùng tới" bên dưới
> giữ nguyên như bản đo gốc, chỉ đánh dấu lại những gì đã chuyển trạng thái.

## 0. Đã triển khai đợt 2 (03/08/2026)

### Listener / sự kiện realtime — thêm 3/15 sự kiện
- **`reaction`** — worker chuẩn hoá (dịch mã icon Zalo về 1 trong 6 icon kinh điển nếu khớp),
  đẩy về Laravel qua `/api/worker/events`, ghi vào bảng `zalo_message_reactions`
  (`ZaloEventIngestService::handleReaction`). Tin trả về cho giao diện (`getMessages`) giờ
  kèm mảng `reactions` - UI vẽ chip "👍 3" thật dưới mỗi bong bóng, khác nút thả cảm xúc vốn
  chỉ phản ánh lựa chọn của chính mình.
- **`undo`** — đánh dấu `is_recalled`/`recalled_at` trên đúng dòng `zalo_messages`, giao diện
  hiện "Tin nhắn đã bị thu hồi" thay nội dung/đính kèm cũ.
- **`group_event`** — các loại `update`/`update_avatar` vá thẳng tên/avatar vào cache
  `zalo_contacts` từ dữ liệu Zalo gửi kèm sự kiện (không cần hỏi lại worker); mọi loại khác
  (thêm/xoá thành viên, đổi quyền admin...) chỉ bỏ cache danh bạ để lần mở "Danh bạ" tiếp
  theo thấy đúng - đúng gợi ý "giữ cache tên/avatar nhóm luôn đúng, khỏi phải poll định kỳ".
- **`friend_event`** — loại `REQUEST` ghi vào bảng `zalo_friend_requests` (lời mời đến, xem
  được và chấp nhận/từ chối ngay trên giao diện); `ADD`/`REMOVE`/`REJECT_REQUEST`/
  `UNDO_REQUEST` cập nhật trạng thái lời mời và bỏ cache danh bạ.

Đường truyền mới: worker → `eventClient` (`worker/src/infrastructure/event-client.ts`, cùng
công thức HMAC với `callbackClient`) → `POST /api/worker/events` →
`ZaloWorkerCallbackController::events()` → `ZaloEventIngestService`. Chưa làm:
`typing`/`seen_messages`/`delivered_messages`/`old_reactions`/`upload_attachment`/
`cipher_key`/`disconnected` (xem lại mục 2 bên dưới - vẫn còn nguyên).

### API nhắn tin/tương tác — đã gọi thêm
`sendSticker`, `sendCard`, `sendVideo`, `sendBankCard`, `deleteMessage`, `undo` (tự thu hồi),
`forwardMessage` (giới hạn: chỉ chuyển tiếp được nội dung CHỮ - `ForwardMessagePayload` của
zca-js không nhận ảnh/file gốc). Giao diện: menu chuột phải trên tin nhắn có thêm "Chuyển
tiếp"/"Thu hồi"/"Xoá phía tôi"; nút "➕" cạnh ô soạn tin mở form nhanh gửi
sticker/danh thiếp/video (URL)/thẻ ngân hàng.

Vẫn CHƯA gọi: `sendVoice`, `sendLink`, `sendTypingEvent`, `sendSeenEvent`,
`sendDeliveredEvent` (báo trạng thái CỦA CHÍNH MÌNH, khác `seen_messages`/`delivered_messages`
là đọc trạng thái đối phương).

### Quản lý nhóm — từ "bỏ trắng" thành có bộ thao tác cơ bản
`createGroup`, `changeGroupName`, `changeGroupAvatar`, `addUserToGroup`,
`removeUserFromGroup`, và `getGroupInfo` + `getGroupMembersInfo` ghép lại thành
`getGroupMembers` (không có sẵn trong zca-js, phải tra 2 lần: id thành viên rồi tên/avatar).
Giao diện: nút "⚙ Nhóm" ở đầu khung chat (chỉ hiện với hội thoại nhóm) mở bảng đổi tên/avatar,
thêm thành viên theo ID, đá thành viên; nút "Tạo nhóm" ở màn Danh bạ.

Vẫn CHƯA làm: `changeGroupOwner`, `addGroupDeputy`/`removeGroupDeputy`, `disperseGroup`,
`updateGroupSettings`, `getPendingGroupMembers`/`reviewPendingMemberRequest`,
`addGroupBlockedMember`/`removeGroupBlockedMember`, mọi API `*GroupLink*`,
`upgradeGroupToCommunity`.

### Bạn bè — từ "chưa có gì" thành đủ vòng đời lời mời cơ bản
`sendFriendRequest`, `acceptFriendRequest`, `rejectFriendRequest`, `undoFriendRequest`,
`removeFriend`, `findUser`, `getFriendRequestStatus`. Giao diện: nút "Kết bạn" ở màn Danh bạ (tra số điện thoại ra
người, bấm vào kết quả để mở hội thoại rồi gửi lời mời từ thanh trên ô soạn - giống Zalo web),
thẻ người gửi trong nhóm (bấm tên/ảnh/thẻ @ để kết bạn nhanh hoặc nhắn riêng), danh sách
"Lời mời kết bạn" (đổ từ bảng `zalo_friend_requests`, nạp từ sự kiện `friend_event`) với nút
Chấp nhận/Từ chối ngay tại chỗ, nút "Xoá bạn" trên từng dòng ở tab Bạn bè.

Vẫn CHƯA làm: `blockUser`/`unblockUser`, `changeFriendAlias`,
`getSentFriendRequest`, `findUserByUsername`, `getMultiUsersByPhones`,
`getCloseFriends`, `getFriendOnlines`, `getFriendRecommendations`.

### Thay đổi hạ tầng đi kèm
- Migration mới: `zalo_messages.is_recalled`/`recalled_at`, bảng `zalo_message_reactions`,
  bảng `zalo_friend_requests`.
- `worker/.env.example` và `docker-compose.yml` có thêm biến `LARAVEL_EVENT_URL` (bắt buộc
  cấu hình để đường sự kiện hoạt động - trống thì worker vẫn nhận sự kiện từ Zalo nhưng
  không gửi đi đâu, y hệt cơ chế của `LARAVEL_CALLBACK_URL`/`LARAVEL_MESSAGE_URL`).

## 1. Đã tận dụng

### Đăng nhập / phiên
- `zalo.login()` — đăng nhập lại bằng cookie đã lưu (`restore`).
- `zalo.loginQR()` — luồng quét QR đầy đủ (sinh mã, hết hạn, quét, xác nhận, lấy credential).
- Đăng nhập bằng Chrome thật rồi mượn cookie (`browser-login.ts`) — không phải API của
  zca-js, là lối vòng tự chế khi luồng QR chuẩn không quét được.
- `getOwnId()`.
- `getCookie` gián tiếp (lưu lại `cookie` từ sự kiện `GotLoginInfo` để tái dùng).

### Listener / sự kiện realtime
zca-js có 15 sự kiện (`connected`, `disconnected`, `closed`, `error`, `typing`, `message`,
`old_messages`, `seen_messages`, `delivered_messages`, `reaction`, `old_reactions`,
`upload_attachment`, `undo`, `friend_event`, `group_event`, `cipher_key`).

Đang dùng: **`connected`, `message`, `old_messages`, `error`, `closed`**.

- `listener.requestOldMessages()` — xin lại lịch sử chat 1-1 (đường duy nhất bù dữ liệu mất
  lúc đứt WebSocket, vì `getGroupChatHistory` đã chết).
- `listener.start({ retryOnClose: true })` + tự viết cơ chế backoff/reconnect riêng vì
  `retryCount` nội bộ của thư viện không reset được.

### Nhắn tin
- `sendMessage()` — text + đính kèm (ảnh/file, đoán phần mở rộng từ mime) + `quote` (trả lời
  tin).
- `addReaction()` — thả cảm xúc lên tin đã có.

### Tra cứu
- `getAllFriends()`, `getAllGroups()` — dựng màn "Danh bạ".
- `getUserInfo()`, `getGroupInfo()` — tên/ảnh đại diện theo lô id, kể cả người lạ/thành viên
  nhóm không có trong danh bạ.
- `getHiddenConversations()` — vì Zalo không bắn sự kiện khi ẩn/bỏ ẩn hội thoại, phải poll.
- `getStickersDetail()` — tra URL ảnh sticker, có cache trong process.
- `getGroupChatHistory()` — **đã gọi nhưng endpoint phía Zalo trả 404** (đo 01/08/2026), giữ
  code lại chờ Zalo mở lại chứ chưa hoạt động.

## 2. zca-js có nhưng project chưa dùng tới

### Sự kiện realtime bị bỏ qua
| Sự kiện | Zalo báo gì | Trạng thái |
|---|---|---|
| `reaction` | Ai vừa react vào tin nào, icon gì | ✅ Đã làm (03/08/2026) — xem mục 0 |
| `undo` | Tin bị thu hồi | ✅ Đã làm (03/08/2026) — xem mục 0 |
| `group_event` | Thành viên vào/ra, đổi tên nhóm, đổi phó nhóm... | ✅ Đã làm (03/08/2026) — xem mục 0 |
| `friend_event` | Có lời mời kết bạn, được chấp nhận... | ✅ Đã làm (03/08/2026) — xem mục 0 |
| `seen_messages` | Đối phương đã xem tới đâu | Chưa làm — không có "đã xem" trên giao diện |
| `delivered_messages` | Tin đã tới máy đối phương | Chưa làm — không có trạng thái "đã nhận" |
| `typing` | Ai đang gõ | Chưa làm — không có báo "đang soạn tin..." |
| `old_reactions` | Lịch sử reaction cũ | Chưa làm — đồng bộ reaction tương tự `requestOldMessages` |
| `upload_attachment` | Tiến độ/URL file khi Zalo xử lý đính kèm | Chưa làm |

### API nhắn tin/tương tác
- ✅ `sendSticker`, `sendCard` (danh thiếp), `sendVideo`, `sendBankCard`, `deleteMessage`,
  `undo` (tự thu hồi), `forwardMessage` — đã gọi (03/08/2026), xem mục 0.
- Vẫn chưa gọi: `sendVoice`, `sendLink`, `sendTypingEvent`, `sendSeenEvent`,
  `sendDeliveredEvent` — báo "đang gõ"/"đã xem" của chính tài khoản mình cho đối phương thấy.

### Quản lý nhóm
✅ `createGroup`, `changeGroupName`, `changeGroupAvatar`, `addUserToGroup`,
`removeUserFromGroup`, `getGroupMembersInfo` (ghép với `getGroupInfo`) — đã gọi (03/08/2026),
xem mục 0.

Vẫn chưa làm: `changeGroupOwner`, `addGroupDeputy`, `removeGroupDeputy`,
`disperseGroup`, `updateGroupSettings`, `getPendingGroupMembers`,
`reviewPendingMemberRequest`, `addGroupBlockedMember`/`removeGroupBlockedMember`,
`getGroupLinkInfo`/`getGroupLinkDetail`/`enableGroupLink`/`disableGroupLink`/`joinGroupLink`,
`upgradeGroupToCommunity`.

### Bạn bè
✅ `sendFriendRequest`, `acceptFriendRequest`, `rejectFriendRequest`, `undoFriendRequest`,
`removeFriend` — đã gọi (03/08/2026), xem mục 0.

Vẫn chưa làm: `blockUser`/`unblockUser`, `changeFriendAlias`, `getFriendRequestStatus`,
`getSentFriendRequest`, `findUser`/`findUserByUsername`, `getMultiUsersByPhones`,
`getCloseFriends`, `getFriendOnlines`, `getFriendRecommendations`.

### Poll / Nhắc việc / Ghi chú / Bảng (Board)
`createPoll`, `addPollOptions`, `votePoll`, `lockPoll`, `getPollDetail`, `sharePoll`,
`createReminder`, `editReminder`, `removeReminder`, `getReminder`, `getListReminder`,
`getReminderResponses`, `createNote`, `editNote`, `getListBoard`, `getFriendBoardList` —
toàn bộ nhóm tính năng "công cụ nhóm" của Zalo (bình chọn, nhắc việc, ghi chú, bảng tin)
chưa đụng tới.

### Cài đặt tài khoản / tuỳ biến
`updateProfile`, `updateProfileBio`, `changeAccountAvatar`/`deleteAvatar`/`reuseAvatar`,
`getAvatarList`, `updateSettings`/`getSettings`, `updateLang`, `updateActiveStatus`,
`lastOnline`, `setMute`/`getMute`, `setPinnedConversations`/`getPinConversations`,
`setHiddenConversations`/`updateHiddenConversPin`/`resetHiddenConversPin` (worker mới chỉ
*đọc*, chưa *ghi* danh sách ẩn), `getArchivedChatList`/`updateArchivedChatList`,
`addUnreadMark`/`removeUnreadMark`/`getUnreadMark`, `getLabels`/`updateLabels`,
`getAliasList`, `blockViewFeed`, `updateAutoDeleteChat`/`getAutoDeleteChat`.

### Trả lời tự động / tin nhắn nhanh
`createAutoReply`, `updateAutoReply`, `deleteAutoReply`, `getAutoReplyList`,
`addQuickMessage`, `updateQuickMessage`, `removeQuickMessage`, `getQuickMessageList` — zca-js
có sẵn cơ chế auto-reply/quick-message cấp tài khoản Zalo, độc lập với AI agent tự viết
trong project.

### Bán hàng / doanh nghiệp (ZBusiness)
`createCatalog`, `updateCatalog`, `deleteCatalog`, `getCatalogList`,
`createProductCatalog`, `updateProductCatalog`, `deleteProductCatalog`,
`getProductCatalogList`, `uploadProductPhoto`, `getBizAccount` — chỉ liên quan nếu tài khoản
Zalo là tài khoản kinh doanh.

### Khác
- `parseLink` — bóc metadata link chia sẻ (preview khi dán link).
- `sendReport` — báo cáo vi phạm.
- `getContext` — lấy thông tin phiên thô.
- `getQR`/`getFullAvatar`/`getAvatarUrlProfile` — tiện ích ảnh.
- `custom` — gọi thẳng endpoint Zalo tuỳ ý khi API dựng sẵn chưa phủ tới.
- `keepAlive` — múc riêng giữ phiên (worker đang dựa vào `retryOnClose` + reconnect tự viết
  thay vì API này).

## 3. Gợi ý ưu tiên nếu muốn mở rộng tiếp

Đợt 1 (mục này) đã xong toàn bộ ở đợt triển khai 03/08/2026 — xem mục 0. Gợi ý kế tiếp, theo
thứ tự chi phí/lợi ích:

1. **`seen_messages`/`delivered_messages`** — nếu giao diện cần hiển thị trạng thái đã
   xem/đã nhận.
2. **`typing` + `sendTypingEvent`** — báo "đang gõ..." hai chiều.
3. **`getPendingGroupMembers`/`reviewPendingMemberRequest`** — nếu nhóm cần duyệt thành viên
   thay vì thêm thẳng.
4. **`blockUser`/`unblockUser`** — thường đi kèm nhu cầu quản lý bạn bè đã có.

Những mục còn lại (poll/reminder/board, ZBusiness, cài đặt tài khoản sâu, quản lý nhóm nâng
cao như phó nhóm/link mời) chỉ nên làm khi có yêu cầu nghiệp vụ cụ thể — bám đúng nguyên tắc
"không xây trước khi cần" của project.
