🐛 Fixed 'index exists' and 'not found' errors in requests to database

Just check this errors and return alternative data for stablity
This commit is contained in:
Maxim Lebedev 2017-11-20 19:31:21 +05:00
parent 168a243665
commit d8bc61cca5
No known key found for this signature in database
GPG Key ID: F8978F46FF0FFA4F
4 changed files with 102 additions and 60 deletions

View File

@ -8,14 +8,13 @@ import (
"github.com/toby3d/go-telegram" // My Telegram bindings
)
func commands(msg *telegram.Message) error {
func commands(msg *telegram.Message) {
log.Ln("[commands] Check command message")
var err error
switch strings.ToLower(msg.Command()) {
case "start":
log.Ln("[commands] Received a /start command")
// TODO: Reply by greetings message and add user to DB
_, _, err = dbChangeUserState(msg.From.ID, stateNone)
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
reply := telegram.NewMessage(
@ -23,9 +22,10 @@ func commands(msg *telegram.Message) error {
fmt.Sprint("Hello, ", msg.From.FirstName, "!"), // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
case "help":
log.Ln("[commands] Received a /help command")
_, _, err = dbChangeUserState(msg.From.ID, stateNone)
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
reply := telegram.NewMessage(
@ -39,9 +39,10 @@ func commands(msg *telegram.Message) error {
),
)
_, err = bot.SendMessage(reply)
errCheck(err)
case "addsticker":
log.Ln("[commands] Received a /addsticker command")
_, _, err = dbChangeUserState(msg.From.ID, stateAdding)
_, err := dbChangeUserState(msg.From.ID, stateAdding)
errCheck(err)
reply := telegram.NewMessage(
@ -49,9 +50,10 @@ func commands(msg *telegram.Message) error {
"Send me any sticker for adding them in your pack.", // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
case "delsticker":
log.Ln("[commands] Received a /delsticker command")
_, _, err = dbChangeUserState(msg.From.ID, stateDeleting)
_, err := dbChangeUserState(msg.From.ID, stateDeleting)
errCheck(err)
reply := telegram.NewMessage(
@ -59,9 +61,10 @@ func commands(msg *telegram.Message) error {
"Send me sticker from your pack for remove them.", // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
case "cancel":
log.Ln("[commands] Received a /cancel command")
prev, _, err := dbChangeUserState(msg.From.ID, stateNone)
prev, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
text := "What are you doing?!"
@ -79,10 +82,9 @@ func commands(msg *telegram.Message) error {
text, // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
default:
log.Ln("[commands] Received unsupported command")
// Do nothing because unsupported command
}
return err
}

View File

@ -2,6 +2,7 @@ package main
import (
"fmt"
"strconv"
"strings"
log "github.com/kirillDanshin/dlog" // Insert logs only in debug builds
@ -22,22 +23,29 @@ func dbInit() {
db, err = buntdb.Open("bot.db")
errCheck(err)
err = db.CreateIndex(
"user_stickers", // name
"user:*:sticker:*", // pattern
buntdb.IndexString, // options
)
errCheck(err)
select {}
}
func dbChangeUserState(userID int, state string) (string, bool, error) {
func dbChangeUserState(userID int, state string) (string, error) {
var prevState string
var changed bool
err := db.Update(func(tx *buntdb.Tx) error {
var err error
prevState, changed, err = tx.Set(
prevState, _, err = tx.Set(
fmt.Sprint("user:", userID, ":state"), // key
state, // val
nil, // options
)
return err
})
return prevState, changed, err
return prevState, err
}
func dbGetUserState(userID int) (string, error) {
@ -49,69 +57,75 @@ func dbGetUserState(userID int) (string, error) {
)
return err
})
switch err {
case buntdb.ErrNotFound:
state, err = dbChangeUserState(userID, stateNone)
}
return state, err
}
func dbAddSticker(userID int, fileID, emoji string) error {
if err := db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(
func dbAddSticker(userID int, fileID, emoji string) (bool, error) {
var exists bool
err := db.Update(func(tx *buntdb.Tx) error {
var err error
_, exists, err = tx.Set(
fmt.Sprint("user:", userID, ":sticker:", fileID), // key
emoji, // value
nil, // options
)
return err
}); err != nil {
return err
}
err := dbUpdateUserStickersIndex(userID)
return err
if err == buntdb.ErrIndexExists {
exists = true
return nil
}
return err
})
return exists, err
}
func dbDeleteSticker(userID int, fileID string) error {
if err := db.Update(func(tx *buntdb.Tx) error {
return db.Update(func(tx *buntdb.Tx) error {
_, err := tx.Delete(
fmt.Sprint("user:", userID, ":sticker:", fileID), // key
)
return err
}); err != nil {
return err
}
err := dbUpdateUserStickersIndex(userID)
return err
}
func dbUpdateUserStickersIndex(userID int) error {
return db.CreateIndex(
fmt.Sprint("stickers", userID), // name
fmt.Sprint("user:", userID, ":sticker:*"), // pattern
buntdb.IndexString, // options
)
})
}
func dbGetUserStickers(userID int, emoji string) ([]string, error) {
var stickers []string
err := db.View(func(tx *buntdb.Tx) error {
return tx.Ascend(
fmt.Sprint("stickers", userID), // index
"user_stickers", // index
func(key, val string) bool { // iterator
fileID := strings.TrimPrefix(
key, // source
fmt.Sprint("user:", userID, ":sticker:"), // prefix
)
log.Ln(key, "=", val)
subKeys := strings.Split(key, ":")
if subKeys[1] != strconv.Itoa(userID) {
return true
}
if emoji != "" {
log.Ln("["+emoji+"]", "?=", "["+val+"]")
if val != emoji {
return true
}
}
stickers = append(stickers, fileID)
stickers = append(stickers, subKeys[3])
return true
},
)
})
switch err {
case buntdb.ErrNotFound:
return nil, nil
}
return stickers, err
}

View File

@ -36,8 +36,7 @@ func main() {
case update.Message != nil:
log.Ln("[main] Get Message update")
// TODO: Added support of commands, grab and save sticker in DB
err = messages(update.Message)
errCheck(err)
messages(update.Message)
default:
log.Ln("[main] Get unsupported update")
// Ignore any other updates

View File

@ -7,16 +7,23 @@ import (
// message function check Message update on commands, sended stickers or other
// user stuff
func messages(msg *telegram.Message) error {
if msg.From.ID == bot.Self.ID ||
msg.ForwardFrom.ID == bot.Self.ID {
func messages(msg *telegram.Message) {
if msg.From.ID == bot.Self.ID {
log.Ln("[messages] Received a message from myself, ignore this update")
return nil
return
}
if msg.ForwardFrom != nil {
if msg.ForwardFrom.ID == bot.Self.ID {
log.Ln("[messages] Received a forward from myself, ignore this update")
return
}
}
if msg.IsCommand() {
log.Ln("[message] Received a command message")
return commands(msg)
commands(msg)
return
}
if msg.Sticker != nil {
@ -30,15 +37,33 @@ func messages(msg *telegram.Message) error {
"Use /addSticker or /delSticker command first.", // text
)
_, err = bot.SendMessage(reply)
case stateAdding:
err = dbAddSticker(msg.From.ID, msg.Sticker.FileID, msg.Sticker.Emoji)
errCheck(err)
case stateAdding:
exists, err := dbAddSticker(msg.From.ID, msg.Sticker.FileID, msg.Sticker.Emoji)
errCheck(err)
if exists {
reply := telegram.NewMessage(
msg.Chat.ID, // chat
"Already added!", // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
return
}
reply := telegram.NewMessage(
msg.Chat.ID, // chat
"Added!", // text
)
_, err = bot.SendMessage(reply)
errCheck(err)
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
case stateDeleting:
err = dbDeleteSticker(msg.From.ID, msg.Sticker.FileID)
errCheck(err)
@ -48,14 +73,16 @@ func messages(msg *telegram.Message) error {
"Removed!", // text
)
_, err = bot.SendMessage(reply)
default:
_, _, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
return messages(msg)
}
// TODO: Upload new or delete exist sticker in pack
return err
}
return nil // Do nothing because unsupported actions
_, err = dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
default:
_, err := dbChangeUserState(msg.From.ID, stateNone)
errCheck(err)
messages(msg)
return
}
}
}