fediverse-blocklist-tool/mastodon_blocklist_deploy/cli.py

122 lines
4.6 KiB
Python

# import tomllib
import argparse
import json
import logging
import requests
import os
import toml
from mastodon_blocklist_deploy.models import Instance
from mastodon_blocklist_deploy.helpers import blocklist_to_markdown, blocklist_to_toml
def load_blocklist_file(filename: str) -> [Instance]:
with open(filename, "r") as f:
data = toml.load(f)
instances = []
for instance_dict in data["instances"]:
instance = Instance(instance_dict)
instances.append(instance)
return instances
def blocklist_json_to_instances(blocklist_json: str) -> [Instance]:
instances = []
for i in blocklist_json:
instances.append(Instance(i))
return instances
def load_blocklist_from_instance(server: str, token: str) -> [Instance]:
headers = {
f'Authorization': f'Bearer {token}',
}
response = requests.get(f'https://{server}/api/v1/admin/domain_blocks', headers=headers)
if response.status_code == 200:
blocklist_json = json.loads(response.content)
return blocklist_json_to_instances(blocklist_json)
else:
raise ConnectionError(f"Could not connect to the server ({response.status_code}: {response.reason})")
def remove_key_from_dict(dict, key):
del dict[key]
return dict
def exporter(blocklist, output=None, format: str = "toml", private: bool = False):
if format == "markdown":
exported_text = blocklist_to_markdown(blocklist, private)
if format == "toml":
exported_text = blocklist_to_toml(blocklist, private)
# Output the text
if output is not None:
with open(output, "w") as f:
f.write(exported_text)
else:
print(exported_text)
def cli():
parser = argparse.ArgumentParser(description='Deploy blocklist updates to a mastodon server')
parser.add_argument('action', choices=['diff', 'deploy', 'export'],
help="Either use 'diff' to check the difference between local blockĺist and the blocklist on "
"the server, 'deploy' to apply the current local blocklist or 'export' to export the remote "
"blocklist into a local file.")
parser.add_argument('-s', '--server', help="The address of the server where you want to deploy (e.g. "
"mastodon.social)")
parser.add_argument('-t', '--token', help="Authorization token")
parser.add_argument('-i', '--input-file', help="The blocklist to use")
parser.add_argument('-r', '--remote-blocklist', help="The remote blocklist as json for debugging reasons")
parser.add_argument('-o', '--output', help="Filename where to export the blocklist")
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('-n', '--no-delete', action='store_true', help="Do not delete existing blocks")
parser.add_argument('--format', help="Export format: toml|markdown")
parser.add_argument('--private', action='store_true', help="When the flag is set, private comment will also be "
"exported.")
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.WARN)
if args.token:
token = args.token
else:
token = os.getenv('MBD_TOKEN')
"""if there is a remote blocklist provided load this instead of fetching it from a server (for debugging reasons)"""
if args.remote_blocklist:
with open(args.remote_blocklist) as f:
remote_blocklist = blocklist_json_to_instances(json.load(f))
else:
remote_blocklist = load_blocklist_from_instance(server=args.server, token=token)
"""Load local blocklist only when needed"""
if args.action in ["diff", "deploy"]:
if args.input_file:
blocklist_filename = args.input_file
else:
blocklist_filename = "../blocklist.toml"
try:
local_blocklist = load_blocklist_file(blocklist_filename)
except FileNotFoundError:
print("Local blocklist file was not found. Make sure to specify it's location via -i")
exit()
if args.action == "diff":
Instance.show_diffs(local_blocklist, remote_blocklist)
elif args.action == "deploy":
diffs = Instance.list_diffs(local_blocklist, remote_blocklist)
Instance.apply_blocks_from_diff(diffs, args.server, token, args.no_delete)
elif args.action == "export":
exporter(remote_blocklist, args.output, args.format, args.private)
if __name__ == "__main__":
cli()