import re from asgiref.sync import async_to_sync from django.contrib.auth.mixins import LoginRequiredMixin from django.db import transaction from django.http import HttpResponse from django.utils import timezone as dj_timezone from mixins.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate from rest_framework import status from rest_framework.views import APIView from core.forms import QueueForm from core.models import Message, QueuedMessage from core.util import logs log = logs.get_logger("queue") _INLINE_TARGET_RE = re.compile(r"^#queue-inline-editor-[A-Za-z0-9_-]+$") class AcceptMessageAPI(LoginRequiredMixin, APIView): def get(self, request, message_id): try: queued = QueuedMessage.objects.select_related( "session", "session__identifier", "session__user", ).get( user=request.user, id=message_id, ) except QueuedMessage.DoesNotExist: return HttpResponse(status=status.HTTP_404_NOT_FOUND) ts = async_to_sync(queued.session.identifier.send)( queued.text or "", [], ) if not ts: log.error("Queue accept send failed for queued message %s", queued.id) return HttpResponse(status=status.HTTP_502_BAD_GATEWAY) sent_ts = ( int(ts) if (ts is not None and not isinstance(ts, bool)) else int(dj_timezone.now().timestamp() * 1000) ) with transaction.atomic(): Message.objects.create( user=queued.session.user, session=queued.session, custom_author=queued.custom_author or "BOT", text=queued.text, ts=sent_ts, delivered_ts=sent_ts, read_source_service=queued.session.identifier.service, ) queued.delete() return HttpResponse(status=status.HTTP_200_OK) class RejectMessageAPI(LoginRequiredMixin, APIView): def get(self, request, message_id): try: message = QueuedMessage.objects.get( user=self.request.user, id=message_id, ) except QueuedMessage.DoesNotExist: return HttpResponse(status=status.HTTP_404_NOT_FOUND) message.delete() return HttpResponse(status=status.HTTP_200_OK) class QueueList(LoginRequiredMixin, ObjectList): list_template = "partials/queue-list.html" model = QueuedMessage page_title = "Queue" list_url_name = "queues" list_url_args = ["type"] submit_url_name = "queue_create" class QueueCreate(LoginRequiredMixin, ObjectCreate): model = QueuedMessage form_class = QueueForm submit_url_name = "queue_create" class QueueUpdate(LoginRequiredMixin, ObjectUpdate): model = QueuedMessage form_class = QueueForm window_content = "mixins/window-content/queue-form-inline.html" submit_url_name = "queue_update" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) raw_target = str(self.request.GET.get("hx_target") or "").strip() if _INLINE_TARGET_RE.fullmatch(raw_target): context["submit_target"] = raw_target else: context["submit_target"] = "#modals-here" context["is_inline_edit"] = context["submit_target"].startswith( "#queue-inline-editor-" ) return context class QueueDelete(LoginRequiredMixin, ObjectDelete): model = QueuedMessage