// Fantasy World Zookeeper Bot // Copyright (c) 2018 Vladimir "fat0troll" Hodakov package router import ( "errors" "regexp" "strconv" "strings" "gitlab.com/toby3d/telegram" ) var ( // acceptingForwardsFrom defines list of users which messages can be used as // forwarded // In case of this bot, this is @FWorldBot acceptingForwardsFrom = []int{} ) func checkForward(update *telegram.Update) error { if update.Message.ForwardFrom != nil { log.Debug().Msgf("Processing forward from Telegram ID = %d", update.Message.ForwardFrom.ID) for i := range acceptingForwardsFrom { if acceptingForwardsFrom[i] == update.Message.ForwardFrom.ID { return nil } } } return errors.New("Can't handle forward from Telegram user with ID =" + strconv.Itoa(update.Message.ForwardFrom.ID)) } func handleInlineQuery(update *telegram.Update) { rxpMatched := false for rxp, function := range router.inlineQueries { if rxp.MatchString(update.InlineQuery.Query) { if rxpMatched { log.Warn().Msgf("The message handled more than once: %s, %s", update.InlineQuery.Query, strings.Replace(rxp.String(), "\n", "\\n", -1)) } else { rxpMatched = true function(update) } } } if !rxpMatched { log.Debug().Msgf("There is no handler for inline: %s", update.InlineQuery.Query) } } func handleRequest(update *telegram.Update, commands map[string]func(*telegram.Update), rxps map[*regexp.Regexp]func(*telegram.Update)) { switch { case update.Message.IsCommand(): if commands[update.Message.Command()] != nil { commands[update.Message.Command()](update) } else { log.Warn().Msgf("There is no handler for command /%s", update.Message.Command()) } default: rxpMatched := false for rxp, function := range rxps { if rxp.MatchString(update.Message.Text) { if rxpMatched { log.Warn().Msgf("The message handled more than once: %s, %s", update.Message.Text, strings.Replace(rxp.String(), "\n", "\\n", -1)) } else { rxpMatched = true function(update) } } } if !rxpMatched { log.Debug().Msgf("There is no handler for message: %s", update.Message.Text) } } } func handleGroupRequest(update *telegram.Update) { handleRequest(update, router.groupCommands, router.groupRegulars) } func handlePrivateRequest(update *telegram.Update) { handleRequest(update, router.privateCommands, router.privateRegulars) } // RegisterPrivateCommand adds function to private commands list func RegisterPrivateCommand(command string, handleFunc func(update *telegram.Update)) { log.Debug().Msgf("Registering handler for private command /%s", command) router.privateCommands[command] = handleFunc } // RegisterPrivateRegexp adds function to private regexp list func RegisterPrivateRegexp(rxp *regexp.Regexp, handleFunc func(update *telegram.Update)) { log.Debug().Msgf("Registering handler for regular expresson: %s", strings.Replace(rxp.String(), "\n", "\\n", -1)) router.privateRegulars[rxp] = handleFunc } // RegisterGroupCommand adds function to group commands list func RegisterGroupCommand(command string, handleFunc func(update *telegram.Update)) { log.Debug().Msgf("Registering handler for group command /%s", command) router.groupCommands[command] = handleFunc } // RegisterGroupRegexp adds function to group regexp list func RegisterGroupRegexp(rxp *regexp.Regexp, handleFunc func(update *telegram.Update)) { log.Debug().Msgf("Registering handler for regular expresson: %s", strings.Replace(rxp.String(), "\n", "\\n", -1)) router.groupRegulars[rxp] = handleFunc } // RegisterInlineQueryResult adds function to list of inline queries func RegisterInlineQueryResult(rxp *regexp.Regexp, handleFunc func(update *telegram.Update)) { log.Debug().Msgf("Registering handler for inline regular expresson: %s", strings.Replace(rxp.String(), "\n", "\\n", -1)) router.inlineQueries[rxp] = handleFunc } // Respond searches for appropriative answer to the request and passes request to found function // If none of the functions can handle this request, it will be warned in log file func Respond(update telegram.Update) { switch { case update.Message != nil: if update.Message.Text != "" { if update.Message.ForwardFrom != nil { err := checkForward(&update) if err != nil { log.Warn().Err(err) return } } if update.Message.Chat.IsPrivate() { handlePrivateRequest(&update) } else if update.Message.Chat.IsGroup() || update.Message.Chat.IsSuperGroup() { handleGroupRequest(&update) } else { log.Debug().Msg("Can't handle update") } } else { log.Debug().Msg("Can't handle empty Message for now") } case update.InlineQuery != nil: if update.InlineQuery.Query != "" { handleInlineQuery(&update) } default: log.Debug().Msg("Can't handle empty Message for now") } }