Added Basic API! Can now get into lobby (C1S2)
This commit is contained in:
parent
a857ce7e63
commit
113c68a38d
|
@ -15,6 +15,13 @@ type CS struct {
|
|||
Output struct {
|
||||
Level string
|
||||
}
|
||||
API struct {
|
||||
Host string
|
||||
Port string
|
||||
}
|
||||
JWT struct {
|
||||
Secret string
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -52,4 +59,19 @@ func LoadConfig() {
|
|||
if Config.Output.Level != "dev" && Config.Output.Level != "prod" && Config.Output.Level != "time" && Config.Output.Level != "info" {
|
||||
panic("Output Level must be either dev or prod")
|
||||
}
|
||||
|
||||
Config.API.Host = cfg.Section("api").Key("host").String()
|
||||
if Config.API.Host == "" {
|
||||
panic("API Host is empty")
|
||||
}
|
||||
|
||||
Config.API.Port = cfg.Section("api").Key("port").String()
|
||||
if Config.API.Port == "" {
|
||||
panic("API Port is empty")
|
||||
}
|
||||
|
||||
Config.JWT.Secret = cfg.Section("jwt").Key("secret").String()
|
||||
if Config.JWT.Secret == "" {
|
||||
panic("JWT Secret is empty")
|
||||
}
|
||||
}
|
29
aid/errors.go
Normal file
29
aid/errors.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
package aid
|
||||
|
||||
func ErrorBadRequest(errorMessage string) JSON {
|
||||
return JSON{
|
||||
"errorCode": "errors.com.epicgames.bad_request",
|
||||
"errorMessage": errorMessage,
|
||||
"numericErrorCode": 1001,
|
||||
"originatingService": "fortnite",
|
||||
"intent": "prod-live",
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
ErrorNotFound = JSON{
|
||||
"errorCode": "errors.com.epicgames.common.not_found",
|
||||
"errorMessage": "Resource Not found",
|
||||
"numericErrorCode": 1004,
|
||||
"originatingService": "fortnite",
|
||||
"intent": "prod-live",
|
||||
}
|
||||
|
||||
ErrorInternalServer = map[string]interface{}{
|
||||
"errorCode": "errors.com.epicgames.common.server_error",
|
||||
"errorMessage": "Internal Server Error",
|
||||
"numericErrorCode": 1000,
|
||||
"originatingService": "fortnite",
|
||||
"intent": "prod-live",
|
||||
}
|
||||
)
|
31
aid/fiber.go
Normal file
31
aid/fiber.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package aid
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/limiter"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
)
|
||||
|
||||
func FiberLogger() fiber.Handler {
|
||||
return logger.New(logger.Config{
|
||||
Format: "${status} ${path}\n",
|
||||
})
|
||||
}
|
||||
|
||||
func FiberLimiter() fiber.Handler {
|
||||
return limiter.New(limiter.Config{
|
||||
Max: 100,
|
||||
Expiration: 1 * time.Minute,
|
||||
})
|
||||
}
|
||||
|
||||
func FiberCors() fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
c.Set("Access-Control-Allow-Origin", "*")
|
||||
c.Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
c.Set("Access-Control-Allow-Headers", "Content-Type, Authorization, Origin, Accept, X-Requested-With")
|
||||
return c.Next()
|
||||
}
|
||||
}
|
44
aid/token.go
Normal file
44
aid/token.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package aid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
func JWTSign(m JSON) (string, error) {
|
||||
claims := jwt.MapClaims{}
|
||||
|
||||
for k, v := range m {
|
||||
claims[k] = v
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(Config.JWT.Secret))
|
||||
}
|
||||
|
||||
func JWTVerify(tokenString string) (JSON, error) {
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
return []byte(Config.JWT.Secret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !token.Valid {
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid claims")
|
||||
}
|
||||
|
||||
json := JSON{}
|
||||
for k, v := range claims {
|
||||
json[k] = v
|
||||
}
|
||||
|
||||
return json, nil
|
||||
}
|
|
@ -11,4 +11,15 @@ drop=false
|
|||
; info = everything
|
||||
; time = only time taken
|
||||
; prod = only errors
|
||||
level="info"
|
||||
level="info"
|
||||
|
||||
[api]
|
||||
; port to listen on
|
||||
port=80
|
||||
; host to listen on
|
||||
; only change if you know what you're doing
|
||||
host="0.0.0.0"
|
||||
|
||||
[jwt]
|
||||
; secret for jwt signing
|
||||
secret="secret"
|
17
go.mod
17
go.mod
|
@ -3,21 +3,28 @@ module github.com/ectrc/snow
|
|||
go 1.21.3
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.50.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/philhofer/fwd v1.1.2 // indirect
|
||||
github.com/r3labs/diff/v3 v3.0.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rs/zerolog v1.26.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
|
@ -29,6 +36,10 @@ require (
|
|||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.6.3 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tinylib/msgp v1.1.8 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.50.0 // indirect
|
||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
|
@ -36,7 +47,7 @@ require (
|
|||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
46
go.sum
46
go.sum
|
@ -43,6 +43,8 @@ github.com/Vilsol/ue4pak v0.1.5 h1:XE17rYgieBh67vpB2lZI6ARv3KxMzAelWh/RDA9O7Ms=
|
|||
github.com/Vilsol/ue4pak v0.1.5/go.mod h1:e/4WiPI80PbsP2+IOWYoqwiZT+lKAcoEr0wmVY3ROLQ=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
|
@ -85,8 +87,12 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
|||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofiber/fiber/v2 v2.50.0 h1:ia0JaB+uw3GpNSCR5nvC5dsaxXjRU5OEu36aytx+zGw=
|
||||
github.com/gofiber/fiber/v2 v2.50.0/go.mod h1:21eytvay9Is7S6z+OgPi7c7n4++tnClWmhpimVHMimw=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
@ -142,6 +148,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
|
|||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
|
@ -174,6 +182,8 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
|
@ -190,6 +200,10 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
|||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
|
@ -202,6 +216,8 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn
|
|||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
|
@ -218,6 +234,9 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
|
|||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/r3labs/diff/v3 v3.0.1 h1:CBKqf3XmNRHXKmdU7mZP1w7TV0pDyVCis1AUHtA4Xtg=
|
||||
github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJX63dgo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
|
@ -268,7 +287,15 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
|
||||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
|
||||
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||
|
@ -282,6 +309,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
|
@ -303,6 +331,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
|
@ -342,6 +371,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -378,6 +409,8 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -398,6 +431,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -437,12 +472,20 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -451,6 +494,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -506,6 +550,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
164
handlers/auth.go
Normal file
164
handlers/auth.go
Normal file
|
@ -0,0 +1,164 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
p "github.com/ectrc/snow/person"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
oatuhTokenGrantTypes = map[string]func(c *fiber.Ctx, body *OAuthTokenBody) error{
|
||||
"client_credentials": PostOAuthTokenClientCredentials,
|
||||
"password": PostOAuthTokenPassword,
|
||||
}
|
||||
)
|
||||
|
||||
type OAuthTokenBody struct {
|
||||
GrantType string `form:"grant_type" binding:"required"`
|
||||
Username string `form:"username"`
|
||||
Password string `form:"password"`
|
||||
}
|
||||
|
||||
func PostOAuthToken(c *fiber.Ctx) error {
|
||||
var body OAuthTokenBody
|
||||
|
||||
if err := c.BodyParser(&body); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Request Body"))
|
||||
}
|
||||
|
||||
if action, ok := oatuhTokenGrantTypes[body.GrantType]; ok {
|
||||
return action(c, &body)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Grant Type"))
|
||||
}
|
||||
|
||||
func PostOAuthTokenClientCredentials(c *fiber.Ctx, body *OAuthTokenBody) error {
|
||||
credentials, err := aid.JWTSign(aid.JSON{
|
||||
"snow_id": 0, // custom
|
||||
"t": "s",
|
||||
"am": "client_credentials", // authorization method
|
||||
"ic": true, // internal client
|
||||
"mver": false, // mobile version
|
||||
"clsvc": "snow", // client service
|
||||
"clid": c.IP(), // client id
|
||||
"jti": rand.Int63(), // jwt id
|
||||
"p": base64.StdEncoding.EncodeToString([]byte(c.IP())), // payload
|
||||
"hours_expire": 1,
|
||||
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||
"access_token": "eg1~"+credentials,
|
||||
"token_type": "bearer",
|
||||
"client_id": c.IP(),
|
||||
"client_service": "snow",
|
||||
"internal_client": true,
|
||||
"expires_in": 3600,
|
||||
"expires_at": time.Now().Add(time.Hour).Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
}
|
||||
|
||||
func PostOAuthTokenPassword(c *fiber.Ctx, body *OAuthTokenBody) error {
|
||||
if body.Username == "" || body.Password == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Username/Password is empty"))
|
||||
}
|
||||
|
||||
person := p.FindByDisplay(strings.Split(body.Username, "@")[0])
|
||||
if person == nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
||||
}
|
||||
|
||||
if person.AccessKey == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Activation Required"))
|
||||
}
|
||||
|
||||
if person.AccessKey != body.Password {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Invalid Access Key"))
|
||||
}
|
||||
|
||||
access, err := aid.JWTSign(aid.JSON{
|
||||
"snow_id": person.ID, // custom
|
||||
"iai": person.ID, // account id
|
||||
"dn": person.DisplayName, // display name
|
||||
"t": "s",
|
||||
"am": "password", // authorization method
|
||||
"ic": true, // internal client
|
||||
"mver": false, // mobile version
|
||||
"clsvc": "snow", // client service
|
||||
"app": "com.epicgames.fortnite", // app name
|
||||
"clid": c.IP(), // client id
|
||||
"dvid": "default", // device id
|
||||
"jti": rand.Int63(), // jwt id
|
||||
"p": base64.StdEncoding.EncodeToString([]byte(c.IP())), // payload
|
||||
"sec": 1, // security level
|
||||
"hours_expire": 24,
|
||||
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
||||
}
|
||||
|
||||
refresh, err := aid.JWTSign(aid.JSON{
|
||||
"snow_id": person.ID, // custom
|
||||
"sub": person.ID, // account id
|
||||
"clid": c.IP(), // client id
|
||||
"jti": rand.Int63(), // jwt id
|
||||
"t": "s",
|
||||
"am": "refresh_token", // authorization method
|
||||
"hours_expire": 24,
|
||||
"creation_date": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(aid.ErrorInternalServer)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||
"access_token": "eg1~"+access,
|
||||
"account_id": person.ID,
|
||||
"client_id": c.IP(),
|
||||
"client_service": "snow",
|
||||
"device_id": "default",
|
||||
"display_name": person.DisplayName,
|
||||
"expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
||||
"expires_in": 86400,
|
||||
"internal_client": true,
|
||||
"refresh_expires": 86400,
|
||||
"refresh_expires_at": time.Now().Add(time.Hour * 24).Format("2006-01-02T15:04:05.999Z"),
|
||||
"refresh_token": "eg1~"+refresh,
|
||||
"token_type": "bearer",
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteOAuthSessions(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{})
|
||||
}
|
||||
|
||||
func GetPublicAccount(c *fiber.Ctx) error {
|
||||
person := p.Find(c.Params("accountId"))
|
||||
if person == nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||
"id": person.ID,
|
||||
"displayName": person.DisplayName,
|
||||
})
|
||||
}
|
||||
|
||||
func GetPublicAccountExternalAuths(c *fiber.Ctx) error {
|
||||
person := p.Find(c.Params("accountId"))
|
||||
if person == nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("No Account Found"))
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON([]aid.JSON{})
|
||||
}
|
36
handlers/common.go
Normal file
36
handlers/common.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func AnyNoContent(c *fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func PostTryPlayOnPlatform(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).SendString("true")
|
||||
}
|
||||
|
||||
func GetEnabledFeatures(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON([]string{})
|
||||
}
|
||||
|
||||
func PostGrantAccess(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).SendString("true")
|
||||
}
|
||||
|
||||
func GetAccountReceipts(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON([]string{})
|
||||
}
|
||||
|
||||
func GetSessionFindPlayer(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON([]string{})
|
||||
}
|
||||
|
||||
func GetVersionCheck(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||
"type": "NO_UPDATE",
|
||||
})
|
||||
}
|
14
handlers/lightswitch.go
Normal file
14
handlers/lightswitch.go
Normal file
|
@ -0,0 +1,14 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func GetLightswitchBulkStatus(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON([]aid.JSON{{
|
||||
"serviceInstanceId": "fortnite",
|
||||
"status": "UP",
|
||||
"banned": false,
|
||||
}})
|
||||
}
|
57
handlers/profile.go
Normal file
57
handlers/profile.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
p "github.com/ectrc/snow/person"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
profileActions = map[string]func(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
"QueryProfile": PostQueryProfileAction,
|
||||
"ClientQuestLogin": PostQueryProfileAction,
|
||||
}
|
||||
)
|
||||
|
||||
func PostProfileAction(c *fiber.Ctx) error {
|
||||
person := p.Find(c.Params("accountId"))
|
||||
if person == nil {
|
||||
return c.Status(404).JSON(aid.ErrorBadRequest("No Account Found"))
|
||||
}
|
||||
|
||||
profile := person.GetProfileFromType(c.Query("profileId"))
|
||||
if profile == nil {
|
||||
return c.Status(404).JSON(aid.ErrorBadRequest("No Profile Found"))
|
||||
}
|
||||
|
||||
snapshot := profile.Snapshot()
|
||||
if action, ok := profileActions[c.Params("action")]; ok {
|
||||
err := action(c, person, profile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
profile.Diff(snapshot)
|
||||
profile.Revision++
|
||||
|
||||
return c.Status(200).JSON(aid.JSON{
|
||||
"profileId": profile.Type,
|
||||
"profileRevision": profile.Revision,
|
||||
"profileCommandRevision": profile.Revision,
|
||||
"profileChangesBaseRevision": profile.Revision - 1,
|
||||
"profileChanges": profile.Changes,
|
||||
"multiUpdate": []aid.JSON{},
|
||||
"notifications": []aid.JSON{},
|
||||
"responseVersion": 1,
|
||||
"serverTime": time.Now().Format("2006-01-02T15:04:05.999Z"),
|
||||
})
|
||||
}
|
||||
|
||||
func PostQueryProfileAction(c *fiber.Ctx, person *p.Person, profile *p.Profile) error {
|
||||
profile.Changes = []interface{}{}
|
||||
profile.CreateFullProfileUpdateChange()
|
||||
return nil
|
||||
}
|
32
handlers/storage.go
Normal file
32
handlers/storage.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func GetCloudStorageFiles(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON([]aid.JSON{})
|
||||
}
|
||||
|
||||
func GetCloudStorageConfig(c *fiber.Ctx) error {
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||
"enumerateFilesPath": "/api/cloudstorage/system",
|
||||
"enableMigration": true,
|
||||
"enableWrites": true,
|
||||
"epicAppName": "Live",
|
||||
"isAuthenticated": true,
|
||||
"disableV2": true,
|
||||
"lastUpdated": "2021-01-01T00:00:00Z",
|
||||
"transports": []string{},
|
||||
})
|
||||
}
|
||||
|
||||
func GetCloudStorageFile(c *fiber.Ctx) error {
|
||||
fileName := c.Params("fileName")
|
||||
if fileName == "" {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{})
|
||||
}
|
57
main.go
57
main.go
|
@ -2,8 +2,11 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/handlers"
|
||||
"github.com/ectrc/snow/person"
|
||||
"github.com/ectrc/snow/storage"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
func init() {
|
||||
aid.LoadConfig()
|
||||
|
@ -36,17 +39,55 @@ func init() {
|
|||
}
|
||||
|
||||
func init() {
|
||||
if aid.Config.Database.DropAllTables {
|
||||
person.NewFortnitePerson("ac", "ket")
|
||||
}
|
||||
|
||||
aid.PrintTime("Loading all persons from database", func() {
|
||||
for _, person := range person.AllFromDatabase() {
|
||||
aid.Print("Loaded person: " + person.DisplayName)
|
||||
}
|
||||
})
|
||||
|
||||
go storage.Cache.CacheKiller()
|
||||
}
|
||||
|
||||
func main() {
|
||||
aid.PrintTime("Fetching Persons", func() {
|
||||
users := person.AllFromDatabase()
|
||||
aid.Print("Found", len(users), "users")
|
||||
for _, user := range users {
|
||||
aid.Print(user.ID)
|
||||
}
|
||||
})
|
||||
r := fiber.New()
|
||||
|
||||
// aid.WaitForExit()
|
||||
r.Use(aid.FiberLogger())
|
||||
r.Use(aid.FiberLimiter())
|
||||
r.Use(aid.FiberCors())
|
||||
|
||||
account := r.Group("/account/api")
|
||||
account.Get("/public/account/:accountId", handlers.GetPublicAccount)
|
||||
account.Get("/public/account/:accountId/externalAuths", handlers.GetPublicAccountExternalAuths)
|
||||
account.Post("/oauth/token", handlers.PostOAuthToken)
|
||||
account.Delete("/oauth/sessions/kill", handlers.DeleteOAuthSessions)
|
||||
|
||||
fortnite := r.Group("/fortnite/api")
|
||||
fortnite.Get("/receipts/v1/account/:accountId/receipts", handlers.GetAccountReceipts)
|
||||
fortnite.Get("/versioncheck/*", handlers.GetVersionCheck)
|
||||
|
||||
matchmaking := fortnite.Group("/matchmaking")
|
||||
matchmaking.Get("/session/findPlayer/:accountId", handlers.GetSessionFindPlayer)
|
||||
|
||||
storage := fortnite.Group("/cloudstorage")
|
||||
storage.Get("/system", handlers.GetCloudStorageFiles)
|
||||
storage.Get("/system/config", handlers.GetCloudStorageConfig)
|
||||
storage.Get("/system/:fileName", handlers.GetCloudStorageFile)
|
||||
|
||||
game := fortnite.Group("/game/v2")
|
||||
game.Post("/tryPlayOnPlatform/account/:accountId", handlers.PostTryPlayOnPlatform)
|
||||
game.Post("/grant_access/:accountId", handlers.PostGrantAccess)
|
||||
game.Get("/enabled_features", handlers.GetEnabledFeatures)
|
||||
|
||||
profile := game.Group("/profile/:accountId")
|
||||
profile.Post("/client/:action", handlers.PostProfileAction)
|
||||
|
||||
lightswitch := r.Group("/lightswitch/api")
|
||||
lightswitch.Get("/service/bulk/status", handlers.GetLightswitchBulkStatus)
|
||||
|
||||
r.All("*", func(c *fiber.Ctx) error { return c.Status(fiber.StatusNotFound).JSON(aid.ErrorNotFound) })
|
||||
r.Listen(aid.Config.API.Host + aid.Config.API.Port)
|
||||
}
|
79
person/fortnite.go
Normal file
79
person/fortnite.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package person
|
||||
|
||||
import "github.com/ectrc/snow/aid"
|
||||
|
||||
func NewFortnitePerson(displayName string, key string) {
|
||||
person := NewPerson()
|
||||
person.DisplayName = displayName
|
||||
person.AccessKey = key
|
||||
|
||||
character := NewItem("AthenaCharacter:CID_001_Athena_Commando_F_Default", 1)
|
||||
pickaxe := NewItem("AthenaPickaxe:DefaultPickaxe", 1)
|
||||
glider := NewItem("AthenaGlider:DefaultGlider", 1)
|
||||
default_dance := NewItem("AthenaDance:EID_DanceMoves", 1)
|
||||
|
||||
person.AthenaProfile.Items.AddItem(character)
|
||||
person.AthenaProfile.Items.AddItem(pickaxe)
|
||||
person.AthenaProfile.Items.AddItem(glider)
|
||||
person.AthenaProfile.Items.AddItem(default_dance)
|
||||
person.CommonCoreProfile.Items.AddItem(NewItem("Currency:MtxPurchased", 0))
|
||||
|
||||
person.Loadout.Character = character.ID
|
||||
person.Loadout.Pickaxe = pickaxe.ID
|
||||
person.Loadout.Glider = glider.ID
|
||||
person.Loadout.Dances[0] = default_dance.ID
|
||||
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("mfa_reward_claimed", true))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("rested_xp_overflow", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("lifetime_wins", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("party_assist_quest", ""))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("quest_manager", aid.JSON{}))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("inventory_limit_bonus", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("daily_rewards", []aid.JSON{}))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("competitive_identity", aid.JSON{}))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("season_update", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("season_num", 2))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("permissions", []aid.JSON{}))
|
||||
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("loadouts", []aid.JSON{}))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("last_applied_loadout", ""))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("active_loadout_index", 0))
|
||||
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("accountLevel", 1))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("level", 1))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("xp", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("xp_overflow", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("rested_xp", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("rested_xp_mult", 0))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("rested_xp_exchange", 0))
|
||||
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("book_purchased", false))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("book_level", 1))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("book_xp", 0))
|
||||
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_character", person.Loadout.Character))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_backpack", person.Loadout.Backpack))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_pickaxe", person.Loadout.Pickaxe))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_glider", person.Loadout.Glider))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_skydivecontrail", person.Loadout.SkyDiveContrail))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_dance", person.Loadout.Dances))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_itemwraps", person.Loadout.ItemWraps))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_loadingscreen", person.Loadout.LoadingScreen))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("favorite_musicpack", person.Loadout.MusicPack))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("banner_icon", person.Loadout.BannerIcon))
|
||||
person.AthenaProfile.Attributes.AddAttribute(NewAttribute("banner_color", person.Loadout.BannerColor))
|
||||
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("mfa_enabled", true))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("mtx_affiliate", ""))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("mtx_purchase_history", aid.JSON{
|
||||
"refundsUsed": 0,
|
||||
"refundCredits": 3,
|
||||
"purchases": []any{},
|
||||
}))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("current_mtx_platform", "EpicPC"))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("allowed_to_receive_gifts", true))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("allowed_to_send_gifts", true))
|
||||
person.CommonCoreProfile.Attributes.AddAttribute(NewAttribute("gift_history", aid.JSON{}))
|
||||
|
||||
person.Save()
|
||||
}
|
|
@ -8,8 +8,11 @@ import (
|
|||
type Person struct {
|
||||
ID string
|
||||
DisplayName string
|
||||
AccessKey string
|
||||
AthenaProfile *Profile
|
||||
CommonCoreProfile *Profile
|
||||
CommonPublicProfile *Profile
|
||||
Profile0 *Profile
|
||||
Loadout *Loadout
|
||||
}
|
||||
|
||||
|
@ -22,13 +25,16 @@ func NewPerson() *Person {
|
|||
return &Person{
|
||||
ID: uuid.New().String(),
|
||||
DisplayName: uuid.New().String(),
|
||||
AccessKey: "",
|
||||
AthenaProfile: NewProfile("athena"),
|
||||
CommonCoreProfile: NewProfile("common_core"),
|
||||
CommonPublicProfile: NewProfile("common_public"),
|
||||
Profile0: NewProfile("profile0"),
|
||||
Loadout: NewLoadout(),
|
||||
}
|
||||
}
|
||||
|
||||
func FromDatabase(personId string) *Person {
|
||||
func Find(personId string) *Person {
|
||||
person := storage.Repo.GetPerson(personId)
|
||||
if person == nil {
|
||||
return nil
|
||||
|
@ -37,6 +43,8 @@ func FromDatabase(personId string) *Person {
|
|||
loadout := FromDatabaseLoadout(&person.Loadout)
|
||||
athenaProfile := NewProfile("athena")
|
||||
commonCoreProfile := NewProfile("common_core")
|
||||
commonPublicProfile := NewProfile("common_public")
|
||||
profile0 := NewProfile("profile0")
|
||||
|
||||
for _, profile := range person.Profiles {
|
||||
if profile.Type == "athena" {
|
||||
|
@ -48,13 +56,72 @@ func FromDatabase(personId string) *Person {
|
|||
commonCoreProfile.ID = profile.ID
|
||||
commonCoreProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "common_public" {
|
||||
commonPublicProfile.ID = profile.ID
|
||||
commonPublicProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "profile0" {
|
||||
profile0.ID = profile.ID
|
||||
profile0 = FromDatabaseProfile(&profile)
|
||||
}
|
||||
}
|
||||
|
||||
return &Person{
|
||||
ID: person.ID,
|
||||
DisplayName: person.DisplayName,
|
||||
AccessKey: person.AccessKey,
|
||||
AthenaProfile: athenaProfile,
|
||||
CommonCoreProfile: commonCoreProfile,
|
||||
CommonPublicProfile: commonPublicProfile,
|
||||
Profile0: profile0,
|
||||
Loadout: loadout,
|
||||
}
|
||||
}
|
||||
|
||||
func FindByDisplay(displayName string) *Person {
|
||||
person := storage.Repo.GetPersonByDisplay(displayName)
|
||||
if person == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
loadout := FromDatabaseLoadout(&person.Loadout)
|
||||
athenaProfile := NewProfile("athena")
|
||||
commonCoreProfile := NewProfile("common_core")
|
||||
commonPublicProfile := NewProfile("common_public")
|
||||
profile0 := NewProfile("profile0")
|
||||
|
||||
for _, profile := range person.Profiles {
|
||||
if profile.Type == "athena" {
|
||||
athenaProfile.ID = profile.ID
|
||||
athenaProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "common_core" {
|
||||
commonCoreProfile.ID = profile.ID
|
||||
commonCoreProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "common_public" {
|
||||
commonPublicProfile.ID = profile.ID
|
||||
commonPublicProfile = FromDatabaseProfile(&profile)
|
||||
}
|
||||
|
||||
if profile.Type == "profile0" {
|
||||
profile0.ID = profile.ID
|
||||
profile0 = FromDatabaseProfile(&profile)
|
||||
}
|
||||
}
|
||||
|
||||
return &Person{
|
||||
ID: person.ID,
|
||||
DisplayName: person.DisplayName,
|
||||
AccessKey: person.AccessKey,
|
||||
AthenaProfile: athenaProfile,
|
||||
CommonCoreProfile: commonCoreProfile,
|
||||
CommonPublicProfile: commonPublicProfile,
|
||||
Profile0: profile0,
|
||||
Loadout: loadout,
|
||||
}
|
||||
}
|
||||
|
@ -63,12 +130,27 @@ func AllFromDatabase() []*Person {
|
|||
var persons []*Person
|
||||
|
||||
for _, person := range storage.Repo.GetAllPersons() {
|
||||
persons = append(persons, FromDatabase(person.ID))
|
||||
persons = append(persons, Find(person.ID))
|
||||
}
|
||||
|
||||
return persons
|
||||
}
|
||||
|
||||
func (p *Person) GetProfileFromType(profileType string) *Profile {
|
||||
switch profileType {
|
||||
case "athena":
|
||||
return p.AthenaProfile
|
||||
case "common_core":
|
||||
return p.CommonCoreProfile
|
||||
case "common_public":
|
||||
return p.CommonPublicProfile
|
||||
case "profile0":
|
||||
return p.Profile0
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Person) Save() {
|
||||
storage.Repo.SavePerson(p.ToDatabase())
|
||||
}
|
||||
|
@ -79,11 +161,14 @@ func (p *Person) ToDatabase() *storage.DB_Person {
|
|||
DisplayName: p.DisplayName,
|
||||
Profiles: []storage.DB_Profile{},
|
||||
Loadout: *p.Loadout.ToDatabase(),
|
||||
AccessKey: p.AccessKey,
|
||||
}
|
||||
|
||||
profilesToConvert := map[string]*Profile{
|
||||
"common_core": p.CommonCoreProfile,
|
||||
"athena": p.AthenaProfile,
|
||||
"athena": p.AthenaProfile,
|
||||
"common_public": p.CommonPublicProfile,
|
||||
"profile0": p.Profile0,
|
||||
}
|
||||
|
||||
for profileType, profile := range profilesToConvert {
|
||||
|
|
|
@ -3,6 +3,7 @@ package person
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ectrc/snow/aid"
|
||||
"github.com/ectrc/snow/storage"
|
||||
"github.com/google/uuid"
|
||||
"github.com/r3labs/diff/v3"
|
||||
|
@ -10,6 +11,7 @@ import (
|
|||
|
||||
type Profile struct {
|
||||
ID string
|
||||
PersonID string
|
||||
Items *ItemMutex
|
||||
Gifts *GiftMutex
|
||||
Quests *QuestMutex
|
||||
|
@ -22,6 +24,7 @@ type Profile struct {
|
|||
func NewProfile(profile string) *Profile {
|
||||
return &Profile{
|
||||
ID: uuid.New().String(),
|
||||
PersonID: "",
|
||||
Items: NewItemMutex(profile),
|
||||
Gifts: NewGiftMutex(),
|
||||
Quests: NewQuestMutex(),
|
||||
|
@ -62,6 +65,7 @@ func FromDatabaseProfile(profile *storage.DB_Profile) *Profile {
|
|||
|
||||
return &Profile{
|
||||
ID: profile.ID,
|
||||
PersonID: profile.PersonID,
|
||||
Items: items,
|
||||
Gifts: gifts,
|
||||
Quests: quests,
|
||||
|
@ -71,6 +75,44 @@ func FromDatabaseProfile(profile *storage.DB_Profile) *Profile {
|
|||
}
|
||||
}
|
||||
|
||||
func (p *Profile) GenerateFortniteProfileEntry() aid.JSON {
|
||||
items := aid.JSON{}
|
||||
attributes := aid.JSON{}
|
||||
|
||||
p.Items.RangeItems(func(id string, item *Item) bool {
|
||||
items[id] = item.GenerateFortniteItemEntry()
|
||||
return true
|
||||
})
|
||||
|
||||
p.Quests.RangeQuests(func(id string, quest *Quest) bool {
|
||||
items[id] = quest.GenerateFortniteQuestEntry()
|
||||
return true
|
||||
})
|
||||
|
||||
p.Gifts.RangeGifts(func(id string, gift *Gift) bool {
|
||||
items[id] = gift.GenerateFortniteGiftEntry()
|
||||
return true
|
||||
})
|
||||
|
||||
p.Attributes.RangeAttributes(func(id string, attribute *Attribute) bool {
|
||||
attributes[attribute.Key] = attribute.Value
|
||||
return true
|
||||
})
|
||||
|
||||
return aid.JSON{
|
||||
"profileId": p.Type,
|
||||
"accountId": p.PersonID,
|
||||
"rvn": p.Revision,
|
||||
"commandRevision": p.Revision,
|
||||
"wipeNumber": 0,
|
||||
"version": "",
|
||||
"items": items,
|
||||
"stats": aid.JSON{
|
||||
"attributes": attributes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Profile) Save() {
|
||||
//storage.Repo.SaveProfile(p.ToDatabase())
|
||||
}
|
||||
|
@ -259,6 +301,13 @@ func (p *Profile) CreateItemAttributeChangedChange(item *Item, attribute string)
|
|||
})
|
||||
}
|
||||
|
||||
func (p *Profile) CreateFullProfileUpdateChange() {
|
||||
p.Changes = append(p.Changes, FullProfileUpdate{
|
||||
ChangeType: "fullProfileUpdate",
|
||||
Profile: p.GenerateFortniteProfileEntry(),
|
||||
})
|
||||
}
|
||||
|
||||
type Loadout struct {
|
||||
ID string
|
||||
Character string
|
||||
|
|
|
@ -47,6 +47,20 @@ func (m *PersonsCache) GetPerson(id string) *DB_Person {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *PersonsCache) GetPersonByDisplay(displayName string) *DB_Person {
|
||||
var person *DB_Person
|
||||
m.Range(func(key, value interface{}) bool {
|
||||
if value.(*CacheEntry).Entry.(*DB_Person).DisplayName == displayName {
|
||||
person = value.(*CacheEntry).Entry.(*DB_Person)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return person
|
||||
}
|
||||
|
||||
func (m *PersonsCache) SavePerson(p *DB_Person) {
|
||||
m.Store(p.ID, &CacheEntry{
|
||||
Entry: p,
|
||||
|
|
|
@ -48,6 +48,26 @@ func (s *PostgresStorage) GetPerson(personId string) *DB_Person {
|
|||
return &dbPerson
|
||||
}
|
||||
|
||||
func (s *PostgresStorage) GetPersonByDisplay(displayName string) *DB_Person {
|
||||
var dbPerson DB_Person
|
||||
s.Postgres.
|
||||
Preload("Profiles").
|
||||
Preload("Profiles.Items.Variants").
|
||||
Preload("Profiles.Gifts.Loot").
|
||||
Preload("Profiles.Attributes").
|
||||
Preload("Profiles.Items").
|
||||
Preload("Profiles.Gifts").
|
||||
Preload("Profiles.Quests").
|
||||
Where("display_name = ?", displayName).
|
||||
Find(&dbPerson)
|
||||
|
||||
if dbPerson.ID == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &dbPerson
|
||||
}
|
||||
|
||||
func (s *PostgresStorage) GetAllPersons() []*DB_Person {
|
||||
var dbPersons []*DB_Person
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ type Storage interface {
|
|||
Migrate(table interface{}, tableName string)
|
||||
|
||||
GetPerson(personId string) *DB_Person
|
||||
GetPersonByDisplay(displayName string) *DB_Person
|
||||
GetAllPersons() []*DB_Person
|
||||
SavePerson(person *DB_Person)
|
||||
|
||||
|
@ -45,6 +46,21 @@ func (r *Repository) GetPerson(personId string) *DB_Person {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetPersonByDisplay(displayName string) *DB_Person {
|
||||
cachePerson := Cache.GetPersonByDisplay(displayName)
|
||||
if cachePerson != nil {
|
||||
return cachePerson
|
||||
}
|
||||
|
||||
storagePerson := r.Storage.GetPersonByDisplay(displayName)
|
||||
if storagePerson != nil {
|
||||
Cache.SavePerson(storagePerson)
|
||||
return storagePerson
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Repository) GetAllPersons() []*DB_Person {
|
||||
return r.Storage.GetAllPersons()
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ type Tabler interface {
|
|||
type DB_Person struct {
|
||||
ID string
|
||||
DisplayName string
|
||||
AccessKey string
|
||||
Profiles []DB_Profile `gorm:"foreignkey:PersonID"`
|
||||
Loadout DB_Loadout `gorm:"foreignkey:PersonID"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user