's'
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
@@ -12,9 +13,10 @@ from urllib.parse import parse_qs
|
||||
import httpx
|
||||
from Crypto.Cipher import AES
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
|
||||
from fastapi.responses import HTMLResponse, PlainTextResponse
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, PlainTextResponse
|
||||
|
||||
from ..config import PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, PB_URL
|
||||
from ..services.mp_recommend import is_mp_recommend_webhook_body, try_persist_from_like_body
|
||||
|
||||
router = APIRouter(prefix="/chatbot", tags=["chatbot"])
|
||||
|
||||
@@ -461,6 +463,81 @@ def chatbot_health():
|
||||
return {"status": "ok", "module": "chatbot-clone", "profile": ACTIVE_PROFILE}
|
||||
|
||||
|
||||
def _log_like_incoming(request: Request, body: bytes) -> None:
|
||||
"""SmsForwarder Webhook 调试:打印完整入参(公众号助手等通知转发)。"""
|
||||
client_host = request.client.host if request.client else None
|
||||
client_port = request.client.port if request.client else None
|
||||
query = {k: v for k, v in request.query_params.multi_items()}
|
||||
headers = {k: v for k, v in request.headers.items()}
|
||||
ct = headers.get("content-type", "") or headers.get("Content-Type", "")
|
||||
|
||||
logger.info(
|
||||
"[like] ----- incoming POST ----- path=%s full_url=%s client=%s:%s query=%r",
|
||||
request.url.path,
|
||||
str(request.url),
|
||||
client_host,
|
||||
client_port,
|
||||
query,
|
||||
)
|
||||
logger.info("[like] content_type=%r content_length=%s body_bytes=%s", ct, headers.get("content-length"), len(body))
|
||||
logger.info("[like] headers=%s", headers)
|
||||
|
||||
if not body:
|
||||
logger.info("[like] body=(empty)")
|
||||
return
|
||||
|
||||
text = None
|
||||
try:
|
||||
text = body.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
hex_preview = body[:400].hex()
|
||||
suffix = "..." if len(body) > 400 else ""
|
||||
logger.info("[like] body=(non-utf8, hex prefix) %s%s", hex_preview, suffix)
|
||||
return
|
||||
|
||||
logger.info("[like] body_text=\n%s", text)
|
||||
low = (ct or "").lower()
|
||||
if "json" in low:
|
||||
try:
|
||||
parsed = json.loads(text)
|
||||
logger.info("[like] body_json=%s", json.dumps(parsed, ensure_ascii=False, indent=2))
|
||||
except json.JSONDecodeError as e:
|
||||
logger.info("[like] body_json_parse_failed: %s", e)
|
||||
|
||||
|
||||
def _client_ip_for_like(request: Request) -> str:
|
||||
xff = request.headers.get("x-forwarded-for") or request.headers.get("X-Forwarded-For")
|
||||
if xff:
|
||||
return xff.split(",")[0].strip()
|
||||
if request.client:
|
||||
return request.client.host or ""
|
||||
return ""
|
||||
|
||||
|
||||
@router.post("/like")
|
||||
async def like_webhook_sink(request: Request):
|
||||
"""接收 SmsForwarder 等 Webhook POST,详细打日志;公众号助手通知写入 PocketBase。"""
|
||||
body = await request.body()
|
||||
_log_like_incoming(request, body)
|
||||
ct = request.headers.get("content-type", "") or ""
|
||||
payload: dict = {"ok": True, "received_bytes": len(body)}
|
||||
try:
|
||||
text = body.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
return JSONResponse(status_code=200, content=payload)
|
||||
|
||||
if is_mp_recommend_webhook_body(text, ct):
|
||||
try:
|
||||
summary = await asyncio.to_thread(try_persist_from_like_body, text, ct, _client_ip_for_like(request))
|
||||
if summary:
|
||||
payload["mp_recommend"] = summary
|
||||
except Exception:
|
||||
logger.exception("[like] PocketBase 写入 mp_recommend 失败")
|
||||
payload["mp_recommend_error"] = "persist_failed"
|
||||
|
||||
return JSONResponse(status_code=200, content=payload)
|
||||
|
||||
|
||||
@router.post("/api/private-message/query")
|
||||
async def chatbot_private_message_query(payload: dict):
|
||||
authtoken = str(payload.get("authtoken", "")).strip()
|
||||
|
||||
Reference in New Issue
Block a user