Skip to content

Commit 341df8d

Browse files
authored
Merge pull request #2 from nthumodifications/chore/update-to-11410
feat: sync courses cronjob
2 parents 59af235 + fb7cfe5 commit 341df8d

File tree

8 files changed

+1138
-1087
lines changed

8 files changed

+1138
-1087
lines changed

src/calendar-proxy.ts

Lines changed: 69 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,84 @@ import { env } from "hono/adapter";
55

66
// Define the app context type to include environment variables
77
interface AppEnv {
8-
NTHUMODS_AUTH_URL: string;
8+
NTHUMODS_AUTH_URL: string;
99
}
1010

11-
const app = new Hono<{ Bindings: AppEnv }>()
12-
.get(
13-
"/ical/:userId",
14-
zValidator(
15-
"query",
16-
z.object({
17-
key: z.string().optional(),
18-
type: z.enum(["basic", "full"]).default("basic"),
19-
}),
20-
),
21-
zValidator(
22-
"param",
23-
z.object({
24-
userId: z.string(),
25-
}),
26-
),
27-
async (c) => {
28-
try {
29-
const { userId } = c.req.valid("param");
30-
const { key, type } = c.req.valid("query");
11+
const app = new Hono<{ Bindings: AppEnv }>().get(
12+
"/ical/:userId",
13+
zValidator(
14+
"query",
15+
z.object({
16+
key: z.string().optional(),
17+
type: z.enum(["basic", "full"]).default("basic"),
18+
}),
19+
),
20+
zValidator(
21+
"param",
22+
z.object({
23+
userId: z.string(),
24+
}),
25+
),
26+
async (c) => {
27+
try {
28+
const { userId } = c.req.valid("param");
29+
const { key, type } = c.req.valid("query");
3130

32-
if (!key) {
33-
return c.json({ error: "Missing API key" }, 400);
34-
}
31+
if (!key) {
32+
return c.json({ error: "Missing API key" }, 400);
33+
}
3534

36-
// Get the secure API URL from environment variable
37-
const { NTHUMODS_AUTH_URL: secureApiUrl } = env<{ NTHUMODS_AUTH_URL: string }>(c);
35+
// Get the secure API URL from environment variable
36+
const { NTHUMODS_AUTH_URL: secureApiUrl } = env<{
37+
NTHUMODS_AUTH_URL: string;
38+
}>(c);
3839

39-
// Construct the URL for the secure API request
40-
const url = new URL(`${secureApiUrl}/calendar/ics/${userId}`);
41-
url.searchParams.set("key", key);
42-
url.searchParams.set("type", type);
40+
// Construct the URL for the secure API request
41+
const url = new URL(`${secureApiUrl}/calendar/ics/${userId}`);
42+
url.searchParams.set("key", key);
43+
url.searchParams.set("type", type);
4344

44-
// Forward the request to the secure API
45-
const response = await fetch(url.toString(), {
46-
headers: {
47-
// Forward any necessary headers
48-
"Accept": "text/calendar",
49-
},
50-
});
45+
// Forward the request to the secure API
46+
const response = await fetch(url.toString(), {
47+
headers: {
48+
// Forward any necessary headers
49+
Accept: "text/calendar",
50+
},
51+
});
5152

52-
// Check if the request was successful
53-
if (!response.ok) {
54-
const errorText = await response.text();
55-
console.error(`Error fetching calendar: ${response.status} ${errorText}`);
56-
return c.json(
57-
{ error: `Failed to fetch calendar: ${response.statusText}`, status: response.status }
58-
);
59-
}
53+
// Check if the request was successful
54+
if (!response.ok) {
55+
const errorText = await response.text();
56+
console.error(
57+
`Error fetching calendar: ${response.status} ${errorText}`,
58+
);
59+
return c.json({
60+
error: `Failed to fetch calendar: ${response.statusText}`,
61+
status: response.status,
62+
});
63+
}
6064

61-
// Get the calendar data
62-
const calendarData = await response.text();
65+
// Get the calendar data
66+
const calendarData = await response.text();
6367

64-
// Set the appropriate headers for the iCalendar file
65-
c.header("Content-Type", "text/calendar");
66-
c.header("Content-Disposition", `attachment; filename=${userId}_calendar.ics`);
67-
c.header("Cache-Control", "private, max-age=3600"); // Cache for 1 hour
68+
// Set the appropriate headers for the iCalendar file
69+
c.header("Content-Type", "text/calendar");
70+
c.header(
71+
"Content-Disposition",
72+
`attachment; filename=${userId}_calendar.ics`,
73+
);
74+
c.header("Cache-Control", "private, max-age=3600"); // Cache for 1 hour
6875

69-
// Return the calendar data
70-
return c.body(calendarData);
71-
} catch (error) {
72-
console.error("Error proxying calendar request:", error);
73-
return c.json(
74-
{ error: "Internal server error while fetching calendar" },
75-
500
76-
);
77-
}
78-
}
79-
);
76+
// Return the calendar data
77+
return c.body(calendarData);
78+
} catch (error) {
79+
console.error("Error proxying calendar request:", error);
80+
return c.json(
81+
{ error: "Internal server error while fetching calendar" },
82+
500,
83+
);
84+
}
85+
},
86+
);
8087

