masto-aio/ansible/roles/fediblockhole/bin/get_token.py

80 lines
2.4 KiB
Python
Executable file

#!/usr/bin/env python3
import sys,requests
from bs4 import BeautifulSoup
# Generate an app token for fediblockhole.
# Mastodon has opted not to expose admin tasks like this in any way that can be automated easily.
# This whole thing is a house of cards that will topple as soon as Mastodon's UI changes,
# which is often. It's a bad idea and I regret doing it. Anyway, enjoy.
# args are simple:
# - server domain
# - app name
# - admin email
# - path to password file
try:
domain = sys.argv[1]
appname = sys.argv[2]
email = sys.argv[3]
pwpath = sys.argv[4]
except IndexError:
print(f"Usage: {sys.argv[0]} domain email path_to_password_file")
password = ""
with open(pwpath) as fh:
password = fh.read()
with requests.Session() as session:
session.max_redirects = 10
# log in first
r = session.get(f"https://{domain}/auth/sign_in")
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find("form")
assert form.get("action") == "/auth/sign_in"
params = {}
for field in form.find_all("input"):
params[field.get("name")] = field.get("value")
params["user[email]"] = email
params["user[password]"] = password
r = session.post(f"https://{domain}{form.get('action')}", data=params)
assert r.status_code == 200
r = session.get(f"https://{domain}/settings/applications/new")
soup = BeautifulSoup(r.text, "html.parser")
form = soup.find("form")
params = {}
for field in form.find_all("input"):
params[field.get("name")] = field.get("value")
for field in form.find_all("textarea"):
params[field.get("name")] = field.get("value")
params["doorkeeper_application[name]"] = appname
params["doorkeeper_application[website]"] = f"https://{domain}/"
params["doorkeeper_application[redirect_uri]"] = "urn:ietf:wg:oauth:2.0:oob"
params["doorkeeper_application[scopes][]"] = [ "admin:read", "admin:write" ]
r = session.post(f"https://{domain}{form.get('action')}", data=params)
soup = BeautifulSoup(r.text, "html.parser")
search = soup.find_all(lambda x: x.name == "a" and x.text == appname)
tag = search[0] # we will just take the first one
r = session.get(f"https://{domain}{tag['href']}")
soup = BeautifulSoup(r.text, "html.parser")
tag = soup.find_all(lambda x: x.text == "Your access token")[0]
print(tag.find_next('code').text)