fix: 规范化含 BV 号的任意 B 站链接(稍后再看/收藏夹/追踪参数)

从"稍后再看"(/list/watchlater/?bvid=BV...)、收藏夹播放页等场景
复制的链接会被判为无效链接,尽管其中包含完整 BV 号;校验通过的
链接也会带着追踪参数原样传给 yt-dlp。

在请求入口新增 normalize_video_url():提取 BV 号重建标准
/video/BVxxx 链接,保留分 P 参数(?p=N),丢弃其余查询参数。
b23.tv 短链与其他平台行为不变,无 BV 号链接仍按原逻辑拒绝。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pumpkinperson996
2026-07-09 15:03:07 -05:00
co-authored by Claude Fable 5
parent 6d67e5a76a
commit b85d7bc1ff
4 changed files with 111 additions and 3 deletions
+11 -2
View File
@@ -7,7 +7,7 @@ from typing import Optional
from urllib.parse import urlparse
from fastapi import APIRouter, HTTPException, BackgroundTasks, UploadFile, File
from pydantic import BaseModel, validator, field_validator
from pydantic import BaseModel, validator, field_validator, model_validator
from dataclasses import asdict
from app.db.video_task_dao import get_task_by_video
@@ -17,7 +17,7 @@ from app.exceptions.note import NoteError
from app.services.note import NoteGenerator, logger
from app.services.task_serial_executor import task_serial_executor
from app.utils.response import ResponseWrapper as R
from app.utils.url_parser import extract_video_id
from app.utils.url_parser import extract_video_id, normalize_video_url
from app.validators.video_url_validator import is_supported_video_url
from fastapi import APIRouter, Request, HTTPException
from fastapi.responses import StreamingResponse
@@ -55,6 +55,15 @@ class VideoRequest(BaseModel):
# {"language": "zh", "full_text": "...", "segments": [{"start","end","text"}, ...]}
prefetched_transcript: Optional[dict] = None
@model_validator(mode="before")
@classmethod
def normalize_url(cls, data):
# 稍后再看/收藏夹/带追踪参数的 B 站链接先规范化成标准 /video/BVxxx 形式,
# 后续校验和 yt-dlp 下载拿到的都是干净链接
if isinstance(data, dict) and data.get("platform") == "bilibili" and data.get("video_url"):
data["video_url"] = normalize_video_url(str(data["video_url"]))
return data
@field_validator("video_url")
def validate_supported_url(cls, v):
url = str(v)