Загрузка плаща вынесена в отдельный метод, реализовано отображение ссылки на плащ в запросах на текстуры

This commit is contained in:
ErickSkrauch 2016-09-22 19:32:00 +03:00
parent a9acfb954f
commit 9467911025
11 changed files with 94 additions and 26 deletions

43
lib/data/CapeItem.go Normal file
View File

@ -0,0 +1,43 @@
package data
import (
"io"
"os"
"fmt"
"strings"
"crypto/md5"
"encoding/hex"
"elyby/minecraft-skinsystem/lib/services"
)
type CapeItem struct {
File *os.File
}
func FindCapeByUsername(username string) (CapeItem, error) {
var record CapeItem
file, err := os.Open(services.RootFolder + "/data/capes/" + strings.ToLower(username) + ".png")
if (err != nil) {
return record, CapeNotFound{username}
}
record.File = file
return record, err
}
func (cape *CapeItem) CalculateHash() string {
hasher := md5.New()
io.Copy(hasher, cape.File)
return hex.EncodeToString(hasher.Sum(nil))
}
type CapeNotFound struct {
Who string
}
func (e CapeNotFound) Error() string {
return fmt.Sprintf("Cape file not found. Required username \"%v\"", e.Who)
}

View File

@ -1,11 +0,0 @@
package data
import "fmt"
type DataNotFound struct {
Who string
}
func (e DataNotFound) Error() string {
return fmt.Sprintf("Skin data not found. Required username \"%v\"", e.Who)
}

View File

