Skip to content

Commit

Permalink
Fix command dispatcher not running hooks, and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
alufers committed Oct 8, 2023
1 parent b874d74 commit eb86562
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 79 deletions.
161 changes: 82 additions & 79 deletions tghelpers/command_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,96 +44,99 @@ func (d *CommandDispatcher) RunUpdateLoop() error {
ctx := context.Background()
for u := range updates {
// run command processing asynchronously
go func(u tgbotapi.Update) {
var cmdText string
args := &CommandArguments{
AskService: d.AskService,
Update: &u,
NamedArguments: map[string]string{},
}
if u.Message != nil {
cmdText = u.Message.Text
args.ChatID = u.Message.Chat.ID
args.FromUserID = u.Message.From.ID
}
if u.CallbackQuery != nil {
cmdText = u.CallbackQuery.Data
args.ChatID = u.CallbackQuery.Message.Chat.ID
args.FromUserID = u.CallbackQuery.From.ID
}
seg := strings.Split(cmdText, " ")
args.CommandName = seg[0]
args.Arguments = seg[1:]

ctx := context.WithValue(ctx, UpdateContextKey, u)
ctx = context.WithValue(ctx, ArgsContextKey, args)

// TODO: move this to a nice hook
if strings.HasSuffix(args.CommandName, "@har") {
ctx = httphelpers.WithHarLoggerStorage(ctx)
for _, hook := range d.UpdateHooks {
if hook.OnUpdate(ctx) {
return // hook has handled the message stop processing
}
}
}
go d.processIncomingUpdate(ctx, u)
}
return nil
}

var err error
func (d *CommandDispatcher) processIncomingUpdate(ctx context.Context, u tgbotapi.Update) {
var cmdText string
args := &CommandArguments{
AskService: d.AskService,
Update: &u,
NamedArguments: map[string]string{},
}
if u.Message != nil {
cmdText = u.Message.Text
args.ChatID = u.Message.Chat.ID
args.FromUserID = u.Message.From.ID
}
if u.CallbackQuery != nil {
cmdText = u.CallbackQuery.Data
args.ChatID = u.CallbackQuery.Message.Chat.ID
args.FromUserID = u.CallbackQuery.From.ID
}
seg := strings.Split(cmdText, " ")
args.CommandName = seg[0]
args.Arguments = seg[1:]

ctx = context.WithValue(ctx, UpdateContextKey, u)
ctx = context.WithValue(ctx, ArgsContextKey, args)

for _, cmd := range d.Commands {
if CommandMatches(cmd, cmdText) {
args.Command = cmd
for i, argTpl := range cmd.Arguments() {
if argTpl.Variadic {
args.NamedArguments[argTpl.Name] = strings.Join(args.Arguments[i:], " ")
break
}
if i >= len(args.Arguments) {
break
}
args.NamedArguments[argTpl.Name] = args.Arguments[i]
}
// TODO: move this to a nice hook
if strings.HasSuffix(args.CommandName, "@har") {
ctx = httphelpers.WithHarLoggerStorage(ctx)
}

for _, hook := range d.UpdateHooks {
if hook.OnUpdate(ctx) {
return // hook has handled the message stop processing
}
}

err = cmd.Execute(ctx)
var err error

for _, cmd := range d.Commands {
if CommandMatches(cmd, cmdText) {
args.Command = cmd
for i, argTpl := range cmd.Arguments() {
if argTpl.Variadic {
args.NamedArguments[argTpl.Name] = strings.Join(args.Arguments[i:], " ")
break
}
}

storage := httphelpers.GetHarLoggerStorage(ctx)

if storage != nil {

jsonData, err := storage.GetJSONData()
if err != nil {
log.Printf("Error while getting HAR data: %v", err)
} else {
sendDoc := tgbotapi.NewDocument(args.ChatID, tgbotapi.FileReader{
Name: "har.json",
Reader: strings.NewReader(string(jsonData)),
})
sendDoc.Caption = "HAR data"
_, err := d.BotAPI.Send(sendDoc)
if err != nil {
log.Printf("Error while sending HAR data: %v", err)
}
if i >= len(args.Arguments) {
break
}
args.NamedArguments[argTpl.Name] = args.Arguments[i]
}

err = cmd.Execute(ctx)

break
}
}

storage := httphelpers.GetHarLoggerStorage(ctx)

if storage != nil {

jsonData, err := storage.GetJSONData()
if err != nil {
log.Printf("Error while getting HAR data: %v", err)
} else {
sendDoc := tgbotapi.NewDocument(args.ChatID, tgbotapi.FileReader{
Name: "har.json",
Reader: strings.NewReader(string(jsonData)),
})
sendDoc.Caption = "HAR data"
_, err := d.BotAPI.Send(sendDoc)
if err != nil {
log.Printf("Error while processing command %v: %v", cmdText, err)
msg := tgbotapi.NewMessage(args.ChatID, "🚫 Error: <b>"+html.EscapeString(err.Error())+"</b>")
msg.ParseMode = "HTML"
if u.Message != nil {
msg.ReplyToMessageID = u.Message.MessageID
}
_, err := d.BotAPI.Send(msg)
if err != nil {
log.Printf("An error has occurred while sending an error message: %v", err)
}
log.Printf("Error while sending HAR data: %v", err)
}
}(u)
}
}
if err != nil {
log.Printf("Error while processing command %v: %v", cmdText, err)
msg := tgbotapi.NewMessage(args.ChatID, "🚫 Error: <b>"+html.EscapeString(err.Error())+"</b>")
msg.ParseMode = "HTML"
if u.Message != nil {
msg.ReplyToMessageID = u.Message.MessageID
}
_, err := d.BotAPI.Send(msg)
if err != nil {
log.Printf("An error has occurred while sending an error message: %v", err)
}
}
return nil
}

// RequestSetMyCommands registers the commands in the Telegram bot API.
Expand Down
45 changes: 45 additions & 0 deletions tghelpers/command_dispatcher_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package tghelpers

import (
"context"
"testing"

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)

type FakeUpdateHook struct {
didRun bool
}

func (h *FakeUpdateHook) OnUpdate(context.Context) bool {
h.didRun = true
return true
}

// a test that chcks if command dispatcher executes update hooks
func TestCommandDispatcherUpdateHooks(t *testing.T) {
botAPI := &MockBotApi{}
// create a fake command dispatcher
dispatcher := NewCommandDispatcher(botAPI, nil)

fh := &FakeUpdateHook{}
// register a fake update hook
dispatcher.RegisterUpdateHooks(fh)

dispatcher.processIncomingUpdate(context.Background(), tgbotapi.Update{
Message: &tgbotapi.Message{
Text: "test",
Chat: &tgbotapi.Chat{
ID: 123,
},
From: &tgbotapi.User{
ID: 456,
},
},
})

// check if the hook was run
if !fh.didRun {
t.Fatal("update hook was not run")
}
}

0 comments on commit eb86562

Please sign in to comment.