All calls go through scripts/kuaishou.py (stdlib-only). The user's OAuth token
arrives as $KUAISHOU_TOKEN and the app id as $KUAISHOU_APP_ID (injected from
the connector's metadata.platform_env); the script reads both and fails fast
with a clear message if either is missing — never print either.
Resolve the script first ($SKILL_DIR may point at a different skill loaded the
same turn), and repeat this preamble in every Bash block:
KS="$SKILL_DIR/scripts/kuaishou.py"; [ -f "$KS" ] || KS=$(find /tmp -maxdepth 8 -path '*/skills/*/scripts/kuaishou.py' 2>/dev/null | head -1)
[ -f "$KS" ] || { echo "kuaishou script not found (SKILL_DIR=$SKILL_DIR)" >&2; exit 1; }
Read
python3 "$KS" whoami # nickname, avatar, fans, follows, city
python3 "$KS" works --limit 20 # works + play/like/comment counts
python3 "$KS" works --limit 20 --cursor <photo_id> # next page
python3 "$KS" work <photo-id> # one work
python3 "$KS" counts # public / friend / private / total
Publish a video
This posts publicly to the user's real account — there is no draft mode. Before publishing, confirm with the user in chat:
- the caption (required by 快手), and
- that the video is their own original work — 快手 bans accounts that publish non-original video, and the ban lands on the user's account.
Without a trailing --confirm the command only dry-runs and publishes nothing.
--confirm must be the last argument.
# 1) Dry run — show the user exactly what will be posted
python3 "$KS" publish --caption "标题" --video-url "https://cdn.acedata.cloud/....mp4" \
--cover-url "https://cdn.acedata.cloud/....jpg"
# 2) After they confirm in chat
python3 "$KS" publish --caption "标题" --video-url "https://cdn.acedata.cloud/....mp4" \
--cover-url "https://cdn.acedata.cloud/....jpg" --confirm
A cover image is required (--cover-url or --cover-file, < 10MB). Local
files work too via --video-file / --cover-file. Optional: --stereo-type
for 360/180 panoramic video, --product-id to attach a 小黄车 product.
Remote --*-url inputs must live on cdn.acedata.cloud (or Kuaishou's own
image hosts). Anything else is rejected — upload it to our CDN first, or pass a
local path. This blocks a hostile URL from turning the upload step into an SSRF.
After a successful publish, record the deliverable once (see
_shared/artifacts.md):
publish_artifact(kind="video", channel="kuaishou", title="<caption>",
url="<the url returned by the script>", status="delivered")
Gotchas
- Upload success ≠ playable video. The upload step only confirms bytes
arrived; a malformed file fails later at transcode with
视频发布失败(120003) or视频未上传成功(120002). Report those verbatim. - Rate limits: 1000 calls/day per user, 100k/day per app.
100100402means the limit was hit or the account is banned. ACCESS_DENIED= the authorization is missing that endpoint's scope → reconnect 快手 and grant it. Token expiry (100200108) also means reconnect.- Kuaishou answers HTTP 200 even on failure — the script already checks
result != 1, so trust itserrorfield rather than the exit status alone. - Connections need re-authorizing roughly every 180 days: the refresh token does not extend on refresh. If the user hits an auth error, have them reconnect.