2023-11-30 20:12:04 +01:00
|
|
|
from toot import api, config, User, App
|
|
|
|
from toot.entities import from_dict, Instance
|
2017-12-30 13:32:52 +01:00
|
|
|
from toot.exceptions import ApiError, ConsoleError
|
2023-05-26 23:53:15 +02:00
|
|
|
from urllib.parse import urlparse
|
2017-12-30 12:52:55 +01:00
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def find_instance(base_url: str) -> Instance:
|
|
|
|
try:
|
|
|
|
instance = api.get_instance(base_url).json()
|
|
|
|
return from_dict(Instance, instance)
|
|
|
|
except Exception:
|
|
|
|
raise ConsoleError(f"Instance not found at {base_url}")
|
|
|
|
|
|
|
|
|
|
|
|
def register_app(domain: str, base_url: str) -> App:
|
2017-12-30 12:52:55 +01:00
|
|
|
try:
|
2023-03-07 10:37:03 +01:00
|
|
|
response = api.create_app(base_url)
|
2017-12-30 16:30:35 +01:00
|
|
|
except ApiError:
|
|
|
|
raise ConsoleError("Registration failed.")
|
2017-12-30 12:52:55 +01:00
|
|
|
|
2017-12-30 16:30:35 +01:00
|
|
|
app = App(domain, base_url, response['client_id'], response['client_secret'])
|
2018-01-02 10:44:32 +01:00
|
|
|
config.save_app(app)
|
|
|
|
|
2017-12-30 12:52:55 +01:00
|
|
|
return app
|
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def get_or_create_app(base_url: str) -> App:
|
|
|
|
instance = find_instance(base_url)
|
|
|
|
domain = _get_instance_domain(instance)
|
2023-03-07 10:37:03 +01:00
|
|
|
return config.load_app(domain) or register_app(domain, base_url)
|
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def create_user(app: App, access_token: str) -> User:
|
2018-01-02 10:44:32 +01:00
|
|
|
# Username is not yet known at this point, so fetch it from Mastodon
|
|
|
|
user = User(app.instance, None, access_token)
|
2023-11-18 14:55:45 +01:00
|
|
|
creds = api.verify_credentials(app, user).json()
|
2018-01-02 10:44:32 +01:00
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
user = User(app.instance, creds["username"], access_token)
|
2018-01-02 10:44:32 +01:00
|
|
|
config.save_user(user, activate=True)
|
2017-12-30 12:52:55 +01:00
|
|
|
|
|
|
|
return user
|
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def login_username_password(app: App, email: str, password: str) -> User:
|
2017-12-30 12:52:55 +01:00
|
|
|
try:
|
|
|
|
response = api.login(app, email, password)
|
2023-11-30 20:12:04 +01:00
|
|
|
except Exception:
|
2017-12-30 12:52:55 +01:00
|
|
|
raise ConsoleError("Login failed")
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
return create_user(app, response["access_token"])
|
2017-12-30 12:52:55 +01:00
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def login_auth_code(app: App, authorization_code: str) -> User:
|
|
|
|
try:
|
|
|
|
response = api.request_access_token(app, authorization_code)
|
|
|
|
except Exception:
|
|
|
|
raise ConsoleError("Login failed")
|
2017-12-30 12:52:55 +01:00
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
return create_user(app, response["access_token"])
|
2017-12-30 12:52:55 +01:00
|
|
|
|
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
def _get_instance_domain(instance: Instance) -> str:
|
|
|
|
"""Extracts the instance domain name.
|
2017-12-30 12:52:55 +01:00
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
Pleroma and its forks return an actual URI here, rather than a domain name
|
|
|
|
like Mastodon. This is contrary to the spec.¯ in that case, parse out the
|
|
|
|
domain and return it.
|
2017-12-30 12:52:55 +01:00
|
|
|
|
2023-11-30 20:12:04 +01:00
|
|
|
TODO: when updating to v2 instance endpoint, this field has been renamed to
|
|
|
|
`domain`
|
|
|
|
"""
|
|
|
|
if instance.uri.startswith("http"):
|
|
|
|
return urlparse(instance.uri).netloc
|
|
|
|
return instance.uri
|