Skip to content

Commit

Permalink
Generate message for stats command
Browse files Browse the repository at this point in the history
  • Loading branch information
MattIPv4 committed Nov 15, 2023
1 parent 230dabe commit 83ecde9
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 6 deletions.
116 changes: 110 additions & 6 deletions src/commands/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
import type { Command } from "workers-discord";

import getStats from "../util/stats";
import checkDate from "../util/check";
import { bold, date, italic, money, number } from "../util/format";
import type { CtxWithEnv } from "../env";

const statsCommand: Command<CtxWithEnv> = {
Expand All @@ -15,26 +17,128 @@ const statsCommand: Command<CtxWithEnv> = {
wait(
(async () => {
const stats = await getStats(context.env.STATS_API_ENDPOINT);
console.log(stats);

// Check if Jingle Jam is running
const start = new Date(stats.event.start);
const check = checkDate(start);
// TODO: Re-enable this check once testing is done
// if (check) return edit({ content: check });

// Check if Jingle Jam has finished
const end = new Date(stats.event.end);
if (isNaN(+end)) throw new Error("Invalid end date");

// Time since launch
// TODO: Switch back to using the current time once testing is done
// const now = new Date();
const now = end;
const timeSinceLaunch = Math.min(
now.getTime() - start.getTime(),
end.getTime() - start.getTime(),
);
const hoursSinceLaunch = Math.max(
timeSinceLaunch / 1000 / 60 / 60,
1,
);
const daysSinceLaunch = Math.max(hoursSinceLaunch / 24, 1);

// Format some stats
const totalRaised = bold(
money(
"£",
stats.raised.yogscast + stats.raised.fundraisers,
),
);
const totalYogscast = bold(money("£", stats.raised.yogscast));
const totalFundraisers = bold(
money("£", stats.raised.fundraisers),
);

const historyRaised = bold(
money(
"£",
stats.raised.yogscast +
stats.raised.fundraisers +
stats.history.reduce(
(total, year) => total + year.total.pounds,
0,
),
),
);
const historyDonations = bold(
number(
stats.donations.count +
stats.history.reduce(
(total, year) => total + year.donations,
0,
),
),
);
const historyYears = bold(number(stats.history.length));
const historyOldest = bold(
Math.min(
...stats.history.map((year) => year.year),
).toString(),
);

const bundles = bold(number(stats.collections.redeemed));
const average = bold(
money("£", stats.raised.yogscast / stats.donations.count),
);

const perHourDonations = bold(
number(stats.donations.count / hoursSinceLaunch, 0),
);
const perDayDonations = bold(
number(stats.donations.count / daysSinceLaunch, 0),
);
const perHourBundles = bold(
number(stats.collections.redeemed / hoursSinceLaunch, 0),
);
const perDayBundles = bold(
number(stats.collections.redeemed / daysSinceLaunch, 0),
);

await edit({
content: `Total Raised: ${
stats.raised.yogscast + stats.raised.fundraisers
}`,
content: [
bold(
`:snowflake: Jingle Jam ${stats.event.year} Stats`,
),
italic(
`Last updated ${date(new Date(stats.date), true)}`,
),
"",
`:money_with_wings: We've raised a total of ${totalRaised} for charity during Jingle Jam ${stats.event.year} so far!`,
` Of that, ${totalYogscast} by the Yogscast, and ${totalFundraisers} from community fundraisers.`,
"",
`:scroll: Over the past ${historyYears} years, plus this year, we've raised a total of ${historyRaised} for charity!`,
` Since ${historyOldest}, we've received ${historyDonations} charitable donations as part of Jingle Jam.`,
"",
`:package: So far, ${bundles} bundles have been redeemed, with the average donation being ${average}.`,
` That works out to an average of ${perHourBundles} bundles claimed per hour, or ${perDayBundles} bundles per day.`,
` We've also received an average of ${perHourDonations} donations per hour, or ${perDayDonations} donations per day.`,
"",
`:heart: Thank you for supporting some wonderful causes! Get involved at <https://jinglejam.tiltify.com>`,
].join("\n"),
});
})().catch(async (error) => {
console.error(error);

await edit({
content: "An error occurred while fetching the stats.",
content: [
":pensive: Sorry, an error occurred while fetching the stats.",
italic(
"An ~~angry~~ polite message has been sent to the team letting them know.",
),
].join("\n"),
});
}),
);

return response({
type: InteractionResponseType.ChannelMessageWithSource,
data: {
content: "Fetching...",
content: ":package: Fetching the latest bundle stats...",
flags: MessageFlags.Ephemeral,
},
});
Expand Down
23 changes: 23 additions & 0 deletions src/util/check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { date, time } from "./format";

const checkDate = (start: Date) => {
// Ensure we have a valid date
if (isNaN(+start)) throw new Error("Invalid start date");

// If the date is in the past, we're fine
if (start < new Date()) return null;

// If we're within the same day, show the time
if (start.getDate() === new Date().getDate()) {
return `The Jingle Jam bundle hasn't launched yet! Get ready to raise money for some awesome causes and grab the bundle when it goes live at ${time(
start,
)}.`;
}

// Otherwise, show the date
return `It's not currently Jingle Jam time. We look forward to seeing you on ${date(
start,
)} when we'll be back to raise money again!`;
};

export default checkDate;
43 changes: 43 additions & 0 deletions src/util/format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export const money = (currency: string, amount: number) =>
`${currency}${amount.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}`;

export const date = (date: Date, time = false) =>
date.toLocaleString(undefined, {
month: "long",
day: "numeric",
...(time && {
hour: "numeric",
minute: "numeric",
timeZone: "GMT",
timeZoneName: "short",
}),
});

export const time = (date: Date, seconds = false) =>
date.toLocaleString(undefined, {
hour: "numeric",
minute: "numeric",
timeZone: "GMT",
timeZoneName: "short",
...(seconds && {
second: "numeric",
}),
});

export const number = (
number: number,
decimals: number | undefined = undefined,
) =>
number.toLocaleString(undefined, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
});

export const bold = (text: string, escape = true) =>
`**${escape ? text.replace(/\*/g, "\\*") : text}**`;

export const italic = (text: string, escape = true) =>
`*${escape ? text.replace(/\*/g, "\\*") : text}*`;

0 comments on commit 83ecde9

Please sign in to comment.