spark-server/internal/module/music/model/repo.go
2026-09-23 17:11:56 +08:00

204 lines
5.1 KiB
Go

package model
import (
"context"
"errors"
"strconv"
"time"
"gorm.io/gorm"
"spark-server/internal/module/music/entity"
)
type Repo struct {
db *gorm.DB
}
func NewRepo(db *gorm.DB) *Repo {
if db == nil {
return nil
}
return &Repo{db: db}
}
func (r *Repo) Ready() bool {
return r != nil && r.db != nil
}
type trackRow struct {
ID int64 `gorm:"column:id;primaryKey"`
Title string `gorm:"column:title"`
CoverKey string `gorm:"column:cover_key"`
AudioKey string `gorm:"column:audio_key"`
CoverURL string `gorm:"column:cover_url"`
AudioURL string `gorm:"column:audio_url"`
RequireMember bool `gorm:"column:require_member"`
SortOrder int `gorm:"column:sort_order"`
Enabled bool `gorm:"column:enabled"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
func (trackRow) TableName() string { return "t_music_tracks" }
type settingRow struct {
SettingKey string `gorm:"column:setting_key;primaryKey"`
SettingValue string `gorm:"column:setting_value"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
func (settingRow) TableName() string { return "t_music_settings" }
func (r *Repo) ListAll(ctx context.Context) ([]entity.Track, error) {
if !r.Ready() {
return nil, errors.New("music repo not ready")
}
var rows []trackRow
err := r.db.WithContext(ctx).Order("sort_order ASC, id ASC").Find(&rows).Error
if err != nil {
return nil, err
}
out := make([]entity.Track, 0, len(rows))
for _, row := range rows {
out = append(out, toEntity(row))
}
return out, nil
}
func (r *Repo) ListEnabled(ctx context.Context) ([]entity.Track, error) {
if !r.Ready() {
return nil, errors.New("music repo not ready")
}
var rows []trackRow
err := r.db.WithContext(ctx).Where("enabled = ?", true).Order("sort_order ASC, id ASC").Find(&rows).Error
if err != nil {
return nil, err
}
out := make([]entity.Track, 0, len(rows))
for _, row := range rows {
out = append(out, toEntity(row))
}
return out, nil
}
func (r *Repo) Get(ctx context.Context, id int64) (*entity.Track, error) {
if !r.Ready() {
return nil, errors.New("music repo not ready")
}
var row trackRow
err := r.db.WithContext(ctx).First(&row, id).Error
if err != nil {
return nil, err
}
t := toEntity(row)
return &t, nil
}
func (r *Repo) Insert(ctx context.Context, t *entity.Track) error {
if !r.Ready() {
return errors.New("music repo not ready")
}
now := time.Now().UTC()
row := trackRow{
Title: t.Title,
CoverKey: t.CoverKey,
AudioKey: t.AudioKey,
CoverURL: t.CoverURL,
AudioURL: t.AudioURL,
RequireMember: t.RequireMember,
SortOrder: t.SortOrder,
Enabled: t.Enabled,
CreatedAt: now,
UpdatedAt: now,
}
if err := r.db.WithContext(ctx).Create(&row).Error; err != nil {
return err
}
t.ID = row.ID
t.CreatedAt = row.CreatedAt
t.UpdatedAt = row.UpdatedAt
return nil
}
func (r *Repo) Update(ctx context.Context, t *entity.Track) error {
if !r.Ready() {
return errors.New("music repo not ready")
}
now := time.Now().UTC()
t.UpdatedAt = now
return r.db.WithContext(ctx).Model(&trackRow{}).Where("id = ?", t.ID).Updates(map[string]any{
"title": t.Title,
"cover_key": t.CoverKey,
"audio_key": t.AudioKey,
"cover_url": t.CoverURL,
"audio_url": t.AudioURL,
"require_member": t.RequireMember,
"sort_order": t.SortOrder,
"enabled": t.Enabled,
"updated_at": now,
}).Error
}
func (r *Repo) Delete(ctx context.Context, id int64) error {
if !r.Ready() {
return errors.New("music repo not ready")
}
return r.db.WithContext(ctx).Delete(&trackRow{}, id).Error
}
func (r *Repo) GetSetting(ctx context.Context, key string) (string, error) {
if !r.Ready() {
return "", errors.New("music repo not ready")
}
var row settingRow
err := r.db.WithContext(ctx).Where("setting_key = ?", key).First(&row).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return "", nil
}
if err != nil {
return "", err
}
return row.SettingValue, nil
}
func (r *Repo) SetSetting(ctx context.Context, key, value string) error {
if !r.Ready() {
return errors.New("music repo not ready")
}
now := time.Now().UTC()
row := settingRow{SettingKey: key, SettingValue: value, UpdatedAt: now}
return r.db.WithContext(ctx).Save(&row).Error
}
func (r *Repo) MemberPreviewSeconds(ctx context.Context) (int, error) {
raw, err := r.GetSetting(ctx, entity.SettingMemberPreviewSeconds)
if err != nil {
return entity.DefaultPreviewSeconds, err
}
if raw == "" {
return entity.DefaultPreviewSeconds, nil
}
n, err := strconv.Atoi(raw)
if err != nil || n < 0 {
return entity.DefaultPreviewSeconds, nil
}
return n, nil
}
func toEntity(row trackRow) entity.Track {
return entity.Track{
ID: row.ID,
Title: row.Title,
CoverKey: row.CoverKey,
AudioKey: row.AudioKey,
CoverURL: row.CoverURL,
AudioURL: row.AudioURL,
RequireMember: row.RequireMember,
SortOrder: row.SortOrder,
Enabled: row.Enabled,
CreatedAt: row.CreatedAt,
UpdatedAt: row.UpdatedAt,
}
}