Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/app/utils/url_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def extract_video_id(url: str, platform: str) -> Optional[str]:
return f"BV{match.group(1)}" if match else None

elif platform == "youtube":
# 匹配 v=xxxxxyoutu.be/xxxxx,ID 长度通常为 11
match = re.search(r"(?:v=|youtu\.be/)([0-9A-Za-z_-]{11})", url)
# 匹配 v=xxxxxyoutu.be/xxxxx 或 shorts/xxxxx,ID 长度通常为 11
match = re.search(r"(?:v=|youtu\.be/|shorts/)([0-9A-Za-z_-]{11})", url)
return match.group(1) if match else None

elif platform == "douyin":
Expand Down
2 changes: 1 addition & 1 deletion backend/app/validators/video_url_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

SUPPORTED_PLATFORMS = {
"bilibili": r"(https?://)?(www\.)?bilibili\.com/video/[a-zA-Z0-9]+",
"youtube": r"(https?://)?(www\.)?(youtube\.com/watch\?v=|youtu\.be/)[\w\-]+",
"youtube": r"(https?://)?(www\.)?(youtube\.com/(watch\?v=|shorts/)|youtu\.be/)[\w\-]+",
"douyin": "douyin",
"kuaishou": "kuaishou"
}
Expand Down
50 changes: 50 additions & 0 deletions backend/tests/test_video_url_support.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import importlib.util
import pathlib
import unittest


ROOT = pathlib.Path(__file__).resolve().parents[1]


def _load_module(name, relative_path):
module_path = ROOT / relative_path
spec = importlib.util.spec_from_file_location(name, module_path)
if spec is None or spec.loader is None:
raise ImportError(f"{name} module spec not found")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module


url_parser = _load_module("url_parser", pathlib.Path("app") / "utils" / "url_parser.py")
video_url_validator = _load_module(
"video_url_validator",
pathlib.Path("app") / "validators" / "video_url_validator.py",
)


class TestVideoUrlSupport(unittest.TestCase):
def test_extract_youtube_video_id_from_supported_url_shapes(self):
expected_id = "dQw4w9WgXcQ"

cases = [
f"https://www.youtube.com/watch?v={expected_id}",
f"https://youtu.be/{expected_id}",
f"https://www.youtube.com/shorts/{expected_id}",
]

for url in cases:
with self.subTest(url=url):
self.assertEqual(
url_parser.extract_video_id(url, "youtube"),
expected_id,
)

def test_accepts_youtube_shorts_url(self):
url = "https://www.youtube.com/shorts/dQw4w9WgXcQ"

self.assertTrue(video_url_validator.is_supported_video_url(url))


if __name__ == "__main__":
unittest.main()