127 lines
4.8 KiB
Python
127 lines
4.8 KiB
Python
"""
|
|
Server management utilities.
|
|
Handles server songs loading and server duplicates tracking.
|
|
"""
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
|
|
def load_server_songs(songs_path="data/songs.json"):
|
|
"""Load the list of songs already available on the server with format information."""
|
|
songs_file = Path(songs_path)
|
|
if not songs_file.exists():
|
|
print(f"⚠️ Server songs file not found: {songs_path}")
|
|
return {}
|
|
try:
|
|
with open(songs_file, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
server_songs = {}
|
|
for song in data:
|
|
if "artist" in song and "title" in song and "path" in song:
|
|
artist = song["artist"].strip()
|
|
title = song["title"].strip()
|
|
path = song["path"].strip()
|
|
key = f"{artist.lower()}_{normalize_title(title)}"
|
|
server_songs[key] = {
|
|
"artist": artist,
|
|
"title": title,
|
|
"path": path,
|
|
"is_mp3": path.lower().endswith('.mp3'),
|
|
"is_cdg": 'cdg' in path.lower(),
|
|
"is_mp4": path.lower().endswith('.mp4')
|
|
}
|
|
print(f"📋 Loaded {len(server_songs)} songs from server (songs.json)")
|
|
return server_songs
|
|
except (json.JSONDecodeError, FileNotFoundError) as e:
|
|
print(f"⚠️ Could not load server songs: {e}")
|
|
return {}
|
|
|
|
|
|
def is_song_on_server(server_songs, artist, title):
|
|
"""Check if a song is already available on the server."""
|
|
key = f"{artist.lower()}_{normalize_title(title)}"
|
|
return key in server_songs
|
|
|
|
|
|
def should_skip_server_song(server_songs, artist, title):
|
|
"""Check if a song should be skipped because it's already available as MP4 on server.
|
|
Returns True if the song should be skipped (MP4 format), False if it should be downloaded (MP3/CDG format)."""
|
|
key = f"{artist.lower()}_{normalize_title(title)}"
|
|
if key not in server_songs:
|
|
return False # Not on server, so don't skip
|
|
|
|
song_info = server_songs[key]
|
|
# Skip if it's an MP4 file (video format)
|
|
# Don't skip if it's MP3 or in CDG folder (different format)
|
|
return song_info.get("is_mp4", False) and not song_info.get("is_cdg", False)
|
|
|
|
|
|
def load_server_duplicates_tracking(
|
|
tracking_path="data/server_duplicates_tracking.json",
|
|
):
|
|
"""Load the tracking of songs found to be duplicates on the server."""
|
|
tracking_file = Path(tracking_path)
|
|
if not tracking_file.exists():
|
|
return {}
|
|
try:
|
|
with open(tracking_file, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
except (json.JSONDecodeError, FileNotFoundError) as e:
|
|
print(f"⚠️ Could not load server duplicates tracking: {e}")
|
|
return {}
|
|
|
|
|
|
def save_server_duplicates_tracking(
|
|
tracking, tracking_path="data/server_duplicates_tracking.json"
|
|
):
|
|
"""Save the tracking of songs found to be duplicates on the server."""
|
|
try:
|
|
with open(tracking_path, "w", encoding="utf-8") as f:
|
|
json.dump(tracking, f, indent=2, ensure_ascii=False)
|
|
except Exception as e:
|
|
print(f"⚠️ Could not save server duplicates tracking: {e}")
|
|
|
|
|
|
def is_song_marked_as_server_duplicate(tracking, artist, title):
|
|
"""Check if a song has been marked as a server duplicate."""
|
|
key = f"{artist.lower()}_{normalize_title(title)}"
|
|
return key in tracking
|
|
|
|
|
|
def mark_song_as_server_duplicate(tracking, artist, title, video_title, channel_name):
|
|
"""Mark a song as a server duplicate for future skipping."""
|
|
key = f"{artist.lower()}_{normalize_title(title)}"
|
|
tracking[key] = {
|
|
"artist": artist,
|
|
"title": title,
|
|
"video_title": video_title,
|
|
"channel": channel_name,
|
|
"marked_at": datetime.now().isoformat(),
|
|
"reason": "already_on_server",
|
|
}
|
|
save_server_duplicates_tracking(tracking)
|
|
|
|
|
|
def check_and_mark_server_duplicate(
|
|
server_songs, server_duplicates_tracking, artist, title, video_title, channel_name
|
|
):
|
|
"""Check if a song should be skipped because it's already available as MP4 on server and mark it as duplicate if so.
|
|
Returns True if it should be skipped (MP4 format), False if it should be downloaded (MP3/CDG format)."""
|
|
if should_skip_server_song(server_songs, artist, title):
|
|
if not is_song_marked_as_server_duplicate(
|
|
server_duplicates_tracking, artist, title
|
|
):
|
|
mark_song_as_server_duplicate(
|
|
server_duplicates_tracking, artist, title, video_title, channel_name
|
|
)
|
|
return True
|
|
return False
|
|
|
|
|
|
def normalize_title(title):
|
|
"""Normalize a title for consistent key generation."""
|
|
normalized = title.replace("(Karaoke Version)", "").replace("(Karaoke)", "").strip()
|
|
return " ".join(normalized.split()).lower()
|