egg_server/db/chat/index.ts

134 lines
3.5 KiB
TypeScript

import PocketBase, { RecordModel } from "pocketbase"
import { Logger } from "winston"
import { Context } from "../../types"
import PbToolBase, { WithExpand } from "../base"
import { SheetModel } from "../sheet"
/** 聊天集合名称 */
const DB_NAME = "chat"
/**
* 聊天数据接口
*/
export interface Chat {
/** 飞书聊天 ID */
chatId: string
/** 聊天名称 */
name: string
/** 聊天头像 URL */
avatar: string
/** 聊天模式: 群组、点对点或话题 */
mode: "group" | "p2p" | "topic"
/** 是否启用周报汇总 */
weeklySummary: boolean
/** 是否启用日报汇总 */
dailySummary: boolean
/** 关联表单 ID */
sheet: string
}
/** 聊天数据模型,继承基础的 RecordModel */
export type ChatModel = Chat & RecordModel
/**
* 带有关联表单数据的聊天模型
* 扩展了表单关联字段
*/
export type ChatModelWithSheet = ChatModel &
WithExpand<{
sheet: SheetModel
}>
/**
* 聊天数据管理类
* 提供对飞书聊天相关数据的存储、查询和管理功能
* 继承自 PbToolBase 基础工具类
*/
class ChatDB extends PbToolBase<ChatModel> {
/**
* 创建 ChatDB 实例
*
* @param pbClient - PocketBase 客户端实例
* @param logger - 日志记录器实例
*/
constructor(pbClient: PocketBase, logger: Logger) {
super(DB_NAME, pbClient, logger)
}
/**
* 通过聊天 ID 获取聊天信息
*
* @param chatId - 飞书聊天 ID
* @returns 聊天数据模型,包含关联的表单数据,失败时返回 null
*
* @example
* ```typescript
* const chat = await chatDB.getOneByChatId("oc_123456");
* ```
*/
public getOneByChatId = (chatId: string) => {
const filter = `chatId = "${chatId}"`
return this.getFirstOne<ChatModelWithSheet>(filter, { expand: "sheet" })
}
/**
* 根据上下文获取聊天信息
* 如果数据库中不存在,则尝试从飞书 API 获取并创建新记录
*
* @param context - 上下文对象,包含飞书服务和请求体
* @returns 聊天数据模型,失败时返回 null
*
* @example
* ```typescript
* const chat = await chatDB.getByCtx(ctx);
* ```
*/
public getByCtx = async ({ larkService, larkBody }: Context) => {
const { chatId } = larkBody
if (!chatId) {
this.logger.error("chatId 为空")
return null
}
const chat = await this.getOneByChatId(chatId)
if (chat) return chat
this.logger.info("群聊不在数据库里,尝试从飞书获取", { chatId })
const chatInfo = await larkService.chat.getChatInfo(chatId)
if (!chatInfo || chatInfo.code !== 0) return null
const { name, avatar, chat_mode } = chatInfo.data
return this.create({
chatId,
name,
avatar,
mode: chat_mode,
weeklySummary: false,
dailySummary: false,
sheet: "",
})
}
/**
* 获取需要汇总的聊天列表
*
* @param timeScope - 汇总时间范围:"daily"(日报)、"weekly"(周报)或"all"(全部)
* @returns 符合条件的聊天数据模型列表,失败时返回 null
*
* @example
* ```typescript
* const dailyChats = await chatDB.getNeedSummaryChats("daily");
* ```
*/
public getNeedSummaryChats = async (
timeScope: "daily" | "weekly" | "all"
) => {
const filterMap = {
daily: "dailySummary = true",
weekly: "weeklySummary = true",
all: "dailySummary = true && weeklySummary = true",
}
return this.list<ChatModel>({ filter: filterMap[timeScope] })
}
}
export default ChatDB