Fix Signal messages and replies

This commit is contained in:
2026-03-03 15:51:58 +00:00
parent 56c620473f
commit d6bd56dace
31 changed files with 3317 additions and 668 deletions

View File

@@ -23,6 +23,7 @@ from core.models import (
TaskProviderConfig,
PersonIdentifier,
PlatformChatLink,
Chat,
)
from core.tasks.providers.mock import get_provider
@@ -138,6 +139,25 @@ def _settings_redirect(request):
return redirect("tasks_settings")
def _ensure_default_completion_patterns(user) -> None:
defaults = ("done", "completed", "fixed")
existing = set(
str(row or "").strip().lower()
for row in TaskCompletionPattern.objects.filter(user=user).values_list("phrase", flat=True)
)
next_pos = TaskCompletionPattern.objects.filter(user=user).count()
for phrase in defaults:
if phrase in existing:
continue
TaskCompletionPattern.objects.create(
user=user,
phrase=phrase,
enabled=True,
position=next_pos,
)
next_pos += 1
def _service_label(service: str) -> str:
key = str(service or "").strip().lower()
labels = {
@@ -158,9 +178,52 @@ def _resolve_channel_display(user, service: str, identifier: str) -> dict:
if bare_identifier and bare_identifier not in variants:
variants.append(bare_identifier)
if service_key == "whatsapp":
direct_identifier = (
raw_identifier if raw_identifier.endswith("@s.whatsapp.net") else ""
)
if direct_identifier and direct_identifier not in variants:
variants.append(direct_identifier)
if bare_identifier:
direct_bare = f"{bare_identifier}@s.whatsapp.net"
if direct_bare not in variants:
variants.append(direct_bare)
group_identifier = f"{bare_identifier}@g.us" if bare_identifier else ""
if group_identifier and group_identifier not in variants:
variants.append(group_identifier)
if service_key == "signal":
digits = "".join(ch for ch in raw_identifier if ch.isdigit())
if digits and digits not in variants:
variants.append(digits)
if digits:
plus = f"+{digits}"
if plus not in variants:
variants.append(plus)
if raw_identifier:
companion_numbers = list(
Chat.objects.filter(source_uuid=raw_identifier)
.exclude(source_number__isnull=True)
.exclude(source_number="")
.values_list("source_number", flat=True)[:200]
)
companion_uuids = list(
Chat.objects.filter(source_number=raw_identifier)
.exclude(source_uuid__isnull=True)
.exclude(source_uuid="")
.values_list("source_uuid", flat=True)[:200]
)
for candidate in companion_numbers + companion_uuids:
candidate_str = str(candidate or "").strip()
if not candidate_str:
continue
if candidate_str not in variants:
variants.append(candidate_str)
candidate_digits = "".join(ch for ch in candidate_str if ch.isdigit())
if candidate_digits and candidate_digits not in variants:
variants.append(candidate_digits)
if candidate_digits:
plus_variant = f"+{candidate_digits}"
if plus_variant not in variants:
variants.append(plus_variant)
group_link = None
if bare_identifier:
@@ -200,9 +263,6 @@ def _resolve_channel_display(user, service: str, identifier: str) -> dict:
str(group_link.chat_jid or "").strip()
or (f"{bare_identifier}@g.us" if bare_identifier else raw_identifier)
)
elif service_key == "whatsapp" and bare_identifier and not raw_identifier.endswith("@g.us"):
display_identifier = f"{bare_identifier}@g.us"
return {
"service_key": service_key,
"service_label": _service_label(service_key),
@@ -275,15 +335,18 @@ class TaskGroupDetail(LoginRequiredMixin, View):
def get(self, request, service, identifier):
channel = _resolve_channel_display(request.user, service, identifier)
variants = list(channel.get("variants") or [str(identifier or "").strip()])
service_keys = [channel["service_key"]]
if channel["service_key"] != "web":
service_keys.append("web")
mappings = ChatTaskSource.objects.filter(
user=request.user,
service=channel["service_key"],
service__in=service_keys,
channel_identifier__in=variants,
).select_related("project", "epic")
tasks = (
DerivedTask.objects.filter(
user=request.user,
source_service=channel["service_key"],
source_service__in=service_keys,
source_channel__in=variants,
)
.select_related("project", "epic")
@@ -330,6 +393,7 @@ class TaskSettings(LoginRequiredMixin, View):
def _context(self, request):
_apply_safe_defaults_for_user(request.user)
_ensure_default_completion_patterns(request.user)
prefill_service = str(request.GET.get("service") or "").strip().lower()
prefill_identifier = str(request.GET.get("identifier") or "").strip()
projects = list(TaskProject.objects.filter(user=request.user).order_by("name"))
@@ -446,6 +510,15 @@ class TaskSettings(LoginRequiredMixin, View):
source.save(update_fields=["settings", "updated_at"])
return _settings_redirect(request)
if action == "source_delete":
source = get_object_or_404(
ChatTaskSource,
id=request.POST.get("source_id"),
user=request.user,
)
source.delete()
return _settings_redirect(request)
if action == "pattern_create":
phrase = str(request.POST.get("phrase") or "").strip()
if phrase: