55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
import { Hono } from "hono";
|
|
import innertube from "../lib/innertube.js";
|
|
import { zValidator } from "@hono/zod-validator";
|
|
import { SearchVideos } from "../models/SearchVideos.js";
|
|
import search from "../templates/search.js";
|
|
import { YTNodes } from "youtubei.js";
|
|
|
|
const video = new Hono();
|
|
|
|
video.get(
|
|
"/videos",
|
|
zValidator("query", SearchVideos),
|
|
async (c) => {
|
|
const params = c.req.valid("query");
|
|
const page = params["start-index"] ?? 1;
|
|
|
|
if (page > 5) {
|
|
return c.html(search([], ""));
|
|
}
|
|
|
|
// * fetch all videos up to current page
|
|
const allVideos: YTNodes.Video[] = [];
|
|
let searchQuery = await innertube.search(params.q, {
|
|
duration: params.duration,
|
|
upload_date: params.time,
|
|
sort_by: params.orderby
|
|
});
|
|
|
|
for (let i = 1; i <= page; i++) {
|
|
const videos = searchQuery.results.filter(
|
|
(node): node is YTNodes.Video => node.type === "Video"
|
|
);
|
|
allVideos.push(...videos);
|
|
|
|
if (i < page) {
|
|
try {
|
|
const nextPage = await searchQuery.getContinuation();
|
|
if (!nextPage) break;
|
|
searchQuery = nextPage;
|
|
} catch (err) {
|
|
// * no more pages available
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// * build next page URL
|
|
const nextUrl = new URL(c.req.url);
|
|
nextUrl.searchParams.set("start-index", (page + 1).toString());
|
|
|
|
return c.html(search(allVideos, nextUrl.toString()));
|
|
}
|
|
);
|
|
|
|
export default video; |