fix source-aware download tracking and filter/path regressions

Make download dedupe source-specific to prevent cross-provider ID collisions. Also correct non-remaster filtering, avoid FLAC tagging on non-FLAC files, and use album IDs for singles folder templating.
This commit is contained in:
2026-04-19 21:25:04 +02:00
parent 97e8b758b3
commit d4643d877e
6 changed files with 157 additions and 21 deletions

View File

@@ -28,8 +28,11 @@ func NewSQLite(path string) (*SQLite, error) {
}
func (s *SQLite) init() error {
if err := s.ensureDownloadsSchema(); err != nil {
return err
}
queries := []string{
`CREATE TABLE IF NOT EXISTS downloads (id TEXT PRIMARY KEY)`,
`CREATE TABLE IF NOT EXISTS failed_downloads (
source TEXT NOT NULL,
media_type TEXT NOT NULL,
@@ -47,23 +50,101 @@ func (s *SQLite) init() error {
return nil
}
func (s *SQLite) IsDownloaded(ctx context.Context, id string) (bool, error) {
func (s *SQLite) ensureDownloadsSchema() error {
rows, err := s.db.Query(`PRAGMA table_info(downloads)`)
if err != nil {
return err
}
defer rows.Close()
hasTable := false
hasSource := false
for rows.Next() {
hasTable = true
var (
cid int
name string
colType string
notNull int
defaultV sql.NullString
pkOrdinal int
)
if err = rows.Scan(&cid, &name, &colType, &notNull, &defaultV, &pkOrdinal); err != nil {
return err
}
if name == "source" {
hasSource = true
}
}
if err = rows.Err(); err != nil {
return err
}
if !hasTable {
_, err = s.db.Exec(`CREATE TABLE downloads (
source TEXT NOT NULL,
id TEXT NOT NULL,
PRIMARY KEY (source, id)
)`)
return err
}
if hasSource {
_, err = s.db.Exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_downloads_source_id ON downloads(source, id)`)
return err
}
tx, err := s.db.Begin()
if err != nil {
return err
}
defer func() {
if err != nil {
_ = tx.Rollback()
}
}()
if _, err = tx.Exec(`DROP TABLE IF EXISTS downloads_legacy`); err != nil {
return err
}
if _, err = tx.Exec(`ALTER TABLE downloads RENAME TO downloads_legacy`); err != nil {
return err
}
if _, err = tx.Exec(`CREATE TABLE downloads (
source TEXT NOT NULL,
id TEXT NOT NULL,
PRIMARY KEY (source, id)
)`); err != nil {
return err
}
if _, err = tx.Exec(`INSERT OR IGNORE INTO downloads(source, id) SELECT '', id FROM downloads_legacy`); err != nil {
return err
}
if _, err = tx.Exec(`DROP TABLE downloads_legacy`); err != nil {
return err
}
err = tx.Commit()
return err
}
func (s *SQLite) IsDownloaded(ctx context.Context, source, id string) (bool, error) {
s.mu.Lock()
defer s.mu.Unlock()
var count int
err := s.db.QueryRowContext(ctx, `SELECT COUNT(1) FROM downloads WHERE id = ?`, id).Scan(&count)
err := s.db.QueryRowContext(ctx, `SELECT COUNT(1) FROM downloads WHERE source = ? AND id = ?`, source, id).Scan(&count)
if err != nil {
return false, err
}
return count > 0, nil
}
func (s *SQLite) MarkDownloaded(ctx context.Context, id string) error {
func (s *SQLite) MarkDownloaded(ctx context.Context, source, id string) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.ExecContext(ctx, `INSERT OR IGNORE INTO downloads(id) VALUES (?)`, id)
_, err := s.db.ExecContext(ctx, `INSERT OR IGNORE INTO downloads(source, id) VALUES (?, ?)`, source, id)
return err
}