draftbot/draftbot.go

153 lines
3.6 KiB
Go

package draftbot
import (
room "git.fromouter.space/mcg/cardgage/room/api"
"github.com/go-kit/kit/log"
)
// DraftBot is the functional part of draftbot
type DraftBot struct {
API BotInterface
Logger log.Logger
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)
}
// NewDraftBot creates a new draft bot instance with the given name
// and communication interface
func NewDraftBot(botAPI BotInterface, name string) *DraftBot {
return &DraftBot{
API: botAPI,
Name: name,
Rooms: make(map[string]roomInfo),
Sessions: make(map[string]*session),
}
}
// OnMessage is the function to be called when messages are received
func (d *DraftBot) OnMessage(msg room.ServerMessage) {
switch msg.Type {
case room.MsgMessage:
if d.Logger != nil {
d.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 d.Logger != nil {
d.Logger.Log("event", "event",
"roomid", msg.RoomID,
"content", msg.Event.Message)
}
d.handleEvent(msg.RoomID, *msg.Event)
}
}
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
d.commands(commandMap{
// Owner wants to create a session
"create": d.cmdfnOnlyOwner(d.cmdCreateSession),
})(roomid, msg)
return
}
// Check if player is in the draft
_, ok = session.Players[msg.From]
if !ok {
// Player not in draft, are they asking to join?
d.commands(commandMap{
// Player wants to join the session
"join": d.cmdJoinSession,
// Owner wants to start the session (but not partecipate)
"start": d.cmdfnOnlyOwner(d.cmdStartSession),
})(roomid, msg)
return
}
// Players in the draft session
d.commands(commandMap{
// Player has picked a card
"pick": d.cmdPickCard,
// Owner wants to start the session
"start": d.cmdfnOnlyOwner(d.cmdStartSession),
})(roomid, msg)
}
func (d *DraftBot) handleEvent(roomid string, evt room.Event) {
switch evt.Type {
// Got added to a new room
case room.EvtNewRoom:
// Add room to the list
d.Rooms[evt.Room.Id] = roomInfo{
Name: evt.Room.Name,
Owner: evt.Room.Creator,
}
// Someone left
case room.EvtLeft:
// Check if room has a running session
sess, ok := d.Sessions[roomid]
if !ok {
break
}
// Check if player is in that session
player, ok := sess.Players[evt.PlayerName]
if !ok {
break
}
// Replace player with bot
//TODO
_ = player
// A room got closed
case room.EvtRoomClosed:
// Check if there's a session there
session, ok := d.Sessions[roomid]
if ok {
// Close session
session.exit <- true
// Remove session from list
delete(d.Sessions, roomid)
}
// Remove room from list
delete(d.Rooms, roomid)
}
}
func (d *DraftBot) handleSessionMessages(roomid string, s *session) {
for msg := range s.messages {
d.sendMessage(roomid, msg)
}
}