import os import secrets import urllib.parse import slugify from ows_text_campaigns.config import settings # https://www.twilio.com/docs/messaging/guides/accepted-mime-types#media-file-name-guidelines HASH_LENGTH = 4 FILENAME_MAX_LENGTH = 20 def unique_hash(size: int | None = HASH_LENGTH) -> str: return secrets.token_urlsafe(size) def get_assets_url(path: str) -> str: return urllib.parse.urljoin( f"https://{settings.assets_cdn_domain}/", urllib.parse.quote_plus(path, safe="/"), ) def create_asset_filename(filename: str) -> str: name, ext = os.path.splitext(filename) slug_part = slugify.slugify(name, max_length=FILENAME_MAX_LENGTH - HASH_LENGTH) return f"{slug_part}__{unique_hash(HASH_LENGTH)}{ext}" def update_asset_key( key: str, *, size: tuple[int, int] | None = None, extension: str | None = None ) -> str: dir_path, filename = os.path.split(key) name, ext = os.path.splitext(filename) slug_part, *_ = name.rsplit("__", 1) slug_part = slugify.slugify(slug_part, lowercase=True) size_suffix = "" if size is not None: width, height = size size_suffix = f"-{width}x{height}" hash_reserved = HASH_LENGTH + 2 # "__" max_slug_len = FILENAME_MAX_LENGTH - len(size_suffix) - hash_reserved slug_part = slug_part[:max_slug_len] if extension is not None: ext = extension if not ext.startswith("."): ext = f".{ext}" return os.path.join( dir_path, f"{slug_part}{size_suffix}__{unique_hash(HASH_LENGTH)}{ext}" )