]> git.mxchange.org Git - fba.git/commitdiff
Continued:
authorRoland Häder <roland@mxchange.org>
Mon, 26 Jun 2023 17:16:48 +0000 (19:16 +0200)
committerRoland Häder <roland@mxchange.org>
Mon, 26 Jun 2023 17:16:48 +0000 (19:16 +0200)
- added command recheck_obfuscation() to recheck if returned instance's
  obfuscated blocked peers can be de-obfuscated
- I use array["fop"] outside strings and array['foo'] inside

fba/boot.py
fba/commands.py
fba/helpers/software.py
fba/http/federation.py
fba/http/network.py
fba/models/blocks.py
fba/networks/mastodon.py
fba/utils.py

index eccd5141ea755cf39fba3eb47e5398c3cca4f82a..a8109fc5b46c403c8d0cf1740b94039d9d1cb9a0 100644 (file)
@@ -65,6 +65,13 @@ def init_parser():
     )
     parser.set_defaults(command=commands.fetch_bkali)
 
+    ### Recheck instance's obfuscated peers ###
+    parser = subparser_command.add_parser(
+        "recheck_obfuscation",
+        help="Checks all instance's obfuscated peers if they can be de-obfuscated now.",
+    )
+    parser.set_defaults(command=commands.recheck_obfuscation)
+
     ### Fetch blocks from registered instances or given ###
     parser = subparser_command.add_parser(
         "fetch_blocks",
index c4b1d0a34d37300127f3adc9abd1e24e518fd585..82242dfdef08e98d6bc3051af9c22fd673d800ac 100644 (file)
@@ -140,10 +140,10 @@ def fetch_bkali(args: argparse.Namespace) -> int:
 
         logger.debug("fetched[]='%s'", type(fetched))
         if "error_message" in fetched:
-            logger.warning("post_json_api() for 'gql.api.bka.li' returned error message='%s", fetched['error_message'])
+            logger.warning("post_json_api() for 'gql.api.bka.li' returned error message='%s", fetched["error_message"])
             return 100
         elif isinstance(fetched["json"], dict) and "error" in fetched["json"] and "message" in fetched["json"]["error"]:
-            logger.warning("post_json_api() returned error: '%s", fetched['error']['message'])
+            logger.warning("post_json_api() returned error: '%s", fetched["error"]["message"])
             return 101
 
         rows = fetched["json"]
@@ -270,10 +270,11 @@ def fetch_blocks(args: argparse.Namespace) -> int:
             logger.warning("Unknown software: blocker='%s',software='%s'", blocker, software)
 
         logger.info("Checking %d entries from blocker='%s',software='%s' ...", len(blocking), blocker, software)
+        blockdict = list()
         for block in blocking:
-            logger.debug("blocked='%s',block_level='%s',reason='%s'", block["blocked"], block['block_level'], block["reason"])
+            logger.debug("blocked='%s',block_level='%s',reason='%s'", block["blocked"], block["block_level"], block["reason"])
 
-            if block['block_level'] == "":
+            if block["block_level"] == "":
                 logger.warning("block_level is empty, blocker='%s',blocked='%s'", block["blocker"], block["blocked"])
                 continue
 
@@ -285,7 +286,7 @@ def fetch_blocks(args: argparse.Namespace) -> int:
             if block["blocked"] == "":
                 logger.warning("blocked is empty, blocker='%s'", blocker)
                 continue
-            elif block["blocked"].count("*") > 0:
+            elif block["blocked"].count("*") >= 0:
                 logger.debug("blocker='%s' uses obfuscated domains, marking ...", blocker)
                 instances.set_has_obfuscation(blocker, True)
 
@@ -300,7 +301,7 @@ def fetch_blocks(args: argparse.Namespace) -> int:
                 block["blocked"] = row[0]
                 origin           = row[1]
                 nodeinfo_url     = row[2]
-            elif block["blocked"].count("?") > 0:
+            elif block["blocked"].count("?") >= 0:
                 logger.debug("blocker='%s' uses obfuscated domains, marking ...", blocker)
                 instances.set_has_obfuscation(blocker, True)
 
@@ -320,21 +321,26 @@ def fetch_blocks(args: argparse.Namespace) -> int:
             if not utils.is_domain_wanted(block["blocked"]):
                 logger.debug("blocked='%s' is not wanted - SKIPPED!", block["blocked"])
                 continue
-            elif block['block_level'] in ["accept", "accepted"]:
+            elif block["block_level"] in ["accept", "accepted"]:
                 logger.debug("blocked='%s' is accepted, not wanted here - SKIPPED!", block["blocked"])
                 continue
             elif not instances.is_registered(block["blocked"]):
                 logger.debug("Hash wasn't found, adding: blocked='%s',blocker='%s'", block["blocked"], blocker)
                 federation.fetch_instances(block["blocked"], blocker, None, inspect.currentframe().f_code.co_name)
 
-            if block['block_level'] == "silence":
+            if block["block_level"] == "silence":
                 logger.debug("Block level 'silence' has been changed to 'silenced'")
-                block['block_level'] = "silenced"
-            elif block['block_level'] == "suspend":
+                block["block_level"] = "silenced"
+            elif block["block_level"] == "suspend":
                 logger.debug("Block level 'suspend' has been changed to 'suspended'")
-                block['block_level'] = "suspended"
+                block["block_level"] = "suspended"
 
-            utils.process_block(blocker, block['blocked'], block['reason'], block['block_level'])
+            if utils.process_block(blocker, block["blocked"], block["reason"], block["block_level"]) and block["block_level"] == "reject" and config.get("bot_enabled"):
+                logger.debug("Appending blocked='%s',reason='%s' for blocker='%s' ...", block["blocked"], block["block_level"], blocker)
+                blockdict.append({
+                    "blocked": block["blocked"],
+                    "reason" : block["reason"],
+                })
 
             logger.debug("Invoking cookies.clear(%s) ...", block["blocked"])
             cookies.clear(block["blocked"])
@@ -352,7 +358,7 @@ def fetch_blocks(args: argparse.Namespace) -> int:
 
         logger.debug("config[bot_enabled]='%s',blockdict()=%d'", config.get("bot_enabled"), len(blockdict))
         if config.get("bot_enabled") and len(blockdict) > 0:
-            logger.info("Sending bot POST for blocker='%s,blockdict()=%d ...", blocker, len(blockdict))
+            logger.info("Sending bot POST for blocker='%s',blockdict()=%d ...", blocker, len(blockdict))
             network.send_bot_post(blocker, blockdict)
 
     logger.debug("Success! - EXIT!")
@@ -465,6 +471,7 @@ def fetch_todon_wiki(args: argparse.Namespace) -> int:
     logger.info("Checking %d suspended entries ...", len(suspended))
     blocklist["reject"] = utils.find_domains(suspended, "div")
 
+    blockdict = list()
     for block_level in blocklist:
         blockers = blocklist[block_level]
 
@@ -485,11 +492,20 @@ def fetch_todon_wiki(args: argparse.Namespace) -> int:
                 continue
 
             logger.info("Adding new block: blocked='%s',block_level='%s'", blocked, block_level)
-            blocks.add_instance("todon.eu", blocked, None, block_level)
+            if utils.process_block("todon.eu", blocked, None, block_level) and block_level == "reject" and config.get("bot_enabled"):
+                logger.debug("Appending blocked='%s',reason='%s' for blocker='todon.eu' ...", block["blocked"], block["block_level"])
+                blockdict.append({
+                    "blocked": blocked,
+                    "reason" : None,
+                })
 
         logger.debug("Invoking commit() ...")
         database.connection.commit()
 
+        if config.get("bot_enabled") and len(blockdict) > 0:
+            logger.info("Sending bot POST for blocker='todon.eu',blockdict()=%d ...", len(blockdict))
+            network.send_bot_post("todon.eu", blockdict)
+
     logger.debug("Success! - EXIT!")
     return 0
 
@@ -554,11 +570,20 @@ def fetch_cs(args: argparse.Namespace):
                         logger.warning("Exception '%s' during fetching instances (fetch_cs) from row[domain]='%s'", type(exception), row["domain"])
                         instances.set_last_error(row["domain"], exception)
 
-                utils.process_block('chaos.social', row['domain'], row['reason'], block_level)
+                if utils.process_block("chaos.social", row["domain"], row["reason"], block_level) and block_level == "reject" and config.get("bot_enabled"):
+                    logger.debug("Appending blocked='%s',reason='%s' for blocker='chaos.social' ...", row["domain"], block_level)
+                    blockdict.append({
+                        "blocked": row["domain"],
+                        "reason" : row["reason"],
+                    })
 
         logger.debug("Invoking commit() ...")
         database.connection.commit()
 
+        if config.get("bot_enabled") and len(blockdict) > 0:
+            logger.info("Sending bot POST for blocker='chaos.social',blockdict()=%d ...", len(blockdict))
+            network.send_bot_post("chaos.social", blockdict)
+
     logger.debug("Success! - EXIT!")
     return 0
 
@@ -772,7 +797,7 @@ def fetch_oliphant(args: argparse.Namespace) -> int:
             continue
 
         # Fetch this URL
-        logger.info("Fetching csv_url='%s' for blocker='%s' ...", block['csv_url'], block["blocker"])
+        logger.info("Fetching csv_url='%s' for blocker='%s' ...", block["csv_url"], block["blocker"])
         response = utils.fetch_url(f"{base_url}/{block['csv_url']}", network.web_headers, (config.get("connection_timeout"), config.get("read_timeout")))
 
         logger.debug("response.ok='%s',response.status_code=%d,response.text()=%d", response.ok, response.status_code, len(response.text))
@@ -781,6 +806,7 @@ def fetch_oliphant(args: argparse.Namespace) -> int:
             reader = csv.DictReader(response.content.decode('utf-8').splitlines(), dialect="unix")
 
             logger.debug("reader[]='%s'", type(reader))
+            blockdict = list()
             for row in reader:
                 logger.debug("row[%s]='%s'", type(row), row)
                 domain = severity = None
@@ -823,11 +849,24 @@ def fetch_oliphant(args: argparse.Namespace) -> int:
                 processed = utils.process_domain(domain, block["blocker"], inspect.currentframe().f_code.co_name)
                 logger.debug("processed='%s'", processed)
 
-                utils.process_block(block['blocker'], domain, None, "reject")
+                if utils.process_block(block["blocker"], domain, None, "reject") and config.get("bot_enabled"):
+                    logger.debug("Appending blocked='%s',reason='%s' for blocker='%s' ...", domain, block["block_level"], block["blocker"])
+                    blockdict.append({
+                        "blocked": domain,
+                        "reason" : block["reason"],
+                    })
+
                 if reject_media:
-                    utils.process_block(block['blocker'], domain, None, "reject_media")
+                    utils.process_block(block["blocker"], domain, None, "reject_media")
                 if reject_reports:
-                    utils.process_block(block['blocker'], domain, None, "reject_reports")
+                    utils.process_block(block["blocker"], domain, None, "reject_reports")
+
+            logger.debug("Invoking commit() ...")
+            database.connection.commit()
+
+            if config.get("bot_enabled") and len(blockdict) > 0:
+                logger.info("Sending bot POST for blocker='%s',blockdict()=%d ...", blocker, len(blockdict))
+                network.send_bot_post(block["blocker"], blockdict)
 
     logger.debug("Success! - EXIT!")
     return 0
@@ -1040,8 +1079,13 @@ def fetch_joinfediverse(args: argparse.Namespace) -> int:
                 logger.debug("blocked='%s' is not wanted - SKIPPED!", block["blocked"])
                 continue
 
-            logger.debug("blocked='%s',reason='%s'", block['blocked'], block['reason'])
-            utils.process_block(blocker, block['blocked'], block['reason'], "reject")
+            logger.debug("blocked='%s',reason='%s'", block["blocked"], block["reason"])
+            if utils.process_block(blocker, block["blocked"], block["reason"], "reject") and config.get("bot_enabled"):
+                logger.debug("Appending blocked='%s',reason='%s' for blocker='%s' ...", block["blocked"], block["block_level"], blocker)
+                blockdict.append({
+                    "blocked": block["blocked"],
+                    "reason" : block["reason"],
+                })
 
         if instances.has_pending(blocker):
             logger.debug("Flushing updates for blocker='%s' ...", blocker)
@@ -1050,10 +1094,96 @@ def fetch_joinfediverse(args: argparse.Namespace) -> int:
         logger.debug("Invoking commit() ...")
         database.connection.commit()
 
-    logger.debug("config[bot_enabled]='%s',blockdict()=%d'", config.get("bot_enabled"), len(blockdict))
-    if config.get("bot_enabled") and len(blockdict) > 0:
-        logger.info("Sending bot POST for blocker='%s,blockdict()=%d ...", blocker, len(blockdict))
-        network.send_bot_post(blocker, blockdict)
+        if config.get("bot_enabled") and len(blockdict) > 0:
+            logger.info("Sending bot POST for blocker='%s,blockdict()=%d ...", blocker, len(blockdict))
+            network.send_bot_post(blocker, blockdict)
+
+    logger.debug("Success! - EXIT!")
+    return 0
+
+def recheck_obfuscation(args: argparse.Namespace) -> int:
+    logger.debug("args[]='%s' - CALLED!", type(args))
+
+    locking.acquire()
+
+    database.cursor.execute("SELECT domain, software, nodeinfo_url FROM instances WHERE has_obfuscation = 1")
+    rows = database.cursor.fetchall()
+    logger.info("Checking %d domains ...", len(rows))
+    for row in rows:
+        logger.debug("Fetching peers from domain='%s',software='%s',nodeinfo_url='%s' ...", row[0], row[1], row[2])
+
+        blocking = list()
+        if row[1] == "pleroma":
+            logger.debug("domain='%s',software='%s'", row[0], row[1])
+            blocking = pleroma.fetch_blocks(row[0], row[2])
+        elif row[1] == "mastodon":
+            logger.debug("domain='%s',software='%s'", row[0], row[1])
+            blocking = mastodon.fetch_blocks(row[0], row[2])
+        elif row[1] == "lemmy":
+            logger.debug("domain='%s',software='%s'", row[0], row[1])
+            blocking = lemmy.fetch_blocks(row[0], row[2])
+        elif row[1] == "friendica":
+            logger.debug("domain='%s',software='%s'", row[0], row[1])
+            blocking = friendica.fetch_blocks(row[0])
+        elif row[1] == "misskey":
+            logger.debug("domain='%s',software='%s'", row[0], row[1])
+            blocking = misskey.fetch_blocks(row[0])
+        else:
+            logger.warning("Unknown sofware: domain='%s',software='%s'", row[0], row[1])
+
+        logger.info("Checking %d block(s) from domain='%s' ...", len(blocking), row[0])
+        obfuscated = 0
+        for block in blocking:
+            logger.debug("blocked='%s'", block["blocked"])
+            blocked = None
+
+            if block["blocked"].endswith(".arpa"):
+                logger.debug("blocked='%s' is a reversed IP address - SKIPPED!", block["blocked"])
+                continue
+            elif block["blocked"].endswith(".tld"):
+                logger.debug("blocked='%s' is a fake domain name - SKIPPED!", block["blocked"])
+                continue
+            elif block["blocked"].endswith(".onion"):
+                logger.debug("blocked='%s' is a TOR onion domain name - SKIPPED!", block["blocked"])
+                continue
+            elif block["blocked"].find("*") >= 0 or block["blocked"].find("?") >= 0:
+                logger.debug("block='%s' is obfuscated.", block["blocked"])
+                obfuscated = obfuscated + 1
+                blocked = utils.deobfuscate_domain(block["blocked"], row[0], block["hash"] if "hash" in block else None)
+            elif not utils.is_domain_wanted(block["blocked"]):
+                logger.debug("blocked='%s' is not wanted - SKIPPED!", block["blocked"])
+                continue
+            elif blocks.is_instance_blocked(row[0], block["blocked"]):
+                logger.debug("blocked='%s' is already blocked - SKIPPED!", block["blocked"])
+                continue
+
+            if blocked is not None and blocked != block["blocked"]:
+                logger.debug("blocked='%s' was deobfuscated to blocked='%s'", block["blocked"], blocked)
+                obfuscated = obfuscated - 1
+                if blocks.is_instance_blocked(row[0], blocked):
+                    logger.debug("blocked='%s' is already blocked by domain='%s' - SKIPPED!", blocked, row[0])
+                    continue
+
+                if block["block_level"] == "silence":
+                    logger.debug("Block level 'silence' has been changed to 'silenced'")
+                    block["block_level"] = "silenced"
+                elif block["block_level"] == "suspend":
+                    logger.debug("Block level 'suspend' has been changed to 'suspended'")
+                    block["block_level"] = "suspended"
+
+                logger.info("blocked='%s' has been deobfuscated to blocked='%s', adding ...", block["blocked"], blocked)
+                if utils.process_block(row[0], blocked, block["reason"], block["block_level"]) and block["block_level"] == "reject" and config.get("bot_enabled"):
+                    logger.debug("Appending blocked='%s',reason='%s' for blocker='%s' ...", block["blocked"], block["block_level"], blocker)
+                    blockdict.append({
+                        "blocked": block["blocked"],
+                        "reason" : block["reason"],
+                    })
+
+        logger.info("domain='%s' has %d obfuscated domain(s)", row[0], obfuscated)
+        if obfuscated == 0 and len(blocking) > 0:
+            logger.info("Block list from domain='%s' has been fully deobfuscated.", row[0])
+            instances.set_has_obfuscation(row[0], False)
+            instances.update_data(row[0])
 
     logger.debug("Success! - EXIT!")
     return 0
index 1987871aec02d36ec5caaebec1c3d0eb91318b6a..2308d2cb3bb87a26d9eaffe5360cb81f9b43712b 100644 (file)
@@ -24,7 +24,7 @@ logger = logging.getLogger(__name__)
 def alias(software: str) -> str:
     logger.debug("software='%s'- CALLED!", software)
     if not isinstance(software, str) and software is not None:
-        raise ValueError(f"software[]='%s' is not type 'str'")
+        raise ValueError(f"software[]='{type(software)}' is not type 'str'")
 
     logger.debug("software='%s'- BEFORE!", software)
     software = tidyup.domain(software)
index 2fa7561903cb21d2734eb0b3ef3b5e175002c3d0..e203c164825b243fa16d2e41d59b613f244ea2f2 100644 (file)
@@ -241,6 +241,7 @@ def fetch_nodeinfo(domain: str, path: str = None) -> dict:
        "/nodeinfo/2.1",
        "/nodeinfo/2.0.json",
        "/nodeinfo/2.0",
+       "/nodeinfo/1.0.json",
        "/nodeinfo/1.0",
        "/api/v1/instance",
     ]
