Signed-off-by: mbrucedogs <mbrucedogs@gmail.com>
This commit is contained in:
parent
c9b2e23e04
commit
148fd2a141
78
web/app.py
78
web/app.py
@ -58,6 +58,35 @@ def get_duplicate_groups(skip_songs: List[Dict[str, Any]]) -> List[Dict[str, Any
|
||||
|
||||
return groups_list
|
||||
|
||||
|
||||
def generate_mp3_song_list(all_songs: List[Dict[str, Any]], skip_songs: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""Generate a list of MP3 songs that remain after cleanup."""
|
||||
# Create a set of paths that are being skipped
|
||||
skip_paths = {song['path'] for song in skip_songs}
|
||||
|
||||
# Filter for MP3/CDG songs that are NOT being skipped
|
||||
mp3_songs = []
|
||||
for song in all_songs:
|
||||
path = song.get('path', '')
|
||||
if path.lower().endswith(('.mp3', '.cdg')) and path not in skip_paths:
|
||||
mp3_songs.append({
|
||||
'position': len(mp3_songs) + 1,
|
||||
'title': song.get('title', 'Unknown'),
|
||||
'artist': song.get('artist', 'Unknown')
|
||||
})
|
||||
|
||||
# Sort by artist, then by title
|
||||
mp3_songs.sort(key=lambda x: (x['artist'].lower(), x['title'].lower()))
|
||||
|
||||
# Update positions after sorting
|
||||
for i, song in enumerate(mp3_songs):
|
||||
song['position'] = i + 1
|
||||
|
||||
return {
|
||||
'title': 'MP3 Songs need to be found',
|
||||
'songs': mp3_songs
|
||||
}
|
||||
|
||||
def get_file_type(path: str) -> str:
|
||||
"""Extract file type from path."""
|
||||
path_lower = path.lower()
|
||||
@ -359,5 +388,54 @@ def get_artists():
|
||||
'total_artists': len(artists_list)
|
||||
})
|
||||
|
||||
|
||||
@app.route('/api/mp3-songs')
|
||||
def get_mp3_songs():
|
||||
"""API endpoint to get MP3 songs that remain after cleanup."""
|
||||
# Load all songs and skip songs
|
||||
all_songs = load_json_file(os.path.join(DATA_DIR, 'allSongs.json'))
|
||||
skip_songs = load_json_file(os.path.join(DATA_DIR, 'reports', 'skip_songs_detailed.json'))
|
||||
|
||||
if not all_songs:
|
||||
return jsonify({'error': 'No all songs data found'}), 404
|
||||
|
||||
if not skip_songs:
|
||||
skip_songs = []
|
||||
|
||||
# Generate MP3 song list
|
||||
mp3_song_list = generate_mp3_song_list(all_songs, skip_songs)
|
||||
|
||||
return jsonify(mp3_song_list)
|
||||
|
||||
|
||||
@app.route('/api/download/mp3-songs')
|
||||
def download_mp3_songs():
|
||||
"""Download MP3 songs list as JSON file."""
|
||||
# Load all songs and skip songs
|
||||
all_songs = load_json_file(os.path.join(DATA_DIR, 'allSongs.json'))
|
||||
skip_songs = load_json_file(os.path.join(DATA_DIR, 'reports', 'skip_songs_detailed.json'))
|
||||
|
||||
if not all_songs:
|
||||
return jsonify({'error': 'No all songs data found'}), 404
|
||||
|
||||
if not skip_songs:
|
||||
skip_songs = []
|
||||
|
||||
# Generate MP3 song list
|
||||
mp3_song_list = generate_mp3_song_list(all_songs, skip_songs)
|
||||
|
||||
# Save to file
|
||||
output_path = os.path.join(DATA_DIR, 'reports', 'mp3SongList.json')
|
||||
with open(output_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(mp3_song_list, f, indent=2, ensure_ascii=False)
|
||||
|
||||
# Return the file for download
|
||||
return send_from_directory(
|
||||
os.path.join(DATA_DIR, 'reports'),
|
||||
'mp3SongList.json',
|
||||
as_attachment=True,
|
||||
download_name='mp3SongList.json'
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, host='0.0.0.0', port=5000)
|
||||
@ -266,6 +266,20 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-3">
|
||||
<button class="btn btn-success w-100" onclick="downloadMp3Songs()">
|
||||
<i class="fas fa-download"></i> Download MP3 Song List
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<small class="text-muted">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
Download a JSON file containing all MP3 songs that remain after cleanup,
|
||||
sorted by artist and title. Use this list to find replacement videos.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -737,6 +751,48 @@
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
async function downloadMp3Songs() {
|
||||
try {
|
||||
// Show loading state
|
||||
const button = event.target.closest('button');
|
||||
const originalText = button.innerHTML;
|
||||
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Generating...';
|
||||
button.disabled = true;
|
||||
|
||||
// Trigger download
|
||||
const response = await fetch('/api/download/mp3-songs');
|
||||
|
||||
if (response.ok) {
|
||||
// Create a blob from the response
|
||||
const blob = await response.blob();
|
||||
|
||||
// Create download link
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'mp3SongList.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Show success message
|
||||
alert('MP3 Song List downloaded successfully!');
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
alert('Error downloading MP3 song list: ' + (errorData.error || 'Unknown error'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error downloading MP3 songs:', error);
|
||||
alert('Error downloading MP3 song list: ' + error.message);
|
||||
} finally {
|
||||
// Restore button state
|
||||
const button = event.target.closest('button');
|
||||
button.innerHTML = originalText;
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user