Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
EthanThatOneKid committed Mar 5, 2024
1 parent 436a581 commit a7cda1e
Show file tree
Hide file tree
Showing 14 changed files with 166 additions and 367 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PORT=8080
WEBHOOK_TOKEN=""
DISCORD_APPLICATION_ID=""
DISCORD_TOKEN=""
DISCORD_PUBLIC_KEY=""
DISCORD_WEBHOOK_URL=""
DISCORD_CHANNEL_ID=""
KV_URL=""
28 changes: 0 additions & 28 deletions .github/workflows/cf.yaml

This file was deleted.

24 changes: 1 addition & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,7 @@ The server is automatically deployed on push to the `main` branch via

### Daily webhook invocation

The daily webhook is invoked by making a POST request to the `/webhook/:token`
endpoint.

Set up a cron job to make the request at the desired time. Supabase supports
cron jobs via the
[pg_cron](https://supabase.com/docs/guides/database/extensions/pg_cron)
extension.

```sql
select cron.unschedule('lc-daily');

select
cron.schedule(
'lc-daily',
'0 0 * * *', -- https://crontab.guru/#0_0_*_*_*
$$
select
net.http_post(
url:='...',
) as request_id;
$$
);
```
The daily webhook is invoked by a daily Deno Cron job.

---

Expand Down
2 changes: 0 additions & 2 deletions deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
"test": "deno test --unstable",
"start": "deno run -A --unstable main.ts",
"ngrok": "ngrok http 8080",
"cf:push": "deno run -A tasks/cf/dailies/push/main.ts",
"cf:serve": "deno run -A tasks/cf/dailies/serve/main.ts",
"dnt": "deno run -A tasks/dnt/main.ts"
},
"imports": {
Expand Down
220 changes: 110 additions & 110 deletions deno.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export {
assertEquals,
assertRejects,
} from "https://deno.land/std@0.211.0/assert/mod.ts";
export { load } from "https://deno.land/std@0.211.0/dotenv/mod.ts";
export * from "https://deno.land/std@0.211.0/datetime/constants.ts";
} from "https://deno.land/std@0.218.2/assert/mod.ts";
export { load } from "https://deno.land/std@0.218.2/dotenv/mod.ts";
export * from "https://deno.land/std@0.218.2/datetime/constants.ts";
export { ulid } from "https://deno.land/x/[email protected]/mod.ts";
export type {
APIApplicationCommandInteractionDataOption,
Expand All @@ -16,12 +16,12 @@ export type {
APIUser,
RESTPostAPIApplicationCommandsJSONBody,
RESTPostAPIWebhookWithTokenJSONBody,
} from "https://deno.land/x/[email protected].67/v10.ts";
} from "https://deno.land/x/[email protected].71/v10.ts";
export {
ApplicationCommandOptionType,
InteractionResponseType,
InteractionType,
MessageFlags,
Utils,
} from "https://deno.land/x/[email protected].67/v10.ts";
} from "https://deno.land/x/[email protected].71/v10.ts";
export { default as nacl } from "https://cdn.skypack.dev/[email protected]";
7 changes: 0 additions & 7 deletions env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ await load({ export: true });
*/
export const PORT = parseInt(Deno.env.get("PORT") || "8080");

/**
* WEBHOOK_TOKEN is used to authenticate requests to execute our webhook.
*
* Usage: POST /daily/:token
*/
export const WEBHOOK_TOKEN = Deno.env.get("WEBHOOK_TOKEN")!;

/**
* DISCORD_APPLICATION_ID is the application ID of the Discord application.
*/
Expand Down
52 changes: 15 additions & 37 deletions lib/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,41 @@
import * as discord from "lc-dailies/lib/discord/mod.ts";
import * as lc from "lc-dailies/lib/lc/mod.ts";
import * as leaderboard from "lc-dailies/lib/leaderboard/mod.ts";
import * as router from "lc-dailies/lib/router/mod.ts";
import * as discord_app from "./discord_app/mod.ts";
import {
makeDailyWebhookPostHandler,
makeManualDailyWebhookPostHandler,
} from "./dailies.ts";
import {
makeSeasonGetHandler,
makeSeasonsGetHandler,
makeSeasonTxtGetHandler,
} from "./seasons.ts";

export interface APIRouterOptions {
discordApplicationID: string;
discordPublicKey: string;
discordChannelID: string;
leaderboardClient: leaderboard.LeaderboardClient;
}