index d15b5636617ebea0921e3f7be51292b926f54113..fdb5dcfce8d5b4950f1d77760ae72045532293ae 100644 (file)
@@ -263,14 +263,16 @@ def json_from_response(response: requests.models.Response) -> list:
     logger.debug("response[]='%s' - CALLED!", type(response))
     if not isinstance(response, requests.models.Response):
         raise ValueError(f"Parameter response[]='{type(response)}' is not type of 'Response'")
+    elif response.headers.get("content-type") != "application/json":
+        logger.warning("response.headers[content-type]='%s' is not a JSON type, below json() invocation may raise an exception", response.headers.get("content-type"))
 
     data = list()
     if response.text.strip() != "":
         logger.debug("response.text()=%d is not empty, invoking response.json() ...", len(response.text))
         try:
             data = response.json()
-        except json.decoder.JSONDecodeError:
-            pass
+        except json.decoder.JSONDecodeError as exception:
+            logger.warning("Exception '%s' during decoding JSON", type(exception))
 
     logger.debug("data[]='%s' - EXIT!", type(data))
     return data
index 2f66445fb322427b63e1f8190fbefd70427d3fd2..ec4fed2e03a20f1b6361cbae3520b91d4376eaab 100644 (file)
@@ -95,7 +95,7 @@ def update_last_seen(blocker: str, blocked: str, block_level: str):
 
     logger.debug("EXIT!")
 
