10 Commits

9 changed files with 55 additions and 28 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
*.toml
*.csv
*.json
# ---> Python # ---> Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files

View File

@@ -4,14 +4,14 @@
In order to have a common development environment, its nice to use docker. Its quite easy. To build a new image, simply run In order to have a common development environment, its nice to use docker. Its quite easy. To build a new image, simply run
`docker build . -t fediverse_blocklist_deploy` `docker build . -t fediverse_blocklist_tool`
Now you can execute any commands using Now you can execute any commands using
`docker run --rm fediverse_blocklist_deploy --help` `docker run --rm fediverse_blocklist_tool --help`
If you want to avoid building new containers for each change, simply mount your code into the container using If you want to avoid building new containers for each change, simply mount your code into the container using
`docker run --rm -v $(pwd):/app fediverse_blocklist_deploy` `docker run --rm -v $(pwd):/app fediverse_blocklist_tool`
Please be aware that changes to the package itself require a rebuild anyways. Please be aware that changes to the package itself require a rebuild anyways.

View File

@@ -4,7 +4,7 @@ ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1 ENV PYTHONUNBUFFERED=1
COPY pyproject.toml poetry.lock README.md /app/ COPY pyproject.toml poetry.lock README.md /app/
COPY fediverse_blocklist_deploy /app/fediverse_blocklist_deploy COPY fediverse_blocklist_tool /app/fediverse_blocklist_tool
WORKDIR /app WORKDIR /app
ENTRYPOINT ["fediverse_blocklist_deploy"] ENTRYPOINT ["fediverse_blocklist_deploy"]

View File

@@ -1,4 +1,4 @@
# fediverse-blocklist-deploy # fediverse-blocklist-tool
A small tool to deploy blocklist updates to a fediverse server using its API. A small tool to deploy blocklist updates to a fediverse server using its API.

View File

@@ -0,0 +1 @@
version = "0.1.0"

View File

