From 3671f2a0ddf9e1ee6cade6711401386f520d5b1e Mon Sep 17 00:00:00 2001 From: lebaudantoine Date: Fri, 11 Apr 2025 13:50:30 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F(backend)=20encapsulate=20rec?= =?UTF-8?q?ording=20key=20and=20extension=20logic=20as=20properties?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move logic for calculating recording keys and file extensions into proper properties on recording objects. Simplifies access to Minio storage keys and clearly documents expected behavior when saving recordings across the application. --- src/backend/core/models.py | 17 +++++++++ .../core/recording/event/notification.py | 4 +-- .../core/tests/test_models_recording.py | 36 ++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/backend/core/models.py b/src/backend/core/models.py index 11baa28a..f5199ec1 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -18,6 +18,8 @@ from django.utils.translation import gettext_lazy as _ from timezone_field import TimeZoneField +from .recording.enums import FileExtension + logger = getLogger(__name__) @@ -576,6 +578,21 @@ class Recording(BaseModel): RecordingStatusChoices.STOPPED, } + @property + def extension(self): + """Get recording extension based on its mode.""" + extensions = { + RecordingModeChoices.TRANSCRIPT: FileExtension.OGG.value, + RecordingModeChoices.SCREEN_RECORDING: FileExtension.MP4.value, + } + return extensions.get(self.mode, FileExtension.MP4.value) + + @property + def key(self): + """Generate the file key based on recording mode.""" + + return f"{settings.RECORDING_OUTPUT_FOLDER}/{self.id}.{self.extension}" + class RecordingAccess(BaseAccess): """Relation model to give access to a recording for a user or a team with a role.""" diff --git a/src/backend/core/recording/event/notification.py b/src/backend/core/recording/event/notification.py index 32d2d030..617ea06d 100644 --- a/src/backend/core/recording/event/notification.py +++ b/src/backend/core/recording/event/notification.py @@ -112,10 +112,8 @@ class NotificationService: logger.error("No owner found for recording %s", recording.id) return False - key = f"{settings.RECORDING_OUTPUT_FOLDER}/{recording.id}.ogg" - payload = { - "filename": key, + "filename": recording.key, "email": owner_access.user.email, "sub": owner_access.user.sub, } diff --git a/src/backend/core/tests/test_models_recording.py b/src/backend/core/tests/test_models_recording.py index 065694e4..abcefede 100644 --- a/src/backend/core/tests/test_models_recording.py +++ b/src/backend/core/tests/test_models_recording.py @@ -12,7 +12,8 @@ from core.factories import ( UserFactory, UserRecordingAccessFactory, ) -from core.models import Recording, RecordingStatusChoices +from core.models import Recording, RecordingModeChoices, RecordingStatusChoices +from core.recording.enums import FileExtension pytestmark = pytest.mark.django_db @@ -216,3 +217,36 @@ def test_models_recording_worker_id_very_long(): too_long_id = "w" * 256 with pytest.raises(ValidationError): RecordingFactory(worker_id=too_long_id) + + +# Test key property method + + +def test_models_recording_key_for_transcript(settings): + """Test key property returns correct path for transcript mode.""" + + settings.RECORDING_OUTPUT_FOLDER = "/custom/path" + + recording = RecordingFactory(mode=RecordingModeChoices.TRANSCRIPT) + expected_path = f"/custom/path/{recording.id}.{FileExtension.OGG.value}" + assert recording.key == expected_path + + +def test_models_recording_key_for_screen_recording(settings): + """Test key property returns correct path for screen recording mode.""" + settings.RECORDING_OUTPUT_FOLDER = "/custom/path" + + recording = RecordingFactory(mode=RecordingModeChoices.SCREEN_RECORDING) + expected_path = f"/custom/path/{recording.id}.{FileExtension.MP4.value}" + assert recording.key == expected_path + + +def test_models_recording_key_for_unknown_mode(settings): + """Test key property uses default extension for unknown mode.""" + + settings.RECORDING_OUTPUT_FOLDER = "/custom/path" + recording = RecordingFactory() + # Directly set an invalid mode (bypassing validation) + recording.mode = "unknown_mode" + expected_path = f"/custom/path/{recording.id}.{FileExtension.MP4.value}" + assert recording.key == expected_path