Skip to content
Snippets Groups Projects
Commit c7489101 authored by Ophestra's avatar Ophestra
Browse files

everything in API updated to use snowflake instead of hash, implement multi-tag search

parent 84f07d55
No related merge requests found
......@@ -7,6 +7,7 @@ import (
"net/http"
"random.chars.jp/git/image-board/store"
"strconv"
"strings"
)
type UserPayload struct {
......@@ -271,6 +272,12 @@ func registerAPI() {
context.JSON(http.StatusOK, instance.UserImages(context.Param("flake")))
})
router.GET("/api/search/:tags", func(context *gin.Context) {
tagsPayload := context.Param("tags")
tags := strings.Split(tagsPayload, "!")
context.JSON(http.StatusOK, instance.ImageSearch(tags))
})
router.GET("/api/image/snowflake", func(context *gin.Context) {
info, ok := getUser(context)
......@@ -378,11 +385,11 @@ func registerAPI() {
context.JSON(http.StatusOK, image)
})
router.GET("/api/image/:hash", func(context *gin.Context) {
context.JSON(http.StatusOK, instance.Image(context.Param("hash")))
router.GET("/api/image/:flake", func(context *gin.Context) {
context.JSON(http.StatusOK, instance.ImageSnowflake(context.Param("flake")))
})
router.PATCH("/api/image/:hash", func(context *gin.Context) {
router.PATCH("/api/image/:flake", func(context *gin.Context) {
user, ok := getUser(context)
// Require sign in
......@@ -391,7 +398,7 @@ func registerAPI() {
return
}
info := instance.Image(context.Param("hash"))
info := instance.ImageSnowflake(context.Param("flake"))
if !user.Privileged && (info.User != user.Snowflake) {
context.JSON(http.StatusForbidden, denied)
return
......@@ -408,7 +415,7 @@ func registerAPI() {
instance.ImageSource(info.Hash, payload.Source)
})
router.DELETE("/api/image/:hash", func(context *gin.Context) {
router.DELETE("/api/image/:flake", func(context *gin.Context) {
info, ok := getUser(context)
// Require sign in
......@@ -417,17 +424,19 @@ func registerAPI() {
return
}
hash := context.Param("hash")
if !info.Privileged && (info.Snowflake != instance.Image(hash).User) {
flake := context.Param("flake")
image := instance.ImageSnowflake(flake)
if !info.Privileged && (info.Snowflake != image.User) {
context.JSON(http.StatusForbidden, denied)
return
}
instance.ImageDestroy(hash)
instance.ImageDestroy(image.Hash)
})
router.GET("/api/image/:hash/file", func(context *gin.Context) {
image, data := instance.ImageData(context.Param("hash"), false)
if image.Hash == "" {
router.GET("/api/image/:flake/file", func(context *gin.Context) {
flake := context.Param("flake")
image, data := instance.ImageData(instance.ImageSnowflakeHash(flake), false)
if image.Snowflake == flake {
context.JSON(http.StatusNotFound, gin.H{
"error": "not found",
})
......@@ -436,9 +445,10 @@ func registerAPI() {
context.Data(http.StatusOK, "image/"+image.Type, data)
})
router.GET("/api/image/:hash/preview", func(context *gin.Context) {
image, data := instance.ImageData(context.Param("hash"), true)
if image.Hash == "" {
router.GET("/api/image/:flake/preview", func(context *gin.Context) {
flake := context.Param("flake")
image, data := instance.ImageData(instance.ImageSnowflakeHash(flake), true)
if image.Snowflake == flake {
context.JSON(http.StatusNotFound, gin.H{
"error": "not found",
})
......@@ -447,11 +457,11 @@ func registerAPI() {
context.Data(http.StatusOK, "image/jpeg", data)
})
router.GET("/api/image/:hash/tag", func(context *gin.Context) {
context.JSON(http.StatusOK, instance.ImageTags(context.Param("hash")))
router.GET("/api/image/:flake/tag", func(context *gin.Context) {
context.JSON(http.StatusOK, instance.ImageTags(context.Param("flake")))
})
router.PUT("/api/image/:hash/tag/:tag", func(context *gin.Context) {
router.PUT("/api/image/:flake/tag/:tag", func(context *gin.Context) {
info, ok := getUser(context)
// Require sign in
......@@ -460,15 +470,15 @@ func registerAPI() {
return
}
hash := context.Param("hash")
if !info.Privileged && (info.Snowflake != instance.Image(hash).User) {
flake := context.Param("flake")
if !info.Privileged && (info.Snowflake != instance.ImageSnowflake(flake).User) {
context.JSON(http.StatusForbidden, denied)
return
}
instance.ImageTagAdd(hash, context.Param("tag"))
instance.ImageTagAdd(flake, context.Param("tag"))
})
router.DELETE("/api/image/:hash/tag/:tag", func(context *gin.Context) {
router.DELETE("/api/image/:flake/tag/:tag", func(context *gin.Context) {
info, ok := getUser(context)
// Require sign in
......@@ -477,12 +487,12 @@ func registerAPI() {
return
}
hash := context.Param("hash")
if !info.Privileged && (info.Snowflake != instance.Image(hash).User) {
flake := context.Param("flake")
if !info.Privileged && (info.Snowflake != instance.ImageSnowflake(flake).User) {
context.JSON(http.StatusForbidden, denied)
return
}
instance.ImageTagRemove(hash, context.Param("tag"))
instance.ImageTagRemove(flake, context.Param("tag"))
})
router.GET("/api/tag", func(context *gin.Context) {
......
......@@ -129,6 +129,81 @@ func (s *Store) imageTags(flake string) []string {
return tags
}
// ImageHasTag figures out if an image has a tag.
func (s *Store) ImageHasTag(flake string, tag string) bool {
return s.file(s.ImageTagsPath(flake) + "/" + tag)
}
//ImageSearch searches for images with specific tags.
func (s *Store) ImageSearch(tags []string) []string {
if len(tags) < 1 || tags == nil {
return nil
}
// Check if every tag matches name regex and exists
for _, tag := range tags {
if !nameRegex.MatchString(tag) || !s.file(s.TagPath(tag)) {
return nil
}
}
// Return if there's only one tag to search for
if len(tags) == 1 {
return s.Tag(tags[0])
}
// Find entry with the least pages
entry := struct {
min int
index int
}{
min: s.PageTotal("tag_" + tags[0]),
index: 0,
}
for i := 1; i < len(tags); i++ {
if entry.min <= 1 {
break
}
pages := s.PageTotal("tag_" + tags[i])
if pages < entry.min {
entry.min = pages
entry.index = i
}
}
// Get initial tag
initial := s.Tag(tags[entry.index])
// Result slice
var result []string
// Walk flakes from initial tag
for _, flake := range initial {
match := true
// Walk all remaining tags
for i, tag := range tags {
// Skip the entrypoint entry
if i == entry.index {
continue
}
// Check if match
if !s.ImageHasTag(flake, tag) {
match = false
break
}
}
// Append flake if all tags matched
if match {
result = append(result, flake)
}
}
return result
}
// ImageAdd adds an image to the store.
func (s *Store) ImageAdd(data []byte, flake string) Image {
if !s.flake(flake) || !s.dir(s.UserPath(flake)) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment