""" Сигналы для видеоконференций. """ import logging from django.db.models.signals import post_save from django.dispatch import receiver from django.utils import timezone from apps.schedule.models import Lesson from .models import VideoRoom logger = logging.getLogger(__name__) @receiver(post_save, sender=Lesson) def create_video_room_for_lesson(sender, instance, created, **kwargs): """ Автоматическое создание видеокомнаты и ссылки на встречу при создании занятия. """ # Создаем комнату для всех занятий (не только confirmed) if created or not hasattr(instance, 'video_room'): try: # Проверяем, есть ли уже комната try: video_room = instance.video_room except VideoRoom.DoesNotExist: video_room = None if not video_room: video_room = VideoRoom.objects.create( lesson=instance, mentor=instance.mentor, client=instance.client, is_recording=True, # По умолчанию включаем запись max_participants=2 ) logger.info(f'Создана видеокомната {video_room.room_id} для занятия {instance.id}') # Создаем или обновляем meeting_url на основе видеокомнаты (LiveKit) from django.conf import settings if not instance.meeting_url: # Используем LiveKit вместо старого video room # ВАЖНО: включаем lesson_id для синхронизации доски между пользователями meeting_url = f'{settings.FRONTEND_URL}/livekit/{video_room.room_id}?lesson_id={instance.id}' instance.meeting_url = meeting_url # Сохраняем без вызова сигналов, чтобы избежать рекурсии Lesson.objects.filter(id=instance.id).update(meeting_url=meeting_url) logger.info(f'Создана ссылка на LiveKit встречу для занятия {instance.id}: {meeting_url}') # Планируем автоматическое удаление видеокомнаты через 10 минут после окончания занятия if instance.end_time: from .tasks import schedule_video_room_deletion schedule_video_room_deletion.delay(instance.id) logger.info(f'Запланировано автоматическое удаление видеокомнаты для занятия {instance.id}') # Отправляем уведомления о создании комнаты (только при создании) if created: from apps.notifications.services import NotificationService meeting_link = f'/video/rooms/{video_room.room_id}/join/' # Уведомление ментору NotificationService.send_notification( user=instance.mentor, notification_type='video_room_created', message=f'Создана видеокомната для занятия "{instance.title}"', link=meeting_link ) # Уведомление клиенту (если есть) if instance.client: try: client_user = instance.client.user if hasattr(instance.client, 'user') else None if client_user: NotificationService.send_notification( user=client_user, notification_type='video_room_created', message=f'Создана видеокомната для занятия "{instance.title}"', link=meeting_link ) except Exception as e: logger.warning(f'Не удалось отправить уведомление клиенту для занятия {instance.id}: {str(e)}') except Exception as e: logger.error(f'Ошибка создания видеокомнаты для занятия {instance.id}: {str(e)}') @receiver(post_save, sender=VideoRoom) def handle_video_room_status_change(sender, instance, created, **kwargs): """ Обработка изменения статуса видеокомнаты. """ if not created: # Если комната только что завершилась if instance.status == 'ended' and instance.ended_at: # Обновляем статус связанного занятия, если оно еще не завершено try: lesson = instance.lesson if lesson.status in ['scheduled', 'in_progress']: lesson.status = 'completed' lesson.completed_at = timezone.now() lesson.save(update_fields=['status', 'completed_at']) logger.info(f'Статус занятия {lesson.id} обновлен на "completed" после завершения видеокомнаты') except Exception as e: logger.error(f'Ошибка обновления статуса занятия для видеокомнаты {instance.room_id}: {str(e)}') # Генерируем лог звонка from .tasks import generate_call_log generate_call_log.delay(instance.id) logger.info(f'Комната {instance.room_id} завершена, запущена генерация лога') # Если есть запись, начинаем обработку if instance.is_recording: from .models import ScreenRecording # Проверяем есть ли запись try: recording = ScreenRecording.objects.get(room=instance) if recording.status == 'processing': from .tasks import process_recording process_recording.delay(recording.id) logger.info(f'Запущена обработка записи {recording.id}') except ScreenRecording.DoesNotExist: logger.warning(f'Запись для комнаты {instance.room_id} не найдена')