sshpong/internal/lobby/lobby_messages.go
2024-09-26 19:49:59 -06:00

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")
}