183 lines
4.1 KiB
Go
183 lines
4.1 KiB
Go
// internal/utils/files.go
|
|
package utils
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"math/rand"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func init() {
|
|
// Seed the random number generator
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
// EnsureDir makes sure the directory exists
|
|
func EnsureDir(dir string) error {
|
|
return os.MkdirAll(dir, 0755)
|
|
}
|
|
|
|
// FileExists checks if a file exists and is not a directory
|
|
func FileExists(filename string) bool {
|
|
info, err := os.Stat(filename)
|
|
if os.IsNotExist(err) {
|
|
return false
|
|
}
|
|
return !info.IsDir()
|
|
}
|
|
|
|
// GetRandomFile returns a random file from the specified directory
|
|
// It only includes files with the given extensions (no dot, e.g. "jpg", "png")
|
|
// If extensions is empty, it includes all files
|
|
func GetRandomFile(dir string, extensions []string) (string, error) {
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return "", fmt.Errorf("failed to read directory: %w", err)
|
|
}
|
|
|
|
// Filter files based on extensions
|
|
var validFiles []string
|
|
for _, file := range files {
|
|
if file.IsDir() {
|
|
continue
|
|
}
|
|
|
|
if len(extensions) == 0 {
|
|
validFiles = append(validFiles, file.Name())
|
|
continue
|
|
}
|
|
|
|
ext := strings.TrimPrefix(filepath.Ext(file.Name()), ".")
|
|
for _, validExt := range extensions {
|
|
if strings.EqualFold(ext, validExt) {
|
|
validFiles = append(validFiles, file.Name())
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(validFiles) == 0 {
|
|
return "", fmt.Errorf("no valid files found in directory")
|
|
}
|
|
|
|
// Pick a random file
|
|
randomIndex := rand.Intn(len(validFiles))
|
|
return filepath.Join(dir, validFiles[randomIndex]), nil
|
|
}
|
|
|
|
// MoveFile moves a file from src to dst
|
|
func MoveFile(src, dst string) error {
|
|
// Ensure the destination directory exists
|
|
if err := EnsureDir(filepath.Dir(dst)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// First try to rename (which works within the same filesystem)
|
|
err := os.Rename(src, dst)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
// If rename fails (e.g., across filesystems), copy and delete the original
|
|
if err := CopyFile(src, dst); err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.Remove(src)
|
|
}
|
|
|
|
// CopyFile copies a file from src to dst
|
|
func CopyFile(src, dst string) error {
|
|
// Ensure the destination directory exists
|
|
if err := EnsureDir(filepath.Dir(dst)); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Open the source file
|
|
sourceFile, err := os.Open(src)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer sourceFile.Close()
|
|
|
|
// Create the destination file
|
|
destFile, err := os.Create(dst)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer destFile.Close()
|
|
|
|
// Copy the content
|
|
_, err = io.Copy(destFile, sourceFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Flush the write buffer to disk
|
|
return destFile.Sync()
|
|
}
|
|
|
|
// CalculateFileHash returns the SHA-256 hash of a file
|
|
func CalculateFileHash(filePath string) (string, error) {
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
hasher := sha256.New()
|
|
if _, err := io.Copy(hasher, file); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return hex.EncodeToString(hasher.Sum(nil)), nil
|
|
}
|
|
|
|
// GetFileContentType tries to determine the content type of a file
|
|
func GetFileContentType(filePath string) (string, error) {
|
|
// Open the file
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
// Read the first 512 bytes to determine the content type
|
|
buffer := make([]byte, 512)
|
|
_, err = file.Read(buffer)
|
|
if err != nil && err != io.EOF {
|
|
return "", err
|
|
}
|
|
|
|
// Reset the file pointer
|
|
_, err = file.Seek(0, 0)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Detect the content type
|
|
contentType := http.DetectContentType(buffer)
|
|
return contentType, nil
|
|
}
|
|
|
|
// GetSupportedImageExtensions returns a list of supported image extensions
|
|
func GetSupportedImageExtensions() []string {
|
|
return []string{"jpg", "jpeg", "png", "gif", "webp", "avif"}
|
|
}
|
|
|
|
// GetSupportedVideoExtensions returns a list of supported video extensions
|
|
func GetSupportedVideoExtensions() []string {
|
|
return []string{"mp4", "webm", "mov", "avi"}
|
|
}
|
|
|
|
// GetAllSupportedMediaExtensions returns all supported media extensions
|
|
func GetAllSupportedMediaExtensions() []string {
|
|
return append(GetSupportedImageExtensions(), GetSupportedVideoExtensions()...)
|
|
} |