Переработка структуры проекта

This commit is contained in:
ErickSkrauch
2017-06-30 18:40:25 +03:00
parent e090d04dc7
commit 07903cf9c8
48 changed files with 894 additions and 1061 deletions

39
ui/cape.go Normal file
View File

@@ -0,0 +1,39 @@
package ui
import (
"io"
"net/http"
"github.com/gorilla/mux"
"elyby/minecraft-skinsystem/utils"
)
func (s *uiService) Cape(response http.ResponseWriter, request *http.Request) {
if mux.Vars(request)["converted"] == "" {
s.logger.IncCounter("capes.request", 1)
}
username := utils.ParseUsername(mux.Vars(request)["username"])
rec, err := s.capesRepo.FindByUsername(username)
if err != nil {
http.Redirect(response, request, "http://skins.minecraft.net/MinecraftCloaks/" + username + ".png", 301)
}
request.Header.Set("Content-Type", "image/png")
io.Copy(response, rec.File)
}
func (s *uiService) CapeGET(response http.ResponseWriter, request *http.Request) {
s.logger.IncCounter("capes.get_request", 1)
username := request.URL.Query().Get("name")
if username == "" {
response.WriteHeader(http.StatusBadRequest)
return
}
mux.Vars(request)["username"] = username
mux.Vars(request)["converted"] = "1"
s.Cape(response, request)
}

28
ui/face.go Normal file
View File

@@ -0,0 +1,28 @@
package ui
import (
"net/http"
"github.com/gorilla/mux"
"elyby/minecraft-skinsystem/utils"
)
const defaultHash = "default"
func (s *uiService) Face(response http.ResponseWriter, request *http.Request) {
username := utils.ParseUsername(mux.Vars(request)["username"])
rec, err := s.skinsRepo.FindByUsername(username)
var hash string
if err != nil || rec.SkinId == 0 {
hash = defaultHash
} else {
hash = rec.Hash
}
http.Redirect(response, request, utils.BuildElyUrl(buildFaceUrl(hash)), 301)
}
func buildFaceUrl(hash string) string {
return "/minecraft/skin_buffer/faces/" + hash + ".png"
}

33
ui/minecraft_php.go Normal file
View File

@@ -0,0 +1,33 @@
package ui
import (
"net/http"
"github.com/gorilla/mux"
)
// Метод-наследие от первой версии системы скинов.
// Всё ещё иногда используется
// Просто конвертируем данные и отправляем их в основной обработчик
func (s *uiService) MinecraftPHP(response http.ResponseWriter, request *http.Request) {
username := request.URL.Query().Get("name")
required := request.URL.Query().Get("type")
if username == "" || required == "" {
response.WriteHeader(http.StatusBadRequest)
return
}
mux.Vars(request)["username"] = username
mux.Vars(request)["converted"] = "1"
switch required {
case "skin":
s.logger.IncCounter("skins.minecraft-php-request", 1)
s.Skin(response, request)
case "cloack":
s.logger.IncCounter("capes.minecraft-php-request", 1)
s.Cape(response, request)
default:
response.WriteHeader(http.StatusNotFound)
}
}

18
ui/not_found.go Normal file
View File

@@ -0,0 +1,18 @@
package ui
import (
"encoding/json"
"net/http"
)
func NotFound(response http.ResponseWriter, request *http.Request) {
json, _ := json.Marshal(map[string]string{
"status": "404",
"message": "Not Found",
"link": "http://docs.ely.by/skin-system.html",
})
response.Header().Set("Content-Type", "application/json")
response.WriteHeader(http.StatusNotFound)
response.Write(json)
}

25
ui/service.go Normal file
View File

@@ -0,0 +1,25 @@
package ui
import (
"elyby/minecraft-skinsystem/model"
"github.com/mono83/slf/wd"
)
type uiService struct {
logger wd.Watchdog
skinsRepo model.SkinsRepository
capesRepo model.CapesRepository
}
func NewUiService(
logger wd.Watchdog,
skinsRepo model.SkinsRepository,
capesRepo model.CapesRepository,
) (*uiService, error) {
return &uiService{
logger: logger,
skinsRepo: skinsRepo,
capesRepo: capesRepo,
}, nil
}

55
ui/signed_textures.go Normal file
View File

@@ -0,0 +1,55 @@
package ui
import (
"encoding/json"
"net/http"
"strings"
"github.com/gorilla/mux"
"elyby/minecraft-skinsystem/utils"
)
type signedTexturesResponse struct {
Id string `json:"id"`
Name string `json:"name"`
IsEly bool `json:"ely,omitempty"`
Props []property `json:"properties"`
}
type property struct {
Name string `json:"name"`
Signature string `json:"signature,omitempty"`
Value string `json:"value"`
}
func (s *uiService) SignedTextures(response http.ResponseWriter, request *http.Request) {
s.logger.IncCounter("signed_textures.request", 1)
username := utils.ParseUsername(mux.Vars(request)["username"])
rec, err := s.skinsRepo.FindByUsername(username)
if err != nil || rec.SkinId == 0 || rec.MojangTextures == "" {
response.WriteHeader(http.StatusNoContent)
return
}
responseData:= signedTexturesResponse{
Id: strings.Replace(rec.Uuid, "-", "", -1),
Name: rec.Username,
Props: []property{
{
Name: "textures",
Signature: rec.MojangSignature,
Value: rec.MojangTextures,
},
{
Name: "ely",
Value: "but why are you asking?",
},
},
}
responseJson,_ := json.Marshal(responseData)
response.Header().Set("Content-Type", "application/json")
response.Write(responseJson)
}

