163 lines
4.6 KiB
TypeScript
163 lines
4.6 KiB
TypeScript
import { stringifyJson } from "@egg/hooks"
|
||
import { LarkService } from "@egg/net-tool"
|
||
|
||
import db from "../../db"
|
||
import { Context, DB, LarkServer, MsgProxy } from "../../types"
|
||
|
||
const LOG_COLLECTION = "message_log"
|
||
|
||
/**
|
||
* 校验消息请求的参数
|
||
* @param {Context.Data} ctx - 上下文数据,包含请求体和响应生成器
|
||
* @returns {false | Response} 如果校验失败,返回响应对象;否则返回 false
|
||
*/
|
||
const validateMessageReq = ({
|
||
body,
|
||
genResp,
|
||
}: Context.Data): false | Response => {
|
||
if (!body.api_key) {
|
||
return genResp.badRequest("api_key is required")
|
||
}
|
||
if (!body.group_id && !body.receive_id) {
|
||
return genResp.badRequest("group_id or receive_id is required")
|
||
}
|
||
if (body.receive_id && !body.receive_id_type) {
|
||
return genResp.badRequest("receive_id_type is required")
|
||
}
|
||
if (!body.msg_type) {
|
||
return genResp.badRequest("msg_type is required")
|
||
}
|
||
if (!body.content) {
|
||
return genResp.badRequest("content is required")
|
||
}
|
||
return false
|
||
}
|
||
|
||
/**
|
||
* 处理消息请求
|
||
* @param {Context.Data} ctx - 上下文数据,包含请求体、日志记录器、响应生成器和 Lark 服务
|
||
* @returns {Promise<Response>} 返回响应对象
|
||
*/
|
||
export const manageMessageReq = async (
|
||
ctx: Context.Data
|
||
): Promise<Response> => {
|
||
const { body: rawBody, genResp, appMap, requestId } = ctx
|
||
const body = rawBody as MsgProxy.Body
|
||
|
||
// 校验参数
|
||
const validateRes = validateMessageReq(ctx)
|
||
if (validateRes) return validateRes
|
||
|
||
// 处理消息内容
|
||
const finalContent =
|
||
typeof body.content !== "string"
|
||
? stringifyJson(body.content)
|
||
: body.content
|
||
|
||
// 初始化发送结果对象
|
||
const sendRes = {
|
||
chat_id: {} as Record<string, any>,
|
||
open_id: {} as Record<string, any>,
|
||
union_id: {} as Record<string, any>,
|
||
user_id: {} as Record<string, any>,
|
||
email: {} as Record<string, any>,
|
||
}
|
||
|
||
// 发送消息列表
|
||
const sendList = [] as Promise<any>[]
|
||
|
||
// 构造消息记录
|
||
const baseLog: DB.MessageLogCreate = {
|
||
...body,
|
||
final_content: finalContent,
|
||
}
|
||
|
||
// 校验 api_key
|
||
const apiKeyInfo = await db.apiKey.getOne(body.api_key)
|
||
if (!apiKeyInfo) {
|
||
const error = "api key not found"
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, error })
|
||
return genResp.notFound(error)
|
||
}
|
||
|
||
// 获取 app name
|
||
const appName = apiKeyInfo.expand?.app?.name
|
||
if (!appName) {
|
||
const error = "app name not found"
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, error })
|
||
return genResp.notFound(error)
|
||
}
|
||
|
||
// 获取 app info
|
||
const appInfo = appMap[appName]
|
||
if (!appInfo) {
|
||
const error = "app not found"
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, error })
|
||
return genResp.notFound(error)
|
||
}
|
||
|
||
const larkService = new LarkService({
|
||
appId: appInfo.app_id,
|
||
appSecret: appInfo.app_secret,
|
||
requestId,
|
||
})
|
||
|
||
// 如果有 group_id,则发送给所有 group_id 中的人
|
||
if (body.group_id) {
|
||
// 获取所有接收者
|
||
const group = await db.messageGroup.getOne(body.group_id!)
|
||
if (!group) {
|
||
const error = "message group not found"
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, error })
|
||
return genResp.notFound(error)
|
||
}
|
||
|
||
const { chat_id, open_id, union_id, user_id, email } = group
|
||
|
||
// 构造发送消息函数
|
||
const makeSendFunc = (receive_id_type: LarkServer.ReceiveIDType) => {
|
||
return (receive_id: string) => {
|
||
sendList.push(
|
||
larkService.message
|
||
.send(receive_id_type, receive_id, body.msg_type, finalContent)
|
||
.then((res) => {
|
||
sendRes[receive_id_type][receive_id] = res
|
||
})
|
||
)
|
||
}
|
||
}
|
||
|
||
// 创建消息列表
|
||
if (chat_id) chat_id.map(makeSendFunc("chat_id"))
|
||
if (open_id) open_id.map(makeSendFunc("open_id"))
|
||
if (union_id) union_id.map(makeSendFunc("union_id"))
|
||
if (user_id) user_id.map(makeSendFunc("user_id"))
|
||
if (email) email.map(makeSendFunc("email"))
|
||
}
|
||
|
||
// 如果有 receive_id,则发送给所有 receive_id 中的人
|
||
if (body.receive_id && body.receive_id_type) {
|
||
body.receive_id.split(",").forEach((receive_id) => {
|
||
sendList.push(
|
||
larkService.message
|
||
.send(body.receive_id_type, receive_id, body.msg_type, finalContent)
|
||
.then((res) => {
|
||
sendRes[body.receive_id_type][receive_id] = res
|
||
})
|
||
)
|
||
})
|
||
}
|
||
|
||
try {
|
||
// 发送消息
|
||
await Promise.allSettled(sendList)
|
||
// 保存消息记录
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, send_result: sendRes })
|
||
return genResp.ok(sendRes)
|
||
} catch {
|
||
const error = "send msg failed"
|
||
db.log.create(LOG_COLLECTION, { ...baseLog, error })
|
||
return genResp.serverError(error, sendRes)
|
||
}
|
||
}
|