feat: 改由透传消息接口
All checks were successful
Egg CI/CD / build-image (push) Successful in 31s
Egg CI/CD / deploy (push) Successful in 45s

This commit is contained in:
zhaoyingbo 2024-03-08 11:19:52 +00:00
parent b9474d00d3
commit 3b97b1def5
7 changed files with 232 additions and 113 deletions

49
routes/bot/activeMsg.ts Normal file
View File

@ -0,0 +1,49 @@
import { fetchCIMonitor } from "../../service";
import { getActionType, getIsActionMsg } from "../../utils/msgTools";
import { updateCard } from "../../utils/sendMsg";
const makeChatIdCard = (body: LarkUserAction) => {
return JSON.stringify({ text: `chatId: ${body.open_chat_id}` });
};
const makeCICard = async () => {
const card = await fetchCIMonitor();
if (!card) return "";
return JSON.stringify(card);
};
const ACTION_MAP = {
chat_id: makeChatIdCard,
ci: makeCICard,
};
/**
*
* @param {LarkUserAction} body
*/
const manageBtnClick = async (body: LarkUserAction) => {
const { action } = body?.action?.value as {
action: keyof typeof ACTION_MAP;
};
if (!action) return;
const card = await ACTION_MAP[action](body);
if (!card) return;
// 更新飞书的卡片
await updateCard(body.open_message_id, card);
};
/**
* Action消息
* @param {LarkUserAction} body
*/
export const manageActionMsg = async (body: LarkUserAction) => {
// 过滤非Action消息
if (!getIsActionMsg(body)) {
return false;
}
const actionType = getActionType(body);
if (actionType === "button") {
manageBtnClick(body);
}
return true;
};

View File

