Add $year variable support to file path templates
Introduces the $year variable for album, single, and playlist path templates, allowing users to include the release year in file organization. Updates the backend to extract and provide the year, adjusts the web UI to document the new variable, and updates validation logic to recognize $year as valid in templates.
This commit is contained in:
parent
3bd8c4f94c
commit
a8935ae8f5
4 changed files with 24 additions and 10 deletions
|
|
@ -48,6 +48,7 @@
|
|||
},
|
||||
"file_organization": {
|
||||
"enabled": true,
|
||||
"_template_variables": "Available: $artist, $albumartist, $album, $title, $track, $year, $playlist",
|
||||
"templates": {
|
||||
"album_path": "$albumartist/$albumartist - $album/$track - $title",
|
||||
"single_path": "$artist/$artist - $title/$title",
|
||||
|
|
|
|||
|
|
@ -6948,6 +6948,14 @@ def _build_final_path_for_track(context, spotify_artist, album_info, file_ext):
|
|||
original_search = context.get("original_search_result", {})
|
||||
playlist_folder_mode = track_info.get("_playlist_folder_mode", False)
|
||||
|
||||
# Extract year from spotify_album for template use (safe for all modes)
|
||||
year = 'Unknown'
|
||||
spotify_album = context.get("spotify_album", {})
|
||||
if spotify_album and spotify_album.get('release_date'):
|
||||
release_date = spotify_album['release_date']
|
||||
if release_date and len(release_date) >= 4:
|
||||
year = release_date[:4]
|
||||
|
||||
# Determine which template type to use
|
||||
if playlist_folder_mode:
|
||||
# PLAYLIST MODE
|
||||
|
|
@ -6960,7 +6968,8 @@ def _build_final_path_for_track(context, spotify_artist, album_info, file_ext):
|
|||
'album': track_name,
|
||||
'title': track_name,
|
||||
'playlist_name': playlist_name,
|
||||
'track_number': 1
|
||||
'track_number': 1,
|
||||
'year': year
|
||||
}
|
||||
|
||||
folder_path, filename_base = _get_file_path_from_template(template_context, 'playlist_path')
|
||||
|
|
@ -6997,7 +7006,8 @@ def _build_final_path_for_track(context, spotify_artist, album_info, file_ext):
|
|||
'albumartist': spotify_artist["name"] if isinstance(spotify_artist, dict) else spotify_artist.name,
|
||||
'album': album_info['album_name'],
|
||||
'title': clean_track_name,
|
||||
'track_number': track_number
|
||||
'track_number': track_number,
|
||||
'year': year
|
||||
}
|
||||
|
||||
folder_path, filename_base = _get_file_path_from_template(template_context, 'album_path')
|
||||
|
|
@ -7032,7 +7042,8 @@ def _build_final_path_for_track(context, spotify_artist, album_info, file_ext):
|
|||
'albumartist': spotify_artist["name"] if isinstance(spotify_artist, dict) else spotify_artist.name,
|
||||
'album': album_info.get('album_name', clean_track_name) if album_info else clean_track_name,
|
||||
'title': clean_track_name,
|
||||
'track_number': 1
|
||||
'track_number': 1,
|
||||
'year': year
|
||||
}
|
||||
|
||||
folder_path, filename_base = _get_file_path_from_template(template_context, 'single_path')
|
||||
|
|
@ -7076,6 +7087,7 @@ def _apply_path_template(template: str, context: dict) -> str:
|
|||
result = result.replace('$album', context.get('album', 'Unknown Album'))
|
||||
result = result.replace('$title', context.get('title', 'Unknown Track'))
|
||||
result = result.replace('$track', f"{context.get('track_number', 1):02d}")
|
||||
result = result.replace('$year', str(context.get('year', 'Unknown')))
|
||||
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -2772,19 +2772,19 @@
|
|||
<div class="form-group">
|
||||
<label>Album Path Template:</label>
|
||||
<input type="text" id="template-album-path" placeholder="$albumartist/$albumartist - $album/$track - $title">
|
||||
<small style="color: #888;">Variables: $albumartist, $artist, $album, $title, $track</small>
|
||||
<small style="color: #888;">Variables: $albumartist, $artist, $album, $title, $track, $year</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Single Path Template:</label>
|
||||
<input type="text" id="template-single-path" placeholder="$artist/$artist - $title/$title">
|
||||
<small style="color: #888;">Variables: $artist, $title, $album</small>
|
||||
<small style="color: #888;">Variables: $artist, $title, $album, $year</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Playlist Path Template:</label>
|
||||
<input type="text" id="template-playlist-path" placeholder="$playlist/$artist - $title">
|
||||
<small style="color: #888;">Variables: $playlist, $artist, $title</small>
|
||||
<small style="color: #888;">Variables: $playlist, $artist, $title, $year</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
|
|
|||
|
|
@ -1484,9 +1484,9 @@ function validateFileOrganizationTemplates() {
|
|||
|
||||
// Valid variables for each template type
|
||||
const validVars = {
|
||||
album: ['$artist', '$albumartist', '$album', '$title', '$track'],
|
||||
single: ['$artist', '$albumartist', '$album', '$title'],
|
||||
playlist: ['$artist', '$playlist', '$title']
|
||||
album: ['$artist', '$albumartist', '$album', '$title', '$track', '$year'],
|
||||
single: ['$artist', '$albumartist', '$album', '$title', '$year'],
|
||||
playlist: ['$artist', '$playlist', '$title', '$year']
|
||||
};
|
||||
|
||||
// Get template values
|
||||
|
|
@ -7219,7 +7219,8 @@ async function startMissingTracksProcess(playlistId) {
|
|||
};
|
||||
|
||||
// If this is an artist album download, use album name and include full context
|
||||
if (playlistId.startsWith('artist_album_')) {
|
||||
// Match both 'artist_album_' and 'enhanced_search_album_' prefixes
|
||||
if (playlistId.startsWith('artist_album_') || playlistId.startsWith('enhanced_search_album_')) {
|
||||
requestBody.playlist_name = process.album?.name || process.playlist.name;
|
||||
requestBody.is_album_download = true;
|
||||
requestBody.album_context = process.album; // Full Spotify album object
|
||||
|
|
|
|||
Loading…
Reference in a new issue