2024-10-14 17:18:57 +08:00
|
|
|
|
import process from "node:process"
|
2024-10-12 12:49:20 +08:00
|
|
|
|
import { TTL } from "@shared/consts"
|
2024-10-08 20:49:19 +08:00
|
|
|
|
import type { SourceID, SourceResponse } from "@shared/types"
|
|
|
|
|
import { sources } from "@shared/sources"
|
2024-10-20 20:28:49 +08:00
|
|
|
|
import { sourcesGetters } from "#/sources"
|
2024-10-17 04:33:52 +08:00
|
|
|
|
import { useCache } from "#/hooks/useCache"
|
2024-09-29 20:57:24 +08:00
|
|
|
|
|
2024-10-05 17:20:49 +08:00
|
|
|
|
export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
2024-10-03 17:24:29 +08:00
|
|
|
|
try {
|
2024-10-08 20:49:19 +08:00
|
|
|
|
let id = getRouterParam(event, "id") as SourceID
|
2024-10-03 17:24:29 +08:00
|
|
|
|
const query = getQuery(event)
|
|
|
|
|
const latest = query.latest !== undefined && query.latest !== "false"
|
2024-10-20 20:28:49 +08:00
|
|
|
|
const isValid = (id: SourceID) => !id || !sources[id] || !sourcesGetters[id]
|
2024-10-08 20:49:19 +08:00
|
|
|
|
|
|
|
|
|
if (isValid(id)) {
|
2024-10-21 17:00:51 +08:00
|
|
|
|
const redirectID = sources?.[id]?.redirect
|
2024-10-08 20:49:19 +08:00
|
|
|
|
if (redirectID) id = redirectID
|
|
|
|
|
if (isValid(id)) throw new Error("Invalid source id")
|
|
|
|
|
}
|
2024-10-03 13:16:14 +08:00
|
|
|
|
|
2024-10-17 04:33:52 +08:00
|
|
|
|
const cacheTable = useCache()
|
2024-10-05 17:20:49 +08:00
|
|
|
|
const now = Date.now()
|
2024-10-23 03:11:20 +08:00
|
|
|
|
if (cacheTable) {
|
2024-10-14 17:18:57 +08:00
|
|
|
|
if (process.env.INIT_TABLE !== "false") await cacheTable.init()
|
2024-10-14 00:02:58 +08:00
|
|
|
|
const cache = await cacheTable.get(id)
|
2024-10-03 17:24:29 +08:00
|
|
|
|
if (cache) {
|
2024-10-08 22:41:38 +08:00
|
|
|
|
// interval 刷新间隔,对于缓存失效也要执行的。本质上表示本来内容更新就很慢,这个间隔内可能内容压根不会更新。
|
2024-10-14 21:50:27 +08:00
|
|
|
|
// 默认 10 分钟,是低于 TTL 的,但部分 Source 的更新间隔会超过 TTL,甚至有的一天更新一次。
|
2024-10-12 12:49:20 +08:00
|
|
|
|
const interval = sources[id].interval
|
2024-10-08 22:41:38 +08:00
|
|
|
|
if (now - cache.updated < interval) {
|
|
|
|
|
return {
|
|
|
|
|
status: "success",
|
2024-10-15 12:05:03 +08:00
|
|
|
|
updatedTime: now,
|
|
|
|
|
items: cache.data,
|
2024-10-08 22:41:38 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-14 00:02:58 +08:00
|
|
|
|
|
2024-10-08 22:41:38 +08:00
|
|
|
|
// 而 TTL 缓存失效时间,在时间范围内,就算内容更新了也要用这个缓存。
|
|
|
|
|
// 复用缓存是不会更新时间的。
|
2024-10-14 21:50:27 +08:00
|
|
|
|
if (now - cache.updated < TTL) {
|
|
|
|
|
// 有 latest
|
|
|
|
|
// 没有 latest,但服务器禁止登录
|
|
|
|
|
|
|
|
|
|
// 没有 latest
|
|
|
|
|
// 有 latest,服务器可以登录但没有登录
|
|
|
|
|
if (!latest || (!event.context.disabledLogin && !event.context.user)) {
|
2024-10-19 15:28:02 +08:00
|
|
|
|
return {
|
|
|
|
|
status: "cache",
|
|
|
|
|
updatedTime: cache.updated,
|
|
|
|
|
items: cache.data,
|
2024-10-14 21:50:27 +08:00
|
|
|
|
}
|
2024-10-03 17:24:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-20 20:28:49 +08:00
|
|
|
|
const data = (await sourcesGetters[id]()).slice(0, 30)
|
2024-10-05 23:55:30 +08:00
|
|
|
|
logger.success(`fetch ${id} latest`)
|
2024-10-17 04:33:52 +08:00
|
|
|
|
if (cacheTable) {
|
|
|
|
|
if (event.context.waitUntil) event.context.waitUntil(cacheTable.set(id, data))
|
|
|
|
|
else await cacheTable.set(id, data)
|
|
|
|
|
}
|
2024-10-05 23:55:30 +08:00
|
|
|
|
return {
|
|
|
|
|
status: "success",
|
2024-10-15 12:05:03 +08:00
|
|
|
|
updatedTime: now,
|
|
|
|
|
items: data,
|
2024-10-03 17:24:29 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (e: any) {
|
2024-10-05 23:55:30 +08:00
|
|
|
|
logger.error(e)
|
2024-10-15 12:05:03 +08:00
|
|
|
|
throw createError({
|
|
|
|
|
statusCode: 500,
|
|
|
|
|
message: e instanceof Error ? e.message : "Internal Server Error",
|
|
|
|
|
})
|
2024-10-03 13:16:14 +08:00
|
|
|
|
}
|
2024-09-29 20:57:24 +08:00
|
|
|
|
})
|