add friends

This commit is contained in:
Eccentric 2024-01-03 23:25:17 +00:00
parent 5130009644
commit 8ce5c0cb2d
7 changed files with 327 additions and 9 deletions

124
handlers/friends.go Normal file
View File

@ -0,0 +1,124 @@
package handlers
import (
"github.com/ectrc/snow/aid"
p "github.com/ectrc/snow/person"
"github.com/ectrc/snow/storage"
"github.com/gofiber/fiber/v2"
)
func GetFriendList(c *fiber.Ctx) error {
person := c.Locals("person").(*p.Person)
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 {
person := c.Locals("person").(*p.Person)
wanted := c.Params("wanted")
existing := person.GetFriend(wanted)
if existing != nil && (existing.Direction == "BOTH" || existing.Direction == "OUTGOING") {
return c.Status(400).JSON(aid.ErrorBadRequest("already active friend request"))
}
person.AddFriend(wanted)
// send xmpp message to disply a popup
return c.SendStatus(204)
}
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"))
}
existing.Person.RemoveFriend(wanted)
person.RemoveFriend(wanted)
// send xmpp message to disply a popup
return c.SendStatus(204)
}
func GetFriendListSummary(c *fiber.Ctx) error {
person := c.Locals("person").(*p.Person)
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 "ACCEPTED":
result["friends"] = append(result["friends"].([]aid.JSON), friend.GenerateSummaryResponse())
case "PENDING":
switch friend.Direction {
case "INCOMING":
result["incoming"] = append(result["incoming"].([]aid.JSON), friend.GenerateSummaryResponse())
case "OUTGOING":
result["outgoing"] = append(result["outgoing"].([]aid.JSON), friend.GenerateSummaryResponse())
}
}
}
return c.Status(200).JSON(result)
}
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{})
}
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)
}

12
main.go
View File

