updated tubesync type directory path
This commit is contained in:
1 parent
40e48c9317
commit
0fafca037c
4 files changed
+121
-3
No files matched your search
@@ -134,3 +134,6 @@ dmypy.json
|
|||||||
|
|
||||||
Pipfile.lock
|
Pipfile.lock
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
|
|
||||||
|
# Ignore Jetbrains IDE files
|
||||||
|
.idea/
|
||||||
@@ -376,7 +376,21 @@ useful if you are manually installing TubeSync in some other environment. These
|
|||||||
| HTTP_PASS | Sets the password for HTTP basic authentication | some-secure-password |
|
| HTTP_PASS | Sets the password for HTTP basic authentication | some-secure-password |
|
||||||
| DATABASE_CONNECTION | Optional external database connection details | mysql://user:pass@host:port/database |
|
| DATABASE_CONNECTION | Optional external database connection details | mysql://user:pass@host:port/database |
|
||||||
| VIDEO_HEIGHT_CUTOFF | Smallest video height in pixels permitted to download | 240 |
|
| VIDEO_HEIGHT_CUTOFF | Smallest video height in pixels permitted to download | 240 |
|
||||||
|
| TUBESYNC_DIRECTORY_MODE | Controls how downloaded files are organized. | default |
|
||||||
|
|
||||||
|
# TubeSync Directory Mode
|
||||||
|
|
||||||
|
Controls how downloaded files are organized.
|
||||||
|
|
||||||
|
Values:
|
||||||
|
- default: Audio files go to `audio`, video files to `video`.
|
||||||
|
- flat: All files are placed in the root of DOWNLOAD_DIR.
|
||||||
|
- custom:<audio_prefix>,<video_prefix>: Allows custom prefixes for audio and video directories under DOWNLOAD_DIR.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
TUBESYNC_DIRECTORY_MODE=custom:music,shows
|
||||||
|
```
|
||||||
|
|
||||||
# Manual, non-containerised, installation
|
# Manual, non-containerised, installation
|
||||||
|
|
||||||
|
|||||||
+28
-3
@@ -514,10 +514,35 @@ class Source(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def type_directory_path(self):
|
def type_directory_path(self):
|
||||||
if self.source_resolution == self.SOURCE_RESOLUTION_AUDIO:
|
# Get the directory mode from the environment
|
||||||
return Path(settings.DOWNLOAD_AUDIO_DIR) / self.directory
|
directory_mode = os.getenv("TUBESYNC_DIRECTORY_MODE", "default")
|
||||||
|
|
||||||
|
# Default behavior
|
||||||
|
if directory_mode == "default":
|
||||||
|
if self.source_resolution == self.SOURCE_RESOLUTION_AUDIO:
|
||||||
|
return Path(settings.DOWNLOAD_AUDIO_DIR) / self.directory
|
||||||
|
else:
|
||||||
|
return Path(settings.DOWNLOAD_VIDEO_DIR) / self.directory
|
||||||
|
|
||||||
|
# Flat mode - Place all files in the root
|
||||||
|
elif directory_mode == "flat":
|
||||||
|
return Path(settings.DOWNLOAD_DIR) / self.directory
|
||||||
|
|
||||||
|
# Custom mode - Parse prefixes for audio and video
|
||||||
|
elif directory_mode.startswith("custom:"):
|
||||||
|
try:
|
||||||
|
audio_prefix, video_prefix = directory_mode.split(":")[1].split(",")
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Invalid format for TUBESYNC_DIRECTORY_MODE=custom. Expected 'custom:audio_prefix,video_prefix'.")
|
||||||
|
|
||||||
|
if self.source_resolution == self.SOURCE_RESOLUTION_AUDIO:
|
||||||
|
return Path(settings.DOWNLOAD_DIR) / audio_prefix / self.directory
|
||||||
|
else:
|
||||||
|
return Path(settings.DOWNLOAD_DIR) / video_prefix / self.directory
|
||||||
|
|
||||||
|
# Fallback for invalid modes
|
||||||
else:
|
else:
|
||||||
return Path(settings.DOWNLOAD_VIDEO_DIR) / self.directory
|
raise ValueError(f"Unsupported TUBESYNC_DIRECTORY_MODE: {directory_mode}")
|
||||||
|
|
||||||
def make_directory(self):
|
def make_directory(self):
|
||||||
return os.makedirs(self.directory_path, exist_ok=True)
|
return os.makedirs(self.directory_path, exist_ok=True)
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from pathlib import Path
|
||||||
from urllib.parse import urlsplit
|
from urllib.parse import urlsplit
|
||||||
from xml.etree import ElementTree
|
from xml.etree import ElementTree
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@@ -1714,3 +1716,77 @@ class TasksTestCase(TestCase):
|
|||||||
self.assertEqual(src1.media_source.all().count(), 3)
|
self.assertEqual(src1.media_source.all().count(), 3)
|
||||||
self.assertEqual(src2.media_source.all().count(), 2)
|
self.assertEqual(src2.media_source.all().count(), 2)
|
||||||
self.assertEqual(Media.objects.filter(pk=m22.pk).exists(), False)
|
self.assertEqual(Media.objects.filter(pk=m22.pk).exists(), False)
|
||||||
|
|
||||||
|
class TypeDirectoryPathTestCase(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
# Mock settings for testing
|
||||||
|
self.audio_dir = Path("/mock/audio/dir")
|
||||||
|
self.video_dir = Path("/mock/video/dir")
|
||||||
|
self.download_dir = Path("/mock/download/dir")
|
||||||
|
settings.DOWNLOAD_AUDIO_DIR = self.audio_dir
|
||||||
|
settings.DOWNLOAD_VIDEO_DIR = self.video_dir
|
||||||
|
settings.DOWNLOAD_DIR = self.download_dir
|
||||||
|
|
||||||
|
# Create a source object for testing
|
||||||
|
self.source = Source(
|
||||||
|
directory="test_directory",
|
||||||
|
source_resolution=Source.SOURCE_RESOLUTION_AUDIO,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_default_mode_audio(self):
|
||||||
|
"""
|
||||||
|
Test default mode for audio resolution.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "default"
|
||||||
|
expected_path = self.audio_dir / self.source.directory
|
||||||
|
self.assertEqual(self.source.type_directory_path, expected_path)
|
||||||
|
|
||||||
|
def test_default_mode_video(self):
|
||||||
|
"""
|
||||||
|
Test default mode for video resolution.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "default"
|
||||||
|
self.source.source_resolution = Source.SOURCE_RESOLUTION_1080P
|
||||||
|
expected_path = self.video_dir / self.source.directory
|
||||||
|
self.assertEqual(self.source.type_directory_path, expected_path)
|
||||||
|
|
||||||
|
def test_flat_mode(self):
|
||||||
|
"""
|
||||||
|
Test flat mode places files in the root download directory.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "flat"
|
||||||
|
expected_path = self.download_dir / self.source.directory
|
||||||
|
self.assertEqual(self.source.type_directory_path, expected_path)
|
||||||
|
|
||||||
|
def test_custom_mode_audio(self):
|
||||||
|
"""
|
||||||
|
Test custom mode with prefixes for audio.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "custom:audio_prefix,video_prefix"
|
||||||
|
expected_path = self.download_dir / "audio_prefix" / self.source.directory
|
||||||
|
self.assertEqual(self.source.type_directory_path, expected_path)
|
||||||
|
|
||||||
|
def test_custom_mode_video(self):
|
||||||
|
"""
|
||||||
|
Test custom mode with prefixes for video.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "custom:audio_prefix,video_prefix"
|
||||||
|
self.source.source_resolution = Source.SOURCE_RESOLUTION_1080P
|
||||||
|
expected_path = self.download_dir / "video_prefix" / self.source.directory
|
||||||
|
self.assertEqual(self.source.type_directory_path, expected_path)
|
||||||
|
|
||||||
|
def test_custom_mode_invalid_format(self):
|
||||||
|
"""
|
||||||
|
Test custom mode with an invalid format.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "custom:only_audio_prefix"
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_ = self.source.type_directory_path
|
||||||
|
|
||||||
|
def test_invalid_mode(self):
|
||||||
|
"""
|
||||||
|
Test unsupported directory mode raises an error.
|
||||||
|
"""
|
||||||
|
os.environ["TUBESYNC_DIRECTORY_MODE"] = "unsupported_mode"
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
_ = self.source.type_directory_path
|
||||||
Reference in new issue
Block a user