import logger from "@egg/logger" import _ from "lodash" import { Logger } from "winston" import { baseErrorCard, basePendingCard, baseSuccessCard } from "./component" type FunctionMap = Record< string, { Xname: string; Xauthor: string; Xicon: string } > type CardMap = Record type TempMap = Record class LarkCard { protected requestId: string protected funcName: string protected functionMap: FunctionMap protected cardMap: CardMap protected tempMap: TempMap protected stringify: boolean protected logger: Logger /** * 构造函数 * @param funcName 函数名 * @param stringify 是否序列化为字符串 * @param requestId 请求 ID * @param cardMap 卡片映射 * @param tempMap 模板映射 * @param functionMap 函数映射 */ constructor( funcName: string, stringify: boolean, requestId: string, cardMap: CardMap, tempMap: TempMap, functionMap: FunctionMap ) { this.stringify = stringify this.requestId = requestId this.funcName = funcName this.functionMap = functionMap this.cardMap = { success: baseSuccessCard, error: baseErrorCard, pending: basePendingCard, ...cardMap, } this.tempMap = tempMap this.logger = logger.child({ requestId }) } /** * 设置函数名 * @param funcName 函数名 */ setFunction(funcName: string) { this.funcName = funcName } /** * 设置是否序列化为字符串 * @param stringify 是否序列化为字符串 */ setStringify(stringify: boolean) { this.stringify = stringify } /** * 创建一个子卡片 * @param func 函数名 * @param stringify 是否序列化为字符串 * @returns 子卡片实例 */ child(func: string, stringify: boolean = true) { return new LarkCard( func, stringify, this.requestId, this.cardMap, this.tempMap, this.functionMap ) } /** * 生成卡片消息 * @param cardKey 卡片ID * @param variables 变量 * @returns 卡片内容或JSON字符串 */ genCard( cardKey: keyof typeof this.cardMap, variables: { [key: string]: any } ) { const card = this.cardMap[cardKey] if (!card) { this.logger.error(`Card ${cardKey} not found`) throw new Error(`Card ${cardKey} not found`) } const finalVariables: Record = { ...variables, requestId: this.requestId, ...this.functionMap[this.funcName], } this.logger.debug( `Card ${cardKey} final variables: ${JSON.stringify(finalVariables)}` ) /** * 替换字符串中的变量 * @param str 字符串 * @returns 替换后的字符串 */ const replaceVariables = (str: string): string => { const variablePattern = /\$\{(\w+)\}/g const matches = str.match(variablePattern) if (matches && matches.length === 1 && matches[0] === str) { // 如果字符串中只有一个变量,且整个字符串就是这个变量 const variableName = matches[0].slice(2, -1) // 去掉 ${ 和 } return finalVariables[variableName] || "" } else { // 否则只替换字符串中的变量部分 return str.replace(variablePattern, (_, v) => finalVariables[v] || "") } } /** * 遍历并替换对象中的变量 * @param obj 对象 * @returns 替换后的对象 */ const traverseAndReplace = (obj: any): any => { if (_.isString(obj)) { return replaceVariables(obj) } else if (_.isArray(obj)) { return obj.map(traverseAndReplace) } else if (_.isObject(obj)) { return _.mapValues(obj, traverseAndReplace) } return obj } const content = traverseAndReplace(card) this.logger.debug( `Card ${cardKey} final content: ${JSON.stringify(content)}` ) return this.stringify ? JSON.stringify(content) : content } /** * 生成成功卡片 * @param content 卡片内容 * @returns 成功卡片内容或JSON字符串 */ genSuccessCard(content: any) { return this.genCard("success", { content }) } /** * 生成错误卡片 * @param content 卡片内容 * @returns 错误卡片内容或JSON字符串 */ genErrorCard(content: any) { return this.genCard("error", { content }) } /** * 生成待处理卡片 * @param content 卡片内容 * @returns 待处理卡片内容或JSON字符串 */ genPendingCard(content: any) { return this.genCard("pending", { content }) } /** * 生成模板卡片 * @param tempKey 模板ID * @param variables 变量 * @returns 模板卡片内容或JSON字符串 */ genTempCard(tempKey: string, variables: { [key: string]: any }) { const tempId = this.tempMap[tempKey] if (!tempId) { this.logger.error(`Temp ${tempKey} not found`) throw new Error(`Temp ${tempKey} not found`) } const finalVariables: Record = { ...variables, requestId: this.requestId, ...this.functionMap[this.funcName], } this.logger.debug( `Temp ${tempKey} final variables: ${JSON.stringify(finalVariables)}` ) const content = { type: "template", data: { config: { update_multi: true, enable_forward: false, }, template_id: tempId, template_variable: finalVariables, }, } this.logger.debug( `Temp ${tempKey} final content: ${JSON.stringify(content)}` ) return this.stringify ? JSON.stringify(content) : content } } export default LarkCard