59 lines
1.7 KiB
TypeScript
59 lines
1.7 KiB
TypeScript
import { Elysia, t } from "elysia";
|
|
import { dbMain } from "@core/drizzle";
|
|
import { bilibiliMetadata, latestVideoSnapshot } from "@core/drizzle/main/schema";
|
|
import { eq, and, gte, lt, desc } from "drizzle-orm";
|
|
import { getMilestoneETA } from "@core/db";
|
|
import serverTiming from "@elysia/middlewares/timing";
|
|
|
|
type MileStoneType = "dendou" | "densetsu" | "shinwa";
|
|
|
|
const range = {
|
|
dendou: [90000, 99999, 100000],
|
|
densetsu: [900000, 999999, 1000000],
|
|
shinwa: [5000000, 9999999, 10000000]
|
|
};
|
|
|
|
export const closeMileStoneHandler = new Elysia({ prefix: "/song" }).use(serverTiming()).get(
|
|
"/close-milestone/:type",
|
|
async ({ params, timeLog }) => {
|
|
timeLog.startTime("retrieveCandidates")
|
|
const type = params.type;
|
|
const min = range[type as MileStoneType][0];
|
|
const max = range[type as MileStoneType][1];
|
|
const data = await dbMain
|
|
.select()
|
|
.from(bilibiliMetadata)
|
|
.innerJoin(latestVideoSnapshot, eq(latestVideoSnapshot.aid, bilibiliMetadata.aid))
|
|
.where(and(gte(latestVideoSnapshot.views, min), lt(latestVideoSnapshot.views, max)))
|
|
.orderBy(desc(latestVideoSnapshot.views));
|
|
type Row = (typeof data)[number];
|
|
type Result = Row & {
|
|
eta: number;
|
|
};
|
|
const result: Result[] = [];
|
|
timeLog.endTime("retrieveCandidates")
|
|
|
|
timeLog.startTime("calculateETA");
|
|
for (let i = 0; i < data.length; i++) {
|
|
const aid = data[i].bilibili_metadata.aid;
|
|
const eta = await getMilestoneETA(aid, range[type as MileStoneType][2]);
|
|
result.push({
|
|
...data[i],
|
|
eta
|
|
});
|
|
}
|
|
timeLog.endTime("calculateETA");
|
|
|
|
result.sort((a, b) => a.eta - b.eta);
|
|
return result;
|
|
},
|
|
{
|
|
response: {
|
|
200: t.Array(t.Any()),
|
|
404: t.Object({
|
|
message: t.String()
|
|
})
|
|
}
|
|
}
|
|
);
|