delete_message tool, optional caption on send_file, and a media-download 403 fix - #166
Open
vyakunin wants to merge 3 commits into
Open
delete_message tool, optional caption on send_file, and a media-download 403 fix#166vyakunin wants to merge 3 commits into
vyakunin wants to merge 3 commits into
Conversation
New POST /api/delete on the Go bridge wraps whatsmeow's BuildRevoke + SendMessage to "Delete for everyone" (default) or just drop the row from the local sqlite store. Python MCP exposes it as `delete_message(chat_jid, message_id, for_everyone)`. Useful for retracting a wrong link/file we just sent (the scenario that motivated this: a broken APK link was sent to a relative on the family_vpn project, and we needed to revoke before they tapped it). Constraints: only own messages can be revoked (whatsmeow); WhatsApp's server enforces the ~2-day "delete for everyone" window — older messages get an error back from SendMessage, which we surface as success=false.
Bridge (Go) already supports media+caption in a single WA message — every image/video/document branch in sendWhatsAppMessage sets Caption from the `message` field. The Python wrapper just wasn't plumbing it through, so callers had to send the file and the explanation as two separate bubbles. Add `caption: str = ""` to send_file in both whatsapp.py and the MCP tool in main.py; if non-empty, include it as `message` in the /api/send payload. Backwards-compatible with existing call sites that pass only recipient + media_path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
extractDirectPathFromURL stripped the URL query string, dropping the oh/oe (+ccb,_nc_sid) CDN-auth signature. whatsmeow's Download rebuilds the request as <freshHost><directPath>&hash=... with NO auth header, so authorization rides entirely on those query params inside directPath. Stripping them 403'd EVERY image and document download. The regression surfaced after the whatsmeow bump (20260107 -> 20260609, also carried here): that version switched Download to build from GetDirectPath() instead of the embedded URL, so the lossy derivation started biting. Returning path+query is exactly the protobuf DirectPath whatsmeow expects; the discarded host is replaced by a media-conn host. Verified end-to-end against the live bridge: a document (the family_vpn log, 54712 B, decrypts to the real text) and a fresh uncached image (576x1280 JPEG) both download where they previously 403'd. Adds a table-driven regression test asserting the signed query survives. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Three independent commits; happy to split into separate PRs.
1.
delete_messageAdds a delete/revoke tool.
for_everyone: truerevokes for both sides ("Delete for everyone", only valid for messages this client sent);falseremoves it locally solist_messagesstops returning it while the other party still sees it. Takeschat_jid+ the whatsmeowmessage_idreturned bysend_message.2.
send_filecaptionsend_filecould only send a bare attachment. Adds an optionalcaptionrendered with the file, matching what the app does. Omitting it preserves current behaviour.3. Media-download 403
Downloads were failing with 403 on some media. The signed query string was being stripped from
directPathbefore the fetch, so the request arrived unsigned. Keeping the query intact fixes it.Each commit stands alone and can be cherry-picked.