photoprism/pkg/fs/filetype.go
Michael Mayer 39878b3f83 Store created files in .photoprism sub directory
See #268, #311 and #313

Hidden directory name poll: https://twitter.com/browseyourlife/status/1262320988081074178

Signed-off-by: Michael Mayer <michael@liquidbytes.net>
2020-05-18 15:45:55 +02:00

204 lines
5.5 KiB
Go

package fs
import (
_ "image/gif" // Import for image.
_ "image/jpeg"
_ "image/png"
"os"
"path/filepath"
"strings"
)
type FileType string
const (
TypeJpeg FileType = "jpg" // JPEG image file.
TypePng FileType = "png" // PNG image file.
TypeGif FileType = "gif" // GIF image file.
TypeTiff FileType = "tiff" // TIFF image file.
TypeBitmap FileType = "bmp" // BMP image file.
TypeRaw FileType = "raw" // RAW image file.
TypeHEIF FileType = "heif" // High Efficiency Image File Format
TypeMov FileType = "mov" // Video files.
TypeMP4 FileType = "mp4"
TypeAvi FileType = "avi"
TypeXMP FileType = "xmp" // Adobe XMP sidecar file (XML).
TypeAAE FileType = "aae" // Apple sidecar file (XML).
TypeXML FileType = "xml" // XML metadata / config / sidecar file.
TypeYaml FileType = "yml" // YAML metadata / config / sidecar file.
TypeToml FileType = "toml" // Tom's Obvious, Minimal Language sidecar file.
TypeJson FileType = "json" // JSON metadata / config / sidecar file.
TypeText FileType = "txt" // Text config / sidecar file.
TypeMarkdown FileType = "md" // Markdown text sidecar file.
TypeOther FileType = "" // Unknown file format.
)
type FileExtensions map[string]FileType
type TypeExtensions map[FileType][]string
// FileExt contains the filename extensions of file formats known to PhotoPrism.
var FileExt = FileExtensions{
".bmp": TypeBitmap,
".gif": TypeGif,
".tif": TypeTiff,
".tiff": TypeTiff,
".png": TypePng,
".crw": TypeRaw,
".cr2": TypeRaw,
".nef": TypeRaw,
".arw": TypeRaw,
".dng": TypeRaw,
".mov": TypeMov,
".avi": TypeAvi,
".mp4": TypeMP4,
".yml": TypeYaml,
".yaml": TypeYaml,
".jpg": TypeJpeg,
".jpeg": TypeJpeg,
".jpe": TypeJpeg,
".jif": TypeJpeg,
".jfif": TypeJpeg,
".jfi": TypeJpeg,
".thm": TypeJpeg,
".xmp": TypeXMP,
".aae": TypeAAE,
".heif": TypeHEIF,
".heic": TypeHEIF,
".3fr": TypeRaw,
".ari": TypeRaw,
".bay": TypeRaw,
".cr3": TypeRaw,
".cap": TypeRaw,
".data": TypeRaw,
".dcs": TypeRaw,
".dcr": TypeRaw,
".drf": TypeRaw,
".eip": TypeRaw,
".erf": TypeRaw,
".fff": TypeRaw,
".gpr": TypeRaw,
".iiq": TypeRaw,
".k25": TypeRaw,
".kdc": TypeRaw,
".mdc": TypeRaw,
".mef": TypeRaw,
".mos": TypeRaw,
".mrw": TypeRaw,
".nrw": TypeRaw,
".obm": TypeRaw,
".orf": TypeRaw,
".pef": TypeRaw,
".ptx": TypeRaw,
".pxn": TypeRaw,
".r3d": TypeRaw,
".raf": TypeRaw,
".raw": TypeRaw,
".rwl": TypeRaw,
".rw2": TypeRaw,
".rwz": TypeRaw,
".sr2": TypeRaw,
".srf": TypeRaw,
".srw": TypeRaw,
".x3f": TypeRaw,
".xml": TypeXML,
".txt": TypeText,
".md": TypeMarkdown,
".json": TypeJson,
}
func (m FileExtensions) TypeExt() TypeExtensions {
result := make(TypeExtensions)
for ext, t := range m {
extUpper := strings.ToUpper(ext)
if _, ok := result[t]; ok {
result[t] = append(result[t], ext, extUpper)
} else {
result[t] = []string{ext, extUpper}
}
}
return result
}
var TypeExt = FileExt.TypeExt()
// Find returns the first filename with the same base name and a given type.
func (t FileType) Find(fileName string, stripSequence bool) string {
base := Base(fileName, stripSequence)
dir := filepath.Dir(fileName)
prefix := filepath.Join(dir, base)
prefixLower := filepath.Join(dir, strings.ToLower(base))
prefixUpper := filepath.Join(dir, strings.ToUpper(base))
for _, ext := range TypeExt[t] {
if info, err := os.Stat(prefix + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
if info, err := os.Stat(prefixLower + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
if info, err := os.Stat(prefixUpper + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
}
return ""
}
// Find returns the first filename with the same base name and a given type (also searches a sub directory).
func (t FileType) FindSub(fileName, subDir string, stripSequence bool) string {
base := Base(fileName, stripSequence)
dir := filepath.Dir(fileName)
prefix := filepath.Join(dir, base)
prefixLower := filepath.Join(dir, strings.ToLower(base))
prefixUpper := filepath.Join(dir, strings.ToUpper(base))
prefixHidden := filepath.Join(dir, subDir, base)
prefixLowerHidden := filepath.Join(dir, subDir, strings.ToLower(base))
prefixUpperHidden := filepath.Join(dir, subDir, strings.ToUpper(base))
for _, ext := range TypeExt[t] {
if info, err := os.Stat(prefix + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
if info, err := os.Stat(prefixLower + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
if info, err := os.Stat(prefixUpper + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, info.Name())
}
if info, err := os.Stat(prefixHidden + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, subDir, info.Name())
}
if info, err := os.Stat(prefixLowerHidden + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, subDir, info.Name())
}
if info, err := os.Stat(prefixUpperHidden + ext); err == nil && info.Mode().IsRegular() {
return filepath.Join(dir, subDir, info.Name())
}
}
return ""
}
// GetFileType returns the (expected) type for a given file name.
func GetFileType(fileName string) FileType {
fileExt := strings.ToLower(filepath.Ext(fileName))
result, ok := FileExt[fileExt]
if !ok {
result = TypeOther
}
return result
}