diff --git a/danmu_api/apis/dandan-api.js b/danmu_api/apis/dandan-api.js index 645d89c..b86b482 100644 --- a/danmu_api/apis/dandan-api.js +++ b/danmu_api/apis/dandan-api.js @@ -421,8 +421,12 @@ async function matchAniAndEp(season, episode, year, searchData, title, req, plat // 判断剧集 const normalizedTitle = normalizeSpaces(title); for (const anime of searchData.animes) { - if (globals.rememberLastSelect && preferAnimeId && anime.bangumiId.toString() !== preferAnimeId.toString() && - anime.animeId.toString() !== preferAnimeId.toString()) continue; + const animeIsPrefer = + globals.rememberLastSelect && + preferAnimeId && + String(anime.bangumiId) !== String(preferAnimeId) && + String(anime.animeId) !== String(preferAnimeId); + if (animeIsPrefer) continue; if (normalizeSpaces(anime.animeTitle).includes(normalizedTitle)) { // 年份匹配优先于季匹配 if (!matchYear(anime, year)) { @@ -445,7 +449,7 @@ async function matchAniAndEp(season, episode, year, searchData, title, req, plat log("info", "过滤后的集标题", filteredEpisodes.map(episode => episode.episodeTitle)); // 年份匹配通过后,再判断season - if (matchSeason(anime, title, season)) { + if (matchSeason(anime, title, season) || !animeIsPrefer) { // 使用新的集数匹配策略 const matchedEpisode = findEpisodeByNumber(filteredEpisodes, episode, platform); if (matchedEpisode) { @@ -459,7 +463,12 @@ async function matchAniAndEp(season, episode, year, searchData, title, req, plat } else { // 判断电影 for (const anime of searchData.animes) { - if (globals.rememberLastSelect && preferAnimeId && anime.bangumiId.toString() !== preferAnimeId.toString()) continue; + const animeIsPrefer = + globals.rememberLastSelect && + preferAnimeId && + String(anime.bangumiId) !== String(preferAnimeId) && + String(anime.animeId) !== String(preferAnimeId); + if (animeIsPrefer) continue; const animeTitle = anime.animeTitle.split("(")[0].trim(); if (animeTitle === title) { // 年份匹配优先 diff --git a/danmu_api/configs/globals.js b/danmu_api/configs/globals.js index 9340328..3987f1f 100644 --- a/danmu_api/configs/globals.js +++ b/danmu_api/configs/globals.js @@ -13,7 +13,7 @@ export const Globals = { accessedEnvVars: {}, // 静态常量 - VERSION: '1.11.0', + VERSION: '1.11.1', MAX_LOGS: 500, // 日志存储,最多保存 500 行 MAX_ANIMES: 100, diff --git a/danmu_api/sources/mango.js b/danmu_api/sources/mango.js index bd02c24..7cb086d 100644 --- a/danmu_api/sources/mango.js +++ b/danmu_api/sources/mango.js @@ -568,6 +568,7 @@ export default class MangoSource extends BaseSource { // 弹幕和视频信息 API 基础地址 const api_video_info = "https://pcweb.api.mgtv.com/video/info"; const api_ctl_barrage = "https://galaxy.bz.mgtv.com/getctlbarrage"; + const api_rd_barrage = "https://galaxy.bz.mgtv.com/rdbarrage"; // 解析 URL 获取 cid 和 vid const regex = /^(https?:\/\/[^\/]+)(\/[^?#]*)/; @@ -615,8 +616,9 @@ export default class MangoSource extends BaseSource { const data = typeof res.data === "string" ? JSON.parse(res.data) : res.data; const time = data.data.info.time; - // 尝试使用新API(支持彩色弹幕)获取分段列表 + let useNewApi = true; try { + // 尝试使用新API(支持彩色弹幕)获取分段列表 const ctlBarrageUrl = `${api_ctl_barrage}?version=8.1.39&abroad=0&uuid=&os=10.15.7&platform=0&mac=&vid=${vid}&pid=&cid=${cid}&ticket=`; const res = await httpGet(ctlBarrageUrl, { headers: { @@ -629,25 +631,35 @@ export default class MangoSource extends BaseSource { // 检查数据结构 if (!ctlBarrage.data || !ctlBarrage.data.cdn_list || !ctlBarrage.data.cdn_version) { log("warn", `新API缺少必要字段,返回空分段列表`); - return new SegmentListResponse({ - "type": "imgo", - "segmentList": [] - }); + useNewApi = false; } // 构建分段列表 const segmentList = []; - const totalSegments = Math.ceil(time_to_second(time) / 60); // 每1分钟一个分段 - const cdnList = ctlBarrage.data.cdn_list.split(',')[0]; - const cdnVersion = ctlBarrage.data.cdn_version; + if (!useNewApi) { + const step = 60; // 每60秒一个分段 + const end_time = time_to_second(time); + for (let i = 0; i < end_time; i += step) { + segmentList.push({ + "type": "imgo", + "segment_start": i, // 每段开始时间(秒) + "segment_end": Math.min((i + step), time_to_second(time)), // 每段结束时间(秒) + "url": `${api_rd_barrage}?vid=${vid}&cid=${cid}&time=${i * 1000}` // 每段弹幕URL + }); + } + } else { + const totalSegments = Math.ceil(time_to_second(time) / 60); // 每1分钟一个分段 + const cdnList = ctlBarrage.data.cdn_list.split(',')[0]; + const cdnVersion = ctlBarrage.data.cdn_version; - for (let i = 0; i < totalSegments; i++) { - segmentList.push({ - "type": "imgo", - "segment_start": i * 60, // 每段开始时间(秒) - "segment_end": Math.min((i + 1) * 60, time_to_second(time)), // 每段结束时间(秒) - "url": `https://${cdnList}/${cdnVersion}/${i}.json` // 每段弹幕URL - }); + for (let i = 0; i < totalSegments; i++) { + segmentList.push({ + "type": "imgo", + "segment_start": i * 60, // 每段开始时间(秒) + "segment_end": Math.min((i + 1) * 60, time_to_second(time)), // 每段结束时间(秒) + "url": `https://${cdnList}/${cdnVersion}/${i}.json` // 每段弹幕URL + }); + } } return new SegmentListResponse({ diff --git a/danmu_api/utils/cache-util.js b/danmu_api/utils/cache-util.js index 024d67f..88f2303 100644 --- a/danmu_api/utils/cache-util.js +++ b/danmu_api/utils/cache-util.js @@ -233,6 +233,7 @@ export function storeAnimeIdsToMap(curAnimes, key) { // 保存旧的prefer值 const oldValue = globals.lastSelectMap.get(key); const oldPrefer = oldValue?.prefer; + const oldSource = oldValue?.source; // 如果key已存在,先删除它(为了更新顺序,保证 FIFO) if (globals.lastSelectMap.has(key)) { @@ -242,7 +243,7 @@ export function storeAnimeIdsToMap(curAnimes, key) { // 添加新记录,保留prefer字段 globals.lastSelectMap.set(key, { animeIds: [...uniqueAnimeIds], - ...(oldPrefer !== undefined && { prefer: oldPrefer }) + ...(oldPrefer !== undefined && { prefer: oldPrefer, source: oldSource }) }); // 检查是否超过 MAX_LAST_SELECT_MAP,超过则删除最早的