Skip to content

Commit

Permalink
Merge pull request #40 from LucaBernstein/39-suggestions-space-handling
Browse files Browse the repository at this point in the history
Handle spaces in suggestion handler
  • Loading branch information
LucaBernstein authored Nov 28, 2021
2 parents 4c82da7 + 66a0b8d commit 3f8903b
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 23 deletions.
60 changes: 41 additions & 19 deletions bot/suggestions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,44 @@ package bot

import (
"fmt"
"log"
"strings"

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

func (bc *BotController) suggestionsHandler(m *tb.Message) {
// splits[0] is the command
splits := strings.Split(m.Text, " ")
var (
command string
subcommand string
suggType string
value string
)
if len(splits) <= 2 { // at least subcommand + type
bc.suggestionsHelp(m)
return
}
if len(splits) >= 3 {
subcommand = splits[1]
suggType = splits[2]
}
if len(splits) >= 4 {
value = splits[3]
command = m.Text
if strings.Contains(m.Text, "\"") {
// Assume quoted value, e.g. '/sugg rm type "some value with spaces"'
splits := strings.Split(m.Text, "\"")

command = splits[0]
value = splits[1]
}
if len(splits) >= 5 {
bc.suggestionsHelp(m)

splits := strings.Split(strings.TrimSpace(command), " ")
if len(splits) != 3 { // at least command + subcommand + type
bc.suggestionsHelp(m, nil)
return
}

subcommand = splits[1]
suggType = splits[2]

if len(splits) == 4 { // exactly 4 splits mean unspaced value. Remove quotes to make sure.
value = strings.Trim(splits[3], "\"")
}

if !h.ArrayContainsC(h.AllowedSuggestionTypes(), suggType, false) {
bc.suggestionsHelp(m)
bc.suggestionsHelp(m, fmt.Errorf("unexpected subcommand"))
return
}

Expand All @@ -45,13 +51,18 @@ func (bc *BotController) suggestionsHandler(m *tb.Message) {
case "rm":
bc.suggestionsHandleRemove(m, suggType, value)
default:
bc.suggestionsHelp(m)
bc.suggestionsHelp(m, nil)
return
}
}

func (bc *BotController) suggestionsHelp(m *tb.Message) {
func (bc *BotController) suggestionsHelp(m *tb.Message, err error) {
suggestionTypes := strings.Join(h.AllowedSuggestionTypes(), ", ")
bc.Bot.Send(m.Sender, fmt.Sprintf(`Usage help for /suggestions:
errorMsg := ""
if err != nil {
errorMsg += fmt.Sprintf("Error executing your command: %s\n\n", err.Error())
}
bc.Bot.Send(m.Sender, errorMsg+fmt.Sprintf(`Usage help for /suggestions:
/suggestions list <type>
/suggestions add <type> <value>
/suggestions rm <type> [value]
Expand Down Expand Up @@ -87,10 +98,21 @@ func (bc *BotController) suggestionsHandleAdd(m *tb.Message, t string, value str
}

func (bc *BotController) suggestionsHandleRemove(m *tb.Message, t string, value string) {
err := bc.Repo.DeleteCacheEntries(m, t, value)
log.Printf("(C%d): About to remove suggestion of type '%s' and value '%s'", m.Chat.ID, t, value)
res, err := bc.Repo.DeleteCacheEntries(m, t, value)
if err != nil {
bc.Bot.Send(m.Sender, "Error encountered while removing suggestion: "+err.Error())
return
}
rowCount, err := res.RowsAffected()
if err != nil {
bc.Bot.Send(m.Sender, "Error encountered while extracting affected entries: "+err.Error())
return
}
if rowCount == 0 {
bc.suggestionsHelp(m, fmt.Errorf("entry could not be found in the database. "+
"If your value contains spaces, consider putting it in double quotes (\")"))
return
}
bc.Bot.Send(m.Sender, "Successfully removed suggestion(s)")
}
64 changes: 64 additions & 0 deletions bot/suggestions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package bot

import (
"fmt"
"log"
"strings"
"testing"

"github.com/DATA-DOG/go-sqlmock"
tb "gopkg.in/tucnak/telebot.v2"
)

func TestSuggestionsHandlingWithSpaces(t *testing.T) {
// Test dependencies
chat := &tb.Chat{ID: 12345}
db, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}
mock.
ExpectExec(`DELETE FROM "bot::cache"`).
WithArgs(12345, "txDesc", "Some description with spaces").
WillReturnResult(sqlmock.NewResult(1, 1))
mock.
ExpectExec(`DELETE FROM "bot::cache"`).
WithArgs(12345, "txDesc", "SomeDescriptionWithoutSpaces").
WillReturnResult(sqlmock.NewResult(1, 1))

bc := NewBotController(db)

bot := &MockBot{}
bc.ConfigureAndAttachBot(bot)

// missing subcommand
bc.commandSuggestions(&tb.Message{Text: "/suggestions", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help") {
t.Errorf("MissingType: Bot unexpectedly did not send usage help: %s", bot.LastSentWhat)
}

// missing type
bc.commandSuggestions(&tb.Message{Text: "/suggestions rm", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help") {
t.Errorf("MissingType: Bot unexpectedly did not send usage help: %s", bot.LastSentWhat)
}

bc.commandSuggestions(&tb.Message{Text: "/suggestions rm txDesc Too Many arguments with spaces", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help") {
t.Errorf("TooManyArgs: Bot unexpectedly did not send usage help: %s", bot.LastSentWhat)
}

bc.commandSuggestions(&tb.Message{Text: "/suggestions rm txDesc \"Some description with spaces\"", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help") {
t.Errorf("Spaced: Bot unexpectedly sent usage help instead of performing command: %s", bot.LastSentWhat)
}

bc.commandSuggestions(&tb.Message{Text: "/suggestions rm txDesc \"SomeDescriptionWithoutSpaces\"", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help") {
t.Errorf("NotSpaced: Bot unexpectedly sent usage help instead of performing command: %s", bot.LastSentWhat)
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}
9 changes: 5 additions & 4 deletions db/crud/bot_cache.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package crud

import (
"database/sql"
"log"

"github.com/LucaBernstein/beancount-bot-tg/helpers"
Expand Down Expand Up @@ -92,7 +93,7 @@ func (r *Repo) DeleteCache(m *tb.Message) {
delete(CACHE_LOCAL, m.Chat.ID)
}

func (r *Repo) DeleteCacheEntries(m *tb.Message, t string, value string) error {
func (r *Repo) DeleteCacheEntries(m *tb.Message, t string, value string) (sql.Result, error) {
// if value is empty string, delete all entries for this user of this type
q := `
DELETE FROM "bot::cache"
Expand All @@ -103,9 +104,9 @@ func (r *Repo) DeleteCacheEntries(m *tb.Message, t string, value string) error {
q += ` AND "value" = $3`
params = append(params, value)
}
_, err := r.db.Exec(q, params...)
res, err := r.db.Exec(q, params...)
if err != nil {
return err
return nil, err
}
return r.FillCache(m)
return res, r.FillCache(m)
}

0 comments on commit 3f8903b

Please sign in to comment.