added better default targets

This commit is contained in:
Hellow2 2023-04-03 10:38:12 +02:00
parent 376bbf2fa2
commit c05199d928
3 changed files with 113 additions and 44 deletions

View File

@ -3,6 +3,8 @@ from typing import Optional, Union, Type, Dict, List
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import requests import requests
import logging import logging
from dataclasses import dataclass
from copy import copy
from ..utils import shared from ..utils import shared
from ..objects import ( from ..objects import (
@ -19,9 +21,34 @@ from ..objects import (
Label Label
) )
from ..tagging import write_metadata_to_target from ..tagging import write_metadata_to_target
from ..utils.shared import DOWNLOAD_PATH, DOWNLOAD_FILE, DEFAULT_VALUES
LOGGER = logging.getLogger("this shouldn't be used") LOGGER = logging.getLogger("this shouldn't be used")
@dataclass
class DefaultTarget:
genre: str = DEFAULT_VALUES["genre"]
label: str = DEFAULT_VALUES["label"]
artist: str = DEFAULT_VALUES["artist"]
album: str = DEFAULT_VALUES["album"]
song: str = DEFAULT_VALUES["song"]
def __setattr__(self, __name: str, __value: str) -> None:
if __name in DEFAULT_VALUES:
if self.__getattribute__(__name) == DEFAULT_VALUES[__name]:
super().__setattr__(__name, __value)
return
super().__setattr__(__name, __value)
@property
def target(self) -> Target:
return Target(
relative_to_music_dir=True,
path=DOWNLOAD_PATH.format(genre=self.genre, label=self.label, artist=self.artist, album=self.album, song=self.song),
file=DOWNLOAD_FILE.format(genre=self.genre, label=self.label, artist=self.artist, album=self.album, song=self.song)
)
class Page: class Page:
""" """
@ -283,56 +310,80 @@ class Page:
cls._clean_collection(song.main_artist_collection, collections) cls._clean_collection(song.main_artist_collection, collections)
@classmethod @classmethod
def download(cls, music_object: Union[Song, Album, Artist, Label], download_features: bool = True): def download(
print("downloading") cls,
print(music_object) music_object: Union[Song, Album, Artist, Label],
download_features: bool = True,
default_target: DefaultTarget = None
):
if default_target is None:
default_target = DefaultTarget()
if type(music_object) is Song: if type(music_object) is Song:
return cls.download_song(music_object) return cls.download_song(music_object, default_target)
if type(music_object) is Album: if type(music_object) is Album:
return cls.download_album(music_object) return cls.download_album(music_object, default_target)
if type(music_object) is Artist: if type(music_object) is Artist:
return cls.download_artist(music_object, download_features=download_features) return cls.download_artist(music_object, default_target)
if type(music_object) is Label: if type(music_object) is Label:
return cls.download_label(music_object, download_features=download_features) return cls.download_label(music_object, download_features=download_features, default_target=default_target)
@classmethod @classmethod
def download_label(cls, label: Label, download_features: bool = True, override_existing: bool = False): def download_label(cls, label: Label, download_features: bool = True, override_existing: bool = False, default_target: DefaultTarget = None):
if default_target is None:
default_target = DefaultTarget()
else:
default_target = copy(default_target)
default_target.label = label.name
cls.fetch_details(label) cls.fetch_details(label)
for artist in label.current_artist_collection: for artist in label.current_artist_collection:
cls.download_artist(artist, download_features=download_features, override_existing=override_existing) cls.download_artist(artist, download_features=download_features, override_existing=override_existing, default_target=default_target)
for album in label.album_collection: for album in label.album_collection:
cls.download_album(album, override_existing=override_existing) cls.download_album(album, override_existing=override_existing, default_target=default_target)
@classmethod @classmethod
def download_artist(cls, artist: Artist, download_features: bool = True, override_existing: bool = False): def download_artist(cls, artist: Artist, download_features: bool = True, override_existing: bool = False, default_target: DefaultTarget = None):
if default_target is None:
default_target = DefaultTarget()
else:
default_target = copy(default_target)
default_target.artist = artist.name
cls.fetch_details(artist) cls.fetch_details(artist)
for album in artist.main_album_collection: for album in artist.main_album_collection:
cls.download_album(album, override_existing=override_existing) cls.download_album(album, override_existing=override_existing, default_target=default_target)
if download_features: if download_features:
for song in artist.feature_album.song_collection: for song in artist.feature_album.song_collection:
cls.download_song(song, override_existing=override_existing) cls.download_song(song, override_existing=override_existing, default_target=default_target)
@classmethod @classmethod
def download_album(cls, album: Album, override_existing: bool = False): def download_album(cls, album: Album, override_existing: bool = False, default_target: DefaultTarget = None):
if default_target is None:
default_target = DefaultTarget()
else:
default_target = copy(default_target)
default_target.album = album.title
cls.fetch_details(album) cls.fetch_details(album)
for song in album.song_collection: for song in album.song_collection:
cls.download_song(song, override_existing=override_existing) cls.download_song(song, override_existing=override_existing, default_target=default_target)
@classmethod @classmethod
def download_song(cls, song: Song, override_existing: bool = False, create_target_on_demand: bool = True): def download_song(cls, song: Song, override_existing: bool = False, create_target_on_demand: bool = True, default_target: DefaultTarget = None):
if default_target is None:
default_target = DefaultTarget()
else:
default_target = copy(default_target)
default_target.song = song.title
cls.fetch_details(song) cls.fetch_details(song)
if song.target_collection.empty: if song.target_collection.empty:
if create_target_on_demand and not song.main_artist_collection.empty and not song.album_collection.empty: if create_target_on_demand and not song.main_artist_collection.empty and not song.album_collection.empty:
song.target_collection.append( song.target_collection.append(default_target.target)
Target(
file=f"{song.title}.mp3",
relative_to_music_dir=True,
path=f"{song.main_artist_collection[0].name}/{song.album_collection[0].title}"
)
)
else: else:
return return

View File

@ -10,8 +10,7 @@ from pathlib import Path
import random import random
from ..utils.shared import ( from ..utils.shared import (
ENCYCLOPAEDIA_METALLUM_LOGGER as LOGGER, ENCYCLOPAEDIA_METALLUM_LOGGER as LOGGER
TEMP_FOLDER
) )
from .abstract import Page from .abstract import Page
@ -864,7 +863,7 @@ class Musify(Page):
:param source: :param source:
:return: :return:
""" """
album = Album(title="Hi :)") album = Album(title="Hi :)", source_list=[source])
url = cls.parse_url(source.url) url = cls.parse_url(source.url)
@ -881,6 +880,14 @@ class Musify(Page):
card_soup: BeautifulSoup card_soup: BeautifulSoup
for card_soup in cards_soup.find_all("div", {"class": "playlist__item"}): for card_soup in cards_soup.find_all("div", {"class": "playlist__item"}):
album.song_collection.append(cls.parse_song_card(card_soup)) album.song_collection.append(cls.parse_song_card(card_soup))
if stop_at_level > 1:
song: Song
for song in album.song_collection:
sources = song.source_collection.get_sources_from_page(cls.SOURCE_TYPE)
for source in sources:
song.merge(cls._fetch_song_from_source(source=source))
album.update_tracksort() album.update_tracksort()
return album return album

View File

@ -4,18 +4,13 @@ import tempfile
import os import os
import configparser import configparser
from sys import platform as current_os from sys import platform as current_os
from pathlib import Path
TEMP_FOLDER = "music-downloader"
LOG_FILE = "download_logs.log" LOG_FILE = "download_logs.log"
TEMP_DATABASE_FILE = "metadata.db" TEMP_DATABASE_FILE = "metadata.db"
DATABASE_STRUCTURE_FILE = "database_structure.sql" TEMP_DIR = Path(tempfile.gettempdir(), "music-downloader")
DATABASE_STRUCTURE_FALLBACK = "https://raw.githubusercontent.com/HeIIow2/music-downloader/master/assets/database_structure.sql" TEMP_DIR.mkdir(exist_ok=True)
TEMP_DIR = os.path.join(tempfile.gettempdir(), TEMP_FOLDER)
if not os.path.exists(TEMP_DIR):
os.mkdir(TEMP_DIR)
TEMP_DATABASE_PATH = os.path.join(TEMP_DIR, TEMP_DATABASE_FILE)
# configure logger default # configure logger default
logging.basicConfig( logging.basicConfig(
@ -33,18 +28,17 @@ INIT_PATH_LOGGER = logging.getLogger("init_path")
DATABASE_LOGGER = logging.getLogger("database") DATABASE_LOGGER = logging.getLogger("database")
METADATA_DOWNLOAD_LOGGER = logging.getLogger("metadata") METADATA_DOWNLOAD_LOGGER = logging.getLogger("metadata")
URL_DOWNLOAD_LOGGER = logging.getLogger("AudioSource") URL_DOWNLOAD_LOGGER = logging.getLogger("AudioSource")
TAGGING_LOGGER = logging.getLogger("tagging")
YOUTUBE_LOGGER = logging.getLogger("Youtube") YOUTUBE_LOGGER = logging.getLogger("Youtube")
MUSIFY_LOGGER = logging.getLogger("Musify") MUSIFY_LOGGER = logging.getLogger("Musify")
PATH_LOGGER = logging.getLogger("create-paths") PATH_LOGGER = logging.getLogger("create-paths")
DOWNLOAD_LOGGER = logging.getLogger("download") DOWNLOAD_LOGGER = logging.getLogger("download")
LYRICS_LOGGER = logging.getLogger("lyrics") LYRICS_LOGGER = logging.getLogger("lyrics")
GENIUS_LOGGER = logging.getLogger("genius") GENIUS_LOGGER = logging.getLogger("genius")
TAGGING_LOGGER = logging.getLogger("tagging")
ENCYCLOPAEDIA_METALLUM_LOGGER = logging.getLogger("ma") ENCYCLOPAEDIA_METALLUM_LOGGER = logging.getLogger("ma")
NOT_A_GENRE = ".", "..", "misc_scripts", "Music", "script", ".git", ".idea" NOT_A_GENRE = ".", "..", "misc_scripts", "Music", "script", ".git", ".idea"
MUSIC_DIR = os.path.join(os.path.expanduser("~"), "Music") MUSIC_DIR = Path(os.path.expanduser("~"), "Music")
if current_os == "linux": if current_os == "linux":
# XDG_USER_DIRS_FILE reference: https://freedesktop.org/wiki/Software/xdg-user-dirs/ # XDG_USER_DIRS_FILE reference: https://freedesktop.org/wiki/Software/xdg-user-dirs/
@ -58,17 +52,34 @@ if current_os == "linux":
config.read_string(data) config.read_string(data)
xdg_config = config['XDG_USER_DIRS'] xdg_config = config['XDG_USER_DIRS']
MUSIC_DIR = os.path.expandvars(xdg_config['xdg_music_dir'].strip('"')) MUSIC_DIR = os.path.expandvars(xdg_config['xdg_music_dir'].strip('"'))
except (FileNotFoundError, KeyError) as E: except (FileNotFoundError, KeyError) as E:
logger.warning(f''' logger.warning(
Missing file or No entry found for "xdg_music_dir" in: \'{XDG_USER_DIRS_FILE}\'. f"Missing file or No entry found for \"xdg_music_dir\" in: \"{XDG_USER_DIRS_FILE}\".\n" \
Will fallback on default '$HOME/Music'. f"Will fallback on default \"$HOME/Music\"."
---- )
''')
TOR = False TOR = False
proxies = { proxies = {
'http': 'socks5h://127.0.0.1:9150', 'http': 'socks5h://127.0.0.1:9150',
'https': 'socks5h://127.0.0.1:9150' 'https': 'socks5h://127.0.0.1:9150'
} if TOR else {} } if TOR else {}
# only the sources here will get downloaded, in the order the list is ordered
AUDIO_SOURCES = ["Musify", "Youtube"] """
available variables:
- genre
- label
- artist
- album
- song
"""
DOWNLOAD_PATH = "{genre}/{artist}/{album}"
DOWNLOAD_FILE = "{song}.mp3"
DEFAULT_VALUES = {
"genre": "Various Genre",
"label": "Various Labels",
"artist": "Various Artists",
"album": "Various Album",
"song": "Various Song",
}