Lightweight containerized prosody tooling + moved auth scripts + xmpp reconnect/auth stabilization
This commit is contained in:
122
core/tasks/chat_defaults.py
Normal file
122
core/tasks/chat_defaults.py
Normal file
@@ -0,0 +1,122 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from core.models import ChatTaskSource, TaskProject
|
||||
from core.tasks.codex_support import channel_variants
|
||||
|
||||
SAFE_TASK_FLAGS_DEFAULTS = {
|
||||
"derive_enabled": True,
|
||||
"match_mode": "strict",
|
||||
"require_prefix": True,
|
||||
"allowed_prefixes": ["task:", "todo:"],
|
||||
"completion_enabled": True,
|
||||
"ai_title_enabled": True,
|
||||
"announce_task_id": False,
|
||||
"min_chars": 3,
|
||||
}
|
||||
|
||||
|
||||
def normalize_channel_identifier(service: str, identifier: str) -> str:
|
||||
service_key = str(service or "").strip().lower()
|
||||
value = str(identifier or "").strip()
|
||||
if not value:
|
||||
return ""
|
||||
if service_key == "whatsapp":
|
||||
bare = value.split("@", 1)[0].strip()
|
||||
if not bare:
|
||||
return value
|
||||
if value.endswith("@s.whatsapp.net"):
|
||||
return f"{bare}@s.whatsapp.net"
|
||||
return f"{bare}@g.us"
|
||||
return value
|
||||
|
||||
|
||||
def resolve_message_scope(message) -> tuple[str, str]:
|
||||
source_service = str(getattr(message, "source_service", "") or "").strip().lower()
|
||||
source_channel = str(getattr(message, "source_chat_id", "") or "").strip()
|
||||
if source_service != "web":
|
||||
return source_service, source_channel
|
||||
identifier = getattr(getattr(message, "session", None), "identifier", None)
|
||||
fallback_service = str(getattr(identifier, "service", "") or "").strip().lower()
|
||||
fallback_identifier = str(getattr(identifier, "identifier", "") or "").strip()
|
||||
if fallback_service and fallback_identifier and fallback_service != "web":
|
||||
return fallback_service, fallback_identifier
|
||||
return source_service, source_channel
|
||||
|
||||
|
||||
def _project_name_candidate(service: str, channel_identifier: str, message=None) -> str:
|
||||
person_name = ""
|
||||
if message is not None:
|
||||
identifier = getattr(getattr(message, "session", None), "identifier", None)
|
||||
person = getattr(identifier, "person", None)
|
||||
person_name = str(getattr(person, "name", "") or "").strip()
|
||||
if person_name:
|
||||
return person_name[:255]
|
||||
raw = str(channel_identifier or "").strip()
|
||||
if str(service or "").strip().lower() == "whatsapp":
|
||||
raw = raw.split("@", 1)[0].strip()
|
||||
cleaned = re.sub(r"\s+", " ", raw).strip()
|
||||
if not cleaned:
|
||||
cleaned = "Chat"
|
||||
return f"Chat: {cleaned}"[:255]
|
||||
|
||||
|
||||
def _ensure_unique_project_name(user, base_name: str) -> str:
|
||||
base = str(base_name or "").strip() or "Chat"
|
||||
if not TaskProject.objects.filter(user=user, name=base).exists():
|
||||
return base
|
||||
idx = 2
|
||||
while idx < 10000:
|
||||
candidate = f"{base} ({idx})"[:255]
|
||||
if not TaskProject.objects.filter(user=user, name=candidate).exists():
|
||||
return candidate
|
||||
idx += 1
|
||||
return f"{base} ({str(user.id)[:8]})"[:255]
|
||||
|
||||
|
||||
def ensure_default_source_for_chat(
|
||||
*,
|
||||
user,
|
||||
service: str,
|
||||
channel_identifier: str,
|
||||
message=None,
|
||||
):
|
||||
service_key = str(service or "").strip().lower()
|
||||
normalized_identifier = normalize_channel_identifier(service_key, channel_identifier)
|
||||
variants = channel_variants(service_key, normalized_identifier)
|
||||
if not service_key or not variants:
|
||||
return None
|
||||
existing = (
|
||||
ChatTaskSource.objects.filter(
|
||||
user=user,
|
||||
service=service_key,
|
||||
channel_identifier__in=variants,
|
||||
)
|
||||
.select_related("project", "epic")
|
||||
.order_by("-enabled", "-updated_at", "-created_at")
|
||||
.first()
|
||||
)
|
||||
if existing is not None:
|
||||
if not existing.enabled:
|
||||
existing.enabled = True
|
||||
existing.save(update_fields=["enabled", "updated_at"])
|
||||
return existing
|
||||
project_name = _ensure_unique_project_name(
|
||||
user,
|
||||
_project_name_candidate(service_key, normalized_identifier, message=message),
|
||||
)
|
||||
project = TaskProject.objects.create(
|
||||
user=user,
|
||||
name=project_name,
|
||||
settings=dict(SAFE_TASK_FLAGS_DEFAULTS),
|
||||
)
|
||||
return ChatTaskSource.objects.create(
|
||||
user=user,
|
||||
service=service_key,
|
||||
channel_identifier=normalized_identifier,
|
||||
project=project,
|
||||
epic=None,
|
||||
enabled=True,
|
||||
settings=dict(SAFE_TASK_FLAGS_DEFAULTS),
|
||||
)
|
||||
Reference in New Issue
Block a user