SuperAPI AI Directory

ray-wechat

General & other

View repository

Updated 10-15 22:37

About this skill

Ray WeChat

Split Official Account delivery into two gates: first confirm the local layout, then modify the online draft. Layout completion does not mean the draft has been saved; an API returning success does not mean the Chinese text, cover, and body are correct.

Fixed boundaries

  1. Only accept a final draft that has passed the ray-writer check. The content-pack in the knowledge base is a writing task description, not the body; if the facts, judgments, or article structure are still changing, return to the writing stage first.
  2. The cover comes from ray-cover. The Official Account cover and the X Article cover are used separately; do not stretch one to substitute for the other.
  3. When the user has not explicitly said "save to / update the WeChat draft box" in the current task, only generate the local HTML and preview, and do not call the WeChat write API.
  4. When the article already has an wechat_draft_media_id , only update the original draft; only allow creation when there is no ID, and the creation confirmation parameter must be explicitly used.
  5. By default, do not generate an author byline, QR code, or a "like, watch, forward" footer note. If the original text includes them, keep them as in the original; if the user asks to remove them, delete the entire block.
  6. Only save the draft; do not call freepublish/*, mass-send, or any publishing API; reading a published article is also a separate read-only task and must not be mixed into the draft-writing process.
  7. Do not output the AppSecret, access token, or image service key in logs, command parameters, or error messages.
  8. kind: translation or kind: repost translated articles have an extra authorization gate: whensource_permission is not granted or open-license , only produce local artifacts and do not write to the backend. After writing, do not check the originality declaration either — the Official Account's reprint declaration requires the original author to add a whitelist in the backend, which is a user action.
  9. All Official Account APIs go through the fixed egress declared in ~/.wewrite/fixed-egress.json by default. If the fixed egress is unavailable, the egress address does not match, or the configuration is missing, stop immediately and do not silently switch to the local machine's dynamic address; only set RAY_WECHAT_DIRECT=1temporarily when the user explicitly requests a direct connection. The network path does not change the draft-writing authorization.

0. Determine authorization first

Before starting, choose the single level based on the user's exact words in the current turn. This table and the decision rules are fully consistent with the ray main entry point andray-x-article , and are not explained separately in this Skill:

Level What can be done Basis for determination
local_only Only produce local artifacts: layout, mobile preview, delivery package, without touching any online backend The user only says "let me take a look first," "give me a preview," or "prepare a delivery package," or the whole sentence does not name a platform destination
draft_write Create or update a platform draft, and fully read it back for acceptance The exact words of this turn simultaneously containa specific platformanda destination, for example "save to the WeChat draft box" or "update the original Official Account draft"
Public publishing is not part of the content production pipeline This determination never produces it; a separate explicit publishing task must be opened

Three determination rules:

  1. Only names the platform, verb is vague—"push to WeChat", "sync to two platforms", "list in the backend"—do not directly escalate to draft_write. First finish the local artifact, then ask clearly in one sentence: "It's ready locally, should I write it into the official account draft box now?" Only write after receiving an affirmative answer. Neither write without authorization nor finish without saying anything.
  2. No platform destination named at all—"draft approved", "move to the next stage", "run the full publishing process"—always local_only, neither ask nor write.
  3. The user explicitly says "publish", "mass send", "make public"—still only go as far as the draft, and explain that public publishing exceeds the boundary of this Skill, and do not call the publishing interface.

Permission from past tasks, permission for platform X, an existing media ID, or a whitelist that has already been fixed do not constitute authorization for this round. When uncertain, always downgrade to local_only。

1. Read the current state

Read the article Markdown, formatted HTML, official account cover, and frontmatter. At minimum confirm:

  • title
  • wechat_draft_media_id(if present)
  • wechat_draft_cover or the local official account cover
  • wechat_draft_theme
  • Whether the user this round is "viewing a preview" or has already authorized "push to draft box"
  • Whether the user's current exact words can be clearly determined as draft_write

First verify the role of the source file.kind: content-pack、kind: idea or kind: research must stop, and follow the draft link in the frontmatter to find the main text; do not treat the task description as the final article just because the filename says "final package".

kind: translation or kind: repost is a translated piece, and the main text belongs to the original author. In addition to this round's authorization determination, also read source_permission: only granted and open-license can enter the backend,pending stays local and tell the user that what is missing is the original author's permission, not a script problem. For the contract, see ray-writer/references/translation.md。

When the article has no compatible knowledge base, it can still be delivered in the current workspace, but do not create a vault with a fixed name on your own. When long-term回流 is needed, first hand it over to ray-obsidian。

2. Generate formatting and preview

First read layout-contract.md and theme-library.md. By default use the three proprietary main styles, choosing according to the article's main reading action:

  • ray-judgment(Ray judgment): opinions, controversial judgments, a sense of power, and calls to action.
  • ray-method(Ray method): tutorials, steps, tool roundups, and action guides.
  • ray-deepread(Ray deep read): tech commentary, professional analysis, and long-form explanations.

When the user is still exploring, only give the single most fitting recommendation and one alternative, and format only after confirmation. Only when the user explicitly requests a third-party theme, call the already installed external formatting Skill;gzh-design can be used as an external formatter, but its AGPL component code must not be copied into this repository.

By default use the proprietary renderer to generate clean body text and a mobile preview:

python3 scripts/render_article.py \
  --article <文章.md> \
  --theme <ray-judgment|ray-method|ray-deepread> \
  --html <公众号正文.html> \
  --preview <手机预览.html>

Formatting must achieve:

  • The title is handled by the official account backend, and the body HTML starts from the global <section> .
  • Long articles have clear sections and skimmable highlights; by default do not add cards, tags, decorative English, or quote containers.
  • Leave only one blank line between each Markdown paragraph; there are no empty <p>。
  • Original bold text is fully preserved; do not proactively underline the keywords in every paragraph.
  • Do not split English words such as Instagram and YouTube for underlining or highlighting.
  • The attribution strategy is consistent with the user's requirements, leaving no placeholders.

Generate a local preview with a copy button. Actually open it at phone width and check the first screen, table of contents, chapters, long English text, ending, and horizontal overflow. Do not proceed to the next step until the user confirms the style.

3. Local delivery gate

Run:

python3 scripts/prepare_article.py \
  --article <文章.md> \
  --html <公众号正文.html> \
  --signature absent \
  --out <交付清单.json>

--signature Use absent、present or inherit. Any ERROR must be fixed and rerun; do not bypass the checks for source omissions, empty paragraphs, chapter count, English word splitting, or attribution.

The renderer intentionally leaves local absolute paths in <img src> so that the local preview can actually see the images. Therefore, when the body contains images, this step will inevitably report images are not uploaded yet:

  • local_only Stop here. This ERROR is expected and is the only ERROR allowed to remain; do not manually edit the HTML just to make the status green.
  • draft_write Continue to 3.1, and after the upload is complete, rerun this gate; it must status: ready before proceeding to step 4.

Translated/adapted drafts also verify authorization and attribution.source_permission If it is not cleared, or the original author or source link cannot be found in the body, these are hard ERRORs and can only be fixed by going back to ray-writer ; do not just manually add a line in the HTML. When the source link is written as a Markdown hyperlink, a reminder will remain: the URL is only in href , and external links in the body of a WeChat official account cannot be opened by most accounts, so it is recommended to change it to plain text.

3.1 Upload body images (only draft_write)

First do a dry run to confirm that the pending upload list corresponds one-to-one with the body references and that all files are on disk:

python3 scripts/wechat_images.py --html <公众号正文.html> --dry-run

After confirmation, upload for real; the script will replace the local paths in place with mmbiz.qpic.cn permanent links:

python3 scripts/wechat_images.py \
  --html <公众号正文.html> \
  --config ~/.wewrite/config.yaml
  • Go through media/uploadimg, return the body permanent link, do not consume the material library quota, and do not produce any publishing action.
  • Cache by file content sha256 in ~/.wewrite/image-cache.json; rerunning after rearranging or changing the theme will not upload duplicates.
  • Images larger than 1MB or not in jpg/png format will first be converted to JPEG copies no larger than 1600px before upload; the source files are not modified.
  • If any image is not on disk, the script fails entirely before upload begins and will not upload halfway.

4. Create or update draft

First read wechat-api.md and recovery-runbook.md. Credentials are preferentially read from WECHAT_APPID、WECHAT_SECRET , and existing ~/.wewrite/config.yamlmay also be used. Do not splice keys into visible commands.

WeChat official account image upload, cover upload, draft read/write, and read-back all go through the fixed egress confirmed in ~/.wewrite/fixed-egress.json by default. The script verifies the public address before obtaining the token; if the address does not match or the tunnel is unavailable, it stops in place and will not silently switch back to the home broadband. If WeChat still reports 40164, check according to the "IP whitelist" section of the recovery manual whether the fixed address is still in the backend whitelist, then retry from the same step. Do not bypass prepare_article.py、wechat_images.py、wechat_draft.py or the full read-back, and do not switch to freepublish/* for duplicate checking, verification, or publishing.

Update an existing draft:

python3 scripts/wechat_draft.py update \
  --article <文章.md> \
  --html <公众号正文.html> \
  --config ~/.wewrite/config.yaml \
  --theme <主题标识> \
  --signature absent \
  --record \
  --confirm

When there is no draft ID and the user has explicitly agreed to create one:

python3 scripts/wechat_draft.py create \
  --article <文章.md> \
  --html <公众号正文.html> \
  --cover <公众号封面.png> \
  --digest "文章摘要" \
  --config ~/.wewrite/config.yaml \
  --theme <主题标识> \
  --signature absent \
  --record \
  --confirm

update The original draft must first be read, preserving the author, cover, and comment settings; the correct title in the article frontmatter takes precedence over the old backend title.create Must have a cover and summary. Both actions must read the draft again after writing and be accepted; only after acceptance passes is it allowed to --record write back the local state.

5. Final acceptance

Completion requires all of the following conditions to be met simultaneously:

  • The updated item is the original media ID, or a new ID is obtained after explicit creation; there are no duplicate drafts.
  • The title, summary, author, and cover meet expectations.
  • All original sections and paragraphs are present in the original order, and the first and last sentences can be found.
  • The empty paragraph count is zero; the section count and emphasis style count match the local delivery checklist.
  • The attribution policy takes effect, and there are no placeholders.
  • The Chinese has no garbled characters, and English proper nouns have not been split apart.
  • frontmatter is updated to only after the remote readback passes as wechat_draft_status: draft。
  • The publishing interface was not called.
  • Local records use the exact field wechat_draft_status: draft, and do not write approximate fields.

When encountering network, allowlist, credential, encoding, or readback inconsistency issues, do not claim success. Repair the same draft according to the recovery manual and re-accept it.

On-device review

A passing readback only proves the content went into the right draft; it does not prove it looks right in WeChat. Local preview uses browser rendering, while WeChat injects its own default styles for properties that are not explicitly declared, so there will inevitably be differences between the two.

The script has no on-device rendering capability, nor does it replace the user clicking "Preview" in the backend to send it to their own WeChat. Therefore, at delivery, you must explicitly ask the user to open the draft on their phone, and provide these specific check items:

  • The spacing between the title and the opening paragraph on the first screen, and whether there is extra blank space.
  • The borders and background colors of section titles, and whether any lines or color blocks appear that are not written in the theme.
  • The borders of blockquotes, tables, and inline code, and whether they are the same set declared by the theme.
  • Whether all body images are displayed, whether their width fills the space, and whether any broken images remain.
  • Whether long English words and links overflow horizontally.

When the user reports any inconsistency, handle it according to the "styles on device differ from local preview" line in the recovery manual: explicitly declare the corresponding property in references/ray-themes.json , re-layout, re-upload, update the same media ID, and then ask the user to check again. Do not wrap it up by verbally explaining it as a "WeChat display issue".

Reference routing

Delivery requirements

Explain to the user whether the original draft or a new draft was updated, as well as the final status of the title, cover, body integrity, empty paragraphs, attribution, and encoding; for articles with images, add a sentence stating how many body images were uploaded. Then ask the user to review the items under "On-device review" on their phone, and explain that only the user can do this step. Finally, separately make clear that "this is a draft, and it has not been publicly published or mass-sent." Do not display keys, tokens, full API responses, or internal script details.