38
ui/skin.go Normal file
View File

@@ -0,0 +1,38 @@
package ui
import (
"net/http"
"github.com/gorilla/mux"
"elyby/minecraft-skinsystem/utils"
)
func (s *uiService) Skin(response http.ResponseWriter, request *http.Request) {
if mux.Vars(request)["converted"] == "" {
s.logger.IncCounter("skins.request", 1)
}
username := utils.ParseUsername(mux.Vars(request)["username"])
rec, err := s.skinsRepo.FindByUsername(username)
if err != nil {
http.Redirect(response, request, "http://skins.minecraft.net/MinecraftSkins/" + username + ".png", 301)
return
}
http.Redirect(response, request, utils.BuildElyUrl(rec.Url), 301)
}
func (s *uiService) SkinGET(response http.ResponseWriter, request *http.Request) {
s.logger.IncCounter("skins.get_request", 1)
username := request.URL.Query().Get("name")
if username == "" {
response.WriteHeader(http.StatusBadRequest)
return
}
mux.Vars(request)["username"] = username
mux.Vars(request)["converted"] = "1"
s.Skin(response, request)
}

92
ui/textures.go Normal file
View File

@@ -0,0 +1,92 @@
package ui
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"crypto/md5"
"encoding/hex"
"io"
"elyby/minecraft-skinsystem/model"
"elyby/minecraft-skinsystem/utils"
)
type texturesResponse struct {
Skin *Skin `json:"SKIN"`
Cape *Cape `json:"CAPE,omitempty"`
}
type Skin struct {
Url string `json:"url"`
Hash string `json:"hash"`
Metadata *skinMetadata `json:"metadata,omitempty"`
}
type skinMetadata struct {
Model string `json:"model"`
}
type Cape struct {
Url string `json:"url"`
Hash string `json:"hash"`
}
func (s *uiService) Textures(response http.ResponseWriter, request *http.Request) {
s.logger.IncCounter("textures.request", 1)
username := utils.ParseUsername(mux.Vars(request)["username"])
skin, err := s.skinsRepo.FindByUsername(username)
if err != nil || skin.SkinId == 0 {
skin.Url = "http://skins.minecraft.net/MinecraftSkins/" + username + ".png"
skin.Hash = string(utils.BuildNonElyTexturesHash(username))
} else {
skin.Url = utils.BuildElyUrl(skin.Url)
}
textures := texturesResponse{
Skin: &Skin{
Url: skin.Url,
Hash: skin.Hash,
},
}
if skin.IsSlim {
textures.Skin.Metadata = &skinMetadata{
Model: "slim",
}
}
cape, err := s.capesRepo.FindByUsername(username)
if err == nil {
// capeUrl, err := services.Router.Get("cloaks").URL("username", username)
capeUrl := "/capes/" + username
if err != nil {
s.logger.Error(err.Error())
}
var scheme string = "http://"
if request.TLS != nil {
scheme = "https://"
}
textures.Cape = &Cape{
// Url: scheme + request.Host + capeUrl.String(),
Url: scheme + request.Host + capeUrl,
Hash: calculateCapeHash(cape),
}
}
responseData,_ := json.Marshal(textures)
response.Header().Set("Content-Type", "application/json")
response.Write(responseData)
}
func calculateCapeHash(cape model.Cape) string {
hasher := md5.New()
io.Copy(hasher, cape.File)
return hex.EncodeToString(hasher.Sum(nil))
}

39
ui/ui.go Normal file
View File

@@ -0,0 +1,39 @@
package ui
import (
"net"
"net/http"
"time"
"github.com/gorilla/mux"
)
type Config struct {
}
func Start(cfg Config, s *uiService, lst net.Listener) {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/skins/{username}", s.Skin).Methods("GET")
router.HandleFunc("/cloaks/{username}", s.Cape).Methods("GET")
router.HandleFunc("/textures/{username}", s.Textures).Methods("GET")
router.HandleFunc("/textures/signed/{username}", s.SignedTextures).Methods("GET")
router.HandleFunc("/skins/{username}/face", s.Face).Methods("GET")
router.HandleFunc("/skins/{username}/face.png", s.Face).Methods("GET")
// Legacy
router.HandleFunc("/minecraft.php", s.MinecraftPHP).Methods("GET")
router.HandleFunc("/skins/", s.SkinGET).Methods("GET")
router.HandleFunc("/cloaks/", s.CapeGET).Methods("GET")
// 404
router.NotFoundHandler = http.HandlerFunc(NotFound)
server := &http.Server{
ReadTimeout: 60 * time.Second,
WriteTimeout: 60 * time.Second,
MaxHeaderBytes: 1 << 16,
Handler: router,
}
go server.Serve(lst)
}