X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=fba%2Finstances.py;h=d1c27a989fcd7da10a26d7c130fa8c8218569072;hb=88c30cbcf5f275c39bee5426443dd5b30c51281a;hp=af018e4fabdac74769ee97488b31aa04d585a8a4;hpb=2c4499be32b730eae02187a6af5446bf49e26f3f;p=fba.git diff --git a/fba/instances.py b/fba/instances.py index af018e4..d1c27a9 100644 --- a/fba/instances.py +++ b/fba/instances.py @@ -14,14 +14,19 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import json +import requests import sys import time +import validators +from fba import blacklist +from fba import cache from fba import fba # Found info from node, such as nodeinfo URL, detection mode that needs to be # written to database. Both arrays must be filled at the same time or else -# update_instance_data() will fail +# update_data() will fail _pending = { # Detection mode: 'AUTO_DISCOVERY', 'STATIC_CHECKS' or 'GENERATOR' # NULL means all detection methods have failed (maybe still reachable instance) @@ -46,14 +51,14 @@ _pending = { def set(key: str, domain: str, value: any): # DEBUG: print(f"DEBUG: key='{key}',domain='{domain}',value[]='{type(value)}' - CALLED!") - if type(key) != str: + if not isinstance(key, str): raise ValueError("Parameter key[]='{type(key)}' is not 'str'") elif key == "": - raise ValueError(f"Parameter 'key' cannot be empty") - elif type(domain) != str: - raise ValueError("Parameter domain[]='{type(domain)}' is not 'str'") + raise ValueError("Parameter 'key' is empty") + elif not isinstance(domain, str): + raise ValueError(f"Parameter domain[]='{type(domain)}' is not 'str'") elif domain == "": - raise ValueError(f"Parameter 'domain' cannot be empty") + raise ValueError("Parameter 'domain' is empty") elif not key in _pending: raise ValueError(f"key='{key}' not found in _pending") elif not fba.is_primitive(value): @@ -66,10 +71,10 @@ def set(key: str, domain: str, value: any): def has_pending_instance_data(domain: str) -> bool: # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") - if type(domain) != str: + if not isinstance(domain, str): raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") elif domain == "": - raise ValueError(f"Parameter 'domain' cannot be empty") + raise ValueError("Parameter 'domain' is empty") has_pending = False for key in _pending: @@ -81,12 +86,12 @@ def has_pending_instance_data(domain: str) -> bool: # DEBUG: print(f"DEBUG: has_pending='{has_pending}' - EXIT!") return has_pending -def update_instance_data(domain: str): - # DEBUG: print(f"DEBUG: domain={domain} - CALLED!") - if type(domain) != str: +def update_data(domain: str): + # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") + if not isinstance(domain, str): raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") elif domain == "": - raise ValueError(f"Parameter 'domain' cannot be empty") + raise ValueError("Parameter 'domain' is empty") elif not has_pending_instance_data(domain): raise Exception(f"Domain '{domain}' has no pending instance data, but function invoked") @@ -96,9 +101,9 @@ def update_instance_data(domain: str): for key in _pending: # DEBUG: print("DEBUG: key:", key) if domain in _pending[key]: - # DEBUG: print(f"DEBUG: Adding '{_pending[key][domain]}' for key='{key}' ...") - fields.append(_pending[key][domain]) - sql_string += f" {key} = ?," + # DEBUG: print(f"DEBUG: Adding '{_pending[key][domain]}' for key='{key}' ...") + fields.append(_pending[key][domain]) + sql_string += f" {key} = ?," fields.append(time.time()) fields.append(domain) @@ -130,8 +135,179 @@ def update_instance_data(domain: str): except: pass - except BaseException as e: - print(f"ERROR: failed SQL query: domain='{domain}',sql_string='{sql_string}',exception[{type(e)}]:'{str(e)}'") + except BaseException as exception: + print(f"ERROR: failed SQL query: domain='{domain}',sql_string='{sql_string}',exception[{type(exception)}]:'{str(exception)}'") + sys.exit(255) + + # DEBUG: print("DEBUG: EXIT!") + +def update_last_instance_fetch(domain: str): + # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + + # DEBUG: print("DEBUG: Updating last_instance_fetch for domain:", domain) + set("last_instance_fetch", domain, time.time()) + + # Running pending updated + # DEBUG: print(f"DEBUG: Invoking update_data({domain}) ...") + update_data(domain) + + # DEBUG: print("DEBUG: EXIT!") + +def update_last_blocked(domain: str): + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + + # DEBUG: print("DEBUG: Updating last_blocked for domain", domain) + set("last_blocked", domain, time.time()) + + # Running pending updated + # DEBUG: print(f"DEBUG: Invoking update_data({domain}) ...") + update_data(domain) + + # DEBUG: print("DEBUG: EXIT!") + +def add(domain: str, origin: str, command: str, path: str = None): + # DEBUG: print(f"DEBUG: domain='{domain}',origin='{origin}',command='{command}',path='{path}' - CALLED!") + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + elif not isinstance(origin, str) and origin is not None: + raise ValueError(f"origin[]={type(origin)} is not 'str'") + elif origin == "": + raise ValueError("Parameter 'origin' is empty") + elif not isinstance(command, str): + raise ValueError(f"command[]={type(command)} is not 'str'") + elif command == "": + raise ValueError("Parameter 'command' is empty") + elif not validators.domain(domain.split("/")[0]): + raise ValueError(f"Bad domain name='{domain}'") + elif origin is not None and not validators.domain(origin.split("/")[0]): + raise ValueError(f"Bad origin name='{origin}'") + elif blacklist.is_blacklisted(domain): + raise Exception(f"domain='{domain}' is blacklisted, but method invoked") + elif domain.find("/profile/") > 0 or domain.find("/users/") > 0: + raise Exception(f"domain='{domain}' is a single user") + + # DEBUG: print("DEBUG: domain,origin,command,path:", domain, origin, command, path) + software = fba.determine_software(domain, path) + # DEBUG: print("DEBUG: Determined software:", software) + if domain.find("/c/") > 0 and software == "lemmy": + domain = domain.split("/c/")[0] + if is_registered(domain): + print(f"WARNING: domain='{domain}' already registered after cutting off user part. - EXIT!") + return + + print(f"INFO: Adding instance domain='{domain}' (origin='{origin}',software='{software}')") + try: + fba.cursor.execute( + "INSERT INTO instances (domain, origin, command, hash, software, first_seen) VALUES (?, ?, ?, ?, ?, ?)", + ( + domain, + origin, + command, + fba.get_hash(domain), + software, + time.time() + ), + ) + + cache.set_sub_key("is_registered", domain, True) + + if has_pending_instance_data(domain): + # DEBUG: print(f"DEBUG: domain='{domain}' has pending nodeinfo being updated ...") + set("last_status_code" , domain, None) + set("last_error_details", domain, None) + update_data(domain) + fba.remove_pending_error(domain) + + if domain in fba.pending_errors: + # DEBUG: print("DEBUG: domain has pending error being updated:", domain) + update_last_error(domain, fba.pending_errors[domain]) + fba.remove_pending_error(domain) + + except BaseException as exception: + print(f"ERROR: failed SQL query: domain='{domain}',exception[{type(exception)}]:'{str(exception)}'") sys.exit(255) + else: + # DEBUG: print("DEBUG: Updating nodeinfo for domain:", domain) + update_last_nodeinfo(domain) + + # DEBUG: print("DEBUG: EXIT!") + +def update_last_nodeinfo(domain: str): + # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + + # DEBUG: print("DEBUG: Updating last_nodeinfo for domain:", domain) + set("last_nodeinfo", domain, time.time()) + set("last_updated" , domain, time.time()) + + # Running pending updated + # DEBUG: print(f"DEBUG: Invoking update_data({domain}) ...") + update_data(domain) + + # DEBUG: print("DEBUG: EXIT!") + +def update_last_error(domain: str, response: requests.models.Response): + # DEBUG: print("DEBUG: domain,response[]:", domain, type(response)) + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + + # DEBUG: print("DEBUG: BEFORE response[]:", type(response)) + if isinstance(response, BaseException) or isinstance(response, json.decoder.JSONDecodeError): + response = f"{type}:str(response)" + + # DEBUG: print("DEBUG: AFTER response[]:", type(response)) + if isinstance(response, str): + # DEBUG: print(f"DEBUG: Setting last_error_details='{response}'"); + set("last_status_code" , domain, 999) + set("last_error_details", domain, response) + else: + # DEBUG: print(f"DEBUG: Setting last_error_details='{response.reason}'"); + set("last_status_code" , domain, response.status_code) + set("last_error_details", domain, response.reason) + + # Running pending updated + # DEBUG: print(f"DEBUG: Invoking update_data({domain}) ...") + update_data(domain) + + fba.log_error(domain, response) # DEBUG: print("DEBUG: EXIT!") + +def is_registered(domain: str) -> bool: + # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") + if not isinstance(domain, str): + raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'") + elif domain == "": + raise ValueError("Parameter 'domain' is empty") + + # DEBUG: print(f"DEBUG: domain='{domain}' - CALLED!") + if not cache.key_exists("is_registered"): + # DEBUG: print(f"DEBUG: Cache for 'is_registered' not initialized, fetching all rows ...") + try: + fba.cursor.execute("SELECT domain FROM instances") + + # Check Set all + cache.set_all("is_registered", fba.cursor.fetchall(), True) + except BaseException as exception: + print(f"ERROR: failed SQL query: domain='{domain}',exception[{type(exception)}]:'{str(exception)}'") + sys.exit(255) + + # Is cache found? + registered = cache.sub_key_exists("is_registered", domain) + + # DEBUG: print(f"DEBUG: registered='{registered}' - EXIT!") + return registered