feat: layed out commit
This commit is contained in:
parent
fc83ba3d23
commit
aec62903e0
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@ -10,5 +10,9 @@
|
|||||||
"test*.py"
|
"test*.py"
|
||||||
],
|
],
|
||||||
"python.testing.pytestEnabled": false,
|
"python.testing.pytestEnabled": false,
|
||||||
"python.testing.unittestEnabled": true
|
"python.testing.unittestEnabled": true,
|
||||||
|
"[python]": {
|
||||||
|
"editor.defaultFormatter": "ms-python.autopep8"
|
||||||
|
},
|
||||||
|
"python.formatting.provider": "none"
|
||||||
}
|
}
|
@ -29,7 +29,8 @@ if __name__ == "__main__":
|
|||||||
]
|
]
|
||||||
|
|
||||||
youtube_music_test = [
|
youtube_music_test = [
|
||||||
"s: psychonaut 4"
|
"s: psychonaut 4",
|
||||||
|
"0"
|
||||||
]
|
]
|
||||||
|
|
||||||
music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True)
|
music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True)
|
||||||
|
@ -3,7 +3,7 @@ import logging
|
|||||||
import gc
|
import gc
|
||||||
import musicbrainzngs
|
import musicbrainzngs
|
||||||
|
|
||||||
from .utils.config import read_config
|
from .utils.old_config import read_config
|
||||||
from .utils.shared import MODIFY_GC
|
from .utils.shared import MODIFY_GC
|
||||||
from . import cli
|
from . import cli
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ def cli():
|
|||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
from . import cli
|
from . import cli
|
||||||
from .utils.config import read_config
|
from .utils.old_config import read_config
|
||||||
from .utils import shared
|
from .utils import shared
|
||||||
|
|
||||||
if arguments.r:
|
if arguments.r:
|
||||||
|
@ -5,7 +5,7 @@ import re
|
|||||||
from .utils import cli_function
|
from .utils import cli_function
|
||||||
from .options.first_config import initial_config
|
from .options.first_config import initial_config
|
||||||
|
|
||||||
from ..utils.config import set_name_to_value, write_config
|
from ..utils.old_config import set_name_to_value, write_config
|
||||||
from ..utils.shared import MUSIC_DIR, NOT_A_GENRE_REGEX, ENABLE_RESULT_HISTORY, HISTORY_LENGTH, HELP_MESSAGE, HASNT_YET_STARTED
|
from ..utils.shared import MUSIC_DIR, NOT_A_GENRE_REGEX, ENABLE_RESULT_HISTORY, HISTORY_LENGTH, HELP_MESSAGE, HASNT_YET_STARTED
|
||||||
from ..utils.regex import URL_PATTERN
|
from ..utils.regex import URL_PATTERN
|
||||||
from ..utils.string_processing import fit_to_file_system
|
from ..utils.string_processing import fit_to_file_system
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from ..utils import cli_function
|
from ..utils import cli_function
|
||||||
|
|
||||||
from ...utils.config import config, write_config
|
from ...utils.old_config import config, write_config
|
||||||
from ...utils import exception
|
from ...utils import exception
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,17 +67,6 @@ class YouTube(SuperYouTube):
|
|||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def get_source_type(self, source: Source) -> Optional[Type[DatabaseObject]]:
|
|
||||||
_url_type = {
|
|
||||||
YouTubeUrlType.CHANNEL: Artist,
|
|
||||||
YouTubeUrlType.PLAYLIST: Album,
|
|
||||||
YouTubeUrlType.VIDEO: Song,
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed = YouTubeUrl(source.url)
|
|
||||||
if parsed.url_type in _url_type:
|
|
||||||
return _url_type[parsed.url_type]
|
|
||||||
|
|
||||||
def general_search(self, search_query: str) -> List[DatabaseObject]:
|
def general_search(self, search_query: str) -> List[DatabaseObject]:
|
||||||
return self.artist_search(Artist(name=search_query, dynamic=True))
|
return self.artist_search(Artist(name=search_query, dynamic=True))
|
||||||
|
|
||||||
|
@ -50,12 +50,17 @@ class YouTubeUrl:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, url: str) -> None:
|
def __init__(self, url: str) -> None:
|
||||||
|
self.SOURCE_TYPE = SourcePages.YOUTUBE
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Raises Index exception for wrong url, and value error for not found enum type
|
Raises Index exception for wrong url, and value error for not found enum type
|
||||||
"""
|
"""
|
||||||
self.id = ""
|
self.id = ""
|
||||||
parsed = urlparse(url=url)
|
parsed = urlparse(url=url)
|
||||||
|
|
||||||
|
if parsed.netloc == "music.youtube.com":
|
||||||
|
self.SOURCE_TYPE = SourcePages.YOUTUBE_MUSIC
|
||||||
|
|
||||||
self.url_type: YouTubeUrlType
|
self.url_type: YouTubeUrlType
|
||||||
|
|
||||||
type_frag_list = parsed.path.split("/")
|
type_frag_list = parsed.path.split("/")
|
||||||
@ -135,6 +140,19 @@ class SuperYouTube(Page):
|
|||||||
_sponsorblock_connection: Connection = Connection(host="https://sponsor.ajay.app/")
|
_sponsorblock_connection: Connection = Connection(host="https://sponsor.ajay.app/")
|
||||||
self.sponsorblock_client = sponsorblock.Client(session=_sponsorblock_connection.session)
|
self.sponsorblock_client = sponsorblock.Client(session=_sponsorblock_connection.session)
|
||||||
|
|
||||||
|
|
||||||
|
def get_source_type(self, source: Source) -> Optional[Type[DatabaseObject]]:
|
||||||
|
_url_type = {
|
||||||
|
YouTubeUrlType.CHANNEL: Artist,
|
||||||
|
YouTubeUrlType.PLAYLIST: Album,
|
||||||
|
YouTubeUrlType.VIDEO: Song,
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed = YouTubeUrl(source.url)
|
||||||
|
if parsed.url_type in _url_type:
|
||||||
|
return _url_type[parsed.url_type]
|
||||||
|
|
||||||
|
|
||||||
def download_song_to_target(self, source: Source, target: Target, desc: str = None) -> DownloadResult:
|
def download_song_to_target(self, source: Source, target: Target, desc: str = None) -> DownloadResult:
|
||||||
"""
|
"""
|
||||||
1. getting the optimal source
|
1. getting the optimal source
|
||||||
|
@ -8,7 +8,7 @@ import re
|
|||||||
|
|
||||||
from ...utils.exception.config import SettingValueError
|
from ...utils.exception.config import SettingValueError
|
||||||
from ...utils.shared import PROXIES_LIST, YOUTUBE_MUSIC_LOGGER, DEBUG
|
from ...utils.shared import PROXIES_LIST, YOUTUBE_MUSIC_LOGGER, DEBUG
|
||||||
from ...utils.config import CONNECTION_SECTION, write_config
|
from ...utils.old_config import CONNECTION_SECTION, write_config
|
||||||
from ...utils.functions import get_current_millis
|
from ...utils.functions import get_current_millis
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
from ...utils.debug_utils import dump_to_file
|
from ...utils.debug_utils import dump_to_file
|
||||||
@ -279,10 +279,13 @@ class YoutubeMusic(SuperYouTube):
|
|||||||
|
|
||||||
|
|
||||||
def fetch_song(self, source: Source, stop_at_level: int = 1) -> Song:
|
def fetch_song(self, source: Source, stop_at_level: int = 1) -> Song:
|
||||||
|
print(source)
|
||||||
return Song()
|
return Song()
|
||||||
|
|
||||||
def fetch_album(self, source: Source, stop_at_level: int = 1) -> Album:
|
def fetch_album(self, source: Source, stop_at_level: int = 1) -> Album:
|
||||||
return Album()
|
return Album()
|
||||||
|
|
||||||
def fetch_artist(self, source: Source, stop_at_level: int = 1) -> Artist:
|
def fetch_artist(self, source: Source, stop_at_level: int = 1) -> Artist:
|
||||||
|
print("fuck you")
|
||||||
|
print(source)
|
||||||
return Artist()
|
return Artist()
|
||||||
|
@ -1 +1 @@
|
|||||||
from .config import config, read_config, write_config
|
from .old_config import config, read_config, write_config
|
||||||
|
17
src/music_kraken/utils/config.py
Normal file
17
src/music_kraken/utils/config.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from dynaconf import Dynaconf
|
||||||
|
|
||||||
|
from .path_manager import LOCATIONS
|
||||||
|
|
||||||
|
"""
|
||||||
|
https://www.dynaconf.com/settings_files/
|
||||||
|
|
||||||
|
This file is there to load the settings.
|
||||||
|
How I will structure this programm exactly is in the stars.
|
||||||
|
|
||||||
|
The concept is that I package a config file, with this programm, and then load it.
|
||||||
|
Then I check if there is a config file at the LOCATIONS.CONFIG_FILE, and if yes they get merged
|
||||||
|
"""
|
||||||
|
|
||||||
|
settings = Dynaconf(
|
||||||
|
settings_files=[str(LOCATIONS.CONFIG_FILE)],
|
||||||
|
)
|
@ -1,10 +1,10 @@
|
|||||||
from .logging import LOGGING_SECTION
|
from .sections.logging import LOGGING_SECTION
|
||||||
from .audio import AUDIO_SECTION
|
from .sections.audio import AUDIO_SECTION
|
||||||
from .connection import CONNECTION_SECTION
|
from .sections.connection import CONNECTION_SECTION
|
||||||
from .misc import MISC_SECTION
|
from .sections.misc import MISC_SECTION
|
||||||
from .paths import PATHS_SECTION
|
from .sections.paths import PATHS_SECTION
|
||||||
|
|
||||||
from .paths import LOCATIONS
|
from .sections.paths import LOCATIONS
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
|
|
60
src/music_kraken/utils/old_config/attributes/attribute.py
Normal file
60
src/music_kraken/utils/old_config/attributes/attribute.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from ...exception.config import SettingValueError
|
||||||
|
from ..utils import comment
|
||||||
|
|
||||||
|
|
||||||
|
class Description:
|
||||||
|
def __init__(self, string: str) -> None:
|
||||||
|
self.string = string
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_string(self) -> str:
|
||||||
|
return comment(self.string)
|
||||||
|
|
||||||
|
|
||||||
|
class Attribute:
|
||||||
|
pattern: str = r'^.*a$'
|
||||||
|
rule: str = "This is a default string, it has no rule."
|
||||||
|
string_value: str = ""
|
||||||
|
|
||||||
|
def __init__(self, name: str, description: str, pattern: str = None, rule: str = None) -> None:
|
||||||
|
if pattern is not None:
|
||||||
|
self.pattern = pattern
|
||||||
|
if rule is not None:
|
||||||
|
self.rule = rule
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
|
||||||
|
def validate(self, input_string: str) -> bool:
|
||||||
|
return re.match(self.REGEX, input_string) is None
|
||||||
|
|
||||||
|
def output_parse(self):
|
||||||
|
return self.string_value.strip()
|
||||||
|
|
||||||
|
def input_parse(self, input_string: str) -> str:
|
||||||
|
match_result = re.match(self.pattern, input_string)
|
||||||
|
|
||||||
|
if match_result is None:
|
||||||
|
raise SettingValueError(
|
||||||
|
setting_name=self.name,
|
||||||
|
setting_value=input_string,
|
||||||
|
rule=self.rule
|
||||||
|
)
|
||||||
|
|
||||||
|
return match_result.string
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_string(self) -> str:
|
||||||
|
return NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
attr = Attribute(name="hello world", description="fuck you", value="defaulte")
|
||||||
|
attr.input_parse("fafda")
|
||||||
|
attr.input_parse("eeee")
|
@ -0,0 +1,34 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
from .attribute import Attribute
|
||||||
|
from ..utils import comment
|
||||||
|
|
||||||
|
|
||||||
|
class ListAttribute(Attribute):
|
||||||
|
def __init__(self, name: str, description: str, value: List[str], pattern: str = None, rule: str = None) -> None:
|
||||||
|
super().__init__(name, description, pattern, rule)
|
||||||
|
|
||||||
|
self.string_value_list = []
|
||||||
|
self.set_to_list(value)
|
||||||
|
|
||||||
|
|
||||||
|
def set_to_list(self, input_value_list: List[str]):
|
||||||
|
self.string_value_list = []
|
||||||
|
for input_value in input_value_list:
|
||||||
|
self.string_value_list.append(input_value)
|
||||||
|
|
||||||
|
def append(self, input_value: str):
|
||||||
|
self.string_value_list.append(self.input_parse(input_value))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> str:
|
||||||
|
return [self.output_parse(element) for element in self.string_value_list]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_string(self) -> str:
|
||||||
|
NEWLINE = "\n"
|
||||||
|
return f"[{self.name}.start]" \
|
||||||
|
f"{comment(self.description)}\n" \
|
||||||
|
f"{NEWLINE.join(self.name+'='+v for v in self.string_value_list)}\n" \
|
||||||
|
f"{comment('RULE: ' + self.rule)}\n" \
|
||||||
|
f"[{self.name}.end]"
|
@ -0,0 +1,18 @@
|
|||||||
|
from ..utils import comment
|
||||||
|
from .attribute import Attribute
|
||||||
|
|
||||||
|
class SingleAttribute(Attribute):
|
||||||
|
def __init__(self, name: str, description: str, value: str, pattern: str = None, rule: str = None) -> None:
|
||||||
|
super().__init__(name, description, pattern, rule)
|
||||||
|
|
||||||
|
self.string_value = self.input_parse(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self) -> str:
|
||||||
|
return self.output_parse(self.string_value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_string(self) -> str:
|
||||||
|
return f"{comment(self.description)}\n" \
|
||||||
|
f"{self.name}={self.value}\n" \
|
||||||
|
f"{comment('RULE: ' + self.rule)}" \
|
@ -6,11 +6,11 @@ import os
|
|||||||
from ..exception.config import SettingNotFound, SettingValueError
|
from ..exception.config import SettingNotFound, SettingValueError
|
||||||
from ..path_manager import LOCATIONS
|
from ..path_manager import LOCATIONS
|
||||||
from .base_classes import Description, Attribute, Section, EmptyLine, COMMENT_PREFIX
|
from .base_classes import Description, Attribute, Section, EmptyLine, COMMENT_PREFIX
|
||||||
from .audio import AUDIO_SECTION
|
from .sections.audio import AUDIO_SECTION
|
||||||
from .logging import LOGGING_SECTION
|
from .sections.logging import LOGGING_SECTION
|
||||||
from .connection import CONNECTION_SECTION
|
from .sections.connection import CONNECTION_SECTION
|
||||||
from .misc import MISC_SECTION
|
from .sections.misc import MISC_SECTION
|
||||||
from .paths import PATHS_SECTION
|
from .sections.paths import PATHS_SECTION
|
||||||
|
|
||||||
|
|
||||||
LOGGER = logging.getLogger("config")
|
LOGGER = logging.getLogger("config")
|
@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from .base_classes import (
|
from ..base_classes import (
|
||||||
SingleAttribute,
|
SingleAttribute,
|
||||||
FloatAttribute,
|
FloatAttribute,
|
||||||
StringAttribute,
|
StringAttribute,
|
||||||
@ -10,8 +10,8 @@ from .base_classes import (
|
|||||||
BoolAttribute,
|
BoolAttribute,
|
||||||
ListAttribute
|
ListAttribute
|
||||||
)
|
)
|
||||||
from ...utils.enums.album import AlbumType
|
from ...enums.album import AlbumType
|
||||||
from ...utils.exception.config import SettingValueError
|
from ...exception.config import SettingValueError
|
||||||
|
|
||||||
# Only the formats with id3 metadata can be used
|
# Only the formats with id3 metadata can be used
|
||||||
# https://www.audioranger.com/audio-formats.php
|
# https://www.audioranger.com/audio-formats.php
|
@ -1,9 +1,9 @@
|
|||||||
from urllib.parse import urlparse, ParseResult
|
from urllib.parse import urlparse, ParseResult
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from .base_classes import Section, FloatAttribute, IntAttribute, BoolAttribute, ListAttribute, StringAttribute
|
from ..base_classes import Section, FloatAttribute, IntAttribute, BoolAttribute, ListAttribute, StringAttribute
|
||||||
from ..regex import URL_PATTERN
|
from ...regex import URL_PATTERN
|
||||||
from ..exception.config import SettingValueError
|
from ...exception.config import SettingValueError
|
||||||
|
|
||||||
|
|
||||||
class ProxAttribute(ListAttribute):
|
class ProxAttribute(ListAttribute):
|
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
from .base_classes import SingleAttribute, StringAttribute, Section, Description, EmptyLine
|
from ..base_classes import SingleAttribute, StringAttribute, Section, Description, EmptyLine
|
||||||
|
|
||||||
LOG_LEVELS = {
|
LOG_LEVELS = {
|
||||||
"CRITICAL": 50,
|
"CRITICAL": 50,
|
@ -1,4 +1,4 @@
|
|||||||
from .base_classes import Section, IntAttribute, ListAttribute, BoolAttribute
|
from ..base_classes import Section, IntAttribute, ListAttribute, BoolAttribute
|
||||||
|
|
||||||
|
|
||||||
class MiscSection(Section):
|
class MiscSection(Section):
|
@ -1,7 +1,7 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ..path_manager import LOCATIONS
|
from ...path_manager import LOCATIONS
|
||||||
from .base_classes import Section, StringAttribute, ListAttribute
|
from ..base_classes import Section, StringAttribute, ListAttribute
|
||||||
|
|
||||||
|
|
||||||
class PathAttribute(StringAttribute):
|
class PathAttribute(StringAttribute):
|
4
src/music_kraken/utils/old_config/utils.py
Normal file
4
src/music_kraken/utils/old_config/utils.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
def comment(uncommented_string: str) -> str:
|
||||||
|
_fragments = uncommented_string.split("\n")
|
||||||
|
_fragments = ["# " + frag for frag in _fragments]
|
||||||
|
return "\n".join(_fragments)
|
@ -19,7 +19,8 @@ class Locations:
|
|||||||
|
|
||||||
self.CONFIG_DIRECTORY = get_config_directory(str(application_name))
|
self.CONFIG_DIRECTORY = get_config_directory(str(application_name))
|
||||||
self.CONFIG_DIRECTORY.mkdir(exist_ok=True, parents=True)
|
self.CONFIG_DIRECTORY.mkdir(exist_ok=True, parents=True)
|
||||||
self.CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.conf")
|
self.CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.toml")
|
||||||
|
self.LEGACY_CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.conf")
|
||||||
|
|
||||||
self.FFMPEG_BIN = Path(FFmpeg(enable_log=False).get_ffmpeg_bin())
|
self.FFMPEG_BIN = Path(FFmpeg(enable_log=False).get_ffmpeg_bin())
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
URL_PATTERN = 'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
|
URL_PATTERN = r"https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+"
|
||||||
|
INT_PATTERN = r"^\d*$"
|
||||||
|
FLOAT_PATTERN = r"^[\d|\,|\.]*$"
|
||||||
|
@ -5,7 +5,7 @@ from typing import List, Tuple, Set, Dict
|
|||||||
from urllib.parse import ParseResult
|
from urllib.parse import ParseResult
|
||||||
|
|
||||||
from .path_manager import LOCATIONS
|
from .path_manager import LOCATIONS
|
||||||
from .config import LOGGING_SECTION, AUDIO_SECTION, CONNECTION_SECTION, MISC_SECTION, PATHS_SECTION
|
from .old_config import LOGGING_SECTION, AUDIO_SECTION, CONNECTION_SECTION, MISC_SECTION, PATHS_SECTION
|
||||||
from .enums.album import AlbumType
|
from .enums.album import AlbumType
|
||||||
|
|
||||||
CONFIG_FILE = LOCATIONS.CONFIG_FILE
|
CONFIG_FILE = LOCATIONS.CONFIG_FILE
|
||||||
|
@ -33,3 +33,10 @@ def fit_to_file_system(string: str) -> str:
|
|||||||
string = sanitize_filename(string)
|
string = sanitize_filename(string)
|
||||||
|
|
||||||
return string
|
return string
|
||||||
|
|
||||||
|
|
||||||
|
def comment(uncommented_string: str) -> str:
|
||||||
|
_fragments = uncommented_string.split("\n")
|
||||||
|
_fragments = ["# " + frag for frag in _fragments]
|
||||||
|
return "\n".join(_fragments)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user