uchill/backend/apps/video/signals.py

127 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Сигналы для видеоконференций.
"""
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} не найдена')