@ -1,38 +1,12 @@
import { fetchCIMonitor } from "../../service";
import { getChatId, getIsEventMsg, getMsgType } from "../../utils/msgTools";
import { sendMsg } from "../../utils/sendMsg";
/**
*
* @param {LarkMessageEvent} body
*/
const isEventMsg = (body: LarkMessageEvent) => {
return body?.header?.event_type === "im.message.receive_v1";
};
/**
*
* @param {LarkMessageEvent} body
* @returns
*/
const getMsgType = (body: LarkMessageEvent) => {
return body?.event?.message?.message_type;
};
/**
* Id
* @param {LarkMessageEvent} body
* @returns
*/
const getChatId = (body: LarkMessageEvent) => {
return body?.event?.message?.chat_id;
};
/**
*
* @param {LarkMessageEvent} body
* @returns {string}
*/
const getMsgText = (body: LarkMessageEvent) => {
export const getMsgText = (body: LarkMessageEvent) => {
// TODO: 如果之后想支持单独提醒,这里需要做模板解析
try {
const { text } = JSON.parse(body?.event?.message?.content);
@ -78,67 +52,33 @@ const filterIllegalMsg = (body: LarkMessageEvent) => {
};
/**
* info指令
* @param chatId Id
*/
const manageInfoCommand = (chatId: string) => {
const content = JSON.stringify({ text: `chatId: ${chatId}` });
sendMsg("chat_id", chatId, "text", content);
};
/**
*
*
* @param {LarkMessageEvent} body
* @returns {boolean} info指令
*/
const filterCommand = (body: LarkMessageEvent) => {
const chatId = getChatId(body);
const text = getMsgText(body);
if (text === "info") {
manageInfoCommand(chatId);
return true;
}
if (text === "ci") {
fetchCIMonitor();
return true;
}
return false;
};
const replyNomalMsg = async (body: LarkMessageEvent) => {
const chatId = getChatId(body);
const content = JSON.stringify({
elements: [
{
tag: "markdown",
content: "**目前支持的指令**\n1. info\n2. ci",
},
],
header: {
template: "blue",
title: {
content: "欢迎使用小煎蛋 ₍ᐢ..ᐢ₎♡",
tag: "plain_text",
},
type: "template",
data: {
template_id: "ctp_AAyVx5R39xU9",
},
});
sendMsg("chat_id", chatId, "interactive", content);
};
/**
* Event消息
* @param {LarkUserAction} body
*/
export const manageEventMsg = async (body: LarkMessageEvent) => {
// 过滤非Event消息
if (!isEventMsg(body)) {
if (!getIsEventMsg(body)) {
return false;
}
// 过滤非法消息
if (filterIllegalMsg(body)) {
return true;
}
// 过滤指令
if (filterCommand(body)) {
return true;
}
// 临时返回消息
replyNomalMsg(body);
return true;

View File

@ -1,13 +1,16 @@
import { manageEventMsg } from "./eventMsg"
import { manageActionMsg } from "./activeMsg";
import { manageEventMsg } from "./eventMsg";
export const manageBotReq = async (req: Request) => {
const body = await req.json() as any
const body = (await req.json()) as any;
// 验证机器人
if (body?.type === 'url_verification') {
console.log("🚀 ~ manageBotReq ~ url_verification:")
return Response.json({ challenge: body?.challenge })
if (body?.type === "url_verification") {
console.log("🚀 ~ manageBotReq ~ url_verification:");
return Response.json({ challenge: body?.challenge });
}
// 处理Event消息
if (await manageEventMsg(body)) return new Response("success")
return new Response("hello, glade to see you!")
}
if (await manageEventMsg(body)) return new Response("success");
// 处理Action消息
if (await manageActionMsg(body)) return new Response("success");
return new Response("hello, glade to see you!");
};

View File

@ -1,15 +1,28 @@
import db from "../../db";
import { sendMsg } from "../../utils/sendMsg";
interface MessageReqJson {
group_id: string;
interface BaseMsg {
msg_type: MsgType;
content: string;
}
interface GroupMsg extends BaseMsg {
group_id: string;
}
interface NormalMsg extends BaseMsg {
receive_id: string;
receive_id_type: ReceiveIDType;
}
type MessageReqJson = GroupMsg & NormalMsg;
const validateMessageReq = (body: MessageReqJson) => {
if (!body.group_id) {
return new Response("group_id is required");
if (!body.group_id && !body.receive_id) {
return new Response("group_id or receive_id is required");
}
if (body.receive_id && !body.receive_id_type) {
return new Response("receive_id_type is required");
}
if (!body.msg_type) {
return new Response("msg_type is required");
@ -24,16 +37,8 @@ export const manageMessageReq = async (req: Request) => {
const body = (await req.json()) as MessageReqJson;
// 校验参数
const validateRes = validateMessageReq(body);
if (validateRes) {
return validateRes;
}
// 获取所有接收者
const group = (await db.messageGroup.getOne(body.group_id)) as PBMessageGroup;
if (!group) {
return new Response("group not found");
}
if (validateRes) return validateRes;
const { chat_id, open_id, union_id, user_id, email } = group;
// 遍历所有id发送消息保存所有对应的messageId
const sendRes = {
chat_id: {} as Record<string, any>,
@ -42,33 +47,63 @@ export const manageMessageReq = async (req: Request) => {
user_id: {} as Record<string, any>,
email: {} as Record<string, any>,
};
// 发送消息列表
const sendList = [] as Promise<any>[];
// 处理消息内容
const finalContent =
typeof body.content !== "string"
? JSON.stringify(body.content)
: body.content;
// 构造发送消息函数
const makeSendFunc = (receive_id_type: ReceiveIDType) => {
return (receive_id: string) => {
sendList.push(
sendMsg(receive_id_type, receive_id, body.msg_type, finalContent).then(
(res) => {
sendRes[receive_id_type][receive_id] = res;
}
)
);
};
};
if (body.group_id) {
// 获取所有接收者
const group = (await db.messageGroup.getOne(
body.group_id!
)) as PBMessageGroup;
if (!group) {
return new Response("group not found");
}
// 发送消息
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"));
const { chat_id, open_id, union_id, user_id, email } = group;
// 构造发送消息函数
const makeSendFunc = (receive_id_type: ReceiveIDType) => {
return (receive_id: string) => {
sendList.push(
sendMsg(
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"));
}
if (body.receive_id && body.receive_id_type) {
sendList.push(
sendMsg(
body.receive_id_type,
body.receive_id,
body.msg_type,
finalContent
).then((res) => {
sendRes[body.receive_id_type][body.receive_id] = res;
})
);
}
try {
await Promise.all(sendList);

View File

@ -1 +1,8 @@
export const fetchCIMonitor = () => fetch("https://ci-monitor.xiaomiwh.cn/ci");
export const fetchCIMonitor = async () => {
try {
const res = await fetch("https://ci-monitor.xiaomiwh.cn/ci");
return (await res.json()) as any;
} catch {
return null;
}
};

42
utils/msgTools.ts Normal file
View File

@ -0,0 +1,42 @@
/**
*
* @param {LarkMessageEvent} body
*/
export const getIsEventMsg = (body: LarkMessageEvent) => {
return body?.header?.event_type === "im.message.receive_v1";
};
/**
*
* @param {LarkMessageEvent} body
* @returns
*/
export const getMsgType = (body: LarkMessageEvent) => {
return body?.event?.message?.message_type;
};
/**
* Id
* @param {LarkMessageEvent} body
* @returns
*/
export const getChatId = (body: LarkMessageEvent) => {
return body?.event?.message?.chat_id;
};
/**
* Action消息
* @param {LarkUserAction} body
*/
export const getIsActionMsg = (body: LarkUserAction) => {
return body?.action;
};
/**
* Action类型
* @param {LarkUserAction} body
* @returns {string} Action类型
*/
export const getActionType = (body: LarkUserAction) => {
return body?.action?.tag;
};

View File

@ -47,9 +47,52 @@ export const sendMsg = async (
console.log("sendMsg error", error);
return {
code: 1,
msg: "fetch error",
msg: "sendMsg fetch error",
};
}
};
// sendMsg('user_id', 'liuke9', 'text', JSON.stringify({text: '这是测试消息,不要回复'}))
/**
*
* @param {string} message_id id
* @param {*} content JSON结构序列化后的字符串msg_type对应不同内容
*/
export const updateCard = async (message_id: string, content: string) => {
const URL = `https://open.f.mioffice.cn/open-apis/im/v1/messages/${message_id}`;
const tenant_access_token = await db.tenantAccessToken.get();
const header = {
"Content-Type": "application/json; charset=utf-8",
Authorization: `Bearer ${tenant_access_token}`,
};
const body = { content };
try {
const res = await fetch(URL, {
method: "PATCH",
headers: header,
body: JSON.stringify(body),
});
const data = (await res.json()) as any;
if (data.code !== 0) {
console.log("updateCard error", data);
return {
code: data.code,
msg: data.msg,
};
}
console.log("updateCard success", data);
return {
code: 0,
msg: "success",
data: {
message_id: data.data.message_id,
},
};
} catch (error) {
console.log("updateCard error", error);
return {
code: 1,
msg: "updateCard fetch error",
};
}
};