feat: list traversal improvements with safeTraverse()

translateLinks() also now strips any params (if present) by default
This commit is contained in:
2025-09-25 06:34:13 +02:00
parent 873abbd413
commit caa9e0c2b1

View File

@@ -84,26 +84,64 @@ def getHeaders(caller="proxy"):
return headers return headers
def translateLinks(link): def translateLinks(link: str, remove_params: bool = True):
link = link.replace("https://i.ytimg.com/", config['general']['public_facing_url']) link = link.replace("https://i.ytimg.com/", config['general']['public_facing_url'])
link = link.replace("https://yt3.ggpht.com/", config['general']['public_facing_url'] + "ggpht/") link = link.replace("https://yt3.ggpht.com/", config['general']['public_facing_url'] + "ggpht/")
link = link.replace("https://yt3.googleusercontent.com/", config['general']['public_facing_url'] + "guc/") link = link.replace("https://yt3.googleusercontent.com/", config['general']['public_facing_url'] + "guc/")
# try to remove tracking params
if remove_params and "?" in link:
link = link[:link.find("?")]
return link return link
def getUptime(): def getUptime():
return int(time.time()) - starttime return int(time.time()) - starttime
def safeTraverse(obj: dict, path: list, default=None, quiet: bool = False): def safeTraverse(obj: dict, path: list, default=None, quiet: bool = False):
"""
Traverse dynamic objects with fallback to default values
This function can take an Ellipsis as part of traversal path,
meaning that it will return the object from the list
that contains the next key. This has been introduced
so that no matter which object in a list holds the relevant
model, it will find it (meaning no assumptions are necessary).
Kepp in mind that only one ellipsis at a time is supported,
thus ["some_key", ..., ..., "some_other_key"] won't work.
:param obj: Traversed object
:type obj: dict
:param path: Path which shall be traversed
:type path: list
:param default: Default value returned on failure
:type default: any, None by default
:param quiet: Quiet flag
:type quiet: bool
"""
result = obj result = obj
try: try:
for x in path: # for every item in path and its position
#print(f"traversing {result} with respect to {x}") for pos, iterable_key in enumerate(path):
result = result[x] # if the key is not an ellipsis, traverse it
if iterable_key is not Ellipsis:
result = result[iterable_key]
# if it is an ellipsis, and there is another key beside it
elif pos < len(path) - 1:
# then iterate through all of the list contents
for list_content in result:
# in search of the next traversal key
if path[pos + 1] in list_content:
result = list_content
# show an error message if ellipsis is used incorrectly
else:
print("error(safeTraverse): Traversal path can't end with an Ellipsis!")
raise TypeError()
# handle exceptions
except (KeyError, TypeError, IndexError): except (KeyError, TypeError, IndexError):
result = default result = default
if not quiet: print(f"error reading: {' -> '.join(path)} - returning: {default}") if not quiet: print(f"error reading: {' -> '.join([str(x) for x in path])} - returning: {default}")
finally: finally:
return result return result