113 lines
3.6 KiB
Python
113 lines
3.6 KiB
Python
import os
|
|
from typing import List
|
|
from app.utils.logger import logger
|
|
|
|
def load_local_playlist(playlist_path: str) -> List[str]:
|
|
"""
|
|
Load a local playlist from a m3u or m3u8 file.
|
|
Skip # comments and empty lines.
|
|
|
|
Args:
|
|
playlist_path (str): The path to the playlist file.
|
|
|
|
Returns:
|
|
list: A list of songs in the playlist.
|
|
"""
|
|
try:
|
|
result = []
|
|
with open(playlist_path, 'r', encoding="utf-8") as file:
|
|
for line in file:
|
|
line = line.strip()
|
|
if not line:
|
|
# Skip empty lines
|
|
continue
|
|
if line.startswith('#'):
|
|
# Skip comments
|
|
continue
|
|
result.append(line)
|
|
logger.info(f"Loaded {len(result)} songs from the playlist: {playlist_path}")
|
|
return result
|
|
except FileNotFoundError:
|
|
logger.error(f"Error: The file {playlist_path} does not exist.")
|
|
return []
|
|
except Exception as e:
|
|
logger.error(f"An error occurred while loading the playlist: {e}")
|
|
return []
|
|
|
|
|
|
def scan_local_playlists(base_path: str) -> list[dict]:
|
|
"""Scan a directory for playlist files and return their basic info.
|
|
|
|
Args:
|
|
base_path: Directory that contains playlist files.
|
|
|
|
Returns:
|
|
A list of dictionaries with ``name`` and ``track_count`` keys.
|
|
"""
|
|
|
|
playlists: list[dict] = []
|
|
if not base_path:
|
|
logger.warning("No base path provided for local playlists scan.")
|
|
return playlists
|
|
|
|
absolute_path = os.path.abspath(base_path)
|
|
if not os.path.isdir(absolute_path):
|
|
logger.warning(f"Playlist path does not exist or is not a directory: {absolute_path}")
|
|
return playlists
|
|
|
|
for entry in os.scandir(absolute_path):
|
|
if not entry.is_file():
|
|
continue
|
|
if not entry.name.lower().endswith((".m3u", ".m3u8")):
|
|
continue
|
|
tracks = load_local_playlist(entry.path)
|
|
playlists.append({"name": entry.name, "track_count": len(tracks)})
|
|
|
|
playlists.sort(key=lambda item: item["name"].lower())
|
|
logger.info(f"Found {len(playlists)} playlists under {absolute_path}.")
|
|
return playlists
|
|
def write_local_playlist(playlist_path: str, tracks: List[str]) -> bool:
|
|
"""
|
|
Write a list of tracks to a local playlist file.
|
|
|
|
Args:
|
|
playlist_path (str): The path to the playlist file.
|
|
tracks (list): A list of songs to write to the playlist.
|
|
|
|
Returns:
|
|
bool: True if successful, False otherwise.
|
|
"""
|
|
try:
|
|
with open(playlist_path, 'w', encoding="utf-8") as file:
|
|
file.write("#EXTM3U\n")
|
|
for track in tracks:
|
|
file.write(f"{track}\n")
|
|
logger.info(f"Written {len(tracks)} songs to the playlist: {playlist_path}")
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"An error occurred while writing the playlist {playlist_path}: {e}")
|
|
return False
|
|
|
|
|
|
def delete_local_playlist(playlist_path: str) -> bool:
|
|
"""
|
|
Delete a local playlist file.
|
|
|
|
Args:
|
|
playlist_path (str): The path to the playlist file.
|
|
|
|
Returns:
|
|
bool: True if successful, False otherwise.
|
|
"""
|
|
try:
|
|
if os.path.exists(playlist_path):
|
|
os.remove(playlist_path)
|
|
logger.info(f"Deleted playlist: {playlist_path}")
|
|
return True
|
|
else:
|
|
logger.warning(f"Playlist not found for deletion: {playlist_path}")
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"An error occurred while deleting the playlist {playlist_path}: {e}")
|
|
return False
|