Skip to content

Commit

Permalink
Start work on email notifs
Browse files Browse the repository at this point in the history
  • Loading branch information
Blocksnmore committed Mar 14, 2024
1 parent 0f4feed commit 7b3164e
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 10 deletions.
5 changes: 3 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"jsxSingleQuote": false,
"singleQuote": false,
"trailingComma": "all",
"tabWidth": 2,
"endOfLine": "lf"
"tabWidth": 4,
"endOfLine": "lf",
"useTabs": true
}
9 changes: 4 additions & 5 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
"lock": false,
"tasks": {
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
// Do items like reordering imports
"fmt": "deno fmt && npx prettier . --write",
"start": "deno run -A --unstable-kv --watch=static/,routes/ dev.ts",
"build": "deno run -A --unstable-kv dev.ts build",
"preview": "deno run --unstable-kv -A main.ts",
"update": "deno run --unstable-kv -A -r https://fresh.deno.dev/update ."
"start": "deno run -A --unstable-kv --unstable-cron --watch=static/,routes/ dev.ts",
"build": "deno run -A --unstable-kv --unstable-cron dev.ts build",
"preview": "deno run --unstable-kv --unstable-cron -A main.ts",
"update": "deno run --unstable-kv --unstable-cron -A -r https://fresh.deno.dev/update ."
},
"lint": {
"rules": { "tags": ["fresh", "recommended"], "include": ["no-unused-vars"] }
Expand Down
1 change: 1 addition & 0 deletions fresh.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { defineConfig } from "$fresh/server.ts";
import tailwind from "$fresh/plugins/tailwind.ts";
import { kvInsightsPlugin } from "https://deno.land/x/[email protected]/mod.ts";
import { kv } from "@/utils/db/kv.ts";
import "./utils/email.ts";

export default defineConfig({
plugins: [
Expand Down
3 changes: 0 additions & 3 deletions utils/dates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ const timeFmt = new Intl.DateTimeFormat("en-US", {
hour: "numeric",
minute: "2-digit",
});
const timezoneFmt = new Intl.DateTimeFormat("en-US", {
timeZoneName: "short",
});

export const happened = (startDate: string, startTime?: string) => {
const date = new Date(startDate);
Expand Down
2 changes: 2 additions & 0 deletions utils/db/kv.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface ShowTime {
soldTickets: number;
maxTickets: number;
multiPurchase: boolean;
hasEmailed?: boolean;
}

export const defaultEvent: Event = {
Expand All @@ -64,6 +65,7 @@ export const defaultEvent: Event = {
soldTickets: 0,
maxTickets: 75,
multiPurchase: true,
hasEmailed: false,
},
],

Expand Down
110 changes: 110 additions & 0 deletions utils/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { kv, Event, Ticket, ShowTime } from "@/utils/db/kv.ts";

const cronTask = async () => {
const events = kv.list<Event>({ prefix: ["event"] });

for await (const event of events) {
const showtimes = event.value.showTimes
.filter((s) => !s.hasEmailed)
.sort(
(a, b) =>
new Date(a.startDate).valueOf() -
new Date(b.startDate).valueOf(),
);

const showtimesStartingIn24Hours = showtimes.filter(
(showtime) =>
new Date(showtime.startDate).valueOf() - Date.now() <
24 * 60 * 60 * 1000,
);

if (showtimesStartingIn24Hours.length > 0) {
await kv.enqueue(
JSON.stringify({
event,
showtimesStartingIn24Hours,
eventID: event.key[1],
}),
);
}
}
};

cronTask();

// Deno.cron("check emails", "0 */4 * * *", cronTask);

kv.listenQueue(async (msg) => {
const message = JSON.parse(msg) as
| {
eventID: string;
event: Event;
showtimesStartingIn24Hours: Event["showTimes"];
}
| {
eventID: string;
event: Event;
showtime: ShowTime;
cursor: string;
};

if ("showtimesStartingIn24Hours" in message) {
let delay = 0;

for (const showtime of message.showtimesStartingIn24Hours) {
await kv.set(["event", message.eventID], {
...message.event,
showTimes: message.event.showTimes.map((s) =>
s.id === showtime.id ? { ...s, hasEmailed: true } : s,
),
});
await kv.enqueue(
JSON.stringify({
eventID: message.eventID,
event: message.event,
showtime,
}),
{
delay: delay,
},
);

delay += 1000 + Math.random() * 3000;
}
} else {
await startEmails(
message.eventID,
message.event,
message.showtime,
message.cursor,
);
}
});

const startEmails = async (
eventID: string,
event: Event,
showtime: ShowTime,
cursor?: string,
) => {
const tickets = kv.list<Ticket>(
{ prefix: ["ticket", eventID, showtime.id] },
{ cursor, limit: 18 },
);

for await (const ticket of tickets) {
console.log("Sending email to", ticket.value.userEmail);
}

if (tickets.cursor) {
await kv.enqueue(
JSON.stringify({
eventID,
event,
showtime,
cursor: tickets.cursor,
}),
{ delay: 1000 },
);
}
};
1 change: 1 addition & 0 deletions utils/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const YupShowtimeValidation = Yup.array()
maxTickets: Yup.number().required(),
id: Yup.string().uuid().required(),
multiPurchase: Yup.boolean().required(),
hasEmailed: Yup.boolean().optional()
}),
);

Expand Down

0 comments on commit 7b3164e

Please sign in to comment.