Track bundled vendor runtime sources
This commit is contained in:
458
vendor/social-auto-upload/docs/superpowers/plans/2026-03-25-bilibili-cli-implementation.md
vendored
Normal file
458
vendor/social-auto-upload/docs/superpowers/plans/2026-03-25-bilibili-cli-implementation.md
vendored
Normal file
@@ -0,0 +1,458 @@
|
||||
# Bilibili CLI Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 为 Bilibili 补齐和抖音、快手同层级的 `sau` CLI、自动更新 `biliup` 的运行时机制、对应 skill,以及完整文档与上游致谢说明。
|
||||
|
||||
**Architecture:** 保持轻量,不新建大而全框架。新增一个 Bilibili 运行时模块负责检查 GitHub Release、下载/更新 `biliup`、执行命令;`sau_cli.py` 仅补 `bilibili` 子命令和参数映射;skill、example、README/CLI/install/update 文档按现有 Douyin/Kuaishou 结构对齐。
|
||||
|
||||
**Tech Stack:** Python 3.10+, `requests`, `argparse`, `asyncio`, `subprocess`, `pathlib`, `unittest`, GitHub Releases, existing `biliup` integration
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
### New files
|
||||
|
||||
- `uploader/bilibili_uploader/runtime.py`
|
||||
- Bilibili 运行时入口
|
||||
- 负责 `biliup` 自动检查、自动下载、自动更新、执行命令
|
||||
- `tests/__init__.py`
|
||||
- 测试包初始化
|
||||
- `tests/test_bilibili_runtime.py`
|
||||
- 测试自动更新、下载、缓存复用、执行器行为
|
||||
- `tests/test_sau_bilibili_cli.py`
|
||||
- 测试 `sau bilibili` parser 和 dispatch 行为
|
||||
- `skills/bilibili-upload/SKILL.md`
|
||||
- Bilibili CLI skill 主说明
|
||||
- `skills/bilibili-upload/references/runtime-requirements.md`
|
||||
- 运行前提和自动下载说明
|
||||
- `skills/bilibili-upload/references/cli-contract.md`
|
||||
- `sau bilibili ...` 命令契约
|
||||
- `skills/bilibili-upload/references/troubleshooting.md`
|
||||
- 常见问题与排障
|
||||
- `skills/bilibili-upload/scripts/examples/bilibili_commands.ps1`
|
||||
- PowerShell 示例命令
|
||||
- `skills/bilibili-upload/scripts/examples/bilibili_commands.sh`
|
||||
- shell 示例命令
|
||||
- `skills/bilibili-upload/scripts/examples/bilibili_cli_template.py`
|
||||
- Python 调用模板
|
||||
|
||||
### Modified files
|
||||
|
||||
- `sau_cli.py`
|
||||
- 补 `bilibili` 子命令
|
||||
- 复用现有 `resolve_account_file()`、`parse_tags()`、`parse_schedule()`
|
||||
- `examples/get_bilibili_cookie.py`
|
||||
- 对齐新的 `sau bilibili login` 用法
|
||||
- `examples/upload_video_to_bilibili.py`
|
||||
- 对齐新的 CLI/账号文件约定
|
||||
- `README.md`
|
||||
- 补 Bilibili CLI 用法、自动下载说明、致谢说明
|
||||
- `docs/CLI.md`
|
||||
- 补 `sau bilibili login/check/upload-video`
|
||||
- `docs/install.md`
|
||||
- 补 Bilibili 自动下载/首次运行说明
|
||||
- `docs/update.md`
|
||||
- 补 Bilibili 自动更新行为说明
|
||||
|
||||
## Task 1: Bilibili 自动更新运行时
|
||||
|
||||
**Files:**
|
||||
- Create: `uploader/bilibili_uploader/runtime.py`
|
||||
- Create: `tests/__init__.py`
|
||||
- Create: `tests/test_bilibili_runtime.py`
|
||||
|
||||
- [ ] **Step 1: 写 Bilibili 运行时测试**
|
||||
|
||||
使用 `unittest`,覆盖这些最小路径:
|
||||
|
||||
```python
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from uploader.bilibili_uploader.runtime import (
|
||||
build_biliup_runtime_path,
|
||||
ensure_biliup_binary,
|
||||
run_biliup_command,
|
||||
)
|
||||
|
||||
|
||||
class BiliupRuntimeTests(unittest.TestCase):
|
||||
def test_build_biliup_runtime_path_returns_platform_path(self):
|
||||
path = build_biliup_runtime_path("Windows")
|
||||
self.assertTrue(str(path).endswith("biliup.exe"))
|
||||
|
||||
@patch("uploader.bilibili_uploader.runtime.fetch_latest_release")
|
||||
def test_ensure_biliup_binary_downloads_when_missing(self, mock_release):
|
||||
mock_release.return_value = {
|
||||
"tag_name": "v1.0.0",
|
||||
"asset_url": "https://example.invalid/biliup.exe",
|
||||
"asset_name": "biliup.exe",
|
||||
}
|
||||
with patch("uploader.bilibili_uploader.runtime.download_biliup_asset") as mock_download:
|
||||
ensure_biliup_binary(force_check=True)
|
||||
mock_download.assert_called_once()
|
||||
|
||||
@patch("uploader.bilibili_uploader.runtime.fetch_latest_release")
|
||||
def test_ensure_biliup_binary_reuses_local_when_up_to_date(self, mock_release):
|
||||
mock_release.return_value = {
|
||||
"tag_name": "v1.0.0",
|
||||
"asset_url": "https://example.invalid/biliup.exe",
|
||||
"asset_name": "biliup.exe",
|
||||
}
|
||||
with patch("uploader.bilibili_uploader.runtime.read_local_biliup_version", return_value="v1.0.0"):
|
||||
with patch("uploader.bilibili_uploader.runtime.download_biliup_asset") as mock_download:
|
||||
ensure_biliup_binary(force_check=True)
|
||||
mock_download.assert_not_called()
|
||||
|
||||
@patch("uploader.bilibili_uploader.runtime.subprocess.run")
|
||||
def test_run_biliup_command_returns_completed_process(self, mock_run):
|
||||
mock_run.return_value = Mock(returncode=0, stdout="ok", stderr="")
|
||||
result = run_biliup_command(["login"])
|
||||
self.assertEqual(result.returncode, 0)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 运行测试,确认先失败**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m unittest tests.test_bilibili_runtime -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 因为 `uploader.bilibili_uploader.runtime` 还不存在而失败
|
||||
|
||||
- [ ] **Step 3: 写最小运行时实现**
|
||||
|
||||
在 `uploader/bilibili_uploader/runtime.py` 里先补这些最小函数:
|
||||
|
||||
```python
|
||||
def get_biliup_runtime_root() -> Path: ...
|
||||
def build_biliup_runtime_path(system_name: str | None = None) -> Path: ...
|
||||
def fetch_latest_release() -> dict: ...
|
||||
def read_local_biliup_version() -> str | None: ...
|
||||
def write_local_biliup_version(version: str) -> None: ...
|
||||
def download_biliup_asset(release: dict, destination: Path) -> Path: ...
|
||||
def ensure_biliup_binary(force_check: bool = True) -> Path: ...
|
||||
def run_biliup_command(arguments: list[str]) -> subprocess.CompletedProcess[str]: ...
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- 不引入复杂 manifest
|
||||
- 直接面向 GitHub Release 最新版本
|
||||
- 本地只保存当前版本字符串和二进制
|
||||
- 保持简单的路径/网络/替换逻辑
|
||||
|
||||
- [ ] **Step 4: 再跑运行时测试,确认通过**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m unittest tests.test_bilibili_runtime -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 所有 `BiliupRuntimeTests` 通过
|
||||
|
||||
- [ ] **Step 5: 提交这一小步**
|
||||
|
||||
```powershell
|
||||
git add uploader/bilibili_uploader/runtime.py tests/__init__.py tests/test_bilibili_runtime.py
|
||||
git commit -m "feat: add biliup runtime bootstrap"
|
||||
```
|
||||
|
||||
## Task 2: 接入 `sau bilibili` CLI
|
||||
|
||||
**Files:**
|
||||
- Modify: `sau_cli.py`
|
||||
- Create: `tests/test_sau_bilibili_cli.py`
|
||||
- Reference: `uploader/bilibili_uploader/main.py`
|
||||
- Reference: `utils/constant.py`
|
||||
|
||||
- [ ] **Step 1: 写 CLI parser 和 dispatch 测试**
|
||||
|
||||
在 `tests/test_sau_bilibili_cli.py` 中覆盖:
|
||||
|
||||
```python
|
||||
import unittest
|
||||
from argparse import Namespace
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import sau_cli
|
||||
|
||||
|
||||
class BilibiliCliTests(unittest.TestCase):
|
||||
def test_build_parser_accepts_bilibili_login(self):
|
||||
parser = sau_cli.build_parser()
|
||||
args = parser.parse_args(["bilibili", "login", "--account", "creator"])
|
||||
self.assertEqual(args.platform, "bilibili")
|
||||
self.assertEqual(args.action, "login")
|
||||
|
||||
def test_build_parser_requires_tid_for_upload_video(self):
|
||||
parser = sau_cli.build_parser()
|
||||
with self.assertRaises(SystemExit):
|
||||
parser.parse_args([
|
||||
"bilibili", "upload-video",
|
||||
"--account", "creator",
|
||||
"--file", "demo.mp4",
|
||||
"--title", "hello",
|
||||
"--desc", "hello",
|
||||
])
|
||||
|
||||
def test_dispatch_bilibili_check_prints_valid(self):
|
||||
args = Namespace(platform="bilibili", action="check", account="creator")
|
||||
with patch("sau_cli.check_bilibili_account", new=AsyncMock(return_value=True)):
|
||||
code = asyncio.run(sau_cli.dispatch(args))
|
||||
self.assertEqual(code, 0)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 运行测试,确认先失败**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m unittest tests.test_sau_bilibili_cli -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 因为 `sau_cli.py` 里还没有 `bilibili` parser/dispatch 分支而失败
|
||||
|
||||
- [ ] **Step 3: 在 `sau_cli.py` 中补 Bilibili 请求模型和命令**
|
||||
|
||||
只做最小接入,保持和 Douyin/Kuaishou 同风格:
|
||||
|
||||
```python
|
||||
@dataclass(slots=True)
|
||||
class BilibiliVideoUploadRequest:
|
||||
account_name: str
|
||||
video_file: Path
|
||||
title: str
|
||||
description: str
|
||||
tid: int
|
||||
tags: list[str]
|
||||
publish_date: datetime | int
|
||||
debug: bool = True
|
||||
|
||||
|
||||
async def login_bilibili_account(account_name: str) -> dict: ...
|
||||
async def check_bilibili_account(account_name: str) -> bool: ...
|
||||
async def upload_bilibili_video(request: BilibiliVideoUploadRequest) -> Path: ...
|
||||
```
|
||||
|
||||
Parser 最小要求:
|
||||
|
||||
- `sau bilibili login --account <name>`
|
||||
- `sau bilibili check --account <name>`
|
||||
- `sau bilibili upload-video --account ... --file ... --title ... --desc ... --tid ... [--tags] [--schedule]`
|
||||
|
||||
Dispatch 最小要求:
|
||||
|
||||
- 和其他平台一样输出 `valid` / `invalid`
|
||||
- 上传成功后打印简洁摘要
|
||||
|
||||
- [ ] **Step 4: 复用现有 B 站参数语义**
|
||||
|
||||
在 Bilibili wrapper 中直接沿用现有工程概念:
|
||||
|
||||
- `tid` 必填
|
||||
- `tags` 用现有 `parse_tags()`
|
||||
- `schedule` 沿用现有 `parse_schedule()`
|
||||
- `account` 仍通过 `resolve_account_file("bilibili", account_name)` 得到项目内账号路径
|
||||
|
||||
- [ ] **Step 5: 再跑 CLI 测试,确认通过**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m unittest tests.test_sau_bilibili_cli -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `BilibiliCliTests` 通过
|
||||
|
||||
- [ ] **Step 6: 做一次联测**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe sau_cli.py bilibili --help
|
||||
.\.venv\Scripts\python.exe sau_cli.py bilibili upload-video --help
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 能看到 `login` / `check` / `upload-video`
|
||||
- `upload-video` 中 `--tid` 显示为必填
|
||||
|
||||
- [ ] **Step 7: 提交这一小步**
|
||||
|
||||
```powershell
|
||||
git add sau_cli.py tests/test_sau_bilibili_cli.py
|
||||
git commit -m "feat: add bilibili cli commands"
|
||||
```
|
||||
|
||||
## Task 3: 补 skill 和 example
|
||||
|
||||
**Files:**
|
||||
- Create: `skills/bilibili-upload/SKILL.md`
|
||||
- Create: `skills/bilibili-upload/references/runtime-requirements.md`
|
||||
- Create: `skills/bilibili-upload/references/cli-contract.md`
|
||||
- Create: `skills/bilibili-upload/references/troubleshooting.md`
|
||||
- Create: `skills/bilibili-upload/scripts/examples/bilibili_commands.ps1`
|
||||
- Create: `skills/bilibili-upload/scripts/examples/bilibili_commands.sh`
|
||||
- Create: `skills/bilibili-upload/scripts/examples/bilibili_cli_template.py`
|
||||
- Modify: `examples/get_bilibili_cookie.py`
|
||||
- Modify: `examples/upload_video_to_bilibili.py`
|
||||
|
||||
- [ ] **Step 1: 参考 Douyin/Kuaishou skill 结构搭出 Bilibili skill**
|
||||
|
||||
要求:
|
||||
|
||||
- `SKILL.md` 风格和现有两个 skill 对齐
|
||||
- 默认优先用 `sau bilibili ...`
|
||||
- 明确写“程序会自动准备 `biliup`”
|
||||
|
||||
- [ ] **Step 2: 写示例命令文件**
|
||||
|
||||
示例命令至少包括:
|
||||
|
||||
```powershell
|
||||
sau bilibili login --account creator
|
||||
sau bilibili check --account creator
|
||||
sau bilibili upload-video --account creator --file .\videos\demo.mp4 --title "demo" --desc "demo" --tid 249 --tags 足球,测试
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 修改本地 example**
|
||||
|
||||
让以下 example 明确转向新入口或新约定:
|
||||
|
||||
- `examples/get_bilibili_cookie.py`
|
||||
- `examples/upload_video_to_bilibili.py`
|
||||
|
||||
要求:
|
||||
|
||||
- 不再让用户手动猜 `biliup.exe` 路径
|
||||
- 明确说明现在推荐走 `sau bilibili ...`
|
||||
- 继续保留 `VideoZoneTypes` 的使用示例
|
||||
|
||||
- [ ] **Step 4: 做一次文件级自检**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem skills\bilibili-upload -Recurse
|
||||
Get-Content examples\get_bilibili_cookie.py
|
||||
Get-Content examples\upload_video_to_bilibili.py
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- Bilibili skill 目录完整
|
||||
- example 内容已切到新的 CLI/说明
|
||||
|
||||
- [ ] **Step 5: 提交这一小步**
|
||||
|
||||
```powershell
|
||||
git add skills/bilibili-upload examples/get_bilibili_cookie.py examples/upload_video_to_bilibili.py
|
||||
git commit -m "feat: add bilibili upload skill"
|
||||
```
|
||||
|
||||
## Task 4: 补文档与上游致谢
|
||||
|
||||
**Files:**
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/CLI.md`
|
||||
- Modify: `docs/install.md`
|
||||
- Modify: `docs/update.md`
|
||||
|
||||
- [ ] **Step 1: 在 README 中补 Bilibili CLI 用法**
|
||||
|
||||
至少写清:
|
||||
|
||||
- `sau bilibili login`
|
||||
- `sau bilibili check`
|
||||
- `sau bilibili upload-video`
|
||||
- 自动下载/自动更新 `biliup`
|
||||
|
||||
- [ ] **Step 2: 在 CLI 文档中补命令契约**
|
||||
|
||||
把 Bilibili 一节写成和 Douyin/Kuaishou 同风格:
|
||||
|
||||
- 参数表
|
||||
- `tid` 必填
|
||||
- `schedule` 的行为
|
||||
|
||||
- [ ] **Step 3: 在安装/更新文档中写清自动下载机制**
|
||||
|
||||
至少补这些说明:
|
||||
|
||||
- 用户不需要自己安装 `biliup`
|
||||
- 第一次运行会自动下载
|
||||
- 后续运行会自动检查更新
|
||||
|
||||
- [ ] **Step 4: 在文档中加入对上游项目的感谢与借用说明**
|
||||
|
||||
至少在 README 中补一段明确说明:
|
||||
|
||||
- Bilibili 能力基于 `biliup`
|
||||
- 感谢/借用上游项目
|
||||
- 给出项目地址
|
||||
|
||||
建议文案:
|
||||
|
||||
```markdown
|
||||
## 致谢
|
||||
|
||||
本项目的 Bilibili 上传能力基于开源项目 `biliup` 的能力进行接入与封装。
|
||||
感谢 `biliup` 项目及其贡献者提供的基础能力:
|
||||
|
||||
- https://github.com/biliup/biliup
|
||||
```
|
||||
|
||||
- [ ] **Step 5: 做一次文档核对**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-Content README.md | Select-String -Pattern "bilibili|biliup|致谢" -Context 1,2
|
||||
Get-Content docs\CLI.md | Select-String -Pattern "bilibili" -Context 1,3
|
||||
Get-Content docs\install.md | Select-String -Pattern "bilibili|biliup" -Context 1,2
|
||||
Get-Content docs\update.md | Select-String -Pattern "bilibili|biliup" -Context 1,2
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- README、CLI、install、update 都出现 Bilibili 新内容
|
||||
- README 里有明确的上游致谢
|
||||
|
||||
- [ ] **Step 6: 跑最终验证**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
.\.venv\Scripts\python.exe -m unittest tests.test_bilibili_runtime tests.test_sau_bilibili_cli -v
|
||||
.\.venv\Scripts\python.exe sau_cli.py bilibili --help
|
||||
.\.venv\Scripts\python.exe sau_cli.py bilibili upload-video --help
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 单元测试通过
|
||||
- Bilibili CLI 帮助可用
|
||||
- `upload-video` 显示必填 `--tid`
|
||||
|
||||
- [ ] **Step 7: 提交收尾**
|
||||
|
||||
```powershell
|
||||
git add README.md docs/CLI.md docs/install.md docs/update.md
|
||||
git commit -m "docs: add bilibili cli guidance and attribution"
|
||||
```
|
||||
@@ -0,0 +1,583 @@
|
||||
# Browser CLI Unification Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** 为抖音、快手、小红书三家浏览器平台统一 `sau` CLI 契约,补齐小红书 CLI/skill,并把视频正文统一为 `desc`、图文正文统一为 `note`。
|
||||
|
||||
**Architecture:** 保持现有 `sau_cli.py` 单文件主入口,不引入新的 CLI 框架。`sau_cli.py` 负责 parser、request dataclass、dispatch 和账号文件解析;各平台 uploader 只做最小字段接线;skill、README、CLI/install/update 文档、examples 同步切到统一契约,避免对外同时暴露多套命名。
|
||||
|
||||
**Tech Stack:** Python 3.10+, `argparse`, `asyncio`, `dataclasses`, `pathlib`, `unittest`, existing Patchright-based uploaders, repository markdown docs
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
### New files
|
||||
|
||||
- `tests/test_sau_browser_cli.py`
|
||||
- 覆盖三家浏览器平台统一 CLI parser / dispatch / request 映射
|
||||
- `skills/xiaohongshu-upload/SKILL.md`
|
||||
- 小红书 CLI skill 主说明
|
||||
- `skills/xiaohongshu-upload/references/runtime-requirements.md`
|
||||
- 小红书运行前提
|
||||
- `skills/xiaohongshu-upload/references/cli-contract.md`
|
||||
- 小红书 CLI 契约
|
||||
- `skills/xiaohongshu-upload/references/troubleshooting.md`
|
||||
- 小红书排障文档
|
||||
- `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_commands.ps1`
|
||||
- PowerShell 示例命令
|
||||
- `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_commands.sh`
|
||||
- shell 示例命令
|
||||
- `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_cli_template.py`
|
||||
- Python 命令模板
|
||||
|
||||
### Modified files
|
||||
|
||||
- `sau_cli.py`
|
||||
- 新增 `xiaohongshu` parser / dispatch
|
||||
- 改造抖音、快手 request dataclass 和参数模型
|
||||
- `uploader/douyin_uploader/main.py`
|
||||
- 给视频接入 `desc`
|
||||
- 给图文接入 `title + note`
|
||||
- `uploader/ks_uploader/main.py`
|
||||
- 给视频接入 `desc`
|
||||
- 给图文接入 `title + note`
|
||||
- `uploader/xiaohongshu_uploader/main.py`
|
||||
- 只补 CLI 接线所需的最小字段适配
|
||||
- `README.md`
|
||||
- 补小红书 CLI / skill,并统一三家参数说明
|
||||
- `docs/CLI.md`
|
||||
- 统一三家浏览器平台命令契约
|
||||
- `docs/install.md`
|
||||
- 补小红书 CLI 示例和统一参数说明
|
||||
- `docs/update.md`
|
||||
- 补小红书检查项与 skill 路径
|
||||
- `skills/douyin-upload/SKILL.md`
|
||||
- `skills/douyin-upload/references/cli-contract.md`
|
||||
- `skills/douyin-upload/scripts/examples/douyin_commands.ps1`
|
||||
- `skills/douyin-upload/scripts/examples/douyin_commands.sh`
|
||||
- `skills/douyin-upload/scripts/examples/douyin_cli_template.py`
|
||||
- `skills/kuaishou-upload/SKILL.md`
|
||||
- `skills/kuaishou-upload/references/cli-contract.md`
|
||||
- `skills/kuaishou-upload/scripts/examples/kuaishou_commands.ps1`
|
||||
- `skills/kuaishou-upload/scripts/examples/kuaishou_commands.sh`
|
||||
- `skills/kuaishou-upload/scripts/examples/kuaishou_cli_template.py`
|
||||
- `examples/get_xiaohongshu_cookie.py`
|
||||
- `examples/upload_video_to_xiaohongshu.py`
|
||||
|
||||
## Task 1: 用测试锁定统一 CLI 契约
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_sau_browser_cli.py`
|
||||
- Reference: `sau_cli.py`
|
||||
|
||||
- [ ] **Step 1: 写统一 CLI parser 测试**
|
||||
|
||||
在 `tests/test_sau_browser_cli.py` 里覆盖最小命令契约:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import unittest
|
||||
from argparse import Namespace
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
import sau_cli
|
||||
|
||||
|
||||
class BrowserCliParserTests(unittest.TestCase):
|
||||
def test_build_parser_accepts_xiaohongshu_login(self):
|
||||
parser = sau_cli.build_parser()
|
||||
args = parser.parse_args(["xiaohongshu", "login", "--account", "creator"])
|
||||
self.assertEqual(args.platform, "xiaohongshu")
|
||||
self.assertEqual(args.action, "login")
|
||||
|
||||
def test_douyin_upload_video_accepts_desc(self):
|
||||
parser = sau_cli.build_parser()
|
||||
args = parser.parse_args([
|
||||
"douyin", "upload-video",
|
||||
"--account", "creator",
|
||||
"--file", "demo.mp4",
|
||||
"--title", "标题",
|
||||
"--desc", "视频简介",
|
||||
])
|
||||
self.assertEqual(args.desc, "视频简介")
|
||||
|
||||
def test_kuaishou_upload_note_accepts_title_and_note(self):
|
||||
parser = sau_cli.build_parser()
|
||||
args = parser.parse_args([
|
||||
"kuaishou", "upload-note",
|
||||
"--account", "creator",
|
||||
"--images", "1.png",
|
||||
"--title", "图文标题",
|
||||
"--note", "图文正文",
|
||||
])
|
||||
self.assertEqual(args.title, "图文标题")
|
||||
self.assertEqual(args.note, "图文正文")
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 写 dispatch 路由测试**
|
||||
|
||||
继续在 `tests/test_sau_browser_cli.py` 中补最小 dispatch 验证:
|
||||
|
||||
```python
|
||||
class BrowserCliDispatchTests(unittest.TestCase):
|
||||
def test_dispatch_xiaohongshu_check_prints_valid(self):
|
||||
args = Namespace(platform="xiaohongshu", action="check", account="creator")
|
||||
with patch("sau_cli.check_xiaohongshu_account", new=AsyncMock(return_value=True)):
|
||||
code = asyncio.run(sau_cli.dispatch(args))
|
||||
self.assertEqual(code, 0)
|
||||
|
||||
def test_dispatch_douyin_upload_note_uses_new_request_fields(self):
|
||||
args = Namespace(
|
||||
platform="douyin",
|
||||
action="upload-note",
|
||||
account="creator",
|
||||
images=[Path("1.png")],
|
||||
title="图文标题",
|
||||
note="图文正文",
|
||||
tags="测试,图文",
|
||||
schedule=0,
|
||||
debug=False,
|
||||
headless=True,
|
||||
)
|
||||
with patch("sau_cli.upload_note", new=AsyncMock()) as mock_upload:
|
||||
asyncio.run(sau_cli.dispatch(args))
|
||||
request = mock_upload.await_args.args[0]
|
||||
self.assertEqual(request.title, "图文标题")
|
||||
self.assertEqual(request.note, "图文正文")
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 先跑测试确认失败**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
py -3 -m unittest tests.test_sau_browser_cli -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 因为 `sau_cli.py` 还没有 `xiaohongshu` 分支和统一字段而失败
|
||||
|
||||
- [ ] **Step 4: 提交测试脚手架**
|
||||
|
||||
```powershell
|
||||
git add tests/test_sau_browser_cli.py
|
||||
git commit -m "test: define browser cli unification contract"
|
||||
```
|
||||
|
||||
## Task 2: 改 `sau_cli.py`,补齐统一参数与小红书路由
|
||||
|
||||
**Files:**
|
||||
- Modify: `sau_cli.py`
|
||||
- Reference: `uploader/xiaohongshu_uploader/main.py`
|
||||
- Reference: `uploader/douyin_uploader/main.py`
|
||||
- Reference: `uploader/ks_uploader/main.py`
|
||||
|
||||
- [ ] **Step 1: 增加小红书 request dataclass**
|
||||
|
||||
在 `sau_cli.py` 中新增:
|
||||
|
||||
```python
|
||||
@dataclass(slots=True)
|
||||
class XiaohongshuVideoUploadRequest:
|
||||
account_name: str
|
||||
video_file: Path
|
||||
title: str
|
||||
description: str
|
||||
tags: list[str]
|
||||
publish_date: datetime | int
|
||||
thumbnail_file: Path | None = None
|
||||
publish_strategy: str = XIAOHONGSHU_PUBLISH_STRATEGY_IMMEDIATE
|
||||
debug: bool = True
|
||||
headless: bool = True
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class XiaohongshuNoteUploadRequest:
|
||||
account_name: str
|
||||
image_files: list[Path]
|
||||
title: str
|
||||
note: str
|
||||
tags: list[str]
|
||||
publish_date: datetime | int
|
||||
publish_strategy: str = XIAOHONGSHU_PUBLISH_STRATEGY_IMMEDIATE
|
||||
debug: bool = True
|
||||
headless: bool = True
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 改造抖音、快手 request dataclass**
|
||||
|
||||
把字段统一到以下模型:
|
||||
|
||||
```python
|
||||
class DouyinVideoUploadRequest:
|
||||
title: str
|
||||
description: str
|
||||
|
||||
class DouyinNoteUploadRequest:
|
||||
title: str
|
||||
note: str
|
||||
|
||||
class KuaishouVideoUploadRequest:
|
||||
title: str
|
||||
description: str
|
||||
|
||||
class KuaishouNoteUploadRequest:
|
||||
title: str
|
||||
note: str
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 视频用 `description`
|
||||
- 图文用 `note`
|
||||
- 不再把图文 request 设计成只有历史 `note` 语义但没有 `title`
|
||||
|
||||
- [ ] **Step 3: 改 parser**
|
||||
|
||||
在 `build_parser()` 里完成:
|
||||
|
||||
- `douyin upload-video` 增加 `--desc`
|
||||
- `kuaishou upload-video` 增加 `--desc`
|
||||
- `douyin upload-note` 改成 `--title --note`
|
||||
- `kuaishou upload-note` 改成 `--title --note`
|
||||
- 新增整套 `xiaohongshu`:
|
||||
- `login`
|
||||
- `check`
|
||||
- `upload-video --title --desc --tags --thumbnail`
|
||||
- `upload-note --images --title --note --tags`
|
||||
|
||||
- [ ] **Step 4: 补小红书账号操作函数**
|
||||
|
||||
在 `sau_cli.py` 中新增:
|
||||
|
||||
```python
|
||||
async def login_xiaohongshu_account(account_name: str, headless: bool = True) -> dict: ...
|
||||
async def check_xiaohongshu_account(account_name: str) -> bool: ...
|
||||
async def upload_xiaohongshu_video(request: XiaohongshuVideoUploadRequest) -> Path: ...
|
||||
async def upload_xiaohongshu_note(request: XiaohongshuNoteUploadRequest) -> Path: ...
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- 账号路径继续走 `resolve_account_file("xiaohongshu", account_name)`
|
||||
- 登录 / 检查分别复用 `xiaohongshu_setup` 与 `cookie_auth`
|
||||
- 上传前先做 `setup(handle=False)` 校验
|
||||
|
||||
- [ ] **Step 5: 改 dispatch**
|
||||
|
||||
要求:
|
||||
|
||||
- 三家浏览器平台都统一输出:
|
||||
- `login` 成功时打印账号文件路径
|
||||
- `check` 输出 `valid` / `invalid`
|
||||
- `upload-video` 打印简洁摘要
|
||||
- `upload-note` 打印图片数量摘要
|
||||
- request 构造统一映射:
|
||||
- 视频:`title + description`
|
||||
- 图文:`title + note`
|
||||
|
||||
- [ ] **Step 6: 跑 CLI 测试确认通过**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
py -3 -m unittest tests.test_sau_browser_cli -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `BrowserCliParserTests`
|
||||
- `BrowserCliDispatchTests`
|
||||
|
||||
全部通过
|
||||
|
||||
- [ ] **Step 7: 跑最小 help 自检**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
py -3 sau_cli.py douyin --help
|
||||
py -3 sau_cli.py kuaishou --help
|
||||
py -3 sau_cli.py xiaohongshu --help
|
||||
py -3 sau_cli.py xiaohongshu upload-note --help
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 小红书子命令存在
|
||||
- 图文命令展示 `--title`、`--note`
|
||||
- 视频命令展示 `--desc`
|
||||
|
||||
- [ ] **Step 8: 提交 CLI 主线**
|
||||
|
||||
```powershell
|
||||
git add sau_cli.py tests/test_sau_browser_cli.py
|
||||
git commit -m "feat: unify browser cli contracts"
|
||||
```
|
||||
|
||||
## Task 3: 给 uploader 做最小字段接线
|
||||
|
||||
**Files:**
|
||||
- Modify: `uploader/douyin_uploader/main.py`
|
||||
- Modify: `uploader/ks_uploader/main.py`
|
||||
- Modify: `uploader/xiaohongshu_uploader/main.py`
|
||||
- Modify: `tests/test_xiaohongshu_uploader.py`
|
||||
|
||||
- [ ] **Step 1: 给抖音视频接入 `desc`**
|
||||
|
||||
在 `DouYinVideo.__init__()` 中补 `desc` 参数和 `self.desc`,并把发布页填写逻辑改成:
|
||||
|
||||
```python
|
||||
await self.fill_title_and_description(page, self.title, self.desc or self.title, self.tags)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: 给抖音图文接入 `title + note`**
|
||||
|
||||
在 `DouYinNote.__init__()` 中补 `title` 参数,保留 `note` 作为图文正文,发布页填写改成:
|
||||
|
||||
```python
|
||||
await self.fill_title_and_description(page, self.title, self.note, self.tags)
|
||||
```
|
||||
|
||||
要求:
|
||||
|
||||
- `title` 必填
|
||||
- `note` 可选但建议非空;如果现有逻辑要求非空,就继续保留校验
|
||||
|
||||
- [ ] **Step 3: 给快手视频接入 `desc`**
|
||||
|
||||
在 `KSVideo.__init__()` 中补 `desc` 参数和 `self.desc`,填写“描述”区域时改成:
|
||||
|
||||
```python
|
||||
await page.keyboard.type(self.desc or self.title)
|
||||
```
|
||||
|
||||
- [ ] **Step 4: 给快手图文接入 `title + note`**
|
||||
|
||||
在 `KSNote.__init__()` 中补 `title` 参数与 `self.title`,保留 `self.note` 作为正文。
|
||||
|
||||
要求:
|
||||
|
||||
- 图文上传校验里增加 `title` 必填
|
||||
- 如果页面当前只有正文输入区,没有独立标题区,仍然要在 CLI / request / 构造函数层保持 `title` 字段,以便后续平台对齐
|
||||
|
||||
- [ ] **Step 5: 检查小红书 CLI 接线是否需要补充适配**
|
||||
|
||||
确认 `XiaoHongShuVideo` / `XiaoHongShuNote` 只需要以下映射即可:
|
||||
|
||||
```python
|
||||
title=request.title
|
||||
desc=request.description # 视频
|
||||
desc=request.note # 图文
|
||||
```
|
||||
|
||||
如果 `XiaoHongShuNote` 里还保留历史 `note` 兼容,不要删,只保持 CLI 层优先走 `title + note + tags`。
|
||||
|
||||
- [ ] **Step 6: 补一条小红书映射测试**
|
||||
|
||||
在 `tests/test_xiaohongshu_uploader.py` 中增加最小断言:
|
||||
|
||||
```python
|
||||
def test_note_title_defaults_do_not_override_explicit_title(self):
|
||||
app = xhs_main.XiaoHongShuNote(
|
||||
image_paths=["a.png"],
|
||||
note="正文",
|
||||
tags=[],
|
||||
publish_date=0,
|
||||
account_file="account.json",
|
||||
title="显式标题",
|
||||
desc="图文正文",
|
||||
)
|
||||
self.assertEqual(app.title, "显式标题")
|
||||
self.assertEqual(app.desc, "图文正文")
|
||||
```
|
||||
|
||||
- [ ] **Step 7: 跑 uploader 相关测试**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
py -3 -m unittest tests.test_xiaohongshu_uploader -v
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 小红书 uploader 相关单测通过
|
||||
|
||||
- [ ] **Step 8: 提交 uploader 接线**
|
||||
|
||||
```powershell
|
||||
git add uploader/douyin_uploader/main.py uploader/ks_uploader/main.py uploader/xiaohongshu_uploader/main.py tests/test_xiaohongshu_uploader.py
|
||||
git commit -m "feat: align browser uploader metadata fields"
|
||||
```
|
||||
|
||||
## Task 4: 新增小红书 skill,并同步更新抖音、快手 skill
|
||||
|
||||
**Files:**
|
||||
- Create: `skills/xiaohongshu-upload/SKILL.md`
|
||||
- Create: `skills/xiaohongshu-upload/references/runtime-requirements.md`
|
||||
- Create: `skills/xiaohongshu-upload/references/cli-contract.md`
|
||||
- Create: `skills/xiaohongshu-upload/references/troubleshooting.md`
|
||||
- Create: `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_commands.ps1`
|
||||
- Create: `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_commands.sh`
|
||||
- Create: `skills/xiaohongshu-upload/scripts/examples/xiaohongshu_cli_template.py`
|
||||
- Modify: `skills/douyin-upload/SKILL.md`
|
||||
- Modify: `skills/douyin-upload/references/cli-contract.md`
|
||||
- Modify: `skills/douyin-upload/scripts/examples/douyin_commands.ps1`
|
||||
- Modify: `skills/douyin-upload/scripts/examples/douyin_commands.sh`
|
||||
- Modify: `skills/douyin-upload/scripts/examples/douyin_cli_template.py`
|
||||
- Modify: `skills/kuaishou-upload/SKILL.md`
|
||||
- Modify: `skills/kuaishou-upload/references/cli-contract.md`
|
||||
- Modify: `skills/kuaishou-upload/scripts/examples/kuaishou_commands.ps1`
|
||||
- Modify: `skills/kuaishou-upload/scripts/examples/kuaishou_commands.sh`
|
||||
- Modify: `skills/kuaishou-upload/scripts/examples/kuaishou_cli_template.py`
|
||||
|
||||
- [ ] **Step 1: 复制现有 skill 目录结构作为小红书骨架**
|
||||
|
||||
要求:
|
||||
|
||||
- 风格对齐 `skills/douyin-upload/`
|
||||
- 默认优先走 `sau xiaohongshu ...`
|
||||
- 明确小红书支持:
|
||||
- `login`
|
||||
- `check`
|
||||
- `upload-video`
|
||||
- `upload-note`
|
||||
|
||||
- [ ] **Step 2: 写小红书 CLI 契约**
|
||||
|
||||
至少写清:
|
||||
|
||||
```bash
|
||||
sau xiaohongshu login --account <account>
|
||||
sau xiaohongshu check --account <account>
|
||||
sau xiaohongshu upload-video --account <account> --file <video> --title "<title>" [--desc "..."] [--tags ...]
|
||||
sau xiaohongshu upload-note --account <account> --images <img...> --title "<title>" [--note "..."] [--tags ...]
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 更新抖音、快手 skill 契约**
|
||||
|
||||
要求:
|
||||
|
||||
- 视频示例命令补 `--desc`
|
||||
- 图文示例命令改成 `--title --note`
|
||||
- 所有模板文件同步更新,不要只改文档不改脚本
|
||||
|
||||
- [ ] **Step 4: 做 skill 文件级自检**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-ChildItem skills\xiaohongshu-upload -Recurse
|
||||
Get-Content skills\douyin-upload\references\cli-contract.md
|
||||
Get-Content skills\kuaishou-upload\references\cli-contract.md
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 小红书 skill 目录完整
|
||||
- 抖音、快手 skill 契约都已经切到新参数模型
|
||||
|
||||
- [ ] **Step 5: 提交 skill 变更**
|
||||
|
||||
```powershell
|
||||
git add skills/xiaohongshu-upload skills/douyin-upload skills/kuaishou-upload
|
||||
git commit -m "feat: add xiaohongshu skill and align browser skill contracts"
|
||||
```
|
||||
|
||||
## Task 5: 更新 examples 和 README / docs
|
||||
|
||||
**Files:**
|
||||
- Modify: `examples/get_xiaohongshu_cookie.py`
|
||||
- Modify: `examples/upload_video_to_xiaohongshu.py`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/CLI.md`
|
||||
- Modify: `docs/install.md`
|
||||
- Modify: `docs/update.md`
|
||||
|
||||
- [ ] **Step 1: 改小红书 examples**
|
||||
|
||||
要求:
|
||||
|
||||
- `examples/get_xiaohongshu_cookie.py` 明确指向 `sau xiaohongshu login --account <account_name>` 这一主线
|
||||
- `examples/upload_video_to_xiaohongshu.py` 说明当前主线优先走 CLI
|
||||
- 如果继续保留 uploader 直连示例,注释里标明“调试入口 / 历史直连路径”
|
||||
|
||||
- [ ] **Step 2: 更新 README 平台表和快速开始**
|
||||
|
||||
README 至少要改这些位置:
|
||||
|
||||
- 平台能力表里把小红书改成:
|
||||
- `CLI ✅`
|
||||
- `Skill ✅`
|
||||
- 快速开始里的浏览器平台命令改成统一契约
|
||||
- 抖音、快手图文示例改成:
|
||||
|
||||
```bash
|
||||
sau douyin upload-note --account <account_name> --images videos/1.png videos/2.png --title "图文标题" --note "图文正文"
|
||||
sau kuaishou upload-note --account <account_name> --images videos/1.png videos/2.png --title "图文标题" --note "图文正文"
|
||||
sau xiaohongshu upload-note --account <account_name> --images videos/1.png videos/2.png --title "图文标题" --note "图文正文"
|
||||
```
|
||||
|
||||
- [ ] **Step 3: 更新 `docs/CLI.md`**
|
||||
|
||||
要求:
|
||||
|
||||
- 补 `xiaohongshu` 小节
|
||||
- 把三家浏览器平台整理成一致说明:
|
||||
- 视频:`title + desc + tags`
|
||||
- 图文:`title + note + tags`
|
||||
- 登录二维码说明补小红书
|
||||
|
||||
- [ ] **Step 4: 更新 `docs/install.md` 和 `docs/update.md`**
|
||||
|
||||
要求:
|
||||
|
||||
- 安装文档里补 `sau xiaohongshu --help`
|
||||
- 更新文档里补小红书自检命令和 skill 路径
|
||||
- 文档统一写 `account_name`
|
||||
|
||||
- [ ] **Step 5: 做文档与示例核对**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
Get-Content README.md | Select-String -Pattern "xiaohongshu|upload-note|--note|--desc" -Context 1,2
|
||||
Get-Content docs\CLI.md | Select-String -Pattern "xiaohongshu|--note|--desc" -Context 1,2
|
||||
Get-Content docs\install.md | Select-String -Pattern "xiaohongshu" -Context 1,2
|
||||
Get-Content docs\update.md | Select-String -Pattern "xiaohongshu" -Context 1,2
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- README、CLI、install、update 都出现小红书 CLI
|
||||
- 图文正文写成 `--note`
|
||||
- 视频描述写成 `--desc`
|
||||
|
||||
- [ ] **Step 6: 跑最终最小验证**
|
||||
|
||||
Run:
|
||||
|
||||
```powershell
|
||||
py -3 -m unittest tests.test_sau_browser_cli tests.test_xiaohongshu_uploader -v
|
||||
py -3 sau_cli.py xiaohongshu --help
|
||||
py -3 sau_cli.py xiaohongshu upload-video --help
|
||||
py -3 sau_cli.py xiaohongshu upload-note --help
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- 单测通过
|
||||
- 小红书 CLI 帮助存在
|
||||
- 视频命令显示 `--desc`
|
||||
- 图文命令显示 `--note`
|
||||
|
||||
- [ ] **Step 7: 提交收尾**
|
||||
|
||||
```powershell
|
||||
git add examples/get_xiaohongshu_cookie.py examples/upload_video_to_xiaohongshu.py README.md docs/CLI.md docs/install.md docs/update.md
|
||||
git commit -m "docs: align browser cli docs and examples"
|
||||
```
|
||||
47
vendor/social-auto-upload/docs/superpowers/plans/2026-03-25-xiaohongshu-shallow-alignment.md
vendored
Normal file
47
vendor/social-auto-upload/docs/superpowers/plans/2026-03-25-xiaohongshu-shallow-alignment.md
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# Xiaohongshu Shallow Alignment Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Align the browser-based Xiaohongshu uploader with the current Douyin/Kuaishou style for login QR flow, patchright usage, and formal video/note entry points without expanding into CLI or docs work.
|
||||
|
||||
**Architecture:** Keep the work inside `uploader/xiaohongshu_uploader/main.py` as a shallow refactor. Introduce a thin login flow with QR extraction, cookie validation, and result payloads, then add a shared base uploader plus separate video and note browser flows that reuse common setup.
|
||||
|
||||
**Tech Stack:** Python, patchright, async Playwright-compatible browser automation, unittest
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Lock expected login/setup behavior
|
||||
|
||||
**Files:**
|
||||
- Create: `tests/test_xiaohongshu_uploader.py`
|
||||
- Modify: `uploader/xiaohongshu_uploader/main.py`
|
||||
|
||||
- [ ] Add tests for `xiaohongshu_setup(..., return_detail=True)` invalid-cookie behavior and uploader validation behavior.
|
||||
- [ ] Run the targeted test file and confirm it fails for the expected missing behavior.
|
||||
- [ ] Implement the minimal production changes to satisfy those tests.
|
||||
|
||||
### Task 2: Refactor Xiaohongshu uploader module
|
||||
|
||||
**Files:**
|
||||
- Modify: `uploader/xiaohongshu_uploader/main.py`
|
||||
|
||||
- [ ] Switch the module from `playwright.async_api` to `patchright.async_api`.
|
||||
- [ ] Replace `page.pause()` login with QR extraction, terminal printing, QR file saving, polling, and cookie persistence.
|
||||
- [ ] Add a shared base uploader plus formal video and note entry points while keeping legacy public names callable.
|
||||
|
||||
### Task 3: Refresh local debug examples
|
||||
|
||||
**Files:**
|
||||
- Modify: `examples/get_xiaohongshu_cookie.py`
|
||||
- Modify: `examples/upload_video_to_xiaohongshu.py`
|
||||
|
||||
- [ ] Update the login example to use the aligned setup entry.
|
||||
- [ ] Update the upload example to expose direct video/note debug functions.
|
||||
|
||||
### Task 4: Verify
|
||||
|
||||
**Files:**
|
||||
- Test: `tests/test_xiaohongshu_uploader.py`
|
||||
|
||||
- [ ] Run the targeted unittest file.
|
||||
- [ ] Run a quick Python syntax/import check for the modified uploader and examples.
|
||||
Reference in New Issue
Block a user