From 3e8a728fe751cfb02a34e3d72730dc4d6ee1a7cb Mon Sep 17 00:00:00 2001 From: nico wellpott Date: Sat, 27 Mar 2021 00:11:22 +0100 Subject: Python Package + init basic python package + add console_script blimp --- src/blimp/__init__.py | 14 ++++++ src/blimp/bl_process.py | 54 +++++++++++++++++++++++ src/blimp/cli.py | 16 +++++++ src/blimp/main.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ src/blimp/misc.py | 17 +++++++ 5 files changed, 216 insertions(+) create mode 100644 src/blimp/__init__.py create mode 100644 src/blimp/bl_process.py create mode 100644 src/blimp/cli.py create mode 100644 src/blimp/main.py create mode 100644 src/blimp/misc.py (limited to 'src/blimp') diff --git a/src/blimp/__init__.py b/src/blimp/__init__.py new file mode 100644 index 0000000..5486de7 --- /dev/null +++ b/src/blimp/__init__.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# version +__version__ = "0.1" + +# main +from .main import BlacklistImporter + +# modules +from .bl_process import ProcessBlocklist + +# utils +from .misc import * diff --git a/src/blimp/bl_process.py b/src/blimp/bl_process.py new file mode 100644 index 0000000..e1d8c93 --- /dev/null +++ b/src/blimp/bl_process.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import sys + +from ruamel.yaml import YAML, scalarstring + +from .misc import * + +class ProcessBlocklist: + def process(self, blacklist, outfile, dryrun: bool): + """ + function to build and compare the local yaml file to the remote file + if the remote file is different, the local file gets overwritten + """ + # cheeky none catch + try: + # load local blacklist outfile + if local_file_present(outfile): + with open(outfile, "r", encoding="utf-8") as local_file: + local_blacklist = local_file.read() + + print("step local file") + + except TypeError: + # no local copy use empty one instead + local_blacklist = YAML(typ="safe") + + # blacklist frame + remote_file = {"acl": {"spamblacklist": {"server": []}}} + + # build the blacklist with the given frame to compare to local blacklist + for entry in blacklist.split(): + entry = scalarstring.DoubleQuotedScalarString(entry) + remote_file["acl"]["spamblacklist"]["server"].append(entry) + + yml = YAML() + yml.indent(offset=2) + yml.default_flow_style = False + + # if dry-run true print expected content + if dryrun: + yml.dump(remote_file, sys.stdout) + return + + if local_blacklist == remote_file: + return + + if outfile is None: + print("no outfile assigned", file=sys.stderr) + sys.exit(2) + + # proceed to update the defined outfile + with open(outfile, "w", encoding="utf-8") as new_local_file: + yml.dump(remote_file, new_local_file) diff --git a/src/blimp/cli.py b/src/blimp/cli.py new file mode 100644 index 0000000..b462918 --- /dev/null +++ b/src/blimp/cli.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import argparse + +from .main import BlacklistImporter + + +def cli(): + parser = argparse.ArgumentParser() + parser.add_argument("-out", "--outfile", help="set path to output file", action="store", default=None) + parser.add_argument("-dr", "--dry-run", help="perform a dry run", action="store_true", default=False) + args = parser.parse_args() + + # run + BlacklistImporter(args).main() diff --git a/src/blimp/main.py b/src/blimp/main.py new file mode 100644 index 0000000..5d4c3ac --- /dev/null +++ b/src/blimp/main.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import argparse + +import requests +from appdirs import * + +from .bl_process import ProcessBlocklist +from .misc import * + + +class BlacklistImporter: + def __init__(self, args): + self.outfile = args.outfile + self.dryrun = args.dry_run + self.path = Path(user_cache_dir("blimp")) + self.url = "https://raw.githubusercontent.com/JabberSPAM/blacklist/master/blacklist.txt" + self.blacklist = "" + self.apply_changes = False + + self.etag_path = self.path.joinpath(".etag") + self.blacklist_path = self.path.joinpath("blacklist.txt") + + def cache_dir_check(self): + if not self.path.is_dir(): + Path(self.path).mkdir(parents=True, exist_ok=True) + + def download_required(self, etag) -> bool: + """ + method to determine if a new download should be initiated + :param etag: requests etag object + :return: true if download is required + """ + # always trigger download if any local cache file is missing + if not local_file_present(self.blacklist_path): + return True + + if not local_file_present(self.etag_path): + return True + + # etag file is present but outdated + else: + with open(self.etag_path, "r") as local_file: + local_etag = local_file.read() + + if local_etag != etag: + return True + + return False + + def start_request(self): + """ + determine if the download is required + """ + with requests.Session() as s: + # head request to check etag + head = s.head(self.url) + etag = head.headers["etag"] + + if head.status_code != requests.codes.ok: + return + + if not self.download_required(etag): + with open(self.blacklist_path, "r", encoding="utf-8") as local_file: + self.blacklist = local_file.read() + + else: + r = s.get(self.url) + r.encoding = "utf-8" + local_etag = head.headers["etag"] + self.blacklist = r.content.decode() + + with open(self.blacklist_path, "w", encoding="utf-8") as local_file: + local_file.write(self.blacklist) + + with open(self.etag_path, "w", encoding="utf-8") as local_file: + local_file.write(local_etag) + + def main(self): + # check the cache dir first + self.cache_dir_check() + + # only output the selected outfile + if self.dryrun: + print("outfile selected: %s" % self.outfile) + + # go + self.start_request() + + # blacklist processing + ProcessBlocklist().process(self.blacklist, self.outfile, self.dryrun) + + """# reload config if changes have been applied + if self.change: + # catch ejabberdctl missing + if Path("/usr/sbin/ejabberdctl").is_file(): + subprocess.call(["/usr/sbin/ejabberdctl", "reload_config"], shell=False) + + # report missing ejabberdctl reload_config + else: + print("/usr/sbin/ejabberdctl was not found", file=sys.stderr) + print("blacklist changes have been applied\nejabberd config was not reloaded", file=sys.stderr) + sys.exit(1) +""" + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-out", "--outfile", help="set path to output file", action="store", default=None) + parser.add_argument("-dr", "--dry-run", help="perform a dry run", action="store_true", default=False) + args = parser.parse_args() + + # run + BlacklistImporter(args).main() diff --git a/src/blimp/misc.py b/src/blimp/misc.py new file mode 100644 index 0000000..d25c8d7 --- /dev/null +++ b/src/blimp/misc.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from pathlib import Path + + +def local_file_present(somepath) -> bool: + """ + check local etag copy + :return: true if present + """ + if not Path(somepath).is_file(): + return False + + return True + +def asd(): + print("yo") -- cgit v1.2.3-54-g00ecf