77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""Shared media type constants and helpers.
|
|
|
|
Single source of truth for the file extensions and MIME types handled by the
|
|
image support (roadmap #108) and reused by the audio/video players (#109).
|
|
Keeping these sets here avoids the previous duplication (``indexer.py``,
|
|
``attachment_indexer.py`` and ``main.py`` each carried their own copy).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import mimetypes
|
|
|
|
# Image extensions viewable in the browser (HEIC/HEIF deliberately excluded —
|
|
# no browser decodes them natively; see roadmap #108).
|
|
IMAGE_EXTENSIONS: frozenset[str] = frozenset({
|
|
".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".bmp", ".ico",
|
|
})
|
|
|
|
# Audio extensions (socle for #109, not wired into the index yet).
|
|
AUDIO_EXTENSIONS: frozenset[str] = frozenset({
|
|
".mp3", ".m4a", ".aac", ".wav", ".ogg", ".oga", ".opus", ".flac",
|
|
})
|
|
|
|
# Video extensions (socle for #109, not wired into the index yet).
|
|
VIDEO_EXTENSIONS: frozenset[str] = frozenset({
|
|
".mp4", ".webm", ".mov", ".m4v",
|
|
})
|
|
|
|
MEDIA_EXTENSIONS: frozenset[str] = IMAGE_EXTENSIONS | AUDIO_EXTENSIONS | VIDEO_EXTENSIONS
|
|
|
|
# Explicit MIME types for extensions ``mimetypes`` gets wrong or does not know.
|
|
_MIME_OVERRIDES: dict[str, str] = {
|
|
".jpg": "image/jpeg",
|
|
".jpeg": "image/jpeg",
|
|
".svg": "image/svg+xml",
|
|
".ico": "image/x-icon",
|
|
".webp": "image/webp",
|
|
".m4a": "audio/mp4",
|
|
".oga": "audio/ogg",
|
|
".opus": "audio/ogg",
|
|
".mov": "video/quicktime",
|
|
".m4v": "video/mp4",
|
|
}
|
|
|
|
|
|
def is_image(ext: str) -> bool:
|
|
"""Return True when *ext* (with leading dot, any case) is an image."""
|
|
return ext.lower() in IMAGE_EXTENSIONS
|
|
|
|
|
|
def is_audio(ext: str) -> bool:
|
|
"""Return True when *ext* is an audio extension."""
|
|
return ext.lower() in AUDIO_EXTENSIONS
|
|
|
|
|
|
def is_video(ext: str) -> bool:
|
|
"""Return True when *ext* is a video extension."""
|
|
return ext.lower() in VIDEO_EXTENSIONS
|
|
|
|
|
|
def is_media(ext: str) -> bool:
|
|
"""Return True when *ext* is any supported image/audio/video extension."""
|
|
return ext.lower() in MEDIA_EXTENSIONS
|
|
|
|
|
|
def media_mime_type(path: str) -> str:
|
|
"""Return the best MIME type for *path* (extension based).
|
|
|
|
Falls back to ``application/octet-stream`` when the type is unknown.
|
|
"""
|
|
lower = path.lower()
|
|
for ext, mime in _MIME_OVERRIDES.items():
|
|
if lower.endswith(ext):
|
|
return mime
|
|
guessed, _ = mimetypes.guess_type(path)
|
|
return guessed or "application/octet-stream"
|