2023-11-30 20:12:04 +01:00
|
|
|
import click
|
2023-11-26 18:00:57 +01:00
|
|
|
import logging
|
2023-11-30 20:12:04 +01:00
|
|
|
import os
|
2023-11-26 18:00:57 +01:00
|
|
|
import sys
|
2023-12-05 09:15:39 +01:00
|
|
|
import typing as t
|
2023-11-26 18:00:57 +01:00
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
from click.testing import Result
|
2023-11-26 18:00:57 +01:00
|
|
|
from functools import wraps
|
2023-11-28 10:13:20 +01:00
|
|
|
from toot import App, User, config, __version__
|
2023-12-05 10:45:38 +01:00
|
|
|
from toot.settings import load_settings
|
2023-12-05 09:15:39 +01:00
|
|
|
|
|
|
|
if t.TYPE_CHECKING:
|
|
|
|
import typing_extensions as te
|
|
|
|
P = te.ParamSpec("P")
|
|
|
|
|
|
|
|
R = t.TypeVar("R")
|
|
|
|
T = t.TypeVar("T")
|
2023-11-26 18:00:57 +01:00
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
PRIVACY_CHOICES = ["public", "unlisted", "private"]
|
|
|
|
VISIBILITY_CHOICES = ["public", "unlisted", "private", "direct"]
|
|
|
|
|
|
|
|
DURATION_EXAMPLES = """e.g. "1 day", "2 hours 30 minutes", "5 minutes 30
|
|
|
|
seconds" or any combination of above. Shorthand: "1d", "2h30m", "5m30s\""""
|
|
|
|
|
|
|
|
|
|
|
|
# Type alias for run commands
|
2023-12-05 09:15:39 +01:00
|
|
|
Run = t.Callable[..., Result]
|
2023-11-30 20:12:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
def get_default_visibility() -> str:
|
|
|
|
return os.getenv("TOOT_POST_VISIBILITY", "public")
|
|
|
|
|
|
|
|
|
2023-12-05 10:45:38 +01:00
|
|
|
def get_default_map():
|
|
|
|
settings = load_settings()
|
|
|
|
common = settings.get("common", {})
|
|
|
|
commands = settings.get("commands", {})
|
|
|
|
return {**common, **commands}
|
|
|
|
|
|
|
|
|
2023-11-26 18:00:57 +01:00
|
|
|
# Tweak the Click context
|
|
|
|
# https://click.palletsprojects.com/en/8.1.x/api/#context
|
|
|
|
CONTEXT = dict(
|
|
|
|
# Enable using environment variables to set options
|
|
|
|
auto_envvar_prefix="TOOT",
|
|
|
|
# Add shorthand -h for invoking help
|
|
|
|
help_option_names=["-h", "--help"],
|
|
|
|
# Give help some more room (default is 80)
|
|
|
|
max_content_width=100,
|
|
|
|
# Always show default values for options
|
|
|
|
show_default=True,
|
2023-12-05 10:45:38 +01:00
|
|
|
# Load command defaults from settings
|
|
|
|
default_map=get_default_map(),
|
2023-11-26 18:00:57 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Data object to add to Click context
|
2023-12-05 09:15:39 +01:00
|
|
|
class Context(t.NamedTuple):
|
|
|
|
app: t.Optional[App]
|
|
|
|
user: t.Optional[User] = None
|
2023-11-26 18:00:57 +01:00
|
|
|
color: bool = False
|
|
|
|
debug: bool = False
|
|
|
|
quiet: bool = False
|
|
|
|
|
|
|
|
|
2023-12-05 09:15:39 +01:00
|
|
|
def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]":
|
2023-11-26 18:00:57 +01:00
|
|
|
"""Pass `obj` from click context as first argument."""
|
|
|
|
@wraps(f)
|
2023-12-05 09:15:39 +01:00
|
|
|
def wrapped(*args: "P.args", **kwargs: "P.kwargs") -> R:
|
2023-11-26 18:00:57 +01:00
|
|
|
ctx = click.get_current_context()
|
|
|
|
return f(ctx.obj, *args, **kwargs)
|
|
|
|
|
|
|
|
return wrapped
|
|
|
|
|
|
|
|
|
|
|
|
json_option = click.option(
|
|
|
|
"--json",
|
|
|
|
is_flag=True,
|
|
|
|
default=False,
|
|
|
|
help="Print data as JSON rather than human readable text"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@click.group(context_settings=CONTEXT)
|
|
|
|
@click.option("--debug/--no-debug", default=False, help="Log debug info to stderr")
|
|
|
|
@click.option("--color/--no-color", default=sys.stdout.isatty(), help="Use ANSI color in output")
|
|
|
|
@click.option("--quiet/--no-quiet", default=False, help="Don't print anything to stdout")
|
2023-11-28 10:13:20 +01:00
|
|
|
@click.version_option(__version__, message="%(prog)s v%(version)s")
|
2023-11-26 18:00:57 +01:00
|
|
|
@click.pass_context
|
2023-12-05 09:59:40 +01:00
|
|
|
def cli(
|
|
|
|
ctx: click.Context,
|
|
|
|
color: bool,
|
|
|
|
debug: bool,
|
|
|
|
quiet: bool,
|
|
|
|
app: t.Optional[App] = None,
|
|
|
|
user: t.Optional[User] = None,
|
|
|
|
):
|
2023-11-26 18:00:57 +01:00
|
|
|
"""Toot is a Mastodon CLI"""
|
|
|
|
user, app = config.get_active_user_app()
|
|
|
|
ctx.obj = Context(app, user, color, debug, quiet)
|
2023-12-05 09:59:40 +01:00
|
|
|
ctx.color = color
|
2023-11-26 18:00:57 +01:00
|
|
|
|
|
|
|
if debug:
|
|
|
|
logging.basicConfig(level=logging.DEBUG)
|