Skip to content

Commit

Permalink
Merge pull request #66 from LucaBernstein/message-max-length
Browse files Browse the repository at this point in the history
Limit list messages in length
  • Loading branch information
LucaBernstein authored Dec 18, 2021
2 parents 77532d4 + 3981baf commit 4830bca
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 12 deletions.
25 changes: 23 additions & 2 deletions bot/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,36 @@ func (bc *BotController) commandList(m *tb.Message) {
}
return
}
if tx == "" {
if tx == nil {
bc.Logf(ERROR, m, "Tx unexpectedly was nil")
return
}
SEP := "\n"
TG_MAX_MSG_CHAR_LEN := 4096
txMessages := []string{}
transactionsList := ""
for _, t := range tx {
if len(transactionsList)+len(t) >= TG_MAX_MSG_CHAR_LEN {
bc.Logf(TRACE, m, "Listed messages extend max message length. Splitting into multiple messages.")
txMessages = append(txMessages, transactionsList)
transactionsList = ""
}
transactionsList += t + SEP
}
if transactionsList != "" {
txMessages = append(txMessages, transactionsList)
}
if len(txMessages) == 0 {
_, err := bc.Bot.Send(m.Sender, fmt.Sprintf("Your transaction list is empty. Create some first. Check /%s for commands to create a transaction."+
"\nYou might also be looking for archived transactions using '/list archived'.", CMD_HELP), clearKeyboard())
if err != nil {
bc.Logf(ERROR, m, "Sending bot message failed: %s", err.Error())
}
return
}
_, err = bc.Bot.Send(m.Sender, tx, clearKeyboard())
for _, message := range txMessages {
_, err = bc.Bot.Send(m.Sender, message, clearKeyboard())
}
if err != nil {
bc.Logf(ERROR, m, "Sending bot message failed: %s", err.Error())
}
Expand Down
62 changes: 61 additions & 1 deletion bot/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,28 @@ import (
tb "gopkg.in/tucnak/telebot.v2"

"github.com/DATA-DOG/go-sqlmock"
"github.com/LucaBernstein/beancount-bot-tg/db/crud"
"github.com/LucaBernstein/beancount-bot-tg/helpers"
)

type MockBot struct {
LastSentWhat interface{}
LastSentWhat interface{}
AllLastSentWhat []interface{}
}

func (b *MockBot) Start() {}
func (b *MockBot) Handle(endpoint interface{}, handler interface{}) {}
func (b *MockBot) Send(to tb.Recipient, what interface{}, options ...interface{}) (*tb.Message, error) {
b.LastSentWhat = what
b.AllLastSentWhat = append(b.AllLastSentWhat, what)
return nil, nil
}
func (b *MockBot) Me() *tb.User {
return &tb.User{Username: "Test bot"}
}
func (b *MockBot) reset() {
b.AllLastSentWhat = nil
}

// GitHub-Issue #16: Panic if plain message without state arrives
func TestTextHandlingWithoutPriorState(t *testing.T) {
Expand Down Expand Up @@ -108,3 +114,57 @@ func TestTransactionDeletion(t *testing.T) {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestTransactionListMaxLength(t *testing.T) {
// create test dependencies
chat := &tb.Chat{ID: 12345}
db, mock, err := sqlmock.New()
crud.TEST_MODE = true
if err != nil {
log.Fatal(err)
}
mock.
ExpectQuery(`SELECT "value" FROM "bot::transaction"`).
WithArgs(chat.ID, false).
WillReturnRows(sqlmock.NewRows([]string{"value"}).AddRow(strings.Repeat("**********", 100)).AddRow(strings.Repeat("**********", 100))) // 1000 + 1000
mock.
ExpectQuery(`SELECT "value" FROM "bot::transaction"`).
WithArgs(chat.ID, false).
WillReturnRows(sqlmock.NewRows([]string{"value"}).
// 5 * 1000
AddRow(strings.Repeat("**********", 100)).
AddRow(strings.Repeat("**********", 100)).
AddRow(strings.Repeat("**********", 100)).
AddRow(strings.Repeat("**********", 100)).
AddRow(strings.Repeat("**********", 100)),
)

bc := NewBotController(db)
bot := &MockBot{}
bc.AddBotAndStart(bot)

// < 4096 chars tx
bc.commandList(&tb.Message{Chat: chat})
if len(bot.AllLastSentWhat) != 1 {
t.Errorf("Expected exactly one message to be sent out: %v", bot.AllLastSentWhat)
}

bot.reset()

// > 4096 chars tx
bc.commandList(&tb.Message{Chat: chat})
if len(bot.AllLastSentWhat) != 2 {
t.Errorf("Expected exactly two messages to be sent out: %v", strings.Join(stringArr(bot.AllLastSentWhat), ", "))
}
if bot.LastSentWhat != strings.Repeat("**********", 100)+"\n" {
t.Errorf("Expected last message to contain last transaction as it flowed over the first message: %v", bot.LastSentWhat)
}
}

func stringArr(i []interface{}) []string {
arr := []string{}
for _, e := range i {
arr = append(arr, fmt.Sprintf("%v", e))
}
return arr
}
11 changes: 5 additions & 6 deletions db/crud/bot_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,26 @@ func (r *Repo) RecordTransaction(chatId int64, tx string) error {
return err
}

func (r *Repo) GetTransactions(m *tb.Message, isArchived bool) (string, error) {
func (r *Repo) GetTransactions(m *tb.Message, isArchived bool) ([]string, error) {
LogDbf(r, helpers.TRACE, m, "Getting transactions")
rows, err := r.db.Query(`
SELECT "value" FROM "bot::transaction"
WHERE "tgChatId" = $1 AND "archived" = $2
ORDER BY "created" ASC
`, m.Chat.ID, isArchived)
if err != nil {
return "", err
return nil, err
}
defer rows.Close()

SEP := "\n"
allTransactionsMessage := ""
allTransactionsMessage := []string{}
var transactionString string
for rows.Next() {
err = rows.Scan(&transactionString)
if err != nil {
return "", err
return nil, err
}
allTransactionsMessage += transactionString + SEP
allTransactionsMessage = append(allTransactionsMessage, transactionString)
}
return allTransactionsMessage, nil
}
Expand Down
14 changes: 11 additions & 3 deletions db/crud/logger.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package crud

import (
"log"

"github.com/LucaBernstein/beancount-bot-tg/helpers"
tb "gopkg.in/tucnak/telebot.v2"
)

var TEST_MODE = false

func LogDbf(r *Repo, level helpers.Level, m *tb.Message, format string, v ...interface{}) {
prefix, message := helpers.LogLocalf(level, m, format, v...)
go logToDb(r, prefix, level, message)
Expand All @@ -17,8 +21,12 @@ func logToDb(r *Repo, chat string, level helpers.Level, message string) {
} else {
values = append(values, nil)
}
_, err := r.db.Exec(`INSERT INTO "app::log" ("level", "message", "chat") VALUES ($1, $2, $3)`, values...)
if err != nil {
helpers.LogLocalf(helpers.ERROR, nil, "Error inserting log statement into db: %s", err.Error())
if !TEST_MODE {
_, err := r.db.Exec(`INSERT INTO "app::log" ("level", "message", "chat") VALUES ($1, $2, $3)`, values...)
if err != nil {
helpers.LogLocalf(helpers.ERROR, nil, "Error inserting log statement into db: %s", err.Error())
}
} else {
log.Printf("DB LOGGER IS IN TEST MODE")
}
}

0 comments on commit 4830bca

Please sign in to comment.