mlp-server-tools/draftbot/draftbot.go

160 lines
3.6 KiB
Go

package main
import (
"fmt"
room "git.fromouter.space/mcg/cardgage/room/api"
"git.fromouter.space/mcg/draft"
)
type draftBot struct {
API BotInterface
Name string
Rooms map[string]roomInfo
Sessions map[string]session
}
type roomInfo struct {
Name string
Owner string
}
// BotInterface is the interface needed by draftbot for working in cardgage
// This exists so that draftbot can be attached to a mocked API for testing
type BotInterface interface {
Send(room.BotMessage)
}
func newDraftBot(botAPI BotInterface, name string) *draftBot {
return &draftBot{
API: botAPI,
Name: name,
Sessions: make(map[string]session),
}
}
func (d *draftBot) onMessage(msg room.ServerMessage) {
switch msg.Type {
case room.MsgMessage:
if *logAll {
logger.Log("event", "message",
"roomid", msg.RoomID,
"from", msg.Message.From,
"to", msg.Message.To,
"content", msg.Message.Message)
}
// Only consider messages that speak directly to me
if msg.Message.To == d.Name {
d.handleMessage(msg.RoomID, *msg.Message)
}
case room.MsgEvent:
if *logAll {
logger.Log("event", "event",
"roomid", msg.RoomID,
"content", msg.Event.Message)
}
}
}
func (d *draftBot) sendMessage(roomid string, msg room.Message) {
d.API.Send(room.BotMessage{
RoomID: roomid,
Type: room.MsgMessage,
Message: &msg,
})
}
func (d *draftBot) handleMessage(roomid string, msg room.Message) {
// Get session in room
session, ok := d.Sessions[roomid]
if !ok {
// Room does not have a currently running session, ignore unless it's the owner asking for specific stuff
//TODO
return
}
// Check if player is in the draft
player, ok := session.Players[msg.From]
if !ok {
// Player not in draft, are they asking to join?
switch msg.Type {
// Player is asking to join
case "join":
// Players can only join if session didn't start yet
if session.started {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "session-already-started",
Message: "You can't join a running session",
})
return
}
// Check if there are still open slots
if len(session.Players)+1 > len(session.Pod.Players) {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "session-full",
Message: "There aren't any spots left",
})
return
}
// Add player to the list
session.Players[msg.From] = nil
d.sendMessage(roomid, room.Message{
Channel: "draft",
Type: "player-joined-session",
Data: msg.From,
Message: fmt.Sprintf("%s joined the draft session (%d players, %d missing)", msg.From, len(session.Players), len(session.Pod.Players)-len(session.Players)),
})
// Player wants something else
default:
// Tell them can either join or GTFO
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "not-joined-err",
Data: "not joined",
Message: "You must join the session to do anything",
})
return
}
return
}
switch msg.Type {
// Player has picked a card
case "pick":
// Get picked card
picked := msg.Data.(string)
// Try to pick on player struct
err := player.Pick(draft.Card{ID: picked})
if err != nil {
if err == draft.ErrNotInPack {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "invalid-pick",
})
} else {
// Technically not needed, as Pick can only throw ErrNotInPack right now
}
return
}
d.sendMessage(roomid, room.Message{
Channel: "draft",
Type: "card-picked",
Data: struct {
Player string
}{
msg.From,
},
Message: fmt.Sprintf("%s picked a card from his pack", msg.From),
})
}
}