import io import pathlib import tarfile import requests from django.conf import settings from django.core.management.base import BaseCommand DATABASE_URLS = [ ( "GeoLite2-Country.mmdb", "https://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.tar.gz", ), ( "GeoLite2-City.mmdb", "https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz", ), ] class Command(BaseCommand): help = "Update Maxmind GeoLite binary databases for Cities and Countries." def handle(self, *args, **options): data_path = pathlib.Path(settings.GEOIP_PATH) data_path.mkdir(parents=True, exist_ok=True) for db_name, url in DATABASE_URLS: _, local_filename = url.rsplit("/", 1) local_fullpath = str(data_path / db_name) self.stdout.write( "Downloading geoip file '%s' to '%s'" % (url, local_fullpath) ) try: req = requests.get(url, stream=True) fileobj = io.BytesIO(req.content) # We need seekability tar = tarfile.open( mode="r:gz", fileobj=fileobj, errorlevel=1, # Thus all fatal errors are raised as OSError ) all_member_names = tar.getnames() for member_name in all_member_names: if member_name.endswith(db_name): fr = tar.extractfile(member_name) db_content = fr.read() with open(local_fullpath, "wb") as fw: fw.write(db_content) self.stdout.write( "New DB extracted from archive: %s" % member_name ) break else: raise IOError( "Couldn't find Geoip DB '%s' inside archive: %s" % (db_name, all_member_names) ) except EnvironmentError as exc: self.stderr.write("Download of Geoip DB failed: %r" % exc) raise