mirror of
https://github.com/MoonTechLab/LunaTV.git
synced 2026-02-28 01:13:15 +08:00
131 lines
3.6 KiB
TypeScript
131 lines
3.6 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any,no-console */
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
|
|
import { getCacheTime } from '@/lib/config';
|
|
import { fetchDoubanData } from '@/lib/douban';
|
|
import { DoubanResult } from '@/lib/types';
|
|
|
|
interface DoubanRecommendApiResponse {
|
|
total: number;
|
|
items: Array<{
|
|
id: string;
|
|
title: string;
|
|
year: string;
|
|
type: string;
|
|
pic: {
|
|
large: string;
|
|
normal: string;
|
|
};
|
|
rating: {
|
|
value: number;
|
|
};
|
|
}>;
|
|
}
|
|
|
|
export const runtime = 'nodejs';
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const { searchParams } = new URL(request.url);
|
|
|
|
// 获取参数
|
|
const kind = searchParams.get('kind');
|
|
const pageLimit = parseInt(searchParams.get('limit') || '20');
|
|
const pageStart = parseInt(searchParams.get('start') || '0');
|
|
const category =
|
|
searchParams.get('category') === 'all' ? '' : searchParams.get('category');
|
|
const format =
|
|
searchParams.get('format') === 'all' ? '' : searchParams.get('format');
|
|
const region =
|
|
searchParams.get('region') === 'all' ? '' : searchParams.get('region');
|
|
const year =
|
|
searchParams.get('year') === 'all' ? '' : searchParams.get('year');
|
|
const platform =
|
|
searchParams.get('platform') === 'all' ? '' : searchParams.get('platform');
|
|
const sort = searchParams.get('sort') === 'T' ? '' : searchParams.get('sort');
|
|
const label =
|
|
searchParams.get('label') === 'all' ? '' : searchParams.get('label');
|
|
|
|
if (!kind) {
|
|
return NextResponse.json({ error: '缺少必要参数: kind' }, { status: 400 });
|
|
}
|
|
|
|
const selectedCategories = { 类型: category } as any;
|
|
if (format) {
|
|
selectedCategories['形式'] = format;
|
|
}
|
|
if (region) {
|
|
selectedCategories['地区'] = region;
|
|
}
|
|
|
|
const tags = [] as Array<string>;
|
|
if (category) {
|
|
tags.push(category);
|
|
}
|
|
if (!category && format) {
|
|
tags.push(format);
|
|
}
|
|
if (label) {
|
|
tags.push(label);
|
|
}
|
|
if (region) {
|
|
tags.push(region);
|
|
}
|
|
if (year) {
|
|
tags.push(year);
|
|
}
|
|
if (platform) {
|
|
tags.push(platform);
|
|
}
|
|
|
|
const baseUrl = `https://m.douban.com/rexxar/api/v2/${kind}/recommend`;
|
|
const params = new URLSearchParams();
|
|
params.append('refresh', '0');
|
|
params.append('start', pageStart.toString());
|
|
params.append('count', pageLimit.toString());
|
|
params.append('selected_categories', JSON.stringify(selectedCategories));
|
|
params.append('uncollect', 'false');
|
|
params.append('score_range', '0,10');
|
|
params.append('tags', tags.join(','));
|
|
if (sort) {
|
|
params.append('sort', sort);
|
|
}
|
|
|
|
const target = `${baseUrl}?${params.toString()}`;
|
|
console.log(target);
|
|
try {
|
|
const doubanData = await fetchDoubanData<DoubanRecommendApiResponse>(
|
|
target
|
|
);
|
|
const list = doubanData.items
|
|
.filter((item) => item.type == 'movie' || item.type == 'tv')
|
|
.map((item) => ({
|
|
id: item.id,
|
|
title: item.title,
|
|
poster: item.pic?.normal || item.pic?.large || '',
|
|
rate: item.rating?.value ? item.rating.value.toFixed(1) : '',
|
|
year: item.year,
|
|
}));
|
|
const response: DoubanResult = {
|
|
code: 200,
|
|
message: '获取成功',
|
|
list: list,
|
|
};
|
|
|
|
const cacheTime = await getCacheTime();
|
|
return NextResponse.json(response, {
|
|
headers: {
|
|
'Cache-Control': `public, max-age=${cacheTime}, s-maxage=${cacheTime}`,
|
|
'CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
|
|
'Vercel-CDN-Cache-Control': `public, s-maxage=${cacheTime}`,
|
|
'Netlify-Vary': 'query',
|
|
},
|
|
});
|
|
} catch (error) {
|
|
return NextResponse.json(
|
|
{ error: '获取豆瓣数据失败', details: (error as Error).message },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|