refactored Song object. I hooooope it works
This commit is contained in:
parent
ddf19c4716
commit
12c453e005
@ -1,6 +1,7 @@
|
|||||||
import music_kraken as mk
|
import music_kraken as mk
|
||||||
print(mk.__file__)
|
print(mk.__file__)
|
||||||
|
|
||||||
|
"""
|
||||||
mk.clear_cache()
|
mk.clear_cache()
|
||||||
song_list = mk.cache.get_custom_track([])
|
song_list = mk.cache.get_custom_track([])
|
||||||
print(mk.cache, len(song_list))
|
print(mk.cache, len(song_list))
|
||||||
@ -14,4 +15,5 @@ print(song.length)
|
|||||||
mk.set_targets(genre="test")
|
mk.set_targets(genre="test")
|
||||||
|
|
||||||
song = mk.cache.get_track_metadata(musicbrainz_releasetrackid=id_)
|
song = mk.cache.get_track_metadata(musicbrainz_releasetrackid=id_)
|
||||||
mk.fetch_sources([song])
|
"""
|
||||||
|
mk.fetch_audios(mk.cache.get_tracks_to_download())
|
||||||
|
@ -16,7 +16,7 @@ calling of the functions do search for a song and to download it.
|
|||||||
class AudioSource:
|
class AudioSource:
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch_source(cls, row: dict):
|
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
|
@classmethod
|
||||||
def fetch_audio(cls, song: song_objects.Song, src: song_objects.Source):
|
def fetch_audio(cls, song: song_objects.Song, src: song_objects.Source):
|
||||||
|
@ -7,6 +7,7 @@ import requests
|
|||||||
from pkg_resources import resource_string
|
from pkg_resources import resource_string
|
||||||
|
|
||||||
from . import song
|
from . import song
|
||||||
|
from .get_song import get_song_from_response
|
||||||
from ..utils.shared import (
|
from ..utils.shared import (
|
||||||
DATABASE_LOGGER
|
DATABASE_LOGGER
|
||||||
)
|
)
|
||||||
@ -194,7 +195,7 @@ GROUP BY track.id;
|
|||||||
|
|
||||||
def get_custom_track(self, custom_where: list) -> List[song.Song]:
|
def get_custom_track(self, custom_where: list) -> List[song.Song]:
|
||||||
query = Database.get_custom_track_query(custom_where=custom_where)
|
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):
|
def get_track_metadata(self, musicbrainz_releasetrackid: str):
|
||||||
# this would be vulnerable if musicbrainz_releasetrackid would be user input
|
# this would be vulnerable if musicbrainz_releasetrackid would be user input
|
||||||
|
@ -5,109 +5,6 @@ from .metadata import Metadata
|
|||||||
from .source import Source
|
from .source import Source
|
||||||
from .target import Target
|
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:
|
class Lyrics:
|
||||||
@ -117,11 +14,9 @@ class Lyrics:
|
|||||||
|
|
||||||
|
|
||||||
class LyricsContainer:
|
class LyricsContainer:
|
||||||
def __init__(self, parent: Song):
|
def __init__(self):
|
||||||
self.lyrics_list: List[Lyrics] = []
|
self.lyrics_list: List[Lyrics] = []
|
||||||
|
|
||||||
self.parent = parent
|
|
||||||
|
|
||||||
def append(self, lyrics: Lyrics):
|
def append(self, lyrics: Lyrics):
|
||||||
# due to my db not supporting multiple Lyrics yet, I just use for doing stuff with the 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
|
# 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)
|
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]
|
||||||
|
@ -22,22 +22,22 @@ class UrlPath:
|
|||||||
|
|
||||||
self.genre = genre
|
self.genre = genre
|
||||||
|
|
||||||
for row in temp_database.get_tracks_without_filepath():
|
for song in temp_database.get_tracks_without_filepath():
|
||||||
# print(row)
|
# print(song)
|
||||||
file, path = self.get_path_from_row(row)
|
file, path = self.get_path_from_song(song)
|
||||||
logger.info(f"setting target to {file}")
|
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
|
genre/artist/song.mp3
|
||||||
|
|
||||||
:param row:
|
:param song:
|
||||||
:return: path:
|
:return: path:
|
||||||
"""
|
"""
|
||||||
return 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(row)}.mp3"), os.path.join(self.get_genre(), self.get_artist(row),
|
f"{self.get_song(song)}.mp3"), os.path.join(self.get_genre(), self.get_artist(song),
|
||||||
self.get_album(row))
|
self.get_album(song))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def escape_part(part: str):
|
def escape_part(part: str):
|
||||||
@ -46,15 +46,15 @@ class UrlPath:
|
|||||||
def get_genre(self):
|
def get_genre(self):
|
||||||
return self.escape_part(self.genre)
|
return self.escape_part(self.genre)
|
||||||
|
|
||||||
def get_album(self, row):
|
def get_album(self, song):
|
||||||
return self.escape_part(row['album'])
|
return self.escape_part(song.release)
|
||||||
|
|
||||||
def get_artist(self, row):
|
def get_artist(self, song):
|
||||||
artists = [artist['name'] for artist in row['artists']]
|
artists = song.get_artist_names()
|
||||||
return self.escape_part(artists[0])
|
return self.escape_part(artists[0])
|
||||||
|
|
||||||
def get_song(self, row):
|
def get_song(self, song):
|
||||||
return self.escape_part(row['title'])
|
return self.escape_part(song.title)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
Reference in New Issue
Block a user