Compare commits
7 Commits
9da626f17b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b237d542b | |||
| c01e005afb | |||
| e5d9d62be2 | |||
| 8d63d4fa5e | |||
| 07bece1f6c | |||
| 2ed38e92bc | |||
| 26ca15d4aa |
@@ -15,7 +15,7 @@ type AiringSchedule = {
|
||||
id: number;
|
||||
};
|
||||
|
||||
export async function getUpcomingTitlesFromAnilist(req: HonoRequest) {
|
||||
export async function getUpcomingTitlesFromAnilist() {
|
||||
const durableObjectId = env.ANILIST_DO.idFromName("GLOBAL");
|
||||
const stub = env.ANILIST_DO.get(durableObjectId);
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import { getUpcomingTitlesFromAnilist } from "./anilist";
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
app.post("/", async (c) => {
|
||||
const titles = await getUpcomingTitlesFromAnilist(c.req);
|
||||
export async function checkUpcomingTitles() {
|
||||
const titles = await getUpcomingTitlesFromAnilist();
|
||||
|
||||
await Promise.allSettled(
|
||||
titles.map(async (title) => {
|
||||
@@ -44,6 +44,10 @@ app.post("/", async (c) => {
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
app.post("/", async (c) => {
|
||||
await checkUpcomingTitles();
|
||||
|
||||
return c.json(SuccessResponse, 200);
|
||||
});
|
||||
|
||||
@@ -51,7 +51,7 @@ describe('requests the "/title" route', () => {
|
||||
headers: new Headers({ "x-anilist-token": "asd" }),
|
||||
});
|
||||
|
||||
expect(await response.json()).toMatchSnapshot();
|
||||
await expect(response.json()).resolves.toMatchSnapshot();
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('requests the "/title" route', () => {
|
||||
|
||||
const response = await app.request("/title?id=10");
|
||||
|
||||
expect(await response.json()).toMatchSnapshot();
|
||||
await expect(response.json()).resolves.toMatchSnapshot();
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ describe('requests the "/title" route', () => {
|
||||
|
||||
const response = await app.request("/title?id=-1");
|
||||
|
||||
expect(await response.json()).toEqual({ success: false });
|
||||
await expect(response.json()).resolves.toEqual({ success: false });
|
||||
expect(response.status).toBe(404);
|
||||
});
|
||||
});
|
||||
|
||||
19
src/index.ts
19
src/index.ts
@@ -12,6 +12,8 @@ import {
|
||||
} from "~/libs/tasks/queueTask";
|
||||
import { maybeUpdateLastConnectedAt } from "~/middleware/maybeUpdateLastConnectedAt";
|
||||
|
||||
import { checkUpcomingTitles } from "./controllers/internal/upcoming-titles";
|
||||
|
||||
export const app = new OpenAPIHono<{ Bindings: Env }>();
|
||||
|
||||
app.use(maybeUpdateLastConnectedAt);
|
||||
@@ -121,9 +123,20 @@ export default {
|
||||
});
|
||||
},
|
||||
async scheduled(event, env, ctx) {
|
||||
const { processDelayedTasks } =
|
||||
await import("~/libs/tasks/processDelayedTasks");
|
||||
await processDelayedTasks(env);
|
||||
switch (event.cron) {
|
||||
case "0 */12 * * *":
|
||||
const { processDelayedTasks } =
|
||||
await import("~/libs/tasks/processDelayedTasks");
|
||||
await processDelayedTasks(env);
|
||||
break;
|
||||
case "0 18 * * *":
|
||||
const { checkUpcomingTitles } =
|
||||
await import("~/controllers/internal/upcoming-titles");
|
||||
await checkUpcomingTitles();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unhandled cron: ${event.cron}`);
|
||||
}
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ export class AnilistDurableObject extends DurableObject {
|
||||
|
||||
async getTitle(
|
||||
id: number,
|
||||
userId?: string,
|
||||
userId?: number,
|
||||
token?: string,
|
||||
): Promise<Title | null> {
|
||||
const promises: Promise<any>[] = [
|
||||
@@ -135,8 +135,7 @@ export class AnilistDurableObject extends DurableObject {
|
||||
nextSeason,
|
||||
nextYear,
|
||||
limit,
|
||||
page,
|
||||
}).then((data) => data?.Page);
|
||||
});
|
||||
},
|
||||
DateTime.now().plus({ days: 1 }),
|
||||
);
|
||||
@@ -155,7 +154,8 @@ export class AnilistDurableObject extends DurableObject {
|
||||
nextSeason,
|
||||
nextYear,
|
||||
limit,
|
||||
});
|
||||
page,
|
||||
}).then((data) => data?.Page);
|
||||
},
|
||||
DateTime.now().plus({ days: 1 }),
|
||||
);
|
||||
@@ -276,13 +276,11 @@ export class AnilistDurableObject extends DurableObject {
|
||||
|
||||
const result = await fetcher();
|
||||
await this.state.storage.put(key, result);
|
||||
console.debug(`Retrieved alarms from cache:`, Object.entries(alarms));
|
||||
|
||||
const calculatedTtl = typeof ttl === "function" ? ttl(result) : ttl;
|
||||
if (calculatedTtl) {
|
||||
const alarmTime = calculatedTtl.toMillis();
|
||||
await this.state.storage.setAlarm(alarmTime);
|
||||
console.debug(`Deleting storage key ${storageKey} & alarm ${key}`);
|
||||
await this.state.storage.put(`alarm:${key}`, alarmTime);
|
||||
}
|
||||
|
||||
@@ -292,11 +290,13 @@ export class AnilistDurableObject extends DurableObject {
|
||||
async alarm() {
|
||||
const now = Date.now();
|
||||
const alarms = await this.state.storage.list({ prefix: "alarm:" });
|
||||
console.debug(`Retrieved alarms from cache:`, Object.entries(alarms));
|
||||
for (const [key, ttl] of Object.entries(alarms)) {
|
||||
if (now >= ttl) {
|
||||
// The key in alarms is `alarm:${storageKey}`
|
||||
// We want to delete the storageKey
|
||||
const storageKey = key.replace("alarm:", "");
|
||||
console.debug(`Deleting storage key ${storageKey} & alarm ${key}`);
|
||||
await this.state.storage.delete(storageKey);
|
||||
await this.state.storage.delete(key);
|
||||
}
|
||||
|
||||
@@ -259,8 +259,8 @@ export const NextSeasonPopularQuery = graphql(
|
||||
$nextSeason: MediaSeason
|
||||
$nextYear: Int
|
||||
$limit: Int!
|
||||
) {
|
||||
$page: Int!
|
||||
) {
|
||||
Page(page: $page, perPage: $limit) {
|
||||
media(
|
||||
season: $nextSeason
|
||||
|
||||
@@ -3,11 +3,13 @@ import mapKeys from "lodash.mapkeys";
|
||||
|
||||
import { Case, changeStringCase } from "../changeStringCase";
|
||||
|
||||
export function getAdminSdkCredentials(env: Cloudflare.Env = cloudflareEnv) {
|
||||
export function getAdminSdkCredentials(
|
||||
env: Cloudflare.Env = cloudflareEnv,
|
||||
): AdminSdkCredentials {
|
||||
return mapKeys(
|
||||
JSON.parse(env.ADMIN_SDK_JSON) as AdminSdkCredentials,
|
||||
(_, key) => changeStringCase(key, Case.snake_case, Case.camelCase),
|
||||
);
|
||||
) satisfies AdminSdkCredentials;
|
||||
}
|
||||
|
||||
export interface AdminSdkCredentials {
|
||||
|
||||
@@ -67,7 +67,7 @@ id = "c8db249d8ee7462b91f9c374321776e4"
|
||||
preview_id = "ff38240eb2aa4b1388c705f4974f5aec"
|
||||
|
||||
[triggers]
|
||||
crons = ["0 */12 * * *"]
|
||||
crons = ["0 */12 * * *", "0 18 * * *"]
|
||||
|
||||
[[d1_databases]]
|
||||
binding = "DB"
|
||||
|
||||
Reference in New Issue
Block a user