package main 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) } }