import socket import json import base64 import ipaddress from urllib.parse import urlparse def load_artwork_settings(settings_data): if not settings_data: return None try: # Пробуем base64 + JSON try: raw = base64.b64decode(settings_data) return json.loads(raw) except: pass # Просто JSON try: return json.loads(settings_data) except: pass # Fallback — plain text description return {'description': settings_data} except: return {'description': settings_data} def save_artwork_description(description): if not description: return None return json.dumps({'description': description}) class ArtworkConfig: def __init__(self, colors=None, animation=False, public=True): self.colors = colors or ["#FF0000", "#00FF00", "#0000FF"] self.animation = animation self.public = public def __repr__(self): return f"ArtworkConfig(colors={self.colors}, animation={self.animation}, public={self.public})" def __str__(self): return self.__repr__() def __reduce__(self): return (self.__class__, (self.colors, self.animation, self.public)) def is_safe_url(url: str): try: parsed = urlparse(url) if parsed.scheme not in ("http", "https"): return False, "403" hostname = parsed.hostname if not hostname: return False, "403" try: ip_str = socket.gethostbyname(hostname) except socket.gaierror: return False, "403" try: ip = ipaddress.ip_address(ip_str) except ValueError: return False, "403" if ( ip.is_loopback or ip.is_private or ip.is_link_local or ip.is_unspecified ): return False, "403" return True, ip_str except Exception: return False, "403"