@@ -6,18 +6,22 @@ import requests
import os import os
import toml import toml
from fediverse_blocklist_deploy.models import Instance from fediverse_blocklist_tool.models import Instance
from fediverse_blocklist_deploy.helpers import blocklist_to_markdown, blocklist_to_toml, blocklist_to_csv, \ from fediverse_blocklist_tool.helpers import blocklist_to_markdown, blocklist_to_toml, blocklist_to_csv, \
blocklist_to_json blocklist_to_json
def load_blocklist_file(filename: str) -> [Instance]: def load_blocklist_file(filename: str) -> [Instance]:
with open(filename, "r") as f: if filename.endswith("json"):
data = toml.load(f) with open(filename) as f:
instances = [] instances = blocklist_json_to_instances(json.load(f))
for instance_dict in data["instances"]: else:
instance = Instance(instance_dict) with open(filename, "r") as f:
instances.append(instance) data = toml.load(f)
instances = []
for instance_dict in data["instances"]:
instance = Instance(instance_dict)
instances.append(instance)
return instances return instances
@@ -65,6 +69,9 @@ def exporter(blocklist, output=None, format: str = "toml", private: bool = False
def merge(input_file, merge_target, format: str = "toml", private: bool = False, overwrite=False): def merge(input_file, merge_target, format: str = "toml", private: bool = False, overwrite=False):
"""Shows a table in the CLI comparing the local and remote blocklist"""
from rich.table import Table
from rich.console import Console
input_blocklist = load_blocklist_file(input_file) input_blocklist = load_blocklist_file(input_file)
merge_target_blocklist = load_blocklist_file(merge_target) merge_target_blocklist = load_blocklist_file(merge_target)
for input_instance in input_blocklist: for input_instance in input_blocklist:
@@ -73,12 +80,12 @@ def merge(input_file, merge_target, format: str = "toml", private: bool = False,
continue continue
# Check if there is a domain in the merge target where the input domain is similar # Check if there is a domain in the merge target where the input domain is similar
try: try:
merge_target_instance = [merge_target_instance for merge_target_instance in merge_target if input_instance.domain == merge_target_instance.domain][0] merge_target_instance = [merge_target_instance for merge_target_instance in merge_target_blocklist if input_instance.domain == merge_target_instance.domain][0]
if not overwrite: if not overwrite:
key_input = "" key_input = ""
while key_input not in ("i", "O"): while key_input not in ("i", "O"):
print(f"Different settings for {input_instance.domain} detected.") print(f"Different settings for {input_instance.domain} detected.")
print(f"In the input blocklist the setting is\n{input_instance} whereas it's {merge_target_instance} in the merge target") Instance.show_diff(input_instance, merge_target_instance)
key_input = input("Keep input (i) or original (o) [i/O]") key_input = input("Keep input (i) or original (o) [i/O]")
elif key_input == "i": elif key_input == "i":
merge_target_blocklist.append(merge_target_instance) merge_target_blocklist.append(merge_target_instance)
@@ -89,7 +96,7 @@ def merge(input_file, merge_target, format: str = "toml", private: bool = False,
def cli(): def cli():
parser = argparse.ArgumentParser(description='Deploy blocklist updates to a fediverse server') parser = argparse.ArgumentParser(description='Compare, merge, export and deploy blocklist of a fediverse server')
parser.add_argument('action', choices=['diff', 'deploy', 'export', 'merge'], parser.add_argument('action', choices=['diff', 'deploy', 'export', 'merge'],
help="Either use 'diff' to check the difference between local blockĺist and the blocklist on " 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 " "the server, 'deploy' to apply the current local blocklist or 'export' to export the remote "
@@ -117,12 +124,13 @@ def cli():
else: else:
token = os.getenv('MBD_TOKEN') token = os.getenv('MBD_TOKEN')
"""if there is a remote blocklist provided load this instead of fetching it from a server (for debugging reasons)""" """Get a remote blocklist only when necessary"""
if args.remote_blocklist: if args.action in ["diff", "deploy", "export"]:
with open(args.remote_blocklist) as f: """if there is a remote blocklist provided load this instead of fetching it from a server (for debugging reasons)"""
remote_blocklist = blocklist_json_to_instances(json.load(f)) if args.remote_blocklist:
else: remote_blocklist = load_blocklist_file(args.remote_blocklist)
remote_blocklist = load_blocklist_from_instance(server=args.server, token=token) else:
remote_blocklist = load_blocklist_from_instance(server=args.server, token=token)
"""Load local blocklist only when needed""" """Load local blocklist only when needed"""
if args.action in ["diff", "deploy", "merge"]: if args.action in ["diff", "deploy", "merge"]:

View File

@@ -1,4 +1,4 @@
from fediverse_blocklist_deploy.models import Instance from fediverse_blocklist_tool.models import Instance
import toml import toml
import io import io
import csv import csv

View File

@@ -145,3 +145,18 @@ class Instance:
table.add_row(diff["local"].domain, diff["local"].status_str(), diff["remote"].status_str()) table.add_row(diff["local"].domain, diff["local"].status_str(), diff["remote"].status_str())
console = Console() console = Console()
console.print(table) console.print(table)
@staticmethod
def show_diff(instanceA, instanceB, column_names=('Input', 'Original')):
from rich.table import Table
from rich.console import Console
table = Table(title="Differences", expand=True, show_lines=True)
table.add_column("Attribute", style="cyan")
table.add_column(column_names[0], style="green")
table.add_column(column_names[1], style="magenta")
compare_attributes = ["domain", "severity", "obfuscate", "private_comment", "public_comment", "reject_media", "reject_reports"]
for attr in compare_attributes:
table.add_row(attr, str(getattr(instanceA, attr)), str(getattr(instanceB, attr)))
console = Console()
console.print(table)

View File

@@ -1,12 +1,12 @@
[tool.poetry] [tool.poetry]
name = "fediverse-blocklist-deploy" name = "fediverse-blocklist-tool"
version = "0.1.0" version = "0.1.0"
description = "A small tool to deploy blocklist updates to a fediverse server using its API." description = "A small tool to export, compareof merge and deploy blocklists of a fediverse server"
authors = ["Georg Krause <mail@georg-krause.net>", "Julian-Samuel Gebühr <julian-samuel@gebuehr.net>"] authors = ["Georg Krause <mail@georg-krause.net>", "Julian-Samuel Gebühr <julian-samuel@gebuehr.net>"]
readme = "README.md" readme = "README.md"
packages = [{include = "fediverse_blocklist_deploy"}] packages = [{include = "fediverse_blocklist_tool"}]
license = "MIT" license = "MIT"
keywords = ["fediverse", "blocklist", "fediverse"] keywords = ["fediverse", "blocklist", "mastodon", "gotosocial", "safety"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
@@ -16,7 +16,7 @@ rich = "^13.0.1"
toml = "^0.10.2" toml = "^0.10.2"
[tool.poetry.scripts] [tool.poetry.scripts]
fediverse_blocklist_deploy = 'fediverse_blocklist_deploy.cli:cli' fbt = 'fediverse_blocklist_tool.cli:cli'
[tool.poetry.group.test.dependencies] [tool.poetry.group.test.dependencies]