feat: persist inbound quoted_message_id and add reply support to /api/send#109
Open
blazer5000 wants to merge 1 commit into
Open
feat: persist inbound quoted_message_id and add reply support to /api/send#109blazer5000 wants to merge 1 commit into
blazer5000 wants to merge 1 commit into
Conversation
…/send - Bridge: add quoted_message_id column to messages via ensureColumn (additive migration, safe on existing installs). StoreMessage gains a 14th param; the value is stored as SQL NULL for plain messages. ON CONFLICT merge uses COALESCE so a history-sync re-store (passing "") never clobbers an ID already written by handleMessage. sendWhatsAppMessage gains quoted_message_id / quoted_sender_jid / quoted_content params. When quoted_message_id is set and no media path is provided, the bridge builds an ExtendedTextMessage with ContextInfo so the sent message renders as a quoted reply on the recipient's device. Outbound rows persist the quoted_message_id so list_messages can report it. SendMessageRequest adds three optional JSON fields: quoted_message_id, quoted_sender_jid, quoted_content. - MCP server: send_message() and the send_message MCP tool both accept the three optional quote params and include them in the /api/send payload when present. list_messages and get_message_context SELECT quoted_message_id; msg_to_dict exposes it (null for non-replies). - Tests: Go tests cover quoted_message_id persistence for inbound replies and plain messages, quote-field parsing at the /api/send boundary, and extractQuotedMessageInfo corner cases. Python tests cover quoted-field propagation in the payload and absence of fields when no quoted_message_id is given, plus msg_to_dict output. - README: document quote params on send_message and inbound field. Closes verygoodplugins#107
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.
Closes #107
What this adds
Inbound persistence — quoted-reply detection was already implemented in
extractQuotedMessageInfo(used for webhook forwarding). This PR wires the extractedquotedMessageIdintoStoreMessageso replies are also archived in SQLite.A new nullable
quoted_message_id TEXTcolumn is added viaensureColumn— the existing migration helper, so it's safe on all existing installs with no manual action needed.quoted_message_idPlain messages store
NULL; theCOALESCEmerge inON CONFLICTmeans a later history-sync re-store (which passes"") cannot clobber a non-null ID already written byhandleMessage.Outbound quoted replies —
POST /api/sendnow accepts three optional fields:{ "recipient": "[email protected]", "message": "Great point!", "quoted_message_id": "3AORIGINAL0000001", "quoted_sender_jid": "[email protected]", "quoted_content": "original text" }When
quoted_message_idis non-empty and nomedia_pathis provided, the bridge sends anExtendedTextMessagewith aContextInfoblock so the message renders as a quoted reply on the recipient's device. Limitation: text-only — quoting media messages is not supported because the quote preview requires the original media key/URL, which the API caller does not have.Outbound rows also persist
quoted_message_idsolist_messagescan report it.MCP server —
send_message()and thesend_messageMCP tool both acceptquoted_message_id,quoted_sender_jid, andquoted_content(all optional, default""). They are forwarded to/api/sendonly when non-empty.list_messagesandget_message_contextnow includequoted_message_idin every returned message dict (null for non-replies).Tests
Go (
whatsapp-bridge/main_test.go):TestHandleMessage_QuotedReply_IDPersisted— inbound reply stores correctquoted_message_idTestHandleMessage_PlainMessage_QuotedIDIsNull— plain message stores SQL NULLTestSendHandler_QuotedReplyFields_PassedThrough— new JSON fields are parsed (empty recipient → 400)TestExtractQuotedMessageInfo_ExtendedText— helper extracts StanzaID, Participant, and contentTestExtractQuotedMessageInfo_NoContextInfo— plain/nil message returns all-emptyPython (
tests/test_bridge_auth.py,tests/test_whatsapp.py):test_send_message_with_quoted_reply_includes_quote_fields— payload contains all three fieldstest_send_message_without_quote_omits_quote_fields— no extra keys when not quotingtest_msg_to_dict_quoted_message_id_present/absentAll existing tests continue to pass (
go test ./...anduv run pytest -v).Schema impact
One new nullable column:
messages.quoted_message_id TEXT. Added viaensureColumn— idempotent, backward-compatible, no downtime.