Increase platform abstraction cohesion
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
from asgiref.sync import sync_to_async
|
||||
from django.conf import settings
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from core.events.ledger import append_event
|
||||
@@ -628,6 +629,277 @@ async def apply_reaction(
|
||||
return target
|
||||
|
||||
|
||||
async def _resolve_message_target(
|
||||
user,
|
||||
identifier,
|
||||
*,
|
||||
target_message_id="",
|
||||
target_ts=0,
|
||||
target_author="",
|
||||
):
|
||||
queryset = Message.objects.filter(
|
||||
user=user,
|
||||
session__identifier=identifier,
|
||||
).select_related("session")
|
||||
|
||||
target = None
|
||||
match_strategy = "none"
|
||||
target_author_value = str(target_author or "").strip()
|
||||
target_uuid = str(target_message_id or "").strip()
|
||||
if target_uuid:
|
||||
is_uuid = True
|
||||
try:
|
||||
uuid.UUID(str(target_uuid))
|
||||
except Exception:
|
||||
is_uuid = False
|
||||
if is_uuid:
|
||||
target = await sync_to_async(
|
||||
lambda: queryset.filter(id=target_uuid).order_by("-ts").first()
|
||||
)()
|
||||
if target is not None:
|
||||
match_strategy = "local_message_id"
|
||||
if target is None:
|
||||
target = await sync_to_async(
|
||||
lambda: queryset.filter(source_message_id=target_uuid)
|
||||
.order_by("-ts")
|
||||
.first()
|
||||
)()
|
||||
if target is not None:
|
||||
match_strategy = "source_message_id"
|
||||
|
||||
if target is None:
|
||||
try:
|
||||
ts_value = int(target_ts or 0)
|
||||
except Exception:
|
||||
ts_value = 0
|
||||
if ts_value > 0:
|
||||
exact_candidates = await sync_to_async(list)(
|
||||
queryset.filter(source_message_id=str(ts_value)).order_by("-ts")[:20]
|
||||
)
|
||||
if target_author_value and exact_candidates:
|
||||
filtered = [
|
||||
row
|
||||
for row in exact_candidates
|
||||
if str(row.sender_uuid or "").strip() == target_author_value
|
||||
]
|
||||
if filtered:
|
||||
exact_candidates = filtered
|
||||
if exact_candidates:
|
||||
target = exact_candidates[0]
|
||||
match_strategy = "exact_source_message_id_ts"
|
||||
|
||||
if target is None and ts_value > 0:
|
||||
strict_ts_rows = await sync_to_async(list)(
|
||||
queryset.filter(ts=ts_value).order_by("-id")[:20]
|
||||
)
|
||||
if target_author_value and strict_ts_rows:
|
||||
filtered = [
|
||||
row
|
||||
for row in strict_ts_rows
|
||||
if str(row.sender_uuid or "").strip() == target_author_value
|
||||
]
|
||||
if filtered:
|
||||
strict_ts_rows = filtered
|
||||
if strict_ts_rows:
|
||||
target = strict_ts_rows[0]
|
||||
match_strategy = "strict_ts_match"
|
||||
|
||||
if target is None and ts_value > 0:
|
||||
lower = ts_value - 10_000
|
||||
upper = ts_value + 10_000
|
||||
window_rows = await sync_to_async(list)(
|
||||
queryset.filter(ts__gte=lower, ts__lte=upper).order_by("ts")[:200]
|
||||
)
|
||||
if target_author_value and window_rows:
|
||||
author_rows = [
|
||||
row
|
||||
for row in window_rows
|
||||
if str(row.sender_uuid or "").strip() == target_author_value
|
||||
]
|
||||
if author_rows:
|
||||
window_rows = author_rows
|
||||
if window_rows:
|
||||
target = min(
|
||||
window_rows,
|
||||
key=lambda row: (
|
||||
abs(int(row.ts or 0) - ts_value),
|
||||
-int(row.ts or 0),
|
||||
),
|
||||
)
|
||||
match_strategy = "nearest_ts_window"
|
||||
|
||||
return target, match_strategy
|
||||
|
||||
|
||||
async def apply_message_edit(
|
||||
user,
|
||||
identifier,
|
||||
*,
|
||||
target_message_id="",
|
||||
target_ts=0,
|
||||
new_text="",
|
||||
source_service="",
|
||||
actor="",
|
||||
payload=None,
|
||||
trace_id="",
|
||||
target_author="",
|
||||
):
|
||||
target, match_strategy = await _resolve_message_target(
|
||||
user,
|
||||
identifier,
|
||||
target_message_id=target_message_id,
|
||||
target_ts=target_ts,
|
||||
target_author=target_author,
|
||||
)
|
||||
if target is None:
|
||||
log.warning(
|
||||
"edit-sync history-apply miss user=%s person_identifier=%s target_message_id=%s target_ts=%s",
|
||||
getattr(user, "id", "-"),
|
||||
getattr(identifier, "id", "-"),
|
||||
str(target_message_id or "") or "-",
|
||||
int(target_ts or 0),
|
||||
)
|
||||
return None
|
||||
|
||||
old_text = str(target.text or "")
|
||||
updated_text = str(new_text or "")
|
||||
event_ts = int(target_ts or target.ts or int(time.time() * 1000))
|
||||
receipt_payload = dict(target.receipt_payload or {})
|
||||
edit_history = list(receipt_payload.get("edit_history") or [])
|
||||
edit_history.append(
|
||||
{
|
||||
"edited_ts": int(event_ts),
|
||||
"source_service": str(source_service or "").strip().lower(),
|
||||
"actor": str(actor or "").strip(),
|
||||
"previous_text": old_text,
|
||||
"new_text": updated_text,
|
||||
"match_strategy": str(match_strategy or ""),
|
||||
"payload": dict(payload or {}),
|
||||
}
|
||||
)
|
||||
if len(edit_history) > 200:
|
||||
edit_history = edit_history[-200:]
|
||||
receipt_payload["edit_history"] = edit_history
|
||||
receipt_payload["last_edited_ts"] = int(event_ts)
|
||||
receipt_payload["edit_count"] = len(edit_history)
|
||||
target.receipt_payload = receipt_payload
|
||||
|
||||
update_fields = ["receipt_payload"]
|
||||
if old_text != updated_text:
|
||||
target.text = updated_text
|
||||
update_fields.append("text")
|
||||
await sync_to_async(target.save)(update_fields=update_fields)
|
||||
try:
|
||||
await append_event(
|
||||
user=user,
|
||||
session=target.session,
|
||||
ts=int(event_ts),
|
||||
event_type="message_edited",
|
||||
direction="system",
|
||||
actor_identifier=str(actor or ""),
|
||||
origin_transport=str(source_service or ""),
|
||||
origin_message_id=str(target.source_message_id or target.id),
|
||||
origin_chat_id=str(target.source_chat_id or ""),
|
||||
payload={
|
||||
"message_id": str(target.id),
|
||||
"target_message_id": str(target_message_id or target.id),
|
||||
"target_ts": int(target_ts or target.ts or 0),
|
||||
"old_text": old_text,
|
||||
"new_text": updated_text,
|
||||
"source_service": str(source_service or "").strip().lower(),
|
||||
"actor": str(actor or ""),
|
||||
"match_strategy": str(match_strategy or ""),
|
||||
},
|
||||
raw_payload=dict(payload or {}),
|
||||
trace_id=ensure_trace_id(trace_id, payload or {}),
|
||||
)
|
||||
except Exception as exc:
|
||||
log.warning(
|
||||
"Event ledger append failed for message edit message=%s: %s",
|
||||
target.id,
|
||||
exc,
|
||||
)
|
||||
return target
|
||||
|
||||
|
||||
async def apply_message_delete(
|
||||
user,
|
||||
identifier,
|
||||
*,
|
||||
target_message_id="",
|
||||
target_ts=0,
|
||||
source_service="",
|
||||
actor="",
|
||||
payload=None,
|
||||
trace_id="",
|
||||
target_author="",
|
||||
):
|
||||
target, match_strategy = await _resolve_message_target(
|
||||
user,
|
||||
identifier,
|
||||
target_message_id=target_message_id,
|
||||
target_ts=target_ts,
|
||||
target_author=target_author,
|
||||
)
|
||||
if target is None:
|
||||
log.warning(
|
||||
"delete-sync history-apply miss user=%s person_identifier=%s target_message_id=%s target_ts=%s",
|
||||
getattr(user, "id", "-"),
|
||||
getattr(identifier, "id", "-"),
|
||||
str(target_message_id or "") or "-",
|
||||
int(target_ts or 0),
|
||||
)
|
||||
return None
|
||||
|
||||
event_ts = int(target_ts or target.ts or int(time.time() * 1000))
|
||||
deleted_row = {
|
||||
"deleted_ts": int(event_ts),
|
||||
"source_service": str(source_service or "").strip().lower(),
|
||||
"actor": str(actor or "").strip(),
|
||||
"match_strategy": str(match_strategy or ""),
|
||||
"payload": dict(payload or {}),
|
||||
}
|
||||
receipt_payload = dict(target.receipt_payload or {})
|
||||
delete_events = list(receipt_payload.get("delete_events") or [])
|
||||
delete_events.append(dict(deleted_row))
|
||||
if len(delete_events) > 200:
|
||||
delete_events = delete_events[-200:]
|
||||
receipt_payload["delete_events"] = delete_events
|
||||
receipt_payload["deleted"] = deleted_row
|
||||
receipt_payload["is_deleted"] = True
|
||||
target.receipt_payload = receipt_payload
|
||||
await sync_to_async(target.save)(update_fields=["receipt_payload"])
|
||||
try:
|
||||
await append_event(
|
||||
user=user,
|
||||
session=target.session,
|
||||
ts=int(event_ts),
|
||||
event_type="message_deleted",
|
||||
direction="system",
|
||||
actor_identifier=str(actor or ""),
|
||||
origin_transport=str(source_service or ""),
|
||||
origin_message_id=str(target.source_message_id or target.id),
|
||||
origin_chat_id=str(target.source_chat_id or ""),
|
||||
payload={
|
||||
"message_id": str(target.id),
|
||||
"target_message_id": str(target_message_id or target.id),
|
||||
"target_ts": int(target_ts or target.ts or 0),
|
||||
"source_service": str(source_service or "").strip().lower(),
|
||||
"actor": str(actor or ""),
|
||||
"match_strategy": str(match_strategy or ""),
|
||||
},
|
||||
raw_payload=dict(payload or {}),
|
||||
trace_id=ensure_trace_id(trace_id, payload or {}),
|
||||
)
|
||||
except Exception as exc:
|
||||
log.warning(
|
||||
"Event ledger append failed for message delete message=%s: %s",
|
||||
target.id,
|
||||
exc,
|
||||
)
|
||||
return target
|
||||
|
||||
|
||||
def _iter_bridge_refs(receipt_payload, source_service):
|
||||
payload = dict(receipt_payload or {})
|
||||
refs = payload.get("bridge_refs") or {}
|
||||
|
||||
Reference in New Issue
Block a user