diff --git a/bot.go b/bot.go index 911756c..9eaad74 100644 --- a/bot.go +++ b/bot.go @@ -7,7 +7,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/technoweenie/multipartstreamer" "io/ioutil" "log" "net/http" @@ -16,14 +15,20 @@ import ( "strconv" "strings" "time" + + "github.com/technoweenie/multipartstreamer" ) // BotAPI allows you to interact with the Telegram Bot API. type BotAPI struct { - Token string `json:"token"` - Debug bool `json:"debug"` - Self User `json:"-"` - Client *http.Client `json:"-"` + Token string `json:"token"` + Debug bool `json:"debug"` + Self User `json:"-"` + Client *http.Client `json:"-"` + CommandHandlers map[string]MessageHandlerFunc + TextHandler MessageHandlerFunc + InlineHandler InlineHandlerFunc + InlineResultHandler InlineResultHandlerFunc } // NewBotAPI creates a new BotAPI instance. @@ -39,8 +44,9 @@ func NewBotAPI(token string) (*BotAPI, error) { // It requires a token, provided by @BotFather on Telegram. func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) { bot := &BotAPI{ - Token: token, - Client: client, + Token: token, + Client: client, + CommandHandlers: map[string]MessageHandlerFunc{}, } self, err := bot.GetMe() @@ -53,6 +59,71 @@ func NewBotAPIWithClient(token string, client *http.Client) (*BotAPI, error) { return bot, nil } +// ProcessUpdate calls corresponding handler for update +func (bot *BotAPI) ProcessUpdate(update Update) { + if update.IsMessage() { + msg := update.Message + if msg.IsCommand() { + cmd := msg.Command() + if f, ok := bot.CommandHandlers[cmd]; ok { + f.Serve(bot, msg) + } else { + log.Fatal("No handler defined for: " + cmd) + } + } else { + if f := bot.TextHandler; f != nil { + f.Serve(bot, msg) + } else { + log.Fatal("No Text Handler defined") + } + } + } else if update.IsInlineQuery() { + query := update.InlineQuery + if f := bot.InlineHandler; f != nil { + f.Serve(bot, query) + } else { + log.Fatal("No Inline Query Handler defined") + } + } else if update.IsChosenInlineResult() { + rt := update.ChosenInlineResult + if f := bot.InlineResultHandler; f != nil { + f.Serve(bot, rt) + } else { + log.Fatal("No Inline Result Handler defined") + } + } else { + log.Printf("Invalid Update") + } +} + +// AddCommandHandler adds a MessageHandlerFunc for commands +// +// +func (bot *BotAPI) AddCommandHandler(cmd string, f MessageHandlerFunc) { + bot.CommandHandlers[cmd] = f +} + +// AddTextHandler adds a MessageHandlerFunc for non-commands +// +// +func (bot *BotAPI) AddTextHandler(f MessageHandlerFunc) { + bot.TextHandler = f +} + +// AddInlineHandler adds a InlineHandlerFunc for inline querys +// +// +func (bot *BotAPI) AddInlineHandler(f InlineHandlerFunc) { + bot.InlineHandler = f +} + +// AddInlineResultHandler adds a InlineResultHandlerFunc for chosen inline result +// +// +func (bot *BotAPI) AddInlineResultHandler(f InlineResultHandlerFunc) { + bot.InlineResultHandler = f +} + // MakeRequest makes a request to a specific endpoint with our token. func (bot *BotAPI) MakeRequest(endpoint string, params url.Values) (APIResponse, error) { method := fmt.Sprintf(APIEndpoint, bot.Token, endpoint) diff --git a/types.go b/types.go index ef16c10..430bea3 100644 --- a/types.go +++ b/types.go @@ -24,6 +24,30 @@ type Update struct { ChosenInlineResult ChosenInlineResult `json:"chosen_inline_result"` } +// Checks if Update is InlineQuery +func (u Update) IsInlineQuery() bool { + if u.InlineQuery.ID != "" { + return true + } + return false +} + +// Checks if Update is Message +func (u Update) IsMessage() bool { + if u.Message.MessageID != 0 { + return true + } + return false +} + +// Checks if Update is ChosenInlineResult +func (u Update) IsChosenInlineResult() bool { + if u.ChosenInlineResult.ResultID != "" { + return true + } + return false +} + // User is a user on Telegram. type User struct { ID int `json:"id"` @@ -135,7 +159,6 @@ func (m *Message) Command() string { if !m.IsCommand() { return "" } - command := strings.SplitN(m.Text, " ", 2)[0][1:] if i := strings.Index(command, "@"); i != -1 { @@ -366,3 +389,27 @@ type ChosenInlineResult struct { From User `json:"from"` Query string `json:"query"` } + +// MessageHandlerFunc for handling Messages +// Something similar in line to http.HandlerFunc +type MessageHandlerFunc func(*BotAPI, Message) + +func (f MessageHandlerFunc) Serve(bot *BotAPI, msg Message) { + f(bot, msg) +} + +// InlineHandlerFunc for handling Inline Query +// Something similar in line to http.HandlerFunc +type InlineHandlerFunc func(*BotAPI, InlineQuery) + +func (f InlineHandlerFunc) Serve(bot *BotAPI, q InlineQuery) { + f(bot, q) +} + +// InlineResultHandlerFunc for handling Inline Query +// Something similar in line to http.HandlerFunc +type InlineResultHandlerFunc func(*BotAPI, ChosenInlineResult) + +func (f InlineResultHandlerFunc) Serve(bot *BotAPI, q ChosenInlineResult) { + f(bot, q) +}