Implement workspace history reconciliation
This commit is contained in:
@@ -1025,7 +1025,18 @@ class SignalClient(ClientBase):
|
||||
text=text,
|
||||
attachments=attachments,
|
||||
metadata=metadata,
|
||||
detailed=True,
|
||||
)
|
||||
if isinstance(result, dict) and (not bool(result.get("ok"))):
|
||||
status_value = int(result.get("status") or 0)
|
||||
error_text = str(result.get("error") or "").strip()
|
||||
recipient_value = str(result.get("recipient") or recipient).strip()
|
||||
raise RuntimeError(
|
||||
"signal_send_failed"
|
||||
f" status={status_value or 'unknown'}"
|
||||
f" recipient={recipient_value or 'unknown'}"
|
||||
f" error={error_text or 'unknown'}"
|
||||
)
|
||||
if result is False or result is None:
|
||||
raise RuntimeError("signal_send_failed")
|
||||
transport.set_runtime_command_result(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import logging
|
||||
import re
|
||||
|
||||
import aiohttp
|
||||
import orjson
|
||||
@@ -9,6 +10,25 @@ from django.conf import settings
|
||||
from rest_framework import status
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
SIGNAL_UUID_PATTERN = re.compile(
|
||||
r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def normalize_signal_recipient(recipient: str) -> str:
|
||||
raw = str(recipient or "").strip()
|
||||
if not raw:
|
||||
return ""
|
||||
if SIGNAL_UUID_PATTERN.fullmatch(raw):
|
||||
return raw
|
||||
if raw.startswith("+"):
|
||||
digits = re.sub(r"[^0-9]", "", raw)
|
||||
return f"+{digits}" if digits else raw
|
||||
digits_only = re.sub(r"[^0-9]", "", raw)
|
||||
if digits_only and raw.isdigit():
|
||||
return f"+{digits_only}"
|
||||
return raw
|
||||
|
||||
|
||||
async def start_typing(uuid):
|
||||
@@ -73,7 +93,9 @@ async def download_and_encode_base64(file_url, filename, content_type, session=N
|
||||
return None
|
||||
|
||||
|
||||
async def send_message_raw(recipient_uuid, text=None, attachments=None, metadata=None):
|
||||
async def send_message_raw(
|
||||
recipient_uuid, text=None, attachments=None, metadata=None, detailed=False
|
||||
):
|
||||
"""
|
||||
Sends a message using the Signal REST API, ensuring attachment links are not included in the text body.
|
||||
|
||||
@@ -88,8 +110,9 @@ async def send_message_raw(recipient_uuid, text=None, attachments=None, metadata
|
||||
base = getattr(settings, "SIGNAL_HTTP_URL", "http://signal:8080").rstrip("/")
|
||||
url = f"{base}/v2/send"
|
||||
|
||||
normalized_recipient = normalize_signal_recipient(recipient_uuid)
|
||||
data = {
|
||||
"recipients": [recipient_uuid],
|
||||
"recipients": [normalized_recipient],
|
||||
"number": settings.SIGNAL_NUMBER,
|
||||
"base64_attachments": [],
|
||||
}
|
||||
@@ -168,8 +191,37 @@ async def send_message_raw(recipient_uuid, text=None, attachments=None, metadata
|
||||
ts = orjson.loads(response_text).get("timestamp", None)
|
||||
return ts if ts else False
|
||||
if index == len(payloads) - 1:
|
||||
log.warning(
|
||||
"Signal send failed status=%s recipient=%s body=%s",
|
||||
response_status,
|
||||
normalized_recipient,
|
||||
response_text[:300],
|
||||
)
|
||||
if detailed:
|
||||
return {
|
||||
"ok": False,
|
||||
"status": int(response_status),
|
||||
"error": str(response_text or "").strip()[:500],
|
||||
"recipient": normalized_recipient,
|
||||
}
|
||||
return False
|
||||
if response_status not in {status.HTTP_400_BAD_REQUEST, status.HTTP_422_UNPROCESSABLE_ENTITY}:
|
||||
if response_status not in {
|
||||
status.HTTP_400_BAD_REQUEST,
|
||||
status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||
}:
|
||||
log.warning(
|
||||
"Signal send failed early status=%s recipient=%s body=%s",
|
||||
response_status,
|
||||
normalized_recipient,
|
||||
response_text[:300],
|
||||
)
|
||||
if detailed:
|
||||
return {
|
||||
"ok": False,
|
||||
"status": int(response_status),
|
||||
"error": str(response_text or "").strip()[:500],
|
||||
"recipient": normalized_recipient,
|
||||
}
|
||||
return False
|
||||
log.warning(
|
||||
"signal send quote payload rejected (%s), trying fallback shape: %s",
|
||||
@@ -305,7 +357,7 @@ def send_message_raw_sync(recipient_uuid, text=None, attachments=None):
|
||||
base = getattr(settings, "SIGNAL_HTTP_URL", "http://signal:8080").rstrip("/")
|
||||
url = f"{base}/v2/send"
|
||||
data = {
|
||||
"recipients": [recipient_uuid],
|
||||
"recipients": [normalize_signal_recipient(recipient_uuid)],
|
||||
"number": settings.SIGNAL_NUMBER,
|
||||
"base64_attachments": [],
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user