Add support for custom instance domains

The instance domain can be different from their base url, for example
the instance at https://social.vivaldi.net uses the vivaldi.net domain,
sans 'social'.

This commit requires the user to provide the base url of the instance,
instead of domain name. The domain is then fetched from the server.

fixes #217
This commit is contained in:
Ivan Habunek 2023-03-07 10:37:03 +01:00
parent 9baa0823f9
commit d5b5c89996
No known key found for this signature in database
GPG Key ID: F5F0623FF5EBCB3D
6 changed files with 70 additions and 32 deletions

View File

@ -5,7 +5,7 @@ __version__ = '0.35.0'
App = namedtuple('App', ['instance', 'base_url', 'client_id', 'client_secret'])
User = namedtuple('User', ['instance', 'username', 'access_token'])
DEFAULT_INSTANCE = 'mastodon.social'
DEFAULT_INSTANCE = 'https://mastodon.social'
CLIENT_NAME = 'toot - a Mastodon CLI client'
CLIENT_WEBSITE = 'https://github.com/ihabunek/toot'

View File

@ -28,8 +28,8 @@ def _tag_action(app, user, tag_name, action):
return http.post(app, user, url).json()
def create_app(domain, scheme='https'):
url = f"{scheme}://{domain}/api/v1/apps"
def create_app(base_url):
url = f"{base_url}/api/v1/apps"
json = {
'client_name': CLIENT_NAME,
@ -504,6 +504,6 @@ def clear_notifications(app, user):
http.post(app, user, '/api/v1/notifications/clear')
def get_instance(domain, scheme="https"):
url = f"{scheme}://{domain}/api/v1/instance"
def get_instance(base_url):
url = f"{base_url}/api/v1/instance"
return http.anon_get(url).json()

View File

@ -9,21 +9,13 @@ from toot.exceptions import ApiError, ConsoleError
from toot.output import print_out
def register_app(domain, scheme='https'):
print_out("Looking up instance info...")
instance = api.get_instance(domain, scheme)
print_out("Found instance <blue>{}</blue> running Mastodon version <yellow>{}</yellow>".format(
instance['title'], instance['version']))
def register_app(domain, base_url):
try:
print_out("Registering application...")
response = api.create_app(domain, scheme)
response = api.create_app(base_url)
except ApiError:
raise ConsoleError("Registration failed.")
base_url = scheme + '://' + domain
app = App(domain, base_url, response['client_id'], response['client_secret'])
config.save_app(app)
@ -32,14 +24,30 @@ def register_app(domain, scheme='https'):
return app
def create_app_interactive(instance=None, scheme='https'):
if not instance:
print_out("Choose an instance [<green>{}</green>]: ".format(DEFAULT_INSTANCE), end="")
instance = input()
if not instance:
instance = DEFAULT_INSTANCE
def create_app_interactive(base_url):
if not base_url:
print_out(f"Enter instance URL [<green>{DEFAULT_INSTANCE}</green>]: ", end="")
base_url = input()
if not base_url:
base_url = DEFAULT_INSTANCE
return config.load_app(instance) or register_app(instance, scheme)
domain = get_instance_domain(base_url)
return config.load_app(domain) or register_app(domain, base_url)
def get_instance_domain(base_url):
print_out("Looking up instance info...")
instance = api.get_instance(base_url)
print_out(
f"Found instance <blue>{instance['title']}</blue> "
f"running Mastodon version <yellow>{instance['version']}</yellow>"
)
# NB: when updating to v2 instance endpoint, this field has been renamed to `domain`
return instance["uri"]
def create_user(app, access_token):

View File

@ -10,7 +10,7 @@ from toot.output import (print_out, print_instance, print_account, print_acct_li
print_search_results, print_timeline, print_notifications,
print_tag_list)
from toot.tui.utils import parse_datetime
from toot.utils import delete_tmp_status_file, editor_input, multiline_input, EOF_KEY
from toot.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY
def get_timeline_generator(app, user, args):
@ -305,7 +305,8 @@ def update_account(app, user, args):
def login_cli(app, user, args):
app = create_app_interactive(instance=args.instance, scheme=args.scheme)
base_url = args_get_instance(args.instance, args.scheme)
app = create_app_interactive(base_url)
login_interactive(app, args.email)
print_out()
@ -313,7 +314,8 @@ def login_cli(app, user, args):
def login(app, user, args):
app = create_app_interactive(instance=args.instance, scheme=args.scheme)
base_url = args_get_instance(args.instance, args.scheme)
app = create_app_interactive(base_url)
login_browser_interactive(app)
print_out()
@ -452,17 +454,19 @@ def whois(app, user, args):
def instance(app, user, args):
name = args.instance or (app and app.instance)
if not name:
raise ConsoleError("Please specify instance name.")
default = app.base_url if app else None
base_url = args_get_instance(args.instance, args.scheme, default)
if not base_url:
raise ConsoleError("Please specify an instance.")
try:
instance = api.get_instance(name, args.scheme)
instance = api.get_instance(base_url)
print_instance(instance)
except ApiError:
raise ConsoleError(
"Instance not found at {}.\n"
"The given domain probably does not host a Mastodon instance.".format(name)
f"Instance not found at {base_url}.\n"
"The given domain probably does not host a Mastodon instance."
)

View File

@ -336,7 +336,7 @@ class TUI(urwid.Frame):
See: https://github.com/mastodon/mastodon/issues/19328
"""
def _load_instance():
return api.get_instance(self.app.instance)
return api.get_instance(self.app.base_url)
def _done(instance):
if "max_toot_chars" in instance:

View File

@ -160,3 +160,29 @@ def _use_existing_tmp_file(tmp_path) -> bool:
def drop_empty_values(data: Dict) -> Dict:
"""Remove keys whose values are null"""
return {k: v for k, v in data.items() if v is not None}
def args_get_instance(instance, scheme, default=None):
if not instance:
return default
if scheme == "http":
_warn_scheme_deprecated()
if instance.startswith("http"):
return instance.rstrip("/")
else:
return f"{scheme}://{instance}"
def _warn_scheme_deprecated():
from toot.output import print_err
print_err("\n".join([
"--disable-https flag is deprecated and will be removed.",
"Please specify the instance as URL instead.",
"e.g. instead of writing:",
" toot instance unsafehost.com --disable-https",
"instead write:",
" toot instance http://unsafehost.com\n"
]))