import hashlib import io import random import requests from PIL import Image OPENVERSE_URL = "https://api.openverse.engineering/v1/images/" DEFAULT_QUERIES = ( "nature landscape", "scenic outdoor", "abstract texture background", "colorful sky", "urban architecture", "peaceful garden", "ocean horizon", "mountain vista", ) USER_AGENT = "cursor-pilot-background-fetch/1.0" def _download_image(url: str, timeout: int = 25) -> Image.Image | None: try: resp = requests.get( url, timeout=timeout, headers={"User-Agent": USER_AGENT}, ) resp.raise_for_status() img = Image.open(io.BytesIO(resp.content)) img.load() return img.convert("RGB") except (OSError, requests.RequestException): return None def _search_openverse(query: str, page_size: int = 20) -> list[str]: page = random.randint(1, 5) try: resp = requests.get( OPENVERSE_URL, params={ "q": query, "license": "cc0,by,by-sa", "page_size": page_size, "page": page, "mature": "false", }, timeout=25, headers={"User-Agent": USER_AGENT}, ) resp.raise_for_status() data = resp.json() except (requests.RequestException, ValueError): return [] urls = [] for item in data.get("results", []): url = item.get("url") or item.get("thumbnail") if url and url.startswith("http"): urls.append(url) random.shuffle(urls) return urls def _fit_background(image: Image.Image, size: tuple[int, int]) -> Image.Image: target_w, target_h = size src_w, src_h = image.size scale = max(target_w / src_w, target_h / src_h) new_w, new_h = int(src_w * scale), int(src_h * scale) resized = image.resize((new_w, new_h), Image.Resampling.LANCZOS) left = (new_w - target_w) // 2 top = (new_h - target_h) // 2 return resized.crop((left, top, left + target_w, top + target_h)).convert("RGB") def fetch_public_background( query: str | None, size: tuple[int, int], max_attempts: int = 8, ) -> tuple[Image.Image, dict]: """Fetch a CC-licensed background from Openverse (always from the web, no local assets).""" search_query = query or random.choice(DEFAULT_QUERIES) urls = _search_openverse(search_query) for url in urls[:max_attempts]: img = _download_image(url) if img is None or min(img.size) < 240: continue fitted = _fit_background(img, size) digest = hashlib.sha1(url.encode()).hexdigest()[:10] return fitted, { "query": search_query, "source": "openverse", "image_id": digest, } fallback = Image.new("RGB", size, color=(100, 140, 180)) return fallback, { "query": search_query, "source": "fallback", "image_id": "none", }