Compare commits

...

15 commits
1.1.1 ... main

3 changed files with 56 additions and 9 deletions

View file

@ -9,8 +9,11 @@ To make certain that you don't block just any instance in the Fediverse
because $somebody has it on their blocklist you assign _trust levels_ to
the correctness of the blocklists of the other servers. Only when a server
is blocked with a total trust level that is above a confidence level, it
will be added to resulting blocklist automatically. Otherwise the user
will be ask if they want to add a node to their blocklist or not.
will be added to resulting blocklist automatically. Otherwise you will be
ask if you want to add a node to the blocklist or not.
And just to state the obvious: You should never blindly trust the blocklists
of your peers but do your own investications about in block when in doubt.
## Config file
@ -94,7 +97,8 @@ domains = friendica.example.com
You can also add Mastodon instances you trust. In addition to the configuration
needed for Friendica nodes you have to add the `type = mastodon` entry to the
config section.
config section. *Please note* that the used API endpoint is not available on
all Mastodon instances.
Please note only suspended entries from the Mastodon blocklist will be added to
the blocklist. Silenced entries will be ignored.

View file

@ -1,10 +1,16 @@
[tool.poetry]
name = "brewserverblocklist"
version = "1.1.1"
version = "1.1.7"
description = "A python script to collect the server-wide blocklists from Friendica nodes to build a collection from trusted admin choice"
authors = ["Tobias Diekershoff"]
license = "GNU General Public License v3.0"
readme = "README.md"
include = [
{ path = "src/brewserverblocklist" },
]
packages = [
{ include = "brewserverblocklist", from = "src"},
]
[tool.poetry.scripts]
brewserverblocklist = "brewserverblocklist.brewserverblocklist:main"

View file

@ -14,6 +14,21 @@ import sys
from os.path import exists
import requests
class BParser(argparse.ArgumentParser):
"""
This expansion of the ArgParser class will display the --help results by
default if an error occurs (e.g. no arguments are passed to the script).
It is based on an StackOverflow answer from 2010 by unutbu who refered to
a reply from Steven Bethard as source of the code.
https://stackoverflow.com/questions/4042452/display-help-message-with-python-argparse-when-script-is-called-without-any-argu/4042861#4042861
"""
def error(self, message):
sys.stderr.write('error: %s\n' % message)
self.print_help()
sys.exit(2)
class BrewBlocklist():
"""
This is the cauldron that is used to
@ -32,10 +47,14 @@ class BrewBlocklist():
self.auto_accept = auto_accept
self.auto_accept_direction = auto_accept_direction
self.safe_harbor = []
self.error = []
config = configparser.RawConfigParser()
config.read(configfile)
for section in config.sections():
section_values = dict(config.items(section))
if (section.find('http://') > -1) or (section.find('https://') > -1):
print('The section name in the config file must not contain the protocol ({})'.format(section))
sys.exit(1)
if not section == 'safe harbor':
if not 'type' in section_values.keys():
section_values['type'] = 'friendica'
@ -62,6 +81,9 @@ class BrewBlocklist():
if source['type'] == 'friendica':
# Friendica publishes the blocklist as CSV file
requ = requests.get('https://{}/blocklist/domain/download'.format(source['url']))
if not requ.status_code == requests.codes.ok:
self.error.append('The request to {} failed'.format(sources['url']))
break
for line in requ.text.split('\n'):
try:
pattern, reason = line.split(',')
@ -75,9 +97,15 @@ class BrewBlocklist():
elif source['type'] == 'mastodon':
# Mastodon has an API endpoint that contains the information
requ = requests.get('https://{}//api/v1/instance/domain_blocks'.format(source['url']))
for item in requ.json():
self.blocklist[item['domain']] = self.blocklist.get(item['domain'], 0) + source['trust']
self.reasons[item['domain']] = self.reasons.get(item['domain'], item['comment'])
if not requ.status_code == requests.codes.ok:
self.error.append('The request to {} failed'.format(sources['url']))
break
try:
for item in requ.json():
self.blocklist[item['domain']] = self.blocklist.get(item['domain'], 0) + source['trust']
self.reasons[item['domain']] = self.reasons.get(item['domain'], item['comment'])
except:
self.error.append('{} returned no valid json to the API call'.format(source['url']))
else:
raise ValueError('{} is not a supported node type, check your config file'.format(source['type']))
@ -125,10 +153,19 @@ class BrewBlocklist():
orig_stdout = sys.stdout
sys.stdout = out_file
for key, value in self.blocklist.items():
try:
if ("," in self.reasons[key] or " " in self.reasons[key]) and not self.reasons[key].startswith('"'):
self.reasons[key] = '"{}"'.format(self.reasons[key])
except TypeError:
self.reasons[key] = '"no reason given"'
self.error.append("for {} no blocking reason was provided".format(key))
print('{}, {}, {}'.format(key, self.reasons[key], value))
if self.outputfile:
sys.stdout = orig_stdout
out_file.close()
if len(self.error):
print("\n\nWhile creating the blocklist the following problems occured:")
print("\n".join(self.error))
def main():
"""
@ -140,7 +177,7 @@ def main():
* collect the ingredient
* serve the result
"""
parser = argparse.ArgumentParser()
parser = BParser()
parser.add_argument('-c', '--config',
dest='configfile',
required=True,
@ -168,7 +205,7 @@ def main():
arg_auto_accept = not args.auto_accept_direction is None
if not exists(args.configfile):
print('The config file {} was not found.'.format(args.configfile))
sys.exit()
sys.exit(1)
brew = BrewBlocklist(args.configfile, args.outputfile, arg_auto_accept,
args.auto_accept_direction, args.confidence)
brew.collect_ingrediens()