mirror of
http://git.nowherejezfoltodf4jiyl6r56jnzintap5vyjlia7fkirfsnfizflqd.onion/nihilist/darknet-lantern.git
synced 2025-07-02 06:46:42 +00:00
utils.py refactoring
This commit is contained in:
parent
b8b4a770ce
commit
08697f5c40
1 changed files with 210 additions and 268 deletions
236
scripts/utils.py
236
scripts/utils.py
|
@ -15,6 +15,31 @@ RED = '\033[31;40m'
|
||||||
BOLD_RED = '\033[31;40;1m'
|
BOLD_RED = '\033[31;40;1m'
|
||||||
RESET = '\033[m'
|
RESET = '\033[m'
|
||||||
|
|
||||||
|
# name should contain only up to 64 alphanumeric characters
|
||||||
|
VALID_NAME_PATTERN = re.compile(r"^[A-Za-z0-9]{1,64}$")
|
||||||
|
|
||||||
|
# pattern for regular urls
|
||||||
|
# TODO: this is very simplified pattern
|
||||||
|
URL_PATTERN = re.compile(r"^[A-Za-z0-9:\/\._%-=#?&@]+$")
|
||||||
|
|
||||||
|
# pattern for onion urls (56 bytes of base32 alphabet + .onion)
|
||||||
|
ONION_URL_PATTERN = re.compile(r"^(\w+:)?(?:\/\/)?(\w+\.)?[a-z2-7]{56}\.onion")
|
||||||
|
|
||||||
|
|
||||||
|
def print_colors(s:str=' ', bold:bool=False, is_error:bool = False, default:bool=False):
|
||||||
|
"""
|
||||||
|
Helper function to print with colors
|
||||||
|
"""
|
||||||
|
if is_error:
|
||||||
|
print(f"{RED}{s}{RESET}")
|
||||||
|
elif bold:
|
||||||
|
print(f"{BOLD_PURPLE}{s}{RESET}")
|
||||||
|
elif is_error and bold:
|
||||||
|
print(f"{BOLD_RED}{s}{RESET}")
|
||||||
|
elif default:
|
||||||
|
print(f'{s}')
|
||||||
|
else:
|
||||||
|
print(f"{PURPLE}{s}{RESET}")
|
||||||
|
|
||||||
|
|
||||||
#### Checking Functions to validate that links are legit ####
|
#### Checking Functions to validate that links are legit ####
|
||||||
|
@ -29,13 +54,10 @@ def CheckUrl(url):
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
status = requests.get(url, proxies=proxies, timeout=5).status_code
|
status = requests.get(url, proxies=proxies, timeout=5).status_code
|
||||||
if status != 502:
|
return bool(status == 200)
|
||||||
return True
|
except requests.ConnectionError:
|
||||||
else:
|
|
||||||
return False
|
return False
|
||||||
except requests.ConnectionError as e:
|
except requests.exceptions.ReadTimeout:
|
||||||
return False
|
|
||||||
except requests.exceptions.ReadTimeout as e:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +68,7 @@ def IsBannerValid(path: str) -> bool:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
im = Image.open(path)
|
im = Image.open(path)
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print("ERROR, EXCEPTION")
|
print("ERROR, EXCEPTION")
|
||||||
return False
|
return False
|
||||||
width, height = im.size
|
width, height = im.size
|
||||||
|
@ -65,37 +87,21 @@ def IsOnionValid(url: str)-> bool:
|
||||||
Checks if the domain(param) is a valid onion domain and return True else False.
|
Checks if the domain(param) is a valid onion domain and return True else False.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
pattern = re.compile("^[A-Za-z0-9.]+(.onion)?$")
|
# make sure the protocol is there
|
||||||
url = url.strip().removesuffix('/')
|
if not url.startswith(('http://', 'https://')):
|
||||||
if url.startswith('http://'):
|
url = 'http://' + url.strip().removesuffix('/')
|
||||||
|
|
||||||
domain = url.split('/')[2]
|
domain = url.split('/')[2]
|
||||||
if pattern.fullmatch(domain) is not None:
|
|
||||||
if len(domain.split('.')) > 3:
|
if ONION_URL_PATTERN.fullmatch(domain):
|
||||||
return False
|
parts_count = len(domain.split('.'))
|
||||||
else:
|
# TODO: we probably don't really need to check 62 char length
|
||||||
if len(domain) < 62:
|
# regex does that beforehand
|
||||||
return False
|
return (len(domain) == 62) and (parts_count <= 3)
|
||||||
return True
|
except Exception:
|
||||||
elif pattern.fullmatch(domain) is None:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
#TODO : edit the url to make sure it has http:// at the beginning, in case if it's missing? (problem is that it only returns true or false)
|
|
||||||
if pattern.fullmatch(url) is not None:
|
|
||||||
if len(url.split('.')) > 3:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
if len(url) < 62:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
elif pattern.fullmatch(url) is None:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def IsSimpleXChatroomValid(url: str) -> bool:
|
def IsSimpleXChatroomValid(url: str) -> bool:
|
||||||
"""Validate the SimpleX chatroom URL."""
|
"""Validate the SimpleX chatroom URL."""
|
||||||
REQUIRED_SUBSTRING = "#/?v=2-7&smp=smp%3A%2F"
|
REQUIRED_SUBSTRING = "#/?v=2-7&smp=smp%3A%2F"
|
||||||
|
@ -103,7 +109,8 @@ def IsSimpleXChatroomValid(url: str) -> bool:
|
||||||
# Step 1: Check if it starts with http://, https://, or simplex:/
|
# Step 1: Check if it starts with http://, https://, or simplex:/
|
||||||
if url.startswith(('http://', 'https://', 'simplex:/')):
|
if url.startswith(('http://', 'https://', 'simplex:/')):
|
||||||
# Step 1.5: If http:// or https://, check for valid clearnet or onion domain
|
# Step 1.5: If http:// or https://, check for valid clearnet or onion domain
|
||||||
if url.startswith(('http://', 'https://')) and not IsUrlValid(url):
|
if url.startswith(('http://', 'https://')) \
|
||||||
|
and RecognizeUrlOnionClear(url) != 'invalid':
|
||||||
return False
|
return False
|
||||||
elif not url.startswith('simplex:/'):
|
elif not url.startswith('simplex:/'):
|
||||||
return False # Must start with one of the valid protocols
|
return False # Must start with one of the valid protocols
|
||||||
|
@ -129,7 +136,7 @@ def IsSimpleXChatroomValid(url: str) -> bool:
|
||||||
return False # Must contain '@' to separate fingerprint and hostname
|
return False # Must contain '@' to separate fingerprint and hostname
|
||||||
|
|
||||||
fingerprint, hostname = smp_value.split('@', 1)
|
fingerprint, hostname = smp_value.split('@', 1)
|
||||||
if not IsUrlValid(hostname):
|
if RecognizeUrlOnionClear(hostname) != 'invalid':
|
||||||
return False # Invalid hostname
|
return False # Invalid hostname
|
||||||
|
|
||||||
# Step 4: Check for the presence of "%2F" in the original URL
|
# Step 4: Check for the presence of "%2F" in the original URL
|
||||||
|
@ -139,26 +146,43 @@ def IsSimpleXChatroomValid(url: str) -> bool:
|
||||||
# If all checks pass, return True
|
# If all checks pass, return True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def IsUrlValid(url:str)->bool:
|
def RecognizeUrlOnionClear(url: str) -> str:
|
||||||
"""
|
"""
|
||||||
Check if url is valid both dark net end clearnet.
|
Recognize if the URL is invalid, onion or clearnet.
|
||||||
"""
|
"""
|
||||||
pattern = re.compile(r"^[A-Za-z0-9:/._%-=#?&@]+$")
|
|
||||||
onion_pattern = re.compile(r"^(\w+:)?(?://)?(\w+\.)?[a-z2-7]{56}\.onion")
|
|
||||||
url = str(url)
|
|
||||||
if len(url) < 4:
|
|
||||||
return False
|
|
||||||
if onion_pattern.match(url) is not None:
|
|
||||||
return IsOnionValid(url)
|
|
||||||
else:
|
|
||||||
if not url.__contains__('.'):
|
|
||||||
return False
|
|
||||||
if url.__contains__(';'):
|
|
||||||
return False #required otherwise lantern thinks there are extra columns
|
|
||||||
if pattern.fullmatch(url) is None:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
# early terminate preconditions
|
||||||
|
if len(url) < 4 or (';' in url) or ('.' not in url):
|
||||||
|
return 'invalid'
|
||||||
|
|
||||||
|
# check if possibly onion url, here just perliminary check
|
||||||
|
# IsOnionValid checks it against regex expression
|
||||||
|
if '.onion' in url:
|
||||||
|
if IsOnionValid(url):
|
||||||
|
return 'onion'
|
||||||
|
|
||||||
|
if URL_PATTERN.fullmatch(url):
|
||||||
|
return 'clearnet'
|
||||||
|
|
||||||
|
return 'invalid'
|
||||||
|
|
||||||
|
|
||||||
|
def RecognizeUrlFull(url: str) -> str:
|
||||||
|
"""
|
||||||
|
Recognize if URL is smp, xftp, simplex groupchat, onion, clearnet or just invalid
|
||||||
|
Depends on RecognizeUrlOnionClear
|
||||||
|
"""
|
||||||
|
if IsSimpleXChatroomValid(url):
|
||||||
|
return 'chatroom'
|
||||||
|
if url.startswith(('http://', 'https://')):
|
||||||
|
return RecognizeUrlOnionClear(url)
|
||||||
|
if url.startswith('xftp://'):
|
||||||
|
if IsSimpleXServerValid(url):
|
||||||
|
return 'xftp'
|
||||||
|
if url.startswith('smp://'):
|
||||||
|
if IsSimpleXServerValid(url):
|
||||||
|
return 'smp'
|
||||||
|
return 'invalid'
|
||||||
|
|
||||||
#def IsUrlValid(url:str)->bool:
|
#def IsUrlValid(url:str)->bool:
|
||||||
# """
|
# """
|
||||||
|
@ -183,10 +207,8 @@ def IsStatusValid(status: str)-> bool:
|
||||||
Checks if status contains only ['YES','NO']. Verbose only if False is returned
|
Checks if status contains only ['YES','NO']. Verbose only if False is returned
|
||||||
"""
|
"""
|
||||||
pattern = ['YES','NO','✔️','❌','']
|
pattern = ['YES','NO','✔️','❌','']
|
||||||
#pattern = ['YES','NO']
|
status = status.strip()
|
||||||
status = str(status)
|
if status not in pattern:
|
||||||
status.strip()
|
|
||||||
if (status not in pattern):
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -203,7 +225,7 @@ def IsScoreValid(score:str)->bool:
|
||||||
return True
|
return True
|
||||||
if pattern.fullmatch(score) is None:
|
if pattern.fullmatch(score) is None:
|
||||||
return False
|
return False
|
||||||
elif len(score) > 8:
|
if len(score) > 8:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -214,7 +236,7 @@ def IsDescriptionValid(desc:str)->bool:
|
||||||
"""
|
"""
|
||||||
if desc == "":
|
if desc == "":
|
||||||
return True
|
return True
|
||||||
pattern = re.compile("^[A-Za-z0-9-.,' \"\(\)\/]+$")
|
pattern = re.compile(r"^[A-Za-z0-9-.,' \"\(\)\/]+$")
|
||||||
desc = str(desc)
|
desc = str(desc)
|
||||||
desc.strip()
|
desc.strip()
|
||||||
if pattern.fullmatch(desc) is None:
|
if pattern.fullmatch(desc) is None:
|
||||||
|
@ -225,7 +247,8 @@ def IsDescriptionValid(desc:str)->bool:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def IsCategoryValid(categories: list)-> bool:
|
|
||||||
|
def IsCategoryValid(categories: list[str]) -> bool:
|
||||||
"""
|
"""
|
||||||
Check the categories are only [a-zA-Z0-9 ] with 64 max chars.
|
Check the categories are only [a-zA-Z0-9 ] with 64 max chars.
|
||||||
"""
|
"""
|
||||||
|
@ -240,7 +263,6 @@ def IsCategoryValid(categories: list)-> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def IsSimpleXServerValid(url: str) -> bool:
|
def IsSimpleXServerValid(url: str) -> bool:
|
||||||
pattern = re.compile('[0-9A-Za-z-_]*')
|
pattern = re.compile('[0-9A-Za-z-_]*')
|
||||||
url = url.strip()
|
url = url.strip()
|
||||||
|
@ -260,12 +282,11 @@ def IsSimpleXServerValid(url: str) -> bool:
|
||||||
# Check fingerprint length and pattern
|
# Check fingerprint length and pattern
|
||||||
if len(fingerprint) == 44 and pattern.match(fingerprint):
|
if len(fingerprint) == 44 and pattern.match(fingerprint):
|
||||||
# Validate the hostname
|
# Validate the hostname
|
||||||
result = IsSimpleXUrlValid(hostname)
|
if RecognizeUrlOnionClear(hostname) != 'invalid':
|
||||||
if result:
|
|
||||||
# Check for an optional comma and a valid onion domain
|
# Check for an optional comma and a valid onion domain
|
||||||
if ',' in proless:
|
if ',' in proless:
|
||||||
onion_part = proless.split(',')[1].strip()
|
onion_part = proless.split(',')[1].strip()
|
||||||
if not hostname_pattern.match(onion_part):
|
if RecognizeUrlOnionClear(onion_part) != 'invalid':
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -281,91 +302,12 @@ def IsNameValid(name: str)->bool:
|
||||||
Check the parameter name only contains [a-zA-Z0-9] and is 64 chars long.
|
Check the parameter name only contains [a-zA-Z0-9] and is 64 chars long.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
name = str(name)
|
return bool(VALID_NAME_PATTERN.fullmatch(name.strip()))
|
||||||
except Exception as e:
|
except Exception:
|
||||||
return False
|
|
||||||
pattern = re.compile("^[A-Za-z0-9 ]+$")
|
|
||||||
name = name.strip()
|
|
||||||
if (pattern.fullmatch(name) is None):
|
|
||||||
return False
|
|
||||||
elif len(name) > 64:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def print_colors(s:str=' ', bold:bool=False, is_error:bool = False, default:bool=False):
|
|
||||||
"""
|
|
||||||
Helper function to print with colors
|
|
||||||
"""
|
|
||||||
if is_error:
|
|
||||||
print(f"{RED}{s}{RESET}")
|
|
||||||
elif bold:
|
|
||||||
print(f"{BOLD_PURPLE}{s}{RESET}")
|
|
||||||
elif is_error and bold:
|
|
||||||
print(f"{BOLD_RED}{s}{RESET}")
|
|
||||||
elif default:
|
|
||||||
print(f'{s}')
|
|
||||||
else:
|
|
||||||
print(f"{PURPLE}{s}{RESET}")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def IsSimpleXOnionValid(url: str)-> bool:
|
|
||||||
"""
|
|
||||||
Checks if the domain(param) is a valid onion domain and return True else False.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
pattern = re.compile(r"^[A-Za-z0-9:/._%-=#?&@]+(.onion)$")
|
|
||||||
url_pattern = re.compile(r"^(\w+:)?(?://)?(\w+\.)?[a-z2-7]{56}\.onion")
|
|
||||||
url = url.strip().removesuffix('/')
|
|
||||||
if url.startswith('http://'):
|
|
||||||
domain = url.split('/')[2]
|
|
||||||
if pattern.fullmatch(domain) is not None:
|
|
||||||
if len(domain.split('.')) > 3:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
if len(domain) < 62:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
elif pattern.fullmatch(domain) is None:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
#TODO : edit the url to make sure it has http:// at the beginning, in case if it's missing? (problem is that it only returns true or false)
|
|
||||||
if url_pattern.match(url) is not None:
|
|
||||||
if len(url.split('.')) > 3:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
if len(url) < 62:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
elif url_pattern.match(url) is None:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def IsSimpleXUrlValid(url:str)->bool:
|
|
||||||
"""
|
|
||||||
Check if url is valid both dark net end clearnet.
|
|
||||||
"""
|
|
||||||
pattern = re.compile(r"^[A-Za-z0-9:/._%-=#?&@]+$")
|
|
||||||
onion_pattern = re.compile(r"^(\w+:)?(?://)?(\w+\.)?[a-z2-7]{56}\.onion")
|
|
||||||
url = str(url)
|
|
||||||
if len(url) < 4:
|
|
||||||
return False
|
|
||||||
if onion_pattern.match(url) is not None:
|
|
||||||
return IsSimpleXOnionValid(url)
|
|
||||||
else:
|
|
||||||
if not url.__contains__('.'):
|
|
||||||
return False
|
|
||||||
if pattern.fullmatch(url) is None:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def send_server_checks(url:str) -> ():
|
def send_server_checks(url: str) -> tuple[str, str, str]:
|
||||||
"""
|
"""
|
||||||
Sends requests to sxc websocket and retuns
|
Sends requests to sxc websocket and retuns
|
||||||
response, response type and testFailure or None.
|
response, response type and testFailure or None.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue