This commit is contained in:
m5r
2021-08-01 22:03:49 +08:00
parent 7d34fcd48f
commit 1489f97c14
33 changed files with 147 additions and 313 deletions

View File

@ -19,9 +19,7 @@ const insertIncomingMessageQueue = Queue<Payload>(
}
const encryptionKey = customer.encryptionKey;
const message = await twilio(customer.accountSid, customer.authToken)
.messages.get(messageSid)
.fetch();
const message = await twilio(customer.accountSid, customer.authToken).messages.get(messageSid).fetch();
await db.message.create({
data: {
customerId,

View File

@ -9,28 +9,25 @@ type Payload = {
messages: MessageInstance[];
};
const insertMessagesQueue = Queue<Payload>(
"api/queue/insert-messages",
async ({ messages, customerId }) => {
const customer = await db.customer.findFirst({ where: { id: customerId } });
const encryptionKey = customer!.encryptionKey;
const insertMessagesQueue = Queue<Payload>("api/queue/insert-messages", async ({ messages, customerId }) => {
const customer = await db.customer.findFirst({ where: { id: customerId } });
const encryptionKey = customer!.encryptionKey;
const sms = messages
.map<Omit<Message, "id">>((message) => ({
customerId,
content: encrypt(message.body, encryptionKey),
from: message.from,
to: message.to,
status: translateStatus(message.status),
direction: translateDirection(message.direction),
twilioSid: message.sid,
sentAt: new Date(message.dateCreated),
}))
.sort((a, b) => a.sentAt.getTime() - b.sentAt.getTime());
const sms = messages
.map<Omit<Message, "id">>((message) => ({
customerId,
content: encrypt(message.body, encryptionKey),
from: message.from,
to: message.to,
status: translateStatus(message.status),
direction: translateDirection(message.direction),
twilioSid: message.sid,
sentAt: new Date(message.dateCreated),
}))
.sort((a, b) => a.sentAt.getTime() - b.sentAt.getTime());
await db.message.createMany({ data: sms });
},
);
await db.message.createMany({ data: sms });
});
export default insertMessagesQueue;

View File

@ -17,10 +17,7 @@ const sendMessageQueue = Queue<Payload>(
const phoneNumber = await db.phoneNumber.findFirst({ where: { customerId } });
try {
const message = await twilio(
customer!.accountSid!,
customer!.authToken!,
).messages.create({
const message = await twilio(customer!.accountSid!, customer!.authToken!).messages.create({
body: content,
to,
from: phoneNumber!.phoneNumber,

View File

@ -57,12 +57,7 @@ export default async function incomingMessageHandler(req: BlitzApiRequest, res:
}
const url = `https://${serverRuntimeConfig.app.baseUrl}/api/webhook/incoming-message`;
const isRequestValid = twilio.validateRequest(
customer.authToken,
twilioSignature,
url,
req.body,
);
const isRequestValid = twilio.validateRequest(customer.authToken, twilioSignature, url, req.body);
if (!isRequestValid) {
const statusCode = 400;
const apiError: ApiError = {

View File

@ -28,8 +28,7 @@ export default function Conversation() {
const isSameNext = message.from === nextMessage?.from;
const isSamePrevious = message.from === previousMessage?.from;
const differenceInMinutes = previousMessage
? (new Date(message.sentAt).getTime() -
new Date(previousMessage.sentAt).getTime()) /
? (new Date(message.sentAt).getTime() - new Date(previousMessage.sentAt).getTime()) /
1000 /
60
: 0;
@ -63,9 +62,7 @@ export default function Conversation() {
<span
className={clsx(
"inline-block text-left w-[fit-content] p-2 rounded-lg text-white",
isOutbound
? "bg-[#3194ff] rounded-br-none"
: "bg-black rounded-bl-none",
isOutbound ? "bg-[#3194ff] rounded-br-none" : "bg-black rounded-bl-none",
)}
>
{message.content}

View File

@ -23,9 +23,7 @@ export default function ConversationsList() {
<a className="flex flex-col">
<div className="flex flex-row justify-between">
<strong>{recipient}</strong>
<div>
{new Date(lastMessage.sentAt).toLocaleString("fr-FR")}
</div>
<div>{new Date(lastMessage.sentAt).toLocaleString("fr-FR")}</div>
</div>
<div>{lastMessage.content}</div>
</a>

View File

@ -41,9 +41,7 @@ export default function NewMessageBottomSheet() {
<NewMessageArea
recipient={recipient}
onSend={() => {
router
.push(Routes.ConversationPage({ recipient }))
.then(() => setIsOpen(false));
router.push(Routes.ConversationPage({ recipient })).then(() => setIsOpen(false));
}}
/>
</Suspense>

View File

@ -16,45 +16,39 @@ const Body = z.object({
to: z.string(),
});
export default resolver.pipe(
resolver.zod(Body),
resolver.authorize(),
async ({ content, to }, context) => {
const customer = await getCurrentCustomer(null, context);
try {
await twilio(customer!.accountSid!, customer!.authToken!)
.lookups.v1.phoneNumbers(to)
.fetch();
} catch (error) {
logger.error(error);
return;
}
export default resolver.pipe(resolver.zod(Body), resolver.authorize(), async ({ content, to }, context) => {
const customer = await getCurrentCustomer(null, context);
try {
await twilio(customer!.accountSid!, customer!.authToken!).lookups.v1.phoneNumbers(to).fetch();
} catch (error) {
logger.error(error);
return;
}
const customerId = customer!.id;
const customerPhoneNumber = await getCustomerPhoneNumber({ customerId }, context);
const customerId = customer!.id;
const customerPhoneNumber = await getCustomerPhoneNumber({ customerId }, context);
const message = await db.message.create({
data: {
customerId,
to,
from: customerPhoneNumber!.phoneNumber,
direction: Direction.Outbound,
status: MessageStatus.Queued,
content: encrypt(content, customer!.encryptionKey),
sentAt: new Date(),
},
});
const message = await db.message.create({
data: {
customerId,
to,
from: customerPhoneNumber!.phoneNumber,
direction: Direction.Outbound,
status: MessageStatus.Queued,
content: encrypt(content, customer!.encryptionKey),
sentAt: new Date(),
},
});
await sendMessageQueue.enqueue(
{
id: message.id,
customerId,
to,
content,
},
{
id: message.id,
},
);
},
);
await sendMessageQueue.enqueue(
{
id: message.id,
customerId,
to,
content,
},
{
id: message.id,
},
);
});

View File

@ -2,11 +2,7 @@ import { Suspense } from "react";
import type { BlitzPage } from "blitz";
import { Routes, useRouter } from "blitz";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faLongArrowLeft,
faInfoCircle,
faPhoneAlt as faPhone,
} from "@fortawesome/pro-regular-svg-icons";
import { faLongArrowLeft, faInfoCircle, faPhoneAlt as faPhone } from "@fortawesome/pro-regular-svg-icons";
import Layout from "../../../core/layouts/layout";
import Conversation from "../../components/conversation";

View File

@ -9,23 +9,19 @@ const GetConversations = z.object({
recipient: z.string(),
});
export default resolver.pipe(
resolver.zod(GetConversations),
resolver.authorize(),
async ({ recipient }, context) => {
const customer = await getCurrentCustomer(null, context);
const conversation = await db.message.findMany({
where: {
OR: [{ from: recipient }, { to: recipient }],
},
orderBy: { sentAt: Prisma.SortOrder.asc },
});
export default resolver.pipe(resolver.zod(GetConversations), resolver.authorize(), async ({ recipient }, context) => {
const customer = await getCurrentCustomer(null, context);
const conversation = await db.message.findMany({
where: {
OR: [{ from: recipient }, { to: recipient }],
},
orderBy: { sentAt: Prisma.SortOrder.asc },
});
return conversation.map((message) => {
return {
...message,
content: decrypt(message.content, customer!.encryptionKey),
};
});
},
);
return conversation.map((message) => {
return {
...message,
content: decrypt(message.content, customer!.encryptionKey),
};
});
});