feat: Separate tracks by user
This commit is contained in:
@@ -74,6 +74,7 @@ async def handle_download(album_id: str, request: Request, current_user: User =
|
|||||||
"url": url,
|
"url": url,
|
||||||
"name": name_from_spotify,
|
"name": name_from_spotify,
|
||||||
"artist": artist_from_spotify,
|
"artist": artist_from_spotify,
|
||||||
|
"username": current_user.username,
|
||||||
"orig_request": orig_params,
|
"orig_request": orig_params,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ async def handle_download(playlist_id: str, request: Request, current_user: User
|
|||||||
"url": url,
|
"url": url,
|
||||||
"name": name_from_spotify, # Use fetched name
|
"name": name_from_spotify, # Use fetched name
|
||||||
"artist": artist_from_spotify, # Use fetched owner name as artist
|
"artist": artist_from_spotify, # Use fetched owner name as artist
|
||||||
|
"username": current_user.username,
|
||||||
"orig_request": orig_params,
|
"orig_request": orig_params,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ async def handle_download(track_id: str, request: Request, current_user: User =
|
|||||||
"url": url,
|
"url": url,
|
||||||
"name": name_from_spotify,
|
"name": name_from_spotify,
|
||||||
"artist": artist_from_spotify,
|
"artist": artist_from_spotify,
|
||||||
|
"username": current_user.username,
|
||||||
"orig_request": orig_params,
|
"orig_request": orig_params,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ DEFAULT_MAIN_CONFIG = {
|
|||||||
"artistSeparator": "; ",
|
"artistSeparator": "; ",
|
||||||
"recursiveQuality": False,
|
"recursiveQuality": False,
|
||||||
"spotifyMetadata": True,
|
"spotifyMetadata": True,
|
||||||
|
"separateTracksByUser": False,
|
||||||
"watch": {},
|
"watch": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ def get_config_params():
|
|||||||
"recursiveQuality": config.get(
|
"recursiveQuality": config.get(
|
||||||
"recursiveQuality", config.get("recursive_quality", False)
|
"recursiveQuality", config.get("recursive_quality", False)
|
||||||
),
|
),
|
||||||
|
"separateTracksByUser": config.get("separateTracksByUser", False),
|
||||||
"watch": config.get("watch", {}),
|
"watch": config.get("watch", {}),
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -93,6 +94,7 @@ def get_config_params():
|
|||||||
"bitrate": None, # Default for bitrate
|
"bitrate": None, # Default for bitrate
|
||||||
"artistSeparator": "; ",
|
"artistSeparator": "; ",
|
||||||
"recursiveQuality": False,
|
"recursiveQuality": False,
|
||||||
|
"separateTracksByUser": False,
|
||||||
"watch": {},
|
"watch": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,6 +363,9 @@ class CeleryDownloadQueueManager:
|
|||||||
original_request = task.get(
|
original_request = task.get(
|
||||||
"orig_request", task.get("original_request", {})
|
"orig_request", task.get("original_request", {})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get username for user-specific paths
|
||||||
|
username = task.get("username", "")
|
||||||
|
|
||||||
complete_task = {
|
complete_task = {
|
||||||
"download_type": incoming_type,
|
"download_type": incoming_type,
|
||||||
@@ -383,8 +388,10 @@ class CeleryDownloadQueueManager:
|
|||||||
"real_time": self._parse_bool_param(
|
"real_time": self._parse_bool_param(
|
||||||
original_request.get("real_time"), config_params["realTime"]
|
original_request.get("real_time"), config_params["realTime"]
|
||||||
),
|
),
|
||||||
"custom_dir_format": original_request.get(
|
"custom_dir_format": self._get_user_specific_dir_format(
|
||||||
"custom_dir_format", config_params["customDirFormat"]
|
original_request.get("custom_dir_format", config_params["customDirFormat"]),
|
||||||
|
config_params.get("separateTracksByUser", False),
|
||||||
|
username
|
||||||
),
|
),
|
||||||
"custom_track_format": original_request.get(
|
"custom_track_format": original_request.get(
|
||||||
"custom_track_format", config_params["customTrackFormat"]
|
"custom_track_format", config_params["customTrackFormat"]
|
||||||
@@ -487,6 +494,23 @@ class CeleryDownloadQueueManager:
|
|||||||
return param_value.lower() in ["true", "1", "yes", "y", "on"]
|
return param_value.lower() in ["true", "1", "yes", "y", "on"]
|
||||||
return bool(param_value)
|
return bool(param_value)
|
||||||
|
|
||||||
|
def _get_user_specific_dir_format(self, base_format, separate_by_user, username):
|
||||||
|
"""
|
||||||
|
Modify the directory format to include username if separateTracksByUser is enabled
|
||||||
|
|
||||||
|
Args:
|
||||||
|
base_format (str): The base directory format from config
|
||||||
|
separate_by_user (bool): Whether to separate tracks by user
|
||||||
|
username (str): The username to include in path
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The modified directory format
|
||||||
|
"""
|
||||||
|
if separate_by_user and username:
|
||||||
|
# Add username as a subdirectory at the beginning
|
||||||
|
return f"{username}/{base_format}"
|
||||||
|
return base_format
|
||||||
|
|
||||||
def cancel_task(self, task_id):
|
def cancel_task(self, task_id):
|
||||||
"""
|
"""
|
||||||
Cancels a task by its ID.
|
Cancels a task by its ID.
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ interface DownloadSettings {
|
|||||||
deezerQuality: "MP3_128" | "MP3_320" | "FLAC";
|
deezerQuality: "MP3_128" | "MP3_320" | "FLAC";
|
||||||
spotifyQuality: "NORMAL" | "HIGH" | "VERY_HIGH";
|
spotifyQuality: "NORMAL" | "HIGH" | "VERY_HIGH";
|
||||||
recursiveQuality: boolean; // frontend field (sent as camelCase to backend)
|
recursiveQuality: boolean; // frontend field (sent as camelCase to backend)
|
||||||
|
separateTracksByUser: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface WatchConfig {
|
interface WatchConfig {
|
||||||
@@ -195,6 +196,13 @@ export function DownloadsTab({ config, isLoading }: DownloadsTabProps) {
|
|||||||
<label htmlFor="recursiveQualityToggle" className="text-content-primary dark:text-content-primary-dark">Recursive Quality</label>
|
<label htmlFor="recursiveQualityToggle" className="text-content-primary dark:text-content-primary-dark">Recursive Quality</label>
|
||||||
<input id="recursiveQualityToggle" type="checkbox" {...register("recursiveQuality")} className="h-6 w-6 rounded" />
|
<input id="recursiveQualityToggle" type="checkbox" {...register("recursiveQuality")} className="h-6 w-6 rounded" />
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<label htmlFor="separateTracksByUserToggle" className="text-content-primary dark:text-content-primary-dark">Separate tracks by user</label>
|
||||||
|
<input id="separateTracksByUserToggle" type="checkbox" {...register("separateTracksByUser")} className="h-6 w-6 rounded" />
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-content-muted dark:text-content-muted-dark">
|
||||||
|
When enabled, downloads will be organized in user-specific subdirectories (downloads/username/...)
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* Watch validation info */}
|
{/* Watch validation info */}
|
||||||
{watchConfig?.enabled && (
|
{watchConfig?.enabled && (
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export type FlatAppSettings = {
|
|||||||
hlsThreads: number;
|
hlsThreads: number;
|
||||||
// Frontend-only flag used in DownloadsTab
|
// Frontend-only flag used in DownloadsTab
|
||||||
recursiveQuality: boolean;
|
recursiveQuality: boolean;
|
||||||
|
separateTracksByUser: boolean;
|
||||||
// Add defaults for the new formatting properties
|
// Add defaults for the new formatting properties
|
||||||
track: string;
|
track: string;
|
||||||
album: string;
|
album: string;
|
||||||
@@ -90,6 +91,7 @@ const defaultSettings: FlatAppSettings = {
|
|||||||
hlsThreads: 8,
|
hlsThreads: 8,
|
||||||
// Frontend-only default
|
// Frontend-only default
|
||||||
recursiveQuality: false,
|
recursiveQuality: false,
|
||||||
|
separateTracksByUser: false,
|
||||||
// Add defaults for the new formatting properties
|
// Add defaults for the new formatting properties
|
||||||
track: "{artist_name}/{album_name}/{track_number} - {track_name}",
|
track: "{artist_name}/{album_name}/{track_number} - {track_name}",
|
||||||
album: "{artist_name}/{album_name}",
|
album: "{artist_name}/{album_name}",
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export interface AppSettings {
|
|||||||
m3u: boolean;
|
m3u: boolean;
|
||||||
hlsThreads: number;
|
hlsThreads: number;
|
||||||
recursiveQuality: boolean;
|
recursiveQuality: boolean;
|
||||||
|
separateTracksByUser: boolean;
|
||||||
// Properties from the old 'formatting' object
|
// Properties from the old 'formatting' object
|
||||||
track: string;
|
track: string;
|
||||||
album: string;
|
album: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user