Request to join now works

This commit is contained in:
Eccentric 2024-02-17 14:40:17 +00:00
parent 8d59f63c88
commit 11a135ea3f
6 changed files with 256 additions and 14 deletions

View File

@ -240,9 +240,12 @@ func PostPartyInvite(c *fiber.Ctx) error {
invite := p.NewPartyInvite(party, person, towards, body)
party.AddInvite(invite)
towards.Invites.Set(party.ID, invite)
socket.EmitPartyInvite(invite)
if c.QueryBool("sendPing", false) {
socket.EmitPartyPingFromInvite(invite)
}
return c.SendStatus(204)
}
@ -257,6 +260,16 @@ func PostPartyJoin(c *fiber.Ctx) error {
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
}
if party.Config["joinability"] != "OPEN" {
invite := party.GetInvite(person)
if invite == nil {
return c.Status(400).JSON(aid.ErrorBadRequest("No Invite Found"))
}
party.RemoveInvite(invite)
person.Invites.Delete(party.ID)
}
var body struct {
Meta map[string]interface{} `json:"meta"`
Connection aid.JSON `json:"connection"`
@ -300,5 +313,100 @@ func PostPartyPromoteMember(c *fiber.Ctx) error {
party.PromoteMember(member)
socket.EmitPartyNewCaptain(party)
return c.SendStatus(204)
}
func PostPartyCreateIntention(c *fiber.Ctx) error {
person := c.Locals("person").(*p.Person)
var body map[string]interface{}
if err := c.BodyParser(&body); err != nil {
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Request"))
}
towards := p.Find(c.Params("friendId"))
if towards == nil {
return c.Status(400).JSON(aid.ErrorBadRequest("Person Not Found"))
}
var party *p.Party
towards.Parties.Range(func(key string, p *p.Party) bool {
party = p
return false
})
if party == nil {
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
}
intention := p.NewPartyIntention(party, person, towards, body)
party.AddIntention(intention)
person.Intentions.Set(towards.ID, intention)
socket.EmitPartyIntention(intention)
return c.Status(204).JSON(intention.GenerateFortnitePartyIntention())
}
func PostPartyJoinFromPing(c *fiber.Ctx) error {
person := c.Locals("person").(*p.Person)
if person.Parties.Len() != 0 {
return c.Status(400).JSON(aid.ErrorBadRequest("Already in a party"))
}
party, ok := p.Parties.Get(c.Params("partyId"))
if !ok {
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
}
intention, ok := person.Intentions.Get(c.Params("friendId"))
if !ok {
return c.Status(400).JSON(aid.ErrorBadRequest("Intention Not Found"))
}
if intention.Party.ID != party.ID {
return c.Status(400).JSON(aid.ErrorBadRequest("Intention Not for this party"))
}
var body struct {
Meta map[string]interface{} `json:"meta"`
Connection aid.JSON `json:"connection"`
}
if err := c.BodyParser(&body); err != nil {
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Request"))
}
party.AddMember(person)
party.UpdateMemberMeta(person, body.Meta)
party.UpdateMemberConnection(person, body.Connection)
party.RemoveIntention(intention)
member := party.GetMember(person)
socket.EmitPartyMemberJoined(party, member)
socket.EmitPartyMemberMetaUpdated(party, party.GetMember(person), body.Meta, []string{})
socket.EmitPartyMetaUpdated(party, party.Meta, []string{}, map[string]interface{}{})
return c.Status(200).JSON(aid.JSON{
"party_id": party.ID,
"status": "JOINED",
})
}
func PostPartyDeletePings(c *fiber.Ctx) error {
person := c.Locals("person").(*p.Person)
friend := p.Find(c.Params("friendId"))
if friend == nil {
c.Status(400).JSON(aid.ErrorBadRequest("Friend Not Found"))
return nil
}
person.Intentions.Delete(friend.ID)
friend.Parties.Range(func(key string, party *p.Party) bool {
intent := party.GetIntention(person)
party.RemoveIntention(intent)
return true
})
return c.SendStatus(204)
}

View File

@ -4,6 +4,7 @@ import (
"crypto/sha1"
"crypto/sha256"
"encoding/hex"
"time"
"github.com/ectrc/snow/aid"
"github.com/ectrc/snow/person"
@ -26,12 +27,12 @@ func (c *cloudstorage) Add(name string, bytes []byte) error {
"hash256": hex.EncodeToString(sumation256[:]),
"length": len(bytes),
"contentType": "application/octet-stream",
"uploaded": aid.TimeStartOfDay(),
"uploaded": time.Now().Format(time.RFC3339),
"storageType": "S3",
"storageIds": aid.JSON{
"primary": "primary",
},
"doNotCache": false,
"doNotCache": true,
})
return nil

14
main.go
View File

@ -156,6 +156,8 @@ func main() {
party.Get("/user/:accountId/settings/privacy", handlers.GetPartyUserPrivacy)
party.Get("/user/:accountId/notifications/undelivered/count", handlers.GetPartyNotifications)
party.Get("/user/:accountId/pings/:friendId/parties", handlers.GetPartyPingsFromFriend)
party.Post("/user/:accountId/pings/:friendId/join", handlers.PostPartyJoinFromPing)
party.Delete("/user/:accountId/pings/:friendId", handlers.PostPartyDeletePings)
party.Get("/parties/:partyId", handlers.GetPartyForMember)
party.Post("/parties", handlers.PostPartyCreate)
party.Post("/parties/:partyId/invites/:accountId", handlers.PostPartyInvite)
@ -164,12 +166,7 @@ func main() {
party.Patch("/parties/:partyId", handlers.PatchPartyUpdateState)
party.Patch("/parties/:partyId/members/:accountId/meta", handlers.PatchPartyUpdateMemberState)
party.Delete("/parties/:partyId/members/:accountId", handlers.DeletePartyMember)
// post /parties/:partyId/members/:accountId/conferences/connection (join a voip channel)
// get /user/:accountId/pings/:pinger/friendId/parties (get pings from a friend)
// post /user/:accountId/pings/:pinger/join (join a party from a ping)
// post /user/:friendId/pings/:accountId (send a ping)
// delete /user/:accountId/pings/:pinger/friendId (delete pings)
// post /members/:friendId/intentions/:accountId (send an invite and add invite to party)
party.Post("/members/:friendId/intentions/:accountId", handlers.PostPartyCreateIntention)
snow := r.Group("/snow")
snow.Use(handlers.MiddlewareOnlyDebug)
@ -195,13 +192,12 @@ func main() {
r.All("*", func(c *fiber.Ctx) error { return c.Status(fiber.StatusNotFound).JSON(aid.ErrorNotFound) })
if aid.Config.Fortnite.Season <= 2 {
t := handlers.NewServer()
go t.Listen()
// t := handlers.NewServer()
// go t.Listen()
}
err := r.Listen("0.0.0.0" + aid.Config.API.Port)
if err != nil {
panic(fmt.Sprintf("(fiber) failed to listen: %v", err))
}
}

View File

@ -8,6 +8,40 @@ import (
"github.com/google/uuid"
)
type PartyIntention struct{
Party *Party `json:"-"`
Requester *Person `json:"-"`
Towards *Person `json:"-"`
Meta map[string]interface{}
CreatedAt time.Time
ExpiresAt time.Time
}
func NewPartyIntention(party *Party, requester *Person, towards *Person, meta map[string]interface{}) *PartyIntention {
return &PartyIntention{
Party: party,
Requester: requester,
Towards: towards,
Meta: meta,
CreatedAt: time.Now(),
ExpiresAt: time.Now().Add(time.Minute * 60),
}
}
func (pi *PartyIntention) GenerateFortnitePartyIntention() aid.JSON {
return aid.JSON{
"requester_id": pi.Requester.ID,
"requester_dn": pi.Requester.DisplayName,
"requester_pl": "",
"requester_pl_dn": "",
"requestee_id": pi.Towards.ID,
"meta": pi.Meta,
"expires_at": pi.ExpiresAt.Format(time.RFC3339),
"sent_at": pi.CreatedAt.Format(time.RFC3339),
}
}
type PartyInvite struct{
Party *Party `json:"-"`
Inviter *Person `json:"-"`
@ -81,6 +115,7 @@ type Party struct{
Captain *PartyMember
Members map[string]*PartyMember
Invites []*PartyInvite
Intentions []*PartyIntention
Config map[string]interface{}
Meta map[string]interface{}
CreatedAt time.Time
@ -95,15 +130,16 @@ var (
func NewParty() *Party {
party := &Party{
ID: uuid.New().String(),
Members: make(map[string]*PartyMember),
Members: map[string]*PartyMember{},
Config: map[string]interface{}{
"type": "DEFAULT",
"sub_type": "default",
"intention_ttl:": 60,
"invite_ttl:": 60,
},
Meta: make(map[string]interface{}),
Meta: map[string]interface{}{},
Invites: []*PartyInvite{},
Intentions: []*PartyIntention{},
CreatedAt: time.Now(),
}
@ -261,6 +297,19 @@ func (p *Party) AddInvite(invite *PartyInvite) {
p.Invites = append(p.Invites, invite)
}
func (p *Party) GetInvite(person *Person) *PartyInvite {
p.m.Lock()
defer p.m.Unlock()
for _, invite := range p.Invites {
if invite.Towards == person {
return invite
}
}
return nil
}
func (p *Party) RemoveInvite(invite *PartyInvite) {
p.m.Lock()
defer p.m.Unlock()
@ -273,6 +322,38 @@ func (p *Party) RemoveInvite(invite *PartyInvite) {
}
}
func (p *Party) AddIntention(intention *PartyIntention) {
p.m.Lock()
defer p.m.Unlock()
p.Intentions = append(p.Intentions, intention)
}
func (p *Party) GetIntention(person *Person) *PartyIntention {
p.m.Lock()
defer p.m.Unlock()
for _, intention := range p.Intentions {
if intention.Towards == person {
return intention
}
}
return nil
}
func (p *Party) RemoveIntention(intention *PartyIntention) {
p.m.Lock()
defer p.m.Unlock()
for i, v := range p.Intentions {
if v == intention {
p.Intentions = append(p.Intentions[:i], p.Intentions[i+1:]...)
break
}
}
}
func (p *Party) GenerateFortniteParty() aid.JSON {
p.m.Lock()
defer p.m.Unlock()
@ -298,5 +379,9 @@ func (p *Party) GenerateFortniteParty() aid.JSON {
party["invites"] = append(party["invites"].([]aid.JSON), invite.GenerateFortnitePartyInvite())
}
for _, intention := range p.Intentions {
party["intentions"] = append(party["intentions"].([]aid.JSON), intention.GenerateFortnitePartyIntention())
}
return party
}

View File

@ -24,6 +24,7 @@ type Person struct {
Relationships aid.GenericSyncMap[Relationship]
Parties aid.GenericSyncMap[Party]
Invites aid.GenericSyncMap[PartyInvite]
Intentions aid.GenericSyncMap[PartyIntention]
}
func NewPerson() *Person {
@ -42,6 +43,7 @@ func NewPerson() *Person {
Relationships: aid.GenericSyncMap[Relationship]{},
Parties: aid.GenericSyncMap[Party]{},
Invites: aid.GenericSyncMap[PartyInvite]{},
Intentions: aid.GenericSyncMap[PartyIntention]{},
}
}
@ -61,6 +63,7 @@ func NewPersonWithCustomID(id string) *Person {
Relationships: aid.GenericSyncMap[Relationship]{},
Parties: aid.GenericSyncMap[Party]{},
Invites: aid.GenericSyncMap[PartyInvite]{},
Intentions: aid.GenericSyncMap[PartyIntention]{},
}
}
@ -210,6 +213,7 @@ func findHelper(databasePerson *storage.DB_Person, shallow bool, save bool) *Per
Relationships: aid.GenericSyncMap[Relationship]{},
Parties: aid.GenericSyncMap[Party]{},
Invites: aid.GenericSyncMap[PartyInvite]{},
Intentions: aid.GenericSyncMap[PartyIntention]{},
}
for _, ban := range databasePerson.BanHistory {

View File

@ -163,4 +163,52 @@ func EmitPartyInvite(invite *person.PartyInvite) {
"sent": time.Now().Format(time.RFC3339),
"type": "com.epicgames.social.party.notification.v0.INITIAL_INVITE",
})
}
func EmitPartyIntention(invite *person.PartyIntention) {
s, ok := JabberSockets.Get(invite.Towards.ID)
if !ok {
return
}
s.JabberSendMessageToPerson(aid.JSON{
"requester_id": invite.Requester.ID,
"requester_dn": invite.Requester.DisplayName,
"requester_pl": "win",
"requester_pl_dn": invite.Requester.DisplayName,
"requestee_id": invite.Towards.ID,
"meta": invite.Meta,
"sent_at": invite.CreatedAt.Format(time.RFC3339),
"friends_ids": []string{},
"members_count": len(invite.Party.Members),
"party_id": invite.Party.ID,
"ns": "Fortnite",
"sent": time.Now().Format(time.RFC3339),
"type": "com.epicgames.social.party.notification.v0.INITIAL_INTENTION",
})
}
func EmitPartyPingFromInvite(i *person.PartyInvite) {
s, ok := JabberSockets.Get(i.Towards.ID)
if !ok {
return
}
meta := i.Meta
meta["urn:epic:member:dn_s"] = i.Inviter.DisplayName
meta["urn:epic:invite:platformdata_s"] = "RequestToJoin"
meta["urn:epic:conn:platform_s"] = "WIN"
meta["urn:epic:conn:platform:dn_s"] = i.Inviter.DisplayName
s.JabberSendMessageToPerson(aid.JSON{
"expires_at": i.CreatedAt.Add(time.Minute * 60).Format(time.RFC3339),
"pinger_id": i.Inviter.ID,
"pinger_dn": i.Inviter.DisplayName,
"pinger_pl": "win",
"pinger_pl_dn": i.Inviter.DisplayName,
"meta": meta,
"ns": "Fortnite",
"sent": time.Now().Format(time.RFC3339),
"type": "com.epicgames.social.party.notification.v0.PING",
})
}