2022-08-05 17:56:20 +00:00
|
|
|
import type { NextApiRequest, NextApiResponse } from "next";
|
|
|
|
import { z } from "zod";
|
|
|
|
|
|
|
|
import logger from "@calcom/lib/logger";
|
|
|
|
import { defaultHandler, defaultResponder } from "@calcom/lib/server";
|
|
|
|
import prisma from "@calcom/prisma";
|
|
|
|
|
|
|
|
import { getAppKeys } from "../common";
|
|
|
|
import { sendPostMsg } from "../lib/BotService";
|
|
|
|
|
|
|
|
const log = logger.getChildLogger({ prefix: [`[lark/api/events]`] });
|
|
|
|
|
|
|
|
const larkKeysSchema = z.object({
|
|
|
|
open_verification_token: z.string(),
|
|
|
|
});
|
|
|
|
|
|
|
|
const appTicketEventsReqSchema = z.object({
|
|
|
|
body: z.object({
|
|
|
|
event: z.object({
|
|
|
|
app_ticket: z.string().min(1),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
|
|
|
|
const imMessageReceivedEventsReqSchema = z.object({
|
|
|
|
body: z.object({
|
|
|
|
header: z.object({
|
|
|
|
tenant_key: z.string().min(1),
|
|
|
|
}),
|
|
|
|
event: z.object({
|
|
|
|
sender: z.object({
|
|
|
|
sender_id: z.object({
|
|
|
|
open_id: z.string().min(1),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
|
|
|
|
const p2pChatCreateEventsReqSchema = z.object({
|
|
|
|
body: z.object({
|
|
|
|
tenant_key: z.string().min(1),
|
|
|
|
event: z.object({
|
|
|
|
user: z.object({
|
|
|
|
open_id: z.string().min(1),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
|
|
|
|
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|
|
|
log.debug("receive events", req.body);
|
|
|
|
const appKeys = await getAppKeys();
|
|
|
|
const { open_verification_token } = larkKeysSchema.parse(appKeys);
|
|
|
|
|
|
|
|
// used for events handler binding in lark open platform, see
|
|
|
|
// https://open.larksuite.com/document/ukTMukTMukTM/uUTNz4SN1MjL1UzM?lang=en-US
|
2022-08-30 17:08:29 +00:00
|
|
|
if (req.body.type === "url_verification" && req.body.token === open_verification_token) {
|
|
|
|
log.debug("update token", req.body);
|
2022-08-05 17:56:20 +00:00
|
|
|
return res.status(200).json({ challenge: req.body.challenge });
|
|
|
|
}
|
|
|
|
|
|
|
|
// used for receiving app_ticket, see
|
|
|
|
// https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/application-v6/event/app_ticket-events
|
|
|
|
if (req.body.event?.type === "app_ticket" && open_verification_token === req.body.token) {
|
|
|
|
const {
|
|
|
|
body: {
|
|
|
|
event: { app_ticket: appTicket },
|
|
|
|
},
|
|
|
|
} = appTicketEventsReqSchema.parse(req);
|
|
|
|
|
|
|
|
await prisma.app.update({
|
|
|
|
where: { slug: "lark-calendar" },
|
|
|
|
data: {
|
|
|
|
keys: {
|
|
|
|
...appKeys,
|
|
|
|
app_ticket: appTicket,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return res.status(200).json({ code: 0, msg: "success" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// used for handle user at bot in lark chat with cal.com connector bot, see
|
|
|
|
// https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/events/receive
|
|
|
|
if (req.body.header?.event_type === "im.message.receive_v1") {
|
|
|
|
const {
|
|
|
|
body: {
|
|
|
|
header: { tenant_key: tenantKey },
|
|
|
|
event: {
|
|
|
|
sender: {
|
|
|
|
sender_id: { open_id: senderOpenId },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} = imMessageReceivedEventsReqSchema.parse(req);
|
|
|
|
|
|
|
|
sendPostMsg(tenantKey, senderOpenId);
|
|
|
|
|
|
|
|
return res.status(200).json({ code: 0, msg: "success" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// used for handle user first talk with cal.com connector bot, see
|
|
|
|
// https://open.larksuite.com/document/ukTMukTMukTM/uYDNxYjL2QTM24iN0EjN/bot-events
|
|
|
|
if (req.body.event?.type === "p2p_chat_create") {
|
|
|
|
const {
|
|
|
|
body: {
|
|
|
|
tenant_key: tenantKey,
|
|
|
|
event: {
|
|
|
|
user: { open_id: senderOpenId },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} = p2pChatCreateEventsReqSchema.parse(req);
|
|
|
|
|
|
|
|
sendPostMsg(tenantKey, senderOpenId);
|
|
|
|
|
|
|
|
return res.status(200).json({ code: 0, msg: "success" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default defaultHandler({
|
|
|
|
POST: Promise.resolve({ default: defaultResponder(postHandler) }),
|
|
|
|
});
|