from __future__ import annotations from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Count, Max, Q from django.shortcuts import render from django.views import View from core.models import ( ContactAvailabilityEvent, ContactAvailabilitySettings, ) def _to_int(value, default=0): try: return int(value) except Exception: return int(default) def _to_bool(value, default=False): if value is None: return bool(default) text = str(value).strip().lower() if text in {"1", "true", "yes", "on", "y"}: return True if text in {"0", "false", "no", "off", "n"}: return False return bool(default) class AvailabilitySettingsPage(LoginRequiredMixin, View): template_name = "pages/availability-settings.html" def _settings(self, request): row, _ = ContactAvailabilitySettings.objects.get_or_create(user=request.user) return row def post(self, request): row = self._settings(request) row.enabled = _to_bool(request.POST.get("enabled"), row.enabled) row.show_in_chat = _to_bool(request.POST.get("show_in_chat"), row.show_in_chat) row.show_in_groups = _to_bool( request.POST.get("show_in_groups"), row.show_in_groups ) row.inference_enabled = _to_bool( request.POST.get("inference_enabled"), row.inference_enabled ) row.retention_days = max(1, _to_int(request.POST.get("retention_days"), 90)) row.fade_threshold_seconds = max( 30, _to_int(request.POST.get("fade_threshold_seconds"), 900) ) row.save( update_fields=[ "enabled", "show_in_chat", "show_in_groups", "inference_enabled", "retention_days", "fade_threshold_seconds", "updated_at", ] ) return self.get(request) def get(self, request): settings_row = self._settings(request) contact_stats = list( ContactAvailabilityEvent.objects.filter( user=request.user, person__isnull=False ) .values("person_id", "person__name", "service") .annotate( total_events=Count("id"), available_events=Count("id", filter=Q(availability_state="available")), fading_events=Count("id", filter=Q(availability_state="fading")), unavailable_events=Count( "id", filter=Q(availability_state="unavailable") ), unknown_events=Count("id", filter=Q(availability_state="unknown")), native_presence_events=Count( "id", filter=Q(source_kind="native_presence") ), read_receipt_events=Count("id", filter=Q(source_kind="read_receipt")), typing_events=Count( "id", filter=Q(source_kind="typing_start") | Q(source_kind="typing_stop"), ), message_activity_events=Count( "id", filter=Q(source_kind="message_in") | Q(source_kind="message_out"), ), inferred_timeout_events=Count( "id", filter=Q(source_kind="inferred_timeout") ), last_event_ts=Max("ts"), ) .order_by("-total_events", "person__name", "service") ) context = { "settings_row": settings_row, "contact_stats": contact_stats, } return render(request, self.template_name, context)