245 lines
4.7 KiB
Go
245 lines
4.7 KiB
Go
|
package lobby
|
||
|
|
||
|
import (
|
||
|
"encoding/base64"
|
||
|
"encoding/json"
|
||
|
"errors"
|
||
|
"log/slog"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type LobbyMessage struct {
|
||
|
MessageType string `json:"message_type"`
|
||
|
Message any `json:"message"`
|
||
|
}
|
||
|
|
||
|
type Name struct {
|
||
|
Name string `json:"name"`
|
||
|
}
|
||
|
|
||
|
type Chat struct {
|
||
|
From string `json:"from"`
|
||
|
Message string `json:"message"`
|
||
|
}
|
||
|
|
||
|
type Invite struct {
|
||
|
From string `json:"from"`
|
||
|
To string `json:"to"`
|
||
|
}
|
||
|
|
||
|
type PendingInvite struct {
|
||
|
Recipient string `json:"recipient"`
|
||
|
}
|
||
|
|
||
|
type Accept struct {
|
||
|
From string `json:"from"`
|
||
|
To string `json:"to"`
|
||
|
}
|
||
|
|
||
|
type Accepted struct {
|
||
|
Accepter string `json:"accepter"`
|
||
|
GameID string `json:"game_id"`
|
||
|
}
|
||
|
|
||
|
type StartGame struct {
|
||
|
To string `json:"to"`
|
||
|
GameID string `json:"game_id"`
|
||
|
}
|
||
|
|
||
|
type Decline struct {
|
||
|
From string `json:"from"`
|
||
|
To string `json:"to"`
|
||
|
}
|
||
|
|
||
|
type Disconnect struct {
|
||
|
From string `json:"from"`
|
||
|
}
|
||
|
|
||
|
type Connect struct {
|
||
|
From string `json:"from"`
|
||
|
}
|
||
|
|
||
|
type Error struct {
|
||
|
Message string `json:"message"`
|
||
|
}
|
||
|
|
||
|
func Marshal(a LobbyMessage) ([]byte, error) {
|
||
|
slog.Debug("Marshalling message", slog.Any("message type", a.MessageType))
|
||
|
bm, err := json.Marshal(a.Message)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
a.Message = bm
|
||
|
return json.Marshal(a)
|
||
|
}
|
||
|
|
||
|
// Use this to get the appropriate message type into the message field then assert the
|
||
|
// right struct accordingly to safely access the fields you need.
|
||
|
func Unmarshal(b []byte) (LobbyMessage, error) {
|
||
|
lm := LobbyMessage{}
|
||
|
err := json.Unmarshal(b, &lm)
|
||
|
if err != nil {
|
||
|
return lm, err
|
||
|
}
|
||
|
|
||
|
smsg, ok := lm.Message.(string)
|
||
|
if !ok {
|
||
|
slog.Debug("error asserting message to string")
|
||
|
}
|
||
|
slog.Debug("type of message", slog.Any("type of message", reflect.TypeOf(smsg)), slog.String("message", smsg))
|
||
|
|
||
|
jsonBytes, err := base64.StdEncoding.DecodeString(smsg)
|
||
|
lm.Message = jsonBytes
|
||
|
|
||
|
switch strings.ToLower(lm.MessageType) {
|
||
|
case "name":
|
||
|
n := Name{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
|
||
|
err := json.Unmarshal(bs, &n)
|
||
|
if err != nil {
|
||
|
slog.Debug("Error", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = n
|
||
|
return lm, nil
|
||
|
case "chat":
|
||
|
c := Chat{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &c)
|
||
|
if err != nil {
|
||
|
slog.Debug("chat", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = c
|
||
|
return lm, nil
|
||
|
case "invite":
|
||
|
i := Invite{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &i)
|
||
|
if err != nil {
|
||
|
slog.Debug("invite", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = i
|
||
|
return lm, nil
|
||
|
case "pending_invite":
|
||
|
pi := PendingInvite{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &pi)
|
||
|
if err != nil {
|
||
|
slog.Debug("pending_invite", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = pi
|
||
|
case "accept":
|
||
|
a := Accept{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &a)
|
||
|
if err != nil {
|
||
|
slog.Debug("accept", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = a
|
||
|
return lm, nil
|
||
|
case "accepted":
|
||
|
a := Accepted{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &a)
|
||
|
if err != nil {
|
||
|
slog.Debug("accepted", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = a
|
||
|
return lm, nil
|
||
|
case "start_game":
|
||
|
sg := StartGame{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &sg)
|
||
|
if err != nil {
|
||
|
slog.Debug("start_game", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = sg
|
||
|
return lm, nil
|
||
|
case "decline":
|
||
|
d := Decline{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &d)
|
||
|
if err != nil {
|
||
|
slog.Debug("decline", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = d
|
||
|
return lm, nil
|
||
|
case "disconnect":
|
||
|
di := Disconnect{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &di)
|
||
|
if err != nil {
|
||
|
slog.Debug("disconnect", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = di
|
||
|
return lm, nil
|
||
|
case "connect":
|
||
|
co := Connect{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &co)
|
||
|
if err != nil {
|
||
|
slog.Debug("connect", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = co
|
||
|
return lm, nil
|
||
|
case "error":
|
||
|
e := Error{}
|
||
|
bs, ok := lm.Message.([]byte)
|
||
|
if !ok {
|
||
|
return lm, err
|
||
|
}
|
||
|
err := json.Unmarshal(bs, &e)
|
||
|
if err != nil {
|
||
|
slog.Debug("error", slog.Any("error", err))
|
||
|
return lm, err
|
||
|
}
|
||
|
lm.Message = e
|
||
|
return lm, nil
|
||
|
default:
|
||
|
return lm, errors.New("unknown message type")
|
||
|
}
|
||
|
return lm, errors.New("unknown message type")
|
||
|
}
|