Conversation
…bhook Cron/standalone delivery builds a one-shot BlueBubblesAdapter to POST a message while the gateway's live adapter already listens on the webhook port. Three failure modes, all reproduced on a real BB deployment: 1. connect() unconditionally binds webhook_host:webhook_port → EADDRINUSE kills the fallback send before send() runs (cron jobs 'delivered' nothing for days). 2. The one-shot disconnect() unregisters the webhook by URL — identical to the live adapter's registration — wiping it from BlueBubbles. Outbound REST keeps working, inbound iMessage events silently die. 3. _webhook_url normalises 127.0.0.1 → localhost; the listener binds IPv4 only and macOS resolves localhost to ::1 first, so the server POSTs events at a dead port. Inbound dies again, differently. Fix: add connect_send_only (platform extra or BLUEBUBBLES_CONNECT_SEND_ONLY) — connect() pings the server, skips the webhook bind/register, and disconnect() skips the unregister. The standalone send path in send_message_tool sets the flag; _webhook_url now keeps the literal 127.0.0.1 instead of rewriting to localhost.
Duplicate of #51763 for the standalone send-only lifecycle: it already avoids the webhook bind/register/unregister collision. This branch also carries loopback normalization work from the existing BlueBubbles repair family; please split or rebase any distinct portion. |
|
Agreed — closing this as duplicate. #51763 covers the send-only bind/unregister lifecycle (same root cause, cleaner API via One thing worth adding for the other two PRs, from a real deployment (macOS, gateway + BlueBubbles server on the same host, cron delivery + inbound iMessage):
Both were reproduced and fixed locally; happy to help review either PR. Also: the send-only flag currently on my branch reads from platform |
Summary
Cron/standalone delivery builds a one-shot
BlueBubblesAdapterto POST a message while the gateway live adapter already holds the webhook listener. Three failure modes, all reproduced on a real BB deployment (macOS, gateway + BB server on same host):connect()unconditionally bindswebhook_host:webhook_port; a second bind on 8645 fails with[Errno 48] address already in use, killing the send before it runs. Cron jobs that hit the standalone fallback silently delivered nothing._webhook_urlnormalizes127.0.0.1→localhost; the listener binds IPv4 only and macOS resolves localhost to::1(IPv6) first, so BlueBubbles POSTs events at a dead port. Inbound dies again, differently.Fix
connect_send_only(from platformextraorBLUEBUBBLES_CONNECT_SEND_ONLY):connect()pings the server then skips the webhook bind/register;disconnect()skips the unregister.tools/send_message_tool._send_bluebubblessets the flag (it builds a one-shot adapter by design)._webhook_urlkeeps the literal127.0.0.1instead of rewriting tolocalhost.Test Plan
tests/gateway/test_bluebubbles.py(24 existing + 4 new: send-only flag from extra/env, default off, and send-only disconnect must not call_unregister_webhook; webhook URL tests updated to assert127.0.0.1survives normalization)._send_bluebubblessucceeds (SendResult.success=True), no second bind on 8645, webhook registration intact after disconnect, and inbound iMessage events reach the gateway again (verified by sending a reply from the phone).