2023-01-09 07:42:36 +00:00
|
|
|
# import tomllib
|
|
|
|
import argparse
|
|
|
|
import json
|
|
|
|
import logging
|
|
|
|
import requests
|
|
|
|
|
2023-01-09 12:10:40 +00:00
|
|
|
import toml
|
2023-01-09 07:42:36 +00:00
|
|
|
|
2023-01-12 07:00:36 +00:00
|
|
|
from mastodon_blocklist_deploy.models import Instance
|
2023-01-09 07:42:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
def load_local_blocklist(filename: str) -> [Instance]:
|
2023-01-11 18:16:59 +00:00
|
|
|
with open(filename, "r") as f:
|
2023-01-09 12:10:40 +00:00
|
|
|
data = toml.load(f)
|
2023-01-09 07:42:36 +00:00
|
|
|
instances = []
|
|
|
|
for instance_dict in data["instances"]:
|
|
|
|
instance = Instance(instance_dict)
|
|
|
|
instances.append(instance)
|
|
|
|
return instances
|
|
|
|
|
|
|
|
|
2023-01-09 12:10:40 +00:00
|
|
|
def export_blocklist_toml(blocklist: [Instance], filname: str):
|
|
|
|
toml_str = ""
|
|
|
|
for instance in blocklist:
|
|
|
|
toml_str += f'''
|
2023-01-11 18:16:59 +00:00
|
|
|
[[instances]]
|
2023-01-09 12:10:40 +00:00
|
|
|
name = "{instance.domain}"
|
|
|
|
domain = "{instance.domain}"
|
|
|
|
severity = "{instance.severity}"
|
|
|
|
reject_media = {str(instance.reject_media).lower()}
|
|
|
|
reject_reports = {str(instance.reject_reports).lower()}
|
|
|
|
public_comment = "{instance.public_comment}"
|
|
|
|
private_comment = "{instance.private_comment}"
|
|
|
|
'''
|
|
|
|
with open(filname, "w") as f:
|
|
|
|
f.write(toml_str)
|
|
|
|
|
|
|
|
|
2023-01-09 11:01:39 +00:00
|
|
|
def blocklist_json_to_instances(blocklist_json: str):
|
2023-01-09 07:42:36 +00:00
|
|
|
instances = []
|
|
|
|
for i in blocklist_json:
|
|
|
|
instances.append(Instance(i))
|
|
|
|
return instances
|
|
|
|
|
|
|
|
|
2023-01-09 11:01:39 +00:00
|
|
|
def load_remote_blocklist(server: str, token: str):
|
2023-01-09 07:42:36 +00:00
|
|
|
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 cli():
|
|
|
|
parser = argparse.ArgumentParser(description='Deploy blocklist updates to a mastodon server')
|
2023-01-09 12:10:40 +00:00
|
|
|
parser.add_argument('action', choices=['diff', 'deploy', 'export'],
|
2023-01-12 07:40:25 +00:00
|
|
|
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 "
|
2023-01-11 18:38:47 +00:00
|
|
|
"blocklist into a local file.")
|
2023-01-09 07:42:36 +00:00
|
|
|
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")
|
2023-01-09 12:10:40 +00:00
|
|
|
parser.add_argument('-o', '--output', help="Filename where to export the blocklist")
|
2023-01-11 19:21:01 +00:00
|
|
|
parser.add_argument('-v', '--verbose', action='store_true')
|
|
|
|
parser.add_argument('-n', '--no-delete', action='store_true', help="Do not delete existing blocks")
|
2023-01-09 07:42:36 +00:00
|
|
|
args = parser.parse_args()
|
2023-01-11 18:29:38 +00:00
|
|
|
if args.verbose:
|
|
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
else:
|
|
|
|
logging.basicConfig(level=logging.WARN)
|
2023-01-09 12:10:40 +00:00
|
|
|
|
2023-01-11 18:29:38 +00:00
|
|
|
"""if there is a remote blocklist provided load this instead of fetching it from a server (for debugging reasons)"""
|
2023-01-09 07:42:36 +00:00
|
|
|
if args.remote_blocklist:
|
|
|
|
with open(args.remote_blocklist) as f:
|
|
|
|
remote_blocklist = blocklist_json_to_instances(json.load(f))
|
|
|
|
else:
|
|
|
|
remote_blocklist = load_remote_blocklist(server=args.server, token=args.token)
|
2023-01-09 12:10:40 +00:00
|
|
|
|
|
|
|
"""Load local blocklist only when needed"""
|
|
|
|
if args.action in ["diff", "deploy"]:
|
|
|
|
if args.input_file:
|
|
|
|
blocklist_filename = args.input_file
|
|
|
|
else:
|
2023-01-12 07:00:36 +00:00
|
|
|
blocklist_filename = "../blocklist.toml"
|
2023-01-09 12:10:40 +00:00
|
|
|
local_blocklist = load_local_blocklist(blocklist_filename)
|
|
|
|
|
2023-01-09 10:48:44 +00:00
|
|
|
if args.action == "diff":
|
|
|
|
Instance.show_diffs(local_blocklist, remote_blocklist)
|
|
|
|
elif args.action == "deploy":
|
|
|
|
diffs = Instance.list_diffs(local_blocklist, remote_blocklist)
|
2023-01-11 19:21:01 +00:00
|
|
|
Instance.apply_blocks_from_diff(diffs, args.server, args.token, args.no_delete)
|
2023-01-09 12:10:40 +00:00
|
|
|
elif args.action == "export":
|
|
|
|
export_blocklist_toml(remote_blocklist, args.output)
|
2023-01-09 07:42:36 +00:00
|
|
|
|
2023-01-09 11:01:39 +00:00
|
|
|
|
2023-01-09 07:42:36 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
cli()
|