LineGroup 規格說明書
項目名稱: Aile
範圍: Gateway Line 群組事件 → tenant → room(lineGroup)
最後更新: 2026-06-13
版本: v2.0 — 結合代碼實現的完整規格
1. 概述
LineGroup 是 Aile 針對 LINE 渠道「群組聊天」場景設計的專用聊天室類型。與私聊 services 聊天室不同,LineGroup 以群為單位管理 LINE 群組內的成員、消息和外發路由。
1.1 設計目標
| 目標 | 說明 |
|---|---|
| 一個群一個房 | 一個 serviceNumberId + chat.code 只對應一個啟用中的 lineGroup 聊天室 |
| 真實發言人 | 群消息顯示真實發言人頭像/暱稱,不是「群本身」 |
| 群級路由 | 對外回發消息只向群發一次,不按成員逐個外發 |
| 持久化關係 | 持久化群成員與聊天室的關係,支援成員展示與歸屬追蹤 |
1.2 非目標
- 不創建
ServiceSession(不走客服會話流程) - 不走機器人歡迎語、自動接待、會話超時分配邏輯
- 不要求機器人入群前回補歷史群成員
2. 資料模型
2.1 聊天室類型
// aile-api/aile-room-api/.../constant/RoomType.java
public static final String LineGroup = "lineGroup";
RoomModel 中的關鍵字段(用於 LineGroup):
| 字段 | 來源 | 說明 |
|---|---|---|
type | 固定 "lineGroup" | 聊天室類型標識 |
serviceNumberId | webhook.to.code | 歸屬服務號 |
name | webhook.chat.name | 群組名稱 |
avatar | webhook.chat.pictureUrl | 群組頭像 |
externalRoomId | webhook.chat.code | LINE 群組唯一 ID |
channel | "Line" | 來源渠道 |
2.2 LineGroupContactRelationModel
MongoDB 集合:aile.tenant.contact.linegroup.relation
此模型記錄「LINE 群組 ↔ 客戶(聯繫人)」的多對多關聯。
// aile-api/aile-tenant-api/.../model/servicenumber/LineGroupContactRelationModel.java
@Document("aile.tenant.contact.linegroup.relation")
@CompoundIndexes({
@CompoundIndex(name = "serviceNumberId_1_lineGroupId_1_scopeId_1",
def = "{'serviceNumberId': 1, 'lineGroupId': 1, 'scopeId': 1}"),
@CompoundIndex(name = "roomId_1_status_1", def = "{'roomId': 1, 'status': 1}"),
@CompoundIndex(name = "contactId_1_status_1", def = "{'contactId': 1, 'status': 1}"),
@CompoundIndex(name = "tenantId_1_lineGroupId_1_status_1",
def = "{'tenantId': 1, 'lineGroupId': 1, 'status': 1}")
})
public class LineGroupContactRelationModel extends BaseModel {
String tenantId; // 租戶 ID
String serviceNumberId; // 服務號 ID
String lineGroupId; // LINE 群組 ID(即 chat.code)
String roomId; // Aile 聊天室 ID
String scopeId; // LINE 用戶 scopeId(即 sender.code)
String contactId; // Aile 聯繫人 ID
String status; // 狀態(Enable / Disable)
}
3. 核心服務與實現
3.1 LineGroupRoomImpl(聊天室工廠策略)
位置:aile-service/aile-service-room/.../factory/strategy/impl/LineGroupRoomImpl.java
繼承 CommonRoomImpl,覆寫關鍵方法以適應群組場景:
| 方法 | 行為 |
|---|---|
checkMessage() | 識別系統帳號消息,設置發送人 名稱 |
createRoom() | 基於 LineGroupRoomCreateDto 建立聊天室 |
| 消息分發 | 走 roomMessageDispatchBatchWorkerExecutor 批量分發 |
3.2 Gateway 事件處理(tenant 服務)
位置:aile-service/aile-service-tenant/.../gateway/factory/strategy/impl/
| 事件 | 實現類 | 處理邏輯 |
|---|---|---|
Join | AbstractEventImpl (共用) | 建立/恢復群級 scope + lineGroup 聊天室 |
Leave | AbstractEventImpl (共用) | 停用 lineGroup + 群級 scope + 外部成員關係 |
MemberJoin | MemberJoinEventImpl | 建立聯繫人 + 成員級 scope + 房間成員 |
MemberLeave | MemberLeaveEventImpl | 停用房間成員關係 |
Messaging | MessagingEventImpl | 懶建立群/成員 → 寫入消息 |
3.3 LineGroupContactRelationService
位置:aile-service/aile-service-tenant/.../service/servicenumber/
提供 Line 群組與客戶關聯的 CRUD 及查詢能力:
public interface LineGroupContactRelationService extends BaseMongoService<LineGroupContactRelationModel> {
// 依 lineGroupId + scopeId 查找關聯
// 依 roomId 查詢成員列表
// 批量啟用/停用關聯
}
對應 Controller:LineGroupContactRelationController(路由:/servicenumber/linegroup-contact-relation)
3.4 Saga 整合
在租戶資料歸戶/清理流程中,LineGroup 關聯資料也納入 Saga 步驟:
MergeLineGroupContactRelationStep:合併 LineGroup 聯繫人關聯MergeAnonymousVisitorContactDataStep:合併匿名訪客資料(包含 LineGroup 關聯)
4. 事件處理完整流程
4.1 Join(LINE OA 被拉入群)
Gateway ──→ aile-service-tenant (GatewayController)
│
├── 解析 webhook:提取 chat.code、chat.name、chat.pictureUrl、to.code
│
├── 建立/恢復群級 scope
│ scopeId = chat.code
│ code = from.code
│ channel = Line
│ serviceNumberId = to.code
│
├── 建立/恢復 lineGroup 聊天室(透過 RoomFeign 呼叫 room 服務)
│ type = lineGroup
│ serviceNumberId = to.code
│ externalRoomId = chat.code
│ name = chat.name
│ avatar = chat.pictureUrl
│
└── 加入服務號為房間成員
4.2 MemberJoin(新成員加入)
Gateway ──→ aile-service-tenant
│
├── 解析 members[]:提取每個 member 的 code、name、pictureUrl
│
├── 確保群級 scope 和 lineGroup 存在(不存在則補建)
│
└── 對每個 member:
├── 建立/更新 TenantContactModel(聯繫人資料)
├── 建立/更新成員級 scope(scopeId = member.code)
├── 建立 LineGroupContactRelationModel
└── 加入 lineGroup 房間成員
4.3 Messaging(群消息)
Gateway ──→ aile-service-tenant ──→ aile-service-room
│
├── 確保群級 scope 和 lineGroup 存在
│
├── 依 sender.code 懶建立聯繫人/成員級 scope/房間成員
│ (若此前未收到 MemberJoin)
│
├── 消息寫入 lineGroup 聊天室
│ senderId = 實際成員聯繫人 ID(非 chat.code)
│ senderName = 聯繫人名稱
│
└── 不創建 ServiceSession,不走機器人流程
4.4 Leave(LINE OA 被移出群)
Gateway ──→ aile-service-tenant
│
├── 停用 lineGroup 聊天室(軟刪除)
├── 停用群級 scope
└── 批量停用房間成員關係
5. 發送規則詳解
5.1 群級路由
LINE 群組消息外發使用 群級 scope(scopeId = chat.code),而非成員級 scope。
對外發送目標:scopeId = chat.code
路由方式:GatewayFeign → Gateway 群級路由
發送次數:一條內部消息 → 一次外部發送
5.2 發送者展示
| 展示元素 | 取值來源 |
|---|---|
| senderId | 實際成員對應的聯繫人 ID |
| senderName | 成員聯繫人名稱 |
| senderAvatar | 成員聯繫人頭像 |
禁止使用 chat.code 或群級 scope 作為消息發送者。
5.3 與 Services Room 的關鍵差異
| 維度 | Services Room | LineGroup Room |
|---|---|---|
| 會話模型 | 每客戶一個 ServiceSession | 無 ServiceSession |
| 外發目標 | 成員級 scope(單個客戶) | 群級 scope(整個群) |
| 機器人流程 | 支援(歡迎語/自動接待/超時) | 不支援 |
| 消息發送者 | 客戶本人 | 群內實際發言人 |
| 房間類型 | services | lineGroup |
6. 冪等性與一致性
- 同一
serviceNumberId + chat.code只允許一個啟用中的 lineGroup - 同一成員在同一 lineGroup 中只允許一條啟用中的成員關係
- 事件亂序時採取「補建優先、刪除冪等」策略
- 處理順序:先保證群級資料 → 再保證成員級資料 → 最後寫入消息
7. 關鍵檔案索引
| 層級 | 檔案 | 說明 |
|---|---|---|
| API Model | aile-api/aile-room-api/.../constant/RoomType.java | LineGroup 常量 |
| API Model | aile-api/aile-room-api/.../dto/room/LineGroupRoomCreateDto.java | 建立聊天室 DTO |
| API Model | aile-api/aile-room-api/.../dto/room/LineGroupRoomInfoSyncDto.java | 群資訊同步 DTO |
| API Model | aile-api/aile-room-api/.../dto/room/LineGroupRoomListDto.java | 列表查詢 DTO |
| API Model | aile-api/aile-tenant-api/.../model/servicenumber/LineGroupContactRelationModel.java | 群客戶關聯 |
| API Model | aile-api/aile-tenant-api/.../dto/servicenumber/LineGroupContactRelationListDto.java | 關聯查詢 DTO |
| Room 服務 | aile-service/aile-service-room/.../factory/strategy/impl/LineGroupRoomImpl.java | 群組聊天室策略 |
| Room 服務 | aile-service/aile-service-room/.../util/LineGroupUnreadWrite.java | 未讀數寫入 |
| Room 服務 | aile-service/aile-service-room/.../util/LineGroupMemberRoomRedisUtil.java | 成員房間 Redis |
| Room 服務 | aile-service/aile-service-room/.../util/LineGroupMemberUnread.java | 成員未讀 |
| Tenant 服務 | aile-service/aile-service-tenant/.../gateway/factory/strategy/impl/MemberJoinEventImpl.java | MemberJoin 事件 |
| Tenant 服務 | aile-service/aile-service-tenant/.../gateway/factory/strategy/impl/MemberLeaveEventImpl.java | MemberLeave 事件 |
| Tenant 服務 | aile-service/aile-service-tenant/.../service/servicenumber/impl/LineGroupContactRelationServiceImpl.java | 關聯服務實現 |
| Tenant 服務 | aile-service/aile-service-tenant/.../controller/servicenumber/LineGroupContactRelationController.java | 關聯 API |
| Saga | aile-service/aile-service-tenant/.../saga/step/MergeLineGroupContactRelationStep.java | Saga 合併步驟 |