feat(send): async acceptance and send_result event
This commit is contained in:
@@ -1,33 +1,116 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from typing import Optional
|
||||
|
||||
from app.clients.pywechat_client import ClientRegistry, OnlineStatus, registry
|
||||
from app.models.event import EventType, OutboundEvent
|
||||
from app.repositories.event_store import EventStore, event_store
|
||||
|
||||
|
||||
class SendService:
|
||||
def __init__(self, registry: ClientRegistry):
|
||||
def __init__(self, registry: ClientRegistry, store: EventStore):
|
||||
self.registry = registry
|
||||
self.store = store
|
||||
|
||||
def send_text(self, account_id: str, conversation_id: str, text: str) -> dict:
|
||||
def send_text(
|
||||
self,
|
||||
account_id: str,
|
||||
conversation_id: str,
|
||||
text: str,
|
||||
record_id: str,
|
||||
tenant_code: str = "default",
|
||||
) -> dict:
|
||||
client = self.registry.get(account_id)
|
||||
if client is None:
|
||||
return {"success": False, "error": f"account {account_id} not registered"}
|
||||
return self._fail(account_id, record_id, tenant_code, conversation_id, f"account {account_id} not registered")
|
||||
if client.state.online_status != OnlineStatus.ONLINE:
|
||||
return {"success": False, "error": "account not online"}
|
||||
return client.send_text(conversation_id, text)
|
||||
return self._fail(account_id, record_id, tenant_code, conversation_id, "account not online")
|
||||
if client.state.risk_level >= 80:
|
||||
return self._fail(
|
||||
account_id,
|
||||
record_id,
|
||||
tenant_code,
|
||||
conversation_id,
|
||||
"account risk level too high",
|
||||
error_code="RISK_CONTROL_BLOCKED",
|
||||
)
|
||||
|
||||
def send_image(self, account_id: str, conversation_id: str, image_url: str) -> dict:
|
||||
# Placeholder for image sending via pywechat.
|
||||
message_id = f"mock-msg-{uuid.uuid4().hex[:16]}"
|
||||
channel_result = client.send_text(conversation_id, text)
|
||||
self._emit_send_result(account_id, record_id, tenant_code, conversation_id, True, message_id, channel_result)
|
||||
return {"accepted": True, "message_id": message_id}
|
||||
|
||||
def send_image(
|
||||
self,
|
||||
account_id: str,
|
||||
conversation_id: str,
|
||||
image_url: str,
|
||||
record_id: str,
|
||||
tenant_code: str = "default",
|
||||
) -> dict:
|
||||
client = self.registry.get(account_id)
|
||||
if client is None:
|
||||
return {"success": False, "error": f"account {account_id} not registered"}
|
||||
return self._fail(account_id, record_id, tenant_code, conversation_id, f"account {account_id} not registered")
|
||||
if client.state.online_status != OnlineStatus.ONLINE:
|
||||
return {"success": False, "error": "account not online"}
|
||||
return {
|
||||
"success": True,
|
||||
"message_id": f"mock-img-{image_url.split('/')[-1]}",
|
||||
"conversation_id": conversation_id,
|
||||
"type": "image",
|
||||
}
|
||||
return self._fail(account_id, record_id, tenant_code, conversation_id, "account not online")
|
||||
|
||||
message_id = f"mock-img-{image_url.split('/')[-1]}"
|
||||
self._emit_send_result(
|
||||
account_id,
|
||||
record_id,
|
||||
tenant_code,
|
||||
conversation_id,
|
||||
True,
|
||||
message_id,
|
||||
{"image_url": image_url},
|
||||
)
|
||||
return {"accepted": True, "message_id": message_id}
|
||||
|
||||
def _fail(
|
||||
self,
|
||||
account_id: str,
|
||||
record_id: str,
|
||||
tenant_code: str,
|
||||
conversation_id: str,
|
||||
error: str,
|
||||
error_code: str = "SEND_FAILED",
|
||||
) -> dict:
|
||||
self._emit_send_result(
|
||||
account_id,
|
||||
record_id,
|
||||
tenant_code,
|
||||
conversation_id,
|
||||
False,
|
||||
None,
|
||||
{"error": error, "error_code": error_code},
|
||||
)
|
||||
return {"accepted": False, "error": error}
|
||||
|
||||
def _emit_send_result(
|
||||
self,
|
||||
account_id: str,
|
||||
record_id: str,
|
||||
tenant_code: str,
|
||||
conversation_id: str,
|
||||
success: bool,
|
||||
message_id: Optional[str],
|
||||
channel_result: dict,
|
||||
) -> None:
|
||||
event = OutboundEvent(
|
||||
event_type=EventType.SEND_RESULT,
|
||||
account_id=account_id,
|
||||
tenant_code=tenant_code,
|
||||
data={
|
||||
"record_id": record_id,
|
||||
"conversation_id": conversation_id,
|
||||
"success": success,
|
||||
"message_id": message_id,
|
||||
"channel_result": channel_result,
|
||||
"error": channel_result.get("error"),
|
||||
},
|
||||
)
|
||||
self.store.save(event)
|
||||
|
||||
|
||||
send_service = SendService(registry)
|
||||
send_service = SendService(registry, event_store)
|
||||
|
||||
Reference in New Issue
Block a user