124 lines
3 KiB
Go
124 lines
3 KiB
Go
package wsmanager
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"git.sapphic.engineer/ps2.live/saerro-go/cmd/ws/eventhandler"
|
|
"git.sapphic.engineer/ps2.live/saerro-go/types"
|
|
"github.com/coder/websocket"
|
|
)
|
|
|
|
type WebsocketManager struct {
|
|
Conn *websocket.Conn
|
|
EventHandler eventhandler.EventHandler
|
|
Closed chan bool
|
|
}
|
|
|
|
func NewWebsocketManager(eh eventhandler.EventHandler) WebsocketManager {
|
|
return WebsocketManager{
|
|
EventHandler: eh,
|
|
Closed: make(chan bool, 1),
|
|
}
|
|
}
|
|
|
|
func (wsm *WebsocketManager) Connect(ctx context.Context, addr string) (err error) {
|
|
wsm.Conn, _, err = websocket.Dial(ctx, addr, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("wsm: connect failed: %w", err)
|
|
}
|
|
|
|
log.Println("wsm: connected to", addr)
|
|
|
|
return
|
|
}
|
|
|
|
type ESSSubscription struct {
|
|
Action string `json:"action,omitempty"`
|
|
Worlds []string `json:"worlds,omitempty"`
|
|
EventNames []string `json:"eventNames,omitempty"`
|
|
Characters []string `json:"characters,omitempty"`
|
|
Service string `json:"service,omitempty"`
|
|
LogicalAndCharactersWithWorlds bool `json:"logicalAndCharactersWithWorlds,omitempty"`
|
|
}
|
|
|
|
func (wsm *WebsocketManager) Subscribe(ctx context.Context) error {
|
|
sub := ESSSubscription{
|
|
Action: "subscribe",
|
|
Service: "event",
|
|
Worlds: []string{"all"},
|
|
EventNames: getEventNames(),
|
|
Characters: []string{"all"},
|
|
LogicalAndCharactersWithWorlds: true,
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
err := json.NewEncoder(&buf).Encode(sub)
|
|
if err != nil {
|
|
return fmt.Errorf("wsm: subscribe: json encode failed: %w", err)
|
|
}
|
|
|
|
log.Printf("wsm: subscribe message: %s", buf.String())
|
|
|
|
err = wsm.Conn.Write(ctx, websocket.MessageText, buf.Bytes())
|
|
if err != nil {
|
|
return fmt.Errorf("wsm: subscribe: ws write failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (wsm *WebsocketManager) Start() {
|
|
go wsm.startWatchdog()
|
|
|
|
for {
|
|
ctx := context.Background()
|
|
|
|
var event types.ESSData
|
|
|
|
_, data, err := wsm.Conn.Read(ctx)
|
|
if err != nil {
|
|
log.Fatalln("wsm: read failed:", err)
|
|
}
|
|
|
|
// log.Printf("raw event: %s", string(data))
|
|
|
|
err = json.Unmarshal(data, &event)
|
|
if err != nil {
|
|
log.Println("wsm: json unmarshal failed:", err)
|
|
log.Println("wsm: json unmarshal failed (payload)", string(data))
|
|
}
|
|
|
|
go wsm.EventHandler.HandleEvent(ctx, event.Payload)
|
|
}
|
|
}
|
|
|
|
func (wsm *WebsocketManager) startWatchdog() {
|
|
for {
|
|
time.Sleep(time.Second * 30)
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
|
|
err := wsm.Conn.Ping(ctx)
|
|
if err != nil {
|
|
log.Println("wsm: watchdog failed")
|
|
wsm.Closed <- true
|
|
}
|
|
|
|
cancel()
|
|
}
|
|
}
|
|
|
|
func (wsm *WebsocketManager) Close() {
|
|
wsm.Conn.Close(websocket.StatusNormalClosure, "")
|
|
wsm.Closed <- true
|
|
}
|
|
|
|
func (wsm *WebsocketManager) FailClose() {
|
|
wsm.Conn.Close(websocket.StatusAbnormalClosure, "")
|
|
wsm.Closed <- true
|
|
}
|