refactor: ♻️emoves Env parameter

Removes the `Env` parameter from several functions to simplify their signatures and rely on the global `env` for configuration.

This change reduces the number of arguments passed around, making the code cleaner and easier to maintain.
This commit is contained in:
2025-08-10 19:22:14 -04:00
parent 0b0078328c
commit 8175d73df1
26 changed files with 8716 additions and 184 deletions

View File

@@ -1,12 +1,10 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { env } from "hono/adapter";
import { streamSSE } from "hono/streaming";
import { fetchEpisodes } from "~/controllers/episodes/getByAniListId";
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
import { associateDeviceIdWithUsername } from "~/models/token";
import { setWatchStatus } from "~/models/watchStatus";
import type { Env } from "~/types/env";
import { EpisodesResponseSchema } from "~/types/episode";
import { ErrorResponse, ErrorResponseSchema } from "~/types/schema";
import { Title } from "~/types/title";
@@ -87,7 +85,7 @@ const route = createRoute({
},
});
const app = new OpenAPIHono<Env>();
const app = new OpenAPIHono<Cloudflare.Env>();
app.openapi(route, async (c) => {
const deviceId =
@@ -112,11 +110,7 @@ app.openapi(route, async (c) => {
}
try {
await associateDeviceIdWithUsername(
env(c, "workerd"),
deviceId!,
user.name!,
);
await associateDeviceIdWithUsername(deviceId!, user.name!);
} catch (error) {
console.error("Failed to associate device");
console.error(error);
@@ -157,17 +151,12 @@ app.openapi(route, async (c) => {
const mediaListEntry = media.mediaListEntry;
if (mediaListEntry) {
const { wasAdded } = await setWatchStatus(
env(c, "workerd"),
deviceId!,
media.id,
mediaListEntry.status,
);
if (wasAdded) {
await maybeScheduleNextAiringEpisode(
env<Env, typeof c>(c, "workerd"),
c.req,
media.id,
);
await maybeScheduleNextAiringEpisode(c.req, media.id);
}
}

View File

@@ -4,14 +4,12 @@ import { PromiseTimedOutError, promiseTimeout } from "~/libs/promiseTimeout";
import { readEnvVariable } from "~/libs/readEnvVariable";
import { sortByProperty } from "~/libs/sortByProperty";
import { getValue, setValue } from "~/models/kv";
import type { Env } from "~/types/env";
import type { EpisodesResponse } from "~/types/episode";
export async function getEpisodesFromAnify(
env: Env,
aniListId: number,
): Promise<EpisodesResponse | null> {
if (await shouldSkipAnify(env, aniListId)) {
if (await shouldSkipAnify(aniListId)) {
console.log("Skipping Anify for title", aniListId);
return null;
}
@@ -33,7 +31,6 @@ export async function getEpisodesFromAnify(
DateTime.now().plus({ minutes: 1 }).toISO(),
);
setValue(
env,
"anify_killswitch_till",
DateTime.now().plus({ minutes: 1 }).toISO(),
);
@@ -93,11 +90,8 @@ export async function getEpisodesFromAnify(
};
}
export async function shouldSkipAnify(
env: Env,
aniListId: number,
): Promise<boolean> {
if (!readEnvVariable(env, "ENABLE_ANIFY")) {
export async function shouldSkipAnify(aniListId: number): Promise<boolean> {
if (!readEnvVariable("ENABLE_ANIFY")) {
return true;
}
@@ -114,7 +108,7 @@ export async function shouldSkipAnify(
return true;
}
return await getValue(env, "anify_killswitch_till").then((dateTime) => {
return await getValue("anify_killswitch_till").then((dateTime) => {
if (!dateTime) {
return false;
}

View File

@@ -1,6 +1,5 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import type { Env } from "~/types/env";
import { EpisodesResponseSchema } from "~/types/episode";
import {
AniListIdQuerySchema,
@@ -37,7 +36,7 @@ const route = createRoute({
},
});
const app = new OpenAPIHono<Env>();
const app = new OpenAPIHono<Cloudflare.Env>();
export function fetchEpisodes(aniListId: number, shouldRetry: boolean = false) {
return import("./aniwatch")

View File

@@ -1,6 +1,5 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import type { Env } from "~/types/env";
import { FetchUrlResponse } from "~/types/episode/fetch-url-response";
import {
AniListIdQuerySchema,
@@ -65,7 +64,7 @@ const route = createRoute({
},
});
const app = new OpenAPIHono<Env>();
const app = new OpenAPIHono<Cloudflare.Env>();
export async function fetchEpisodeUrl({
id,

View File

@@ -2,7 +2,6 @@ import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { env } from "hono/adapter";
import { updateWatchStatus } from "~/controllers/watch-status";
import type { Env } from "~/types/env";
import {
AniListIdQuerySchema,
EpisodeNumberSchema,
@@ -63,7 +62,7 @@ const route = createRoute({
},
});
const app = new OpenAPIHono<Env>();
const app = new OpenAPIHono<Cloudflare.Env>();
app.openapi(route, async (c) => {
const aniListToken = c.req.header("X-AniList-Token");
@@ -85,13 +84,7 @@ app.openapi(route, async (c) => {
isComplete,
);
if (isComplete) {
await updateWatchStatus(
env(c, "workerd"),
c.req,
deviceId,
aniListId,
"COMPLETED",
);
await updateWatchStatus(c.req, deviceId, aniListId, "COMPLETED");
}
if (!user) {

View File

@@ -1,6 +1,5 @@
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { env } from "hono/adapter";
import { z } from "zod";
import { fetchEpisodeUrl } from "~/controllers/episodes/getEpisodeUrl";
@@ -9,7 +8,6 @@ import { sendFcmMessage } from "~/libs/gcloud/sendFcmMessage";
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
import { getTokensSubscribedToTitle } from "~/models/token";
import { isWatchingTitle } from "~/models/watchStatus";
import type { Env } from "~/types/env";
import {
AniListIdSchema,
EpisodeNumberSchema,
@@ -36,7 +34,7 @@ app.post(
`Internal new episode route, aniListId: ${aniListId}, episodeNumber: ${episodeNumber}`,
);
if (!(await isWatchingTitle(env<Env, typeof c>(c, "workerd"), aniListId))) {
if (!(await isWatchingTitle(aniListId))) {
console.log(`Title ${aniListId} is no longer being watched`);
return c.json(
{ success: true, result: { isNoLongerWatching: true } },
@@ -53,35 +51,25 @@ app.post(
);
}
const tokens = await getTokensSubscribedToTitle(
env<Env, typeof c>(c, "workerd"),
aniListId,
);
const tokens = await getTokensSubscribedToTitle(aniListId);
await Promise.allSettled(
tokens.map(async (token) => {
return sendFcmMessage(
getAdminSdkCredentials(env<Env, typeof c>(c, "workerd")),
{
token,
data: {
type: "new_episode",
episodes: JSON.stringify(episodes),
episodeStreamInfo: JSON.stringify(fetchUrlResult),
aniListId: aniListId.toString(),
episodeNumber: episodeNumber.toString(),
},
android: { priority: "high" },
return sendFcmMessage(getAdminSdkCredentials(), {
token,
data: {
type: "new_episode",
episodes: JSON.stringify(episodes),
episodeStreamInfo: JSON.stringify(fetchUrlResult),
aniListId: aniListId.toString(),
episodeNumber: episodeNumber.toString(),
},
);
android: { priority: "high" },
});
}),
);
await maybeScheduleNextAiringEpisode(
env<Env, typeof c>(c, "workerd"),
c.req,
aniListId,
);
await maybeScheduleNextAiringEpisode(c.req, aniListId);
return c.json(SuccessResponse, 200);
},

View File

@@ -6,7 +6,6 @@ import { DateTime } from "luxon";
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
import { getValue, setValue } from "~/models/kv";
import { filterUnreleasedTitles } from "~/models/unreleasedTitles";
import type { Env } from "~/types/env";
import type { Title } from "~/types/title";
import { MediaFragment } from "~/types/title/mediaFragment";
@@ -49,12 +48,11 @@ type AiringSchedule = {
id: number;
};
export async function getUpcomingTitlesFromAnilist(env: Env, req: HonoRequest) {
export async function getUpcomingTitlesFromAnilist(req: HonoRequest) {
const client = new GraphQLClient("https://graphql.anilist.co/");
const lastCheckedScheduleAt = await getValue(
env,
"schedule_last_checked_at",
).then((value) => (value ? Number(value) : DateTime.now().toUnixInteger()));
const lastCheckedScheduleAt = await getValue("schedule_last_checked_at").then(
(value) => (value ? Number(value) : DateTime.now().toUnixInteger()),
);
const twoDaysFromNow = DateTime.now().plus({ days: 2 }).toUnixInteger();
let currentPage = 1;
@@ -72,7 +70,6 @@ export async function getUpcomingTitlesFromAnilist(env: Env, req: HonoRequest) {
const { airingSchedules, pageInfo } = Page!;
plannedToWatchTitles = plannedToWatchTitles.union(
await filterUnreleasedTitles(
env,
airingSchedules!.map((schedule) => schedule!.media?.id!),
),
);
@@ -90,7 +87,7 @@ export async function getUpcomingTitlesFromAnilist(env: Env, req: HonoRequest) {
await Promise.all(
Array.from(plannedToWatchTitles).map((titleId) =>
maybeScheduleNextAiringEpisode(env, req, titleId),
maybeScheduleNextAiringEpisode(req, titleId),
),
);
@@ -99,7 +96,6 @@ export async function getUpcomingTitlesFromAnilist(env: Env, req: HonoRequest) {
}
await setValue(
env,
"schedule_last_checked_at",
scheduleList[scheduleList.length - 1].airingAt.toString(),
);

View File

@@ -1,10 +1,8 @@
import { Hono } from "hono";
import { env } from "hono/adapter";
import { DateTime } from "luxon";
import { getAdminSdkCredentials } from "~/libs/gcloud/getAdminSdkCredentials";
import { sendFcmMessage } from "~/libs/gcloud/sendFcmMessage";
import type { Env } from "~/types/env";
import { SuccessResponse } from "~/types/schema";
import { getUpcomingTitlesFromAnilist } from "./anilist";
@@ -12,10 +10,7 @@ import { getUpcomingTitlesFromAnilist } from "./anilist";
const app = new Hono();
app.post("/", async (c) => {
const titles = await getUpcomingTitlesFromAnilist(
env<Env, typeof c>(c, "workerd"),
c.req,
);
const titles = await getUpcomingTitlesFromAnilist(c.req);
await Promise.allSettled(
titles.map(async (title) => {
@@ -24,7 +19,7 @@ app.post("/", async (c) => {
title.media.title?.english ??
"Unknown Title";
return sendFcmMessage(getAdminSdkCredentials(c.env), {
return sendFcmMessage(getAdminSdkCredentials(), {
topic: "newTitles",
data: {
type: "new_title",

View File

@@ -4,7 +4,6 @@ import { env } from "hono/adapter";
import { getAdminSdkCredentials } from "~/libs/gcloud/getAdminSdkCredentials";
import { verifyFcmToken } from "~/libs/gcloud/verifyFcmToken";
import { saveToken } from "~/models/token";
import type { Env } from "~/types/env";
import {
ErrorResponse,
ErrorResponseSchema,
@@ -68,15 +67,12 @@ app.openapi(route, async (c) => {
const { token, deviceId } = await c.req.json<typeof SaveTokenRequest._type>();
try {
const isValidToken = await verifyFcmToken(
token,
getAdminSdkCredentials(c.env),
);
const isValidToken = await verifyFcmToken(token, getAdminSdkCredentials());
if (!isValidToken) {
return c.json(ErrorResponse, 401);
}
await saveToken(env(c, "workerd"), deviceId, token);
await saveToken(deviceId, token);
} catch (error) {
console.error("Failed to save token");
console.error(error);

View File

@@ -1,13 +1,11 @@
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import type { HonoRequest } from "hono";
import { env } from "hono/adapter";
import { maybeScheduleNextAiringEpisode } from "~/libs/maybeScheduleNextAiringEpisode";
import { buildNewEpisodeTaskId } from "~/libs/tasks/id";
import { queueTask } from "~/libs/tasks/queueTask";
import { removeTask } from "~/libs/tasks/removeTask";
import { setWatchStatus } from "~/models/watchStatus";
import type { Env } from "~/types/env";
import {
AniListIdSchema,
ErrorResponse,
@@ -19,7 +17,7 @@ import { WatchStatus } from "~/types/title/watchStatus";
import { maybeUpdateWatchStatusOnAnilist } from "./anilist";
const app = new OpenAPIHono<Env>();
const app = new OpenAPIHono<Cloudflare.Env>();
const UpdateWatchStatusRequest = z.object({
deviceId: z.string(),
@@ -67,22 +65,20 @@ const route = createRoute({
});
export async function updateWatchStatus(
env: Env,
req: HonoRequest,
deviceId: string,
titleId: number,
watchStatus: WatchStatus | null,
) {
const { wasAdded, wasDeleted } = await setWatchStatus(
env,
deviceId,
Number(titleId),
watchStatus,
);
if (wasAdded) {
await maybeScheduleNextAiringEpisode(env, req, titleId);
await maybeScheduleNextAiringEpisode(req, titleId);
} else if (wasDeleted) {
await removeTask(env, "new-episode", buildNewEpisodeTaskId(titleId));
await removeTask("new-episode", buildNewEpisodeTaskId(titleId));
}
}
@@ -97,13 +93,7 @@ app.openapi(route, async (c) => {
if (!isRetrying) {
try {
await updateWatchStatus(
env(c, "workerd"),
c.req,
deviceId,
titleId,
watchStatus,
);
await updateWatchStatus(c.req, deviceId, titleId, watchStatus);
} catch (error) {
console.error("Error setting watch status");
console.error(error);
@@ -125,7 +115,6 @@ app.openapi(route, async (c) => {
}
await queueTask(
env(c, "workerd"),
"anilist-updates",
{
deviceId,