158 lines
3.7 KiB
Go
158 lines
3.7 KiB
Go
package database
|
|
|
|
import (
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
"github.com/peterqiu0516/sub-store/internal/model"
|
|
"github.com/peterqiu0516/sub-store/internal/util"
|
|
)
|
|
|
|
type SourceRepo struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
func NewSourceRepo(db *sqlx.DB) *SourceRepo {
|
|
return &SourceRepo{db: db}
|
|
}
|
|
|
|
type sourceRow struct {
|
|
ID string `db:"id"`
|
|
Name string `db:"name"`
|
|
Type string `db:"type"`
|
|
URL string `db:"url"`
|
|
Content string `db:"content"`
|
|
Enabled int `db:"enabled"`
|
|
FiltersJSON string `db:"filters_json"`
|
|
MetaJSON string `db:"meta_json"`
|
|
CreatedAt int64 `db:"created_at"`
|
|
UpdatedAt int64 `db:"updated_at"`
|
|
}
|
|
|
|
func (r *SourceRepo) List() ([]model.SourceRecord, error) {
|
|
var rows []sourceRow
|
|
if err := r.db.Select(&rows, "SELECT * FROM sources ORDER BY created_at ASC"); err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]model.SourceRecord, 0, len(rows))
|
|
for _, row := range rows {
|
|
result = append(result, sourceFromRow(row))
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (r *SourceRepo) Get(id string) (*model.SourceRecord, error) {
|
|
var row sourceRow
|
|
if err := r.db.Get(&row, "SELECT * FROM sources WHERE id = ?", id); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
rec := sourceFromRow(row)
|
|
return &rec, nil
|
|
}
|
|
|
|
func (r *SourceRepo) Upsert(input model.SourceRecord) (model.SourceRecord, error) {
|
|
now := time.Now().UnixMilli()
|
|
id := input.ID
|
|
if id == "" {
|
|
id = util.ToId(input.Name)
|
|
}
|
|
existing, _ := r.Get(id)
|
|
createdAt := now
|
|
if existing != nil {
|
|
createdAt = existing.CreatedAt
|
|
}
|
|
|
|
filters := input.Filters
|
|
if filters == nil {
|
|
filters = []model.FilterRule{}
|
|
}
|
|
meta := input.Meta
|
|
if meta == nil {
|
|
meta = map[string]any{}
|
|
}
|
|
|
|
rec := model.SourceRecord{
|
|
ID: id,
|
|
Name: input.Name,
|
|
Type: input.Type,
|
|
URL: input.URL,
|
|
Content: input.Content,
|
|
Enabled: input.Enabled,
|
|
Filters: filters,
|
|
Meta: meta,
|
|
CreatedAt: createdAt,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
filtersJSON := marshalJSON(filters)
|
|
metaJSON := marshalJSON(meta)
|
|
enabled := boolToInt(rec.Enabled)
|
|
sourceType := rec.Type
|
|
if sourceType == "" {
|
|
sourceType = "remote"
|
|
}
|
|
if sourceType != "local" {
|
|
sourceType = "remote"
|
|
}
|
|
|
|
_, err := r.db.Exec(
|
|
`INSERT INTO sources (id, name, type, url, content, enabled, filters_json, meta_json, created_at, updated_at)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(id) DO UPDATE SET
|
|
name = excluded.name, type = excluded.type, url = excluded.url,
|
|
content = excluded.content, enabled = excluded.enabled,
|
|
filters_json = excluded.filters_json, meta_json = excluded.meta_json,
|
|
updated_at = excluded.updated_at`,
|
|
rec.ID, rec.Name, sourceType, rec.URL, rec.Content, enabled, filtersJSON, metaJSON, rec.CreatedAt, rec.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return rec, err
|
|
}
|
|
return rec, nil
|
|
}
|
|
|
|
func (r *SourceRepo) Delete(id string) error {
|
|
_, err := r.db.Exec("DELETE FROM sources WHERE id = ?", id)
|
|
return err
|
|
}
|
|
|
|
func (r *SourceRepo) Sort(ids []string) error {
|
|
now := time.Now().UnixMilli()
|
|
tx, err := r.db.Beginx()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback()
|
|
for i, id := range ids {
|
|
_, err := tx.Exec("UPDATE sources SET created_at = ?, updated_at = ? WHERE id = ?", now+int64(i), now, id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func sourceFromRow(row sourceRow) model.SourceRecord {
|
|
sourceType := "remote"
|
|
if row.Type == "local" {
|
|
sourceType = "local"
|
|
}
|
|
return model.SourceRecord{
|
|
ID: row.ID,
|
|
Name: row.Name,
|
|
Type: sourceType,
|
|
URL: row.URL,
|
|
Content: row.Content,
|
|
Enabled: row.Enabled != 0,
|
|
Filters: model.UnmarshalFilterRules(row.FiltersJSON),
|
|
Meta: model.UnmarshalMeta(row.MetaJSON),
|
|
CreatedAt: row.CreatedAt,
|
|
UpdatedAt: row.UpdatedAt,
|
|
}
|
|
}
|