2022-09-10 11:39:07 +00:00
|
|
|
package quotedb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
2022-10-22 22:08:02 +00:00
|
|
|
"gorm.io/gorm"
|
|
|
|
|
2022-11-02 21:38:14 +00:00
|
|
|
"github.com/Luzifer/twitch-bot/v3/pkg/database"
|
2022-09-10 11:39:07 +00:00
|
|
|
)
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
type (
|
|
|
|
quote struct {
|
|
|
|
Channel string `gorm:"not null;uniqueIndex:ensure_sort_idx;size:32"`
|
|
|
|
CreatedAt int64 `gorm:"uniqueIndex:ensure_sort_idx"`
|
|
|
|
Quote string
|
|
|
|
}
|
|
|
|
)
|
2022-09-10 11:39:07 +00:00
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func AddQuote(db database.Connector, channel, quoteStr string) error {
|
|
|
|
return errors.Wrap(
|
|
|
|
db.DB().Create(quote{
|
|
|
|
Channel: channel,
|
|
|
|
CreatedAt: time.Now().UnixNano(),
|
|
|
|
Quote: quoteStr,
|
|
|
|
}).Error,
|
|
|
|
"adding quote to database",
|
2022-09-10 11:39:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func DelQuote(db database.Connector, channel string, quoteIdx int) error {
|
|
|
|
_, createdAt, _, err := GetQuoteRaw(db, channel, quoteIdx)
|
2022-09-10 11:39:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "fetching specified quote")
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
return errors.Wrap(
|
|
|
|
db.DB().Delete("e{}, "channel = ? AND created_at = ?", channel, createdAt).Error,
|
|
|
|
"deleting quote",
|
2022-09-10 11:39:07 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func GetChannelQuotes(db database.Connector, channel string) ([]string, error) {
|
|
|
|
var qs []quote
|
|
|
|
if err := db.DB().Where("channel = ?", channel).Order("created_at").Find(&qs).Error; err != nil {
|
2022-09-10 11:39:07 +00:00
|
|
|
return nil, errors.Wrap(err, "querying quotes")
|
|
|
|
}
|
|
|
|
|
|
|
|
var quotes []string
|
2022-10-22 22:08:02 +00:00
|
|
|
for _, q := range qs {
|
|
|
|
quotes = append(quotes, q.Quote)
|
2022-09-10 11:39:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
return quotes, nil
|
2022-09-10 11:39:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func GetMaxQuoteIdx(db database.Connector, channel string) (int, error) {
|
|
|
|
var count int64
|
|
|
|
if err := db.DB().
|
|
|
|
Model("e{}).
|
|
|
|
Where("channel = ?", channel).
|
|
|
|
Count(&count).
|
|
|
|
Error; err != nil {
|
|
|
|
return 0, errors.Wrap(err, "getting quote count")
|
|
|
|
}
|
2022-09-10 11:39:07 +00:00
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
return int(count), nil
|
2022-09-10 11:39:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func GetQuote(db database.Connector, channel string, quote int) (int, string, error) {
|
|
|
|
quoteIdx, _, quoteText, err := GetQuoteRaw(db, channel, quote)
|
2022-09-10 11:39:07 +00:00
|
|
|
return quoteIdx, quoteText, err
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func GetQuoteRaw(db database.Connector, channel string, quoteIdx int) (int, int64, string, error) {
|
|
|
|
if quoteIdx == 0 {
|
|
|
|
max, err := GetMaxQuoteIdx(db, channel)
|
2022-09-10 11:39:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return 0, 0, "", errors.Wrap(err, "getting max quote idx")
|
|
|
|
}
|
2022-10-22 22:08:02 +00:00
|
|
|
quoteIdx = rand.Intn(max) + 1 // #nosec G404 // no need for cryptographic safety
|
2022-09-10 11:39:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
var q quote
|
|
|
|
err := db.DB().
|
|
|
|
Where("channel = ?", channel).
|
|
|
|
Limit(1).
|
|
|
|
Offset(quoteIdx - 1).
|
|
|
|
First(&q).Error
|
2022-09-10 11:39:07 +00:00
|
|
|
|
|
|
|
switch {
|
|
|
|
case err == nil:
|
2022-10-22 22:08:02 +00:00
|
|
|
return quoteIdx, q.CreatedAt, q.Quote, nil
|
2022-09-10 11:39:07 +00:00
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
case errors.Is(err, gorm.ErrRecordNotFound):
|
2022-09-10 11:39:07 +00:00
|
|
|
return 0, 0, "", nil
|
|
|
|
|
|
|
|
default:
|
|
|
|
return 0, 0, "", errors.Wrap(err, "getting quote from DB")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func SetQuotes(db database.Connector, channel string, quotes []string) error {
|
|
|
|
return errors.Wrap(
|
|
|
|
db.DB().Transaction(func(tx *gorm.DB) error {
|
|
|
|
if err := tx.Where("channel = ?", channel).Delete("e{}).Error; err != nil {
|
|
|
|
return errors.Wrap(err, "deleting quotes for channel")
|
|
|
|
}
|
|
|
|
|
|
|
|
t := time.Now()
|
|
|
|
for _, quoteStr := range quotes {
|
|
|
|
if err := tx.Create(quote{
|
|
|
|
Channel: channel,
|
|
|
|
CreatedAt: t.UnixNano(),
|
|
|
|
Quote: quoteStr,
|
|
|
|
}).Error; err != nil {
|
|
|
|
return errors.Wrap(err, "adding quote")
|
|
|
|
}
|
|
|
|
|
|
|
|
t = t.Add(time.Nanosecond) // Increase by one ns to adhere to unique index
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}),
|
|
|
|
"replacing quotes",
|
|
|
|
)
|
2022-09-10 11:39:07 +00:00
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
func UpdateQuote(db database.Connector, channel string, idx int, quoteStr string) error {
|
|
|
|
_, createdAt, _, err := GetQuoteRaw(db, channel, idx)
|
2022-09-10 11:39:07 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "fetching specified quote")
|
|
|
|
}
|
|
|
|
|
2022-10-22 22:08:02 +00:00
|
|
|
return errors.Wrap(
|
|
|
|
db.DB().
|
|
|
|
Where("channel = ? AND created_at = ?", channel, createdAt).
|
|
|
|
Update("quote", quoteStr).
|
|
|
|
Error,
|
|
|
|
"updating quote",
|
2022-09-10 11:39:07 +00:00
|
|
|
)
|
|
|
|
}
|