Remove friends and fix client credentials bug
This commit is contained in:
parent
8619cac5ca
commit
20cbc92e7f
|
@ -35,6 +35,7 @@ type CS struct {
|
||||||
Build float64
|
Build float64
|
||||||
Everything bool
|
Everything bool
|
||||||
Password bool
|
Password bool
|
||||||
|
DisableClientCredentials bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,4 +135,5 @@ func LoadConfig(file []byte) {
|
||||||
Config.Fortnite.Season = parsedSeason
|
Config.Fortnite.Season = parsedSeason
|
||||||
Config.Fortnite.Everything = cfg.Section("fortnite").Key("everything").MustBool(false)
|
Config.Fortnite.Everything = cfg.Section("fortnite").Key("everything").MustBool(false)
|
||||||
Config.Fortnite.Password = cfg.Section("fortnite").Key("password").MustBool(false)
|
Config.Fortnite.Password = cfg.Section("fortnite").Key("password").MustBool(false)
|
||||||
|
Config.Fortnite.DisableClientCredentials = cfg.Section("fortnite").Key("disable_client_credentials").MustBool(false)
|
||||||
}
|
}
|
|
@ -45,3 +45,9 @@ everything=true
|
||||||
; if this is set to false, you can login to any account with just the username
|
; if this is set to false, you can login to any account with just the username
|
||||||
; if this is true you must login using an exchange code given by the bot
|
; if this is true you must login using an exchange code given by the bot
|
||||||
password=true
|
password=true
|
||||||
|
|
||||||
|
; if you recieve lots of /account/api/oauth/token requests, set this to true
|
||||||
|
; this will disable the client credentials grant type
|
||||||
|
; however this will also disable a user to get the hotfixes before login
|
||||||
|
; so xmpp and other hotfix related things will be delayed by ~1 minute
|
||||||
|
disable_client_credentials=false
|
6
go.mod
6
go.mod
|
@ -3,10 +3,8 @@ module github.com/ectrc/snow
|
||||||
go 1.21.3
|
go 1.21.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beevik/etree v1.3.0
|
|
||||||
github.com/bwmarrin/discordgo v0.27.1
|
github.com/bwmarrin/discordgo v0.27.1
|
||||||
github.com/goccy/go-json v0.10.2
|
github.com/goccy/go-json v0.10.2
|
||||||
github.com/gofiber/contrib/websocket v1.3.0
|
|
||||||
github.com/gofiber/fiber/v2 v2.51.0
|
github.com/gofiber/fiber/v2 v2.51.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||||
github.com/google/uuid v1.4.0
|
github.com/google/uuid v1.4.0
|
||||||
|
@ -20,7 +18,6 @@ require (
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||||
github.com/fasthttp/websocket v1.5.7 // indirect
|
|
||||||
github.com/gorilla/websocket v1.4.2 // indirect
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
github.com/jackc/pgpassfile 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/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
@ -33,7 +30,7 @@ require (
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/philhofer/fwd v1.1.2 // indirect
|
github.com/philhofer/fwd v1.1.2 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
|
github.com/stretchr/testify v1.8.4 // indirect
|
||||||
github.com/tinylib/msgp v1.1.8 // indirect
|
github.com/tinylib/msgp v1.1.8 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
github.com/valyala/fasthttp v1.51.0 // indirect
|
||||||
|
@ -41,7 +38,6 @@ require (
|
||||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
golang.org/x/crypto v0.15.0 // indirect
|
golang.org/x/crypto v0.15.0 // indirect
|
||||||
golang.org/x/net v0.18.0 // indirect
|
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -1,18 +1,12 @@
|
||||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/beevik/etree v1.3.0 h1:hQTc+pylzIKDb23yYprodCWWTt+ojFfUZyzU09a/hmU=
|
|
||||||
github.com/beevik/etree v1.3.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
|
|
||||||
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
|
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
|
||||||
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fasthttp/websocket v1.5.7 h1:0a6o2OfeATvtGgoMKleURhLT6JqWPg7fYfWnH4KHau4=
|
|
||||||
github.com/fasthttp/websocket v1.5.7/go.mod h1:bC4fxSono9czeXHQUVKxsC0sNjbm7lPJR04GDFqClfU=
|
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/gofiber/contrib/websocket v1.3.0 h1:XADFAGorer1VJ1bqC4UkCjqS37kwRTV0415+050NrMk=
|
|
||||||
github.com/gofiber/contrib/websocket v1.3.0/go.mod h1:xguaOzn2ZZ759LavtosEP+rcxIgBEE/rdumPINhR+Xo=
|
|
||||||
github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ=
|
github.com/gofiber/fiber/v2 v2.51.0 h1:JNACcZy5e2tGApWB2QrRpenTWn0fq0hkFm6k0C86gKQ=
|
||||||
github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U=
|
github.com/gofiber/fiber/v2 v2.51.0/go.mod h1:xaQRZQJGqnKOQnbQw+ltvku3/h8QxvNi8o6JiJ7Ll0U=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||||
|
@ -53,8 +47,6 @@ github.com/r3labs/diff/v3 v3.0.1/go.mod h1:f1S9bourRbiM66NskseyUdo0fTmEE0qKrikYJ
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
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 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
|
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
@ -85,8 +77,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
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/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
|
||||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.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/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
|
@ -40,6 +40,10 @@ func PostFortniteToken(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostTokenClientCredentials(c *fiber.Ctx, body *FortniteTokenBody) error {
|
func PostTokenClientCredentials(c *fiber.Ctx, body *FortniteTokenBody) error {
|
||||||
|
if aid.Config.Fortnite.DisableClientCredentials {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(aid.ErrorBadRequest("Client Credentials is disabled."))
|
||||||
|
}
|
||||||
|
|
||||||
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
return c.Status(fiber.StatusOK).JSON(aid.JSON{
|
||||||
"access_token": "snow",
|
"access_token": "snow",
|
||||||
"token_type": "bearer",
|
"token_type": "bearer",
|
||||||
|
|
|
@ -1,138 +1,26 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ectrc/snow/aid"
|
"github.com/ectrc/snow/aid"
|
||||||
p "github.com/ectrc/snow/person"
|
|
||||||
"github.com/ectrc/snow/storage"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetFriendList(c *fiber.Ctx) error {
|
func GetFriendList(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
return c.Status(200).JSON([]aid.JSON{})
|
||||||
result := map[string]aid.JSON{}
|
|
||||||
|
|
||||||
for _, partial := range storage.Repo.GetFriendsForPerson(person.ID) {
|
|
||||||
friend := person.GetFriend(partial.ID)
|
|
||||||
if friend == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result[partial.ID] = friend.GenerateFriendResponse()
|
|
||||||
}
|
|
||||||
|
|
||||||
response := []aid.JSON{}
|
|
||||||
for _, friend := range result {
|
|
||||||
response = append(response, friend)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Status(200).JSON(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostCreateFriend(c *fiber.Ctx) error {
|
func PostCreateFriend(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
|
||||||
friendId := c.Params("wanted")
|
|
||||||
|
|
||||||
existing := person.GetFriend(friendId)
|
|
||||||
if existing != nil && (existing.Direction == "BOTH" || existing.Direction == "OUTGOING") {
|
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("already active friend request"))
|
|
||||||
}
|
|
||||||
|
|
||||||
person.AddFriend(friendId)
|
|
||||||
|
|
||||||
socket := FindSocketForPerson(person)
|
|
||||||
socket.PresenceWriteJSON(aid.JSON{
|
|
||||||
"payload": person.GetFriend(friendId).GenerateFriendResponse(),
|
|
||||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
|
||||||
"timestamp": time.Now().Format(time.RFC3339),
|
|
||||||
})
|
|
||||||
|
|
||||||
friendSocket := FindSocketForPerson(p.Find(friendId))
|
|
||||||
friendSocket.PresenceWriteJSON(aid.JSON{
|
|
||||||
"payload": friendSocket.Person.GetFriend(person.ID).GenerateFriendResponse(),
|
|
||||||
"type": "com.epicgames.friends.core.apiobjects.Friend",
|
|
||||||
"timestamp": time.Now().Format(time.RFC3339),
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.SendStatus(204)
|
return c.SendStatus(204)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteFriend(c *fiber.Ctx) error {
|
func DeleteFriend(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
|
||||||
wanted := c.Params("wanted")
|
|
||||||
|
|
||||||
existing := person.GetFriend(wanted)
|
|
||||||
if existing == nil {
|
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("not friends"))
|
|
||||||
}
|
|
||||||
|
|
||||||
person.RemoveFriend(wanted)
|
|
||||||
existing.Person.RemoveFriend(person.ID)
|
|
||||||
|
|
||||||
return c.SendStatus(204)
|
return c.SendStatus(204)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetFriendListSummary(c *fiber.Ctx) error {
|
func GetFriendListSummary(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
return c.Status(200).JSON([]aid.JSON{})
|
||||||
|
|
||||||
all := map[string]*p.Friend{}
|
|
||||||
for _, partial := range storage.Repo.GetFriendsForPerson(person.ID) {
|
|
||||||
friend := person.GetFriend(partial.ID)
|
|
||||||
if friend == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
all[partial.ID] = friend
|
|
||||||
}
|
|
||||||
|
|
||||||
result := aid.JSON{
|
|
||||||
"friends": []aid.JSON{},
|
|
||||||
"incoming": []aid.JSON{},
|
|
||||||
"outgoing": []aid.JSON{},
|
|
||||||
"settings": aid.JSON{
|
|
||||||
"acceptInvites": "public",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, friend := range all {
|
|
||||||
switch friend.Status {
|
|
||||||
case p.FriendStatusAccepted:
|
|
||||||
result["friends"] = append(result["friends"].([]aid.JSON), friend.GenerateSummaryResponse())
|
|
||||||
case p.FriendStatusPending:
|
|
||||||
switch friend.Direction {
|
|
||||||
case p.FriendDirectionIncoming:
|
|
||||||
result["incoming"] = append(result["incoming"].([]aid.JSON), friend.GenerateSummaryResponse())
|
|
||||||
case p.FriendDirectionOutgoing:
|
|
||||||
result["outgoing"] = append(result["outgoing"].([]aid.JSON), friend.GenerateSummaryResponse())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Status(200).JSON(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPersonSearch(c *fiber.Ctx) error {
|
func GetPersonSearch(c *fiber.Ctx) error {
|
||||||
query := c.Query("prefix")
|
|
||||||
|
|
||||||
matches := storage.Repo.GetPersonsByPartialDisplayFromDB(query)
|
|
||||||
if matches == nil {
|
|
||||||
return c.Status(200).JSON([]aid.JSON{})
|
return c.Status(200).JSON([]aid.JSON{})
|
||||||
}
|
|
||||||
|
|
||||||
result := []aid.JSON{}
|
|
||||||
for i, match := range matches {
|
|
||||||
result = append(result, aid.JSON{
|
|
||||||
"accountId": match.ID,
|
|
||||||
"epicMutuals": 0,
|
|
||||||
"sortPosition": i,
|
|
||||||
"matchType": "prefix",
|
|
||||||
"matches": []aid.JSON{{
|
|
||||||
"value": match.DisplayName,
|
|
||||||
"matchType": "prefix",
|
|
||||||
}},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Status(200).JSON(result)
|
|
||||||
}
|
}
|
|
@ -1,130 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/ectrc/snow/aid"
|
|
||||||
"github.com/ectrc/snow/person"
|
|
||||||
"github.com/gofiber/contrib/websocket"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SocketType string
|
|
||||||
const SocketTypeXmpp SocketType = "xmpp"
|
|
||||||
const SocketTypeUnknown SocketType = "unknown"
|
|
||||||
|
|
||||||
type Socket struct {
|
|
||||||
ID string
|
|
||||||
Connection *websocket.Conn
|
|
||||||
Person *person.Person
|
|
||||||
|
|
||||||
Type SocketType
|
|
||||||
PresenceState *PresenceState
|
|
||||||
}
|
|
||||||
|
|
||||||
type MessageToWrite struct {
|
|
||||||
Socket *Socket
|
|
||||||
Message []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Socket) Write(message []byte) {
|
|
||||||
socketWriteQueue <- MessageToWrite{
|
|
||||||
Socket: s,
|
|
||||||
Message: message,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
socketWriteQueue = make(chan MessageToWrite, 1000)
|
|
||||||
socketHandlers = map[SocketType]func(string) {
|
|
||||||
SocketTypeXmpp: presenceSocketHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
sockets = aid.GenericSyncMap[Socket]{}
|
|
||||||
)
|
|
||||||
|
|
||||||
func MiddlewareWebsocket(c *fiber.Ctx) error {
|
|
||||||
if !websocket.IsWebSocketUpgrade(c) {
|
|
||||||
return fiber.ErrUpgradeRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
var protocol SocketType
|
|
||||||
switch c.Get("Sec-WebSocket-Protocol") {
|
|
||||||
case "xmpp":
|
|
||||||
protocol = SocketTypeXmpp
|
|
||||||
default:
|
|
||||||
protocol = SocketTypeUnknown
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Locals("uuid", uuid.New().String())
|
|
||||||
c.Locals("protocol", protocol)
|
|
||||||
return c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func WebsocketConnection(c *websocket.Conn) {
|
|
||||||
protocol := c.Locals("protocol").(SocketType)
|
|
||||||
uuid := c.Locals("uuid").(string)
|
|
||||||
|
|
||||||
sockets.Add(uuid, &Socket{
|
|
||||||
ID: uuid,
|
|
||||||
Type: protocol,
|
|
||||||
Connection: c,
|
|
||||||
})
|
|
||||||
defer func() {
|
|
||||||
socket, ok := sockets.Get(uuid)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
socket.Connection.Close()
|
|
||||||
sockets.Delete(uuid)
|
|
||||||
aid.Print("(xmpp) connection closed", uuid)
|
|
||||||
}()
|
|
||||||
|
|
||||||
if handle, ok := socketHandlers[protocol]; ok {
|
|
||||||
handle(uuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAllSockets(c *fiber.Ctx) error {
|
|
||||||
result := []any{}
|
|
||||||
|
|
||||||
sockets.Range(func(key string, socket *Socket) bool {
|
|
||||||
result = append(result, *socket)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(200).JSON(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FindSocketForPerson(person *person.Person) *Socket {
|
|
||||||
var recieverSocket *Socket
|
|
||||||
sockets.Range(func(key string, value *Socket) bool {
|
|
||||||
if value.Person == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if value.Person.ID == person.ID {
|
|
||||||
recieverSocket = value
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return recieverSocket
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
if aid.Config != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
message := <-socketWriteQueue
|
|
||||||
aid.Print("(socket) writing message to", message.Socket.ID, string(message.Message))
|
|
||||||
message.Socket.Connection.WriteMessage(websocket.TextMessage, message.Message)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
355
handlers/xmpp.go
355
handlers/xmpp.go
|
@ -1,355 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/beevik/etree"
|
|
||||||
"github.com/ectrc/snow/aid"
|
|
||||||
p "github.com/ectrc/snow/person"
|
|
||||||
"github.com/ectrc/snow/storage"
|
|
||||||
"github.com/goccy/go-json"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PresenceStatus struct {
|
|
||||||
Status string `json:"Status"`
|
|
||||||
IsPlaying bool `json:"bIsPlaying"`
|
|
||||||
IsJoinable bool `json:"bIsJoinable"`
|
|
||||||
HasVoiceSupport bool `json:"bHasVoiceSupport"`
|
|
||||||
SessionId string `json:"SessionId"`
|
|
||||||
Properties map[string]struct {
|
|
||||||
SourceId string `json:"sourceId"`
|
|
||||||
SourceDisplayName string `json:"sourceDisplayName"`
|
|
||||||
SourcePlatform string `json:"sourcePlatform"`
|
|
||||||
PartyId string `json:"partyId"`
|
|
||||||
PartyTypeId int `json:"partyTypeId"`
|
|
||||||
Key string `json:"key"`
|
|
||||||
AppId string `json:"appId"`
|
|
||||||
BuildId string `json:"buildId"`
|
|
||||||
PartyFlags int `json:"partyFlags"`
|
|
||||||
NotAcceptingReason int `json:"notAcceptingReason"`
|
|
||||||
Pc int `json:"pc"`
|
|
||||||
} `json:"Properties"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PresenceState struct {
|
|
||||||
JID string
|
|
||||||
Open bool
|
|
||||||
RawStatus string
|
|
||||||
ParsedStatus PresenceStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
socketXmppMessageHandlers = map[string]func(*Socket, *etree.Document) error {
|
|
||||||
"open": presenceSocketOpenEvent,
|
|
||||||
"iq": presenceSocketIqRootEvent,
|
|
||||||
"message": presenceSocketMessageEvent,
|
|
||||||
"presence": presenceSocketPresenceEvent,
|
|
||||||
"close": presenceSocketCloseEvent,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func presenceSocketHandle(id string) {
|
|
||||||
socket, ok := sockets.Get(id)
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.Type = SocketTypeXmpp
|
|
||||||
socket.PresenceState = &PresenceState{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
_, message, err := socket.Connection.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed := etree.NewDocument()
|
|
||||||
if err := parsed.ReadFromBytes(message); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if handler, ok := socketXmppMessageHandlers[parsed.Root().Tag]; ok {
|
|
||||||
if err := handler(socket, parsed); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, partial := range storage.Repo.GetFriendsForPerson(socket.Person.ID) {
|
|
||||||
friend := socket.Person.GetFriend(partial.ID)
|
|
||||||
if friend == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
friendSocket := FindSocketForPerson(friend.Person)
|
|
||||||
if friendSocket == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
friendDocument := etree.NewDocument()
|
|
||||||
friendPresence := friendDocument.CreateElement("presence")
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "from", Value: socket.PresenceState.JID})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "to", Value: friendSocket.PresenceState.JID})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "type", Value: "available"})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
friendPresence.CreateElement("status").SetText(aid.JSONStringify(aid.JSON{}))
|
|
||||||
friendPresence.CreateElement("show").SetText("away")
|
|
||||||
|
|
||||||
friendSocket.PresenceWrite(friendDocument)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, party := range socket.PresenceState.ParsedStatus.Properties {
|
|
||||||
if party.PartyId == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sockets.Range(func(_ string, recieverSocket *Socket) bool {
|
|
||||||
if recieverSocket.Type != SocketTypeXmpp || recieverSocket.Person == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
message := document.CreateElement("message")
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "id", Value: uuid.New().String()})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "from", Value: socket.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "to", Value: recieverSocket.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
message.CreateElement("body").SetText(aid.JSONStringify(aid.JSON{
|
|
||||||
"type": "com.epicgames.party.memberexited",
|
|
||||||
"timestamp": time.Now().Format(time.RFC3339),
|
|
||||||
"payload": aid.JSON{
|
|
||||||
"memberId": socket.Person.ID,
|
|
||||||
"partyId": party.PartyId,
|
|
||||||
"wasKicked": false,
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
|
|
||||||
recieverSocket.PresenceWrite(document)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketOpenEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
document := etree.NewDocument()
|
|
||||||
open := document.CreateElement("open")
|
|
||||||
open.Attr = append(open.Attr, etree.Attr{Key: "xmlns", Value: "urn:ietf:params:xml:ns:xmpp-framing"})
|
|
||||||
open.Attr = append(open.Attr, etree.Attr{Key: "from", Value: "prod.ol.epicgames.com"})
|
|
||||||
open.Attr = append(open.Attr, etree.Attr{Key: "version", Value: "1.0"})
|
|
||||||
open.Attr = append(open.Attr, etree.Attr{Key: "id", Value: socket.ID})
|
|
||||||
|
|
||||||
socket.PresenceWrite(document)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketCloseEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
return fmt.Errorf("safe exit")
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketIqRootEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
redirect := map[string]func(*Socket, *etree.Document) error{
|
|
||||||
"set": presenceSocketIqSetEvent,
|
|
||||||
"get": presenceSocketIqGetEvent,
|
|
||||||
}
|
|
||||||
|
|
||||||
if handler, ok := redirect[tree.Root().SelectAttr("type").Value]; ok {
|
|
||||||
if err := handler(socket, tree); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketIqSetEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
token := tree.Root().SelectElement("query").SelectElement("password")
|
|
||||||
if token == nil || token.Text() == "" {
|
|
||||||
return fmt.Errorf("invalid token")
|
|
||||||
}
|
|
||||||
real := strings.ReplaceAll(token.Text(), "eg1~", "")
|
|
||||||
|
|
||||||
claims, err := aid.JWTVerify(real)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid token")
|
|
||||||
}
|
|
||||||
|
|
||||||
if claims["snow_id"] == nil {
|
|
||||||
return fmt.Errorf("invalid token")
|
|
||||||
}
|
|
||||||
|
|
||||||
snowId, ok := claims["snow_id"].(string)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("invalid token")
|
|
||||||
}
|
|
||||||
|
|
||||||
person := p.Find(snowId)
|
|
||||||
if person == nil {
|
|
||||||
return fmt.Errorf("invalid token")
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.Person = person
|
|
||||||
socket.PresenceState.JID = person.ID + "@prod.ol.epicgames.com/" + tree.Root().SelectElement("query").SelectElement("resource").Text()
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
iq := document.CreateElement("iq")
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "type", Value: "result"})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "id", Value: "_xmpp_auth1"})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "from", Value: "prod.ol.epicgames.com"})
|
|
||||||
|
|
||||||
socket.PresenceWrite(document)
|
|
||||||
socket.PresenceWriteStatus()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketIqGetEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
document := etree.NewDocument()
|
|
||||||
iq := document.CreateElement("iq")
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "type", Value: "result"})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "id", Value: tree.Root().SelectAttr("id").Value})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "to", Value: tree.Root().SelectAttr("from").Value})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "from", Value: "prod.ol.epicgames.com"})
|
|
||||||
ping := iq.CreateElement("ping")
|
|
||||||
ping.Attr = append(ping.Attr, etree.Attr{Key: "xmlns", Value: "urn:xmpp:ping"})
|
|
||||||
|
|
||||||
socket.PresenceWrite(document)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketMessageEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
reciever := p.Find(strings.Split(tree.Root().SelectAttr("to").Value, "@")[0])
|
|
||||||
if reciever == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
recieverSocket := FindSocketForPerson(reciever)
|
|
||||||
if recieverSocket == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
message := document.CreateElement("message")
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "id", Value: tree.Root().SelectAttr("id").Value})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "from", Value: socket.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "to", Value: recieverSocket.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
message.CreateElement("body").SetText(tree.Root().SelectElement("body").Text())
|
|
||||||
|
|
||||||
recieverSocket.PresenceWrite(document)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func presenceSocketPresenceEvent(socket *Socket, tree *etree.Document) error {
|
|
||||||
status := tree.Root().SelectElement("status")
|
|
||||||
if status == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.PresenceState.RawStatus = status.Text()
|
|
||||||
json.NewDecoder(strings.NewReader(status.Text())).Decode(&socket.PresenceState.ParsedStatus)
|
|
||||||
socket.PresenceWriteStatus()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Socket) PresenceWrite(message *etree.Document) {
|
|
||||||
bytes, err := message.WriteToBytes()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Write(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Socket) PresenceWriteStatus() {
|
|
||||||
for _, partial := range storage.Repo.GetFriendsForPerson(s.Person.ID) {
|
|
||||||
friend := s.Person.GetFriend(partial.ID)
|
|
||||||
if friend == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
friendSocket := FindSocketForPerson(friend.Person)
|
|
||||||
if friendSocket == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
friendDocument := etree.NewDocument()
|
|
||||||
friendPresence := friendDocument.CreateElement("presence")
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "from", Value: s.PresenceState.JID})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "to", Value: friendSocket.PresenceState.JID})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "type", Value: "available"})
|
|
||||||
friendPresence.Attr = append(friendPresence.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
friendPresence.CreateElement("status").SetText(s.PresenceState.RawStatus)
|
|
||||||
friendSocket.PresenceWrite(friendDocument)
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
presence := document.CreateElement("presence")
|
|
||||||
presence.Attr = append(presence.Attr, etree.Attr{Key: "from", Value: friendSocket.PresenceState.JID})
|
|
||||||
presence.Attr = append(presence.Attr, etree.Attr{Key: "to", Value: s.PresenceState.JID})
|
|
||||||
presence.Attr = append(presence.Attr, etree.Attr{Key: "type", Value: "available"})
|
|
||||||
presence.Attr = append(presence.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
presence.CreateElement("status").SetText(friendSocket.PresenceState.RawStatus)
|
|
||||||
s.PresenceWrite(document)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Socket) PresenceWriteJSON(body aid.JSON) {
|
|
||||||
aid.PrintJSON(body)
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
message := document.CreateElement("message")
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "id", Value: uuid.New().String()})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "from", Value: "xmpp-admin@prod.ol.epicgames.com"})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "to", Value: s.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
message.CreateElement("body").SetText(aid.JSONStringify(body))
|
|
||||||
s.PresenceWrite(document)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Socket) PresenceWriteGiftReceived() {
|
|
||||||
document := etree.NewDocument()
|
|
||||||
message := document.CreateElement("message")
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "id", Value: uuid.New().String()})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "from", Value: "prod.ol.epicgames.com"})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "to", Value: s.PresenceState.JID})
|
|
||||||
message.Attr = append(message.Attr, etree.Attr{Key: "xmlns", Value: "jabber:client"})
|
|
||||||
message.CreateElement("body").SetText(aid.JSONStringify(aid.JSON{
|
|
||||||
"type": "com.epicgames.gift.received",
|
|
||||||
"timestamp": time.Now().Format(time.RFC3339),
|
|
||||||
"payload": aid.JSON{},
|
|
||||||
}))
|
|
||||||
s.PresenceWrite(document)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
if aid.Config != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timer := time.NewTicker(30 * time.Second)
|
|
||||||
for {
|
|
||||||
<-timer.C
|
|
||||||
sockets.Range(func(key string, socket *Socket) bool {
|
|
||||||
if socket.Type != SocketTypeXmpp || socket.Person == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
document := etree.NewDocument()
|
|
||||||
iq := document.CreateElement("iq")
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "id", Value: "_xmpp_auth1"})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "type", Value: "get"})
|
|
||||||
iq.Attr = append(iq.Attr, etree.Attr{Key: "from", Value: "prod.ol.epicgames.com"})
|
|
||||||
ping := iq.CreateElement("ping")
|
|
||||||
ping.Attr = append(iq.Attr, etree.Attr{Key: "xmlns", Value: "urn:xmpp:ping"})
|
|
||||||
|
|
||||||
socket.PresenceWrite(document)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
4
main.go
4
main.go
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/ectrc/snow/storage"
|
"github.com/ectrc/snow/storage"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
"github.com/gofiber/contrib/websocket"
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ func main() {
|
||||||
r.Post("/api/v1/assets/Fortnite/:versionId/:assetName", handlers.PostAssets)
|
r.Post("/api/v1/assets/Fortnite/:versionId/:assetName", handlers.PostAssets)
|
||||||
|
|
||||||
r.Get("//", func(c *fiber.Ctx) error { return c.Redirect("/socket") })
|
r.Get("//", func(c *fiber.Ctx) error { return c.Redirect("/socket") })
|
||||||
r.Get("/socket", handlers.MiddlewareWebsocket, websocket.New(handlers.WebsocketConnection))
|
// r.Get("/socket", handlers.MiddlewareWebsocket, websocket.New(handlers.WebsocketConnection))
|
||||||
|
|
||||||
account := r.Group("/account/api")
|
account := r.Group("/account/api")
|
||||||
account.Get("/public/account", handlers.GetPublicAccounts)
|
account.Get("/public/account", handlers.GetPublicAccounts)
|
||||||
|
@ -131,7 +130,6 @@ func main() {
|
||||||
snow := r.Group("/snow")
|
snow := r.Group("/snow")
|
||||||
snow.Get("/cosmetics", handlers.GetPreloadedCosmetics)
|
snow.Get("/cosmetics", handlers.GetPreloadedCosmetics)
|
||||||
snow.Get("/image/:playlist", handlers.GetPlaylistImage)
|
snow.Get("/image/:playlist", handlers.GetPlaylistImage)
|
||||||
snow.Get("/sockets", handlers.GetAllSockets)
|
|
||||||
|
|
||||||
discord := snow.Group("/discord")
|
discord := snow.Group("/discord")
|
||||||
discord.Get("/", handlers.GetDiscordOAuthURL)
|
discord.Get("/", handlers.GetDiscordOAuthURL)
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package person
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ectrc/snow/aid"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FriendDirection string
|
|
||||||
var FriendDirectionBoth FriendDirection = "BOTH"
|
|
||||||
var FriendDirectionIncoming FriendDirection = "INCOMING"
|
|
||||||
var FriendDirectionOutgoing FriendDirection = "OUTGOING"
|
|
||||||
|
|
||||||
type FriendStatus string
|
|
||||||
var FriendStatusPending FriendStatus = "PENDING"
|
|
||||||
var FriendStatusAccepted FriendStatus = "ACCEPTED"
|
|
||||||
var FriendStatusDeleted FriendStatus = "DELETED"
|
|
||||||
|
|
||||||
type Friend struct {
|
|
||||||
Person *Person
|
|
||||||
Status FriendStatus
|
|
||||||
Direction FriendDirection
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Friend) GenerateSummaryResponse() aid.JSON {
|
|
||||||
return aid.JSON{
|
|
||||||
"accountId": f.Person.ID,
|
|
||||||
"groups": []string{},
|
|
||||||
"mutual": 0,
|
|
||||||
"alias": "",
|
|
||||||
"note": "",
|
|
||||||
"favorite": false,
|
|
||||||
"created": time.Now().Add(-time.Hour * 24 * 7).Format(time.RFC3339),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Friend) GenerateFriendResponse() aid.JSON {
|
|
||||||
return aid.JSON{
|
|
||||||
"accountId": f.Person.ID,
|
|
||||||
"status": f.Status,
|
|
||||||
"direction": f.Direction,
|
|
||||||
"created": time.Now().Add(-time.Hour * 24 * 7).Format(time.RFC3339),
|
|
||||||
"favourite": false,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,7 +10,6 @@ type Person struct {
|
||||||
DisplayName string
|
DisplayName string
|
||||||
Permissions []string
|
Permissions []string
|
||||||
IsBanned bool
|
IsBanned bool
|
||||||
Friends []string
|
|
||||||
AthenaProfile *Profile
|
AthenaProfile *Profile
|
||||||
CommonCoreProfile *Profile
|
CommonCoreProfile *Profile
|
||||||
CommonPublicProfile *Profile
|
CommonPublicProfile *Profile
|
||||||
|
@ -26,7 +25,6 @@ func NewPerson() *Person {
|
||||||
DisplayName: uuid.New().String(),
|
DisplayName: uuid.New().String(),
|
||||||
Permissions: []string{},
|
Permissions: []string{},
|
||||||
IsBanned: false,
|
IsBanned: false,
|
||||||
Friends: []string{},
|
|
||||||
AthenaProfile: NewProfile("athena"),
|
AthenaProfile: NewProfile("athena"),
|
||||||
CommonCoreProfile: NewProfile("common_core"),
|
CommonCoreProfile: NewProfile("common_core"),
|
||||||
CommonPublicProfile: NewProfile("common_public"),
|
CommonPublicProfile: NewProfile("common_public"),
|
||||||
|
@ -42,7 +40,6 @@ func NewPersonWithCustomID(id string) *Person {
|
||||||
DisplayName: uuid.New().String(),
|
DisplayName: uuid.New().String(),
|
||||||
Permissions: []string{},
|
Permissions: []string{},
|
||||||
IsBanned: false,
|
IsBanned: false,
|
||||||
Friends: []string{},
|
|
||||||
AthenaProfile: NewProfile("athena"),
|
AthenaProfile: NewProfile("athena"),
|
||||||
CommonCoreProfile: NewProfile("common_core"),
|
CommonCoreProfile: NewProfile("common_core"),
|
||||||
CommonPublicProfile: NewProfile("common_public"),
|
CommonPublicProfile: NewProfile("common_public"),
|
||||||
|
@ -151,7 +148,6 @@ func findHelper(databasePerson *storage.DB_Person) *Person {
|
||||||
DisplayName: databasePerson.DisplayName,
|
DisplayName: databasePerson.DisplayName,
|
||||||
Permissions: databasePerson.Permissions,
|
Permissions: databasePerson.Permissions,
|
||||||
IsBanned: databasePerson.IsBanned,
|
IsBanned: databasePerson.IsBanned,
|
||||||
Friends: databasePerson.Friends,
|
|
||||||
AthenaProfile: athenaProfile,
|
AthenaProfile: athenaProfile,
|
||||||
CommonCoreProfile: commonCoreProfile,
|
CommonCoreProfile: commonCoreProfile,
|
||||||
CommonPublicProfile: commonPublicProfile,
|
CommonPublicProfile: commonPublicProfile,
|
||||||
|
@ -251,71 +247,12 @@ func (p *Person) HasPermission(permission Permission) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Person) AddFriend(friendId string) {
|
|
||||||
p.Friends = append(p.Friends, friendId)
|
|
||||||
p.Save()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Person) RemoveFriend(friendId string) {
|
|
||||||
for i, friend := range p.Friends {
|
|
||||||
if friend == friendId {
|
|
||||||
p.Friends = append(p.Friends[:i], p.Friends[i+1:]...)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.Save()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Person) GetFriend(friendId string) *Friend {
|
|
||||||
friend := Find(friendId)
|
|
||||||
if friend == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.IsFriendInFriendList(friendId) {
|
|
||||||
if friend.IsFriendInFriendList(p.ID) {
|
|
||||||
return &Friend{
|
|
||||||
Person: friend,
|
|
||||||
Status: FriendStatusAccepted,
|
|
||||||
Direction: FriendDirectionBoth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Friend{
|
|
||||||
Person: friend,
|
|
||||||
Status: FriendStatusPending,
|
|
||||||
Direction: FriendDirectionOutgoing,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if friend.IsFriendInFriendList(p.ID) {
|
|
||||||
return &Friend{
|
|
||||||
Person: friend,
|
|
||||||
Status: FriendStatusPending,
|
|
||||||
Direction: FriendDirectionIncoming,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Person) IsFriendInFriendList(friendId string) bool {
|
|
||||||
for _, idA := range p.Friends {
|
|
||||||
if idA == friendId {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Person) ToDatabase() *storage.DB_Person {
|
func (p *Person) ToDatabase() *storage.DB_Person {
|
||||||
dbPerson := storage.DB_Person{
|
dbPerson := storage.DB_Person{
|
||||||
ID: p.ID,
|
ID: p.ID,
|
||||||
DisplayName: p.DisplayName,
|
DisplayName: p.DisplayName,
|
||||||
Permissions: p.Permissions,
|
Permissions: p.Permissions,
|
||||||
IsBanned: p.IsBanned,
|
IsBanned: p.IsBanned,
|
||||||
Friends: p.Friends,
|
|
||||||
Profiles: []storage.DB_Profile{},
|
Profiles: []storage.DB_Profile{},
|
||||||
Stats: []storage.DB_SeasonStat{},
|
Stats: []storage.DB_SeasonStat{},
|
||||||
Discord: storage.DB_DiscordPerson{},
|
Discord: storage.DB_DiscordPerson{},
|
||||||
|
|
|
@ -57,7 +57,7 @@ func (s *PostgresStorage) GetPerson(personId string) *DB_Person {
|
||||||
Model(&DB_Person{}).
|
Model(&DB_Person{}).
|
||||||
Preload("Profiles").
|
Preload("Profiles").
|
||||||
Preload("Profiles.Loadouts").
|
Preload("Profiles.Loadouts").
|
||||||
Preload("Profiles.Items.Variants").
|
// Preload("Profiles.Items.Variants").
|
||||||
Preload("Profiles.Gifts.Loot").
|
Preload("Profiles.Gifts.Loot").
|
||||||
Preload("Profiles.Attributes").
|
Preload("Profiles.Attributes").
|
||||||
Preload("Profiles.Items").
|
Preload("Profiles.Items").
|
||||||
|
@ -80,7 +80,7 @@ func (s *PostgresStorage) GetPersonByDisplay(displayName string) *DB_Person {
|
||||||
Model(&DB_Person{}).
|
Model(&DB_Person{}).
|
||||||
Preload("Profiles").
|
Preload("Profiles").
|
||||||
Preload("Profiles.Loadouts").
|
Preload("Profiles.Loadouts").
|
||||||
Preload("Profiles.Items.Variants").
|
// Preload("Profiles.Items.Variants").
|
||||||
Preload("Profiles.Gifts.Loot").
|
Preload("Profiles.Gifts.Loot").
|
||||||
Preload("Profiles.Attributes").
|
Preload("Profiles.Attributes").
|
||||||
Preload("Profiles.Items").
|
Preload("Profiles.Items").
|
||||||
|
@ -103,7 +103,7 @@ func (s *PostgresStorage) GetPersonsByPartialDisplay(displayName string) []*DB_P
|
||||||
Model(&DB_Person{}).
|
Model(&DB_Person{}).
|
||||||
Preload("Profiles").
|
Preload("Profiles").
|
||||||
Preload("Profiles.Loadouts").
|
Preload("Profiles.Loadouts").
|
||||||
Preload("Profiles.Items.Variants").
|
// Preload("Profiles.Items.Variants").
|
||||||
Preload("Profiles.Gifts.Loot").
|
Preload("Profiles.Gifts.Loot").
|
||||||
Preload("Profiles.Attributes").
|
Preload("Profiles.Attributes").
|
||||||
Preload("Profiles.Items").
|
Preload("Profiles.Items").
|
||||||
|
@ -138,7 +138,7 @@ func (s *PostgresStorage) GetAllPersons() []*DB_Person {
|
||||||
Model(&DB_Person{}).
|
Model(&DB_Person{}).
|
||||||
Preload("Profiles").
|
Preload("Profiles").
|
||||||
Preload("Profiles.Loadouts").
|
Preload("Profiles.Loadouts").
|
||||||
Preload("Profiles.Items.Variants").
|
// Preload("Profiles.Items.Variants").
|
||||||
Preload("Profiles.Gifts.Loot").
|
Preload("Profiles.Gifts.Loot").
|
||||||
Preload("Profiles.Attributes").
|
Preload("Profiles.Attributes").
|
||||||
Preload("Profiles.Items").
|
Preload("Profiles.Items").
|
||||||
|
@ -156,42 +156,6 @@ func (s *PostgresStorage) GetPersonsCount() int {
|
||||||
return int(count)
|
return int(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PostgresStorage) GetFriendsForPerson(personId string) []*DB_Person {
|
|
||||||
person := s.GetPerson(personId)
|
|
||||||
|
|
||||||
var mine []*DB_Person
|
|
||||||
s.Postgres.
|
|
||||||
Model(&DB_Person{}).
|
|
||||||
Preload("Profiles").
|
|
||||||
Preload("Profiles.Loadouts").
|
|
||||||
Preload("Profiles.Items.Variants").
|
|
||||||
Preload("Profiles.Gifts.Loot").
|
|
||||||
Preload("Profiles.Attributes").
|
|
||||||
Preload("Profiles.Items").
|
|
||||||
Preload("Profiles.Gifts").
|
|
||||||
Preload("Profiles.Quests").
|
|
||||||
Preload("Discord").
|
|
||||||
Where("id IN (?)", person.Friends).
|
|
||||||
Find(&mine)
|
|
||||||
|
|
||||||
var theirs []*DB_Person
|
|
||||||
s.Postgres.
|
|
||||||
Model(&DB_Person{}).
|
|
||||||
Preload("Profiles").
|
|
||||||
Preload("Profiles.Loadouts").
|
|
||||||
Preload("Profiles.Items.Variants").
|
|
||||||
Preload("Profiles.Gifts.Loot").
|
|
||||||
Preload("Profiles.Attributes").
|
|
||||||
Preload("Profiles.Items").
|
|
||||||
Preload("Profiles.Gifts").
|
|
||||||
Preload("Profiles.Quests").
|
|
||||||
Preload("Discord").
|
|
||||||
Where("? = ?", person.ID, gorm.Expr("ANY(friends)")).
|
|
||||||
Find(&theirs)
|
|
||||||
|
|
||||||
return append(mine, theirs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PostgresStorage) TotalVBucks() int {
|
func (s *PostgresStorage) TotalVBucks() int {
|
||||||
var total int64
|
var total int64
|
||||||
s.Postgres.Model(&DB_Item{}).Select("sum(quantity)").Where("template_id = ?", "Currency:MtxPurchased").Find(&total)
|
s.Postgres.Model(&DB_Item{}).Select("sum(quantity)").Where("template_id = ?", "Currency:MtxPurchased").Find(&total)
|
||||||
|
@ -207,7 +171,7 @@ func (s *PostgresStorage) DeletePerson(personId string) {
|
||||||
Model(&DB_Person{}).
|
Model(&DB_Person{}).
|
||||||
Preload("Profiles").
|
Preload("Profiles").
|
||||||
Preload("Profiles.Loadouts").
|
Preload("Profiles.Loadouts").
|
||||||
Preload("Profiles.Items.Variants").
|
// Preload("Profiles.Items.Variants").
|
||||||
Preload("Profiles.Gifts.Loot").
|
Preload("Profiles.Gifts.Loot").
|
||||||
Preload("Profiles.Attributes").
|
Preload("Profiles.Attributes").
|
||||||
Preload("Profiles.Items").
|
Preload("Profiles.Items").
|
||||||
|
|
|
@ -19,8 +19,6 @@ type Storage interface {
|
||||||
SavePerson(person *DB_Person)
|
SavePerson(person *DB_Person)
|
||||||
DeletePerson(personId string)
|
DeletePerson(personId string)
|
||||||
|
|
||||||
GetFriendsForPerson(personId string) []*DB_Person
|
|
||||||
|
|
||||||
SaveProfile(profile *DB_Profile)
|
SaveProfile(profile *DB_Profile)
|
||||||
DeleteProfile(profileId string)
|
DeleteProfile(profileId string)
|
||||||
|
|
||||||
|
@ -108,10 +106,6 @@ func (r *Repository) GetPersonsCount() int {
|
||||||
return r.Storage.GetPersonsCount()
|
return r.Storage.GetPersonsCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Repository) GetFriendsForPerson(personId string) []*DB_Person {
|
|
||||||
return r.Storage.GetFriendsForPerson(personId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Repository) SavePerson(person *DB_Person) {
|
func (r *Repository) SavePerson(person *DB_Person) {
|
||||||
r.Storage.SavePerson(person)
|
r.Storage.SavePerson(person)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ type DB_Person struct {
|
||||||
IsBanned bool
|
IsBanned bool
|
||||||
Profiles []DB_Profile `gorm:"foreignkey:PersonID"`
|
Profiles []DB_Profile `gorm:"foreignkey:PersonID"`
|
||||||
Stats []DB_SeasonStat `gorm:"foreignkey:PersonID"`
|
Stats []DB_SeasonStat `gorm:"foreignkey:PersonID"`
|
||||||
Friends pq.StringArray `gorm:"type:text[]"`
|
|
||||||
Discord DB_DiscordPerson `gorm:"foreignkey:PersonID"`
|
Discord DB_DiscordPerson `gorm:"foreignkey:PersonID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user