1
0
mirror of https://github.com/ihabunek/toot synced 2024-12-22 23:08:17 +01:00
Toot-Mastodon-CLI-TUI-clien.../toot/cli/read.py
2024-11-12 09:10:22 +01:00

137 lines
4.2 KiB
Python

import click
import json as pyjson
from itertools import chain
from typing import Optional
from toot import api
from toot.cli.validators import validate_instance
from toot.entities import Instance, Status, from_dict, Account
from toot.exceptions import ApiError, ConsoleError
from toot.output import print_account, print_instance, print_search_results, print_status, print_timeline
from toot.cli import InstanceParamType, cli, get_context, json_option, pass_context, Context
@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()
@click.argument("instance", type=InstanceParamType(), callback=validate_instance, required=False)
@json_option
def instance(instance: Optional[str], json: bool):
"""Display instance details
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
try:
response = api.get_instance(instance)
except ApiError:
raise ConsoleError(
f"Instance not found at {instance}.\n" +
"The given domain probably does not host a Mastodon instance."
)
if json:
click.echo(response.text)
else:
print_instance(from_dict(Instance, response.json()))
@cli.command()
@click.argument("query")
@click.option("-r", "--resolve", is_flag=True, help="Resolve non-local accounts")
@click.option(
"-t", "--type",
type=click.Choice(["accounts", "hashtags", "statuses"]),
help="Limit search to one type only"
)
@click.option("-o", "--offset", type=int, help="Return results starting from (default 0)")
@click.option("-l", "--limit", type=int, help="Maximum number of results to return, per type. (default 20, max 40)")
@click.option("--min-id", help="Return results newer than this ID.")
@click.option("--max-id", help="Return results older than this ID.")
@json_option
@pass_context
def search(
ctx: Context,
query: str,
resolve: bool,
type: Optional[str],
offset: Optional[int],
limit: Optional[int],
min_id: Optional[str],
max_id: Optional[str],
json: bool
):
"""Search for content in accounts, statuses and hashtags."""
response = api.search(ctx.app, ctx.user, query, resolve, type, offset, limit, min_id, max_id)
if json:
click.echo(response.text)
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:
click.echo(response.text)
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:
click.echo(context_response.text)
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)