2017-04-15 14:53:08 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
2017-04-14 16:41:09 +02:00
|
|
|
|
2019-08-22 17:10:37 +02:00
|
|
|
import logging
|
2018-01-14 15:34:41 +01:00
|
|
|
import os
|
2019-08-22 17:10:37 +02:00
|
|
|
import shutil
|
2017-04-12 16:42:04 +02:00
|
|
|
import sys
|
|
|
|
|
2019-02-13 14:15:47 +01:00
|
|
|
from argparse import ArgumentParser, FileType, ArgumentTypeError
|
2017-04-19 14:47:30 +02:00
|
|
|
from collections import namedtuple
|
2018-06-12 12:22:16 +02:00
|
|
|
from toot import config, commands, CLIENT_NAME, CLIENT_WEBSITE, __version__
|
2017-12-30 13:32:52 +01:00
|
|
|
from toot.exceptions import ApiError, ConsoleError
|
2017-05-08 09:09:20 +02:00
|
|
|
from toot.output import print_out, print_err
|
2017-04-18 16:40:26 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
VISIBILITY_CHOICES = ['public', 'unlisted', 'private', 'direct']
|
2017-04-18 16:40:26 +02:00
|
|
|
|
|
|
|
|
2019-07-30 16:13:29 +02:00
|
|
|
def language(value):
|
|
|
|
"""Validates the language parameter"""
|
|
|
|
if len(value) != 3:
|
|
|
|
raise ArgumentTypeError(
|
|
|
|
"Invalid language specified: '{}'. Expected a 3 letter "
|
|
|
|
"abbreviation according to ISO 639-2 standard.".format(value)
|
|
|
|
)
|
|
|
|
|
|
|
|
return value
|
|
|
|
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
def visibility(value):
|
2019-07-30 16:13:29 +02:00
|
|
|
"""Validates the visibility parameter"""
|
2017-04-19 14:47:30 +02:00
|
|
|
if value not in VISIBILITY_CHOICES:
|
|
|
|
raise ValueError("Invalid visibility value")
|
2017-04-18 16:40:26 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
return value
|
2017-04-18 16:40:26 +02:00
|
|
|
|
|
|
|
|
2019-02-13 14:15:47 +01:00
|
|
|
def timeline_count(value):
|
|
|
|
n = int(value)
|
|
|
|
if not 0 < n <= 20:
|
|
|
|
raise ArgumentTypeError("Number of toots should be between 1 and 20.")
|
|
|
|
return n
|
|
|
|
|
|
|
|
|
2019-08-22 17:10:37 +02:00
|
|
|
def editor(value):
|
|
|
|
if not value:
|
|
|
|
raise ArgumentTypeError(
|
|
|
|
"Editor not specified in --editor option and $EDITOR environment "
|
|
|
|
"variable not set."
|
|
|
|
)
|
|
|
|
|
|
|
|
# Check editor executable exists
|
|
|
|
exe = shutil.which(value)
|
|
|
|
if not exe:
|
2019-08-29 12:46:00 +02:00
|
|
|
raise ArgumentTypeError("Editor `{}` not found".format(value))
|
2019-08-22 17:10:37 +02:00
|
|
|
|
|
|
|
return exe
|
|
|
|
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
Command = namedtuple("Command", ["name", "description", "require_auth", "arguments"])
|
|
|
|
|
|
|
|
|
2020-01-02 10:34:00 +01:00
|
|
|
# Arguments added to every command
|
2017-05-08 09:09:20 +02:00
|
|
|
common_args = [
|
|
|
|
(["--no-color"], {
|
|
|
|
"help": "don't use ANSI colors in output",
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
2017-08-26 15:12:32 +02:00
|
|
|
}),
|
2018-06-15 09:02:19 +02:00
|
|
|
(["--quiet"], {
|
|
|
|
"help": "don't write to stdout on success",
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
|
|
|
}),
|
2017-08-26 15:12:32 +02:00
|
|
|
(["--debug"], {
|
|
|
|
"help": "show debug log in console",
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
2018-06-30 09:44:36 +02:00
|
|
|
}),
|
|
|
|
]
|
|
|
|
|
|
|
|
# Arguments added to commands which require authentication
|
|
|
|
common_auth_args = [
|
|
|
|
(["-u", "--using"], {
|
|
|
|
"help": "the account to use, overrides active account",
|
|
|
|
}),
|
2017-05-08 09:09:20 +02:00
|
|
|
]
|
|
|
|
|
2017-04-26 11:49:21 +02:00
|
|
|
account_arg = (["account"], {
|
2018-01-02 10:44:32 +01:00
|
|
|
"help": "account name, e.g. 'Gargron@mastodon.social'",
|
2017-04-26 11:49:21 +02:00
|
|
|
})
|
|
|
|
|
2017-08-26 14:39:53 +02:00
|
|
|
instance_arg = (["-i", "--instance"], {
|
|
|
|
"type": str,
|
|
|
|
"help": 'mastodon instance to log into e.g. "mastodon.social"',
|
|
|
|
})
|
|
|
|
|
|
|
|
email_arg = (["-e", "--email"], {
|
|
|
|
"type": str,
|
|
|
|
"help": 'email address to log in with',
|
|
|
|
})
|
|
|
|
|
2018-12-25 02:20:30 +01:00
|
|
|
scheme_arg = (["--disable-https"], {
|
|
|
|
"help": "disable HTTPS and use insecure HTTP",
|
|
|
|
"dest": "scheme",
|
|
|
|
"default": "https",
|
|
|
|
"action": "store_const",
|
|
|
|
"const": "http",
|
|
|
|
})
|
|
|
|
|
2019-01-02 12:24:38 +01:00
|
|
|
status_id_arg = (["status_id"], {
|
|
|
|
"help": "ID of the status",
|
2020-09-06 14:00:02 +02:00
|
|
|
"type": str,
|
2019-01-02 12:24:38 +01:00
|
|
|
})
|
2017-04-26 11:49:21 +02:00
|
|
|
|
2019-02-15 14:06:47 +01:00
|
|
|
# Arguments for selecting a timeline (see `toot.commands.get_timeline_generator`)
|
2019-04-23 14:12:29 +02:00
|
|
|
common_timeline_args = [
|
2019-02-15 14:06:47 +01:00
|
|
|
(["-p", "--public"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "show public timeline (does not require auth)",
|
|
|
|
}),
|
|
|
|
(["-t", "--tag"], {
|
|
|
|
"type": str,
|
|
|
|
"help": "show hashtag timeline (does not require auth)",
|
|
|
|
}),
|
|
|
|
(["-l", "--local"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "show only statuses from local instance (public and tag timelines only)",
|
|
|
|
}),
|
|
|
|
(["-i", "--instance"], {
|
|
|
|
"type": str,
|
|
|
|
"help": "mastodon instance from which to read (public and tag timelines only)",
|
|
|
|
}),
|
|
|
|
(["--list"], {
|
2020-09-06 14:00:02 +02:00
|
|
|
"type": str,
|
2019-02-15 14:06:47 +01:00
|
|
|
"help": "show timeline for given list.",
|
|
|
|
}),
|
2019-04-23 14:12:29 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
timeline_args = common_timeline_args + [
|
2019-02-15 14:06:47 +01:00
|
|
|
(["-c", "--count"], {
|
|
|
|
"type": timeline_count,
|
|
|
|
"help": "number of toots to show per page (1-20, default 10).",
|
|
|
|
"default": 10,
|
|
|
|
}),
|
2019-04-23 14:12:29 +02:00
|
|
|
(["-r", "--reverse"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "Reverse the order of the shown timeline (to new posts at the bottom)",
|
|
|
|
}),
|
|
|
|
(["-1", "--once"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "Only show the first <count> toots, do not prompt to continue.",
|
|
|
|
}),
|
2019-02-15 14:06:47 +01:00
|
|
|
]
|
|
|
|
|
2017-04-26 12:11:52 +02:00
|
|
|
AUTH_COMMANDS = [
|
2017-04-19 14:47:30 +02:00
|
|
|
Command(
|
|
|
|
name="login",
|
2018-06-15 09:39:28 +02:00
|
|
|
description="Log into a mastodon instance using your browser (recommended)",
|
2018-12-25 02:20:30 +01:00
|
|
|
arguments=[instance_arg, scheme_arg],
|
2017-08-26 14:39:53 +02:00
|
|
|
require_auth=False,
|
|
|
|
),
|
|
|
|
Command(
|
2018-06-15 09:39:28 +02:00
|
|
|
name="login_cli",
|
|
|
|
description="Log in from the console, does NOT support two factor authentication",
|
2018-12-25 02:20:30 +01:00
|
|
|
arguments=[instance_arg, email_arg, scheme_arg],
|
2018-01-02 10:44:32 +01:00
|
|
|
require_auth=False,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="activate",
|
|
|
|
description="Switch between logged in accounts.",
|
|
|
|
arguments=[account_arg],
|
2017-04-19 14:47:30 +02:00
|
|
|
require_auth=False,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="logout",
|
|
|
|
description="Log out, delete stored access keys",
|
2018-01-02 10:44:32 +01:00
|
|
|
arguments=[account_arg],
|
2017-04-19 14:47:30 +02:00
|
|
|
require_auth=False,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="auth",
|
2018-01-02 10:44:32 +01:00
|
|
|
description="Show logged in accounts and instances",
|
2017-04-19 14:47:30 +02:00
|
|
|
arguments=[],
|
|
|
|
require_auth=False,
|
|
|
|
),
|
2017-04-26 12:11:52 +02:00
|
|
|
]
|
|
|
|
|
2019-08-29 13:44:06 +02:00
|
|
|
TUI_COMMANDS = [
|
|
|
|
Command(
|
|
|
|
name="tui",
|
|
|
|
description="Launches the toot terminal user interface",
|
|
|
|
arguments=[],
|
2020-01-02 10:21:58 +01:00
|
|
|
require_auth=True,
|
2019-08-29 13:44:06 +02:00
|
|
|
),
|
|
|
|
]
|
|
|
|
|
2019-02-15 14:06:47 +01:00
|
|
|
|
2017-04-26 12:11:52 +02:00
|
|
|
READ_COMMANDS = [
|
2017-04-19 14:47:30 +02:00
|
|
|
Command(
|
|
|
|
name="whoami",
|
|
|
|
description="Display logged in user details",
|
|
|
|
arguments=[],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2017-04-19 15:29:40 +02:00
|
|
|
Command(
|
|
|
|
name="whois",
|
2017-04-26 12:11:52 +02:00
|
|
|
description="Display account details",
|
2017-04-19 15:29:40 +02:00
|
|
|
arguments=[
|
|
|
|
(["account"], {
|
|
|
|
"help": "account name or numeric ID"
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2019-02-17 14:03:11 +01:00
|
|
|
Command(
|
|
|
|
name="notifications",
|
|
|
|
description="Notifications for logged in user",
|
2019-02-17 14:18:51 +01:00
|
|
|
arguments=[
|
|
|
|
(["--clear"], {
|
|
|
|
"help": "delete all notifications from the server",
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
|
|
|
}),
|
2020-05-11 13:49:00 +02:00
|
|
|
(["-r", "--reverse"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "Reverse the order of the shown notifications (newest on top)",
|
|
|
|
}),
|
2021-07-28 04:26:51 +02:00
|
|
|
(["-m", "--mentions"], {
|
|
|
|
"action": "store_true",
|
|
|
|
"default": False,
|
|
|
|
"help": "Only print mentions",
|
|
|
|
})
|
2019-02-17 14:18:51 +01:00
|
|
|
],
|
2019-02-17 14:03:11 +01:00
|
|
|
require_auth=True,
|
|
|
|
),
|
2017-12-29 14:26:40 +01:00
|
|
|
Command(
|
|
|
|
name="instance",
|
|
|
|
description="Display instance details",
|
|
|
|
arguments=[
|
|
|
|
(["instance"], {
|
|
|
|
"help": "instance domain (e.g. 'mastodon.social') or blank to use current",
|
|
|
|
"nargs": "?",
|
|
|
|
}),
|
2018-12-30 09:53:12 +01:00
|
|
|
scheme_arg,
|
2017-12-29 14:26:40 +01:00
|
|
|
],
|
|
|
|
require_auth=False,
|
|
|
|
),
|
2017-04-26 12:11:52 +02:00
|
|
|
Command(
|
|
|
|
name="search",
|
|
|
|
description="Search for users or hashtags",
|
|
|
|
arguments=[
|
|
|
|
(["query"], {
|
|
|
|
"help": "the search query",
|
|
|
|
}),
|
|
|
|
(["-r", "--resolve"], {
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
|
|
|
"help": "Resolve non-local accounts",
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2019-01-19 18:38:17 +01:00
|
|
|
Command(
|
|
|
|
name="thread",
|
2019-01-21 17:25:20 +01:00
|
|
|
description="Show toot thread items",
|
2019-01-19 18:38:17 +01:00
|
|
|
arguments=[
|
|
|
|
(["status_id"], {
|
|
|
|
"help": "Show thread for toot.",
|
|
|
|
}),
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2017-04-26 12:11:52 +02:00
|
|
|
Command(
|
|
|
|
name="timeline",
|
2018-06-12 10:40:36 +02:00
|
|
|
description="Show recent items in a timeline (home by default)",
|
2019-04-23 14:12:29 +02:00
|
|
|
arguments=timeline_args,
|
2017-04-26 12:11:52 +02:00
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
|
|
|
|
POST_COMMANDS = [
|
2017-04-19 14:47:30 +02:00
|
|
|
Command(
|
|
|
|
name="post",
|
|
|
|
description="Post a status text to your timeline",
|
|
|
|
arguments=[
|
|
|
|
(["text"], {
|
|
|
|
"help": "The status text to post.",
|
2017-12-30 16:42:52 +01:00
|
|
|
"nargs": "?",
|
2017-04-19 14:47:30 +02:00
|
|
|
}),
|
|
|
|
(["-m", "--media"], {
|
2019-08-01 12:56:21 +02:00
|
|
|
"action": "append",
|
|
|
|
"type": FileType("rb"),
|
|
|
|
"help": "path to the media file to attach (specify multiple "
|
|
|
|
"times to attach up to 4 files)"
|
2017-04-19 14:47:30 +02:00
|
|
|
}),
|
2021-08-26 17:54:31 +02:00
|
|
|
(["-d", "--description"], {
|
|
|
|
"action": "append",
|
|
|
|
"type": str,
|
|
|
|
"help": "plain-text description of the media for accessibility "
|
|
|
|
"purposes, one per attached media"
|
|
|
|
}),
|
2017-04-19 14:47:30 +02:00
|
|
|
(["-v", "--visibility"], {
|
|
|
|
"type": visibility,
|
|
|
|
"default": "public",
|
|
|
|
"help": 'post visibility, one of: %s' % ", ".join(VISIBILITY_CHOICES),
|
2018-06-07 10:04:50 +02:00
|
|
|
}),
|
|
|
|
(["-s", "--sensitive"], {
|
|
|
|
"action": 'store_true',
|
|
|
|
"default": False,
|
|
|
|
"help": "mark the media as NSFW",
|
|
|
|
}),
|
|
|
|
(["-p", "--spoiler-text"], {
|
|
|
|
"type": str,
|
2019-07-30 16:13:29 +02:00
|
|
|
"help": "text to be shown as a warning before the actual content",
|
2018-06-13 12:43:31 +02:00
|
|
|
}),
|
|
|
|
(["-r", "--reply-to"], {
|
2020-09-01 16:09:29 +02:00
|
|
|
"type": str,
|
2019-07-30 16:13:29 +02:00
|
|
|
"help": "local ID of the status you want to reply to",
|
|
|
|
}),
|
|
|
|
(["-l", "--language"], {
|
|
|
|
"type": language,
|
|
|
|
"help": "ISO 639-2 language code of the toot, to skip automatic detection",
|
2018-06-13 12:43:31 +02:00
|
|
|
}),
|
2019-08-22 17:10:37 +02:00
|
|
|
(["-e", "--editor"], {
|
|
|
|
"type": editor,
|
|
|
|
"nargs": "?",
|
|
|
|
"const": os.getenv("EDITOR", ""), # option given without value
|
|
|
|
"help": "Specify an editor to compose your toot, "
|
|
|
|
"defaults to editor defined in $EDITOR env variable.",
|
|
|
|
}),
|
2021-01-17 12:42:08 +01:00
|
|
|
(["--scheduled-at"], {
|
|
|
|
"type": str,
|
|
|
|
"help": "ISO 8601 Datetime at which to schedule a status. Must "
|
|
|
|
"be at least 5 minutes in the future.",
|
|
|
|
}),
|
2021-08-28 21:08:44 +02:00
|
|
|
(["-t", "--content-type"], {
|
|
|
|
"type": str,
|
|
|
|
"help": "MIME type for the status text (not supported on all instances)",
|
|
|
|
}),
|
2017-04-19 14:47:30 +02:00
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="upload",
|
|
|
|
description="Upload an image or video file",
|
|
|
|
arguments=[
|
|
|
|
(["file"], {
|
|
|
|
"help": "Path to the file to upload",
|
|
|
|
"type": FileType('rb')
|
2021-08-26 17:54:31 +02:00
|
|
|
}),
|
|
|
|
(["-d", "--description"], {
|
|
|
|
"type": str,
|
|
|
|
"help": "plain-text description of the media for accessibility purposes"
|
|
|
|
}),
|
2017-04-19 14:47:30 +02:00
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2019-01-02 12:24:38 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
STATUS_COMMANDS = [
|
2018-06-14 10:40:16 +02:00
|
|
|
Command(
|
|
|
|
name="delete",
|
2019-01-02 12:24:38 +01:00
|
|
|
description="Delete a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="favourite",
|
|
|
|
description="Favourite a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unfavourite",
|
|
|
|
description="Unfavourite a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="reblog",
|
|
|
|
description="Reblog a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unreblog",
|
|
|
|
description="Unreblog a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2019-01-24 09:36:25 +01:00
|
|
|
Command(
|
|
|
|
name="reblogged_by",
|
|
|
|
description="Show accounts that reblogged the status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=False,
|
|
|
|
),
|
2019-01-02 12:24:38 +01:00
|
|
|
Command(
|
|
|
|
name="pin",
|
|
|
|
description="Pin a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unpin",
|
|
|
|
description="Unpin a status",
|
|
|
|
arguments=[status_id_arg],
|
2018-06-14 10:40:16 +02:00
|
|
|
require_auth=True,
|
|
|
|
),
|
2022-11-17 06:28:41 +01:00
|
|
|
Command(
|
|
|
|
name="bookmark",
|
|
|
|
description="Bookmark a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unbookmark",
|
|
|
|
description="Unbookmark a status",
|
|
|
|
arguments=[status_id_arg],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2017-04-26 12:11:52 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
ACCOUNTS_COMMANDS = [
|
2017-04-19 14:47:30 +02:00
|
|
|
Command(
|
|
|
|
name="follow",
|
|
|
|
description="Follow an account",
|
|
|
|
arguments=[
|
2017-04-26 11:49:21 +02:00
|
|
|
account_arg,
|
2017-04-19 14:47:30 +02:00
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unfollow",
|
|
|
|
description="Unfollow an account",
|
|
|
|
arguments=[
|
2017-04-26 11:49:21 +02:00
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2022-11-17 22:45:51 +01:00
|
|
|
Command(
|
|
|
|
name="following",
|
2022-11-18 08:28:15 +01:00
|
|
|
description="List accounts following the given account",
|
2022-11-17 22:45:51 +01:00
|
|
|
arguments=[
|
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="followers",
|
2022-11-18 08:28:15 +01:00
|
|
|
description="List accounts followed by the given account",
|
2022-11-17 22:45:51 +01:00
|
|
|
arguments=[
|
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
2017-04-26 11:49:21 +02:00
|
|
|
Command(
|
|
|
|
name="mute",
|
|
|
|
description="Mute an account",
|
|
|
|
arguments=[
|
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unmute",
|
|
|
|
description="Unmute an account",
|
|
|
|
arguments=[
|
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="block",
|
|
|
|
description="Block an account",
|
|
|
|
arguments=[
|
|
|
|
account_arg,
|
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
Command(
|
|
|
|
name="unblock",
|
|
|
|
description="Unblock an account",
|
|
|
|
arguments=[
|
|
|
|
account_arg,
|
2017-04-19 14:47:30 +02:00
|
|
|
],
|
|
|
|
require_auth=True,
|
|
|
|
),
|
|
|
|
]
|
2017-04-18 16:40:26 +02:00
|
|
|
|
2019-08-29 13:44:06 +02:00
|
|
|
COMMANDS = AUTH_COMMANDS + READ_COMMANDS + TUI_COMMANDS + POST_COMMANDS + STATUS_COMMANDS + ACCOUNTS_COMMANDS
|
2017-04-26 12:11:52 +02:00
|
|
|
|
2017-04-18 16:40:26 +02:00
|
|
|
|
2017-04-12 16:42:04 +02:00
|
|
|
def print_usage():
|
2017-04-26 12:11:52 +02:00
|
|
|
max_name_len = max(len(command.name) for command in COMMANDS)
|
|
|
|
|
|
|
|
groups = [
|
|
|
|
("Authentication", AUTH_COMMANDS),
|
2019-08-29 13:44:06 +02:00
|
|
|
("TUI", TUI_COMMANDS),
|
2017-04-26 12:11:52 +02:00
|
|
|
("Read", READ_COMMANDS),
|
|
|
|
("Post", POST_COMMANDS),
|
2019-01-02 12:24:38 +01:00
|
|
|
("Status", STATUS_COMMANDS),
|
2017-04-26 12:11:52 +02:00
|
|
|
("Accounts", ACCOUNTS_COMMANDS),
|
|
|
|
]
|
|
|
|
|
2017-05-08 09:09:20 +02:00
|
|
|
print_out("<green>{}</green>".format(CLIENT_NAME))
|
2018-06-12 12:22:16 +02:00
|
|
|
print_out("<blue>v{}</blue>".format(__version__))
|
2017-04-19 14:47:30 +02:00
|
|
|
|
2017-04-26 12:11:52 +02:00
|
|
|
for name, cmds in groups:
|
2017-05-08 09:09:20 +02:00
|
|
|
print_out("")
|
|
|
|
print_out(name + ":")
|
2017-04-19 14:47:30 +02:00
|
|
|
|
2017-04-26 12:11:52 +02:00
|
|
|
for cmd in cmds:
|
2017-05-08 09:09:20 +02:00
|
|
|
cmd_name = cmd.name.ljust(max_name_len + 2)
|
|
|
|
print_out(" <yellow>toot {}</yellow> {}".format(cmd_name, cmd.description))
|
2017-04-19 14:47:30 +02:00
|
|
|
|
2017-05-08 09:09:20 +02:00
|
|
|
print_out("")
|
|
|
|
print_out("To get help for each command run:")
|
|
|
|
print_out(" <yellow>toot <command> --help</yellow>")
|
|
|
|
print_out("")
|
|
|
|
print_out("<green>{}</green>".format(CLIENT_WEBSITE))
|
2017-04-15 12:00:05 +02:00
|
|
|
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
def get_argument_parser(name, command):
|
|
|
|
parser = ArgumentParser(
|
|
|
|
prog='toot %s' % name,
|
|
|
|
description=command.description,
|
|
|
|
epilog=CLIENT_WEBSITE)
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2018-06-30 09:44:36 +02:00
|
|
|
combined_args = command.arguments + common_args
|
2018-01-02 10:44:32 +01:00
|
|
|
if command.require_auth:
|
2018-06-30 09:44:36 +02:00
|
|
|
combined_args += common_auth_args
|
|
|
|
|
|
|
|
for args, kwargs in combined_args:
|
|
|
|
parser.add_argument(*args, **kwargs)
|
2018-01-02 10:44:32 +01:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
return parser
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2017-04-15 12:12:33 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
def run_command(app, user, name, args):
|
|
|
|
command = next((c for c in COMMANDS if c.name == name), None)
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
if not command:
|
2017-05-08 09:09:20 +02:00
|
|
|
print_err("Unknown command '{}'\n".format(name))
|
2017-04-19 14:47:30 +02:00
|
|
|
print_usage()
|
2017-04-16 17:15:05 +02:00
|
|
|
return
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
parser = get_argument_parser(name, command)
|
|
|
|
parsed_args = parser.parse_args(args)
|
2017-04-13 13:52:28 +02:00
|
|
|
|
2018-01-02 10:44:32 +01:00
|
|
|
# Override the active account if 'using' option is given
|
|
|
|
if command.require_auth and parsed_args.using:
|
|
|
|
user, app = config.get_user_app(parsed_args.using)
|
|
|
|
if not user or not app:
|
|
|
|
raise ConsoleError("User '{}' not found".format(parsed_args.using))
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
if command.require_auth and (not user or not app):
|
2017-05-08 09:09:20 +02:00
|
|
|
print_err("This command requires that you are logged in.")
|
|
|
|
print_err("Please run `toot login` first.")
|
2017-04-13 13:52:28 +02:00
|
|
|
return
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
fn = commands.__dict__.get(name)
|
2017-04-13 13:52:28 +02:00
|
|
|
|
2017-04-19 15:29:40 +02:00
|
|
|
if not fn:
|
|
|
|
raise NotImplementedError("Command '{}' does not have an implementation.".format(name))
|
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
return fn(app, user, parsed_args)
|
2017-04-13 13:52:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
2018-01-14 15:34:41 +01:00
|
|
|
# Enable debug logging if --debug is in args
|
2017-08-26 15:12:32 +02:00
|
|
|
if "--debug" in sys.argv:
|
2018-01-14 15:34:41 +01:00
|
|
|
filename = os.getenv("TOOT_LOG_FILE")
|
|
|
|
logging.basicConfig(level=logging.DEBUG, filename=filename)
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
command_name = sys.argv[1] if len(sys.argv) > 1 else None
|
2017-04-16 14:06:16 +02:00
|
|
|
args = sys.argv[2:]
|
2017-04-12 16:42:04 +02:00
|
|
|
|
2017-04-19 14:47:30 +02:00
|
|
|
if not command_name:
|
2017-04-13 13:52:28 +02:00
|
|
|
return print_usage()
|
|
|
|
|
2018-01-02 10:44:32 +01:00
|
|
|
user, app = config.get_active_user_app()
|
2017-04-19 14:47:30 +02:00
|
|
|
|
2017-04-13 13:52:28 +02:00
|
|
|
try:
|
2017-04-19 14:47:30 +02:00
|
|
|
run_command(app, user, command_name, args)
|
2018-06-15 10:01:18 +02:00
|
|
|
except (ConsoleError, ApiError) as e:
|
2017-05-08 09:09:20 +02:00
|
|
|
print_err(str(e))
|
2017-05-08 09:11:20 +02:00
|
|
|
sys.exit(1)
|
2019-08-22 17:10:37 +02:00
|
|
|
except KeyboardInterrupt:
|
2018-06-15 10:01:18 +02:00
|
|
|
pass
|