|
|
|
@ -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 |