diff --git a/README.md b/README.md
index 6fab7eb..0b95fca 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@ LogVar 弹幕 API 服务器
- **日志记录**:捕获 `console.log`(info 级别)和 `console.error`(error 级别),JSON 内容格式化输出。
- **部署支持**:支持本地运行、Docker 容器化、Vercel 一键部署、Cloudflare 一键部署和 Docker 一键启动。
- **手动选择记忆**:支持记住之前搜索title时手动选择的anime,并在后续的match自动匹配时优选该anime【实验性】。
+- **手动搜索支持输入播放链接获取弹幕**:支持手动搜索的播放器输入爱优腾芒哔播放链接可获取弹幕,如`senplayer`。
## 前置条件
- Node.js(v18.0.0 或更高版本;理论兼容更低版本,请自行测试)
@@ -212,6 +213,7 @@ LogVar 弹幕 API 服务器
+4. 现已支持手动搜索标题输入爱优腾芒哔播放链接获取弹幕。
> 注意:
>
diff --git a/danmu_api/worker.js b/danmu_api/worker.js
index a211fef..9b4b35e 100644
--- a/danmu_api/worker.js
+++ b/danmu_api/worker.js
@@ -854,7 +854,7 @@ async function get360Zongyi(title, entId, site, year) {
links.push({
"name": episodeInfo.id,
"url": episodeInfo.url,
- "title": `【${site}】${title}(${year}) #${episodeInfo.name} ${episodeInfo.period}#`,
+ "title": `【${site}】 #${episodeInfo.name} ${episodeInfo.period}#`,
"sort": epNum || episodeInfo.sort || null
});
}
@@ -2645,11 +2645,12 @@ async function fetchYouku(inputUrl) {
content: "",
};
content.timepoint = danmu.playat / 1000;
- if (danmu.propertis?.color) {
- content.color = JSON.parse(danmu.propertis).color;
+ const prop = JSON.parse(danmu.propertis)
+ if (prop?.color) {
+ content.color = prop.color;
}
- if (danmu.propertis?.pos) {
- const pos = JSON.parse(danmu.propertis).pos;
+ if (prop?.pos) {
+ const pos = prop.pos;
if (pos === 1) content.ct = 5;
else if (pos === 2) content.ct = 4;
}
@@ -3754,7 +3755,12 @@ function log(level, ...args) {
const message = args
.map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : arg))
.join(" ");
- const timestamp = new Date().toISOString();
+
+ // 获取上海时区时间(UTC+8)
+ const now = new Date();
+ const shanghaiTime = new Date(now.getTime() + (8 * 60 * 60 * 1000));
+ const timestamp = shanghaiTime.toISOString().replace('Z', '+08:00');
+
logBuffer.push({ timestamp, level, message });
if (logBuffer.length > MAX_LOGS) logBuffer.shift();
console[level](...args);
@@ -3900,7 +3906,7 @@ async function handleVodAnimes(animesVod, curAnimes, key) {
links.push({
"name": count,
"url": epInfo[1],
- "title": `【${platform}】${anime.vod_name}(${anime.vod_year}) #${epInfo[0]}#`
+ "title": `【${platform}】 #${epInfo[0]}#`
});
}
}
@@ -3952,7 +3958,7 @@ async function handle360Animes(animes360, curAnimes) {
links.push({
"name": i + 1,
"url": item.url,
- "title": `【${anime.seriesSite}】${anime.titleTxt}(${anime.year}) #${i + 1}#`
+ "title": `【${anime.seriesSite}】 #${i + 1}#`
});
}
}
@@ -4011,7 +4017,7 @@ async function handleRenrenAnimes(animesRenren, queryTitle, curAnimes) {
links.push({
"name": ep.episodeIndex,
"url": ep.episodeId,
- "title": `【${ep.provider}】${anime.title}(${anime.year}) #${ep.title}#`
+ "title": `【${ep.provider}】 #${ep.title}#`
});
}
@@ -4064,7 +4070,7 @@ async function handleHanjutvAnimes(animesHanjutv, queryTitle, curAnimes) {
links.push({
"name": ep.title,
"url": ep.pid,
- "title": `【hanjutv】${anime.name}(${new Date(anime.updateTime).getFullYear()}) #${epTitle}#`
+ "title": `【hanjutv】 #${epTitle}#`
});
}
@@ -4112,7 +4118,7 @@ async function handleBahamutAnimes(animesBahamut, queryTitle, curAnimes) {
links.push({
"name": ep.episode,
"url": ep.videoSn.toString(),
- "title": `【bahamut】${simplized(anime.title)}(${(anime.info.match(/(\d{4})/) || [null])[0]}) #${epTitle}#`
+ "title": `【bahamut】 #${epTitle}#`
});
}
@@ -4204,6 +4210,56 @@ async function searchAnime(url) {
const curAnimes = [];
+ // 链接弹幕解析
+ const urlRegex = /^(https?:\/\/)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,6}(:\d+)?(\/[^\s]*)?$/;
+ if (urlRegex.test(queryTitle)) {
+ const tmpAnime = {
+ "animeId": 111,
+ "bangumiId": "string",
+ "animeTitle": queryTitle,
+ "type": "type",
+ "typeDescription": "string",
+ "imageUrl": "string",
+ "startDate": "2025-08-08T13:25:11.189Z",
+ "episodeCount": 1,
+ "rating": 0,
+ "isFavorited": true
+ };
+
+ let platform = "all";
+ if (queryTitle.includes(".qq.com")) {
+ platform = "qq";
+ } else if (queryTitle.includes(".iqiyi.com")) {
+ platform = "qiyi";
+ } else if (queryTitle.includes(".mgtv.com")) {
+ platform = "imgo";
+ } else if (queryTitle.includes(".youku.com")) {
+ platform = "youku";
+ } else if (queryTitle.includes(".bilibili.com")) {
+ platform = "bilibili1";
+ }
+
+ const links = [{
+ "name": "手动解析链接弹幕",
+ "url": queryTitle,
+ "title": `【${platform}】 #${queryTitle}#`
+ }];
+ curAnimes.push(tmpAnime);
+ const exists = animes.some(existingAnime => existingAnime.animeId === tmpAnime.animeId);
+ if (!exists) {
+ const transformedAnimeCopy = {...tmpAnime, links: links};
+ addAnime(transformedAnimeCopy);
+ }
+ if (animes.length > MAX_ANIMES) removeEarliestAnime();
+
+ return jsonResponse({
+ errorCode: 0,
+ success: true,
+ errorMessage: "",
+ animes: curAnimes,
+ });
+ }
+
try {
// 根据 sourceOrderArr 动态构建请求数组
log("info", `Search sourceOrderArr: ${sourceOrderArr}`);