1
0
cvsa/packages/elysia/routes/song/milestone.ts

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()
})
}
}
);