Send the MCP's answer back to the bound phone/chat, with any images the model captured along the way (e.g. capture_screen). Charges that channel's quota once, regardless of image count. Image delivery is best-effort — a failed upload/send is logged, not fatal.
(request_data: RemoteReplyRequest, current_user: AuthUser)
| 252 | |
| 253 | @remote_router.post("/remote/reply", tags=["Remote"]) |
| 254 | async def remote_reply(request_data: RemoteReplyRequest, current_user: AuthUser): |
| 255 | """Send the MCP's answer back to the bound phone/chat, with any images the model captured |
| 256 | along the way (e.g. capture_screen). Charges that channel's quota once, regardless of |
| 257 | image count. Image delivery is best-effort — a failed upload/send is logged, not fatal.""" |
| 258 | # Imported here: both modules import this one for their webhooks. |
| 259 | from messaging import assert_content_allowed, save_temp_image, send_whatsapp_text |
| 260 | from tools_router import send_telegram_photo, send_telegram_text |
| 261 | from quota_manager import try_consume_for |
| 262 | |
| 263 | code = await _require_owner(request_data.code, current_user.id) |
| 264 | r = await get_redis() |
| 265 | address = await r.get(_bind_key(code, request_data.channel)) |
| 266 | if not address: |
| 267 | raise HTTPException(status_code=404, detail=f"No {request_data.channel} linked to this code.") |
| 268 | |
| 269 | assert_content_allowed(request_data.text) |
| 270 | |
| 271 | allowed, _usage_count, _reason = await try_consume_for(current_user, request_data.channel) |
| 272 | if not allowed: |
| 273 | raise HTTPException( |
| 274 | status_code=429, |
| 275 | detail={ |
| 276 | "message": f"Daily {request_data.channel} quota has been exceeded.", |
| 277 | "quota_type": request_data.channel, |
| 278 | }, |
| 279 | ) |
| 280 | |
| 281 | images = (request_data.images or [])[:MAX_REPLY_IMAGES] |
| 282 | |
| 283 | if request_data.channel == "whatsapp": |
| 284 | media_urls = [] |
| 285 | for i, image_b64 in enumerate(images): |
| 286 | try: |
| 287 | media_urls.append(await save_temp_image(image_b64)) |
| 288 | except Exception as e: |
| 289 | logger.warning(f"Remote reply: failed to host image {i+1} for WhatsApp: {e}") |
| 290 | await send_whatsapp_text(address, request_data.text[:1600], media_urls or None) |
| 291 | else: |
| 292 | for i, image_b64 in enumerate(images): |
| 293 | try: |
| 294 | await send_telegram_photo(address, image_b64) |
| 295 | except Exception as e: |
| 296 | logger.warning(f"Remote reply: failed to send image {i+1} to Telegram: {e}") |
| 297 | await send_telegram_text(address, request_data.text[:4096]) |
| 298 | return {"success": True} |
nothing calls this directly
no test coverage detected