- Remove duplicate function definitions with hardcoded "AI-оператор" strings (ai_voice_runtime, ai_orchestrator, voice_name_config, voice.py) - Remove unreachable dead code after return in ai_voice_runtime - Add SQL LIMIT to 17 unbounded queries across 12 services to prevent OOM - Move Python-side filtering to SQL WHERE in reporting_service - Downgrade 19 logger.warning to logger.info for normal-flow events in media_runtime Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
121 lines
4.0 KiB
Python
121 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from fastapi import FastAPI
|
|
from sqlalchemy import select
|
|
|
|
from services.shared.core import new_id, utc_now_iso
|
|
from services.shared.db import get_session
|
|
from services.shared.models import HealthResponse, WebchatMessageIn, WebchatMessageOut
|
|
from services.shared.sql_init import init_sql_schema
|
|
from services.shared.sql_models import Interaction, InteractionTimeline, WebchatMessageRow
|
|
|
|
app = FastAPI(title="webchat-adapter-service", version="2.0.0")
|
|
|
|
init_sql_schema()
|
|
|
|
|
|
def _to_out(row: WebchatMessageRow) -> WebchatMessageOut:
|
|
return WebchatMessageOut(
|
|
message_id=row.message_id,
|
|
session_id=row.session_id,
|
|
text=row.text,
|
|
visitor_name=row.visitor_name,
|
|
customer_external_id=row.customer_external_id,
|
|
queue_id=row.queue_id,
|
|
priority=row.priority,
|
|
payload=json.loads(row.payload_json or "{}"),
|
|
interaction_id=row.interaction_id,
|
|
created_at=row.created_at,
|
|
)
|
|
|
|
|
|
def _interaction_subject(payload: WebchatMessageIn) -> str:
|
|
subject = str(payload.payload.get("subject", "")).strip()
|
|
if subject:
|
|
return subject[:120]
|
|
text = payload.text.strip()
|
|
if len(text) <= 120:
|
|
return text
|
|
return f"{text[:117]}..."
|
|
|
|
|
|
def _create_interaction(session, payload: WebchatMessageIn, created_at: str) -> str:
|
|
interaction_id = new_id("int")
|
|
session.add(
|
|
Interaction(
|
|
interaction_id=interaction_id,
|
|
channel="webchat",
|
|
subject=_interaction_subject(payload),
|
|
customer_id=payload.customer_external_id,
|
|
queue_id=payload.queue_id or "q_webchat",
|
|
priority=payload.priority,
|
|
status="new",
|
|
assigned_to=None,
|
|
created_at=created_at,
|
|
updated_at=created_at,
|
|
)
|
|
)
|
|
session.add(
|
|
InteractionTimeline(
|
|
interaction_id=interaction_id,
|
|
timestamp=created_at,
|
|
action="interaction.created",
|
|
metadata_json=json.dumps({"channel": "webchat"}, ensure_ascii=False),
|
|
)
|
|
)
|
|
session.add(
|
|
InteractionTimeline(
|
|
interaction_id=interaction_id,
|
|
timestamp=created_at,
|
|
action="webchat.message_received",
|
|
metadata_json=json.dumps({"session_id": payload.session_id}, ensure_ascii=False),
|
|
)
|
|
)
|
|
return interaction_id
|
|
|
|
|
|
@app.get("/health", response_model=HealthResponse)
|
|
def health() -> HealthResponse:
|
|
return HealthResponse(status="ok", service="webchat-adapter-service", version="v2")
|
|
|
|
|
|
@app.post("/integrations/webchat/messages", response_model=WebchatMessageOut)
|
|
def create_message(payload: WebchatMessageIn) -> WebchatMessageOut:
|
|
session = get_session()
|
|
try:
|
|
created_at = utc_now_iso()
|
|
interaction_id = _create_interaction(session, payload, created_at)
|
|
row = WebchatMessageRow(
|
|
message_id=new_id("wcm"),
|
|
session_id=payload.session_id,
|
|
text=payload.text,
|
|
visitor_name=payload.visitor_name,
|
|
customer_external_id=payload.customer_external_id,
|
|
interaction_id=interaction_id,
|
|
queue_id=payload.queue_id or "q_webchat",
|
|
priority=payload.priority,
|
|
payload_json=json.dumps(payload.payload, ensure_ascii=False),
|
|
created_at=created_at,
|
|
)
|
|
session.add(row)
|
|
session.commit()
|
|
session.refresh(row)
|
|
return _to_out(row)
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
@app.get("/integrations/webchat/messages", response_model=list[WebchatMessageOut])
|
|
def list_messages(session_id: str | None = None, limit: int = 100) -> list[WebchatMessageOut]:
|
|
session = get_session()
|
|
try:
|
|
stmt = select(WebchatMessageRow).order_by(WebchatMessageRow.id.desc())
|
|
if session_id:
|
|
stmt = stmt.where(WebchatMessageRow.session_id == session_id)
|
|
rows = session.execute(stmt.limit(max(limit, 1))).scalars().all()
|
|
return [_to_out(row) for row in reversed(rows)]
|
|
finally:
|
|
session.close()
|