8188
export default app;

src/config/algolia.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@ import type { Context } from "hono";
33
import { env } from "hono/adapter";
44

55
const algolia = (c: Context) => {
6-
const { ALGOLIA_APP_ID, ALGOLIA_API_KEY } = env<{
7-
ALGOLIA_APP_ID: string;
8-
ALGOLIA_API_KEY: string;
9-
}>(c);
6+
const { ALGOLIA_APP_ID, ALGOLIA_API_KEY } = env<{
7+
ALGOLIA_APP_ID: string;
8+
ALGOLIA_API_KEY: string;
9+
}>(c);
1010

11-
return algoliaWithEnv(ALGOLIA_APP_ID, ALGOLIA_API_KEY);
12-
}
11+
return algoliaWithEnv(ALGOLIA_APP_ID, ALGOLIA_API_KEY);
12+
};
1313

1414
export const algoliaWithEnv = (appId: string, apiKey: string) => {
15-
const client = algoliasearch(appId, apiKey);
16-
const index = client.initIndex("nthu_courses");
17-
return index;
18-
}
15+
const client = algoliasearch(appId, apiKey);
16+
const index = client.initIndex("nthu_courses");
17+
return index;
18+
};
1919

20-
export default algolia;
20+
export default algolia;

src/config/supabase_server.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const supabaseWithEnv = (url: string, key: string) => {
88
throw new Error("Supabase credentials not found");
99
}
1010
return createClient<Database>(url, key);
11-
}
11+
};
1212

1313
const supabase_server = (c: Context) => {
1414
const { SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY } = env<{
@@ -18,5 +18,4 @@ const supabase_server = (c: Context) => {
1818
return supabaseWithEnv(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
1919
};
2020

21-
2221
export default supabase_server;

src/headless-ais/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import inthu from "./inthu";
66
import eeclass from "./eeclass";
77
import grades from "./grades";
88
import type { ScheduledController, Scheduler } from "@cloudflare/workers-types";
9-
import { scrapeArchivedCourses } from '../scheduled/syllabus';
9+
import { scrapeArchivedCourses } from "../scheduled/syllabus";
1010

1111
const app = new Hono()
1212
.route("/auth", auth)
@@ -15,4 +15,4 @@ const app = new Hono()
1515
.route("/eeclass", eeclass)
1616
.route("/grades", grades);
1717

18-
export default app;
18+
export default app;

src/index.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ import shortlink from "./shortlink";
1111
import issue from "./issue";
1212
import headlessAis from "./headless-ais";
1313
import planner from "./planner-replication";
14-
import { D1Database } from '@cloudflare/workers-types';
15-
import { scrapeArchivedCourses, scrapeSyllabus, syncCoursesToAlgolia } from './scheduled/syllabus';
14+
import { D1Database } from "@cloudflare/workers-types";
15+
import {
16+
scrapeArchivedCourses,
17+
scrapeSyllabus,
18+
syncCoursesToAlgolia,
19+
} from "./scheduled/syllabus";
1620

1721
export type Bindings = {
1822
DB: D1Database;
@@ -29,7 +33,8 @@ export const app = new Hono<{ Bindings: Bindings }>()
2933
.use(logger())
3034
.get("/", (c) => {
3135
return c.text("I AM NTHUMODS UWU");
32-
}).route("/acacalendar", acaCalendar)
36+
})
37+
.route("/acacalendar", acaCalendar)
3338
.route("/calendar", calendarProxy)
3439
.route("/weather", weather)
3540
.route("/course", course)
@@ -39,7 +44,6 @@ export const app = new Hono<{ Bindings: Bindings }>()
3944
.route("/issue", issue)
4045
.route("/planner", planner);
4146

42-
4347
const APIHandler = {
4448
...app,
4549
async scheduled(
@@ -48,19 +52,20 @@ const APIHandler = {
4852
ctx: ExecutionContext,
4953
) {
5054
console.log("cron processed");
51-
ctx.waitUntil(new Promise(async (resolve) => {
52-
const semester = '11320';
53-
// Scrape archived courses and syllabus
54-
try {
55-
const cache = await scrapeArchivedCourses(env, semester);
56-
await scrapeSyllabus(env, semester, cache);
57-
resolve(void 0);
58-
} catch (error) {
59-
console.error("Error during scheduled task:", error);
60-
}
61-
}))
55+
ctx.waitUntil(
56+
new Promise(async (resolve) => {
57+
const semester = "11410";
58+
// Scrape archived courses and syllabus
59+
try {
60+
const cache = await scrapeArchivedCourses(env, semester);
61+
await scrapeSyllabus(env, semester, cache);
62+
resolve(void 0);
63+
} catch (error) {
64+
console.error("Error during scheduled task:", error);
65+
}
66+
}),
67+
);
6268
},
63-
6469
};
6570

6671
export default APIHandler;

0 commit comments

Comments
 (0)