threadr.lostcave.ddnss.de/models/file.go

106 lines
2.5 KiB
Go

package models
import (
"database/sql"
"fmt"
"os"
"path/filepath"
"strings"
)
const ProfileImageExtension = ".png"
type File struct {
ID int
OriginalName string
Hash string
HashAlgorithm string
}
func GetFileByID(db *sql.DB, id int64) (*File, error) {
query := "SELECT id, original_name, hash, hash_algorithm FROM files WHERE id = ?"
row := db.QueryRow(query, id)
file := &File{}
err := row.Scan(&file.ID, &file.OriginalName, &file.Hash, &file.HashAlgorithm)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, err
}
return file, nil
}
func IsProfileImageFile(db *sql.DB, id int64) (bool, error) {
var exists bool
err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM users WHERE pfp_file_id = ?)", id).Scan(&exists)
if err != nil {
return false, err
}
return exists, nil
}
func CreateFile(db *sql.DB, file File) (int64, error) {
query := "INSERT INTO files (original_name, hash, hash_algorithm) VALUES (?, ?, ?)"
result, err := db.Exec(query, file.OriginalName, file.Hash, file.HashAlgorithm)
if err != nil {
return 0, err
}
return result.LastInsertId()
}
func DeleteFileByID(db *sql.DB, id int64) error {
_, err := db.Exec("DELETE FROM files WHERE id = ?", id)
return err
}
func ProfileImageStorageName(id int64) string {
return fmt.Sprintf("%d%s", id, ProfileImageExtension)
}
func LegacyImageStorageName(id int64, originalName string) (string, bool) {
ext := strings.ToLower(filepath.Ext(originalName))
if !allowedImageExtension(ext) {
return "", false
}
return fmt.Sprintf("%d%s", id, ext), true
}
func ProfileImageContentType(fileName string) string {
switch strings.ToLower(filepath.Ext(fileName)) {
case ".jpg", ".jpeg":
return "image/jpeg"
case ".gif":
return "image/gif"
default:
return "image/png"
}
}
func ResolveStoredImagePath(storageDir string, file *File) (string, string, bool) {
currentPath := filepath.Join(storageDir, ProfileImageStorageName(int64(file.ID)))
if _, err := os.Stat(currentPath); err == nil {
return currentPath, ProfileImageContentType(currentPath), true
}
legacyName, ok := LegacyImageStorageName(int64(file.ID), file.OriginalName)
if !ok {
return "", "", false
}
legacyPath := filepath.Join(storageDir, legacyName)
if _, err := os.Stat(legacyPath); err == nil {
return legacyPath, ProfileImageContentType(legacyPath), true
}
return "", "", false
}
func allowedImageExtension(ext string) bool {
switch ext {
case ".png", ".jpg", ".jpeg", ".gif":
return true
default:
return false
}
}