DispelEvilBot/admin/media.py

57 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Общий каталог картинок для бота и админки (Docker volume)."""
from __future__ import annotations
import logging
import shutil
from pathlib import Path
from starlette.datastructures import UploadFile
from common.config import AdminSettings
logger = logging.getLogger(__name__)
#: Встроенная картинка приветствия (лежит в образе бота и админки).
BUILTIN_WELCOME = Path("images/welcome_image.jpg")
#: Имя файла в volume, которое ждёт сид последовательности `welcome`.
WELCOME_IMAGE_NAME = "welcome_image.jpg"
#: Допустимые типы и максимальный размер загружаемых картинок.
ALLOWED_IMAGE_TYPES = {"image/jpeg": ".jpg", "image/png": ".png", "image/webp": ".webp"}
MAX_IMAGE_BYTES = 5 * 1024 * 1024
async def read_image(upload: UploadFile) -> tuple[bytes, str, str]:
"""Прочитать картинку из формы. Возвращает (данные, mime, расширение)."""
content_type = (upload.content_type or "").lower()
extension = ALLOWED_IMAGE_TYPES.get(content_type)
if extension is None:
raise ValueError("Картинка должна быть JPEG, PNG или WebP")
data = await upload.read()
if len(data) > MAX_IMAGE_BYTES:
raise ValueError("Картинка больше 5 МБ")
return data, content_type, extension
def ensure_media(settings: AdminSettings) -> Path:
"""Создать каталог и положить туда встроенное приветствие, если его нет."""
directory = Path(settings.media_dir)
directory.mkdir(parents=True, exist_ok=True)
target = directory / WELCOME_IMAGE_NAME
if not target.exists() and BUILTIN_WELCOME.is_file():
try:
shutil.copyfile(BUILTIN_WELCOME, target)
logger.info("Приветственная картинка скопирована в %s", target)
except OSError:
logger.warning("Не удалось скопировать приветственную картинку в %s", target, exc_info=True)
return directory
def media_path(settings: AdminSettings, name: str) -> Path:
"""Безопасный путь к файлу в media (без выхода из каталога)."""
return Path(settings.media_dir) / Path(name).name