Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes markdown parse error #127 #128

Merged
merged 5 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions app/events/telegram.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -245,16 +246,11 @@ func (l *TelegramListener) sendBotResponse(resp bot.Response, chatID int64) erro
}

log.Printf("[DEBUG] bot response - %+v, pin: %t, reply-to:%d, parse-mode:%s", resp.Text, resp.Pin, resp.ReplyTo, resp.ParseMode)
tbMsg := tbapi.NewMessage(chatID, resp.Text)
tbMsg.ParseMode = tbapi.ModeMarkdown
if resp.ParseMode != "" {
tbMsg.ParseMode = resp.ParseMode
}
tbMsg.DisableWebPagePreview = !resp.Preview
tbMsg.ReplyToMessageID = resp.ReplyTo
res, err := l.TbAPI.Send(tbMsg)

res, err := l.sendMdWithFallback(resp, chatID)

if err != nil {
return fmt.Errorf("can't send message to telegram %q: %w", resp.Text, err)
return err
}

l.saveBotMessage(&res, chatID)
Expand All @@ -276,6 +272,33 @@ func (l *TelegramListener) sendBotResponse(resp bot.Response, chatID int64) erro
return nil
}

// sendMdWithFallback sends message with markdown mode and fallback to plain text
func (l *TelegramListener) sendMdWithFallback(resp bot.Response, chatID int64) (tbapi.Message, error) {
log.Printf("[DEBUG] sending message to telegram")
tbMsg := tbapi.NewMessage(chatID, resp.Text)
tbMsg.ParseMode = tbapi.ModeMarkdown
if resp.ParseMode != "" {
tbMsg.ParseMode = resp.ParseMode
paskal marked this conversation as resolved.
Show resolved Hide resolved
}
tbMsg.DisableWebPagePreview = !resp.Preview
tbMsg.ReplyToMessageID = resp.ReplyTo
res, err := l.TbAPI.Send(tbMsg)

if err != nil {
// If it can't parse entities, try to send message as plain text
if tbMsg.ParseMode == tbapi.ModeMarkdown && strings.Contains(err.Error(), "Bad Request: can't parse entities:") {
log.Printf("[WARN] failed to send message as markdown, retrying as plain text. Error: %v", err)
tbMsg.ParseMode = ""
res, err = l.TbAPI.Send(tbMsg)
}
if err != nil {
return res, fmt.Errorf("can't send message to telegram %q: %w", resp.Text, err)
}
}

return res, nil
}

// bans user or a channel
func (l *TelegramListener) applyBan(msg bot.Message, duration time.Duration, chatID, userID int64) error {
mention := "@" + msg.From.Username
Expand Down
54 changes: 54 additions & 0 deletions app/events/telegram_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package events

import (
"context"
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -860,3 +861,56 @@ func TestTelegram_transformEntities(t *testing.T) {
),
)
}

func TestSendMdWithFallback_SuccessMarkdown(t *testing.T) {
mockAPI := &tbAPIMock{
SendFunc: func(c tbapi.Chattable) (tbapi.Message, error) {
return tbapi.Message{Text: c.(tbapi.MessageConfig).Text}, nil
},
}

l := TelegramListener{TbAPI: mockAPI}

resp := bot.Response{Text: "Hello, world!", ParseMode: tbapi.ModeMarkdown}
_, err := l.sendMdWithFallback(resp, 123456)

assert.NoError(t, err)
assert.Equal(t, 1, len(mockAPI.SendCalls()))
assert.Equal(t, tbapi.ModeMarkdown, mockAPI.SendCalls()[0].C.(tbapi.MessageConfig).ParseMode)
}

func TestSendMdWithFallback_FallbackToPlainText(t *testing.T) {
mockAPI := &tbAPIMock{
SendFunc: func(c tbapi.Chattable) (tbapi.Message, error) {
if c.(tbapi.MessageConfig).ParseMode == tbapi.ModeMarkdown {
return tbapi.Message{}, fmt.Errorf("Bad Request: can't parse entities:")
}
return tbapi.Message{Text: c.(tbapi.MessageConfig).Text}, nil
},
}

l := TelegramListener{TbAPI: mockAPI}

resp := bot.Response{Text: "Hello, world!", ParseMode: tbapi.ModeMarkdown}
_, err := l.sendMdWithFallback(resp, 123456)

assert.NoError(t, err)
assert.Equal(t, 2, len(mockAPI.SendCalls()))
assert.Equal(t, "", mockAPI.SendCalls()[1].C.(tbapi.MessageConfig).ParseMode)
}

func TestSendMdWithFallback_ErrorMarkdownAndPlainText(t *testing.T) {
mockAPI := &tbAPIMock{
SendFunc: func(c tbapi.Chattable) (tbapi.Message, error) {
return tbapi.Message{}, fmt.Errorf("Bad Request: can't parse entities:")
},
}

l := TelegramListener{TbAPI: mockAPI}

resp := bot.Response{Text: "Hello, world!", ParseMode: tbapi.ModeMarkdown}
_, err := l.sendMdWithFallback(resp, 123456)

assert.Error(t, err)
assert.Equal(t, 2, len(mockAPI.SendCalls()))
}
Loading