From 0cf9b9a101eaae74a0fb8d5c73e8a157957aa055 Mon Sep 17 00:00:00 2001 From: Ian Byrd Date: Tue, 21 Nov 2017 03:50:44 +0200 Subject: [PATCH] Routing: Handle() and Endpoint introduced. --- bot.go | 37 +++++++++++++++++++++----- handle.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ poller.go | 2 +- telebot.go | 15 +++++++++++ 4 files changed, 123 insertions(+), 7 deletions(-) create mode 100644 handle.go diff --git a/bot.go b/bot.go index a2170f3..8bcbc32 100644 --- a/bot.go +++ b/bot.go @@ -5,14 +5,13 @@ import ( "fmt" "strconv" - "github.com/armon/go-radix" "github.com/pkg/errors" ) // Bot represents a separate Telegram bot instance. type Bot struct { - Token string - Identity *User + Token string + Me *User Updates chan Update Messages chan Message @@ -23,7 +22,10 @@ type Bot struct { // will use it to report all occuring errors. Errors chan error - tree *radix.Tree + // Poller is the update provider. + Poller Poller + + handlers map[string]interface{} } // NewBot does try to build a Bot with token `token`, which @@ -36,7 +38,9 @@ func NewBot(pref Settings) (*Bot, error) { bot := &Bot{ Token: pref.Token, Updates: make(chan Update, pref.Updates), - tree: radix.New(), + Poller: pref.Poller, + + handlers: make(map[string]interface{}), } if pref.Messages != 0 { @@ -56,7 +60,7 @@ func NewBot(pref Settings) (*Bot, error) { return nil, err } - bot.Identity = user + bot.Me = user return bot, nil } @@ -95,9 +99,30 @@ type Update struct { // Start brings bot into motion by consuming incoming // updates (see Bot.Updates channel). func (b *Bot) Start() { + if b.Poller == nil { + panic("telebot: can't start without a poller") + } + + go b.Poller.Poll(b, b.Updates) + + if b.Messages != nil { + go b.handleMessages(b.Messages) + } + + if b.Queries != nil { + go b.handleQueries(b.Queries) + } + + if b.Callbacks != nil { + go b.handleCallbacks(b.Callbacks) + } + + fmt.Println("start ranging...") for upd := range b.Updates { + fmt.Println(upd) if b.Messages != nil { if upd.Message != nil { + fmt.Println("receiving 1:", upd.Message.Text) b.Messages <- *upd.Message continue } diff --git a/handle.go b/handle.go new file mode 100644 index 0000000..71d2e4d --- /dev/null +++ b/handle.go @@ -0,0 +1,76 @@ +package telebot + +import ( + "regexp" + "strings" +) + +// Handle lets you set the handler for some command name or +// one of the supported endpoints. +// +// See Endpoint. +func (b *Bot) Handle(endpoint, handler interface{}) { + if cmd, ok := endpoint.(string); ok { + b.handlers[cmd] = handler + + } else if end, ok := endpoint.(Endpoint); ok { + b.handlers[string(end)] = handler + + } else { + panic("Handle() only supports patterns and endpoints") + } +} + +var cmdRx = regexp.MustCompile(`^\/(\w+)(@(\w+))?`) + +func (b *Bot) handleMessages(messages chan Message) { + for m := range messages { + // Text message + if m.Text != "" { + match := cmdRx.FindAllStringSubmatch(m.Text, -1) + + // Command found + if match != nil { + if b.handleCommand(&m, match[0][1], match[0][3]) { + continue + } + } + + // Feeding it to OnMessage if one exists. + if handler, ok := b.handlers[string(OnMessage)]; ok { + if handler, ok := handler.(func(*Message)); ok { + go handler(&m) + continue + } + } + } + } +} + +func (b *Bot) handleCommand(m *Message, cmdName, cmdBot string) bool { + // Group-syntax: "/cmd@bot" + if cmdBot != "" && !strings.EqualFold(b.Me.Username, cmdBot) { + return false + } + + if handler, ok := b.handlers[cmdName]; ok { + if handler, ok := handler.(func(*Message)); ok { + go handler(m) + return true + } + } + + return false +} + +func (b *Bot) handleQueries(queries chan Query) { + for _ = range queries { + + } +} + +func (b *Bot) handleCallbacks(callbacks chan Callback) { + for _ = range callbacks { + + } +} diff --git a/poller.go b/poller.go index 03904f8..ee3ed1c 100644 --- a/poller.go +++ b/poller.go @@ -10,7 +10,7 @@ import ( // // All pollers must implement Poll(), which accepts bot // pointer and subscription channel and start polling -// asynchronously straight away. +// synchronously straight away. type Poller interface { // Poll is supposed to take the bot object // subscription channel and start polling diff --git a/telebot.go b/telebot.go index 1ef8361..ae625bf 100644 --- a/telebot.go +++ b/telebot.go @@ -27,6 +27,21 @@ // package telebot +// Endpoint is one of the possible events Handle() can deal with. +// +// For convenience, all Telebot-provided endpoints start with +// an "alert" character \a. +type Endpoint string + +const ( + OnMessage Endpoint = "\amessage" + OnEditedMessage Endpoint = "\aedited_msg" + OnQuery Endpoint = "\aquery" + OnCallback Endpoint = "\acallback" + OnChannelPost Endpoint = "\achan_post" + OnEditedChannelPost Endpoint = "\achan_post" +) + // ChatAction is a client-side status indicating bot activity. type ChatAction string