Compare commits
No commits in common. "e53e50b5d23d46d3f55723ff09487dae9c39687f" and "ed2eeabd6a964f7ede8eb4f93562267ed228a756" have entirely different histories.
e53e50b5d2
...
ed2eeabd6a
@ -5,7 +5,21 @@ from ..__meta__ import DESCRIPTION, PROGRAMM
|
|||||||
from ..download import Downloader
|
from ..download import Downloader
|
||||||
from ..utils import BColors
|
from ..utils import BColors
|
||||||
from ..utils.string_processing import unify
|
from ..utils.string_processing import unify
|
||||||
from .utils import HELP_MESSAGE, ask_for_bool, ask_for_create
|
from .utils import ask_for_bool, ask_for_create
|
||||||
|
|
||||||
|
|
||||||
|
class Selection:
|
||||||
|
def __init__(self, options: list):
|
||||||
|
self.options = options
|
||||||
|
|
||||||
|
def pprint(self):
|
||||||
|
return "\n".join(f"{i}: {option}" for i, option in enumerate(self.options))
|
||||||
|
|
||||||
|
def choose(self, input_: str):
|
||||||
|
try:
|
||||||
|
return self.options[int(input_)]
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentCli:
|
class DevelopmentCli:
|
||||||
@ -53,30 +67,11 @@ class DevelopmentCli:
|
|||||||
return genre
|
return genre
|
||||||
|
|
||||||
|
|
||||||
def help_screen(self) -> None:
|
|
||||||
print(HELP_MESSAGE)
|
|
||||||
|
|
||||||
def shell(self) -> None:
|
|
||||||
print(f"Welcome to the {PROGRAMM} shell!")
|
|
||||||
print(f"Type '{BColors.OKBLUE}help{BColors.ENDC}' for a list of commands.")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
while True:
|
|
||||||
i = input("> ")
|
|
||||||
if i == "help":
|
|
||||||
self.help_screen()
|
|
||||||
elif i == "genre":
|
|
||||||
self.genre
|
|
||||||
elif i == "exit":
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
print("Unknown command. Type 'help' for a list of commands.")
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog=PROGRAMM,
|
prog=PROGRAMM,
|
||||||
description=DESCRIPTION,
|
description=DESCRIPTION,
|
||||||
epilog='This is just a development cli. The real frontend is coming soon.'
|
epilog='This is just a development cli. The real frontend is coming soon.'
|
||||||
)
|
)
|
||||||
parser.add_argument('--genre', '-g', action='store_const', required=False, help="choose a genre to download from")
|
parser.add_argument('--genre', '-g', action='store_const')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
53
music_kraken/development_cli/genre.py
Normal file
53
music_kraken/development_cli/genre.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Generator, List, Set, Type, Union
|
||||||
|
|
||||||
|
from ..download import Downloader, Page, components
|
||||||
|
from ..utils.config import main_settings
|
||||||
|
from .utils import ask_for_bool, cli_function
|
||||||
|
|
||||||
|
|
||||||
|
class GenreIO(components.HumanIO):
|
||||||
|
@staticmethod
|
||||||
|
def ask_to_create(option: components.Option) -> bool:
|
||||||
|
output()
|
||||||
|
return ask_for_bool(f"create the genre {BColors.OKBLUE.value}{option.value}{BColors.ENDC.value}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def not_found(key: str) -> None:
|
||||||
|
output(f"\ngenre {BColors.BOLD.value}{key}{BColors.ENDC.value} not found\n", color=BColors.FAIL)
|
||||||
|
|
||||||
|
|
||||||
|
def _genre_generator() -> Generator[str, None, None]:
|
||||||
|
def is_valid_genre(genre: Path) -> bool:
|
||||||
|
"""
|
||||||
|
gets the name of all subdirectories of shared.MUSIC_DIR,
|
||||||
|
but filters out all directories, where the name matches with any Patern
|
||||||
|
from shared.NOT_A_GENRE_REGEX.
|
||||||
|
"""
|
||||||
|
if not genre.is_dir():
|
||||||
|
return False
|
||||||
|
|
||||||
|
if any(re.match(regex_pattern, genre.name) for regex_pattern in main_settings["not_a_genre_regex"]):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
for genre in filter(is_valid_genre, main_settings["music_directory"].iterdir()):
|
||||||
|
yield genre.name
|
||||||
|
|
||||||
|
def get_genre() -> str:
|
||||||
|
select_genre = components.Select(
|
||||||
|
human_io=GenreIO,
|
||||||
|
can_create_options=True,
|
||||||
|
data=_genre_generator(),
|
||||||
|
)
|
||||||
|
genre: Optional[components.Option[str]] = None
|
||||||
|
|
||||||
|
while genre is None:
|
||||||
|
print(select_genre.pprint())
|
||||||
|
print()
|
||||||
|
|
||||||
|
genre = select_genre.choose(input("> "))
|
||||||
|
|
||||||
|
return genre.value
|
@ -40,44 +40,10 @@ def print_cute_message():
|
|||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
|
|
||||||
def highlight_placeholder(text: str) -> str:
|
AGREE_INPUTS = {"y", "yes", "ok"}
|
||||||
return text.replace("<", f"{BColors.BOLD}<").replace(">", f">{BColors.ENDC}")
|
|
||||||
|
|
||||||
|
|
||||||
HELP_MESSAGE = highlight_placeholder(f"""{BColors.HEADER}To search:{BColors.ENDC}
|
|
||||||
> s: <query/url>
|
|
||||||
> s: https://musify.club/release/some-random-release-183028492
|
|
||||||
> s: #a <artist> #r <release> #t <track>
|
|
||||||
|
|
||||||
If you found the same object twice from different sources you can merge those objects.
|
|
||||||
Then it will use those sources. To do so, use the {BColors.BOLD}m{BColors.ENDC} command.
|
|
||||||
|
|
||||||
{BColors.HEADER}To download:{BColors.ENDC}
|
|
||||||
> d: <id/url>
|
|
||||||
> dm: 0, 3, 4 # merge all objects into one and download this object
|
|
||||||
> d: 1
|
|
||||||
> d: https://musify.club/release/some-random-release-183028492
|
|
||||||
|
|
||||||
{BColors.HEADER}To inspect an object:{BColors.ENDC}
|
|
||||||
If you inspect an object, you see its adjacent object. This means for example the releases of an artist, or the tracks of a release.
|
|
||||||
You can also merge objects with the {BColors.BOLD}m{BColors.ENDC} command here.
|
|
||||||
|
|
||||||
> g: <id/url>
|
|
||||||
> gm: 0, 3, 4 # merge all objects into one and inspect this object
|
|
||||||
> g: 1
|
|
||||||
> g: https://musify.club/release/some-random-release-183028492""")
|
|
||||||
|
|
||||||
|
|
||||||
class COMMANDS:
|
|
||||||
AGREE = {"y", "yes", "ok"}
|
|
||||||
DISAGREE = {"n", "no"}
|
|
||||||
EXIT = {"exit"}
|
|
||||||
HELP = {"help", "h"}
|
|
||||||
|
|
||||||
|
|
||||||
def ask_for_bool(msg: str) -> bool:
|
def ask_for_bool(msg: str) -> bool:
|
||||||
i = input(f"{msg} ({BColors.OKGREEN.value}Y{BColors.ENDC.value}/{BColors.FAIL.value}N{BColors.ENDC.value})? ").lower()
|
i = input(f"{msg} ({BColors.OKGREEN.value}Y{BColors.ENDC.value}/{BColors.FAIL.value}N{BColors.ENDC.value})? ").lower()
|
||||||
return i in COMMANDS.AGREE
|
return i in AGREE_INPUTS
|
||||||
|
|
||||||
|
|
||||||
def ask_for_create(name: str, value: str) -> bool:
|
def ask_for_create(name: str, value: str) -> bool:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
class BColors:
|
class BColors(Enum):
|
||||||
# https://stackoverflow.com/a/287944
|
# https://stackoverflow.com/a/287944
|
||||||
HEADER = "\033[95m"
|
HEADER = "\033[95m"
|
||||||
OKBLUE = "\033[94m"
|
OKBLUE = "\033[94m"
|
||||||
|
Loading…
Reference in New Issue
Block a user