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), }) } }