twitch-bot/internal/apimodules/overlays/database.go

102 lines
2.5 KiB
Go
Raw Normal View History

package overlays
import (
"bytes"
"encoding/json"
"strings"
"time"
"github.com/pkg/errors"
"gorm.io/gorm"
"github.com/Luzifer/go_helpers/v2/backoff"
"github.com/Luzifer/go_helpers/v2/fieldcollection"
"github.com/Luzifer/twitch-bot/v3/internal/helpers"
"github.com/Luzifer/twitch-bot/v3/pkg/database"
)
type (
overlaysEvent struct {
ID uint64 `gorm:"primaryKey"`
Channel string `gorm:"not null;index:overlays_events_sort_idx"`
CreatedAt time.Time `gorm:"index:overlays_events_sort_idx"`
EventType string
Fields string
}
)
func addChannelEvent(db database.Connector, channel string, evt socketMessage) (evtID uint64, err error) {
buf := new(bytes.Buffer)
if err := json.NewEncoder(buf).Encode(evt.Fields); err != nil {
return 0, errors.Wrap(err, "encoding fields")
}
storEvt := &overlaysEvent{
Channel: channel,
CreatedAt: evt.Time.UTC(),
EventType: evt.Type,
Fields: strings.TrimSpace(buf.String()),
}
if err = helpers.RetryTransaction(db.DB(), func(tx *gorm.DB) error {
return tx.Create(storEvt).Error
}); err != nil {
return 0, errors.Wrap(err, "storing event to database")
}
return storEvt.ID, nil
}
func getChannelEvents(db database.Connector, channel string) ([]socketMessage, error) {
var evts []overlaysEvent
if err := helpers.Retry(func() error {
return db.DB().Where("channel = ?", channel).Order("created_at").Find(&evts).Error
}); err != nil {
return nil, errors.Wrap(err, "querying channel events")
}
var out []socketMessage
for _, e := range evts {
sm, err := e.ToSocketMessage()
if err != nil {
return nil, errors.Wrap(err, "transforming event")
}
out = append(out, sm)
}
return out, nil
}
func getEventByID(db database.Connector, eventID uint64) (socketMessage, error) {
var evt overlaysEvent
if err := helpers.Retry(func() (err error) {
err = db.DB().Where("id = ?", eventID).First(&evt).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return backoff.NewErrCannotRetry(err)
}
return err
}); err != nil {
return socketMessage{}, errors.Wrap(err, "fetching event")
}
return evt.ToSocketMessage()
}
func (o overlaysEvent) ToSocketMessage() (socketMessage, error) {
fields := new(fieldcollection.FieldCollection)
if err := json.NewDecoder(strings.NewReader(o.Fields)).Decode(fields); err != nil {
return socketMessage{}, errors.Wrap(err, "decoding fields")
}
return socketMessage{
EventID: o.ID,
IsLive: false,
Time: o.CreatedAt,
Type: o.EventType,
Fields: fields,
}, nil
}