insert call to db when making a call

This commit is contained in:
m5r 2021-08-14 01:16:27 +08:00
parent f628addd80
commit 30d186d37d

View File

@ -1,20 +1,68 @@
import type { BlitzApiRequest, BlitzApiResponse } from "blitz"; import type { BlitzApiRequest, BlitzApiResponse } from "blitz";
import Twilio from "twilio"; import { getConfig } from "blitz";
import twilio from "twilio";
import db from "../../../../db"; import type { ApiError } from "../../../_types";
import db, { Direction } from "../../../../db";
import appLogger from "../../../../integrations/logger";
const { serverRuntimeConfig } = getConfig();
const logger = appLogger.child({ route: "/api/webhook/call" });
export default async function incomingCallHandler(req: BlitzApiRequest, res: BlitzApiResponse) { export default async function incomingCallHandler(req: BlitzApiRequest, res: BlitzApiResponse) {
console.log("req.body", req.body); console.log("req.body", req.body);
const isOutgoingCall = true; const url = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`;
const twilioSignature = req.headers["X-Twilio-Signature"] || req.headers["x-twilio-signature"];
if (!twilioSignature || Array.isArray(twilioSignature)) {
const statusCode = 400;
const apiError: ApiError = {
statusCode,
errorMessage: "Invalid header X-Twilio-Signature",
};
logger.error(apiError);
res.status(statusCode).send(apiError);
return;
}
const isOutgoingCall = req.body.From.startsWith("client:");
if (isOutgoingCall) { if (isOutgoingCall) {
const recipient = req.body.To; const recipient = req.body.To;
const organizationId = req.body.From.slice("client:".length).split("__")[0]; const organizationId = req.body.From.slice("client:".length).split("__")[0];
const phoneNumber = await db.phoneNumber.findFirst({ const phoneNumber = await db.phoneNumber.findFirst({
where: { organizationId }, where: { organizationId },
select: { number: true }, include: { organization: true },
}); });
const twiml = new Twilio.twiml.VoiceResponse(); if (
!phoneNumber ||
!phoneNumber.organization.twilioAuthToken ||
!twilio.validateRequest(phoneNumber.organization.twilioAuthToken, twilioSignature, url, req.body)
) {
const statusCode = 400;
const apiError: ApiError = {
statusCode,
errorMessage: "Invalid webhook",
};
logger.error(apiError);
res.status(statusCode).send(apiError);
return;
}
await db.phoneCall.create({
data: {
id: req.body.CallSid,
from: phoneNumber.number,
to: req.body.To,
status: req.body.CallStatus,
direction: Direction.Outbound,
duration: "", // TODO
organizationId: phoneNumber.organization.id,
phoneNumberId: phoneNumber.id,
},
});
const twiml = new twilio.twiml.VoiceResponse();
const dial = twiml.dial({ const dial = twiml.dial({
answerOnBridge: true, answerOnBridge: true,
callerId: phoneNumber!.number, callerId: phoneNumber!.number,
@ -24,8 +72,42 @@ export default async function incomingCallHandler(req: BlitzApiRequest, res: Bli
res.setHeader("content-type", "text/xml"); res.setHeader("content-type", "text/xml");
return res.status(200).send(twiml.toString()); return res.status(200).send(twiml.toString());
} else {
const phoneNumbers = await db.phoneNumber.findMany({
where: { number: req.body.To },
include: { organization: true },
});
if (phoneNumbers.length === 0) {
// phone number is not registered by any organization
res.status(500).end();
return;
}
const phoneNumber = phoneNumbers.find((phoneNumber) => {
// if multiple organizations have the same number
// find the organization currently using that phone number
// maybe we shouldn't let multiple organizations use the same phone number
const authToken = phoneNumber.organization.twilioAuthToken ?? "";
return twilio.validateRequest(authToken, twilioSignature, url, req.body);
});
if (!phoneNumber) {
const statusCode = 400;
const apiError: ApiError = {
statusCode,
errorMessage: "Invalid webhook",
};
logger.error(apiError);
res.status(statusCode).send(apiError);
return;
}
// TODO send notification
// TODO db.phoneCall.create(...);
} }
// TODO queue job to update duration when call ends
res.status(500).end(); res.status(500).end();
} }