grooveondemand/groove/cli.py

182 lines
4.6 KiB
Python
Raw Normal View History

2022-12-21 23:40:09 -08:00
import io
import logging
import os
2022-12-21 21:16:06 -08:00
import sys
import typer
2022-11-20 16:26:40 -08:00
from pathlib import Path
2022-12-06 16:34:58 -08:00
from typing import Optional
2022-12-21 21:16:06 -08:00
from textwrap import dedent
from dotenv import load_dotenv
2022-12-21 21:16:06 -08:00
from rich import print
2022-12-21 15:17:13 -08:00
from rich.logging import RichHandler
2022-11-20 01:00:54 -08:00
2022-12-21 21:16:06 -08:00
import groove.path
2022-11-30 00:09:23 -08:00
from groove.shell import interactive_shell
2022-11-20 09:28:00 -08:00
from groove.db.manager import database_manager
2022-12-02 21:43:51 -08:00
from groove.webserver import webserver
2022-12-21 21:16:06 -08:00
from groove.exceptions import ConfigurationError
from groove.console import Console
2022-12-21 22:27:30 -08:00
SETUP_HELP = """
2022-12-21 23:40:09 -08:00
# Please make sure you set MEDIA_ROOT and SECRET_KEY in your environment.
# By default, Groove on Demand will attempt to load these variables from
# ~/.groove/defaults, which may contain the following variables as well. See
# also the --root paramter.
2022-12-21 22:27:30 -08:00
# Set this one. The path containing your media files
MEDIA_ROOT=
# the kinds of files to import
2022-12-21 23:40:09 -08:00
MEDIA_GLOB=*.mp3,*.flac,*.m4a
2022-12-21 22:27:30 -08:00
# If defined, transcode media before streaming it, and cache it to disk. The
# strings INFILE and OUTFILE will be replaced with the media source file and
# the cached output location, respectively.
#
TRANSCODER=/usr/bin/ffmpeg -i INFILE -c:v libvpx-vp9 -crf 30 -b:v 0 -b:a 256k -c:a libopus OUTFILE
# where to cache transcoded media files
CACHE_ROOT=~/.groove/cache
2022-12-21 22:27:30 -08:00
# where to store the groove_on_demand.db sqlite database.
2022-12-21 23:40:09 -08:00
DATABASE_PATH=~
2022-12-21 22:27:30 -08:00
# Try 'groove themes' to see a list of available themes.
2022-12-21 23:40:09 -08:00
DEFAULT_THEME=blue_train
2022-12-21 22:27:30 -08:00
# Web interface configuration
2022-12-21 23:40:09 -08:00
HOST=127.0.0.1
PORT=2323
2022-12-21 22:27:30 -08:00
# Set this to a suitably random string.
2022-12-21 23:40:09 -08:00
SECRET_KEY=
2022-12-21 22:27:30 -08:00
# Console configuration
2022-12-21 23:40:09 -08:00
EDITOR=vim
CONSOLE_WIDTH=auto
2022-12-21 22:27:30 -08:00
"""
app = typer.Typer()
2022-12-21 21:16:06 -08:00
@app.callback()
def main(
context: typer.Context,
root: Optional[Path] = typer.Option(
2022-12-21 21:16:06 -08:00
Path('~/.groove'),
help="Path to the Groove on Demand environment",
)
):
load_dotenv(root.expanduser() / Path('defaults'))
2022-12-21 23:40:09 -08:00
load_dotenv(stream=io.StringIO(SETUP_HELP))
2022-11-20 09:28:00 -08:00
debug = os.getenv('DEBUG', None)
2022-12-21 15:17:13 -08:00
logging.basicConfig(
format='%(message)s',
level=logging.DEBUG if debug else logging.INFO,
handlers=[
RichHandler(rich_tracebacks=True, tracebacks_suppress=[typer])
]
)
logging.getLogger('asyncio').setLevel(logging.ERROR)
2022-11-20 01:00:54 -08:00
2022-12-21 21:16:06 -08:00
try:
groove.path.media_root()
groove.path.static_root()
groove.path.themes_root()
groove.path.database()
except ConfigurationError as e:
2022-12-21 22:27:30 -08:00
sys.stderr.write(f'{e}\n\n{SETUP_HELP}')
2022-12-21 21:16:06 -08:00
sys.exit(1)
@app.command()
def setup(context: typer.Context):
"""
(Re)Initialize Groove on Demand.
"""
2022-12-21 23:40:09 -08:00
sys.stderr.write("Interactive setup is not yet available. Sorry!\n")
print(dedent(SETUP_HELP))
2022-12-21 21:16:06 -08:00
2022-11-20 01:00:54 -08:00
2022-12-21 15:17:13 -08:00
@app.command()
2022-12-21 21:16:06 -08:00
def themes(context: typer.Context):
"""
2022-12-21 21:16:06 -08:00
List the available themes.
"""
print("Available themes:")
themes = [theme for theme in groove.path.themes_root().iterdir()]
tags = ('artist', 'title', 'bold', 'dim', 'link', 'prompt', 'bright', 'text', 'help')
for theme in themes:
text = ''
for tag in tags:
text += f'[{tag}]◼◼◼◼◼◼'
Console(theme=theme.name).print(f' ▪ [title]{theme.name}[/title] {text}')
@app.command()
def playlists(context: typer.Context):
"""
List all playlists
"""
with database_manager() as manager:
2022-12-21 15:17:13 -08:00
shell = interactive_shell.InteractiveShell(manager)
shell.list(None)
2022-11-20 16:26:40 -08:00
@app.command()
def scan(
2022-12-21 21:16:06 -08:00
context: typer.Context,
2022-12-21 15:17:13 -08:00
path: Optional[Path] = typer.Option(
'',
help="A path to scan, relative to your MEDIA_ROOT. "
"If not specified, the entire MEDIA_ROOT will be scanned."
2022-11-20 16:26:40 -08:00
),
):
"""
Scan the filesystem and create track entries in the database.
"""
with database_manager() as manager:
2022-12-21 15:17:13 -08:00
shell = interactive_shell.InteractiveShell(manager)
shell.console.print("Starting the Groove on Demand scanner...")
shell.scan([str(path)])
2022-11-27 18:42:46 -08:00
@app.command()
2022-12-21 21:16:06 -08:00
def shell(context: typer.Context):
"""
Start the Groove on Demand interactive shell.
"""
with database_manager() as manager:
interactive_shell.InteractiveShell(manager).start()
2022-11-20 16:26:40 -08:00
@app.command()
def server(
2022-12-21 21:16:06 -08:00
context: typer.Context,
host: str = typer.Argument(
'0.0.0.0',
help="bind address",
),
port: int = typer.Argument(
2323,
help="bind port",
),
debug: bool = typer.Option(
False,
help='Enable debugging output'
),
):
"""
Start the Groove on Demand playlsit server.
"""
2022-11-20 16:26:40 -08:00
with database_manager() as manager:
2022-11-20 09:28:00 -08:00
manager.import_from_filesystem()
webserver.start(host=host, port=port, debug=debug)
if __name__ == '__main__':
app()