Source code for kiosk_show_replacement.utils

"""
Utility functions for kiosk-show-replacement.

This module contains helper functions for file handling, URL validation,
and other common operations.
"""

import mimetypes
import os
import secrets
import string
from typing import Optional
from urllib.parse import urlparse

import requests
from PIL import Image


[docs] def generate_random_password(length: int = 8) -> str: """ Generate a random password of the specified length. Args: length: The desired password length (default: 8) Returns: A random password string containing letters and digits. """ alphabet = string.ascii_letters + string.digits return "".join(secrets.choice(alphabet) for _ in range(length))
[docs] def is_valid_url(url: str) -> bool: """ Check if a URL is valid and accessible. Args: url (str): URL to validate Returns: bool: True if URL is valid and accessible """ try: parsed = urlparse(url) if not all([parsed.scheme, parsed.netloc]): return False # Try to make a HEAD request to check if URL is accessible response = requests.head(url, timeout=5, allow_redirects=True) return response.status_code < 400 except Exception: return False
[docs] def is_image_url(url: str) -> bool: """ Check if a URL points to an image file. Args: url (str): URL to check Returns: bool: True if URL appears to be an image """ try: # Check by file extension first parsed = urlparse(url) path = parsed.path.lower() image_extensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg"} if any(path.endswith(ext) for ext in image_extensions): return True # Check by making a HEAD request and checking content-type response = requests.head(url, timeout=5, allow_redirects=True) content_type = response.headers.get("content-type", "").lower() return content_type.startswith("image/") except Exception: return False
[docs] def validate_image_file(file_path: str) -> bool: """ Validate that a file is a valid image. Args: file_path (str): Path to the image file Returns: bool: True if file is a valid image """ try: with Image.open(file_path) as img: img.verify() return True except Exception: return False
[docs] def get_file_mimetype(file_path: str) -> Optional[str]: """ Get the MIME type of a file. Args: file_path (str): Path to the file Returns: str: MIME type of the file """ mimetype, _ = mimetypes.guess_type(file_path) return mimetype or "application/octet-stream"
[docs] def ensure_directory_exists(directory_path: str) -> None: """ Ensure that a directory exists, creating it if necessary. Args: directory_path (str): Path to the directory """ os.makedirs(directory_path, exist_ok=True)
[docs] def sanitize_filename(filename: str) -> str: """ Sanitize a filename by removing potentially dangerous characters. Args: filename (str): Original filename Returns: str: Sanitized filename """ # Remove potentially dangerous characters dangerous_chars = '<>:"/\\|?*' for char in dangerous_chars: filename = filename.replace(char, "_") # Remove leading/trailing whitespace and dots filename = filename.strip(". ") # Ensure filename is not empty if not filename: filename = "unnamed_file" return filename