-def is_instance_blocked(blocker: str, blocked: str, block_level: str) -> bool:
+def is_instance_blocked(blocker: str, blocked: str, block_level: str = None) -> bool:
     logger.debug("blocker='%s',blocked='%s',block_level='%s' - CALLED!", blocker, blocked, block_level)
     if not isinstance(blocker, str):
         raise ValueError(f"Parameter blocker[]='{type(blocker)}' is not of type 'str'")
@@ -109,21 +109,30 @@ def is_instance_blocked(blocker: str, blocked: str, block_level: str) -> bool:
         raise ValueError("Parameter 'blocked' is empty")
     elif blocked.lower() != blocked:
         raise ValueError(f"Parameter blocked='{blocked}' must be all lower-case")
-    elif not isinstance(block_level, str):
+    elif not isinstance(block_level, str) and block_level is not None:
         raise ValueError(f"Parameter block_level[]='{type(block_level)}' is not of type 'str'")
     elif block_level == "":
         raise ValueError("Parameter 'block_level' is empty")
     elif block_level in ["accept", "suspend", "silence"]:
         raise ValueError(f"blocked='{blocked}' has unwanted block_level='{block_level}'")
 
-    database.cursor.execute(
-        "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ? LIMIT 1",
-        (
-            blocker,
-            blocked,
-            block_level
-        ),
-    )
+    if block_level is None:
+        database.cursor.execute(
+            "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? LIMIT 1",
+            [
+                blocker,
+                blocked
+            ]
+         )
+    else:
+        database.cursor.execute(
+            "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ? LIMIT 1",
+            [
+                blocker,
+                blocked,
+                block_level
+            ]
+        )
 
     is_blocked = database.cursor.fetchone() is not None
 
