package socket import ( "fmt" "reflect" "strings" "github.com/beevik/etree" "github.com/ectrc/snow/aid" "github.com/ectrc/snow/person" "github.com/gofiber/contrib/websocket" ) type JabberData struct { JabberID string PartyID string LastPresence string } var jabberHandlers = map[string]func(*Socket[JabberData], *etree.Document) error { "open": jabberOpenHandler, "iq": jabberIqRootHandler, "presence": jabberPresenceRootHandler, "message": jabberMessageHandler, } func HandleNewJabberSocket(identifier string) { socket, ok := JabberSockets.Get(identifier) if !ok { return } defer JabberSockets.Delete(socket.ID) for { _, message, failed := socket.Connection.ReadMessage() if failed != nil { break } parsed := etree.NewDocument() if err := parsed.ReadFromBytes(message); err != nil { return } if handler, ok := jabberHandlers[parsed.Root().Tag]; ok { if err := handler(socket, parsed); err != nil { socket.Connection.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, err.Error())) return } } } } func jabberOpenHandler(socket *Socket[JabberData], parsed *etree.Document) error { socket.Write([]byte(``)) socket.Write([]byte(``)) return nil } func jabberIqRootHandler(socket *Socket[JabberData], parsed *etree.Document) error { redirect := map[string]func(*Socket[JabberData], *etree.Document) error { "set": jabberIqSetHandler, "get": jabberIqGetHandler, } if handler, ok := redirect[parsed.Root().SelectAttr("type").Value]; ok { if err := handler(socket, parsed); err != nil { return err } } return nil } func jabberIqSetHandler(socket *Socket[JabberData], parsed *etree.Document) error { snowId, err := aid.GetSnowFromToken(parsed.FindElement("/iq/query/password").Text()) if err != nil { return err } person := person.Find(snowId) if person == nil { return fmt.Errorf("person not found") } JabberSockets.ChangeKey(socket.ID, person.ID) socket.ID = person.ID socket.Person = person 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(``)) return nil } func jabberIqGetHandler(socket *Socket[JabberData], parsed *etree.Document) error { socket.Write([]byte(``)) socket.JabberNotifyFriends() return nil } func jabberPresenceRootHandler(socket *Socket[JabberData], parsed *etree.Document) error { status := parsed.FindElement("/presence/status") if status == nil { return jabberPresenceJoinGroupchat(socket, parsed) } socket.Data.LastPresence = status.Text() 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(` `)) } 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(` `)) return nil } func jabberMessageHandler(socket *Socket[JabberData], parsed *etree.Document) error { if parsed.FindElement("/message/body") == nil { return nil } message := parsed.FindElement("/message") target := message.SelectAttr("to").Value parts := strings.Split(target, "@") if len(parts) != 2 { return nil } if reciever, ok := JabberSockets.Get(parts[0]); ok { reciever.Write([]byte(` `+ message.FindElement("/message/body").Text() +` `)) } return nil } func (s *Socket[T]) JabberSendMessageToPerson(data aid.JSON) { if reflect.TypeOf(s.Data) != reflect.TypeOf(&JabberData{}) { return } jabberSocket, ok := JabberSockets.Get(s.ID) if !ok { aid.Print("jabber socket not found even though it should be") return } s.Write([]byte(` `+ string(data.ToBytes()) +` `)) } func (s *Socket[T]) JabberNotifyFriends() { if reflect.TypeOf(s.Data) != reflect.TypeOf(&JabberData{}) { return } jabberSocket, ok := JabberSockets.Get(s.ID) if !ok { aid.Print("jabber socket not found even though it should be") return } s.Person.Relationships.Range(func(key string, value *person.Relationship) bool { friendSocket, found := JabberSockets.Get(value.From.ID) if value.Direction == person.RelationshipOutboundDirection { friendSocket, found = JabberSockets.Get(value.Towards.ID) } if !found { return true } friendSocket.Write([]byte(` `+ jabberSocket.Data.LastPresence +` `)) jabberSocket.Write([]byte(` `+ friendSocket.Data.LastPresence +` `)) return true }) jabberSocket.Write([]byte(` `+ jabberSocket.Data.LastPresence +` `)) }