SuperAPI AI Directory

wjs-picking-comments

Writing & research

View repository

Updated 10-15 23:32

About this skill

wjs-picking-comments

Editthe Top 5 selected comments from the previously published article into an HTML <section> block and append it to the end ofthis not-yet-published article.

Core Principle

Comments = an extension of the previous article. Wang Jianshuo's Official Account receives many quality comments on every post; echoing them at the end of the next post is a sign of respect for readers and, for yourself, a thread that continues the conversation. The footer should not steal the spotlight from the main text—light background color, gray text, gently hanging at the end of the article.

When This Skill Fires

  • The user has finished writing a new WeChat draft, is about to publish, and wants to add a footer to bring along the highlights from the previous article
  • The user says "add the previous article's selected comments", "previous article footer", "pick five comments and put them at the bottom"
  • The user ran /wjs-picking-comments <new-article-folder>

When NOT to use

  • The previous article has not been published yet (drafts in the draft box don't count; you need to see that this entry actually exists in RSS)
  • The new article has not been written yet (finish the main text first, add the footer last)
  • What the user wants isreplying to comments(marking as selected / publicly replying to comments)—that is a matter for the mp.weixin.qq.com backend, and this skill does not do it

Setup (one-time · per machine)

The mp.weixin.qq.com backend cookies expire within a few hours, but the gstack persistent Chromium profile (~/.gstack/chromium-profile/) can last about 7 days after one QR scan; just scan again when it expires.

# 1. 打开后台,弹 QR
~/.claude/skills/gstack/browse/dist/browse goto https://mp.weixin.qq.com/
~/.claude/skills/gstack/browse/dist/browse screenshot --viewport /tmp/qr.png
open /tmp/qr.png

# 2. 手机微信扫屏幕上的 QR

# 3. 验证(应该看到 ...token=数字)
~/.claude/skills/gstack/browse/dist/browse wait --networkidle
~/.claude/skills/gstack/browse/dist/browse url

Do notuse browse connect—that is headed mode, and cookies are not persistent.Must use headless + screenshot scanning.

Signals that the session has expired: the script reports "not logged in" or browse js "document.body.innerText.includes('请重新登录')?'OUT':'IN'" returns OUT. Just rerun the 3 steps above.

Workflow

Step 1: Locate the "previous article"

scripts/fetch-latest-from-rss.py

Output JSON {title, url, published_at, summary}. The script sorts by <published> / <updated> in reverse order and automatically gives the truly latest entry.

Don't blindly trust: if the latest RSS entry is a zero-comment placeholder post like "Sharing an image", skip to the next one (--skip 1). Generally, use human judgment.

Step 2: Find the local article folder corresponding to the previous article

Search for a match by title in ~/code/wechat-publish/articles/*/meta.json :

python3 -c "
import json, glob, sys
title = sys.argv[1]
for p in sorted(glob.glob('$HOME/code/wechat-publish/articles/*/meta.json')):
    if json.load(open(p)).get('title') == title:
        print(p.rsplit('/',1)[0]); break
" "$TITLE_FROM_RSS"

If no local folder is found → create one temporarily:

mkdir -p /tmp/picking-comments-cache/<slug>
echo '{"title":"<title>"}' > /tmp/picking-comments-cache/<slug>/meta.json

Step 3: Fetch the previous article's appmsgcomment URL (one-time per article)

If <prev-folder>/comment-url.txt already exists → skip.

scripts/capture-comment-url.sh <prev-folder>

What the script does: use the gstack browser to open the comment management page → use JS to find the row matching the title → automatically click "N comments" on that row → capture the appmsgcomment URL from the network log → save it to <prev-folder>/comment-url.txt。

If the script reports NOT_FOUND → the article may be after page 2 of comment management; have the LLM turn the page (browse js simulate clicking "Next page") and rerun.

Step 4: Fetch comments

~/.claude/skills/wjs-publishing-wechat/scripts/fetch-comments-via-gstack.sh <prev-folder> --both

Output <prev-folder>/comments.md + comments.json. The script uses in-page browser fetch()—same-origin + cookies are automatically included, bypassing all token/cookie hassle.

If the script reports "session expired" → go back to Setup, scan the QR code again, and rerun.

Step 5: Filter + have the LLM pick Top 5

scripts/select-elected-comments.py <prev-folder>/comments.md --max 20 --min-elected 5

Output candidate JSON.Only look at selected comments; if there are fewer than 5 selected comments, automatically fill in unselected ones with likes ≥ 3.

Hand the candidates to the LLM (that is, the current you) and rank the Top 5 according to the followingWang Jianshuo Selection Criteria:

Wang Jianshuo Selection Criteria (ordered by weight)

  1. New angle > Old viewpoint + resonance. A perspective not mentioned in the previous post but that emerges after reading it.
  2. Concise > Wordy. One sentence that gets to the point > three paragraphs beating around the bush.
  3. Positive, curious, candid > Contrarian, fault-finding, self-promoting. Being different from Wang Jianshuo's viewpoint but gently curious is selectable; passive-aggressive is not.
  4. Can trigger the next post > Simple agreement. Comments that raise new questions or new hypotheses have the highest priority.
  5. High likes are a tie-breaker, not a deciding factor. Small-talk comments often get very high likes; comments with genuine insight may have only 1-2 likes.

Rank the 5 selected comments from strongest to weakest, written as picks.json:

[
  {"nick_name": "...", "location": "上海", "like_num": 19, "content": "..."},
  ...
]

location Take the province from the comment.content Use the original text,only remove emoji and obvious typos, do not polish.

If the total selections < 5: pick as many as there are, the footer template supports 1-5.

Step 6: Generate the footer HTML

scripts/build-footer.py \
  --prev-title "<上一篇标题>" \
  --prev-url   "<上一篇 mp.weixin URL>" \
  --recap      "<一句话复述上一篇核心问题或主张,≤50 字>" \
  --total-count <总留言数(含未精选)> \
  --picks-json /tmp/picks.json \
  --closing    "<本次收束语,不要每次都用同一句>" \
  --out        /tmp/footer-section.html

recap You write it yourself—refer back in one sentence to the question or claim raised in the previous post, so that readers who haven't seen the previous post can instantly catch the context.

closing Change the sentence each time to match the tone of this round's selections. Default phrasing reference: "Thank you to every friend who commented—next post I'll continue finding the key from your comments."

Step 7: Append to the new article

scripts/inject-footer.py <new-article-folder> /tmp/footer-section.html

Idempotent: if article.md already has a "Previous Post Selected Comments" section, replace it; otherwise append to the end of the article.

Step 8: Wrap up

Tell the user to run this upload:

~/.claude/skills/wjs-publishing-wechat/scripts/upload-draft.sh <new-article-folder>

Inputs

/wjs-picking-comments <new-article-folder>

First run: it will have you do Setup (scan QR code to log in to gstack) + automatically run capture-comment-url.sh to grab the URL. Every time after: single command, zero manual work.

File Layout

~/.claude/skills/wjs-picking-comments/
├── SKILL.md
└── scripts/
    ├── fetch-latest-from-rss.py    # 从 wewe-rss 拿最新一篇文章
    ├── capture-comment-url.sh      # 用 gstack 浏览器自动抓 appmsgcomment URL
    ├── select-elected-comments.py  # 从 comments.md 筛已精选 + 排序
    ├── build-footer.py             # 用 5 条候选 + 元数据生成 <section> HTML
    └── inject-footer.py            # 把 HTML 块追加/替换到 article.md

Anti-Patterns

Don't Reason
Select more than 5 With 6 or more, the footer becomes the main event
Select pleasantries like "Teacher Jianshuo writes so well" The footer is "continuing the conversation," not "showing off reader praise"
Select passive-aggressive comments This is not a debate arena
Modify the original comment text (except removing emoji and fixing typos) Comments are written by others; tampering is a breach of trust
Treat like_num as the sole standard Small talk gets high likes, insight often gets 1-2 likes
Put the footer in the middle of the body Always at the end of the article
Copy and paste the previous post's footer Every post must be re-selected
Use browse connect to scan the QR code Headed mode cookies are not persistent—must be headless + screenshot
Take cookies dump it out and stuff it into the Cookie header slave_sid contains an em-dash that clashes with latin-1 encoding, and token/cookies easily become inconsistent—already deprecated, all go through in-browser fetch()

Dependencies

  • gstack browse(~/.claude/skills/gstack/browse/dist/browse): persistent browser
  • wewe-rss container:http://localhost:4000/feeds/MP_WXS_2397242840.atom provides the Wang Jianshuo official account RSS (if the container isn't running, start it first)
  • wjs-publishing-wechat skill:fetch-comments-via-gstack.sh + upload-draft.sh is here
  • mp.weixin.qq.com backend login: persisted in the gstack profile, valid for about 7 days

Common Pitfalls

  • Do not wrap browse js as (async()=>{...})()—it will not await an IIFE async Promise. Use .then() chaining (fetch(url).then(r=>r.text())) to get the result.
  • fetch-comments-via-gstack.sh uses in-browser fetch—it does not go through the Cookie header, bypassing cookie encoding issues + bypassing token/session inconsistency.
  • comments.json in comment_list is a JSON string, requiring a second json.loads()—the script already unwraps automatically.
  • is_elected is a 0/1 integer, not a boolean.
  • location fieldis sometimes called province, the script falls back on both keys.
  • post_time is Unix epoch seconds, not milliseconds.
  • Comment management only shows the current page. If the previous post is after page 2, capture-comment-url.sh cannot find it—turn the page first and rerun.