func handleMessage(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) { typ := msg.Type() if typ != tbotapi.TextMessage { //ignore non-text messages for now return } text := *msg.Text if msg.Chat.IsPrivateChat() { fmt.Printf("<-%d, %s,\t%q\n", msg.ID, msg.Chat, text) } else { fmt.Printf("<-%d, %s(%s),\t%q\n", msg.ID, msg.Chat, msg.From, text) } if msg.Chat.IsPrivateChat() { //always update the list of private chats putChat(msg.From.ID, msg.Chat.ID) } if strings.HasPrefix(text, "/") { //command cmd := parseCommand(text) if cmd == cmdNew { game(msg, api) return } groupsLock.RLock() if c, ok := groups[msg.Chat.ID]; ok { c <- msg } groupsLock.RUnlock() } else { if msg.Chat.IsPrivateChat() { uid := msg.From.ID expectsLock.Lock() if expect, ok := expects[uid]; ok { switch parseChoice(text) { case choiceRock, choicePaper, choiceScissors: expect <- parseChoice(text) delete(expects, uid) default: reply(msg, api, "No understand") } } expectsLock.Unlock() } } }
func game(msg tbotapi.Message, api *tbotapi.TelegramBotAPI) { if hasExpect(msg.From.ID) { reply(msg, api, msgAlreadyIngame) return } if msg.Chat.IsPrivateChat() { reply(msg, api, "You will play against the bot. "+msgChoose) eChan := make(chan choice) expectsLock.Lock() expects[msg.From.ID] = eChan expectsLock.Unlock() go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, expected chan choice) { choice := <-eChan botChoice := rand.Float64() var resp string if botChoice < (float64(1) / float64(3)) { resp = formatResponse("the bot", "you", choiceRock, choice) } else if botChoice < (float64(2) / float64(3)) { resp = formatResponse("the bot", "you", choicePaper, choice) } else { resp = formatResponse("the bot", "you", choiceScissors, choice) } reply(original, api, resp) }(msg, api, eChan) } else { //group mode if !hasChat(msg.From.ID) { reply(msg, api, msgNoPrivateChat) return } if hasGroup(msg.Chat.ID) { reply(msg, api, "This group already has an open game.") return } messages := make(chan tbotapi.Message) groups[msg.Chat.ID] = messages reply(msg, api, msgGameOpened) go func(original tbotapi.Message, api *tbotapi.TelegramBotAPI, messages chan tbotapi.Message) { var p1, p2 chan choice var partner tbotapi.User loop: for { msg := <-messages if msg.Type() != tbotapi.TextMessage { continue } text := *msg.Text switch parseCommand(text) { case cmdJoin: if msg.From.ID == original.From.ID { reply(original, api, msgCreatorAlreadyInGame) } else { expectsLock.Lock() if _, ok := expects[original.From.ID]; ok { reply(msg, api, msgAlreadyIngameWillRemainOpen) expectsLock.Unlock() continue loop } if _, ok := expects[msg.From.ID]; ok { reply(msg, api, msgAlreadyIngameWillRemainOpen) expectsLock.Unlock() continue loop } if !hasChat(msg.From.ID) { reply(msg, api, msgNoPrivateChat) expectsLock.Unlock() continue loop } groupsLock.Lock() delete(groups, original.Chat.ID) groupsLock.Unlock() p1 = make(chan choice) expects[original.From.ID] = p1 p2 = make(chan choice) expects[msg.From.ID] = p2 expectsLock.Unlock() p1Chat := chats[original.From.ID] p2Chat := chats[msg.From.ID] partner = msg.From sendTo(p1Chat, api, msgChoose) sendTo(p2Chat, api, msgChoose) reply(original, api, msgGameStarted) break loop } case cmdAbort: if msg.From.ID == original.From.ID { groupsLock.Lock() delete(groups, original.Chat.ID) groupsLock.Unlock() reply(original, api, msgGameAborted) return } reply(original, api, msgOnlyCreatorCanAbort) } } // game running var choice1, choice2 choice nextloop: for { select { case choice1 = <-p1: if choice2 != "" { break nextloop } case choice2 = <-p2: if choice1 != "" { break nextloop } } } resp := formatResponse(original.From.String(), partner.String(), choice1, choice2) reply(original, api, resp) }(msg, api, messages) } }