diff --git a/MANIFEST.in b/MANIFEST.in index b4ee2e95b..b3e17ce6b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,6 +16,7 @@ recursive-include changedetectionio/widgets * prune changedetectionio/static/package-lock.json prune changedetectionio/static/styles/node_modules prune changedetectionio/static/styles/package-lock.json +include changedetectionio/favicon_utils.py include changedetection.py include requirements.txt include README-pip.md diff --git a/changedetectionio/favicon_utils.py b/changedetectionio/favicon_utils.py new file mode 100644 index 000000000..e2274adab --- /dev/null +++ b/changedetectionio/favicon_utils.py @@ -0,0 +1,43 @@ +""" +Favicon utilities for changedetection.io +Handles favicon MIME type detection with caching +""" + +from functools import lru_cache + + +@lru_cache(maxsize=1000) +def get_favicon_mime_type(filepath): + """ + Detect MIME type of favicon by reading file content using puremagic. + Results are cached to avoid repeatedly reading the same files. + + Args: + filepath: Full path to the favicon file + + Returns: + MIME type string (e.g., 'image/png') + """ + mime = None + + try: + import puremagic + with open(filepath, 'rb') as f: + content_bytes = f.read(200) # Read first 200 bytes + + detections = puremagic.magic_string(content_bytes) + if detections: + mime = detections[0].mime_type + except Exception: + pass + + # Fallback to mimetypes if puremagic fails + if not mime: + import mimetypes + mime, _ = mimetypes.guess_type(filepath) + + # Final fallback based on extension + if not mime: + mime = 'image/x-icon' if filepath.endswith('.ico') else 'image/png' + + return mime