# Buggy code
def setup(bot):
    bot.config.define_section("safety", SafetySection)

    if "safety_cache" not in bot.memory:
        bot.memory["safety_cache"] = tools.SopelMemory()
    if "safety_cache_lock" not in bot.memory:
        bot.memory["safety_cache_lock"] = threading.Lock()
    for item in bot.config.safety.known_good:
        known_good.append(re.compile(item, re.I))

    loc = os.path.join(bot.config.homedir, "malwaredomains.txt")
    if os.path.isfile(loc):
        if os.path.getmtime(loc) < time.time() - 24 * 60 * 60 * 7:
            # File exists but older than one week — update it
            _download_malwaredomains_db(loc)
    else:
        _download_malwaredomains_db(loc)
    with open(loc, "r") as f:
        for line in f:
            clean_line = unicode(line).strip().lower()
            if clean_line != "":
                malware_domains.add(clean_line)


# Traceback (urllib.error.HTTPError)
[2020-12-22 13:35:56,136] sopel.modules.safety INFO     - Downloading malwaredomains db from https://mirror1.malwaredomains.com/files/justdomains
[2020-12-22 13:35:56,332] sopel.bot            ERROR    - Error in safety setup: HTTP Error 404: Not Found
Traceback (most recent call last):
File "/mnt/c/Users/dgw/github/sopel/sopel/bot.py", line 310, in setup_plugins
plugin.setup(self)
File "/mnt/c/Users/dgw/github/sopel/sopel/plugins/handlers.py", line 265, in setup
self._module.setup(bot)
File "/mnt/c/Users/dgw/github/sopel/sopel/modules/safety.py", line 98, in setup
_download_malwaredomains_db(loc)
File "/mnt/c/Users/dgw/github/sopel/sopel/modules/safety.py", line 116, in _download_malwaredomains_db
urlretrieve(url, path)
File "/usr/lib/python3.6/urllib/request.py", line 248, in urlretrieve
with contextlib.closing(urlopen(url, data)) as fp:
File "/usr/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python3.6/urllib/request.py", line 532, in open
response = meth(req, response)
File "/usr/lib/python3.6/urllib/request.py", line 642, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python3.6/urllib/request.py", line 570, in error
return self._call_chain(*args)
File "/usr/lib/python3.6/urllib/request.py", line 504, in _call_chain
result = func(*args)
File "/usr/lib/python3.6/urllib/request.py", line 650, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 404: Not Found

# Fixed code
def setup(bot):
    bot.config.define_section("safety", SafetySection)

    if "safety_cache" not in bot.memory:
        bot.memory["safety_cache"] = tools.SopelMemory()
    if "safety_cache_lock" not in bot.memory:
        bot.memory["safety_cache_lock"] = threading.Lock()
    for item in bot.config.safety.known_good:
        known_good.append(re.compile(item, re.I))

    old_file = os.path.join(bot.config.homedir, "malwaredomains.txt")
    if os.path.exists(old_file) and os.path.isfile(old_file):
        LOGGER.info("Removing old malwaredomains file from %s", old_file)
        try:
            os.remove(old_file)
        except Exception as err:
            # for lack of a more specific error type...
            # Python on Windows throws an exception if the file is in use
            LOGGER.info("Could not delete %s: %s", old_file, str(err))

    loc = os.path.join(bot.config.homedir, "unsafedomains.txt")
    if os.path.isfile(loc):
        if os.path.getmtime(loc) < time.time() - 24 * 60 * 60:
            # File exists but older than one day — update it
            _download_domain_list(loc)
    else:
        _download_domain_list(loc)
    with open(loc, "r") as f:
        for line in f:
            clean_line = unicode(line).strip().lower()
            if not clean_line or clean_line[0] == "#":
                # blank line or comment
                continue

            parts = clean_line.split(" ", 1)
            try:
                domain = parts[1]
            except IndexError:
                # line does not contain a hosts entry; skip it
                continue

            if "." in domain:
                # only publicly routable domains matter; skip loopback/link-local stuff
                malware_domains.add(domain)