Party V2 invites+joining & XMPP MUCs
This commit is contained in:
parent
0b9da07d2e
commit
8021c1d436
|
@ -67,4 +67,11 @@ func Regex(str, regex string) *string {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Ternary[T any](condition bool, a, b T) T {
|
||||||
|
if condition {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
}
|
}
|
|
@ -18,9 +18,9 @@ func FiberLogger() fiber.Handler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func FiberLimiter() fiber.Handler {
|
func FiberLimiter(n int) fiber.Handler {
|
||||||
return limiter.New(limiter.Config{
|
return limiter.New(limiter.Config{
|
||||||
Max: 100,
|
Max: n,
|
||||||
Expiration: 1 * time.Minute,
|
Expiration: 1 * time.Minute,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ func JWTSign(m JSON) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
token.Header["kid"] = "g__VKjSSmqJ0xZj1RYkLGKQ7dnHiM9MLhFVwKPySDB4"
|
||||||
return token.SignedString([]byte(Config.JWT.Secret))
|
return token.SignedString([]byte(Config.JWT.Secret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ectrc/snow/aid"
|
"github.com/ectrc/snow/aid"
|
||||||
p "github.com/ectrc/snow/person"
|
p "github.com/ectrc/snow/person"
|
||||||
"github.com/ectrc/snow/socket"
|
"github.com/ectrc/snow/socket"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUserParties(c *fiber.Ctx) error {
|
func GetPartiesForUser(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
response := aid.JSON{
|
response := aid.JSON{
|
||||||
|
@ -24,10 +22,15 @@ func GetUserParties(c *fiber.Ctx) error {
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
person.Invites.Range(func(key string, invite *p.PartyInvite) bool {
|
||||||
|
response["invites"] = append(response["invites"].([]aid.JSON), invite.GenerateFortnitePartyInvite())
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
return c.Status(200).JSON(response)
|
return c.Status(200).JSON(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserPartyPrivacy(c *fiber.Ctx) error {
|
func GetPartyUserPrivacy(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
recieveIntents := person.CommonCoreProfile.Attributes.GetAttributeByKey("party.recieveIntents")
|
recieveIntents := person.CommonCoreProfile.Attributes.GetAttributeByKey("party.recieveIntents")
|
||||||
|
@ -46,25 +49,47 @@ func GetUserPartyPrivacy(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserPartyNotifications(c *fiber.Ctx) error {
|
func GetPartyNotifications(c *fiber.Ctx) error {
|
||||||
|
person := c.Locals("person").(*p.Person)
|
||||||
return c.Status(200).JSON(aid.JSON{
|
return c.Status(200).JSON(aid.JSON{
|
||||||
"pings": 0,
|
"pings": 0,
|
||||||
"invites": 0,
|
"invites": person.Invites.Len(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPartyForMember(c *fiber.Ctx) error {
|
func GetPartyForMember(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
party, ok := person.Parties.Get(c.Params("partyId"))
|
party, ok := p.Parties.Get(c.Params("partyId"))
|
||||||
if !ok {
|
if !ok {
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
|
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aid.Print(person.DisplayName, " is getting party ", party.ID)
|
||||||
|
|
||||||
return c.Status(200).JSON(party.GenerateFortniteParty())
|
return c.Status(200).JSON(party.GenerateFortniteParty())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostCreateParty(c *fiber.Ctx) error {
|
func GetPartyPingsFromFriend(c *fiber.Ctx) error {
|
||||||
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
|
friend := p.Find(c.Params("friendId"))
|
||||||
|
if friend == nil {
|
||||||
|
return c.Status(400).JSON(aid.ErrorBadRequest("Friend Not Found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pings := []aid.JSON{}
|
||||||
|
person.Invites.Range(func(key string, ping *p.PartyInvite) bool {
|
||||||
|
if ping.Inviter.ID == friend.ID {
|
||||||
|
pings = append(pings, ping.Party.GenerateFortniteParty())
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
return c.Status(200).JSON(pings)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostPartyCreate(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
person.Parties.Range(func(key string, party *p.Party) bool {
|
person.Parties.Range(func(key string, party *p.Party) bool {
|
||||||
|
@ -89,41 +114,16 @@ func PostCreateParty(c *fiber.Ctx) error {
|
||||||
party.UpdateMeta(body.Meta)
|
party.UpdateMeta(body.Meta)
|
||||||
party.UpdateConfig(body.Config)
|
party.UpdateConfig(body.Config)
|
||||||
|
|
||||||
party.AddMember(person, "CAPTAIN")
|
party.AddMember(person)
|
||||||
party.UpdateMemberMeta(person, body.JoinInformation.Meta)
|
party.UpdateMemberMeta(person, body.JoinInformation.Meta)
|
||||||
|
party.UpdateMemberConnection(person, body.JoinInformation.Connection)
|
||||||
body.JoinInformation.Connection["connected_at"] = time.Now().Format(time.RFC3339)
|
party.ChangeNewCaptain()
|
||||||
body.JoinInformation.Connection["updated_at"] = time.Now().Format(time.RFC3339)
|
socket.EmitPartyMemberJoined(party, party.GetMember(person))
|
||||||
party.UpdateMemberConnections(person, body.JoinInformation.Connection)
|
|
||||||
|
|
||||||
member := party.GetMember(person)
|
|
||||||
if member == nil {
|
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("Failed to create party"))
|
|
||||||
}
|
|
||||||
|
|
||||||
s, ok := socket.JabberSockets.Get(person.ID)
|
|
||||||
if !ok {
|
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("No socket connection found"))
|
|
||||||
}
|
|
||||||
|
|
||||||
s.JabberSendMessageToPerson(aid.JSON{
|
|
||||||
"ns": "Fortnite",
|
|
||||||
"party_id": party.ID,
|
|
||||||
"account_id": person.ID,
|
|
||||||
"account_dn": person.DisplayName,
|
|
||||||
"connection": body.JoinInformation.Connection,
|
|
||||||
"member_state_updated": member.Meta,
|
|
||||||
"updated_at": member.UpdatedAt.Format(time.RFC3339),
|
|
||||||
"joined_at": member.JoinedAt.Format(time.RFC3339),
|
|
||||||
"sent": time.Now().Format(time.RFC3339),
|
|
||||||
"revision": 0,
|
|
||||||
"type": "com.epicgames.social.party.notification.v0.MEMBER_JOINED",
|
|
||||||
})
|
|
||||||
|
|
||||||
return c.Status(200).JSON(party.GenerateFortniteParty())
|
return c.Status(200).JSON(party.GenerateFortniteParty())
|
||||||
}
|
}
|
||||||
|
|
||||||
func PatchUpdateParty(c *fiber.Ctx) error {
|
func PatchPartyUpdateState(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
var body struct {
|
var body struct {
|
||||||
|
@ -134,9 +134,11 @@ func PatchUpdateParty(c *fiber.Ctx) error {
|
||||||
} `json:"meta"`
|
} `json:"meta"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if err := c.BodyParser(&body); err != nil {
|
if err := c.BodyParser(&body); err != nil {
|
||||||
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Request"))
|
return c.Status(400).JSON(aid.ErrorBadRequest("Invalid Request"))
|
||||||
}
|
}
|
||||||
|
aid.PrintJSON(body)
|
||||||
|
|
||||||
party, ok := person.Parties.Get(c.Params("partyId"))
|
party, ok := person.Parties.Get(c.Params("partyId"))
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -155,11 +157,12 @@ func PatchUpdateParty(c *fiber.Ctx) error {
|
||||||
party.UpdateConfig(body.Config)
|
party.UpdateConfig(body.Config)
|
||||||
party.UpdateMeta(body.Meta.Update)
|
party.UpdateMeta(body.Meta.Update)
|
||||||
party.DeleteMeta(body.Meta.Delete)
|
party.DeleteMeta(body.Meta.Delete)
|
||||||
|
socket.EmitPartyMetaUpdated(party, body.Meta.Update, body.Meta.Delete, body.Meta.Update)
|
||||||
|
|
||||||
return c.Status(200).JSON(party.GenerateFortniteParty())
|
return c.SendStatus(204)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PatchUpdatePartyMemberMeta(c *fiber.Ctx) error {
|
func PatchPartyUpdateMemberState(c *fiber.Ctx) error {
|
||||||
person := c.Locals("person").(*p.Person)
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
var body struct {
|
var body struct {
|
||||||
|
@ -187,6 +190,108 @@ func PatchUpdatePartyMemberMeta(c *fiber.Ctx) error {
|
||||||
|
|
||||||
party.UpdateMemberMeta(person, body.Update)
|
party.UpdateMemberMeta(person, body.Update)
|
||||||
party.DeleteMemberMeta(person, body.Delete)
|
party.DeleteMemberMeta(person, body.Delete)
|
||||||
|
socket.EmitPartyMemberMetaUpdated(party, member, body.Update, body.Delete)
|
||||||
|
|
||||||
return c.Status(200).JSON(party.GenerateFortniteParty())
|
return c.SendStatus(204)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeletePartyMember(c *fiber.Ctx) error {
|
||||||
|
person := c.Locals("person").(*p.Person)
|
||||||
|
|
||||||
|
party, ok := person.Parties.Get(c.Params("partyId"))
|
||||||
|
if !ok {
|
||||||
|
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
member := party.GetMember(person)
|
||||||
|
if member == nil {
|
||||||
|
return c.Status(400).JSON(aid.ErrorBadRequest("Not in Party"))
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.EmitPartyMemberLeft(party, member)
|
||||||
|
party.RemoveMember(person)
|
||||||
|
|
||||||
|
if party.Captain.Person.ID == person.ID && len(party.Members) > 0 {
|
||||||
|
party.ChangeNewCaptain()
|
||||||
|
go socket.EmitPartyNewCaptain(party)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendStatus(204)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostPartyInvite(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("accountId"))
|
||||||
|
if towards == nil {
|
||||||
|
return c.Status(400).JSON(aid.ErrorBadRequest("Person Not Found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
party, ok := person.Parties.Get(c.Params("partyId"))
|
||||||
|
if !ok {
|
||||||
|
return c.Status(400).JSON(aid.ErrorBadRequest("Party Not Found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
invite := p.NewPartyInvite(party, person, towards, body)
|
||||||
|
party.AddInvite(invite)
|
||||||
|
towards.Invites.Set(party.ID, invite)
|
||||||
|
|
||||||
|
socket.EmitPartyInvite(invite)
|
||||||
|
|
||||||
|
return c.SendStatus(204)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostPartyJoin(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"))
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// joinability, ok := party.Config["joinability"].(string)
|
||||||
|
// if ok && joinability != "OPEN" {
|
||||||
|
// invite, ok := person.Invites.Get(c.Params("partyId"))
|
||||||
|
// if !ok {
|
||||||
|
// return c.Status(400).JSON(aid.ErrorBadRequest("Invite Not Found"))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if invite.Party.ID != party.ID {
|
||||||
|
// return c.Status(400).JSON(aid.ErrorBadRequest("Invite Not Found"))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// person.Invites.Delete(c.Params("partyId"))
|
||||||
|
// party.RemoveInvite(invite)
|
||||||
|
// }
|
||||||
|
|
||||||
|
party.AddMember(person)
|
||||||
|
party.UpdateMemberMeta(person, body.Meta)
|
||||||
|
party.UpdateMemberConnection(person, body.Connection)
|
||||||
|
|
||||||
|
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",
|
||||||
|
})
|
||||||
}
|
}
|
23
main.go
23
main.go
|
@ -77,7 +77,7 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Use(aid.FiberLogger())
|
r.Use(aid.FiberLogger())
|
||||||
r.Use(aid.FiberLimiter())
|
r.Use(aid.FiberLimiter(100))
|
||||||
r.Use(aid.FiberCors())
|
r.Use(aid.FiberCors())
|
||||||
|
|
||||||
r.Get("/region", handlers.GetRegion)
|
r.Get("/region", handlers.GetRegion)
|
||||||
|
@ -110,6 +110,7 @@ func main() {
|
||||||
|
|
||||||
storefront := fortnite.Group("/storefront/v2")
|
storefront := fortnite.Group("/storefront/v2")
|
||||||
storefront.Use(handlers.MiddlewareFortnite)
|
storefront.Use(handlers.MiddlewareFortnite)
|
||||||
|
storefront.Use(aid.FiberLimiter(4))
|
||||||
storefront.Get("/catalog", handlers.GetStorefrontCatalog)
|
storefront.Get("/catalog", handlers.GetStorefrontCatalog)
|
||||||
storefront.Get("/keychain", handlers.GetStorefrontKeychain)
|
storefront.Get("/keychain", handlers.GetStorefrontKeychain)
|
||||||
|
|
||||||
|
@ -151,15 +152,23 @@ func main() {
|
||||||
|
|
||||||
party := r.Group("/party/api/v1/Fortnite")
|
party := r.Group("/party/api/v1/Fortnite")
|
||||||
party.Use(handlers.MiddlewareFortnite)
|
party.Use(handlers.MiddlewareFortnite)
|
||||||
party.Get("/user/:accountId", handlers.GetUserParties)
|
|
||||||
party.Get("/user/:accountId/settings/privacy", handlers.GetUserPartyPrivacy)
|
party.Get("/user/:accountId", handlers.GetPartiesForUser)
|
||||||
party.Get("/user/:accountId/notifications/undelivered/count", handlers.GetUserPartyNotifications)
|
party.Get("/user/:accountId/settings/privacy", handlers.GetPartyUserPrivacy)
|
||||||
party.Post("/parties", handlers.PostCreateParty)
|
party.Get("/user/:accountId/notifications/undelivered/count", handlers.GetPartyNotifications)
|
||||||
|
party.Get("/user/:accountId/pings/:friendId/parties", handlers.GetPartyPingsFromFriend)
|
||||||
|
|
||||||
party.Get("/parties/:partyId", handlers.GetPartyForMember)
|
party.Get("/parties/:partyId", handlers.GetPartyForMember)
|
||||||
party.Patch("/parties/:partyId", handlers.PatchUpdateParty)
|
party.Post("/parties", handlers.PostPartyCreate)
|
||||||
party.Patch("/parties/:partyId/members/:accountId/meta", handlers.PatchUpdatePartyMemberMeta)
|
party.Post("/parties/:partyId/invites/:accountId", handlers.PostPartyInvite)
|
||||||
|
party.Post("/parties/:partyId/members/:accountId/join", handlers.PostPartyJoin)
|
||||||
|
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)
|
// post /parties/:partyId/members/:accountId/conferences/connection (join a voip channel)
|
||||||
// delete /parties/:partyId/members/:accountid (remove a person from a party)
|
// delete /parties/:partyId/members/:accountid (remove a person from a party)
|
||||||
|
|
||||||
// get /user/:accountId/pings/:pinger/friendId/parties (get pings from a friend)
|
// 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/:accountId/pings/:pinger/join (join a party from a ping)
|
||||||
// post /user/:friendId/pings/:accountId (send a ping)
|
// post /user/:friendId/pings/:accountId (send a ping)
|
||||||
|
|
|
@ -8,44 +8,78 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PartyPing struct{
|
type PartyInvite struct{
|
||||||
Person *Person
|
Party *Party `json:"-"`
|
||||||
Party *Party
|
Inviter *Person `json:"-"`
|
||||||
|
Towards *Person `json:"-"`
|
||||||
|
Meta map[string]interface{}
|
||||||
|
Status string
|
||||||
|
CreatedAt time.Time
|
||||||
|
UpdatedAt time.Time
|
||||||
|
ExpiresAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPartyInvite(party *Party, inviter *Person, towards *Person, meta map[string]interface{}) *PartyInvite {
|
||||||
|
return &PartyInvite{
|
||||||
|
Party: party,
|
||||||
|
Inviter: inviter,
|
||||||
|
Towards: towards,
|
||||||
|
Meta: meta,
|
||||||
|
Status: "SENT",
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
UpdatedAt: time.Now(),
|
||||||
|
ExpiresAt: time.Now().Add(time.Minute * 60),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *PartyInvite) GenerateFortnitePartyInvite() aid.JSON {
|
||||||
|
return aid.JSON{
|
||||||
|
"party_id": pi.Party.ID,
|
||||||
|
"sent_by": pi.Inviter.ID,
|
||||||
|
"sent_to": pi.Towards.ID,
|
||||||
|
"sent_at": pi.CreatedAt.Format(time.RFC3339),
|
||||||
|
"status": pi.Status,
|
||||||
|
"meta": pi.Meta,
|
||||||
|
"inviter_pl": "win",
|
||||||
|
"inviter_pl_dn": pi.Inviter.DisplayName,
|
||||||
|
"expires_at": pi.ExpiresAt.Format(time.RFC3339),
|
||||||
|
"updated_at": pi.UpdatedAt.Format(time.RFC3339),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PartyMember struct{
|
type PartyMember struct{
|
||||||
Person *Person
|
Person *Person
|
||||||
ConnectionID string
|
ConnectionID string
|
||||||
Meta map[string]interface{}
|
Meta map[string]interface{}
|
||||||
Connections map[string]aid.JSON
|
Connection aid.JSON
|
||||||
Role string
|
Role string
|
||||||
JoinedAt time.Time
|
JoinedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *PartyMember) GenerateFortnitePartyMember() aid.JSON {
|
func (pm *PartyMember) GenerateFortnitePartyMember() aid.JSON {
|
||||||
connections := []aid.JSON{}
|
conn := pm.Connection
|
||||||
for _, connection := range pm.Connections {
|
conn["yield_leadership"] = true
|
||||||
connections = append(connections, connection)
|
|
||||||
}
|
|
||||||
|
|
||||||
return aid.JSON{
|
return aid.JSON{
|
||||||
"account_id": pm.Person.ID,
|
"account_id": pm.Person.ID,
|
||||||
"role": pm.Role,
|
"role": pm.Role,
|
||||||
"meta": pm.Meta,
|
"meta": pm.Meta,
|
||||||
"joined_at": pm.JoinedAt.Format(time.RFC3339),
|
"joined_at": pm.JoinedAt.Format(time.RFC3339),
|
||||||
"connections": connections,
|
"connections": []aid.JSON{conn},
|
||||||
"revision": 0,
|
"revision": 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Party struct{
|
type Party struct{
|
||||||
ID string
|
ID string
|
||||||
|
Captain *PartyMember
|
||||||
Members map[string]*PartyMember
|
Members map[string]*PartyMember
|
||||||
|
Invites []*PartyInvite
|
||||||
Config map[string]interface{}
|
Config map[string]interface{}
|
||||||
Meta map[string]interface{}
|
Meta map[string]interface{}
|
||||||
m sync.Mutex
|
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -63,6 +97,7 @@ func NewParty() *Party {
|
||||||
"invite_ttl:": 60,
|
"invite_ttl:": 60,
|
||||||
},
|
},
|
||||||
Meta: make(map[string]interface{}),
|
Meta: make(map[string]interface{}),
|
||||||
|
Invites: []*PartyInvite{},
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,33 +112,43 @@ func (p *Party) GetMember(person *Person) *PartyMember {
|
||||||
return p.Members[person.ID]
|
return p.Members[person.ID]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Party) AddMember(person *Person, role string) {
|
func (p *Party) ChangeNewCaptain() {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
for _, member := range p.Members {
|
||||||
|
p.Captain = member
|
||||||
|
p.Captain.Role = "CAPTAIN"
|
||||||
|
p.Captain.UpdatedAt = time.Now()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Party) AddMember(person *Person) {
|
||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
|
||||||
partyMember := &PartyMember{
|
partyMember := &PartyMember{
|
||||||
Person: person,
|
Person: person,
|
||||||
Meta: make(map[string]interface{}),
|
Meta: make(map[string]interface{}),
|
||||||
Connections: make(map[string]aid.JSON),
|
Role: "MEMBER",
|
||||||
Role: role,
|
|
||||||
JoinedAt: time.Now(),
|
JoinedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Members[person.ID] = partyMember
|
p.Members[person.ID] = partyMember
|
||||||
person.Parties.Set(p.ID, p)
|
person.Parties.Set(p.ID, p)
|
||||||
// xmpp to person and rest of party to say new member!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Party) RemoveMember(person *Person) {
|
func (p *Party) RemoveMember(person *Person) {
|
||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
person.Parties.Delete(p.ID)
|
||||||
|
|
||||||
delete(p.Members, person.ID)
|
delete(p.Members, person.ID)
|
||||||
if len(p.Members) == 0 {
|
if len(p.Members) == 0 {
|
||||||
Parties.Delete(p.ID)
|
Parties.Delete(p.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
person.Parties.Delete(p.ID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Party) UpdateMeta(m map[string]interface{}) {
|
func (p *Party) UpdateMeta(m map[string]interface{}) {
|
||||||
|
@ -164,16 +209,19 @@ func (p *Party) DeleteMemberMeta(person *Person, keys []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Party) UpdateMemberConnections(person *Person, m aid.JSON) {
|
func (p *Party) UpdateMemberConnection(person *Person, m aid.JSON) {
|
||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
m["connected_at"] = time.Now().Format(time.RFC3339)
|
||||||
|
m["updated_at"] = time.Now().Format(time.RFC3339)
|
||||||
|
|
||||||
member, ok := p.Members[person.ID]
|
member, ok := p.Members[person.ID]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
member.Connections[m["id"].(string)] = m
|
member.Connection = m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Party) UpdateConfig(m map[string]interface{}) {
|
func (p *Party) UpdateConfig(m map[string]interface{}) {
|
||||||
|
@ -185,6 +233,25 @@ func (p *Party) UpdateConfig(m map[string]interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Party) AddInvite(invite *PartyInvite) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
p.Invites = append(p.Invites, invite)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Party) RemoveInvite(invite *PartyInvite) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
|
for i, v := range p.Invites {
|
||||||
|
if v == invite {
|
||||||
|
p.Invites = append(p.Invites[:i], p.Invites[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Party) GenerateFortniteParty() aid.JSON {
|
func (p *Party) GenerateFortniteParty() aid.JSON {
|
||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
@ -206,5 +273,9 @@ func (p *Party) GenerateFortniteParty() aid.JSON {
|
||||||
party["members"] = append(party["members"].([]aid.JSON), member.GenerateFortnitePartyMember())
|
party["members"] = append(party["members"].([]aid.JSON), member.GenerateFortnitePartyMember())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, invite := range p.Invites {
|
||||||
|
party["invites"] = append(party["invites"].([]aid.JSON), invite.GenerateFortnitePartyInvite())
|
||||||
|
}
|
||||||
|
|
||||||
return party
|
return party
|
||||||
}
|
}
|
|
@ -23,7 +23,7 @@ type Person struct {
|
||||||
BanHistory aid.GenericSyncMap[storage.DB_BanStatus]
|
BanHistory aid.GenericSyncMap[storage.DB_BanStatus]
|
||||||
Relationships aid.GenericSyncMap[Relationship]
|
Relationships aid.GenericSyncMap[Relationship]
|
||||||
Parties aid.GenericSyncMap[Party]
|
Parties aid.GenericSyncMap[Party]
|
||||||
Pings aid.GenericSyncMap[PartyPing]
|
Invites aid.GenericSyncMap[PartyInvite]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPerson() *Person {
|
func NewPerson() *Person {
|
||||||
|
@ -41,7 +41,7 @@ func NewPerson() *Person {
|
||||||
BanHistory: aid.GenericSyncMap[storage.DB_BanStatus]{},
|
BanHistory: aid.GenericSyncMap[storage.DB_BanStatus]{},
|
||||||
Relationships: aid.GenericSyncMap[Relationship]{},
|
Relationships: aid.GenericSyncMap[Relationship]{},
|
||||||
Parties: aid.GenericSyncMap[Party]{},
|
Parties: aid.GenericSyncMap[Party]{},
|
||||||
Pings: aid.GenericSyncMap[PartyPing]{},
|
Invites: aid.GenericSyncMap[PartyInvite]{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ func NewPersonWithCustomID(id string) *Person {
|
||||||
BanHistory: aid.GenericSyncMap[storage.DB_BanStatus]{},
|
BanHistory: aid.GenericSyncMap[storage.DB_BanStatus]{},
|
||||||
Relationships: aid.GenericSyncMap[Relationship]{},
|
Relationships: aid.GenericSyncMap[Relationship]{},
|
||||||
Parties: aid.GenericSyncMap[Party]{},
|
Parties: aid.GenericSyncMap[Party]{},
|
||||||
Pings: aid.GenericSyncMap[PartyPing]{},
|
Invites: aid.GenericSyncMap[PartyInvite]{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +209,7 @@ func findHelper(databasePerson *storage.DB_Person, shallow bool, save bool) *Per
|
||||||
RefundTickets: databasePerson.RefundTickets,
|
RefundTickets: databasePerson.RefundTickets,
|
||||||
Relationships: aid.GenericSyncMap[Relationship]{},
|
Relationships: aid.GenericSyncMap[Relationship]{},
|
||||||
Parties: aid.GenericSyncMap[Party]{},
|
Parties: aid.GenericSyncMap[Party]{},
|
||||||
|
Invites: aid.GenericSyncMap[PartyInvite]{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ban := range databasePerson.BanHistory {
|
for _, ban := range databasePerson.BanHistory {
|
||||||
|
|
163
socket/events.go
Normal file
163
socket/events.go
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
package socket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ectrc/snow/aid"
|
||||||
|
"github.com/ectrc/snow/person"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EmitPartyMemberJoined(party *person.Party, joiningMember *person.PartyMember) {
|
||||||
|
for _, partyMember := range party.Members {
|
||||||
|
s, ok := JabberSockets.Get(partyMember.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"account_id": joiningMember.Person.ID,
|
||||||
|
"account_dn": joiningMember.Person.DisplayName,
|
||||||
|
"connection": joiningMember.Connection,
|
||||||
|
"member_state_updated": joiningMember.Meta,
|
||||||
|
"updated_at": joiningMember.UpdatedAt.Format(time.RFC3339),
|
||||||
|
"joined_at": joiningMember.JoinedAt.Format(time.RFC3339),
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"party_id": party.ID,
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"revision": 0,
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.MEMBER_JOINED",
|
||||||
|
})
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"interactions": []aid.JSON{{
|
||||||
|
"app": "Snow",
|
||||||
|
"namespace": "Fortnite",
|
||||||
|
"fromAccountId": joiningMember.Person.ID,
|
||||||
|
"toAccountId": partyMember.Person.ID,
|
||||||
|
"interactionScoreIncremental": aid.JSON{
|
||||||
|
"count": 1,
|
||||||
|
"total": 1,
|
||||||
|
},
|
||||||
|
"interactionType": "PartyJoined",
|
||||||
|
"isFriend": true,
|
||||||
|
"happenedAt": time.Now().Unix(),
|
||||||
|
}},
|
||||||
|
"type": "com.epicgames.social.interactions.notification.v2",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmitPartyMemberLeft(party *person.Party, member *person.PartyMember) {
|
||||||
|
for _, m := range party.Members {
|
||||||
|
s, ok := JabberSockets.Get(m.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"account_id": member.Person.ID,
|
||||||
|
"member_state_updated": aid.JSON{},
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"party_id": party.ID,
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"revision": 0,
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.MEMBER_LEFT",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmitPartyMemberMetaUpdated(party *person.Party, member *person.PartyMember, update map[string]interface{}, deleted []string) {
|
||||||
|
for _, m := range party.Members {
|
||||||
|
s, ok := JabberSockets.Get(m.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"account_id": member.Person.ID,
|
||||||
|
"account_dn": member.Person.DisplayName,
|
||||||
|
"member_state_updated": update,
|
||||||
|
"member_state_removed": deleted,
|
||||||
|
"member_state_overriden": aid.JSON{},
|
||||||
|
"updated_at": member.UpdatedAt.Format(time.RFC3339),
|
||||||
|
"joined_at": member.JoinedAt.Format(time.RFC3339),
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"party_id": party.ID,
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"revision": 0,
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.MEMBER_STATE_UPDATED",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmitPartyMetaUpdated(party *person.Party, override map[string]interface{}, deleted []string, update map[string]interface{}) {
|
||||||
|
for _, m := range party.Members {
|
||||||
|
s, ok := JabberSockets.Get(m.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"captain_id": party.Captain.Person.ID,
|
||||||
|
"party_state_updated": update,
|
||||||
|
"party_state_removed": deleted,
|
||||||
|
"party_state_overriden": override,
|
||||||
|
"party_privacy_type": party.Config["joinability"],
|
||||||
|
"party_type": party.Config["type"],
|
||||||
|
"party_sub_type": party.Config["sub_type"],
|
||||||
|
"max_number_of_members": party.Config["max_size"],
|
||||||
|
"invite_ttl_seconds": party.Config["invite_ttl"],
|
||||||
|
"intention_ttl_seconds": party.Config["intention_ttl"],
|
||||||
|
"updated_at": time.Now().Format(time.RFC3339),
|
||||||
|
"created_at": party.CreatedAt.Format(time.RFC3339),
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"party_id": party.ID,
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"revision": 0,
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.PARTY_UPDATED",
|
||||||
|
})
|
||||||
|
|
||||||
|
aid.Print("EmitPartyMetaUpdated party", party.ID, "to", m.Person.DisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmitPartyNewCaptain(party *person.Party) {
|
||||||
|
for _, m := range party.Members {
|
||||||
|
s, ok := JabberSockets.Get(m.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"account_id": party.Captain.Person.ID,
|
||||||
|
"account_dn": party.Captain.Person.DisplayName,
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"party_id": party.ID,
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"revision": 0,
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.MEMBER_NEW_CAPTAIN",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EmitPartyInvite(invite *person.PartyInvite) {
|
||||||
|
s, ok := JabberSockets.Get(invite.Towards.ID)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.JabberSendMessageToPerson(aid.JSON{
|
||||||
|
"inviter_id": invite.Inviter.ID,
|
||||||
|
"inviter_dn": invite.Inviter.DisplayName,
|
||||||
|
"invitee_id": invite.Towards.ID,
|
||||||
|
"meta": invite.Meta,
|
||||||
|
"sent_at": invite.CreatedAt.Format(time.RFC3339),
|
||||||
|
"updated_at": invite.UpdatedAt.Format(time.RFC3339),
|
||||||
|
"friends_ids": []string{},
|
||||||
|
"members_count": 0,
|
||||||
|
"party_id": invite.Party.ID,
|
||||||
|
"ns": "Fortnite",
|
||||||
|
"sent": time.Now().Format(time.RFC3339),
|
||||||
|
"type": "com.epicgames.social.party.notification.v0.INITIAL_INVITE",
|
||||||
|
})
|
||||||
|
}
|
|
@ -13,13 +13,14 @@ import (
|
||||||
|
|
||||||
type JabberData struct {
|
type JabberData struct {
|
||||||
JabberID string
|
JabberID string
|
||||||
|
PartyID string
|
||||||
LastPresence string
|
LastPresence string
|
||||||
}
|
}
|
||||||
|
|
||||||
var jabberHandlers = map[string]func(*Socket[JabberData], *etree.Document) error {
|
var jabberHandlers = map[string]func(*Socket[JabberData], *etree.Document) error {
|
||||||
"open": jabberOpenHandler,
|
"open": jabberOpenHandler,
|
||||||
"iq": jabberIqRootHandler,
|
"iq": jabberIqRootHandler,
|
||||||
"presence": jabberPresenceHandler,
|
"presence": jabberPresenceRootHandler,
|
||||||
"message": jabberMessageHandler,
|
"message": jabberMessageHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ func jabberIqSetHandler(socket *Socket[JabberData], parsed *etree.Document) erro
|
||||||
socket.ID = person.ID
|
socket.ID = person.ID
|
||||||
socket.Person = person
|
socket.Person = person
|
||||||
socket.Data.JabberID = snowId + "@prod.ol.epicgames.com/" + parsed.FindElement("/iq/query/resource").Text()
|
socket.Data.JabberID = snowId + "@prod.ol.epicgames.com/" + parsed.FindElement("/iq/query/resource").Text()
|
||||||
|
socket.Data.PartyID = person.DisplayName + ":" + person.ID + parsed.FindElement("/iq/query/resource").Text()
|
||||||
|
|
||||||
socket.Write([]byte(`<iq xmlns="jabber:client" type="result" id="_xmpp_auth1" from="prod.ol.epicgames.com" to="`+ socket.Data.JabberID +`" />`))
|
socket.Write([]byte(`<iq xmlns="jabber:client" type="result" id="_xmpp_auth1" from="prod.ol.epicgames.com" to="`+ socket.Data.JabberID +`" />`))
|
||||||
return nil
|
return nil
|
||||||
|
@ -98,13 +100,74 @@ func jabberIqGetHandler(socket *Socket[JabberData], parsed *etree.Document) erro
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func jabberPresenceHandler(socket *Socket[JabberData], parsed *etree.Document) error {
|
func jabberPresenceRootHandler(socket *Socket[JabberData], parsed *etree.Document) error {
|
||||||
status := parsed.FindElement("/presence/status")
|
status := parsed.FindElement("/presence/status")
|
||||||
if status == nil {
|
if status == nil {
|
||||||
return nil
|
return jabberPresenceJoinGroupchat(socket, parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.Data.LastPresence = status.Text()
|
socket.Data.LastPresence = status.Text()
|
||||||
socket.JabberNotifyFriends()
|
socket.JabberNotifyFriends()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func jabberPresenceJoinGroupchat(socket *Socket[JabberData], parsed *etree.Document) error {
|
||||||
|
towards := parsed.FindElement("/presence").SelectAttr("to").Value
|
||||||
|
|
||||||
|
partyId := aid.Regex(towards, `Party-(.*?)@`)
|
||||||
|
if partyId == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
party, ok := person.Parties.Get(*partyId)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, member := range party.Members {
|
||||||
|
if member.Person.ID == socket.ID {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
memberSocket, ok := JabberSockets.Get(member.Person.ID)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
memberPartyId := "Party-" + party.ID + "@muc.prod.ol.epicgames.com/" + memberSocket.Data.PartyID
|
||||||
|
memberRole := aid.Ternary[string](party.Captain.Person.ID == member.Person.ID, "moderator", "participant")
|
||||||
|
memberAffiliation := aid.Ternary[string](party.Captain.Person.ID == member.Person.ID, "owner", "none")
|
||||||
|
|
||||||
|
socket.Write([]byte(`<presence xmlns="jabber:client" from="`+ memberPartyId +`" to="`+ socket.Data.JabberID +`">
|
||||||
|
<x xmlns="http://jabber.org/protocol/muc#user">
|
||||||
|
<item
|
||||||
|
affiliation="`+ memberAffiliation +`"
|
||||||
|
role="`+ memberRole +`"
|
||||||
|
jid="`+ memberSocket.Data.JabberID +`"
|
||||||
|
nick="`+ memberPartyId +`"
|
||||||
|
/>
|
||||||
|
</x>
|
||||||
|
</presence>`))
|
||||||
|
}
|
||||||
|
|
||||||
|
socketPartyId := "Party-" + party.ID + "@muc.prod.ol.epicgames.com/" + socket.Data.PartyID
|
||||||
|
socketRole := aid.Ternary[string](party.Captain.Person.ID == socket.ID, "moderator", "participant")
|
||||||
|
socketAffiliation := aid.Ternary[string](party.Captain.Person.ID == socket.ID, "owner", "none")
|
||||||
|
|
||||||
|
socket.Write([]byte(`<presence xmlns="jabber:client" from="`+ socketPartyId +`" to="`+ socket.Data.JabberID +`">
|
||||||
|
<x xmlns="http://jabber.org/protocol/muc#user">
|
||||||
|
<item
|
||||||
|
affiliation="`+ socketAffiliation +`"
|
||||||
|
role="`+ socketRole +`"
|
||||||
|
jid="`+ socket.Data.JabberID +`"
|
||||||
|
nick="`+ socketPartyId +`"
|
||||||
|
/>
|
||||||
|
<status code="110"/>
|
||||||
|
<status code="100"/>
|
||||||
|
<status code="170"/>
|
||||||
|
</x>
|
||||||
|
</presence>`))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,4 +238,8 @@ func (s *Socket[T]) JabberNotifyFriends() {
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
jabberSocket.Write([]byte(`<presence xmlns="jabber:client" type="available" from="`+ jabberSocket.Data.JabberID +`" to="`+ jabberSocket.Data.JabberID +`">
|
||||||
|
<status>`+ jabberSocket.Data.LastPresence +`</status>
|
||||||
|
</presence>`))
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user