mirror of
https://github.com/elyby/chrly.git
synced 2024-12-22 21:19:55 +05:30
Merge branch 'v3.0'
# Conflicts: # app.php
This commit is contained in:
commit
eeffd17ea9
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,2 +1,5 @@
|
||||
# IDEA
|
||||
/.idea
|
||||
/awstat
|
||||
|
||||
# Docker Compose override file
|
||||
docker-compose.override.yml
|
||||
|
@ -1,5 +0,0 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine on
|
||||
RewriteRule ^$ public/ [L]
|
||||
RewriteRule (.*) public/$1 [L]
|
||||
</IfModule>
|
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM golang:1.7
|
||||
|
||||
RUN mkdir -p /go/src/elyby/minecraft-skinsystem \
|
||||
&& ln -s /go/src/elyby/minecraft-skinsystem /go/src/app
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
COPY ./minecraft-skinsystem.go /go/src/app/
|
||||
COPY ./lib /go/src/app/lib
|
||||
|
||||
RUN go-wrapper download
|
||||
RUN go-wrapper install
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
VOLUME ["/go/src/app"]
|
||||
|
||||
CMD ["go-wrapper", "run"]
|
49
README.md
Normal file
49
README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Это заготовка для нормального файла
|
||||
|
||||
Для настройки Dev-окружения нужно склонировать проект в удобное место,
|
||||
за тем сделать символьную ссылку в свой GOPATH:
|
||||
|
||||
```sh
|
||||
# Выполнять, находясь внутри директории репозитория
|
||||
mkdir -p $GOPATH/src/elyby
|
||||
ln -s $PWD $GOPATH/src/elyby/minecraft-skinsystem
|
||||
```
|
||||
|
||||
Или можно склонировать репозиторий сразу в нужную локацию:
|
||||
|
||||
```sh
|
||||
git clone git@bitbucket.org:elyby/minecraft-skinsystem.git $GOPATH/src/elyby/minecraft-skinsystem
|
||||
```
|
||||
|
||||
Поднять репозиторий можно командой:
|
||||
|
||||
```sh
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Рекомендуемый файл `docker-compose.override.yml` для dev-окружения:
|
||||
|
||||
```sh
|
||||
version: '2'
|
||||
services:
|
||||
app:
|
||||
volumes:
|
||||
- ./:/go/src/app
|
||||
command: ["go", "run", "minecraft-skinsystem.go"]
|
||||
```
|
||||
|
||||
В таком случае, для перезапуска контейнера (при условии, что не появляется
|
||||
новых зависимостей) будет достаточно выполнить только одну команду:
|
||||
|
||||
```sh
|
||||
docker-compose restart app
|
||||
```
|
||||
|
||||
Если нужно пересобрать весь контейнер, то выполняем следующее:
|
||||
|
||||
```
|
||||
docker-compose stop app # Останавливаем конейтнер, если он ещё работает
|
||||
docker-compose rm -f app # Удаляем конейтнер
|
||||
docker-compose build app # Запускаем билд по новой
|
||||
docker-compose up -d app # Поднимаем свежесобранный контейнер обратно
|
||||
```
|
98
app.php
98
app.php
@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
define('ENCODING', 'UTF-8');
|
||||
|
||||
$app->get('/skins/{nickname}', function ($nickname) use ($app) {
|
||||
// $systemVersion = $app->request->get('version', 'int');
|
||||
// $minecraftVersion = $app->request->get('minecraft_version', 'string');
|
||||
|
||||
// На всякий случай проверка на наличие .png для файла
|
||||
if (strrpos($nickname, '.png') != -1) {
|
||||
$nickname = explode('.', $nickname)[0];
|
||||
}
|
||||
|
||||
// TODO: восстановить функцию деградации скинов
|
||||
|
||||
$skin = Skins::findByNickname($nickname);
|
||||
if (!$skin || $skin->skinId == 0) {
|
||||
return $app->response->redirect('http://skins.minecraft.net/MinecraftSkins/' . $nickname . '.png', true);
|
||||
}
|
||||
|
||||
return $app->response->redirect($skin->url);
|
||||
})->setName('skinSystem');
|
||||
|
||||
$app->get('/cloaks/{nickname}', function ($nickname) use ($app) {
|
||||
// На всякий случай проверка на наличие .png для файла
|
||||
if (strrpos($nickname, '.png') != -1) {
|
||||
$nickname = explode('.', $nickname)[0];
|
||||
}
|
||||
|
||||
return $app->response->redirect('http://skins.minecraft.net/MinecraftCloaks/'.$nickname.'.png');
|
||||
});
|
||||
|
||||
$app->get('/textures/{nickname}', function($nickname) use ($app) {
|
||||
$skin = Skins::findByNickname($nickname);
|
||||
if ($skin && $skin->skinId != 0) {
|
||||
$url = $skin->url;
|
||||
$hash = $skin->hash;
|
||||
} else {
|
||||
$url = 'http://skins.minecraft.net/MinecraftSkins/'.$nickname.'.png';
|
||||
$hash = md5('non-ely-' . mktime(date('H'), 0, 0) . '-' . $nickname);
|
||||
}
|
||||
|
||||
// TODO: в authserver.ely.by есть готовый класс для работы с форматом текстур. Так что если мы его вынесем в
|
||||
// common library, то нужно будет заменить его здесь
|
||||
|
||||
$textures = [
|
||||
'SKIN' => [
|
||||
'url' => $url,
|
||||
'hash' => $hash,
|
||||
],
|
||||
];
|
||||
|
||||
$capePath = __DIR__ . '/cloaks/' . $nickname . '.png';
|
||||
if (file_exists($capePath)) {
|
||||
$textures['CAPE'] = [
|
||||
'url' => '/cloaks/' . mb_convert_case($nickname, MB_CASE_LOWER) . '.png',
|
||||
'hash' => md5_file($capePath),
|
||||
];
|
||||
}
|
||||
|
||||
if ($skin && $skin->isSlim) {
|
||||
$textures['SKIN']['metadata']['model'] = 'slim';
|
||||
}
|
||||
|
||||
return $app->response->setContentType('application/json')->setJsonContent($textures);
|
||||
});
|
||||
|
||||
$app->post('/system/setSkin', function() use ($app) {
|
||||
$headers = getallheaders();
|
||||
if (!array_key_exists('X-Ely-key', $headers) || $headers['X-Ely-key'] != '43fd2ce61b3f5704dfd729c1f2d6ffdb') {
|
||||
return $app->response->setStatusCode(403, 'Forbidden')->setContent('Хорошая попытка, мерзкий хакер.');
|
||||
}
|
||||
|
||||
$request = $app->request;
|
||||
$nickname = mb_convert_case($request->getPost('nickname', 'string'), MB_CASE_LOWER, ENCODING);
|
||||
|
||||
$skin = Skins::findByNickname($nickname);
|
||||
if (!$skin) {
|
||||
$skin = new Skins();
|
||||
$skin->nickname = $nickname;
|
||||
}
|
||||
|
||||
$skin->userId = (int) $request->getPost('userId', 'int');
|
||||
$skin->skinId = (int) $request->getPost('skinId', 'int');
|
||||
$skin->hash = $request->getPost('hash', 'string');
|
||||
$skin->is1_8 = (bool) $request->getPost('is1_8', 'int');
|
||||
$skin->isSlim = (bool) $request->getPost('isSlim', 'int');
|
||||
$skin->url = $request->getPost('url', 'string');
|
||||
|
||||
return $app->response->setContent($skin->save() ? 'OK' : 'ERROR');
|
||||
});
|
||||
|
||||
$app->notFound(function () use ($app) {
|
||||
$app->response
|
||||
->setStatusCode(404, 'Not Found')
|
||||
->setContent('Not Found<br /> <a href="http://ely.by">Система скинов Ely.by</a>.')
|
||||
->send();
|
||||
});
|
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
return new \Phalcon\Config([
|
||||
'mongo' => [
|
||||
'host' => 'localhost',
|
||||
'port' => 27017,
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'dbname' => 'ely_skins',
|
||||
],
|
||||
'application' => [
|
||||
'modelsDir' => __DIR__ . '/../models/',
|
||||
'baseUri' => '/',
|
||||
]
|
||||
]);
|
@ -1,12 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \Phalcon\Config $config
|
||||
*/
|
||||
|
||||
$loader = new \Phalcon\Loader();
|
||||
|
||||
$loader->registerDirs(array(
|
||||
$config->application->modelsDir
|
||||
));
|
||||
|
||||
$loader->register();
|
@ -1,46 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \Phalcon\Config $config
|
||||
*/
|
||||
|
||||
use Phalcon\Mvc\Collection\Manager;
|
||||
use Phalcon\Mvc\View;
|
||||
use Phalcon\Mvc\Url as UrlResolver;
|
||||
use Phalcon\DI\FactoryDefault;
|
||||
|
||||
$di = new FactoryDefault();
|
||||
|
||||
$di->set('view', function () {
|
||||
$view = new View();
|
||||
$view->disable();
|
||||
|
||||
return $view;
|
||||
});
|
||||
|
||||
/**
|
||||
* The URL component is used to generate all kind of urls in the application
|
||||
*/
|
||||
$di->set('url', function () use ($config) {
|
||||
$url = new UrlResolver();
|
||||
$url->setBaseUri($config->application->baseUri);
|
||||
|
||||
return $url;
|
||||
});
|
||||
|
||||
$di->set('mongo', function() use ($config) {
|
||||
/** @var StdClass $mongoConfig */
|
||||
$mongoConfig = $config->mongo;
|
||||
$connectionString = 'mongodb://';
|
||||
if ($mongoConfig->username && $mongoConfig->password) {
|
||||
$connectionString .= "{$mongoConfig->username}:{$mongoConfig->password}@";
|
||||
}
|
||||
|
||||
$connectionString .= $mongoConfig->host . ':' . $mongoConfig->port;
|
||||
$mongo = new MongoClient($connectionString);
|
||||
|
||||
return $mongo->selectDb($mongoConfig->dbname);
|
||||
});
|
||||
|
||||
$di->setShared('collectionManager', function() {
|
||||
return new Manager();
|
||||
});
|
0
cloaks/.gitignore → data/.gitignore
vendored
0
cloaks/.gitignore → data/.gitignore
vendored
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
||||
version: '2'
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
links:
|
||||
- redis
|
||||
ports:
|
||||
- "80:80"
|
||||
|
||||
redis:
|
||||
image: redis:3.0
|
||||
volumes:
|
||||
- ./data/:/data
|
39
lib/data/SkinItem.go
Normal file
39
lib/data/SkinItem.go
Normal file
@ -0,0 +1,39 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"log"
|
||||
"encoding/json"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/services"
|
||||
"elyby/minecraft-skinsystem/lib/tools"
|
||||
)
|
||||
|
||||
type SkinItem struct {
|
||||
UserId int `json:"userId"`
|
||||
Username string `json:"username"`
|
||||
SkinId int `json:"skinId"`
|
||||
Url string `json:"url"`
|
||||
Is1_8 bool `json:"is1_8"`
|
||||
IsSlim bool `json:"isSlim"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func (s *SkinItem) Save() {
|
||||
str, _ := json.Marshal(s)
|
||||
services.RedisPool.Cmd("SET", tools.BuildKey(s.Username), str)
|
||||
}
|
||||
|
||||
func FindRecord(username string) (SkinItem, error) {
|
||||
var record SkinItem;
|
||||
result, err := services.RedisPool.Cmd("GET", tools.BuildKey(username)).Str();
|
||||
if (err == nil) {
|
||||
decodeErr := json.Unmarshal([]byte(result), &record)
|
||||
if (decodeErr != nil) {
|
||||
log.Println("Cannot decode record data")
|
||||
}
|
||||
} else {
|
||||
log.Println("Error on request user data: " + err.Error())
|
||||
}
|
||||
|
||||
return record, err
|
||||
}
|
15
lib/data/TexturesResponse.go
Normal file
15
lib/data/TexturesResponse.go
Normal file
@ -0,0 +1,15 @@
|
||||
package data
|
||||
|
||||
type TexturesResponse struct {
|
||||
Skin *Skin `json:"SKIN"`
|
||||
}
|
||||
|
||||
type Skin struct {
|
||||
Url string `json:"url"`
|
||||
Hash string `json:"hash"`
|
||||
Metadata *SkinMetadata `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
type SkinMetadata struct {
|
||||
Model string `json:"model"`
|
||||
}
|
25
lib/routes/Cape.go
Normal file
25
lib/routes/Cape.go
Normal file
@ -0,0 +1,25 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/tools"
|
||||
)
|
||||
|
||||
func Cape(w http.ResponseWriter, r *http.Request) {
|
||||
username := tools.ParseUsername(mux.Vars(r)["username"])
|
||||
http.Redirect(w, r, "http://skins.minecraft.net/MinecraftCloaks/" + username + ".png", 301)
|
||||
}
|
||||
|
||||
func CapeGET(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.URL.Query().Get("name")
|
||||
if username == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
mux.Vars(r)["username"] = username
|
||||
Cape(w, r)
|
||||
}
|
28
lib/routes/MinecraftPHP.go
Normal file
28
lib/routes/MinecraftPHP.go
Normal file
@ -0,0 +1,28 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Метод-наследие от первой версии системы скинов.
|
||||
// Всё ещё иногда используется
|
||||
// Просто конвертируем данные и отправляем их в основной обработчик
|
||||
func MinecraftPHP(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.URL.Query().Get("name")
|
||||
required := r.URL.Query().Get("type")
|
||||
if username == "" || required == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
mux.Vars(r)["username"] = username
|
||||
switch required {
|
||||
case "skin": Skin(w, r)
|
||||
case "cloack": Cape(w, r)
|
||||
default: {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
}
|
18
lib/routes/NotFound.go
Normal file
18
lib/routes/NotFound.go
Normal file
@ -0,0 +1,18 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func NotFound(w http.ResponseWriter, r *http.Request) {
|
||||
json, _ := json.Marshal(map[string]string{
|
||||
"status": "404",
|
||||
"message": "Not Found",
|
||||
"link": "http://docs.ely.by/skin-system.html",
|
||||
})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write(json)
|
||||
}
|
29
lib/routes/SetSkin.go
Normal file
29
lib/routes/SetSkin.go
Normal file
@ -0,0 +1,29 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/data"
|
||||
)
|
||||
|
||||
func SetSkin(w http.ResponseWriter, r *http.Request) {
|
||||
key := r.Header.Get("X-Ely-key")
|
||||
if key != "43fd2ce61b3f5704dfd729c1f2d6ffdb" {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
w.Write([]byte("Nice try"))
|
||||
return
|
||||
}
|
||||
|
||||
skin := new(data.SkinItem)
|
||||
skin.Username = r.PostFormValue("username")
|
||||
skin.UserId, _ = strconv.Atoi(r.PostFormValue("userId"))
|
||||
skin.SkinId, _ = strconv.Atoi(r.PostFormValue("skinId"))
|
||||
skin.Hash = r.PostFormValue("hash")
|
||||
skin.Is1_8, _ = strconv.ParseBool(r.PostFormValue("is1_8"))
|
||||
skin.IsSlim, _ = strconv.ParseBool(r.PostFormValue("isSlim"))
|
||||
skin.Url = r.PostFormValue("url")
|
||||
skin.Save()
|
||||
|
||||
w.Write([]byte("OK"))
|
||||
}
|
34
lib/routes/Skin.go
Normal file
34
lib/routes/Skin.go
Normal file
@ -0,0 +1,34 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/tools"
|
||||
"elyby/minecraft-skinsystem/lib/data"
|
||||
)
|
||||
|
||||
func Skin(w http.ResponseWriter, r *http.Request) {
|
||||
username := tools.ParseUsername(mux.Vars(r)["username"])
|
||||
log.Println("request skin for username " + username);
|
||||
rec, err := data.FindRecord(username)
|
||||
if (err != nil) {
|
||||
http.Redirect(w, r, "http://skins.minecraft.net/MinecraftSkins/" + username + ".png", 301)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, tools.BuildElyUrl(rec.Url), 301);
|
||||
}
|
||||
|
||||
func SkinGET(w http.ResponseWriter, r *http.Request) {
|
||||
username := r.URL.Query().Get("name")
|
||||
if username == "" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
mux.Vars(r)["username"] = username
|
||||
Skin(w, r)
|
||||
}
|
42
lib/routes/Textures.go
Normal file
42
lib/routes/Textures.go
Normal file
@ -0,0 +1,42 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/data"
|
||||
"elyby/minecraft-skinsystem/lib/tools"
|
||||
)
|
||||
|
||||
func Textures(w http.ResponseWriter, r *http.Request) {
|
||||
username := tools.ParseUsername(mux.Vars(r)["username"])
|
||||
log.Println("request textures for username " + username)
|
||||
|
||||
rec, err := data.FindRecord(username)
|
||||
if (err != nil || rec.SkinId == 0) {
|
||||
rec.Url = "http://skins.minecraft.net/MinecraftSkins/" + username + ".png"
|
||||
rec.Hash = string(tools.BuildNonElyTexturesHash(username))
|
||||
} else {
|
||||
rec.Url = tools.BuildElyUrl(rec.Url)
|
||||
}
|
||||
|
||||
textures := data.TexturesResponse{
|
||||
Skin: &data.Skin{
|
||||
Url: rec.Url,
|
||||
Hash: rec.Hash,
|
||||
},
|
||||
}
|
||||
|
||||
if (rec.IsSlim) {
|
||||
textures.Skin.Metadata = &data.SkinMetadata{
|
||||
Model: "slim",
|
||||
}
|
||||
}
|
||||
|
||||
response,_ := json.Marshal(textures)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(response)
|
||||
}
|
10
lib/services/services.go
Normal file
10
lib/services/services.go
Normal file
@ -0,0 +1,10 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/mediocregopher/radix.v2/pool"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var RedisPool *pool.Pool
|
||||
|
||||
var Router *mux.Router
|
40
lib/tools/tools.go
Normal file
40
lib/tools/tools.go
Normal file
@ -0,0 +1,40 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"crypto/md5"
|
||||
"strconv"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
func ParseUsername(username string) string {
|
||||
const suffix = ".png"
|
||||
if strings.HasSuffix(username, suffix) {
|
||||
username = strings.TrimSuffix(username, suffix)
|
||||
}
|
||||
|
||||
return username
|
||||
}
|
||||
|
||||
func BuildNonElyTexturesHash(username string) string {
|
||||
hour := getCurrentHour()
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte("non-ely-" + strconv.FormatInt(hour, 10) + "-" + username))
|
||||
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
|
||||
func BuildKey(username string) string {
|
||||
return "username:" + strings.ToLower(username)
|
||||
}
|
||||
|
||||
func BuildElyUrl(route string) string {
|
||||
return "http://ely.by" + route
|
||||
}
|
||||
|
||||
func getCurrentHour() int64 {
|
||||
n := time.Now()
|
||||
return time.Date(n.Year(), n.Month(), n.Day(), n.Hour(), 0, 0, 0, time.UTC).Unix()
|
||||
}
|
||||
|
22
lib/tools/tools_test.go
Normal file
22
lib/tools/tools_test.go
Normal file
@ -0,0 +1,22 @@
|
||||
package tools_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
. "elyby/minecraft-skinsystem/lib/tools"
|
||||
)
|
||||
|
||||
func TestParseUsername(t *testing.T) {
|
||||
if ParseUsername("test.png") != "test" {
|
||||
t.Error("Function should trim .png at end")
|
||||
}
|
||||
|
||||
if ParseUsername("test") != "test" {
|
||||
t.Error("Function should return string itself, if it not contains .png at end")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildKey(t *testing.T) {
|
||||
if BuildKey("Test") != "username:test" {
|
||||
t.Error("Function shound convert string to lower case and concatenate it with usernmae:")
|
||||
}
|
||||
}
|
64
minecraft-skinsystem.go
Normal file
64
minecraft-skinsystem.go
Normal file
@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
//"time"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/mediocregopher/radix.v2/pool"
|
||||
|
||||
"elyby/minecraft-skinsystem/lib/routes"
|
||||
"elyby/minecraft-skinsystem/lib/services"
|
||||
//"github.com/mediocregopher/radix.v2/redis"
|
||||
)
|
||||
|
||||
const redisString string = "redis:6379"
|
||||
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
pool, redisErr := pool.New("tcp", redisString, 10)
|
||||
if redisErr != nil {
|
||||
log.Fatal("Redis unavailable")
|
||||
}
|
||||
|
||||
router := mux.NewRouter().StrictSlash(true)
|
||||
router.HandleFunc("/skins/{username}", routes.Skin).Methods("GET").Name("skins")
|
||||
router.HandleFunc("/cloaks/{username}", routes.Cape).Methods("GET").Name("cloaks")
|
||||
router.HandleFunc("/textures/{username}", routes.Textures).Methods("GET").Name("textures")
|
||||
// Legacy
|
||||
router.HandleFunc("/minecraft.php", routes.MinecraftPHP).Methods("GET")
|
||||
router.HandleFunc("/skins/", routes.SkinGET).Methods("GET")
|
||||
router.HandleFunc("/cloaks/", routes.CapeGET).Methods("GET")
|
||||
// 404
|
||||
router.NotFoundHandler = http.HandlerFunc(routes.NotFound)
|
||||
|
||||
apiRouter := router.PathPrefix("/api").Subrouter()
|
||||
apiRouter.HandleFunc("/user/{username}/skin", routes.SetSkin).Methods("POST")
|
||||
|
||||
services.RedisPool = pool
|
||||
services.Router = router
|
||||
|
||||
/*go func() {
|
||||
for {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
resp := services.Redis.Cmd("PING")
|
||||
if (resp.Err != nil) {
|
||||
log.Println("Redis not pinged. Try to reconnect")
|
||||
newClient, redisErr := redis.Dial("tcp", redisString)
|
||||
if (redisErr != nil) {
|
||||
log.Println("Cannot reconnect to redis")
|
||||
} else {
|
||||
services.Redis = newClient
|
||||
log.Println("Reconnected")
|
||||
}
|
||||
}
|
||||
}
|
||||
}()*/
|
||||
|
||||
log.Println("Started");
|
||||
log.Fatal(http.ListenAndServe(":80", router))
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Phalcon\Mvc\Collection;
|
||||
|
||||
/**
|
||||
* @property string $id
|
||||
*/
|
||||
class Skins extends Collection {
|
||||
|
||||
public $_id;
|
||||
public $userId;
|
||||
public $nickname;
|
||||
public $skinId;
|
||||
public $url;
|
||||
public $is1_8;
|
||||
public $isSlim;
|
||||
public $hash;
|
||||
|
||||
public function getId() {
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
public function getSource() {
|
||||
return 'skins';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $nickname
|
||||
* @return bool|Skins
|
||||
*/
|
||||
public static function findByNickname($nickname) {
|
||||
return static::findFirst([
|
||||
[
|
||||
'nickname' => mb_convert_case($nickname, MB_CASE_LOWER, ENCODING),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
40
nginx.conf
40
nginx.conf
@ -1,40 +0,0 @@
|
||||
location /minecraft.php {
|
||||
if ($arg_name = "") {
|
||||
return 400;
|
||||
}
|
||||
|
||||
if ($arg_type = "cloack") {
|
||||
rewrite .* http://skins.minecraft.net/MinecraftCloaks/$arg_name.png? permanent;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($arg_type = "skin") {
|
||||
rewrite .* /skins/$arg_name last;
|
||||
}
|
||||
|
||||
return 404;
|
||||
}
|
||||
|
||||
location /cloaks/ {
|
||||
try_files $uri $uri.png @cloaks;
|
||||
}
|
||||
|
||||
location @cloaks {
|
||||
rewrite ^/cloaks/(.+?)(\.[^.]*$|$)$ http://skins.minecraft.net/MinecraftCloaks/$1.png? permanent;
|
||||
}
|
||||
|
||||
location ~* ^/skins/$ {
|
||||
if ($arg_name = "") {
|
||||
return 400;
|
||||
}
|
||||
|
||||
rewrite .* /skins/$arg_name permanent;
|
||||
}
|
||||
|
||||
location ~* ^/cloaks/$ {
|
||||
if ($arg_name = "") {
|
||||
return 400;
|
||||
}
|
||||
|
||||
rewrite .* /cloaks/$arg_name permanent;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
AddDefaultCharset UTF-8
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L]
|
||||
</IfModule>
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Phalcon\Mvc\Micro;
|
||||
|
||||
error_reporting(E_ALL);
|
||||
|
||||
try {
|
||||
/** @var \Phalcon\Config $config */
|
||||
$config = include __DIR__ . '/../config/config.php';
|
||||
/** @var \Phalcon\Loader $loader */
|
||||
include __DIR__ . '/../config/loader.php';
|
||||
/** @var Phalcon\DI\FactoryDefault $di */
|
||||
include __DIR__ . '/../config/services.php';
|
||||
|
||||
$app = new Micro($di);
|
||||
include __DIR__ . '/../app.php';
|
||||
|
||||
$app->handle();
|
||||
|
||||
} catch (Phalcon\Exception $e) {
|
||||
echo $e->getMessage();
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
Loading…
Reference in New Issue
Block a user