🎨 Update project structure
This commit is contained in:
113
pkg/internal/services/attachments.go
Normal file
113
pkg/internal/services/attachments.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.solsynth.dev/hydrogen/paperclip/pkg/internal/database"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
|
||||
"git.solsynth.dev/hydrogen/paperclip/pkg/models"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func GetAttachmentByID(id uint) (models.Attachment, error) {
|
||||
var attachment models.Attachment
|
||||
if err := database.C.Where(models.Attachment{
|
||||
BaseModel: models.BaseModel{ID: id},
|
||||
}).First(&attachment).Error; err != nil {
|
||||
return attachment, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
|
||||
func GetAttachmentByUUID(id string) (models.Attachment, error) {
|
||||
var attachment models.Attachment
|
||||
if err := database.C.Where(models.Attachment{
|
||||
Uuid: id,
|
||||
}).First(&attachment).Error; err != nil {
|
||||
return attachment, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
|
||||
func GetAttachmentByHash(hash string) (models.Attachment, error) {
|
||||
var attachment models.Attachment
|
||||
if err := database.C.Where(models.Attachment{
|
||||
HashCode: hash,
|
||||
}).First(&attachment).Error; err != nil {
|
||||
return attachment, err
|
||||
}
|
||||
return attachment, nil
|
||||
}
|
||||
|
||||
func NewAttachmentMetadata(tx *gorm.DB, user models.Account, file *multipart.FileHeader, attachment models.Attachment) (models.Attachment, bool, error) {
|
||||
linked := false
|
||||
exists, pickupErr := GetAttachmentByHash(attachment.HashCode)
|
||||
if pickupErr == nil {
|
||||
linked = true
|
||||
exists.Alternative = attachment.Alternative
|
||||
exists.Usage = attachment.Usage
|
||||
exists.Metadata = attachment.Metadata
|
||||
attachment = exists
|
||||
attachment.ID = 0
|
||||
attachment.AccountID = user.ID
|
||||
} else {
|
||||
// Upload the new file
|
||||
attachment.Uuid = uuid.NewString()
|
||||
attachment.Size = file.Size
|
||||
attachment.Name = file.Filename
|
||||
attachment.AccountID = user.ID
|
||||
|
||||
// If user didn't provide file mimetype manually, we gotta to detect it
|
||||
if len(attachment.MimeType) == 0 {
|
||||
if ext := filepath.Ext(attachment.Name); len(ext) > 0 {
|
||||
// Detect mimetype by file extensions
|
||||
attachment.MimeType = mime.TypeByExtension(ext)
|
||||
} else {
|
||||
// Detect mimetype by file header
|
||||
// This method as a fallback method, because this isn't pretty accurate
|
||||
header, err := file.Open()
|
||||
if err != nil {
|
||||
return attachment, false, fmt.Errorf("failed to read file header: %v", err)
|
||||
}
|
||||
defer header.Close()
|
||||
|
||||
fileHeader := make([]byte, 512)
|
||||
_, err = header.Read(fileHeader)
|
||||
if err != nil {
|
||||
return attachment, false, err
|
||||
}
|
||||
attachment.MimeType = http.DetectContentType(fileHeader)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Save(&attachment).Error; err != nil {
|
||||
return attachment, linked, fmt.Errorf("failed to save attachment record: %v", err)
|
||||
}
|
||||
|
||||
return attachment, linked, nil
|
||||
}
|
||||
|
||||
func DeleteAttachment(item models.Attachment) error {
|
||||
var dupeCount int64
|
||||
if err := database.C.
|
||||
Where(&models.Attachment{HashCode: item.HashCode}).
|
||||
Model(&models.Attachment{}).
|
||||
Count(&dupeCount).Error; err != nil {
|
||||
dupeCount = -1
|
||||
}
|
||||
|
||||
if err := database.C.Delete(&item).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dupeCount != -1 && dupeCount <= 1 {
|
||||
return DeleteFile(item)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user