From 22909b3cc17131cfa2a3cab1df1abb091faa1faf Mon Sep 17 00:00:00 2001 From: shay <43248357+shayypy@users.noreply.github.com> Date: Mon, 9 Dec 2024 12:27:31 -0600 Subject: [PATCH] feat(bot): khl proxy service binding --- packages/bot/src/commands/calendar.ts | 6 ++-- .../bot/src/commands/pickemsLeaderboard.ts | 6 ++-- packages/bot/src/commands/player.ts | 6 ++-- .../bot/src/commands/seasonAutocomplete.ts | 2 +- packages/bot/src/commands/standings.ts | 2 +- packages/bot/src/commands/thread.ts | 2 +- packages/bot/src/cron.ts | 2 +- packages/bot/src/ht/client.ts | 31 +++++++++++++++++-- packages/bot/src/index.ts | 2 +- packages/bot/src/notifications.ts | 4 +-- packages/bot/worker-configuration.d.ts | 1 + packages/bot/wrangler.toml | 2 ++ 12 files changed, 47 insertions(+), 19 deletions(-) diff --git a/packages/bot/src/commands/calendar.ts b/packages/bot/src/commands/calendar.ts index 7a21f3e..9a2323a 100644 --- a/packages/bot/src/commands/calendar.ts +++ b/packages/bot/src/commands/calendar.ts @@ -185,7 +185,7 @@ const sendScheduleMessage = async ( export const scheduleDayCallback: ChatInputAppCommandCallback = async (ctx) => { const league = ctx.getStringOption("league").value as League; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const teamId = ctx.getStringOption("team")?.value; const dateVal = ctx.getStringOption("date")?.value; @@ -228,7 +228,7 @@ export const scheduleMonthCallback: ChatInputAppCommandCallback = async ( ) => { const league = ctx.getStringOption("league").value as League; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const teamId = ctx.getStringOption("team")?.value || undefined; const monthVal = ctx.getStringOption("month")?.value || undefined; const seasonId = ctx.getStringOption("season")?.value || undefined; @@ -288,7 +288,7 @@ export const htGamedayCallback: ChatInputAppCommandCallback = async (ctx) => { const today = getNow(); today.setUTCHours(6, 0, 0, 0); const league = ctx.getStringOption("league").value as HockeyTechLeague; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const teamId = ctx.getStringOption("team")?.value; const team = teamId ? leagueTeams[league].find((t) => t.id === teamId) diff --git a/packages/bot/src/commands/pickemsLeaderboard.ts b/packages/bot/src/commands/pickemsLeaderboard.ts index 8373f76..55dbaac 100644 --- a/packages/bot/src/commands/pickemsLeaderboard.ts +++ b/packages/bot/src/commands/pickemsLeaderboard.ts @@ -37,7 +37,7 @@ export const seasonAutocompleteWithAll: AppCommandAutocompleteCallback = async ( const league = ctx.getStringOption("league").value as HockeyTechLeague; const query = ctx.getStringOption("season").value; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const seasons = (await client.getSeasonList()).SiteKit.Seasons; return [ @@ -69,7 +69,7 @@ export const pickemsLeaderboardCallback: ChatInputAppCommandCallback = async ( | string | undefined; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const seasons = (await client.getSeasonList()).SiteKit.Seasons; if (seasons.length === 0) { return ctx.reply({ @@ -157,7 +157,7 @@ export const pickemsMeCallback: ChatInputAppCommandCallback = async (ctx) => { const league = ctx.getStringOption("league").value as HockeyTechLeague; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const db = getDb(ctx.env.DB); const votes = await db .select({ diff --git a/packages/bot/src/commands/player.ts b/packages/bot/src/commands/player.ts index 352723c..51b6ea0 100644 --- a/packages/bot/src/commands/player.ts +++ b/packages/bot/src/commands/player.ts @@ -78,7 +78,7 @@ const getPlayerEmbed = async ( db?: DBWithSchema, ) => { const locale = getHtLocale(ctx); - const client = getHtClient(league, locale); + const client = getHtClient(ctx.env, league, locale); const player = typeof playerInput === "number" ? (await client.getPlayerProfileBio(playerInput)).SiteKit.Player @@ -351,7 +351,7 @@ export const playerCallback: ChatInputAppCommandCallback = async (ctx) => { ctx.defer(), async () => { const locale = getHtLocale(ctx); - const client = getHtClient(league, locale); + const client = getHtClient(ctx.env, league, locale); const data = await client.searchPerson(query); const players = data.SiteKit.Searchplayers.filter( (p) => p.role_name === "Player", @@ -414,7 +414,7 @@ export const whoisCallback: ChatInputAppCommandCallback = async (ctx) => { return [ ctx.defer({ ephemeral: true }), async () => { - const client = getHtClient(league, getHtLocale(ctx)); + const client = getHtClient(ctx.env, league, getHtLocale(ctx)); const seasons = (await client.getSeasonList()).SiteKit.Seasons; // All star seasons can behave weirdly const season = seasons.find((s) => s.career === "1") ?? seasons[0]; diff --git a/packages/bot/src/commands/seasonAutocomplete.ts b/packages/bot/src/commands/seasonAutocomplete.ts index d3cc2bb..6f6ba27 100644 --- a/packages/bot/src/commands/seasonAutocomplete.ts +++ b/packages/bot/src/commands/seasonAutocomplete.ts @@ -13,7 +13,7 @@ export const seasonAutocomplete: AppCommandAutocompleteCallback = async ( if (!leagues.includes(league)) return []; const query = ctx.getStringOption("season").value; - const client = getHtClient(league); + const client = getHtClient(ctx.env, league); const seasons = (await client.getSeasonList()).SiteKit.Seasons; return seasons diff --git a/packages/bot/src/commands/standings.ts b/packages/bot/src/commands/standings.ts index 69872de..4333845 100644 --- a/packages/bot/src/commands/standings.ts +++ b/packages/bot/src/commands/standings.ts @@ -201,7 +201,7 @@ export const standingsCallback: ChatInputAppCommandCallback = async (ctx) => { const sort = ctx.getStringOption("sort").value || undefined; const seasonId = ctx.getStringOption("season").value || undefined; - const client = getHtClient(league, getHtLocale(ctx)); + const client = getHtClient(ctx.env, league, getHtLocale(ctx)); const standings = await getHtStandings( client, sort, diff --git a/packages/bot/src/commands/thread.ts b/packages/bot/src/commands/thread.ts index 127ac2d..a87820c 100644 --- a/packages/bot/src/commands/thread.ts +++ b/packages/bot/src/commands/thread.ts @@ -71,7 +71,7 @@ export const threadCloseCallback: ChatInputAppCommandCallback = async (ctx) => { return [ ctx.defer({ ephemeral: false, thinking: true }), async () => { - const client = getHtClient(league, getHtLocale(ctx)); + const client = getHtClient(ctx.env, league, getHtLocale(ctx)); const summary = (await client.getGameSummary(gameId)).GC.Gamesummary; await ctx.followup.editOriginalMessage({ diff --git a/packages/bot/src/cron.ts b/packages/bot/src/cron.ts index 4969737..fc7fe56 100644 --- a/packages/bot/src/cron.ts +++ b/packages/bot/src/cron.ts @@ -532,7 +532,7 @@ export const dailyInitNotifications = async ( // Pickems (7 days from now) try { - const client = getHtClient(league); + const client = getHtClient(env, league); const leagueEntries = premiumEntries.filter( (e): e is typeof e & { channelId: Snowflake } => e.league === league && e.channelId !== null, diff --git a/packages/bot/src/ht/client.ts b/packages/bot/src/ht/client.ts index 5200ea4..6e45ff1 100644 --- a/packages/bot/src/ht/client.ts +++ b/packages/bot/src/ht/client.ts @@ -1,4 +1,4 @@ -import fetchAdapter from "@haverstack/axios-fetch-adapter"; +import { createFetchAdapter } from "@haverstack/axios-fetch-adapter"; import HockeyTech from "hockeytech"; export type HockeyTechLeague = @@ -129,10 +129,35 @@ export const hockeyTechLeagues: Record< }, }; -export const getHtClient = (league: HockeyTechLeague, locale?: "en" | "fr") => { +export const getHtClient = ( + env: Env, + league: HockeyTechLeague, + locale?: "en" | "fr", +) => { const config = hockeyTechLeagues[league]; + + let adapter: ReturnType; + if (isKhl(league) && env.KHL) { + // We use a service binding for our first-party KHL hockeytech proxy + // because Cloudflare was causing issues with intra-zone requests. This + // should be faster and reduce costs. If you aren't also hosting a KHL + // proxy on your CF zone, this will adapt automatically and use the + // public instance. + adapter = createFetchAdapter({ + // @ts-expect-error technically incompatible due to missing `webSocket` + // Instead of doing this, I wanted to just pass `env.KHL.fetch`. While + // type-valid, it caused network errors and wouldn't send the request + // to the worker. + fetch(input, init) { + return fetch(input, { ...init, fetcher: env.KHL }); + }, + }); + } else { + adapter = createFetchAdapter(); + } + return new HockeyTech(config.key, config.clientCode, locale, config.proxy, { - adapter: fetchAdapter, + adapter, }); }; diff --git a/packages/bot/src/index.ts b/packages/bot/src/index.ts index 2d0d5bb..be137db 100644 --- a/packages/bot/src/index.ts +++ b/packages/bot/src/index.ts @@ -247,7 +247,7 @@ router }) // .get("/t", async (request, env: Env) => { // const gameId = Number(new URL(request.url).searchParams.get("game")); - // const client = getHtClient("pwhl"); + // const client = getHtClient(env, "pwhl"); // const plays = (await client.getGamePlayByPlay(gameId)).GC.Pxpverbose; // return json( // plays diff --git a/packages/bot/src/notifications.ts b/packages/bot/src/notifications.ts index 82c5c9a..145705e 100644 --- a/packages/bot/src/notifications.ts +++ b/packages/bot/src/notifications.ts @@ -1095,7 +1095,7 @@ const runNotifications = async ({ switch (league) { case "ahl": case "pwhl": { - const client = getHtClient(league); + const client = getHtClient(env, league); const games = (await client.getDailySchedule(day)).SiteKit.Gamesbydate; for (const game of games) { @@ -1517,7 +1517,7 @@ export class DurableNotificationManager implements DurableObject { return new Response("Invalid `league`", { status: 400 }); } - const client = getHtClient(data.league); + const client = getHtClient(this.env, data.league); const games = (await client.getDailySchedule(data.day)).SiteKit.Gamesbydate; console.log( data.league, diff --git a/packages/bot/worker-configuration.d.ts b/packages/bot/worker-configuration.d.ts index aaad781..b34a2f2 100644 --- a/packages/bot/worker-configuration.d.ts +++ b/packages/bot/worker-configuration.d.ts @@ -7,4 +7,5 @@ interface Env { NOTIFICATIONS: DurableObjectNamespace; MONTHLY_SKU?: string; LIFETIME_SKU?: string; + KHL?: Fetcher; } diff --git a/packages/bot/wrangler.toml b/packages/bot/wrangler.toml index 9fd7749..fc8da9a 100644 --- a/packages/bot/wrangler.toml +++ b/packages/bot/wrangler.toml @@ -8,6 +8,8 @@ compatibility_date = "2023-12-18" # season takes place during NA's standard time period triggers.crons = ["0 17 * * *"] +services = [{ binding = "KHL", service = "khl" }] + [[durable_objects.bindings]] name = "NOTIFICATIONS" class_name = "DurableNotificationManager"