#!/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)