@ -45,7 +45,8 @@ func init() {
fortnite.GeneratePlaylistImages()
if found := person.FindByDisplay("god"); found == nil {
fortnite.NewFortnitePerson("god", true)
god := fortnite.NewFortnitePerson("god", true)
god.AddPermission("all")
}
}
func main() {
@ -63,6 +64,7 @@ func main() {
r.Get("/waitingroom/api/waitingroom", handlers.GetWaitingRoomStatus)
r.Get("/region", handlers.GetRegion)
r.Put("/profile/play_region", handlers.AnyNoContent)
r.Get("/api/v1/search/:accountId", handlers.GetPersonSearch)
r.Post("/api/v1/assets/Fortnite/:versionId/:assetName", handlers.PostAssets)
account := r.Group("/account/api")
@ -98,6 +100,14 @@ func main() {
user.Get("/:accountId/:fileName", handlers.GetUserStorageFile)
user.Put("/:accountId/:fileName", handlers.PutUserStorageFile)
friends := r.Group("/friends/api")
friends.Use(handlers.MiddlewareFortnite)
friends.Get("/public/friends/:accountId", handlers.GetFriendList)
friends.Post("/public/friends/:accountId/:wanted", handlers.PostCreateFriend)
friends.Delete("/public/friends/:accountId/:wanted", handlers.DeleteFriend)
friends.Get("/:version/:accountId/summary", handlers.GetFriendListSummary)
friends.Get("/:version/:accountId/friends/:wanted", handlers.PostCreateFriend)
game := fortnite.Group("/game/v2")
game.Get("/enabled_features", handlers.GetGameEnabledFeatures)
game.Post("/tryPlayOnPlatform/account/:accountId", handlers.PostGamePlatform)

35
person/friend.go Normal file
View File

@ -0,0 +1,35 @@
package person
import (
"time"
"github.com/ectrc/snow/aid"
)
type Friend struct {
Person *Person
Status string
Direction string
}
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,
}
}

View File

@ -10,6 +10,7 @@ type Person struct {
DisplayName string
Permissions []string
IsBanned bool
Friends []string
AthenaProfile *Profile
CommonCoreProfile *Profile
CommonPublicProfile *Profile
@ -19,17 +20,29 @@ type Person struct {
Discord *storage.DB_DiscordPerson
}
type Option struct {
Key string
Value string
}
func NewPerson() *Person {
return &Person{
ID: uuid.New().String(),
DisplayName: uuid.New().String(),
Permissions: []string{},
IsBanned: false,
Friends: []string{},
AthenaProfile: NewProfile("athena"),
CommonCoreProfile: NewProfile("common_core"),
CommonPublicProfile: NewProfile("common_public"),
Profile0Profile: NewProfile("profile0"),
CollectionsProfile: NewProfile("collections"),
CreativeProfile: NewProfile("creative"),
}
}
func NewPersonWithCustomID(id string) *Person {
return &Person{
ID: id,
DisplayName: uuid.New().String(),
Permissions: []string{},
IsBanned: false,
Friends: []string{},
AthenaProfile: NewProfile("athena"),
CommonCoreProfile: NewProfile("common_core"),
CommonPublicProfile: NewProfile("common_public"),
@ -138,6 +151,7 @@ func findHelper(databasePerson *storage.DB_Person) *Person {
DisplayName: databasePerson.DisplayName,
Permissions: databasePerson.Permissions,
IsBanned: databasePerson.IsBanned,
Friends: databasePerson.Friends,
AthenaProfile: athenaProfile,
CommonCoreProfile: commonCoreProfile,
CommonPublicProfile: commonPublicProfile,
@ -237,12 +251,71 @@ func (p *Person) HasPermission(permission Permission) bool {
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: "ACCEPTED",
Direction: "BOTH",
}
}
return &Friend{
Person: friend,
Status: "PENDING",
Direction: "OUTBOUND",
}
}
if friend.IsFriendInFriendList(p.ID) {
return &Friend{
Person: friend,
Status: "PENDING",
Direction: "INBOUND",
}
}
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 {
dbPerson := storage.DB_Person{
ID: p.ID,
DisplayName: p.DisplayName,
Permissions: p.Permissions,
IsBanned: p.IsBanned,
Friends: p.Friends,
Profiles: []storage.DB_Profile{},
Stats: []storage.DB_SeasonStat{},
Discord: storage.DB_DiscordPerson{},

View File

@ -97,6 +97,29 @@ func (s *PostgresStorage) GetPersonByDisplay(displayName string) *DB_Person {
return &dbPerson
}
func (s *PostgresStorage) GetPersonsByPartialDisplay(displayName string) []*DB_Person {
var dbPersons []*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("display_name LIKE ?", "%" + displayName + "%").
Find(&dbPersons)
if len(dbPersons) == 0 {
return nil
}
return dbPersons
}
func (s *PostgresStorage) GetPersonByDiscordID(discordId string) *DB_Person {
var discordEntry DB_DiscordPerson
s.Postgres.Model(&DB_DiscordPerson{}).Where("id = ?", discordId).Find(&discordEntry)
@ -133,6 +156,42 @@ func (s *PostgresStorage) GetPersonsCount() int {
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 {
var total int64
s.Postgres.Model(&DB_Item{}).Select("sum(quantity)").Where("template_id = ?", "Currency:MtxPurchased").Find(&total)

View File

@ -10,13 +10,16 @@ type Storage interface {
GetAllPersons() []*DB_Person
GetPersonsCount() int
TotalVBucks() int
GetPerson(personId string) *DB_Person
GetPersonByDisplay(displayName string) *DB_Person
GetPersonsByPartialDisplay(displayName string) []*DB_Person
GetPersonByDiscordID(discordId string) *DB_Person
SavePerson(person *DB_Person)
DeletePerson(personId string)
TotalVBucks() int
GetFriendsForPerson(personId string) []*DB_Person
SaveProfile(profile *DB_Profile)
DeleteProfile(profileId string)
@ -75,6 +78,15 @@ func (r *Repository) GetPersonByDisplayFromDB(displayName string) *DB_Person {
return nil
}
func (r *Repository) GetPersonsByPartialDisplayFromDB(displayName string) []*DB_Person {
storagePerson := r.Storage.GetPersonsByPartialDisplay(displayName)
if storagePerson != nil {
return storagePerson
}
return nil
}
func (r *Repository) GetPersonByDiscordIDFromDB(discordId string) *DB_Person {
storagePerson := r.Storage.GetPersonByDiscordID(discordId)
if storagePerson != nil {
@ -84,6 +96,10 @@ func (r *Repository) GetPersonByDiscordIDFromDB(discordId string) *DB_Person {
return nil
}
func (r *Repository) TotalVBucks() int {
return r.Storage.TotalVBucks()
}
func (r *Repository) GetAllPersons() []*DB_Person {
return r.Storage.GetAllPersons()
}
@ -92,8 +108,8 @@ func (r *Repository) GetPersonsCount() int {
return r.Storage.GetPersonsCount()
}
func (r *Repository) TotalVBucks() int {
return r.Storage.TotalVBucks()
func (r *Repository) GetFriendsForPerson(personId string) []*DB_Person {
return r.Storage.GetFriendsForPerson(personId)
}
func (r *Repository) SavePerson(person *DB_Person) {

View File

@ -13,6 +13,7 @@ type DB_Person struct {
IsBanned bool
Profiles []DB_Profile `gorm:"foreignkey:PersonID"`
Stats []DB_SeasonStat `gorm:"foreignkey:PersonID"`
Friends pq.StringArray `gorm:"type:text[]"`
Discord DB_DiscordPerson `gorm:"foreignkey:PersonID"`
}