blastoise/routes/fetch.ts

110 lines
3.7 KiB
TypeScript

import { config, DEFAULT_CONFIG } from "../config";
import {
isAvailable as isYtdlpAvailable,
checkUrl,
addToFastQueue,
addToSlowQueue,
getUserQueues,
} from "../ytdlp";
import { getOrCreateUser } from "./helpers";
const ytdlpConfig = config.ytdlp || DEFAULT_CONFIG.ytdlp!;
// POST /api/fetch - fetch from URL (yt-dlp)
export async function handleFetch(req: Request, server: any): Promise<Response> {
const { user, headers } = getOrCreateUser(req, server);
if (!user) {
return Response.json({ error: "Authentication required" }, { status: 401 });
}
if (user.is_guest) {
return Response.json({ error: "Guests cannot fetch from URLs" }, { status: 403 });
}
if (!ytdlpConfig.enabled) {
return Response.json({ error: "Feature disabled" }, { status: 403 });
}
if (!isYtdlpAvailable()) {
return Response.json({ error: "yt-dlp not available" }, { status: 503 });
}
try {
const { url } = await req.json();
if (!url || typeof url !== "string") {
return Response.json({ error: "URL is required" }, { status: 400 });
}
console.log(`[Fetch] ${user.username} checking URL: ${url}`);
const info = await checkUrl(url);
if (info.type === "playlist") {
if (!ytdlpConfig.allowPlaylists) {
return Response.json({ error: "Playlist downloads are disabled" }, { status: 403 });
}
return Response.json(info, { headers });
} else {
const item = addToFastQueue(info.url, info.title, user.id);
console.log(`[Fetch] ${user.username} queued: ${info.title} (id=${item.id})`);
return Response.json({
type: "single",
id: item.id,
title: item.title,
queueType: "fast"
}, { headers });
}
} catch (e: any) {
console.error("[Fetch] Error:", e);
return Response.json({ error: e.message || "Invalid request" }, { status: 400 });
}
}
// POST /api/fetch/confirm - confirm playlist download
export async function handleFetchConfirm(req: Request, server: any): Promise<Response> {
const { user, headers } = getOrCreateUser(req, server);
if (!user) {
return Response.json({ error: "Authentication required" }, { status: 401 });
}
if (user.is_guest) {
return Response.json({ error: "Guests cannot fetch from URLs" }, { status: 403 });
}
if (!ytdlpConfig.enabled || !isYtdlpAvailable()) {
return Response.json({ error: "Feature not available" }, { status: 503 });
}
try {
const { items } = await req.json();
if (!Array.isArray(items) || items.length === 0) {
return Response.json({ error: "Items required" }, { status: 400 });
}
const queueItems = addToSlowQueue(items, user.id);
const estimatedMinutes = Math.ceil(queueItems.length * ytdlpConfig.slowQueueInterval / 60);
const hours = Math.floor(estimatedMinutes / 60);
const mins = estimatedMinutes % 60;
const estimatedTime = hours > 0 ? `${hours}h ${mins}m` : `${mins}m`;
console.log(`[Fetch] ${user.username} confirmed playlist: ${queueItems.length} items`);
return Response.json({
message: `Added ${queueItems.length} items to queue`,
queueType: "slow",
estimatedTime,
items: queueItems.map(i => ({ id: i.id, title: i.title }))
}, { headers });
} catch (e) {
console.error("[Fetch] Confirm error:", e);
return Response.json({ error: "Invalid request" }, { status: 400 });
}
}
// GET /api/fetch - get fetch queue status
export function handleGetFetchQueue(req: Request, server: any): Response {
const { user, headers } = getOrCreateUser(req, server);
if (!user) {
return Response.json({ error: "Authentication required" }, { status: 401 });
}
const queues = getUserQueues(user.id);
return Response.json(queues, { headers });
}