Overview
dsh-wechat-media
README / EN
Package documentation
Registry summary
dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
- **Group sending is unverified but well-founded.** Receiving from a group works today. Every reference implementation addresses a chat through `to_user_id` alone — the official client, the Go library (`daemon365/weixin-clawbot`, whose `Target` holds only `ToUserID` and whose `ChatType` is inbound metadata hardcoded to `direct`) and the Python port (`SiverKing/weixin-ClawBot-API`, which has no `chat_type` field at all). This package sends the same way. What is *not* confirmed against the platform is which inbound field carries a group's addressable id — `group_id` or `session_id`; the host logs `inbound group chat=… session_id=… group_id=… room=…` when a group first writes, which settles it, and if the answer is `session_id` the fix is one line in `describeEnvelope`. - **Stickers and unknown item types are dropped, but visibly.** A message that carries neither text nor a downloadable file is counted (`counters.unusable` in `/dsh-wechat-media/state`) and logged with its item types instead of vanishing silently. - **Voice is not bridged as audio.** WeChat's own transcript rides along as text when present; the `.silk` payload is downloaded but not transcoded. - **Proactive sends need an open conversation window.** Without a stored context token for that peer the server answers `ret=-2`; write to the bot first and the window opens. - **One poller per account token.** Two processes using the same token get `HTTP 403`. - **No message history API** exists on this platform; only live messages are seen. - Media is capped at 100 MiB inbound by default (`maxMediaMiB`). ### Feishu / 飞书 Nine additional tools work with Feishu documents, spreadsheets and bitables. All of them were built against shapes measured from the live API: | Tool | Does | |---|---| | `feishu_doc_create` | Creates a document **and writes the body**, then returns a link you can open | | `feishu_doc_read` | Reads a document's text from a `/docx/<id>` link (or a bare id) | | `feishu_doc_append` | Appends paragraphs to an existing document | | `feishu_sheet_create` / `_read` / `_write` | Creates a spreadsheet, reads a range, writes a range | | `feishu_bitable_create` / `_write` / `_read` | Creates a bitable, writes a record, reads records (by id to confirm a write) | **Document links need your tenant host.** `https://open.feishu.cn/docx/<id>` is the API host and answers a generic page, so the tools will not build a link from it. Set `tenantHost` (panel or `/prefs?feishuTenantHost=…`) or the `FEISHU_TENANT_HOST` environment variable to the host you see in any of your own Feishu document URLs, e.g. `ccnje3t5tkro.feishu.cn`. Without it the tool returns the document id and says why there is no link. - **Attachments are downloaded into the same inbox as the other two transports.** An image, file, audio or video message is fetched with `GET /open-apis/im/v1/messages/:message_id/resources/:file_key?type=image|file` and lands beside the WeChat and WeCom arrivals, so the model gets a path it can open. The `type` parameter is required - the live API answers `400 code 99992402` without it - and that was settled against the API rather than guessed. A fetch that fails says so in the prompt (`[飞书image未保存] …`) instead of leaving the model to assume there was no attachment. - **`delivery=stream` sends in whole parts on Feishu.** Word-by-word preview is a WeCom feature and is not implemented here. `/feishu` states this instead of leaving the setting looking effective. - **Group messages are not filtered by whether the bot was mentioned**, because the bot's own `open_id` is not readable from the SDK source either. Groups behave like WeCom: messages in an allowlisted chat are handled. - **A long connection that cannot start does not break the plugin.** The reason is recorded and shown by `/state` and `/feishu`; the plugin keeps working for every other channel. - **The long connection has not been verified against the live platform yet.** The endpoint
