UNPKG

tv-recommender-mcp-server

Version:

MCP server for TV show recommendations

307 lines (306 loc) 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.findPersonId = findPersonId; exports.convertCastToIds = convertCastToIds; exports.findKeywordId = findKeywordId; exports.discoverShows = discoverShows; exports.getPersonTvCredits = getPersonTvCredits; exports.findShowsByPersonName = findShowsByPersonName; exports.getRecommendationsByActor = getRecommendationsByActor; const tmdbClient_1 = require("../services/tmdbClient"); const genreMap_1 = require("../utils/genreMap"); const errorHandler_1 = require("../utils/errorHandler"); /** * 将字符串类型数组转换为TMDb API所需的ID数组 * @param genres 类型名称数组 * @returns 类型ID数组字符串 */ async function convertGenresToIds(genres) { if (!genres || !genres.length) return ''; const genreIds = genres.map(genre => (0, genreMap_1.mapGenreToId)(genre)).filter(id => id !== null); if (genreIds.length === 0) { throw new errorHandler_1.ApiError(`无法识别提供的类型: ${genres.join(', ')}`, 400); } return genreIds.join(','); } /** * 查找人物ID * @param personName 人物名称 * @returns 人物ID */ async function findPersonId(personName) { try { const response = await tmdbClient_1.tmdbClient.searchPerson(personName); if (response.results && response.results.length > 0) { return response.results[0].id; } return null; } catch (error) { return null; } } /** * 将演员名称数组转换为ID数组 * @param cast 演员名称数组 * @returns 演员ID数组字符串 */ async function convertCastToIds(cast) { if (!cast || !cast.length) return ''; const castPromises = cast.map(name => findPersonId(name)); const castIds = await Promise.all(castPromises); const validIds = castIds.filter(id => id !== null); if (validIds.length === 0) { throw new errorHandler_1.ApiError(`无法找到演员: ${cast.join(', ')}`, 400); } return validIds.join(','); } /** * 查找关键词ID * @param keyword 关键词 * @returns 关键词ID */ async function findKeywordId(keyword) { try { const response = await tmdbClient_1.tmdbClient.searchKeyword(keyword); if (response.results && response.results.length > 0) { return response.results[0].id; } return null; } catch (error) { // console.error(`查找关键词"${keyword}"失败:`, error); return null; } } /** * 将关键词数组转换为ID数组 * @param keywords 关键词数组 * @returns 关键词ID数组字符串 */ async function convertKeywordsToIds(keywords) { if (!keywords || !keywords.length) return ''; const keywordPromises = keywords.map(keyword => findKeywordId(keyword)); const keywordIds = await Promise.all(keywordPromises); const validIds = keywordIds.filter(id => id !== null); if (validIds.length === 0) { throw new errorHandler_1.ApiError(`无法找到关键词: ${keywords.join(', ')}`, 400); } return validIds.join(','); } /** * 格式化发现剧集结果 * @param results TMDb API返回的结果 * @returns 格式化后的结果 */ function formatDiscoverResults(results) { return results.map(show => ({ id: show.id, name: show.name, overview: show.overview || '暂无简介', poster_path: show.poster_path || null, vote_average: show.vote_average || 0, first_air_date: show.first_air_date })); } /** * 高级剧集发现工具实现 * @param params 多个可选筛选条件 * @returns 发现结果 */ async function discoverShows(params) { try { // 构建API请求参数 const apiParams = {}; // 处理类型参数 if (params.with_genres?.length) { apiParams.with_genres = await convertGenresToIds(params.with_genres); } // 注释: TMDB API的discover/tv不支持按演员或人物筛选 // 相关代码已移除 // 存储请求的年份以便后续过滤 const requestedYear = params.first_air_date_year; // 处理年份参数 - 修正参数名称为带点号格式 if (requestedYear) { apiParams['first_air_date.gte'] = `${requestedYear}-01-01`; apiParams['first_air_date.lte'] = `${requestedYear}-12-31`; } // 处理评分参数 - 修正参数名称为带点号格式 if (params.vote_average_gte) { apiParams['vote_average.gte'] = params.vote_average_gte; } // 处理网络参数 if (params.with_networks?.length) { apiParams.with_networks = params.with_networks.join(','); } // 处理关键词参数 if (params.with_keywords?.length) { apiParams.with_keywords = await convertKeywordsToIds(params.with_keywords); } // 处理排序参数 if (params.sort_by) { apiParams.sort_by = params.sort_by; } else { apiParams.sort_by = 'popularity.desc'; } // 处理分页参数 apiParams.page = params.page || 1; // 处理语言参数 if (params.with_original_language) { apiParams.with_original_language = params.with_original_language; } // 处理成人内容参数 if (params.include_adult !== undefined) { apiParams.include_adult = params.include_adult; } // 处理无首播日期内容参数 if (params.include_null_first_air_dates !== undefined) { apiParams.include_null_first_air_dates = params.include_null_first_air_dates; } // 处理原产国参数 if (params.with_origin_country) { apiParams.with_origin_country = params.with_origin_country; } // 处理状态参数 if (params.with_status) { apiParams.with_status = params.with_status; } // 处理院线放映参数 if (params.screened_theatrically !== undefined) { apiParams.screened_theatrically = params.screened_theatrically; } // 处理时区参数 if (params.timezone) { apiParams.timezone = params.timezone; } // 处理观看区域参数 if (params.watch_region) { apiParams.watch_region = params.watch_region; } // 处理制作公司参数 if (params.with_companies) { apiParams.with_companies = params.with_companies; } // 处理观看提供商参数 if (params.with_watch_providers) { apiParams.with_watch_providers = params.with_watch_providers; } // 处理观看货币化类型参数 if (params.with_watch_monetization_types) { apiParams.with_watch_monetization_types = params.with_watch_monetization_types; } // 调用TMDb API const response = await tmdbClient_1.tmdbClient.discoverTvShows(apiParams); // 如果有指定年份,进行额外的过滤确保日期准确性 let filteredResults = response.results || []; if (requestedYear) { console.log(`过滤前剧集数量: ${filteredResults.length}`); filteredResults = filteredResults.filter((show) => { // 确保有首播日期 if (!show.first_air_date) { console.log(`剧集 "${show.name}" (ID: ${show.id}) 缺少首播日期,已过滤`); return false; } // 解析首播年份并与请求的年份比较 const airDateYear = new Date(show.first_air_date).getFullYear(); const matches = airDateYear === requestedYear; if (!matches) { console.log(`剧集 "${show.name}" (ID: ${show.id}) 首播日期 ${show.first_air_date} (${airDateYear}年) 与请求年份 ${requestedYear} 不匹配,已过滤`); } return matches; }); console.log(`过滤后剧集数量: ${filteredResults.length}`); } // 格式化结果 const results = formatDiscoverResults(filteredResults); // 构建响应 return { page: response.page, results, total_pages: response.total_pages, total_results: filteredResults.length // 更新为过滤后的总数 }; } catch (error) { // console.error('高级剧集发现失败:', error); throw new errorHandler_1.ApiError(`高级剧集发现失败: ${(0, errorHandler_1.formatErrorMessage)(error)}`, 500); } } /** * 获取人物的电视作品 * 这是一个替代方案,用于在discover/tv不支持按演员筛选的情况下使用 * @param personId 人物ID * @returns 该人物参与的电视剧列表 */ async function getPersonTvCredits(personId) { try { // 调用person/{person_id}/tv_credits API获取此人参与的所有电视剧 const response = await tmdbClient_1.tmdbClient.getPersonTvCredits(personId); // 格式化结果以匹配DiscoverShowsResponse格式 const results = response.cast || []; const formattedResults = formatDiscoverResults(results); return { page: 1, results: formattedResults, total_pages: 1, total_results: formattedResults.length }; } catch (error) { throw new errorHandler_1.ApiError(`获取人物电视作品失败: ${(0, errorHandler_1.formatErrorMessage)(error)}`, 500); } } /** * 通过人物名称查找其参与的电视剧 * @param personName 人物名称 * @returns 该人物参与的电视剧列表 */ async function findShowsByPersonName(personName) { try { // 先查找人物ID const personId = await findPersonId(personName); if (!personId) { throw new errorHandler_1.ApiError(`未找到人物: ${personName}`, 404); } // 然后获取其电视作品 return getPersonTvCredits(personId); } catch (error) { throw new errorHandler_1.ApiError(`查找人物电视作品失败: ${(0, errorHandler_1.formatErrorMessage)(error)}`, 500); } } /** * 根据演员名称查找推荐电视剧 * 此函数提供了一种替代方法来弥补discover/tv接口不支持按演员筛选的限制 * @param actorName 演员名称 * @param limit 返回结果数量限制 * @returns 包含该演员的电视剧列表 */ async function getRecommendationsByActor(actorName, limit = 10) { try { // 获取演员ID const actorId = await findPersonId(actorName); if (!actorId) { throw new errorHandler_1.ApiError(`未找到演员: ${actorName}`, 404); } // 获取演员的电视剧作品 const response = await getPersonTvCredits(actorId); // 按流行度排序并限制结果数量 let sortedResults = [...response.results]; sortedResults.sort((a, b) => (b.vote_average || 0) - (a.vote_average || 0)); sortedResults = sortedResults.slice(0, limit); return { page: 1, results: sortedResults, total_pages: 1, total_results: sortedResults.length }; } catch (error) { throw new errorHandler_1.ApiError(`获取演员推荐电视剧失败: ${(0, errorHandler_1.formatErrorMessage)(error)}`, 500); } }