index 7402ee5d3b264328f3276bbdc4dc6b5291e3e889..fcfbc6e4f659a839214dc079b982a8ee492f2f9f 100644 (file)
@@ -180,7 +180,7 @@ def fetch_blocks(domain: str, nodeinfo_url: str) -> list:
             rows = fetch_blocks_from_about(domain)
 
         if len(rows) > 0:
-            logger.info("Checking %d entries from domain='%s' ...", len(rows), domain)
+            logger.debug("Checking %d entries from domain='%s' ...", len(rows), domain)
             for block in rows:
                 # Check type
                 logger.debug("block[]='%s'", type(block))
@@ -188,9 +188,9 @@ def fetch_blocks(domain: str, nodeinfo_url: str) -> list:
                     logger.debug("block[]='%s' is of type 'dict' - SKIPPED!", type(block))
                     continue
 
-                reason = tidyup.reason(block["comment"]) if "comment" in block and block['comment'] is not None and block['comment'] != "" else None
+                reason = tidyup.reason(block["comment"]) if "comment" in block and block["comment"] is not None and block["comment"] != "" else None
 
-                logger.debug("Appending blocker='%s',blocked='%s',reason='%s',block_level='%s'", domain, block['domain'], reason, block['severity'])
+                logger.debug("Appending blocker='%s',blocked='%s',reason='%s',block_level='%s'", domain, block["domain"], reason, block["severity"])
                 blocklist.append({
                     "blocker"    : domain,
                     "blocked"    : block["domain"],
index 7ef3e0126bf470d62322d10e1670a79cfb56ea97..8814ea1d9d3d53c66fdc7f39b988b831077940cb 100644 (file)
@@ -179,28 +179,34 @@ def is_domain_wanted(domain: str) -> bool:
     logger.debug("wanted='%s' - EXIT!", wanted)
     return wanted
 
-def deobfuscate_domain(domain: str, blocker: str) -> str:
-    logger.debug("domain='%s',blocker='%s' - CALLED!", domain, blocker)
-    domain_helper.raise_on(domain)
+def deobfuscate_domain(domain: str, blocker: str, domain_hash: str = None) -> str:
+    logger.debug("domain='%s',blocker='%s',domain_hash='%s' - CALLED!", domain, blocker, domain_hash)
     domain_helper.raise_on(blocker)
 
-    if domain.count("*") > 0:
+    if not isinstance(domain, str):
+        raise ValueError(f"Parameter domain[]='{type(domain)}' is not of type 'str'")
+    elif domain == "":
+        raise ValueError("Parameter domain is empty")
+    elif not isinstance(domain_hash, str) and domain_hash is not None:
+        raise ValueError(f"Parameter domain_hash[]='{type(domain_hash)}' is not of type 'str'")
+
+    if domain.count("*") >= 0:
         logger.debug("blocker='%s' uses obfuscated domains, marking ...", blocker)
         instances.set_has_obfuscation(blocker, True)
 
         # Obscured domain name with no hash
-        row = instances.deobfuscate("*", domain)
+        row = instances.deobfuscate("*", domain, domain_hash)
 
         logger.debug("row[]='%s'", type(row))
         if row is not None:
             logger.debug("domain='%s' de-obscured to '%s'", domain, row[0])
             domain = row[0]
-    elif domain.count("?") > 0:
+    elif domain.count("?") >= 0:
         logger.debug("blocker='%s' uses obfuscated domains, marking ...", blocker)
         instances.set_has_obfuscation(blocker, True)
 
         # Obscured domain name with no hash
-        row = instances.deobfuscate("?", domain)
+        row = instances.deobfuscate("?", domain, domain_hash)
 
         logger.debug("row[]='%s'", type(row))
         if row is not None:
@@ -212,29 +218,27 @@ def deobfuscate_domain(domain: str, blocker: str) -> str:
     logger.debug("domain='%s' - EXIT!", domain)
     return domain
 
-def process_block(blocker: str, blocked: str, reason: str, block_level: str):
+def process_block(blocker: str, blocked: str, reason: str, block_level: str) -> bool:
     logger.debug("blocker='%s',blocked='%s',reason='%s',block_level='%s' - CALLED!", blocker, blocked, reason, block_level)
     domain_helper.raise_on(blocker)
     domain_helper.raise_on(blocked)
+    procesed = False
 
     if not isinstance(reason, str) and reason is not None:
-        raise ValueError("Parameter reason[]='%s' is not of type 'str'", type(reason))
+        raise ValueError(f"Parameter reason[]='{type(reason)}' is not of type 'str'")
     elif not isinstance(block_level, str):
-        raise ValueError("Parameter block_level[]='%s' is not of type 'str'", type(block_level))
+        raise ValueError(f"Parameter block_level[]='{type(block_level)}' is not of type 'str'")
     elif block_level == "":
         raise ValueError("Parameter block_level is empty")
 
     if not blocks.is_instance_blocked(blocker, blocked, block_level):
-        logger.debug("Invoking blocks.add_instance(%s, %s, %s, %s)", blocker, blocked, reason, block_level)
+        logger.debug("Invoking blocks.add_instance(%s, %s, %s, %s) ...", blocker, blocked, reason, block_level)
         blocks.add_instance(blocker, blocked, reason, block_level)
-
-        logger.debug("block_level='%s',config[bot_enabled]='%s'", block_level, config.get("bot_enabled"))
-        if config.get("bot_enabled"):
-            logger.debug("blocker='%s' has blocked '%s' with reason='%s' - Adding to bot notification ...", blocker, blocked, reason)
-            blockdict.append({
-                "blocked": blocked,
-                "reason" : reason,
-            })
+        added = True
     else:
         logger.debug("Updating block last seen and reason for blocker='%s',blocked='%s' ...", blocker, blocked)
         blocks.update_last_seen(blocker, blocked, block_level)
+
+    logger.debug("added='%s' - EXIT!", added)
+    return procesed
\ No newline at end of file