mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-21 09:14:42 +08:00
178 lines
4.5 KiB
TypeScript
178 lines
4.5 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
|
|
import { API_CONFIG, ApiSite, getApiSites } from '@/lib/config';
|
|
|
|
import { getVideoDetail } from '../detail/route';
|
|
|
|
export interface SearchResult {
|
|
id: string;
|
|
title: string;
|
|
poster: string;
|
|
episodes?: number;
|
|
source: string;
|
|
source_name: string;
|
|
}
|
|
|
|
interface ApiSearchItem {
|
|
vod_id: string;
|
|
vod_name: string;
|
|
vod_pic: string;
|
|
vod_remarks?: string;
|
|
}
|
|
|
|
async function searchFromApi(
|
|
apiSite: ApiSite,
|
|
query: string
|
|
): Promise<SearchResult[]> {
|
|
try {
|
|
const apiBaseUrl = apiSite.api;
|
|
const apiUrl =
|
|
apiBaseUrl + API_CONFIG.search.path + encodeURIComponent(query);
|
|
const apiName = apiSite.name;
|
|
|
|
// 添加超时处理
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), 8000);
|
|
|
|
const response = await fetch(apiUrl, {
|
|
headers: API_CONFIG.search.headers,
|
|
signal: controller.signal,
|
|
});
|
|
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response.ok) {
|
|
return [];
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (
|
|
!data ||
|
|
!data.list ||
|
|
!Array.isArray(data.list) ||
|
|
data.list.length === 0
|
|
) {
|
|
return [];
|
|
}
|
|
|
|
// 处理第一页结果
|
|
const results = data.list.map((item: ApiSearchItem) => ({
|
|
id: item.vod_id,
|
|
title: item.vod_name,
|
|
poster: item.vod_pic,
|
|
episodes: item.vod_remarks ? parseInt(item.vod_remarks) : undefined,
|
|
source: apiSite.key,
|
|
source_name: apiName,
|
|
}));
|
|
|
|
// 获取总页数
|
|
const pageCount = data.pagecount || 1;
|
|
// 确定需要获取的额外页数
|
|
const pagesToFetch = Math.min(
|
|
pageCount - 1,
|
|
API_CONFIG.search.maxPages - 1
|
|
);
|
|
|
|
// 如果有额外页数,获取更多页的结果
|
|
if (pagesToFetch > 0) {
|
|
const additionalPagePromises = [];
|
|
|
|
for (let page = 2; page <= pagesToFetch + 1; page++) {
|
|
const pageUrl =
|
|
apiBaseUrl +
|
|
API_CONFIG.search.pagePath
|
|
.replace('{query}', encodeURIComponent(query))
|
|
.replace('{page}', page.toString());
|
|
|
|
const pagePromise = (async () => {
|
|
try {
|
|
const pageController = new AbortController();
|
|
const pageTimeoutId = setTimeout(
|
|
() => pageController.abort(),
|
|
8000
|
|
);
|
|
|
|
const pageResponse = await fetch(pageUrl, {
|
|
headers: API_CONFIG.search.headers,
|
|
signal: pageController.signal,
|
|
});
|
|
|
|
clearTimeout(pageTimeoutId);
|
|
|
|
if (!pageResponse.ok) return [];
|
|
|
|
const pageData = await pageResponse.json();
|
|
|
|
if (!pageData || !pageData.list || !Array.isArray(pageData.list))
|
|
return [];
|
|
|
|
return pageData.list.map((item: ApiSearchItem) => ({
|
|
id: item.vod_id,
|
|
title: item.vod_name,
|
|
poster: item.vod_pic,
|
|
episodes: item.vod_remarks
|
|
? parseInt(item.vod_remarks)
|
|
: undefined,
|
|
source: apiSite.key,
|
|
source_name: apiName,
|
|
}));
|
|
} catch (error) {
|
|
return [];
|
|
}
|
|
})();
|
|
|
|
additionalPagePromises.push(pagePromise);
|
|
}
|
|
|
|
// 等待所有额外页的结果
|
|
const additionalResults = await Promise.all(additionalPagePromises);
|
|
|
|
// 合并所有页的结果
|
|
additionalResults.forEach((pageResults) => {
|
|
if (pageResults.length > 0) {
|
|
results.push(...pageResults);
|
|
}
|
|
});
|
|
}
|
|
|
|
// 获取每个结果的详情
|
|
const detailPromises = results.map(async (result: SearchResult) => {
|
|
try {
|
|
const detail = await getVideoDetail(result.id, result.source);
|
|
if (detail.episodes.length > 1) {
|
|
return { ...result, episodes: detail.episodes.length };
|
|
}
|
|
return result;
|
|
} catch (error) {
|
|
return result;
|
|
}
|
|
});
|
|
|
|
return await Promise.all(detailPromises);
|
|
} catch (error) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
export async function GET(request: Request) {
|
|
const { searchParams } = new URL(request.url);
|
|
const query = searchParams.get('q');
|
|
|
|
if (!query) {
|
|
return NextResponse.json({ results: [] });
|
|
}
|
|
|
|
const apiSites = getApiSites();
|
|
const searchPromises = apiSites.map((site) => searchFromApi(site, query));
|
|
|
|
try {
|
|
const results = await Promise.all(searchPromises);
|
|
const flattenedResults = results.flat();
|
|
|
|
return NextResponse.json({ results: flattenedResults });
|
|
} catch (error) {
|
|
return NextResponse.json({ error: '搜索失败' }, { status: 500 });
|
|
}
|
|
}
|