轮播图数据源增加豆瓣
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getTMDBTrendingContent, getTMDBVideos } from '@/lib/tmdb.client';
|
||||
import { getConfig } from '@/lib/config';
|
||||
import { fetchDoubanData } from '@/lib/douban';
|
||||
|
||||
// 缓存配置 - 服务器内存缓存3小时
|
||||
const CACHE_DURATION = 3 * 60 * 60 * 1000; // 3小时
|
||||
@@ -10,6 +11,7 @@ const CACHE_DURATION = 3 * 60 * 60 * 1000; // 3小时
|
||||
// 为不同数据源分别维护缓存
|
||||
let tmdbCache: { data: any; timestamp: number } | null = null;
|
||||
let txCache: { data: any; timestamp: number } | null = null;
|
||||
let doubanCache: { data: any; timestamp: number } | null = null;
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
@@ -17,10 +19,10 @@ export async function GET() {
|
||||
try {
|
||||
// 获取配置
|
||||
const config = await getConfig();
|
||||
const bannerDataSource = config.SiteConfig?.BannerDataSource || 'TMDB';
|
||||
const bannerDataSource = config.SiteConfig?.BannerDataSource || 'Douban';
|
||||
|
||||
// 根据数据源选择对应的缓存
|
||||
const cache = bannerDataSource === 'TX' ? txCache : tmdbCache;
|
||||
const cache = bannerDataSource === 'TX' ? txCache : bannerDataSource === 'Douban' ? doubanCache : tmdbCache;
|
||||
|
||||
// 检查缓存
|
||||
if (cache && Date.now() - cache.timestamp < CACHE_DURATION) {
|
||||
@@ -30,7 +32,17 @@ export async function GET() {
|
||||
let result: any;
|
||||
|
||||
// 根据配置的数据源获取数据
|
||||
if (bannerDataSource === 'TX') {
|
||||
if (bannerDataSource === 'Douban') {
|
||||
// 使用豆瓣数据源
|
||||
result = await getDoubanBannerContent();
|
||||
// 添加数据源标识
|
||||
result.source = 'Douban';
|
||||
// 更新豆瓣缓存
|
||||
doubanCache = {
|
||||
data: result,
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
} else if (bannerDataSource === 'TX') {
|
||||
// 使用TX数据源
|
||||
result = await getTXBannerContent();
|
||||
// 添加数据源标识
|
||||
@@ -234,3 +246,151 @@ function parseTXBannerData(data: any): any[] {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取豆瓣轮播图内容
|
||||
*/
|
||||
async function getDoubanBannerContent(): Promise<{ code: number; list: any[] }> {
|
||||
try {
|
||||
// 获取豆瓣热门电影
|
||||
const hotMoviesUrl = 'https://m.douban.com/rexxar/api/v2/subject/recent_hot/movie?start=0&limit=10&category=热门&type=全部';
|
||||
|
||||
interface DoubanHotMovie {
|
||||
id: string;
|
||||
title: string;
|
||||
card_subtitle?: string;
|
||||
pic?: {
|
||||
large: string;
|
||||
normal: string;
|
||||
};
|
||||
rating?: {
|
||||
value: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface DoubanHotMoviesResponse {
|
||||
items: DoubanHotMovie[];
|
||||
}
|
||||
|
||||
const hotMoviesData = await fetchDoubanData<DoubanHotMoviesResponse>(hotMoviesUrl);
|
||||
|
||||
if (!hotMoviesData.items || hotMoviesData.items.length === 0) {
|
||||
return { code: 200, list: [] };
|
||||
}
|
||||
|
||||
// 取前5个电影
|
||||
const topMovies = hotMoviesData.items.slice(0, 5);
|
||||
|
||||
// 为每个电影获取详情信息
|
||||
const bannerItems = await Promise.all(
|
||||
topMovies.map(async (movie) => {
|
||||
try {
|
||||
const detailUrl = `https://m.douban.com/rexxar/api/v2/subject/${movie.id}`;
|
||||
|
||||
interface DoubanDetailResponse {
|
||||
id: string;
|
||||
title: string;
|
||||
original_title?: string;
|
||||
year: string;
|
||||
rating?: {
|
||||
value: number;
|
||||
};
|
||||
intro?: string;
|
||||
genres?: string[];
|
||||
cover_url?: string;
|
||||
trailers?: Array<{
|
||||
video_url?: string;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const detail = await fetchDoubanData<DoubanDetailResponse>(detailUrl);
|
||||
|
||||
// 获取预告片链接(取第一个)- 豆瓣是直链视频URL
|
||||
const trailerUrl = detail.trailers && detail.trailers.length > 0
|
||||
? detail.trailers[0].video_url
|
||||
: null;
|
||||
|
||||
// 获取横屏图片
|
||||
const backdropPath = detail.cover_url || movie.pic?.large || movie.pic?.normal || '';
|
||||
|
||||
// 提取年份
|
||||
const year = detail.year || movie.card_subtitle?.match(/(\d{4})/)?.[1] || '';
|
||||
|
||||
// 从card_subtitle提取标签(只读取第二个部分,通过空格分割)
|
||||
let tags: string[] = [];
|
||||
if (movie.card_subtitle) {
|
||||
const parts = movie.card_subtitle.split('/').map(s => s.trim());
|
||||
// 过滤掉年份(纯数字)和空字符串
|
||||
const filteredParts = parts.filter(part =>
|
||||
part && !/^\d{4}$/.test(part)
|
||||
);
|
||||
// 取第二个部分(类型),通过空格分割
|
||||
if (filteredParts.length >= 2) {
|
||||
tags = filteredParts[1].split(/\s+/).filter(t => t);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: movie.id,
|
||||
title: detail.title,
|
||||
backdrop_path: backdropPath,
|
||||
poster_path: backdropPath,
|
||||
release_date: year,
|
||||
overview: detail.intro || '',
|
||||
vote_average: detail.rating?.value || movie.rating?.value || 0,
|
||||
media_type: 'movie',
|
||||
genre_ids: [],
|
||||
genres: tags, // 使用从card_subtitle提取的标签
|
||||
trailer_url: trailerUrl, // 豆瓣预告片直链
|
||||
video_key: null, // 豆瓣不使用YouTube key
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`获取豆瓣电影 ${movie.id} 详情失败:`, error);
|
||||
|
||||
// 从card_subtitle提取标签(只读取第二个部分,通过空格分割)
|
||||
let tags: string[] = [];
|
||||
if (movie.card_subtitle) {
|
||||
const parts = movie.card_subtitle.split('/').map(s => s.trim());
|
||||
// 过滤掉年份(纯数字)和空字符串
|
||||
const filteredParts = parts.filter(part =>
|
||||
part && !/^\d{4}$/.test(part)
|
||||
);
|
||||
// 取第二个部分(类型),通过空格分割
|
||||
if (filteredParts.length >= 2) {
|
||||
tags = filteredParts[1].split(/\s+/).filter(t => t);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果获取详情失败,使用基本信息
|
||||
return {
|
||||
id: movie.id,
|
||||
title: movie.title,
|
||||
backdrop_path: movie.pic?.large || movie.pic?.normal || '',
|
||||
poster_path: movie.pic?.large || movie.pic?.normal || '',
|
||||
release_date: movie.card_subtitle?.match(/(\d{4})/)?.[1] || '',
|
||||
overview: '',
|
||||
vote_average: movie.rating?.value || 0,
|
||||
media_type: 'movie',
|
||||
genre_ids: [],
|
||||
genres: tags, // 使用从card_subtitle提取的标签
|
||||
trailer_url: null,
|
||||
video_key: null,
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// 过滤掉没有图片的项目
|
||||
const validBannerItems = bannerItems.filter(item => item.backdrop_path);
|
||||
|
||||
return {
|
||||
code: 200,
|
||||
list: validBannerItems,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('获取豆瓣轮播图数据失败:', error);
|
||||
return { code: 500, list: [] };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user