Shioriko/pkg/app/blob_routes.go

207 lines
5.6 KiB
Go
Raw Normal View History

2021-05-09 22:07:23 +07:00
package app
import (
2021-05-12 01:22:46 +07:00
"encoding/binary"
"image"
_ "image/gif"
"image/jpeg"
_ "image/jpeg"
_ "image/png"
2021-05-09 22:07:23 +07:00
"net/http"
2021-05-10 09:45:40 +07:00
"os"
2021-05-09 22:07:23 +07:00
"path/filepath"
2021-05-12 01:22:46 +07:00
_ "golang.org/x/image/webp"
"golang.org/x/image/draw"
2021-05-12 01:22:46 +07:00
2021-05-09 22:07:23 +07:00
"github.com/Damillora/Shioriko/pkg/config"
"github.com/Damillora/Shioriko/pkg/database"
"github.com/Damillora/Shioriko/pkg/middleware"
"github.com/Damillora/Shioriko/pkg/models"
2021-05-12 01:22:46 +07:00
"github.com/Damillora/Shioriko/pkg/services"
"github.com/corona10/goimagehash"
2021-05-09 22:07:23 +07:00
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
func InitializeBlobRoutes(g *gin.Engine) {
protected := g.Group("/api/blob").Use(middleware.AuthMiddleware())
{
protected.POST("/upload", uploadBlob)
}
}
func uploadBlob(c *gin.Context) {
dataDir := config.CurrentConfig.DataDirectory
// Source
file, err := c.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
2021-05-11 17:33:22 +07:00
return
2021-05-09 22:07:23 +07:00
}
2021-05-11 19:21:11 +07:00
2021-05-11 17:33:22 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
return
}
2021-05-11 19:21:11 +07:00
id := uuid.NewString()
folder1 := id[0:2]
folder2 := id[2:4]
if _, err := os.Stat(filepath.Join(dataDir, folder1)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, folder1), 0755)
}
if _, err := os.Stat(filepath.Join(dataDir, folder1, folder2)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, folder1, folder2), 0755)
}
2021-05-11 17:33:22 +07:00
2021-05-11 19:21:11 +07:00
if _, err := os.Stat(filepath.Join(dataDir, "preview", dataDir, folder1)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, "preview", folder1), 0755)
}
if _, err := os.Stat(filepath.Join(dataDir, "preview", dataDir, folder1, folder2)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, "preview", folder1, folder2), 0755)
}
if _, err := os.Stat(filepath.Join(dataDir, "thumbnail", dataDir, folder1)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, "thumbnail", folder1), 0755)
}
if _, err := os.Stat(filepath.Join(dataDir, "thumbnail", dataDir, folder1, folder2)); os.IsNotExist(err) {
os.Mkdir(filepath.Join(dataDir, "thumbnail", folder1, folder2), 0755)
}
2021-05-12 01:22:46 +07:00
previewFilename := id + ".jpg"
previewFilePath := filepath.Join(dataDir, "preview", folder1, folder2, previewFilename)
thumbnailFilePath := filepath.Join(dataDir, "thumbnail", folder1, folder2, previewFilename)
fileObj, _ := file.Open()
originalImage, _, err := image.Decode(fileObj)
2021-05-11 17:33:22 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
2021-05-12 01:22:46 +07:00
width := originalImage.Bounds().Dx()
height := originalImage.Bounds().Dy()
2021-05-11 17:33:22 +07:00
2021-05-12 01:22:46 +07:00
hash, err := goimagehash.PerceptionHash(originalImage)
2021-05-11 19:21:11 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
2021-05-12 01:22:46 +07:00
return
2021-05-10 09:45:40 +07:00
}
2021-05-12 01:22:46 +07:00
hashInt := hash.GetHash()
similarPosts, err := services.SimilaritySearch(hashInt)
hashSlice := make([]byte, 8)
binary.LittleEndian.PutUint64(hashSlice, hashInt)
2021-05-11 19:21:11 +07:00
if len(similarPosts) > 0 {
c.JSON(http.StatusOK,
models.BlobSimilarResponse{
ID: id,
Width: width,
Height: height,
Similar: similarPosts,
})
return
}
filename := id + filepath.Ext(file.Filename)
filePath := filepath.Join(dataDir, folder1, folder2, filename)
err = c.SaveUploadedFile(file, filePath)
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
return
}
// Resize logic
previewWidth := 1000;
previewFactor := float32(previewWidth) / float32(width)
previewHeight := int(float32(height) * previewFactor)
if width <= previewWidth {
previewHeight = height
2021-05-10 09:45:40 +07:00
}
thumbnailWidth := 300;
thumbnailFactor := float32(thumbnailWidth) / float32(width)
thumbnailHeight := int(float32(height) * thumbnailFactor)
if width <= thumbnailWidth {
thumbnailHeight = height
2021-05-11 19:21:11 +07:00
}
2021-05-09 22:07:23 +07:00
previewImage := image.NewRGBA(image.Rect(0, 0, previewWidth, previewHeight))
draw.BiLinear.Scale(previewImage, previewImage.Rect, originalImage, originalImage.Bounds(), draw.Over, nil)
thumbnailImage := image.NewRGBA(image.Rect(0, 0, thumbnailWidth, thumbnailHeight))
draw.BiLinear.Scale(thumbnailImage, thumbnailImage.Rect, originalImage, originalImage.Bounds(), draw.Over, nil)
2021-05-12 01:22:46 +07:00
previewFile, err := os.Create(previewFilePath)
2021-05-11 19:21:11 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
2021-05-12 01:22:46 +07:00
return
}
thumbnailFile, err := os.Create(thumbnailFilePath)
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
return
2021-05-11 19:21:11 +07:00
}
2021-05-12 01:22:46 +07:00
err = jpeg.Encode(previewFile, previewImage, nil)
2021-05-11 19:21:11 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
2021-05-12 01:22:46 +07:00
err = jpeg.Encode(thumbnailFile, thumbnailImage, nil)
2021-05-09 22:07:23 +07:00
if err != nil {
c.JSON(http.StatusBadRequest, models.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
2021-05-12 01:22:46 +07:00
return
}
2021-05-09 22:07:23 +07:00
blob := database.Blob{
2021-05-11 19:21:11 +07:00
ID: id,
FilePath: filepath.Join(folder1, folder2, filename),
PreviewFilePath: filepath.Join("preview", folder1, folder2, previewFilename),
ThumbnailFilePath: filepath.Join("thumbnail", folder1, folder2, previewFilename),
Width: width,
Height: height,
2021-05-12 01:22:46 +07:00
Hash1: hashSlice[0:2],
Hash2: hashSlice[2:4],
Hash3: hashSlice[4:6],
Hash4: hashSlice[6:8],
2021-05-09 22:07:23 +07:00
}
2021-05-11 19:21:11 +07:00
2021-05-09 22:07:23 +07:00
database.DB.Create(&blob)
c.JSON(http.StatusOK, models.BlobResponse{
ID: id,
Width: width,
Height: height,
})
return
2021-05-09 22:07:23 +07:00
}