refactor list of know file types/mimes
This commit is contained in:
parent
41ef49293e
commit
ad884a13ad
|
@ -5,12 +5,12 @@ import cherrypy
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from photoapp.thumb import ThumbGenerator
|
from photoapp.thumb import ThumbGenerator
|
||||||
from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User
|
from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User, mime2ext
|
||||||
from photoapp.dbsession import DatabaseSession
|
from photoapp.dbsession import DatabaseSession
|
||||||
from photoapp.common import pwhash
|
from photoapp.common import pwhash
|
||||||
from photoapp.api import PhotosApi, LibraryManager
|
from photoapp.api import PhotosApi, LibraryManager
|
||||||
from photoapp.dbutils import SAEnginePlugin, SATool, db, get_db_engine, date_format
|
from photoapp.dbutils import SAEnginePlugin, SATool, db, get_db_engine, date_format
|
||||||
from photoapp.utils import mime2ext, auth, require_auth, photoset_auth_filter, slugify
|
from photoapp.utils import auth, require_auth, photoset_auth_filter, slugify
|
||||||
from photoapp.storage import uri_to_storage
|
from photoapp.storage import uri_to_storage
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
from sqlalchemy import desc, func, and_, or_
|
from sqlalchemy import desc, func, and_, or_
|
||||||
|
|
|
@ -3,31 +3,79 @@ from sqlalchemy.orm import relationship
|
||||||
from sqlalchemy.schema import UniqueConstraint
|
from sqlalchemy.schema import UniqueConstraint
|
||||||
from photoapp.dbutils import Base
|
from photoapp.dbutils import Base
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import enum as py_enum
|
||||||
import uuid
|
import uuid
|
||||||
import enum
|
import enum
|
||||||
|
|
||||||
|
|
||||||
|
class fcategory(py_enum.Enum):
|
||||||
|
image = 0
|
||||||
|
raw = 1
|
||||||
|
video = 2
|
||||||
|
|
||||||
|
|
||||||
|
ftypes = dict(jpg=dict(category=fcategory.image,
|
||||||
|
extensions={"jpeg"},
|
||||||
|
mimes={"image/jpeg"}),
|
||||||
|
png=dict(category=fcategory.image,
|
||||||
|
mimes={"image/png"}),
|
||||||
|
gif=dict(category=fcategory.image,
|
||||||
|
mimes={"image/gif"}),
|
||||||
|
cr2=dict(category=fcategory.raw,
|
||||||
|
mimes={"image/x-canon-cr2"}),
|
||||||
|
xmp=dict(category=fcategory.raw,
|
||||||
|
mimes={"application/octet-stream-xmp"}),
|
||||||
|
psd=dict(category=fcategory.raw,
|
||||||
|
mimes={"image/vnd.adobe.photoshop"}),
|
||||||
|
mp4=dict(category=fcategory.video,
|
||||||
|
mimes={"audio/mp4",
|
||||||
|
"video/mp4"}),
|
||||||
|
mov=dict(category=fcategory.video,
|
||||||
|
mimes={"video/quicktime"}))
|
||||||
|
|
||||||
|
# set various defaults in ftypes
|
||||||
|
# it should look like:
|
||||||
|
# ftypes = {
|
||||||
|
# <default_extension>: {
|
||||||
|
# "category": <fcategory key>, # required, fcategory type
|
||||||
|
# "extensions": {<*default_extension|optional extensions>}, # optional, defaults to set([<default_extension>])
|
||||||
|
# "mimes": { # required, mimes mapped to this type
|
||||||
|
# <mime string>
|
||||||
|
# },
|
||||||
|
# "type": <str(*image|video)>, # optional, defaults to str("image")
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
for extension, entry in ftypes.items():
|
||||||
|
entry["extensions"] = entry.get("extensions", set()) | set([extension])
|
||||||
|
entry["type"] = entry.get("type", "image")
|
||||||
|
|
||||||
|
|
||||||
# file extensions we allow
|
# file extensions we allow
|
||||||
known_extensions = ["jpg", "png", "cr2", "xmp", "mp4", "mov"]
|
known_extensions = set.union(*[i["extensions"] for i in ftypes.values()])
|
||||||
|
|
||||||
# categorizaiton of media type based on extension
|
|
||||||
regular_images = ["jpg", "png"] # we can pull metadata out of these
|
|
||||||
files_raw = ["cr2", "xmp"] # treated as black boxes
|
|
||||||
files_video = ["mp4", "mov"]
|
|
||||||
|
|
||||||
# extensions with well-known aliases
|
|
||||||
mapped_extensions = {"jpg": {"jpeg", }} # target: aliases
|
|
||||||
|
|
||||||
# allowed file types (based on magic identification)
|
# allowed file types (based on magic identification)
|
||||||
# TODO enforce this
|
known_mimes = set.union(*[i["mimes"] for i in ftypes.values()])
|
||||||
known_mimes = {"image/png",
|
|
||||||
"image/jpeg",
|
# categorizaiton of media type based on extension
|
||||||
"image/gif",
|
# we can pull metadata out of these
|
||||||
"application/octet-stream-xmp",
|
# jpg, png, gif etc
|
||||||
"image/x-canon-cr2",
|
regular_images = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.image])
|
||||||
"audio/mp4",
|
# "derived" files, treated as black boxes, we can't open them because proprietary
|
||||||
"video/mp4",
|
# cr2, xmp, etc
|
||||||
"video/quicktime"}
|
files_raw = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.raw])
|
||||||
|
# video types
|
||||||
|
# mp4, mov, etc
|
||||||
|
files_video = set([extension for extension, ftype in ftypes.items() if ftype["category"] == fcategory.video])
|
||||||
|
|
||||||
|
|
||||||
|
def mime2ext(mime):
|
||||||
|
"""
|
||||||
|
Given a mime type return the canonical file extension
|
||||||
|
"""
|
||||||
|
for ext, ftype in ftypes.items():
|
||||||
|
if mime in ftype["mimes"]:
|
||||||
|
return ext
|
||||||
|
raise Exception(f"Unknown mime: '{mime}'")
|
||||||
|
|
||||||
|
|
||||||
def genuuid():
|
def genuuid():
|
||||||
|
@ -35,10 +83,10 @@ def genuuid():
|
||||||
|
|
||||||
|
|
||||||
def map_extension(ext):
|
def map_extension(ext):
|
||||||
for target, aliases in mapped_extensions.items():
|
for known_ext, ftype in ftypes.items():
|
||||||
if ext in aliases:
|
if ext in ftype["extensions"]:
|
||||||
return target
|
return known_ext
|
||||||
return ext
|
raise Exception(f"Unknown extension: '{ext}'")
|
||||||
|
|
||||||
|
|
||||||
def generate_storage_path(timestamp, sha, extension):
|
def generate_storage_path(timestamp, sha, extension):
|
||||||
|
|
|
@ -25,20 +25,6 @@ def shasum(fpin):
|
||||||
return sha.hexdigest()
|
return sha.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def mime2ext(mime):
|
|
||||||
"""
|
|
||||||
Given a mime type return the canonical file extension
|
|
||||||
"""
|
|
||||||
return {"image/png": "png",
|
|
||||||
"image/jpeg": "jpg",
|
|
||||||
"image/gif": "gif",
|
|
||||||
"application/octet-stream-xmp": "xmp",
|
|
||||||
"image/x-canon-cr2": "cr2",
|
|
||||||
"audio/mp4": "mp4",
|
|
||||||
"video/mp4": "mp4",
|
|
||||||
"video/quicktime": "mov"}[mime]
|
|
||||||
|
|
||||||
|
|
||||||
def get_extension(fname):
|
def get_extension(fname):
|
||||||
parts = os.path.basename(fname).split(".")
|
parts = os.path.basename(fname).split(".")
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
|
|
Loading…
Reference in New Issue