初始提交
This commit is contained in:
+107
@@ -0,0 +1,107 @@
|
||||
import os
|
||||
import uuid
|
||||
import logging
|
||||
import mimetypes
|
||||
|
||||
import requests
|
||||
|
||||
import config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
IMAGE_MIME_TYPES = {
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/bmp",
|
||||
"image/gif",
|
||||
"image/webp",
|
||||
"image/tiff",
|
||||
}
|
||||
|
||||
EXT_MAP = {
|
||||
"image/jpeg": ".jpg",
|
||||
"image/png": ".png",
|
||||
"image/bmp": ".bmp",
|
||||
"image/gif": ".gif",
|
||||
"image/webp": ".webp",
|
||||
"image/tiff": ".tiff",
|
||||
}
|
||||
|
||||
|
||||
def _detect_ext(response) -> str:
|
||||
content_type = response.headers.get("Content-Type", "").split(";")[0].strip().lower()
|
||||
if content_type in EXT_MAP:
|
||||
return EXT_MAP[content_type]
|
||||
|
||||
url_path = response.url.split("?")[0]
|
||||
guessed, _ = mimetypes.guess_type(url_path)
|
||||
if guessed and guessed in EXT_MAP:
|
||||
return EXT_MAP[guessed]
|
||||
|
||||
return ".jpg"
|
||||
|
||||
|
||||
def fetch_wallpaper() -> str:
|
||||
cfg = config.load()
|
||||
api = cfg["api"]
|
||||
wallpaper_cfg = cfg["wallpaper"]
|
||||
|
||||
url = api["url"]
|
||||
mode = api.get("mode", "direct")
|
||||
timeout = api.get("timeout", 30)
|
||||
|
||||
cache_dir = wallpaper_cfg.get("cache_dir", "./cache")
|
||||
cache_dir = _resolve_cache(cache_dir)
|
||||
os.makedirs(cache_dir, exist_ok=True)
|
||||
|
||||
if mode == "json":
|
||||
image_url = _fetch_json(url, api.get("json_image_field", "url"), timeout)
|
||||
response = _download(image_url, timeout)
|
||||
else:
|
||||
response = _download(url, timeout)
|
||||
|
||||
ext = _detect_ext(response)
|
||||
filename = f"{uuid.uuid4().hex}{ext}"
|
||||
filepath = os.path.join(cache_dir, filename)
|
||||
|
||||
with open(filepath, "wb") as f:
|
||||
f.write(response.content)
|
||||
|
||||
logger.info("Wallpaper saved to: %s", filepath)
|
||||
max_cache = cfg["wallpaper"].get("max_cache_files", 10)
|
||||
_cleanup_cache(cache_dir, keep=max_cache)
|
||||
return filepath
|
||||
|
||||
|
||||
def _fetch_json(url: str, field: str, timeout: int) -> str:
|
||||
r = requests.get(url, timeout=timeout)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
image_url = data.get(field)
|
||||
if not image_url:
|
||||
raise ValueError(f"Field '{field}' not found in JSON response")
|
||||
return image_url
|
||||
|
||||
|
||||
def _download(url: str, timeout: int) -> requests.Response:
|
||||
r = requests.get(url, timeout=timeout, stream=True)
|
||||
r.raise_for_status()
|
||||
return r
|
||||
|
||||
|
||||
def _resolve_cache(cache_dir: str) -> str:
|
||||
if os.path.isabs(cache_dir):
|
||||
return cache_dir
|
||||
base = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.normpath(os.path.join(base, cache_dir))
|
||||
|
||||
|
||||
def _cleanup_cache(cache_dir: str, keep: int) -> None:
|
||||
try:
|
||||
files = [os.path.join(cache_dir, f) for f in os.listdir(cache_dir)]
|
||||
files = [f for f in files if os.path.isfile(f)]
|
||||
files.sort(key=os.path.getmtime, reverse=True)
|
||||
for old in files[keep:]:
|
||||
os.remove(old)
|
||||
except Exception:
|
||||
pass
|
||||
Reference in New Issue
Block a user