2023-11-26 18:00:57 +01:00
|
|
|
import click
|
|
|
|
import json as pyjson
|
|
|
|
|
|
|
|
from itertools import chain
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
from toot import api
|
2023-12-05 10:18:34 +01:00
|
|
|
from toot.cli.validators import validate_instance
|
2023-11-26 18:00:57 +01:00
|
|
|
from toot.entities import Instance, Status, from_dict, Account
|
|
|
|
from toot.exceptions import ApiError, ConsoleError
|
2023-12-05 09:25:02 +01:00
|
|
|
from toot.output import print_account, print_instance, print_search_results, print_status, print_timeline
|
2023-12-28 19:02:19 +01:00
|
|
|
from toot.cli import InstanceParamType, cli, get_context, json_option, pass_context, Context
|
2023-11-26 18:00:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@json_option
|
|
|
|
@pass_context
|
|
|
|
def whoami(ctx: Context, json: bool):
|
|
|
|
"""Display logged in user details"""
|
|
|
|
response = api.verify_credentials(ctx.app, ctx.user)
|
|
|
|
|
|
|
|
if json:
|
|
|
|
click.echo(response.text)
|
|
|
|
else:
|
|
|
|
account = from_dict(Account, response.json())
|
|
|
|
print_account(account)
|
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.argument("account")
|
|
|
|
@json_option
|
|
|
|
@pass_context
|
|
|
|
def whois(ctx: Context, account: str, json: bool):
|
|
|
|
"""Display account details"""
|
|
|
|
account_dict = api.find_account(ctx.app, ctx.user, account)
|
|
|
|
|
|
|
|
# Here it's not possible to avoid parsing json since it's needed to find the account.
|
|
|
|
if json:
|
|
|
|
click.echo(pyjson.dumps(account_dict))
|
|
|
|
else:
|
|
|
|
account_obj = from_dict(Account, account_dict)
|
|
|
|
print_account(account_obj)
|
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
2023-12-28 19:02:19 +01:00
|
|
|
@click.argument("instance", type=InstanceParamType(), callback=validate_instance, required=False)
|
2023-11-26 18:00:57 +01:00
|
|
|
@json_option
|
2023-12-14 13:04:05 +01:00
|
|
|
def instance(instance: Optional[str], json: bool):
|
|
|
|
"""Display instance details
|
2023-11-26 18:00:57 +01:00
|
|
|
|
2023-12-14 13:04:05 +01:00
|
|
|
INSTANCE can be a domain or base URL of the instance to display.
|
|
|
|
e.g. 'mastodon.social' or 'https://mastodon.social'. If not
|
|
|
|
given will display details for the currently logged in instance.
|
|
|
|
"""
|
|
|
|
if not instance:
|
|
|
|
context = get_context()
|
|
|
|
if not context.app:
|
|
|
|
raise click.ClickException("INSTANCE argument not given and not logged in")
|
|
|
|
instance = context.app.base_url
|
2023-11-26 18:00:57 +01:00
|
|
|
|
|
|
|
try:
|
2023-12-14 13:04:05 +01:00
|
|
|
response = api.get_instance(instance)
|
2023-11-26 18:00:57 +01:00
|
|
|
except ApiError:
|
|
|
|
raise ConsoleError(
|
2023-12-14 13:04:05 +01:00
|
|
|
f"Instance not found at {instance}.\n" +
|
2023-11-26 18:00:57 +01:00
|
|
|
"The given domain probably does not host a Mastodon instance."
|
|
|
|
)
|
|
|
|
|
|
|
|
if json:
|
2023-12-13 15:32:08 +01:00
|
|
|
click.echo(response.text)
|
2023-11-26 18:00:57 +01:00
|
|
|
else:
|
2023-12-14 13:04:05 +01:00
|
|
|
print_instance(from_dict(Instance, response.json()))
|
2023-11-26 18:00:57 +01:00
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.argument("query")
|
|
|
|
@click.option("-r", "--resolve", is_flag=True, help="Resolve non-local accounts")
|
|
|
|
@json_option
|
|
|
|
@pass_context
|
|
|
|
def search(ctx: Context, query: str, resolve: bool, json: bool):
|
2023-12-03 07:07:18 +01:00
|
|
|
"""Search for users or hashtags"""
|
2023-11-26 18:00:57 +01:00
|
|
|
response = api.search(ctx.app, ctx.user, query, resolve)
|
|
|
|
if json:
|
2023-12-13 15:32:08 +01:00
|
|
|
click.echo(response.text)
|
2023-11-26 18:00:57 +01:00
|
|
|
else:
|
|
|
|
print_search_results(response.json())
|
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.argument("status_id")
|
|
|
|
@json_option
|
|
|
|
@pass_context
|
|
|
|
def status(ctx: Context, status_id: str, json: bool):
|
|
|
|
"""Show a single status"""
|
|
|
|
response = api.fetch_status(ctx.app, ctx.user, status_id)
|
|
|
|
if json:
|
2023-12-13 15:32:08 +01:00
|
|
|
click.echo(response.text)
|
2023-11-26 18:00:57 +01:00
|
|
|
else:
|
|
|
|
status = from_dict(Status, response.json())
|
|
|
|
print_status(status)
|
|
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
|
|
@click.argument("status_id")
|
|
|
|
@json_option
|
|
|
|
@pass_context
|
|
|
|
def thread(ctx: Context, status_id: str, json: bool):
|
|
|
|
"""Show thread for a toot."""
|
|
|
|
context_response = api.context(ctx.app, ctx.user, status_id)
|
|
|
|
if json:
|
2023-12-13 15:32:08 +01:00
|
|
|
click.echo(context_response.text)
|
2023-11-26 18:00:57 +01:00
|
|
|
else:
|
|
|
|
toot = api.fetch_status(ctx.app, ctx.user, status_id).json()
|
|
|
|
context = context_response.json()
|
|
|
|
|
|
|
|
statuses = chain(context["ancestors"], [toot], context["descendants"])
|
|
|
|
print_timeline(from_dict(Status, s) for s in statuses)
|