feat(bilibili): support custom video covers

This commit is contained in:
sunshine6666666666
2026-07-11 10:47:39 +08:00
parent 0d3f93e8ac
commit 945bf8e1c0
3 changed files with 19 additions and 1 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ SAU_XHS_CREATOR_BASE_URL=https://creator.rednote.com sau xiaohongshu login --acc
```bash ```bash
sau bilibili login --account <account_name> sau bilibili login --account <account_name>
sau bilibili check --account <account_name> sau bilibili check --account <account_name>
sau bilibili upload-video --account <account_name> --file videos/demo.mp4 --title "示例标题" --desc "示例简介" --tid 249 --tags 足球,测试 sau bilibili upload-video --account <account_name> --file videos/demo.mp4 --title "示例标题" --desc "示例简介" --tid 249 --tags 足球,测试 --thumbnail covers/demo.png
``` ```
补充说明: 补充说明:
+5
View File
@@ -145,6 +145,7 @@ class BilibiliVideoUploadRequest:
tid: int tid: int
tags: list[str] tags: list[str]
publish_date: datetime | int publish_date: datetime | int
thumbnail_file: Path | None = None
@dataclass(slots=True) @dataclass(slots=True)
@@ -501,6 +502,8 @@ async def upload_bilibili_video(request: BilibiliVideoUploadRequest) -> Path:
] ]
if request.tags: if request.tags:
arguments.extend(["--tag", ",".join(request.tags)]) arguments.extend(["--tag", ",".join(request.tags)])
if request.thumbnail_file:
arguments.extend(["--cover", str(request.thumbnail_file)])
if isinstance(request.publish_date, datetime): if isinstance(request.publish_date, datetime):
arguments.extend(["--dtime", str(int(request.publish_date.timestamp()))]) arguments.extend(["--dtime", str(int(request.publish_date.timestamp()))])
@@ -680,6 +683,7 @@ def build_parser() -> argparse.ArgumentParser:
bilibili_upload_video_parser.add_argument("--desc", required=True, help="Video description") bilibili_upload_video_parser.add_argument("--desc", required=True, help="Video description")
bilibili_upload_video_parser.add_argument("--tid", required=True, type=int, help="Bilibili category id") bilibili_upload_video_parser.add_argument("--tid", required=True, type=int, help="Bilibili category id")
bilibili_upload_video_parser.add_argument("--tags", default="", help="Comma-separated tags, such as tag1,tag2") bilibili_upload_video_parser.add_argument("--tags", default="", help="Comma-separated tags, such as tag1,tag2")
bilibili_upload_video_parser.add_argument("--thumbnail", type=existing_file_path, help="Optional Bilibili cover image path")
bilibili_upload_video_parser.add_argument("--schedule", type=schedule_value, help=f"Schedule time in {schedule_help}") bilibili_upload_video_parser.add_argument("--schedule", type=schedule_value, help=f"Schedule time in {schedule_help}")
tencent_parser = platform_parsers.add_parser("tencent", help="Tencent/WeChat Channels operations") tencent_parser = platform_parsers.add_parser("tencent", help="Tencent/WeChat Channels operations")
@@ -926,6 +930,7 @@ async def dispatch(args: argparse.Namespace) -> int:
tid=args.tid, tid=args.tid,
tags=parse_tags(args.tags), tags=parse_tags(args.tags),
publish_date=args.schedule or 0, publish_date=args.schedule or 0,
thumbnail_file=args.thumbnail,
) )
await upload_bilibili_video(request) await upload_bilibili_video(request)
print(f"Bilibili video upload submitted: {request.video_file}") print(f"Bilibili video upload submitted: {request.video_file}")
+13
View File
@@ -1,6 +1,9 @@
import asyncio import asyncio
import tempfile
import unittest import unittest
from argparse import Namespace from argparse import Namespace
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
import sau_cli import sau_cli
@@ -43,3 +46,13 @@ class BilibiliCliTests(unittest.TestCase):
self.assertFalse(result["success"]) self.assertFalse(result["success"])
self.assertIn("local interactive terminal", result["message"].lower()) self.assertIn("local interactive terminal", result["message"].lower())
self.assertIn("qrcode.png", result["message"].lower()) self.assertIn("qrcode.png", result["message"].lower())
def test_upload_bilibili_video_passes_thumbnail_to_biliup(self):
with tempfile.TemporaryDirectory() as temp_dir:
account_file = Path(temp_dir) / "account.json"
account_file.write_text("{}", encoding="utf-8")
request = sau_cli.BilibiliVideoUploadRequest("creator", Path("demo.mp4"), "hello", "hello", 249, ["test"], 0, Path("cover.png"))
with patch("sau_cli.resolve_account_file", return_value=account_file), patch("sau_cli.run_biliup_command", return_value=SimpleNamespace(returncode=0, stdout="", stderr="")) as run_biliup:
asyncio.run(sau_cli.upload_bilibili_video(request))
self.assertIn("--cover", run_biliup.call_args.args[0])
self.assertIn("cover.png", run_biliup.call_args.args[0])