nice
This commit is contained in:
parent
b6c59e81ad
commit
9cd2c9189b
6 changed files with 112 additions and 128 deletions
2
Flow.py
2
Flow.py
|
|
@ -23,6 +23,7 @@ from src.StatGenerator import log_stats
|
|||
class Flow:
|
||||
spotify_library : Library = None
|
||||
local_library : Library = None
|
||||
itunes_library : Library = None
|
||||
|
||||
@staticmethod
|
||||
def fetch_spotify(self):
|
||||
|
|
@ -107,6 +108,7 @@ class Flow:
|
|||
|
||||
def load_libraries(self):
|
||||
self.spotify_library = LibraryLoader().load(work_dir / "spotify_library.json")
|
||||
self.itunes_library = LibraryLoader().load(work_dir / "itunes_library.json")
|
||||
self.local_library = LibraryLoader().load(work_dir / "local_library.json")
|
||||
|
||||
def save_libraries(self):
|
||||
|
|
|
|||
38
Gui.py
38
Gui.py
|
|
@ -6,34 +6,36 @@ import pandas as pd
|
|||
|
||||
import Flow
|
||||
|
||||
from src.Library import Library, Artist, Album, Track, Playlist
|
||||
from src.Library import *
|
||||
|
||||
def entity_to_row(entity: Entity):
|
||||
return {
|
||||
"id": entity.id,
|
||||
"mbid": entity.mbid,
|
||||
"Title": entity.title,
|
||||
"PLay Count": entity.play_count,
|
||||
"Resolved": int(entity.resolved_percentage * 100),
|
||||
"AutoScore": entity.auto_score,
|
||||
"Added": entity.date_added.strftime("%Y-%m-%d") if entity.date_added else None,
|
||||
"Played": entity.date_last_play.strftime("%Y-%m-%d") if entity.date_last_play else None,
|
||||
"Released": entity.date_released.strftime("%Y-%m-%d") if entity.date_released else None,
|
||||
"LocalId": str(entity.local_id) if entity.local_id else None,
|
||||
"Path": str(entity.local_path) if entity.local_path else None,
|
||||
}
|
||||
|
||||
def track_to_row(track: Track):
|
||||
return {
|
||||
"Title": track.title,
|
||||
return entity_to_row(track) | {
|
||||
"Album": track.album.title if track.album else "",
|
||||
"Artists": ", ".join(a.title if a.title else "no_arist_name" for a in track.artists),
|
||||
"Lyrics": track.has_lyrics,
|
||||
"AutoScore": track.auto_score,
|
||||
"Added": track.added_at.strftime("%Y-%m-%d") if track.added_at else "",
|
||||
"LocalId": str(track.local_id) if track.local_id else "",
|
||||
"Path": str(track.local_path) if track.local_path else "",
|
||||
}
|
||||
|
||||
def artist_to_row(artist: Artist):
|
||||
return {
|
||||
"Title": artist.title,
|
||||
"AutoScore": artist.auto_score,
|
||||
"Resolved": int(artist.resolved_percentage * 100),
|
||||
"LocalId": str(artist.local_id) if artist.local_id else "",
|
||||
return entity_to_row(artist) | {
|
||||
}
|
||||
|
||||
def album_to_row(album: Album):
|
||||
return {
|
||||
"Title": album.title,
|
||||
"AutoScore": album.auto_score,
|
||||
"Resolved": int(album.resolved_percentage * 100),
|
||||
"LocalId": str(album.local_id) if album.local_id else "",
|
||||
return entity_to_row(album) | {
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,7 +202,7 @@ def run():
|
|||
# flow.log_stats()
|
||||
|
||||
gui = LibraryView()
|
||||
gui.add_libraries([flow.spotify_library, flow.local_library])
|
||||
gui.add_libraries([flow.spotify_library, flow.itunes_library, flow.local_library])
|
||||
gui.render()
|
||||
|
||||
run()
|
||||
|
|
@ -4,77 +4,58 @@ from datetime import datetime
|
|||
from pathlib import Path
|
||||
from typing import List, Optional, Any
|
||||
|
||||
|
||||
class Entity:
|
||||
def __init__(self):
|
||||
self.id: str = None
|
||||
self.mbid : str = None
|
||||
self.mbid: str = None
|
||||
|
||||
self.title: str = None
|
||||
self.duration_ms: int = None
|
||||
|
||||
self.fav: bool = False
|
||||
self.rating: int = 0
|
||||
self.play_count : int = 0
|
||||
self.date_added : datetime = None
|
||||
self.date_released : datetime = None
|
||||
self.date_last_play : datetime = None
|
||||
self.play_count: int = 0
|
||||
self.date_added: datetime = None
|
||||
self.date_released: datetime = None
|
||||
self.date_last_play: datetime = None
|
||||
self.auto_score: float = 0
|
||||
|
||||
self.local_id: str = None
|
||||
self.resolved_percentage : float = 0
|
||||
self.local_path: Path = None
|
||||
self.resolved_percentage: float = 0
|
||||
|
||||
class Artist:
|
||||
|
||||
class Artist(Entity):
|
||||
def __init__(self):
|
||||
self.id: str = None
|
||||
self.title: str = None
|
||||
super().__init__()
|
||||
self.tracks: List[Track] = []
|
||||
self.albums: List[Album] = []
|
||||
self.local_id: str = None
|
||||
self.auto_score: float = 0
|
||||
self.fav: bool = False
|
||||
self.rating: int = 0
|
||||
self.resolved_percentage : float = 0
|
||||
|
||||
|
||||
class Track:
|
||||
class Track(Entity):
|
||||
def __init__(self):
|
||||
self.id: str = None
|
||||
self.title: str = None
|
||||
super().__init__()
|
||||
|
||||
self.artists: List[Artist] = []
|
||||
self.album: Album = None
|
||||
self.duration_ms: int = None
|
||||
self.added_at: datetime = None
|
||||
self.local_path: Path = None
|
||||
|
||||
self.has_lyrics: bool = False
|
||||
self.local_id: str = None
|
||||
self.auto_score: float = 0
|
||||
self.fav: bool = False
|
||||
self.rating: int = 0
|
||||
|
||||
|
||||
class Album:
|
||||
class Album(Entity):
|
||||
def __init__(self):
|
||||
self.id: str = None
|
||||
self.title: str = None
|
||||
self.release_date: datetime = None
|
||||
super().__init__()
|
||||
self.tracks: List[Track] = []
|
||||
self.artists: List[Artist] = []
|
||||
self.local_id: str = None
|
||||
self.auto_score: float = 0
|
||||
self.fav: bool = False
|
||||
self.rating: int = 0
|
||||
self.resolved_percentage : float = 0
|
||||
|
||||
|
||||
class Playlist:
|
||||
class Playlist(Entity):
|
||||
def __init__(self):
|
||||
self.title: str = None
|
||||
super().__init__()
|
||||
self.tracks: List[Track] = []
|
||||
self.created_at: datetime = None
|
||||
self.description: str = None
|
||||
self.auto_score: float = 0
|
||||
self.fav: bool = False
|
||||
self.rating: int = 0
|
||||
self.resolved_percentage : float = 0
|
||||
|
||||
|
||||
class Library:
|
||||
|
|
@ -120,14 +101,8 @@ class Library:
|
|||
artist.albums.append(album)
|
||||
|
||||
def auto_score(self):
|
||||
self.score_tracks()
|
||||
self.score_artists()
|
||||
self.score_albums()
|
||||
|
||||
def score_tracks(self):
|
||||
for idx, track in enumerate(self.top_tracks):
|
||||
score = len(self.top_tracks) - idx
|
||||
track.auto_score = score
|
||||
self.score_artists()
|
||||
|
||||
def score_artists(self):
|
||||
for track in self.tracks:
|
||||
|
|
|
|||
|
|
@ -26,60 +26,51 @@ class LibrarySaver:
|
|||
def __init__(self, library: Library):
|
||||
self.library = library
|
||||
|
||||
@staticmethod
|
||||
def _artist_to_dict(artist: Artist) -> dict[str, Any]:
|
||||
def _entity_to_dict(self, entity: Entity) -> dict[str, Any]:
|
||||
return {
|
||||
"id": artist.id,
|
||||
"title": artist.title,
|
||||
"tracks": [track.id for track in artist.tracks],
|
||||
"albums": [album.id for album in artist.albums],
|
||||
"local_id": artist.local_id,
|
||||
"auto_score": artist.auto_score,
|
||||
"fav" : artist.fav,
|
||||
"rating" : artist.rating,
|
||||
"id": entity.id,
|
||||
"mbid": entity.mbid,
|
||||
|
||||
"title": entity.title,
|
||||
"duration": entity.duration_ms,
|
||||
|
||||
"fav" : entity.fav,
|
||||
"rating" : entity.rating,
|
||||
"play_count": entity.play_count,
|
||||
"date_added": entity.date_added,
|
||||
"date_released": entity.date_released,
|
||||
"date_last_play": entity.date_last_play,
|
||||
"auto_score": entity.auto_score,
|
||||
|
||||
"local_id": entity.local_id,
|
||||
"local_path": entity.local_path,
|
||||
"resolved_percentage": entity.resolved_percentage,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _track_to_dict(track: Track) -> dict[str, Any]:
|
||||
return {
|
||||
"id": track.id,
|
||||
"title": track.title,
|
||||
def _artist_to_dict(self, artist: Artist) -> dict[str, Any]:
|
||||
return self._entity_to_dict(artist) | {
|
||||
"tracks": [track.id for track in artist.tracks],
|
||||
"albums": [album.id for album in artist.albums],
|
||||
}
|
||||
|
||||
def _track_to_dict(self, track: Track) -> dict[str, Any]:
|
||||
return self._entity_to_dict(track) | {
|
||||
"artists": [artist.id for artist in track.artists],
|
||||
"album": track.album.id,
|
||||
"duration_ms": track.duration_ms,
|
||||
"added_at": _dt_to_str(track.added_at),
|
||||
"local_path": track.local_path,
|
||||
"has_lyrics": track.has_lyrics,
|
||||
"local_id": track.local_id,
|
||||
"auto_score": track.auto_score,
|
||||
"fav" : track.fav,
|
||||
"rating" : track.rating,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _playlist_to_dict(playlist: Playlist) -> dict[str, Any]:
|
||||
return {
|
||||
"title": playlist.title,
|
||||
def _playlist_to_dict(self, playlist: Playlist) -> dict[str, Any]:
|
||||
return self._entity_to_dict(playlist) | {
|
||||
"tracks": [track.id for track in playlist.tracks],
|
||||
"created_at": _dt_to_str(playlist.created_at),
|
||||
"description": playlist.description,
|
||||
"auto_score": playlist.auto_score,
|
||||
"fav" : playlist.fav,
|
||||
"rating" : playlist.rating,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _album_to_dict(album: Album) -> dict[str, Any]:
|
||||
return {
|
||||
"id": album.id,
|
||||
"title": album.title,
|
||||
"release_date": album.release_date,
|
||||
def _album_to_dict(self ,album: Album) -> dict[str, Any]:
|
||||
return self._entity_to_dict(album) | {
|
||||
"tracks": [track.id for track in album.tracks],
|
||||
"artists": [artist.id for artist in album.artists],
|
||||
"local_id": album.local_id,
|
||||
"auto_score": album.auto_score,
|
||||
"fav" : album.fav,
|
||||
"rating" : album.rating,
|
||||
}
|
||||
|
||||
def save(self, path: Path) -> None:
|
||||
|
|
@ -100,6 +91,7 @@ class LibrarySaver:
|
|||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
|
||||
class LibraryLoader:
|
||||
def __init__(self):
|
||||
self.track_map: dict[str, Track] = {}
|
||||
|
|
@ -127,48 +119,54 @@ class LibraryLoader:
|
|||
self.track_map[id] = item
|
||||
return item
|
||||
|
||||
def load_entity(self, entity : Entity, data: dict[str, Any]):
|
||||
entity.id = data.get("id")
|
||||
entity.mbid = data.get("mbid")
|
||||
|
||||
entity.title = data.get("title")
|
||||
entity.duration_ms = data.get("duration_ms")
|
||||
|
||||
entity.fav = data.get("fav")
|
||||
entity.rating = data.get("rating")
|
||||
entity.play_count = data.get("play_count")
|
||||
entity.date_added = _str_to_dt(data.get("date_added"))
|
||||
entity.date_released = _str_to_dt(data.get("date_released"))
|
||||
entity.date_last_play = _str_to_dt(data.get("date_last_play"))
|
||||
entity.auto_score = data.get("auto_score")
|
||||
|
||||
entity.local_id = data.get("local_id")
|
||||
entity.local_path = data.get("local_path")
|
||||
entity.resolved_percentage = data.get("resolved_percentage")
|
||||
|
||||
|
||||
def load_track(self, data: dict[str, Any]) -> Track:
|
||||
track = self.get_track(data.get("id"))
|
||||
track.id = data.get("id")
|
||||
track.title = data.get("title")
|
||||
self.load_entity(track, data)
|
||||
|
||||
track.duration_ms = data.get("duration_ms")
|
||||
track.added_at = _str_to_dt(data.get("added_at"))
|
||||
track.local_path = data.get("local_path")
|
||||
track.artists = [self.get_artist(artist_id) for artist_id in data.get("artists")]
|
||||
track.album = self.get_album(data.get("album"))
|
||||
track.has_lyrics = data.get("has_lyrics")
|
||||
track.local_id = data.get("local_id")
|
||||
track.auto_score = data.get("auto_score")
|
||||
track.fav = data.get("fav")
|
||||
track.rating = data.get("rating")
|
||||
|
||||
self.track_map[track.id] = track
|
||||
return track
|
||||
|
||||
def load_artist(self, data: dict[str, Any]):
|
||||
artist = self.get_artist(data.get("id"))
|
||||
artist.id = data.get("id")
|
||||
artist.title = data.get("title")
|
||||
self.load_entity(artist, data)
|
||||
|
||||
artist.tracks = [self.get_track(track_id) for track_id in data.get("tracks")]
|
||||
artist.albums = [self.get_album(album_id) for album_id in data.get("albums")] if data.get("albums") else []
|
||||
artist.local_id = data.get("local_id")
|
||||
artist.auto_score = data.get("auto_score")
|
||||
artist.fav = data.get("fav")
|
||||
artist.rating = data.get("rating")
|
||||
|
||||
self.artist_map[artist.id] = artist
|
||||
return artist
|
||||
|
||||
def load_album(self, data: dict[str, Any]):
|
||||
album = self.get_album(data.get("id"))
|
||||
album.id = data.get("id")
|
||||
self.load_entity(album, data)
|
||||
|
||||
album.tracks = [self.get_track(track_id) for track_id in data.get("tracks")]
|
||||
album.title = data.get("title")
|
||||
album.artists = [self.get_artist(artist_id) for artist_id in data.get("artists")]
|
||||
album.local_id = data.get("local_id")
|
||||
album.auto_score = data.get("auto_score")
|
||||
album.fav = data.get("fav")
|
||||
album.rating = data.get("rating")
|
||||
|
||||
self.album_map[album.id] = album
|
||||
return album
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ class ParseItunesXml:
|
|||
track.title = data.get("Name")
|
||||
track.artists = self.parse_artists([data.get("Artist")])
|
||||
track.album = self.parse_album(data.get("Album"))
|
||||
track.play_count = int(data.get("Play Count"))
|
||||
|
||||
if not track.album or not len(track.artists) or not track.title:
|
||||
raise "error parsing"
|
||||
|
|
@ -183,10 +184,9 @@ class ParseItunesXml:
|
|||
|
||||
self.library.name = "Itunes"
|
||||
|
||||
for track in self.library.tracks:
|
||||
track.auto_score = track.play_count
|
||||
|
||||
return self.library
|
||||
|
||||
|
||||
def parse_track_item(self, id, track: dict[str, Any]) -> Track:
|
||||
|
||||
return track
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ class Parser:
|
|||
self.library.name = "Spotify"
|
||||
self.library.auto_score()
|
||||
|
||||
self.score_tracks()
|
||||
|
||||
return self.library
|
||||
|
||||
|
||||
|
|
@ -122,3 +124,8 @@ class Parser:
|
|||
self.library.artists.append(artist)
|
||||
|
||||
return artist
|
||||
|
||||
def score_tracks(self):
|
||||
for idx, track in enumerate(self.library.top_tracks):
|
||||
score = len(self.library.top_tracks) - idx
|
||||
track.auto_score = score
|
||||
Loading…
Add table
Add a link
Reference in a new issue