567 lines
12 KiB
Go
567 lines
12 KiB
Go
package routes
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/mineatar-io/api-server/src/util"
|
|
"github.com/mineatar-io/skin-render"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promauto"
|
|
"github.com/valyala/fasthttp"
|
|
)
|
|
|
|
var (
|
|
renderFullBodyMetric = promauto.NewCounter(prometheus.CounterOpts{
|
|
Name: "full_body_render_count",
|
|
Help: "The amount of full body renders",
|
|
})
|
|
renderFrontBodyMetric = promauto.NewCounter(prometheus.CounterOpts{
|
|
Name: "front_body_render_count",
|
|
Help: "The amount of front body renders",
|
|
})
|
|
renderBackBodyMetric = promauto.NewCounter(prometheus.CounterOpts{
|
|
Name: "back_body_render_count",
|
|
Help: "The amount of back body renders",
|
|
})
|
|
renderLeftBodyMetric = promauto.NewCounter(prometheus.CounterOpts{
|
|
Name: "left_body_render_count",
|
|
Help: "The amount of left body renders",
|
|
})
|
|
renderRightBodyMetric = promauto.NewCounter(prometheus.CounterOpts{
|
|
Name: "right_body_render_count",
|
|
Help: "The amount of right body renders",
|
|
})
|
|
)
|
|
|
|
func FullBodyHandler(ctx *fasthttp.RequestCtx) {
|
|
user := ctx.UserValue("user").(string)
|
|
|
|
opts := util.ParseQueryParams(ctx, config.Routes.FullBody)
|
|
|
|
uuid, ok, err := util.LookupUUID(user)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if !ok && !opts.Fallback {
|
|
ctx.SetStatusCode(http.StatusNotFound)
|
|
ctx.SetBodyString(http.StatusText(http.StatusNotFound))
|
|
|
|
return
|
|
}
|
|
|
|
cacheKey := fmt.Sprintf("result:fullbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
|
|
|
{
|
|
cache, ok, err := r.GetBytes(cacheKey)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
if util.Debug {
|
|
log.Printf("Retrieved cache for full body render for '%s'\n", uuid)
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(cache)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
rawSkin, slim, err := util.GetPlayerSkin(uuid)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
render := skin.RenderBody(rawSkin, skin.Options{
|
|
Overlay: opts.Overlay,
|
|
Slim: slim,
|
|
Scale: opts.Scale,
|
|
})
|
|
|
|
if util.Debug {
|
|
log.Printf("Rendered full body image for '%s'\n", uuid)
|
|
}
|
|
|
|
renderFullBodyMetric.Inc()
|
|
|
|
data, err := util.EncodePNG(render)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if err = r.Set(cacheKey, data, config.Cache.RenderCacheDuration); err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(data)
|
|
}
|
|
|
|
func FrontBodyHandler(ctx *fasthttp.RequestCtx) {
|
|
user := ctx.UserValue("user").(string)
|
|
|
|
opts := util.ParseQueryParams(ctx, config.Routes.FrontBody)
|
|
|
|
uuid, ok, err := util.LookupUUID(user)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if !ok && !opts.Fallback {
|
|
ctx.SetStatusCode(http.StatusNotFound)
|
|
ctx.SetBodyString(http.StatusText(http.StatusNotFound))
|
|
|
|
return
|
|
}
|
|
|
|
cacheKey := fmt.Sprintf("result:frontbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
|
|
|
{
|
|
cache, ok, err := r.GetBytes(cacheKey)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
if util.Debug {
|
|
log.Printf("Retrieved cache for front body render for '%s'\n", uuid)
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(cache)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
rawSkin, slim, err := util.GetPlayerSkin(uuid)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
render := skin.RenderFrontBody(rawSkin, skin.Options{
|
|
Overlay: opts.Overlay,
|
|
Slim: slim,
|
|
Scale: opts.Scale,
|
|
})
|
|
|
|
if util.Debug {
|
|
log.Printf("Rendered front body image for '%s'\n", uuid)
|
|
}
|
|
|
|
renderFrontBodyMetric.Inc()
|
|
|
|
data, err := util.EncodePNG(render)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if err = r.Set(cacheKey, data, config.Cache.RenderCacheDuration); err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(data)
|
|
}
|
|
|
|
func BackBodyHandler(ctx *fasthttp.RequestCtx) {
|
|
user := ctx.UserValue("user").(string)
|
|
|
|
opts := util.ParseQueryParams(ctx, config.Routes.BackBody)
|
|
|
|
uuid, ok, err := util.LookupUUID(user)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if !ok && !opts.Fallback {
|
|
ctx.SetStatusCode(http.StatusNotFound)
|
|
ctx.SetBodyString(http.StatusText(http.StatusNotFound))
|
|
|
|
return
|
|
}
|
|
|
|
cacheKey := fmt.Sprintf("result:backbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
|
|
|
{
|
|
cache, ok, err := r.GetBytes(cacheKey)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
if util.Debug {
|
|
log.Printf("Retrieved cache for back body render for '%s'\n", uuid)
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(cache)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
rawSkin, slim, err := util.GetPlayerSkin(uuid)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
render := skin.RenderBackBody(rawSkin, skin.Options{
|
|
Overlay: opts.Overlay,
|
|
Slim: slim,
|
|
Scale: opts.Scale,
|
|
})
|
|
|
|
if util.Debug {
|
|
log.Printf("Rendered back body image for '%s'\n", uuid)
|
|
}
|
|
|
|
renderBackBodyMetric.Inc()
|
|
|
|
data, err := util.EncodePNG(render)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if err = r.Set(cacheKey, data, config.Cache.RenderCacheDuration); err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(data)
|
|
}
|
|
|
|
func LeftBodyHandler(ctx *fasthttp.RequestCtx) {
|
|
user := ctx.UserValue("user").(string)
|
|
|
|
opts := util.ParseQueryParams(ctx, config.Routes.LeftBody)
|
|
|
|
uuid, ok, err := util.LookupUUID(user)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if !ok && !opts.Fallback {
|
|
ctx.SetStatusCode(http.StatusNotFound)
|
|
ctx.SetBodyString(http.StatusText(http.StatusNotFound))
|
|
|
|
return
|
|
}
|
|
|
|
cacheKey := fmt.Sprintf("result:leftbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
|
|
|
{
|
|
cache, ok, err := r.GetBytes(cacheKey)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
if util.Debug {
|
|
log.Printf("Retrieved cache for left body render for '%s'\n", uuid)
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(cache)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
rawSkin, slim, err := util.GetPlayerSkin(uuid)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
render := skin.RenderLeftBody(rawSkin, skin.Options{
|
|
Overlay: opts.Overlay,
|
|
Slim: slim,
|
|
Scale: opts.Scale,
|
|
})
|
|
|
|
if util.Debug {
|
|
log.Printf("Rendered left body image for '%s'\n", uuid)
|
|
}
|
|
|
|
renderLeftBodyMetric.Inc()
|
|
|
|
data, err := util.EncodePNG(render)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if err = r.Set(cacheKey, data, config.Cache.RenderCacheDuration); err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(data)
|
|
}
|
|
|
|
func RightBodyHandler(ctx *fasthttp.RequestCtx) {
|
|
user := ctx.UserValue("user").(string)
|
|
|
|
opts := util.ParseQueryParams(ctx, config.Routes.RightBody)
|
|
|
|
uuid, ok, err := util.LookupUUID(user)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if !ok && !opts.Fallback {
|
|
ctx.SetStatusCode(http.StatusNotFound)
|
|
ctx.SetBodyString(http.StatusText(http.StatusNotFound))
|
|
|
|
return
|
|
}
|
|
|
|
cacheKey := fmt.Sprintf("result:rightbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
|
|
|
{
|
|
cache, ok, err := r.GetBytes(cacheKey)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
if util.Debug {
|
|
log.Printf("Retrieved cache for right body render for '%s'\n", uuid)
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "TRUE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(cache)
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
rawSkin, slim, err := util.GetPlayerSkin(uuid)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
render := skin.RenderRightBody(rawSkin, skin.Options{
|
|
Overlay: opts.Overlay,
|
|
Slim: slim,
|
|
Scale: opts.Scale,
|
|
})
|
|
|
|
if util.Debug {
|
|
log.Printf("Rendered right body image for '%s'\n", uuid)
|
|
}
|
|
|
|
renderRightBodyMetric.Inc()
|
|
|
|
data, err := util.EncodePNG(render)
|
|
|
|
if err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if err = r.Set(cacheKey, data, config.Cache.RenderCacheDuration); err != nil {
|
|
log.Println(err)
|
|
|
|
ctx.SetStatusCode(http.StatusInternalServerError)
|
|
ctx.SetBodyString(http.StatusText(http.StatusInternalServerError))
|
|
|
|
return
|
|
}
|
|
|
|
if opts.Download {
|
|
ctx.Response.Header.Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s.png"`, user))
|
|
}
|
|
|
|
ctx.Response.Header.Set("X-Cache-Hit", "FALSE")
|
|
ctx.SetContentType("image/png")
|
|
ctx.SetBody(data)
|
|
}
|