stillbox/pkg/calls/callstore/store.go
2024-12-28 18:32:13 -05:00

124 lines
2.8 KiB
Go

package callstore
import (
"context"
"fmt"
"dynatron.me/x/stillbox/internal/common"
"dynatron.me/x/stillbox/internal/jsontypes"
"dynatron.me/x/stillbox/pkg/calls"
"dynatron.me/x/stillbox/pkg/database"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
)
type Store interface {
// CallAudio returns a CallAudio struct
CallAudio(ctx context.Context, id uuid.UUID) (*calls.CallAudio, error)
// Calls gets paginated Calls.
Calls(ctx context.Context, p CallsParams) (calls []database.ListCallsPRow, totalCount int, err error)
}
type store struct {
}
func NewStore() *store {
return new(store)
}
type storeCtxKey string
const StoreCtxKey storeCtxKey = "store"
func CtxWithStore(ctx context.Context, s Store) context.Context {
return context.WithValue(ctx, StoreCtxKey, s)
}
func FromCtx(ctx context.Context) Store {
s, ok := ctx.Value(StoreCtxKey).(Store)
if !ok {
return NewStore()
}
return s
}
func (s *store) CallAudio(ctx context.Context, id uuid.UUID) (*calls.CallAudio, error) {
db := database.FromCtx(ctx)
dbCall, err := db.GetCallAudioByID(ctx, id)
if err != nil {
return nil, err
}
return &calls.CallAudio{
CallDate: jsontypes.Time(dbCall.CallDate.Time),
AudioName: dbCall.AudioName,
AudioType: dbCall.AudioType,
AudioBlob: dbCall.AudioBlob,
}, nil
}
type CallsParams struct {
common.Pagination
Direction *common.SortDirection `json:"dir"`
Start *jsontypes.Time `json:"start"`
End *jsontypes.Time `json:"end"`
TagsAny []string `json:"tagsAny"`
TagsNot []string `json:"tagsNot"`
TGFilter *string `json:"tgFilter"`
AtLeastSeconds *float32 `json:"atLeastSeconds"`
}
func (s *store) Calls(ctx context.Context, p CallsParams) (rows []database.ListCallsPRow, totalCount int, err error) {
db := database.FromCtx(ctx)
offset, perPage := p.Pagination.OffsetPerPage(100)
par := database.ListCallsPParams{
Start: p.Start.PGTypeTSTZ(),
End: p.End.PGTypeTSTZ(),
TagsAny: p.TagsAny,
TagsNot: p.TagsNot,
Offset: offset,
PerPage: perPage,
Direction: p.Direction.DirString(common.DirAsc),
TGFilter: p.TGFilter,
}
if p.AtLeastSeconds != nil {
var n pgtype.Numeric
if err := n.Scan(fmt.Sprint(*p.AtLeastSeconds * 1000)); err != nil {
return nil, 0, err
}
par.LongerThan = n
}
var count int64
txErr := db.InTx(ctx, func(db database.Store) error {
var err error
count, err = db.ListCallsCount(ctx, database.ListCallsCountParams{
Start: par.Start,
End: par.End,
TagsAny: par.TagsAny,
TagsNot: par.TagsNot,
TGFilter: par.TGFilter,
})
if err != nil {
return err
}
rows, err = db.ListCallsP(ctx, par)
return err
}, pgx.TxOptions{})
if txErr != nil {
return nil, 0, txErr
}
return rows, int(count), err
}