diff --git a/src/goof.py b/src/goof.py index a0d2899..4a136ff 100644 --- a/src/goof.py +++ b/src/goof.py @@ -1,6 +1,7 @@ import music_kraken as mk print(mk.__file__) +""" mk.clear_cache() song_list = mk.cache.get_custom_track([]) print(mk.cache, len(song_list)) @@ -14,4 +15,5 @@ print(song.length) mk.set_targets(genre="test") song = mk.cache.get_track_metadata(musicbrainz_releasetrackid=id_) -mk.fetch_sources([song]) +""" +mk.fetch_audios(mk.cache.get_tracks_to_download()) diff --git a/src/music_kraken/audio_source/sources/source.py b/src/music_kraken/audio_source/sources/source.py index a8e4e1f..9883866 100644 --- a/src/music_kraken/audio_source/sources/source.py +++ b/src/music_kraken/audio_source/sources/source.py @@ -16,7 +16,7 @@ calling of the functions do search for a song and to download it. class AudioSource: @classmethod def fetch_source(cls, row: dict): - logger.info(f"try getting source {row['title']} from {cls.__name__}") + logger.info(f"try getting source {row.title} from {cls.__name__}") @classmethod def fetch_audio(cls, song: song_objects.Song, src: song_objects.Source): diff --git a/src/music_kraken/database/database.py b/src/music_kraken/database/database.py index 6c7a9cf..6f7bce4 100644 --- a/src/music_kraken/database/database.py +++ b/src/music_kraken/database/database.py @@ -7,6 +7,7 @@ import requests from pkg_resources import resource_string from . import song +from .get_song import get_song_from_response from ..utils.shared import ( DATABASE_LOGGER ) @@ -194,7 +195,7 @@ GROUP BY track.id; def get_custom_track(self, custom_where: list) -> List[song.Song]: query = Database.get_custom_track_query(custom_where=custom_where) - return [song.Song(json.loads(i[0])) for i in self.cursor.execute(query)] + return [get_song_from_response(json.loads(i[0])) for i in self.cursor.execute(query)] def get_track_metadata(self, musicbrainz_releasetrackid: str): # this would be vulnerable if musicbrainz_releasetrackid would be user input diff --git a/src/music_kraken/database/song.py b/src/music_kraken/database/song.py index 0ff906a..bc1284c 100644 --- a/src/music_kraken/database/song.py +++ b/src/music_kraken/database/song.py @@ -5,109 +5,6 @@ from .metadata import Metadata from .source import Source from .target import Target -# I don't import cache from the db module because it would lead to circular imports -# from .temp_database import temp_database as cache -# from . import cache - - - -class Song: - def __init__( - self, - json_response: dict, - ) -> None: - """ - id: is not NECESARRILY the musicbrainz id, but is DISTINCT for every song - mb_id: is the musicbrainz_id - target: Each Song can have exactly one target which can be either full or empty - lyrics: There can be multiple lyrics. Each Lyrics object can me added to multiple lyrics - """ - # attributes - self.id: str | None = None - self.mb_id: str | None = None - self.title: str | None = None - self.isrc: str | None = None - self.length: int | None = None - - self.metadata: Metadata = Metadata() - # joins - self.artists: List[Artist] = [] - self.lyrics: LyricsContainer = LyricsContainer(parent=self) - - self.sources: List[Source] = [] - self.target: Target = Target() - - self.json_data = json_response - - # initialize the data - self.id = self.json_data['id'] - self.title = self.json_data['title'] - self.artists = [] - for a in self.json_data['artists']: - new_artist = Artist(a) - exists = False - for existing_artist in self.artists: - if new_artist == existing_artist: - exists = True - break - if not exists: - self.artists.append(new_artist) - self.isrc = self.json_data['isrc'] - - # initialize the sources - self.sources: List[Source] = [] - for src in self.json_data['source']: - if src['src'] is None: - continue - self.sources.append(Source(src)) - - # initialize the target - self.target = Target() - self.target.file = self.json_data['file'] - self.target.path = self.json_data['path'] - - # initialize id3 metadata - self.metadata = Metadata() - for key, value in self.json_data.items(): - self.metadata[key] = value - self.metadata['artist'] = self.get_artist_names() - - self.length = self.json_data['length'] - # EasyID3.valid_keys.keys() - - # the lyrics are not in the metadata class because the field isn't supported - # by easyid3 - self.lyrics: LyricsContainer = LyricsContainer(parent=self) - - def __str__(self) -> str: - return f"\"{self.title}\" by {', '.join([str(a) for a in self.artists])}" - - def __repr__(self) -> str: - return self.__str__() - - def get_metadata(self): - return self.metadata.get_all_metadata() - - def has_isrc(self) -> bool: - return self.isrc is not None - - def get_artist_names(self) -> List[str]: - return [a.name for a in self.artists] - - def __getitem__(self, item): - if item not in self.json_data: - return None - return self.json_data[item] - - def __setitem__(self, item, value): - if item == "file": - self.target.file = value - return - if item == "path": - self.target.path = value - return - - self.json_data[item] = value class Lyrics: @@ -117,11 +14,9 @@ class Lyrics: class LyricsContainer: - def __init__(self, parent: Song): + def __init__(self): self.lyrics_list: List[Lyrics] = [] - self.parent = parent - def append(self, lyrics: Lyrics): # due to my db not supporting multiple Lyrics yet, I just use for doing stuff with the lyrics # the first element. I know this implementation is junk, but take it or leave it, it is going @@ -141,3 +36,69 @@ class LyricsContainer: is_empty = property(fget=lambda self: len(self.lyrics_list) <= 0) + +class Song: + def __init__( + self, + id_: str = None, + mb_id: str = None, + title: str = None, + release: str = None, + isrc: str = None, + length: int = None, + artists: List[Artist] = None, + metadata: Metadata = None, + sources: List[Source] = None, + target: Target = None, + lyrics: LyricsContainer = None + ) -> None: + """ + id: is not NECESARRILY the musicbrainz id, but is DISTINCT for every song + mb_id: is the musicbrainz_id + target: Each Song can have exactly one target which can be either full or empty + lyrics: There can be multiple lyrics. Each Lyrics object can me added to multiple lyrics + """ + # attributes + self.id: str | None = id_ + self.mb_id: str | None = mb_id + self.title: str | None = title + self.release: str | None = release + self.isrc: str | None = isrc + self.length: int | None = length + + if metadata is None: + metadata = Metadata() + self.metadata: Metadata = metadata + + # joins + if artists is None: + artists = [] + self.artists: List[Artist] = artists + + if sources is None: + sources = [] + self.sources: List[Source] = sources + + if target is None: + target = Target() + self.target: Target = target + + if lyrics is None: + lyrics = LyricsContainer() + self.lyrics: LyricsContainer = lyrics + + + def __str__(self) -> str: + return f"\"{self.title}\" by {', '.join([str(a) for a in self.artists])}" + + def __repr__(self) -> str: + return self.__str__() + + def get_metadata(self): + return self.metadata.get_all_metadata() + + def has_isrc(self) -> bool: + return self.isrc is not None + + def get_artist_names(self) -> List[str]: + return [a.name for a in self.artists] diff --git a/src/music_kraken/target/set_target.py b/src/music_kraken/target/set_target.py index 745e07d..e61187c 100644 --- a/src/music_kraken/target/set_target.py +++ b/src/music_kraken/target/set_target.py @@ -22,22 +22,22 @@ class UrlPath: self.genre = genre - for row in temp_database.get_tracks_without_filepath(): - # print(row) - file, path = self.get_path_from_row(row) + for song in temp_database.get_tracks_without_filepath(): + # print(song) + file, path = self.get_path_from_song(song) logger.info(f"setting target to {file}") - temp_database.set_filepath(row['id'], file, path, genre) + temp_database.set_filepath(song.id, file, path, genre) - def get_path_from_row(self, row): + def get_path_from_song(self, song): """ genre/artist/song.mp3 - :param row: + :param song: :return: path: """ - return os.path.join(self.get_genre(), self.get_artist(row), self.get_album(row), - f"{self.get_song(row)}.mp3"), os.path.join(self.get_genre(), self.get_artist(row), - self.get_album(row)) + return os.path.join(self.get_genre(), self.get_artist(song), self.get_album(song), + f"{self.get_song(song)}.mp3"), os.path.join(self.get_genre(), self.get_artist(song), + self.get_album(song)) @staticmethod def escape_part(part: str): @@ -46,15 +46,15 @@ class UrlPath: def get_genre(self): return self.escape_part(self.genre) - def get_album(self, row): - return self.escape_part(row['album']) + def get_album(self, song): + return self.escape_part(song.release) - def get_artist(self, row): - artists = [artist['name'] for artist in row['artists']] + def get_artist(self, song): + artists = song.get_artist_names() return self.escape_part(artists[0]) - def get_song(self, row): - return self.escape_part(row['title']) + def get_song(self, song): + return self.escape_part(song.title) if __name__ == "__main__":