Remove username support
This commit is contained in:
@@ -8,12 +8,6 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// MinecraftProfile is Minecraft profile information returned from the Mojang API.
|
||||
type MinecraftProfile struct {
|
||||
Username string `json:"name"`
|
||||
UUID string `json:"id"`
|
||||
}
|
||||
|
||||
// MinecraftProfileTextures is texture information about a Minecraft profile returned from the Mojang API.
|
||||
type MinecraftProfileTextures struct {
|
||||
UUID string `json:"id"`
|
||||
@@ -45,47 +39,6 @@ type MinecraftDecodedTextures struct {
|
||||
} `json:"textures"`
|
||||
}
|
||||
|
||||
// UsernameToUUID converts a Minecraft username into a UUID using Mojang.
|
||||
func UsernameToUUID(username string) (*MinecraftProfile, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://api.mojang.com/users/profiles/minecraft/%s", username), nil)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("User-Agent", "mineatar.io Skin Render API")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
if resp.StatusCode == http.StatusNoContent || resp.StatusCode == http.StatusNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("mojang: unexpected response: %s", resp.Status)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &MinecraftProfile{}
|
||||
|
||||
if err = json.Unmarshal(body, response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetProfileTextures returns the textures of a Minecraft player from Mojang.
|
||||
func GetProfileTextures(uuid string) (*MinecraftProfileTextures, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("https://sessionserver.mojang.com/session/minecraft/profile/%s", uuid), nil)
|
||||
@@ -118,13 +71,13 @@ func GetProfileTextures(uuid string) (*MinecraftProfileTextures, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &MinecraftProfileTextures{}
|
||||
response := MinecraftProfileTextures{}
|
||||
|
||||
if err = json.Unmarshal(body, response); err != nil {
|
||||
if err = json.Unmarshal(body, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
// GetDecodedTexturesValue decodes the values from a MinecraftProfileTextures texture value.
|
||||
|
||||
128
src/routes.go
128
src/routes.go
@@ -11,15 +11,14 @@ import (
|
||||
|
||||
func init() {
|
||||
app.Get("/ping", PingHandler)
|
||||
app.Get("/uuid/:user", UUIDHandler)
|
||||
app.Get("/skin/:user", SkinHandler)
|
||||
app.Get("/face/:user", FaceHandler)
|
||||
app.Get("/head/:user", HeadHandler)
|
||||
app.Get("/body/full/:user", FullBodyHandler)
|
||||
app.Get("/body/front/:user", FrontBodyHandler)
|
||||
app.Get("/body/back/:user", BackBodyHandler)
|
||||
app.Get("/body/left/:user", LeftBodyHandler)
|
||||
app.Get("/body/right/:user", RightBodyHandler)
|
||||
app.Get("/skin/:uuid", SkinHandler)
|
||||
app.Get("/face/:uuid", FaceHandler)
|
||||
app.Get("/head/:uuid", HeadHandler)
|
||||
app.Get("/body/full/:uuid", FullBodyHandler)
|
||||
app.Get("/body/front/:uuid", FrontBodyHandler)
|
||||
app.Get("/body/back/:uuid", BackBodyHandler)
|
||||
app.Get("/body/left/:uuid", LeftBodyHandler)
|
||||
app.Get("/body/right/:uuid", RightBodyHandler)
|
||||
app.Use(NotFoundHandler)
|
||||
}
|
||||
|
||||
@@ -28,18 +27,14 @@ func PingHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.SendStatus(http.StatusOK)
|
||||
}
|
||||
|
||||
// FullBodyHandler is the API handler used for the `/body/full/:user` route.
|
||||
// FullBodyHandler is the API handler used for the `/body/full/:uuid` route.
|
||||
func FullBodyHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.FullBody)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:fullbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -79,18 +74,14 @@ func FullBodyHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// FrontBodyHandler is the API handler used for the `/body/front/:user` route.
|
||||
// FrontBodyHandler is the API handler used for the `/body/front/:uuid` route.
|
||||
func FrontBodyHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.FrontBody)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:frontbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -132,18 +123,14 @@ func FrontBodyHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// BackBodyHandler is the API handler used for the `/body/back/:user` route.
|
||||
// BackBodyHandler is the API handler used for the `/body/back/:uuid` route.
|
||||
func BackBodyHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.BackBody)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:backbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -185,18 +172,14 @@ func BackBodyHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// LeftBodyHandler is the API handler used for the `/body/left/:user` route.
|
||||
// LeftBodyHandler is the API handler used for the `/body/left/:uuid` route.
|
||||
func LeftBodyHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.LeftBody)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:leftbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -238,18 +221,14 @@ func LeftBodyHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// RightBodyHandler is the API handler used for the `/body/right/:user` route.
|
||||
// RightBodyHandler is the API handler used for the `/body/right/:uuid` route.
|
||||
func RightBodyHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.RightBody)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:rightbody-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -291,18 +270,14 @@ func RightBodyHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// FaceHandler is the API handler used for the `/face/:user` route.
|
||||
// FaceHandler is the API handler used for the `/face/:uuid` route.
|
||||
func FaceHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.Face)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:face-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -344,18 +319,14 @@ func FaceHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// HeadHandler is the API handler used for the `/head/:user` route.
|
||||
// HeadHandler is the API handler used for the `/head/:uuid` route.
|
||||
func HeadHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.Head)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ExtractUUID(ctx))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("result:head-%d-%t-%s", opts.Scale, opts.Overlay, uuid)
|
||||
@@ -397,18 +368,14 @@ func HeadHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// SkinHandler is the API handler used for the `/skin/:user` route.
|
||||
// SkinHandler is the API handler used for the `/skin/:uuid` route.
|
||||
func SkinHandler(ctx *fiber.Ctx) error {
|
||||
opts := ParseQueryParams(ctx, conf.Routes.RawSkin)
|
||||
|
||||
uuid, ok, err := LookupUUID(ParseUserParam(ctx))
|
||||
uuid, ok := ParseUUID(ctx.Params("uuid"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok && !opts.Fallback {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
if !ok {
|
||||
return SendUsernameDeprecation(ctx)
|
||||
}
|
||||
|
||||
rawSkin, _, err := GetPlayerSkin(uuid)
|
||||
@@ -430,21 +397,6 @@ func SkinHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.Type("png").Send(data)
|
||||
}
|
||||
|
||||
// UUIDHandler is the API handler used for the `/uuid/:user` route.
|
||||
func UUIDHandler(ctx *fiber.Ctx) error {
|
||||
uuid, ok, err := LookupUUID(ctx.Params("user"))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
}
|
||||
|
||||
return ctx.SendString(uuid)
|
||||
}
|
||||
|
||||
// NotFoundHandler is the API handler used for any requests that do not match an existing route.
|
||||
func NotFoundHandler(ctx *fiber.Ctx) error {
|
||||
return ctx.SendStatus(http.StatusNotFound)
|
||||
|
||||
59
src/util.go
59
src/util.go
@@ -21,7 +21,6 @@ type QueryParams struct {
|
||||
Scale int `query:"scale"`
|
||||
Download bool `query:"download"`
|
||||
Overlay bool `query:"overlay"`
|
||||
Fallback bool `query:"fallback"`
|
||||
}
|
||||
|
||||
// FormatUUID returns the UUID string without any dashes.
|
||||
@@ -29,41 +28,15 @@ func FormatUUID(uuid string) string {
|
||||
return strings.ToLower(strings.ReplaceAll(uuid, "-", ""))
|
||||
}
|
||||
|
||||
// LookupUUID returns the UUID of a player either by username or UUID, while attempting to use any cached values in the database.
|
||||
func LookupUUID(value string) (string, bool, error) {
|
||||
// ParseUUID parses the UUID given by the route parameters, and returns a boolean if the UUID is valid.
|
||||
func ParseUUID(value string) (string, bool) {
|
||||
value = FormatUUID(value)
|
||||
|
||||
if len(value) == 32 {
|
||||
return value, true, nil
|
||||
if len(value) != 32 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
cacheKey := fmt.Sprintf("uuid:%s", value)
|
||||
|
||||
cache, ok, err := r.GetString(cacheKey)
|
||||
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
if ok {
|
||||
return cache, true, nil
|
||||
}
|
||||
|
||||
profile, err := UsernameToUUID(value)
|
||||
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
||||
if profile == nil {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
if err = r.Set(cacheKey, profile.UUID, conf.Cache.UUIDCacheDuration); err != nil {
|
||||
return "", true, err
|
||||
}
|
||||
|
||||
return profile.UUID, true, nil
|
||||
return value, true
|
||||
}
|
||||
|
||||
// FetchImage fetches the image by the URL and returns it as a parsed image.
|
||||
@@ -95,12 +68,6 @@ func FetchImage(url string) (*image.NRGBA, error) {
|
||||
|
||||
// GetPlayerSkin fetches the skin of the Minecraft player by the UUID.
|
||||
func GetPlayerSkin(uuid string) (*image.NRGBA, bool, error) {
|
||||
uuid = FormatUUID(uuid)
|
||||
|
||||
if len(uuid) < 1 {
|
||||
return skin.GetDefaultSkin(false), false, nil
|
||||
}
|
||||
|
||||
cache, ok, err := r.GetNRGBA(fmt.Sprintf("skin:%s", uuid))
|
||||
|
||||
if err != nil {
|
||||
@@ -221,7 +188,6 @@ func ParseQueryParams(ctx *fiber.Ctx, route RouteConfig) *QueryParams {
|
||||
Scale: route.DefaultScale,
|
||||
Download: route.DefaultDownload,
|
||||
Overlay: route.DefaultOverlay,
|
||||
Fallback: route.DefaultFallback,
|
||||
}
|
||||
|
||||
if args.Has("scale") {
|
||||
@@ -234,10 +200,6 @@ func ParseQueryParams(ctx *fiber.Ctx, route RouteConfig) *QueryParams {
|
||||
response.Overlay = args.GetBool("overlay")
|
||||
}
|
||||
|
||||
if args.Has("fallback") {
|
||||
response.Fallback = args.GetBool("fallback")
|
||||
}
|
||||
|
||||
if args.Has("download") {
|
||||
response.Download = args.GetBool("download")
|
||||
}
|
||||
@@ -260,7 +222,12 @@ func GetInstanceID() (uint16, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ParseUserParam returns the user name from the route param, allowing values such as "PassTheMayo.png" to be returned as "PassTheMayo".
|
||||
func ParseUserParam(ctx *fiber.Ctx) string {
|
||||
return strings.Split(ctx.Params("user"), ".")[0]
|
||||
// ExtractUUID returns the user name from the route param, allowing values such as "PassTheMayo.png" to be returned as "PassTheMayo".
|
||||
func ExtractUUID(ctx *fiber.Ctx) string {
|
||||
return strings.Split(ctx.Params("uuid"), ".")[0]
|
||||
}
|
||||
|
||||
// SendUsernameDeprecation sends a deprecation warning about usernames.
|
||||
func SendUsernameDeprecation(ctx *fiber.Ctx) error {
|
||||
return ctx.Status(http.StatusBadRequest).SendString("Deprecated: Username support has been deprecated since May 1st 2023, please use a valid UUID instead.")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user