feat: add video note publishing (post-video) - #2
Merged
Conversation
Ports the upstream `post-video` command from jackwener#15 and threads the per-request `uploadAddr` from the upload permit response through both image and video upload paths so it works on rednote too. Behavioral changes: - New `xhs post-video` command (--video required; --cover optional; topics from --topic flags + body hashtags; --private supported). - `create_image_note` now POSTs via `_creator_post` (`webapi.rednote.com` / `creator.xiaohongshu.com`) instead of the edith host. This matches the path the web client actually uses and is the upstream PR's fix for "Chinese title/body returns API error when posting." `business_binds` is now serialized with `ensure_ascii=False` for the same reason. - `get_upload_permit` returns the `uploadAddr` field from the permit response. `upload_file` / `upload_video` accept an `upload_addr` override; falls back to the static `UPLOAD_HOST` constant when empty (preserves xiaohongshu behavior). Refactor: - Note creation paths share a single `_post_note` helper instead of two near-identical 30-line builders. Test plan: - `uv run pytest` — 114 passed under both XHS_TARGET=xiaohongshu (default) and XHS_TARGET=rednote. - `ruff check` clean. - `xhs post-video --help` and validation errors (missing file, unsupported extension) rendered correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
post-videocommand from upstream jackwener/xiaohongshu-cli#15 —xhs post-video --title ... --body ... --video file.mp4 [--cover cover.jpg] [--topic ...] [--private].uploadAddrfrom the upload permit response through both image and video upload paths so video publishing also works underXHS_TARGET=rednote(rednote's permit endpoint returns a different upload host per request, which the upstream PR doesn't handle).create_image_noteandcreate_video_notenow POST via_creator_post(the host the web client actually uses for note creation) and serializebusiness_bindswithensure_ascii=False.Why threading uploadAddr matters here
Without it, the upstream PR works on
xiaohongshu.com(whereUPLOAD_HOST = ros-upload.xiaohongshu.comis a valid CDN endpoint) but breaks onrednote.combecause the rednote permit response points uploads at a different host. Now both targets work without target-specific code paths in the upload methods.Behavioral changes (existing functionality)
xhs post(image notes) now posts via the creator host (webapi.rednote.com/creator.xiaohongshu.com) rather than the edith host. Upstream verified this is the right host and that posting Chinese titles/bodies stops failing with the switch.business_bindsJSON is now serialized withensure_ascii=False(no escaped Unicode in the embedded JSON string).Refactor
Image and video note creation share a
_post_notehelper instead of two near-identical 30-line payload builders. Same payload shape as upstream — just deduped.Test plan
uv run pytest tests/— 114 passed, 27 skippedXHS_TARGET=rednote uv run pytest tests/— 114 passed, 27 skippedruff check xhs_cli/cleanxhs post-video --helpshows expected optionsxhs post-video --video /missing.mp4→ "Video file not found"xhs post-video --video foo.txt→ "Unsupported video format '.txt'. Supported: .mov, .mp4"XHS_TARGET=rednote— pending. We have authenticated rednote sessions working from PR feat: support rednote.com via XHS_TARGET env var #1 but no live video upload was run. If the upload returns a 4xx, the most likely culprit is theuploadAddrhost — easy to debug withXHS_VERBOSE=1.Files
xhs_cli/client_mixins.py— addsget_video_upload_permit,upload_video,create_video_note; foldscreate_image_noteandcreate_video_noteinto_post_note;get_upload_permitreturnsuploadAddr;upload_fileacceptsupload_addroverride.xhs_cli/commands/creator.py— addspost_videocommand with validation; threadsuploadAddrinto the existingpostcommand's image upload.xhs_cli/cli.py— registerspost-video.xhs_cli/formatter_renderers.py— fixes a stale import-order lint carryover.README.md— documentspost-videoin both English and Chinese sections.Notes for reviewers
PR_DESCRIPTION.mdandtest_video.mp4files — both look like leftover scratch from the author's local repo, not source-of-truth.[bundler-runtime…]test artifact for the same reason.🤖 Generated with Claude Code