draftbot/draftbot.messages.go
2019-08-26 11:20:00 +02:00

190 lines
4.5 KiB
Go

package draftbot
import (
"fmt"
"github.com/mitchellh/mapstructure"
room "git.fromouter.space/mcg/cardgage/room/api"
"git.fromouter.space/mcg/draft"
)
type commandHandler func(roomid string, msg room.Message)
type commandMap map[string]commandHandler
func (d *DraftBot) commands(commands commandMap) commandHandler {
return func(roomid string, msg room.Message) {
action, ok := commands[msg.Type]
if !ok {
cmdlist := []string{}
for cmd := range commands {
cmdlist = append(cmdlist, cmd)
}
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "command-unavailable",
Message: fmt.Sprintf("Available commands (at this state) are: %s", cmdlist),
})
return
}
action(roomid, msg)
}
}
func (d *DraftBot) cmdJoinSession(roomid string, msg room.Message) {
// Get session
session, _ := d.Sessions[roomid]
// 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)),
})
}
func (d *DraftBot) cmdPickCard(roomid string, msg room.Message) {
// Get session
session, _ := d.Sessions[roomid]
// Get player
player, _ := session.Players[msg.From]
// 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),
})
}
func (d *DraftBot) cmdCreateSession(roomid string, msg room.Message) {
// Get session options from data
var opt SessionOptions
err := mapstructure.Decode(msg.Data, &opt)
if err != nil {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "invalid-data",
Message: "Error parsing session options: " + err.Error(),
})
return
}
sess, err := newSession(opt.Players, opt.Options)
if err != nil {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "session-create-error",
Data: err.Error(),
Message: "Error creating session: " + err.Error(),
})
return
}
// All ok, assign session
d.Sessions[roomid] = sess
// Start handling messages for the session
go d.handleSessionMessages(roomid, sess)
// Tell everyone about the new session
d.sendMessage(roomid, room.Message{
Channel: "draft",
Type: "session-open",
Data: opt,
Message: fmt.Sprintf("Created a new draft session for %d players, type: %s", opt.Players, opt.Options.Type),
})
}
func (d *DraftBot) cmdStartSession(roomid string, msg room.Message) {
// Get session
session, _ := d.Sessions[roomid]
// Try starting the session
err := session.Start()
if err != nil {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "session-start-error",
Data: err.Error(),
Message: "Could not start session: " + err.Error(),
})
return
}
// Tell everyone about the new session
d.sendMessage(roomid, room.Message{
Channel: "draft",
Type: "session-start",
Message: "Session started, get drafting!",
})
}
func (d *DraftBot) cmdfnOnlyOwner(wrapped commandHandler) commandHandler {
return func(roomid string, msg room.Message) {
// Get room the message was sent from
roomData, ok := d.Rooms[roomid]
if !ok {
// Message from a room we're not in?
// Ignore it for now
return
}
// Make sure the message is coming from the room owner
if msg.From != roomData.Owner {
d.sendMessage(roomid, room.Message{
To: msg.From,
Type: "must-be-owner",
Message: "Sorry, only the room's owner can tell me to do that",
})
return
}
// Check done, call wrapped function
wrapped(roomid, msg)
}
}