/**
* makeAPIRouter creates a router which handles requests on the
* LC-Dailies API.
*/
export function makeAPIRouter(
discordApplicationID: string,
discordPublicKey: string,
discordChannelID: string,
webhookURL: string,
webhookToken: string,
lcClient: lc.LCClient,
leaderboardClient: leaderboard.LeaderboardClient,
) {
export function makeAPIRouter(options: APIRouterOptions) {
return new router.Router()
.post(
new URLPattern({ pathname: "/" }),
discord_app.withErrorResponse(
discord_app.makeDiscordAppHandler(
leaderboardClient,
discordPublicKey,
discordChannelID,
options.leaderboardClient,
options.discordPublicKey,
options.discordChannelID,
),
),
)
.post(
new URLPattern({ pathname: "/webhook" }),
makeManualDailyWebhookPostHandler(
lcClient,
leaderboardClient,
),
)
.post(
new URLPattern({ pathname: "/webhook/:token" }),
makeDailyWebhookPostHandler(
lcClient,
leaderboardClient,
webhookURL,
webhookToken,
),
)
.get(
new URLPattern({ pathname: "/invite" }),
() =>
Promise.resolve(
Response.redirect(makeInviteURL(discordApplicationID)),
Response.redirect(makeInviteURL(options.discordApplicationID)),
),
)
.get(
Expand All @@ -69,15 +47,15 @@ export function makeAPIRouter(
)
.get(
new URLPattern({ pathname: "/seasons" }),
withCORS(makeSeasonsGetHandler(leaderboardClient)),
withCORS(makeSeasonsGetHandler(options.leaderboardClient)),
)
.get(
new URLPattern({ pathname: "/seasons/:season_id.txt" }),
withCORS(makeSeasonTxtGetHandler(leaderboardClient)),
withCORS(makeSeasonTxtGetHandler(options.leaderboardClient)),
)
.get(
new URLPattern({ pathname: "/seasons/:season_id" }),
withCORS(makeSeasonGetHandler(leaderboardClient)),
withCORS(makeSeasonGetHandler(options.leaderboardClient)),
);
}

Expand Down
71 changes: 2 additions & 69 deletions lib/api/dailies.ts
Original file line number Diff line number Diff line change
@@ -1,82 +1,15 @@
import { type APIEmbed, WEEK } from "lc-dailies/deps.ts";
import * as api from "./mod.ts";
import * as discord from "lc-dailies/lib/discord/mod.ts";
import * as router from "lc-dailies/lib/router/mod.ts";
import * as lc from "lc-dailies/lib/lc/mod.ts";
import * as leaderboard from "lc-dailies/lib/leaderboard/mod.ts";
import * as snacks from "./snacks.ts";

/**
* makeDailyWebhookPostHandler creates a handler for daily webhook POST requests.
*/
export function makeDailyWebhookPostHandler(
lcClient: lc.LCClient,
leaderboardClient: leaderboard.LeaderboardClient,
webhookURL: string,
webhookToken?: string,
) {
/**
* handlePostDailyWebhook handles POST requests to the daily webhook.
*/
return async function handlePostDailyWebhook(
request: router.RouterRequest,
): Promise<Response> {
// Override the webhook URL if applicable.
const overrideWebhookURL = request.url.searchParams.get("webhook_url");
if (overrideWebhookURL) {
webhookURL = overrideWebhookURL;
}

// Check the webhook token.
const token = request.params["token"];
if (!overrideWebhookURL && webhookToken && token !== webhookToken) {
return new Response("Invalid token", { status: 401 });
}

// Get the season ID if applicable.
const seasonID = request.url.searchParams.get("season_id");

// Execute the webhook.
return await executeDailyWebhook(
lcClient,
leaderboardClient,
webhookURL,
seasonID,
);
};
}

/**
* makeManualDailyWebhookPostHandler creates a handler for any variable
* webhook URL POST requests.
*/
export function makeManualDailyWebhookPostHandler(
lcClient: lc.LCClient,
leaderboardClient: leaderboard.LeaderboardClient,
) {
return async function handleManualPostDailyWebhook(
request: router.RouterRequest,
): Promise<Response> {
const seasonID = request.url.searchParams.get("season_id");
const webhookURL = request.url.searchParams.get("webhook_url");
if (!webhookURL) {
return new Response("Missing webhook_url", { status: 400 });
}

return await executeDailyWebhook(
lcClient,
leaderboardClient,
webhookURL,
seasonID,
);
};
}

async function executeDailyWebhook(
export async function executeDailyWebhook(
lcClient: lc.LCClient,
leaderboardClient: leaderboard.LeaderboardClient,
webhookURL: string,
seasonID: string | null,
seasonID?: string | null,
): Promise<Response> {
// Get the daily question.
const question = await lcClient.getDailyQuestion();
Expand Down
23 changes: 23 additions & 0 deletions lib/cron/cron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { executeDailyWebhook } from "lc-dailies/lib/api/dailies.ts";
import * as lc from "lc-dailies/lib/lc/mod.ts";
import { DISCORD_WEBHOOK_URL, KV_URL } from "lc-dailies/env.ts";
import { DenoKvLeaderboardClient } from "lc-dailies/lib/leaderboard/denokv/mod.ts";

export function setupCron() {
Deno.cron("discord_webhook", { dayOfWeek: { every: 1 } }, async () => {
const kv = await Deno.openKv(KV_URL);
const lcClient = new lc.LCClient();
const leaderboardClient = new DenoKvLeaderboardClient(
kv,
lcClient,
);
await executeDailyWebhook(
lcClient,
leaderboardClient,
DISCORD_WEBHOOK_URL,
);
});

// TODO: Abstract sync function from executeDailyWebhook.
Deno.cron("sync", {}, () => {});
}
68 changes: 0 additions & 68 deletions lib/denoflare/denoflare.ts

This file was deleted.

1 change: 0 additions & 1 deletion lib/denoflare/mod.ts

This file was deleted.

Loading

1 comment on commit a7cda1e

@deno-deploy
Copy link

@deno-deploy deno-deploy bot commented on a7cda1e Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed to deploy:

UNCAUGHT_EXCEPTION

MissingEnvVarsError: The following variables were defined in the example file but are not present in the environment:
  KV_URL

Make sure to add them to your env file.

If you expect any of these variables to be empty, you can set the allowEmptyValues option to true.
    at assertSafe (https://deno.land/[email protected]/dotenv/mod.ts:363:11)
    at load (https://deno.land/[email protected]/dotenv/mod.ts:295:5)
    at eventLoopTick (ext:core/01_core.js:153:7)
    at async file:///src/env.ts:3:1

Please sign in to comment.