diff --git a/examples/command_handler/main.go b/examples/command_handler/main.go new file mode 100644 index 0000000..48884e8 --- /dev/null +++ b/examples/command_handler/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "context" + "os" + "os/signal" + + "github.com/go-telegram/bot" + "github.com/go-telegram/bot/models" +) + +// Send any text message to the bot after the bot has been started + +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt) + defer cancel() + + opts := []bot.Option{ + bot.WithDefaultHandler(defaultHandler), + } + + b, err := bot.New(os.Getenv("EXAMPLE_TELEGRAM_BOT_TOKEN"), opts...) + if nil != err { + // panics for the sake of simplicity. + // you should handle this error properly in your code. + panic(err) + } + + b.RegisterHandler(bot.HandlerTypeMessageText, "foo", bot.MatchTypeCommand, fooHandler) + b.RegisterHandler(bot.HandlerTypeMessageText, "bar", bot.MatchTypeCommandStartOnly, barHandler) + + b.Start(ctx) +} + +func fooHandler(ctx context.Context, b *bot.Bot, update *models.Update) { + b.SendMessage(ctx, &bot.SendMessageParams{ + ChatID: update.Message.Chat.ID, + Text: "Caught *foo*", + ParseMode: models.ParseModeMarkdown, + }) +} + +func barHandler(ctx context.Context, b *bot.Bot, update *models.Update) { + b.SendMessage(ctx, &bot.SendMessageParams{ + ChatID: update.Message.Chat.ID, + Text: "Caught *bar*", + ParseMode: models.ParseModeMarkdown, + }) +} + +func defaultHandler(ctx context.Context, b *bot.Bot, update *models.Update) { + b.SendMessage(ctx, &bot.SendMessageParams{ + ChatID: update.Message.Chat.ID, + Text: "Say message with `/foo` anywhere or with `/bar` at start of the message", + ParseMode: models.ParseModeMarkdown, + }) +} diff --git a/handlers.go b/handlers.go index 9ed5bd2..8545781 100644 --- a/handlers.go +++ b/handlers.go @@ -22,6 +22,8 @@ const ( MatchTypeExact MatchType = iota MatchTypePrefix MatchTypeContains + MatchTypeCommand + MatchTypeCommandStartOnly matchTypeRegexp matchTypeFunc @@ -44,6 +46,7 @@ func (h handler) match(update *models.Update) bool { } var data string + var entities []models.MessageEntity switch h.handlerType { case HandlerTypeMessageText: @@ -51,6 +54,7 @@ func (h handler) match(update *models.Update) bool { return false } data = update.Message.Text + entities = update.Message.Entities case HandlerTypeCallbackQueryData: if update.CallbackQuery == nil { return false @@ -66,6 +70,7 @@ func (h handler) match(update *models.Update) bool { return false } data = update.Message.Caption + entities = update.Message.CaptionEntities } if h.matchType == MatchTypeExact { @@ -77,6 +82,24 @@ func (h handler) match(update *models.Update) bool { if h.matchType == MatchTypeContains { return strings.Contains(data, h.pattern) } + if h.matchType == MatchTypeCommand { + for _, e := range entities { + if e.Type == models.MessageEntityTypeBotCommand { + if data[e.Offset+1:e.Offset+e.Length] == h.pattern { + return true + } + } + } + } + if h.matchType == MatchTypeCommandStartOnly { + for _, e := range entities { + if e.Type == models.MessageEntityTypeBotCommand { + if e.Offset == 0 && data[e.Offset+1:e.Offset+e.Length] == h.pattern { + return true + } + } + } + } if h.matchType == matchTypeRegexp { return h.re.Match([]byte(data)) } diff --git a/handlers_test.go b/handlers_test.go index 18e2d85..4a48df3 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -196,3 +196,137 @@ func Test_match_exact_game(t *testing.T) { t.Error("unexpected true result") } } + +func Test_match_command_start(t *testing.T) { + t.Run("anywhere 1, yes", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommand, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "/foo", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 0, Length: 4}, + }, + }, + } + + res := h.match(&u) + if !res { + t.Error("unexpected result") + } + }) + + t.Run("anywhere 2, yes", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommand, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "a /foo", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 2, Length: 4}, + }, + }, + } + + res := h.match(&u) + if !res { + t.Error("unexpected result") + } + }) + + t.Run("anywhere 3, no", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommand, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "a /bar", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 2, Length: 4}, + }, + }, + } + + res := h.match(&u) + if res { + t.Error("unexpected result") + } + }) + + t.Run("start 1, yes", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommandStartOnly, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "/foo", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 0, Length: 4}, + }, + }, + } + + res := h.match(&u) + if !res { + t.Error("unexpected result") + } + }) + + t.Run("start 2, no", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommandStartOnly, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "a /foo", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 2, Length: 4}, + }, + }, + } + + res := h.match(&u) + if res { + t.Error("unexpected result") + } + }) + + t.Run("start 3, no", func(t *testing.T) { + b := &Bot{} + + id := b.RegisterHandler(HandlerTypeMessageText, "foo", MatchTypeCommandStartOnly, nil) + + h := findHandler(b, id) + u := models.Update{ + ID: 42, + Message: &models.Message{ + Text: "/bar", + Entities: []models.MessageEntity{ + {Type: models.MessageEntityTypeBotCommand, Offset: 2, Length: 4}, + }, + }, + } + + res := h.match(&u) + if res { + t.Error("unexpected result") + } + }) +}