Skip to content

Commit

Permalink
Guess who hasn't tested their code!
Browse files Browse the repository at this point in the history
  • Loading branch information
Blocksnmore committed Apr 8, 2024
1 parent 4144d18 commit 60f56b4
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 2 deletions.
2 changes: 1 addition & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"rules": { "tags": ["fresh", "recommended"], "include": ["no-unused-vars"] }
},
"imports": {
"$fresh/": "https://deno.land/x/[email protected].6/",
"$fresh/": "https://deno.land/x/[email protected].8/",
"preact": "https://esm.sh/[email protected]",
"preact/": "https://esm.sh/[email protected]/",
"preact-render-to-string": "https://esm.sh/*[email protected]",
Expand Down
89 changes: 89 additions & 0 deletions routes/api/events/dev/sendemails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { Handlers } from "$fresh/server.ts";
import { Event, getUser, kv, Ticket } from "@/utils/db/kv.ts";
import { isUUID } from "@/utils/db/misc.ts";

export const handler: Handlers = {
async POST(req, _ctx) {
const user = await getUser(req);
if (!user) {
return new Response(JSON.stringify({ error: "Not logged in" }), {
status: 401,
});
}

const allowedEmails = JSON.parse(Deno.env.get("ALLOWED_EMAILS") ?? "[]");

if (!allowedEmails.includes(user.email)) {
return new Response(JSON.stringify({ error: "Not authorized" }), {
status: 401,
});
}

const { eventID, showtimeID }: { eventID: string; showtimeID: string } =
await req.json();

if (!isUUID(eventID) || !isUUID(showtimeID)) {
return new Response(JSON.stringify({ error: "Invalid UUID" }), {
status: 400,
});
}

const event = await kv.get<Event>(["event", eventID]);

if (!event || !event.value) {
return new Response(JSON.stringify({ error: "Invalid event ID" }), {
status: 400,
});
}

const showtime = event.value.showTimes.find((s) => s.id === showtimeID);

if (!showtime) {
return new Response(JSON.stringify({ error: "Invalid showtime ID" }), {
status: 400,
});
}

const getAllTickets = async () => {
const ticketsList = kv.list<Ticket>({
prefix: ["ticket", eventID, showtimeID],
});

const tickets: [string, Ticket][] = [];

for await (const ticket of ticketsList) {
tickets.push([ticket.key[3] as string, ticket.value]);
}

return tickets;
};

const tickets = await getAllTickets();

let delayInEmailSendSeconds = 1;

for (const [ticketID, ticket] of tickets) {
kv.enqueue(
{
action: "sendEmail",
payload: {
to: ticket.userEmail,
code: ticketID,
eventID: eventID,
tickets: ticket.tickets,
eventName: event.value.name,
},
},
{
delay: delayInEmailSendSeconds * 1000,
},
);

delayInEmailSendSeconds += 1;
}

return new Response(JSON.stringify({ success: true }), {
status: 200,
});
},
};
52 changes: 51 additions & 1 deletion utils/email.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// import { kv, Event, Ticket, ShowTime } from "@/utils/db/kv.ts";
import { kv, Event, Ticket, ShowTime } from "@/utils/db/kv.ts";
import { sendEmail } from "@/utils/email/client.ts";

// const cronTask = async () => {
// const events = kv.list<Event>({ prefix: ["event"] });
Expand Down Expand Up @@ -108,3 +109,52 @@
// );
// }
// };

// Handle temporary email notifications

const ticketHTML = await Deno.readTextFile("./out/event.html");

kv.listenQueue(async (msg) => {
const data = msg as {
action: "sendEmail";
payload: {
to: string;
code: string;
eventID: string;
tickets: number;
eventName: string;
};
};

const { eventID, code, tickets, eventName } = data.payload;

const [_, showtimeID, ticketID] = code.split("_");

switch (data.action) {
case "sendEmail": {
const emailHTML = ticketHTML
.replace("{{TICKETS}}", tickets.toString())
.replaceAll(
"{{QR-VALUE}}",
`https://events.deno.dev/api/qr?ticket=${code}`,
)
.replaceAll(
"{{TICKET-LINK}}",
`https://events.deno.dev/events/${eventID}/tickets/${ticketID}?s=${showtimeID}`,
)
.replace(
"{{EVENT-LINK}}",
`https://events.deno.dev/events/${eventID}`,
)
.replace("Tickets for the {{EVENT-NAME}} event!", `Your tickets for {{EVENT-NAME}} next week!`)
.replaceAll("{{EVENT-NAME}}", eventName);

await sendEmail([data.payload.to], `Your Tickets for ${eventName} next week!`, {
html: emailHTML,
fallback: `1 Week until ${eventName}! \nView your ticket at https://events.deno.dev/events/${eventID}/tickets/${ticketID}?s=${showtimeID}`,
})

break;
}
}
});
3 changes: 3 additions & 0 deletions utils/email/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import {
SendEmailCommand,
SendEmailRequest,
SESClient,
SendBulkTemplatedEmailCommand,
CreateTemplateCommand,
SendBulkTemplatedEmailCommandInput
} from "npm:@aws-sdk/client-ses";

export const sesClient = new SESClient({
Expand Down

0 comments on commit 60f56b4

Please sign in to comment.