@ -2,6 +2,7 @@ package data
import ( import (
"log" "log"
"fmt"
"encoding/json" "encoding/json"
"elyby/minecraft-skinsystem/lib/services" "elyby/minecraft-skinsystem/lib/services"
@ -59,11 +60,11 @@ func (s *SkinItem) Delete() {
pool.Cmd("EXEC") pool.Cmd("EXEC")
} }
func FindByUsername(username string) (SkinItem, error) { func FindSkinByUsername(username string) (SkinItem, error) {
var record SkinItem; var record SkinItem;
response := services.RedisPool.Cmd("GET", tools.BuildKey(username)); response := services.RedisPool.Cmd("GET", tools.BuildKey(username));
if (response.IsType(redis.Nil)) { if (response.IsType(redis.Nil)) {
return record, DataNotFound{username} return record, SkinNotFound{username}
} }
result, err := response.Str() result, err := response.Str()
@ -79,13 +80,21 @@ func FindByUsername(username string) (SkinItem, error) {
return record, err return record, err
} }
func FindById(id int) (SkinItem, error) { func FindSkinById(id int) (SkinItem, error) {
response := services.RedisPool.Cmd("HGET", accountIdToUsernameKey, id); response := services.RedisPool.Cmd("HGET", accountIdToUsernameKey, id);
if (response.IsType(redis.Nil)) { if (response.IsType(redis.Nil)) {
return SkinItem{}, DataNotFound{"unknown"} return SkinItem{}, SkinNotFound{"unknown"}
} }
username, _ := response.Str() username, _ := response.Str()
return FindByUsername(username) return FindSkinByUsername(username)
}
type SkinNotFound struct {
Who string
}
func (e SkinNotFound) Error() string {
return fmt.Sprintf("Skin data not found. Required username \"%v\"", e.Who)
} }

View File

@ -2,6 +2,7 @@ package data
type TexturesResponse struct { type TexturesResponse struct {
Skin *Skin `json:"SKIN"` Skin *Skin `json:"SKIN"`
Cape *Cape `json:"CAPE,omitempty"`
} }
type Skin struct { type Skin struct {
@ -13,3 +14,8 @@ type Skin struct {
type SkinMetadata struct { type SkinMetadata struct {
Model string `json:"model"` Model string `json:"model"`
} }
type Cape struct {
Url string `json:"url"`
Hash string `json:"hash"`
}

View File

@ -1,28 +1,26 @@
package routes package routes
import ( import (
"os"
"io" "io"
"log" "log"
"strings"
"net/http" "net/http"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"elyby/minecraft-skinsystem/lib/tools" "elyby/minecraft-skinsystem/lib/tools"
"elyby/minecraft-skinsystem/lib/services" "elyby/minecraft-skinsystem/lib/data"
) )
func Cape(response http.ResponseWriter, request *http.Request) { func Cape(response http.ResponseWriter, request *http.Request) {
username := tools.ParseUsername(mux.Vars(request)["username"]) username := tools.ParseUsername(mux.Vars(request)["username"])
log.Println("request cape for username " + username) log.Println("request cape for username " + username)
file, err := os.Open(services.RootFolder + "/data/capes/" + strings.ToLower(username) + ".png") rec, err := data.FindCapeByUsername(username)
if (err != nil) { if (err != nil) {
http.Redirect(response, request, "http://skins.minecraft.net/MinecraftCloaks/" + username + ".png", 301) http.Redirect(response, request, "http://skins.minecraft.net/MinecraftCloaks/" + username + ".png", 301)
} }
request.Header.Set("Content-Type", "image/png") request.Header.Set("Content-Type", "image/png")
io.Copy(response, file) io.Copy(response, rec.File)
} }
func CapeGET(w http.ResponseWriter, r *http.Request) { func CapeGET(w http.ResponseWriter, r *http.Request) {

View File

@ -15,7 +15,7 @@ const defaultHash = "default"
func Face(w http.ResponseWriter, r *http.Request) { func Face(w http.ResponseWriter, r *http.Request) {
username := tools.ParseUsername(mux.Vars(r)["username"]) username := tools.ParseUsername(mux.Vars(r)["username"])
log.Println("request skin for username " + username); log.Println("request skin for username " + username);
rec, err := data.FindByUsername(username) rec, err := data.FindSkinByUsername(username)
var hash string var hash string
if (err != nil || rec.SkinId == 0) { if (err != nil || rec.SkinId == 0) {
hash = defaultHash; hash = defaultHash;

View File

@ -13,7 +13,7 @@ import (
func Skin(w http.ResponseWriter, r *http.Request) { func Skin(w http.ResponseWriter, r *http.Request) {
username := tools.ParseUsername(mux.Vars(r)["username"]) username := tools.ParseUsername(mux.Vars(r)["username"])
log.Println("request skin for username " + username); log.Println("request skin for username " + username);
rec, err := data.FindByUsername(username) rec, err := data.FindSkinByUsername(username)
if (err != nil) { if (err != nil) {
http.Redirect(w, r, "http://skins.minecraft.net/MinecraftSkins/" + username + ".png", 301) http.Redirect(w, r, "http://skins.minecraft.net/MinecraftSkins/" + username + ".png", 301)
return return

View File

@ -9,13 +9,14 @@ import (
"elyby/minecraft-skinsystem/lib/data" "elyby/minecraft-skinsystem/lib/data"
"elyby/minecraft-skinsystem/lib/tools" "elyby/minecraft-skinsystem/lib/tools"
"elyby/minecraft-skinsystem/lib/services"
) )
func Textures(w http.ResponseWriter, r *http.Request) { func Textures(w http.ResponseWriter, r *http.Request) {
username := tools.ParseUsername(mux.Vars(r)["username"]) username := tools.ParseUsername(mux.Vars(r)["username"])
log.Println("request textures for username " + username) log.Println("request textures for username " + username)
rec, err := data.FindByUsername(username) rec, err := data.FindSkinByUsername(username)
if (err != nil || rec.SkinId == 0) { if (err != nil || rec.SkinId == 0) {
rec.Url = "http://skins.minecraft.net/MinecraftSkins/" + username + ".png" rec.Url = "http://skins.minecraft.net/MinecraftSkins/" + username + ".png"
rec.Hash = string(tools.BuildNonElyTexturesHash(username)) rec.Hash = string(tools.BuildNonElyTexturesHash(username))
@ -36,6 +37,24 @@ func Textures(w http.ResponseWriter, r *http.Request) {
} }
} }
capeRec, err := data.FindCapeByUsername(username)
if (err == nil) {
capeUrl, err := services.Router.Get("cloaks").URL("username", username)
if (err != nil) {
log.Println(err.Error())
}
var scheme string = "http://";
if (r.TLS != nil) {
scheme = "https://"
}
textures.Cape = &data.Cape{
Url: scheme + r.Host + capeUrl.String(),
Hash: capeRec.CalculateHash(),
}
}
response,_ := json.Marshal(textures) response,_ := json.Marshal(textures)
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Write(response) w.Write(response)

View File

@ -3,8 +3,11 @@ package services
import ( import (
"github.com/mediocregopher/radix.v2/pool" "github.com/mediocregopher/radix.v2/pool"
"github.com/streadway/amqp" "github.com/streadway/amqp"
"github.com/gorilla/mux"
) )
var Router *mux.Router
var RedisPool *pool.Pool var RedisPool *pool.Pool
var RabbitMQChannel *amqp.Channel var RabbitMQChannel *amqp.Channel

View File

@ -17,7 +17,7 @@ func handleChangeUsername(model usernameChanged) (bool) {
return true return true
} }
record, err := data.FindByUsername(model.OldUsername) record, err := data.FindSkinByUsername(model.OldUsername)
if (err != nil) { if (err != nil) {
log.Println("Exit by not found record") log.Println("Exit by not found record")
// TODO: я не уверен, что это валидное поведение // TODO: я не уверен, что это валидное поведение
@ -35,7 +35,7 @@ func handleChangeUsername(model usernameChanged) (bool) {
} }
func handleSkinChanged(model skinChanged) (bool) { func handleSkinChanged(model skinChanged) (bool) {
record, err := data.FindById(model.AccountId) record, err := data.FindSkinById(model.AccountId)
if (err != nil) { if (err != nil) {
return true return true
} }

View File

@ -62,6 +62,7 @@ func main() {
apiRouter := router.PathPrefix("/api").Subrouter() apiRouter := router.PathPrefix("/api").Subrouter()
apiRouter.HandleFunc("/user/{username}/skin", routes.SetSkin).Methods("POST") apiRouter.HandleFunc("/user/{username}/skin", routes.SetSkin).Methods("POST")
services.Router = router
services.RedisPool = redisPool services.RedisPool = redisPool
services.RabbitMQChannel = rabbitChannel services.RabbitMQChannel = rabbitChannel