From cbecf00166f8bf9b1dd34708de450d30258db5e0 Mon Sep 17 00:00:00 2001 From: mohsentaba Date: Thu, 11 Jun 2026 11:16:12 +0330 Subject: [PATCH] check online classes end status --- apps/course/views/admin.py | 77 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/apps/course/views/admin.py b/apps/course/views/admin.py index 7d2a174..5e3ca52 100644 --- a/apps/course/views/admin.py +++ b/apps/course/views/admin.py @@ -1,4 +1,7 @@ +import logging + from django.db.models import Q +from django.utils import timezone from rest_framework import viewsets from rest_framework.permissions import IsAuthenticated from rest_framework.authentication import TokenAuthentication @@ -7,6 +10,7 @@ from rest_framework.response import Response from rest_framework.exceptions import PermissionDenied from utils.pagination import StandardResultsSetPagination from apps.account.permissions import IsPanelUser, IsSuperAdminOrReadOnlyForProfessor +from apps.course.services.plugnmeet import PlugNMeetClient, PlugNMeetError from apps.course.models import ( Course, CourseCategory, @@ -36,6 +40,8 @@ from apps.course.serializers.admin import ( AdminLiveSessionDetailSerializer ) +logger = logging.getLogger(__name__) + def is_professor(request): return getattr(request.user, 'user_type', None) == 'professor' @@ -436,3 +442,74 @@ class AdminLiveSessionViewSet(viewsets.ModelViewSet): queryset = queryset.filter(ended_at__lte=ended_before) return queryset.order_by('-started_at') + + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + page = self.paginate_queryset(queryset) + + if page is not None: + self._sync_page_live_sessions(page) + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + sessions = list(queryset) + self._sync_page_live_sessions(sessions) + serializer = self.get_serializer(sessions, many=True) + return Response(serializer.data) + + def _sync_page_live_sessions(self, sessions): + for session in sessions: + if session.ended_at or not session.room_id: + continue + + if self._is_room_still_active(session.room_id): + continue + + now = timezone.now() + session.ended_at = now + session.save(update_fields=['ended_at', 'updated_at']) + + LiveSessionUser.objects.filter( + session=session, + is_online=True, + ).update(is_online=False, exited_at=now, updated_at=now) + + logger.info( + f"[Admin Live Sessions] Auto-closed stale session - session_id={session.id} room_id={session.room_id}" + ) + + @staticmethod + def _is_room_still_active(room_id: str) -> bool: + try: + client = PlugNMeetClient() + response = client.is_room_active(room_id) + is_active_raw = response.get('isActive', False) + is_active = ( + is_active_raw + if isinstance(is_active_raw, bool) + else str(is_active_raw).lower() == 'true' + ) + response_msg = response.get('msg', '') + response_status = response.get('status', False) + + if ( + response_status + and 'active' in response_msg.lower() + and 'not' not in response_msg.lower() + ): + return True + + return is_active + except PlugNMeetError as e: + error_msg = str(e).lower() + if 'not found' in error_msg or 'does not exist' in error_msg: + return False + logger.warning( + f"[Admin Live Sessions] PlugNMeet API error while checking room {room_id}: {e}" + ) + return False + except Exception as e: + logger.warning( + f"[Admin Live Sessions] Unexpected error while checking room {room_id}: {type(e).__name__}: {e}" + ) + return False