MyPackBot/database.go

245 lines
4.8 KiB
Go
Executable File

package main
import (
"fmt"
"strconv"
"strings"
log "github.com/kirillDanshin/dlog"
"github.com/tidwall/buntdb"
)
const (
stateNone = "none"
stateAddSticker = "addSticker"
stateAddPack = "addPack"
stateDeleteSticker = "delSticker"
stateDeletePack = "delPack"
stateReset = "reset"
setUploaded = "?"
)
var db *buntdb.DB
func dbInit() {
log.Ln("Open database file...")
var err error
db, err = buntdb.Open("stickers.db")
errCheck(err)
select {}
}
func dbGetUsers() ([]int, error) {
var users []int
err := db.View(func(tx *buntdb.Tx) error {
return tx.AscendKeys(
"user:*:state",
func(key, val string) bool {
subKeys := strings.Split(key, ":")
id, err := strconv.Atoi(subKeys[1])
if err == nil {
users = append(users, id)
}
return true
},
)
})
if err == buntdb.ErrNotFound {
return nil, nil
}
return users, err
}
func dbChangeUserState(userID int, state string) error {
log.Ln("Trying to change", userID, "state to", state)
return db.Update(func(tx *buntdb.Tx) error {
_, _, err := tx.Set(fmt.Sprint("user:", userID, ":state"), state, nil)
return err
})
}
func dbGetUserState(userID int) (string, error) {
log.Ln("Trying to get", userID, "state")
var state string
err := db.View(func(tx *buntdb.Tx) error {
var err error
state, err = tx.Get(fmt.Sprint("user:", userID, ":state"))
return err
})
switch err {
case buntdb.ErrNotFound:
log.Ln(userID, "not found, create new one")
if err = dbChangeUserState(userID, stateNone); err != nil {
return state, err
}
}
return state, err
}
func dbAddSticker(userID int, setName, fileID, emoji string) (bool, error) {
log.Ln("Trying to add", fileID, "sticker from", userID, "user")
if setName == "" {
setName = setUploaded
}
var exists bool
err := db.Update(func(tx *buntdb.Tx) error {
var err error
_, exists, err = tx.Set(
fmt.Sprint("user:", userID, ":set:", setName, ":sticker:", fileID), // key
emoji, // value
nil, // options
)
if err == buntdb.ErrIndexExists {
exists = true
return nil
}
return err
})
return exists, err
}
func dbDeleteSticker(userID int, setName, fileID string) (bool, error) {
log.Ln("Trying to remove", fileID, "sticker from", userID, "user")
if setName == "" {
setName = setUploaded
}
err := db.Update(func(tx *buntdb.Tx) error {
_, err := tx.Delete(
fmt.Sprint("user:", userID, ":set:", setName, ":sticker:", fileID),
)
return err
})
switch err {
case buntdb.ErrNotFound:
log.Ln(userID, "not found, create new one")
return true, nil
}
return false, err
}
func dbDeletePack(userID int, setName string) (bool, error) {
log.Ln("Trying to remove all", setName, "sticker from", userID, "user")
if setName == "" {
setName = setUploaded
}
var fileIDs []string
err := db.View(func(tx *buntdb.Tx) error {
return tx.AscendKeys(
fmt.Sprint("user:", userID, ":set:", setName, ":*"),
func(key, val string) bool {
keys := strings.Split(key, ":")
fileIDs = append(fileIDs, keys[5])
return true
},
)
})
if len(fileIDs) == 0 {
return true, nil
}
for _, fileID := range fileIDs {
var notExist bool
notExist, err = dbDeleteSticker(userID, setName, fileID)
if err != nil {
return notExist, err
}
}
switch err {
case buntdb.ErrNotFound:
log.Ln(userID, "not found")
return true, nil
}
return false, err
}
func dbResetUserStickers(userID int) error {
log.Ln("Trying reset all stickers of", userID, "user")
return db.Update(func(tx *buntdb.Tx) error {
var keys []string
if err := tx.AscendKeys(
fmt.Sprint("user:", userID, ":set:*"), // index
func(key, val string) bool { // iterator
subKeys := strings.Split(key, ":")
if subKeys[1] == strconv.Itoa(userID) {
keys = append(keys, key)
}
return true
},
); err != nil {
return err
}
for i := range keys {
_, err := tx.Delete(keys[i])
if err != nil {
break
}
}
return nil
})
}
func dbGetUserStickers(userID, offset int, query string) ([]string, int, error) {
log.Ln("Trying to get", userID, "stickers")
var total, count int
var stickers []string
offset = offset * 50
err := db.View(func(tx *buntdb.Tx) error {
return tx.AscendKeys(
fmt.Sprint("user:", userID, ":set:*"), // index
func(key, val string) bool { // iterator
subKeys := strings.Split(key, ":")
if subKeys[1] != strconv.Itoa(userID) {
return true
}
total++
if count >= 51 {
return true
}
if total < offset {
return true
}
if query != "" && !strings.Contains(query, val) {
return true
}
count++
stickers = append(stickers, subKeys[5])
return true
},
)
})
switch {
case err == buntdb.ErrNotFound:
log.Ln("Not found stickers")
return nil, total, nil
case err != nil:
return nil, total, err
}
return stickers, total, nil
}