wip on autotagging

This commit is contained in:
2026-05-01 11:52:50 -04:00
parent 5cf019a0ac
commit d5140395da
295 changed files with 11105 additions and 40714 deletions
+107 -6
View File
@@ -35,7 +35,7 @@ func (q *Queries) CountAudioFilesByLibrary(ctx context.Context, libraryID int64)
const createAudioFile = `-- name: CreateAudioFile :one
INSERT INTO audio_files (file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played
RETURNING id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key
`
type CreateAudioFileParams struct {
@@ -82,6 +82,71 @@ func (q *Queries) CreateAudioFile(ctx context.Context, arg CreateAudioFileParams
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
)
return i, err
}
const createAudioFileWithGroupKey = `-- name: CreateAudioFileWithGroupKey :one
INSERT INTO audio_files (
file_path, length_milliseconds, file_type_id, recording_id,
sample_rate, bit_depth, channels, bitrate, file_size, basename,
library_id, group_key, tag_status
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key
`
type CreateAudioFileWithGroupKeyParams struct {
FilePath string
LengthMilliseconds int64
FileTypeID int64
RecordingID int64
SampleRate int64
BitDepth int64
Channels int64
Bitrate int64
FileSize int64
Basename string
LibraryID int64
GroupKey string
TagStatus string
}
func (q *Queries) CreateAudioFileWithGroupKey(ctx context.Context, arg CreateAudioFileWithGroupKeyParams) (AudioFile, error) {
row := q.db.QueryRowContext(ctx, createAudioFileWithGroupKey,
arg.FilePath,
arg.LengthMilliseconds,
arg.FileTypeID,
arg.RecordingID,
arg.SampleRate,
arg.BitDepth,
arg.Channels,
arg.Bitrate,
arg.FileSize,
arg.Basename,
arg.LibraryID,
arg.GroupKey,
arg.TagStatus,
)
var i AudioFile
err := row.Scan(
&i.ID,
&i.FilePath,
&i.LengthMilliseconds,
&i.FileTypeID,
&i.RecordingID,
&i.SampleRate,
&i.BitDepth,
&i.Channels,
&i.Bitrate,
&i.FileSize,
&i.Basename,
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
)
return i, err
}
@@ -138,7 +203,7 @@ func (q *Queries) GetAllAudioFilePaths(ctx context.Context) ([]GetAllAudioFilePa
}
const getAllAudioFiles = `-- name: GetAllAudioFiles :many
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played FROM audio_files
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key FROM audio_files
`
func (q *Queries) GetAllAudioFiles(ctx context.Context) ([]AudioFile, error) {
@@ -165,6 +230,8 @@ func (q *Queries) GetAllAudioFiles(ctx context.Context) ([]AudioFile, error) {
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
); err != nil {
return nil, err
}
@@ -460,7 +527,7 @@ func (q *Queries) GetAllTracksWithFullMetadataByLibrary(ctx context.Context, lib
}
const getAudioFile = `-- name: GetAudioFile :one
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played FROM audio_files
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key FROM audio_files
WHERE id = ? LIMIT 1
`
@@ -482,12 +549,14 @@ func (q *Queries) GetAudioFile(ctx context.Context, id int64) (AudioFile, error)
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
)
return i, err
}
const getAudioFileByPath = `-- name: GetAudioFileByPath :one
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played FROM audio_files
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key FROM audio_files
WHERE file_path = ? LIMIT 1
`
@@ -509,12 +578,26 @@ func (q *Queries) GetAudioFileByPath(ctx context.Context, filePath string) (Audi
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
)
return i, err
}
const getAudioFileGroupKey = `-- name: GetAudioFileGroupKey :one
SELECT group_key FROM audio_files
WHERE id = ? LIMIT 1
`
func (q *Queries) GetAudioFileGroupKey(ctx context.Context, id int64) (string, error) {
row := q.db.QueryRowContext(ctx, getAudioFileGroupKey, id)
var group_key string
err := row.Scan(&group_key)
return group_key, err
}
const getAudioFilesByLibrary = `-- name: GetAudioFilesByLibrary :many
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played FROM audio_files WHERE library_id = ?
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key FROM audio_files WHERE library_id = ?
`
func (q *Queries) GetAudioFilesByLibrary(ctx context.Context, libraryID int64) ([]AudioFile, error) {
@@ -541,6 +624,8 @@ func (q *Queries) GetAudioFilesByLibrary(ctx context.Context, libraryID int64) (
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
); err != nil {
return nil, err
}
@@ -769,7 +854,7 @@ func (q *Queries) GetAudioFilesByReleaseGroupByLibrary(ctx context.Context, arg
}
const getAudioFilesNeedingMetadata = `-- name: GetAudioFilesNeedingMetadata :many
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played FROM audio_files
SELECT id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size, basename, library_id, play_count, last_played, tag_status, group_key FROM audio_files
WHERE recording_id = 0
`
@@ -797,6 +882,8 @@ func (q *Queries) GetAudioFilesNeedingMetadata(ctx context.Context) ([]AudioFile
&i.LibraryID,
&i.PlayCount,
&i.LastPlayed,
&i.TagStatus,
&i.GroupKey,
); err != nil {
return nil, err
}
@@ -999,6 +1086,20 @@ func (q *Queries) SearchAudioFilesByBasename(ctx context.Context, arg SearchAudi
return items, nil
}
const setAudioFileGroupKey = `-- name: SetAudioFileGroupKey :exec
UPDATE audio_files SET group_key = ? WHERE id = ?
`
type SetAudioFileGroupKeyParams struct {
GroupKey string
ID int64
}
func (q *Queries) SetAudioFileGroupKey(ctx context.Context, arg SetAudioFileGroupKeyParams) error {
_, err := q.db.ExecContext(ctx, setAudioFileGroupKey, arg.GroupKey, arg.ID)
return err
}
const updateAudioFile = `-- name: UpdateAudioFile :exec
UPDATE audio_files
SET file_path = ?, length_milliseconds = ?, file_type_id = ?, recording_id = ?, sample_rate = ?, bit_depth = ?, channels = ?, bitrate = ?, file_size = ?, basename = ?
+17 -4
View File
@@ -9,6 +9,15 @@ import (
"context"
)
const ackLibraryAutotagWarning = `-- name: AckLibraryAutotagWarning :exec
UPDATE libraries SET autotag_warning_acked = 1 WHERE id = ?
`
func (q *Queries) AckLibraryAutotagWarning(ctx context.Context, id int64) error {
_, err := q.db.ExecContext(ctx, ackLibraryAutotagWarning, id)
return err
}
const countLibraries = `-- name: CountLibraries :one
SELECT COUNT(*) AS count FROM libraries
`
@@ -22,7 +31,7 @@ func (q *Queries) CountLibraries(ctx context.Context) (int64, error) {
const createLibrary = `-- name: CreateLibrary :one
INSERT INTO libraries (name, path) VALUES (?, ?)
RETURNING id, name, path, created_at
RETURNING id, name, path, created_at, autotag_warning_acked
`
type CreateLibraryParams struct {
@@ -38,6 +47,7 @@ func (q *Queries) CreateLibrary(ctx context.Context, arg CreateLibraryParams) (L
&i.Name,
&i.Path,
&i.CreatedAt,
&i.AutotagWarningAcked,
)
return i, err
}
@@ -52,7 +62,7 @@ func (q *Queries) DeleteLibrary(ctx context.Context, id int64) error {
}
const getAllLibraries = `-- name: GetAllLibraries :many
SELECT id, name, path, created_at FROM libraries ORDER BY name
SELECT id, name, path, created_at, autotag_warning_acked FROM libraries ORDER BY name
`
func (q *Queries) GetAllLibraries(ctx context.Context) ([]Library, error) {
@@ -69,6 +79,7 @@ func (q *Queries) GetAllLibraries(ctx context.Context) ([]Library, error) {
&i.Name,
&i.Path,
&i.CreatedAt,
&i.AutotagWarningAcked,
); err != nil {
return nil, err
}
@@ -84,7 +95,7 @@ func (q *Queries) GetAllLibraries(ctx context.Context) ([]Library, error) {
}
const getLibrary = `-- name: GetLibrary :one
SELECT id, name, path, created_at FROM libraries WHERE id = ? LIMIT 1
SELECT id, name, path, created_at, autotag_warning_acked FROM libraries WHERE id = ? LIMIT 1
`
func (q *Queries) GetLibrary(ctx context.Context, id int64) (Library, error) {
@@ -95,12 +106,13 @@ func (q *Queries) GetLibrary(ctx context.Context, id int64) (Library, error) {
&i.Name,
&i.Path,
&i.CreatedAt,
&i.AutotagWarningAcked,
)
return i, err
}
const getLibraryByPath = `-- name: GetLibraryByPath :one
SELECT id, name, path, created_at FROM libraries WHERE path = ? LIMIT 1
SELECT id, name, path, created_at, autotag_warning_acked FROM libraries WHERE path = ? LIMIT 1
`
func (q *Queries) GetLibraryByPath(ctx context.Context, path string) (Library, error) {
@@ -111,6 +123,7 @@ func (q *Queries) GetLibraryByPath(ctx context.Context, path string) (Library, e
&i.Name,
&i.Path,
&i.CreatedAt,
&i.AutotagWarningAcked,
)
return i, err
}
+24 -4
View File
@@ -48,6 +48,8 @@ type AudioFile struct {
LibraryID int64
PlayCount int64
LastPlayed sql.NullTime
TagStatus string
GroupKey string
}
type CoverArt struct {
@@ -76,10 +78,11 @@ type HttpCache struct {
}
type Library struct {
ID int64
Name string
Path string
CreatedAt time.Time
ID int64
Name string
Path string
CreatedAt time.Time
AutotagWarningAcked int64
}
type PlayHistory struct {
@@ -160,6 +163,7 @@ type ReleaseGroup struct {
CoverArtID sql.NullInt64
AlbumArtistCreditID sql.NullInt64
Year sql.NullInt64
OriginalYear sql.NullInt64
TotalTracks sql.NullInt64
TotalDiscs sql.NullInt64
Mbid sql.NullString
@@ -180,6 +184,21 @@ type SearchIndex struct {
Album string
}
type TaggingItem struct {
GroupKey string
LibraryID int64
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
ClearedAt sql.NullTime
CreatedAt time.Time
}
type TrackMetadatum struct {
ID int64
FilePath string
@@ -191,6 +210,7 @@ type TrackMetadatum struct {
Album string
Genre string
Year int64
ReleaseYear int64
Composer string
FileType string
SampleRate int64
@@ -23,7 +23,7 @@ func (q *Queries) CountReleaseGroupRecordings(ctx context.Context, releaseGroupI
const createReleaseGroup = `-- name: CreateReleaseGroup :one
INSERT INTO release_groups (name) VALUES (?)
RETURNING id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid
RETURNING id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid
`
func (q *Queries) CreateReleaseGroup(ctx context.Context, name string) (ReleaseGroup, error) {
@@ -35,6 +35,7 @@ func (q *Queries) CreateReleaseGroup(ctx context.Context, name string) (ReleaseG
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -46,7 +47,7 @@ const createReleaseGroupFull = `-- name: CreateReleaseGroupFull :one
INSERT INTO release_groups (
name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs
) VALUES (?, ?, ?, ?, ?, ?)
RETURNING id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid
RETURNING id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid
`
type CreateReleaseGroupFullParams struct {
@@ -74,6 +75,7 @@ func (q *Queries) CreateReleaseGroupFull(ctx context.Context, arg CreateReleaseG
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -104,7 +106,8 @@ const getAlbumsByArtist = `-- name: GetAlbumsByArtist :many
SELECT
rg.id,
rg.name,
rg.year,
COALESCE(rg.original_year, rg.year) AS year,
COALESCE(rg.year, 0) AS release_year,
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
COALESCE(ca.file_path, '') as cover_art_path
FROM release_groups rg
@@ -126,6 +129,7 @@ type GetAlbumsByArtistRow struct {
ID int64
Name string
Year sql.NullInt64
ReleaseYear int64
ArtistName string
CoverArtPath string
}
@@ -143,6 +147,7 @@ func (q *Queries) GetAlbumsByArtist(ctx context.Context, artistID int64) ([]GetA
&i.ID,
&i.Name,
&i.Year,
&i.ReleaseYear,
&i.ArtistName,
&i.CoverArtPath,
); err != nil {
@@ -163,7 +168,8 @@ const getAlbumsByArtistByLibrary = `-- name: GetAlbumsByArtistByLibrary :many
SELECT
rg.id,
rg.name,
rg.year,
COALESCE(rg.original_year, rg.year) AS year,
COALESCE(rg.year, 0) AS release_year,
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
COALESCE(ca.file_path, '') as cover_art_path
FROM release_groups rg
@@ -197,6 +203,7 @@ type GetAlbumsByArtistByLibraryRow struct {
ID int64
Name string
Year sql.NullInt64
ReleaseYear int64
ArtistName string
CoverArtPath string
}
@@ -214,6 +221,7 @@ func (q *Queries) GetAlbumsByArtistByLibrary(ctx context.Context, arg GetAlbumsB
&i.ID,
&i.Name,
&i.Year,
&i.ReleaseYear,
&i.ArtistName,
&i.CoverArtPath,
); err != nil {
@@ -234,7 +242,12 @@ const getAllAlbumsWithDetails = `-- name: GetAllAlbumsWithDetails :many
SELECT
rg.id,
rg.name,
rg.year,
-- year prefers original release year (MB first-release-date)
-- over the file-tag year so the UI surfaces the album's
-- original year by default. release_year keeps the file-tag
-- year accessible.
COALESCE(rg.original_year, rg.year) AS year,
COALESCE(rg.year, 0) AS release_year,
rg.mbid,
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
COALESCE(ca.file_path, '') as cover_art_path
@@ -255,6 +268,7 @@ type GetAllAlbumsWithDetailsRow struct {
ID int64
Name string
Year sql.NullInt64
ReleaseYear int64
Mbid sql.NullString
ArtistName string
CoverArtPath string
@@ -273,6 +287,7 @@ func (q *Queries) GetAllAlbumsWithDetails(ctx context.Context) ([]GetAllAlbumsWi
&i.ID,
&i.Name,
&i.Year,
&i.ReleaseYear,
&i.Mbid,
&i.ArtistName,
&i.CoverArtPath,
@@ -294,7 +309,12 @@ const getAllAlbumsWithDetailsByLibrary = `-- name: GetAllAlbumsWithDetailsByLibr
SELECT
rg.id,
rg.name,
rg.year,
-- year prefers original release year (MB first-release-date)
-- over the file-tag year so the UI surfaces the album's
-- original year by default. release_year keeps the file-tag
-- year accessible.
COALESCE(rg.original_year, rg.year) AS year,
COALESCE(rg.year, 0) AS release_year,
rg.mbid,
COALESCE(ac.text, fallback_ac.text, '') as artist_name,
COALESCE(ca.file_path, '') as cover_art_path
@@ -322,6 +342,7 @@ type GetAllAlbumsWithDetailsByLibraryRow struct {
ID int64
Name string
Year sql.NullInt64
ReleaseYear int64
Mbid sql.NullString
ArtistName string
CoverArtPath string
@@ -340,6 +361,7 @@ func (q *Queries) GetAllAlbumsWithDetailsByLibrary(ctx context.Context, libraryI
&i.ID,
&i.Name,
&i.Year,
&i.ReleaseYear,
&i.Mbid,
&i.ArtistName,
&i.CoverArtPath,
@@ -358,7 +380,7 @@ func (q *Queries) GetAllAlbumsWithDetailsByLibrary(ctx context.Context, libraryI
}
const getAllReleaseGroups = `-- name: GetAllReleaseGroups :many
SELECT id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid FROM release_groups
SELECT id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid FROM release_groups
ORDER BY name
`
@@ -377,6 +399,7 @@ func (q *Queries) GetAllReleaseGroups(ctx context.Context) ([]ReleaseGroup, erro
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -395,7 +418,7 @@ func (q *Queries) GetAllReleaseGroups(ctx context.Context) ([]ReleaseGroup, erro
}
const getReleaseGroup = `-- name: GetReleaseGroup :one
SELECT id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid FROM release_groups
SELECT id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid FROM release_groups
WHERE id = ? LIMIT 1
`
@@ -408,6 +431,7 @@ func (q *Queries) GetReleaseGroup(ctx context.Context, id int64) (ReleaseGroup,
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -416,7 +440,7 @@ func (q *Queries) GetReleaseGroup(ctx context.Context, id int64) (ReleaseGroup,
}
const getReleaseGroupByNameAndArtist = `-- name: GetReleaseGroupByNameAndArtist :one
SELECT id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid FROM release_groups
SELECT id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid FROM release_groups
WHERE name = ? AND album_artist_credit_id = ? LIMIT 1
`
@@ -434,6 +458,7 @@ func (q *Queries) GetReleaseGroupByNameAndArtist(ctx context.Context, arg GetRel
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -441,6 +466,24 @@ func (q *Queries) GetReleaseGroupByNameAndArtist(ctx context.Context, arg GetRel
return i, err
}
const setReleaseGroupOriginalYear = `-- name: SetReleaseGroupOriginalYear :exec
UPDATE release_groups SET original_year = ? WHERE id = ?
`
type SetReleaseGroupOriginalYearParams struct {
OriginalYear sql.NullInt64
ID int64
}
// Set the release group's original-release-year (release-group's
// first-release-date from MusicBrainz). Called from autotag apply
// when the user confirms a candidate; the file-tag year stays in
// the year column.
func (q *Queries) SetReleaseGroupOriginalYear(ctx context.Context, arg SetReleaseGroupOriginalYearParams) error {
_, err := q.db.ExecContext(ctx, setReleaseGroupOriginalYear, arg.OriginalYear, arg.ID)
return err
}
const updateReleaseGroup = `-- name: UpdateReleaseGroup :exec
UPDATE release_groups
SET name = ?
@@ -479,7 +522,7 @@ VALUES (?, ?, ?)
ON CONFLICT(name, album_artist_credit_id) DO UPDATE SET
album_artist_credit_id = COALESCE(excluded.album_artist_credit_id, release_groups.album_artist_credit_id),
year = COALESCE(excluded.year, release_groups.year)
RETURNING id, name, cover_art_id, album_artist_credit_id, year, total_tracks, total_discs, mbid
RETURNING id, name, cover_art_id, album_artist_credit_id, year, original_year, total_tracks, total_discs, mbid
`
type UpsertReleaseGroupParams struct {
@@ -497,6 +540,7 @@ func (q *Queries) UpsertReleaseGroup(ctx context.Context, arg UpsertReleaseGroup
&i.CoverArtID,
&i.AlbumArtistCreditID,
&i.Year,
&i.OriginalYear,
&i.TotalTracks,
&i.TotalDiscs,
&i.Mbid,
@@ -0,0 +1,771 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: tagging_items.sql
package sqlcgen
import (
"context"
"database/sql"
"time"
)
const clearCompletedTaggingItems = `-- name: ClearCompletedTaggingItems :exec
UPDATE tagging_items
SET cleared_at = CURRENT_TIMESTAMP
WHERE status = 'confirmed'
AND cleared_at IS NULL
AND (CAST(?1 AS INTEGER) = 0 OR library_id = ?1)
`
func (q *Queries) ClearCompletedTaggingItems(ctx context.Context, libraryID int64) error {
_, err := q.db.ExecContext(ctx, clearCompletedTaggingItems, libraryID)
return err
}
const countPendingTaggingItems = `-- name: CountPendingTaggingItems :one
SELECT COUNT(*) FROM tagging_items
WHERE status = 'pending'
AND (CAST(?1 AS INTEGER) = 0 OR library_id = ?1)
`
func (q *Queries) CountPendingTaggingItems(ctx context.Context, libraryID int64) (int64, error) {
row := q.db.QueryRowContext(ctx, countPendingTaggingItems, libraryID)
var count int64
err := row.Scan(&count)
return count, err
}
const decrementTaggingItemTrackCount = `-- name: DecrementTaggingItemTrackCount :exec
UPDATE tagging_items
SET track_count = track_count - 1
WHERE group_key = ?
`
func (q *Queries) DecrementTaggingItemTrackCount(ctx context.Context, groupKey string) error {
_, err := q.db.ExecContext(ctx, decrementTaggingItemTrackCount, groupKey)
return err
}
const deleteTaggingItemIfEmpty = `-- name: DeleteTaggingItemIfEmpty :exec
DELETE FROM tagging_items
WHERE group_key = ? AND track_count <= 0
`
func (q *Queries) DeleteTaggingItemIfEmpty(ctx context.Context, groupKey string) error {
_, err := q.db.ExecContext(ctx, deleteTaggingItemIfEmpty, groupKey)
return err
}
const getNextPendingTaggingItem = `-- name: GetNextPendingTaggingItem :one
SELECT
ti.group_key,
ti.library_id,
COALESCE(lb.name, '') AS library_name,
ti.track_count,
ti.album_name,
ti.album_artist,
ti.disc_number,
ti.best_match_release_mbid,
ti.score,
ti.last_checked_at,
ti.status,
ti.created_at
FROM tagging_items ti
LEFT JOIN libraries lb ON lb.id = ti.library_id
WHERE ti.status = 'pending'
AND (CAST(?1 AS INTEGER) = 0 OR ti.library_id = ?1)
AND ti.group_key > ?2
ORDER BY ti.group_key
LIMIT 1
`
type GetNextPendingTaggingItemParams struct {
LibraryID int64
AfterGroupKey string
}
type GetNextPendingTaggingItemRow struct {
GroupKey string
LibraryID int64
LibraryName string
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
CreatedAt time.Time
}
func (q *Queries) GetNextPendingTaggingItem(ctx context.Context, arg GetNextPendingTaggingItemParams) (GetNextPendingTaggingItemRow, error) {
row := q.db.QueryRowContext(ctx, getNextPendingTaggingItem, arg.LibraryID, arg.AfterGroupKey)
var i GetNextPendingTaggingItemRow
err := row.Scan(
&i.GroupKey,
&i.LibraryID,
&i.LibraryName,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.CreatedAt,
)
return i, err
}
const getPendingFolderDetail = `-- name: GetPendingFolderDetail :one
SELECT
ti.group_key,
ti.library_id,
COALESCE(lb.name, '') AS library_name,
COALESCE(lb.path, '') AS library_path,
CAST(COALESCE((SELECT af.file_path FROM audio_files af WHERE af.group_key = ti.group_key LIMIT 1), '') AS TEXT) AS sample_file_path,
ti.track_count,
ti.album_name,
ti.album_artist,
ti.disc_number,
ti.best_match_release_mbid,
ti.score,
ti.last_checked_at,
ti.status,
ti.created_at
FROM tagging_items ti
LEFT JOIN libraries lb ON lb.id = ti.library_id
WHERE ti.group_key = ?
LIMIT 1
`
type GetPendingFolderDetailRow struct {
GroupKey string
LibraryID int64
LibraryName string
LibraryPath string
SampleFilePath string
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
CreatedAt time.Time
}
func (q *Queries) GetPendingFolderDetail(ctx context.Context, groupKey string) (GetPendingFolderDetailRow, error) {
row := q.db.QueryRowContext(ctx, getPendingFolderDetail, groupKey)
var i GetPendingFolderDetailRow
err := row.Scan(
&i.GroupKey,
&i.LibraryID,
&i.LibraryName,
&i.LibraryPath,
&i.SampleFilePath,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.CreatedAt,
)
return i, err
}
const getRecordingReleaseGroupID = `-- name: GetRecordingReleaseGroupID :one
SELECT COALESCE(rgr.release_group_id, 0) AS release_group_id
FROM release_group_recordings rgr
WHERE rgr.recording_id = ?
LIMIT 1
`
func (q *Queries) GetRecordingReleaseGroupID(ctx context.Context, recordingID int64) (int64, error) {
row := q.db.QueryRowContext(ctx, getRecordingReleaseGroupID, recordingID)
var release_group_id int64
err := row.Scan(&release_group_id)
return release_group_id, err
}
const getTaggingItem = `-- name: GetTaggingItem :one
SELECT group_key, library_id, track_count, album_name, album_artist, disc_number, best_match_release_mbid, score, last_checked_at, status, cleared_at, created_at FROM tagging_items
WHERE group_key = ?
LIMIT 1
`
func (q *Queries) GetTaggingItem(ctx context.Context, groupKey string) (TaggingItem, error) {
row := q.db.QueryRowContext(ctx, getTaggingItem, groupKey)
var i TaggingItem
err := row.Scan(
&i.GroupKey,
&i.LibraryID,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.ClearedAt,
&i.CreatedAt,
)
return i, err
}
const listAudioFilesInTaggingGroup = `-- name: ListAudioFilesInTaggingGroup :many
SELECT
af.id,
af.file_path,
af.basename,
af.length_milliseconds,
af.tag_status,
COALESCE(r.track_number, 0) AS track_number,
COALESCE(r.disc_number, 0) AS disc_number,
COALESCE(r.name, '') AS title,
COALESCE(ac.text, '') AS artist_name,
COALESCE(r.mbid, '') AS recording_mbid
FROM audio_files af
LEFT JOIN recordings r ON af.recording_id = r.id
LEFT JOIN artist_credit ac ON r.artist_credit_id = ac.id
WHERE af.group_key = ?
ORDER BY COALESCE(r.disc_number, 0),
COALESCE(r.track_number, 0),
af.file_path
`
type ListAudioFilesInTaggingGroupRow struct {
ID int64
FilePath string
Basename string
LengthMilliseconds int64
TagStatus string
TrackNumber int64
DiscNumber int64
Title string
ArtistName string
RecordingMbid string
}
func (q *Queries) ListAudioFilesInTaggingGroup(ctx context.Context, groupKey string) ([]ListAudioFilesInTaggingGroupRow, error) {
rows, err := q.db.QueryContext(ctx, listAudioFilesInTaggingGroup, groupKey)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListAudioFilesInTaggingGroupRow
for rows.Next() {
var i ListAudioFilesInTaggingGroupRow
if err := rows.Scan(
&i.ID,
&i.FilePath,
&i.Basename,
&i.LengthMilliseconds,
&i.TagStatus,
&i.TrackNumber,
&i.DiscNumber,
&i.Title,
&i.ArtistName,
&i.RecordingMbid,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listLocalReleaseGroupCandidates = `-- name: ListLocalReleaseGroupCandidates :many
SELECT
rg.id AS release_group_id,
rg.mbid AS release_group_mbid,
rg.name AS album_name,
COALESCE(rg.year, 0) AS year,
COALESCE(ac.text, '') AS artist_credit,
COALESCE(rgr.track_number, 0) AS track_number,
COALESCE(rgr.disc_number, 0) AS disc_number,
COALESCE(r.name, '') AS track_title,
COALESCE(r.mbid, '') AS recording_mbid,
COALESCE(local_af.length_milliseconds, 0) AS length_milliseconds
FROM release_groups rg
JOIN release_group_recordings rgr ON rgr.release_group_id = rg.id
JOIN recordings r ON r.id = rgr.recording_id
LEFT JOIN artist_credit ac ON rg.album_artist_credit_id = ac.id
LEFT JOIN audio_files local_af ON local_af.recording_id = r.id
WHERE rg.mbid IS NOT NULL
AND rg.mbid != ''
AND r.mbid IS NOT NULL
AND r.mbid != ''
AND rg.name = ? COLLATE NOCASE
ORDER BY rg.id, rgr.disc_number, rgr.track_number
`
type ListLocalReleaseGroupCandidatesRow struct {
ReleaseGroupID int64
ReleaseGroupMbid sql.NullString
AlbumName string
Year int64
ArtistCredit string
TrackNumber int64
DiscNumber int64
TrackTitle string
RecordingMbid string
LengthMilliseconds int64
}
// Returns one row per (release_group, track) combination for any
// local release_group that has an MBID. Callers group these in Go
// and filter by normalized album-name match. Joined case-insensitive
// on name to pre-filter cheaply; Go does the real normalization.
func (q *Queries) ListLocalReleaseGroupCandidates(ctx context.Context, name string) ([]ListLocalReleaseGroupCandidatesRow, error) {
rows, err := q.db.QueryContext(ctx, listLocalReleaseGroupCandidates, name)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListLocalReleaseGroupCandidatesRow
for rows.Next() {
var i ListLocalReleaseGroupCandidatesRow
if err := rows.Scan(
&i.ReleaseGroupID,
&i.ReleaseGroupMbid,
&i.AlbumName,
&i.Year,
&i.ArtistCredit,
&i.TrackNumber,
&i.DiscNumber,
&i.TrackTitle,
&i.RecordingMbid,
&i.LengthMilliseconds,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPendingTaggingItemsAlphabetical = `-- name: ListPendingTaggingItemsAlphabetical :many
SELECT
ti.group_key,
ti.library_id,
COALESCE(lb.name, '') AS library_name,
ti.track_count,
ti.album_name,
ti.album_artist,
ti.disc_number,
ti.best_match_release_mbid,
ti.score,
ti.last_checked_at,
ti.status,
ti.created_at
FROM tagging_items ti
LEFT JOIN libraries lb ON lb.id = ti.library_id
WHERE (CAST(?1 AS INTEGER) = 0 OR ti.library_id = ?1)
AND (CAST(?2 AS TEXT) = 'all' OR ti.status = ?2)
AND ti.cleared_at IS NULL
ORDER BY LOWER(ti.album_artist), LOWER(ti.album_name), ti.disc_number
LIMIT ?4 OFFSET ?3
`
type ListPendingTaggingItemsAlphabeticalParams struct {
LibraryID int64
StatusFilter string
RowOffset int64
RowLimit int64
}
type ListPendingTaggingItemsAlphabeticalRow struct {
GroupKey string
LibraryID int64
LibraryName string
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
CreatedAt time.Time
}
func (q *Queries) ListPendingTaggingItemsAlphabetical(ctx context.Context, arg ListPendingTaggingItemsAlphabeticalParams) ([]ListPendingTaggingItemsAlphabeticalRow, error) {
rows, err := q.db.QueryContext(ctx, listPendingTaggingItemsAlphabetical,
arg.LibraryID,
arg.StatusFilter,
arg.RowOffset,
arg.RowLimit,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPendingTaggingItemsAlphabeticalRow
for rows.Next() {
var i ListPendingTaggingItemsAlphabeticalRow
if err := rows.Scan(
&i.GroupKey,
&i.LibraryID,
&i.LibraryName,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPendingTaggingItemsByRecent = `-- name: ListPendingTaggingItemsByRecent :many
SELECT
ti.group_key,
ti.library_id,
COALESCE(lb.name, '') AS library_name,
ti.track_count,
ti.album_name,
ti.album_artist,
ti.disc_number,
ti.best_match_release_mbid,
ti.score,
ti.last_checked_at,
ti.status,
ti.created_at
FROM tagging_items ti
LEFT JOIN libraries lb ON lb.id = ti.library_id
WHERE (CAST(?1 AS INTEGER) = 0 OR ti.library_id = ?1)
AND (CAST(?2 AS TEXT) = 'all' OR ti.status = ?2)
ORDER BY ti.created_at DESC, ti.group_key
LIMIT ?4 OFFSET ?3
`
type ListPendingTaggingItemsByRecentParams struct {
LibraryID int64
StatusFilter string
RowOffset int64
RowLimit int64
}
type ListPendingTaggingItemsByRecentRow struct {
GroupKey string
LibraryID int64
LibraryName string
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
CreatedAt time.Time
}
func (q *Queries) ListPendingTaggingItemsByRecent(ctx context.Context, arg ListPendingTaggingItemsByRecentParams) ([]ListPendingTaggingItemsByRecentRow, error) {
rows, err := q.db.QueryContext(ctx, listPendingTaggingItemsByRecent,
arg.LibraryID,
arg.StatusFilter,
arg.RowOffset,
arg.RowLimit,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPendingTaggingItemsByRecentRow
for rows.Next() {
var i ListPendingTaggingItemsByRecentRow
if err := rows.Scan(
&i.GroupKey,
&i.LibraryID,
&i.LibraryName,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listPendingTaggingItemsByScore = `-- name: ListPendingTaggingItemsByScore :many
SELECT
ti.group_key,
ti.library_id,
COALESCE(lb.name, '') AS library_name,
COALESCE(lb.path, '') AS library_path,
CAST(COALESCE((SELECT af.file_path FROM audio_files af WHERE af.group_key = ti.group_key LIMIT 1), '') AS TEXT) AS sample_file_path,
ti.track_count,
ti.album_name,
ti.album_artist,
ti.disc_number,
ti.best_match_release_mbid,
ti.score,
ti.last_checked_at,
ti.status,
ti.created_at
FROM tagging_items ti
LEFT JOIN libraries lb ON lb.id = ti.library_id
WHERE (CAST(?1 AS INTEGER) = 0 OR ti.library_id = ?1)
AND (CAST(?2 AS TEXT) = 'all' OR ti.status = ?2)
AND ti.cleared_at IS NULL
ORDER BY ti.score IS NULL, ti.score DESC, LOWER(ti.album_artist), LOWER(ti.album_name)
LIMIT ?4 OFFSET ?3
`
type ListPendingTaggingItemsByScoreParams struct {
LibraryID int64
StatusFilter string
RowOffset int64
RowLimit int64
}
type ListPendingTaggingItemsByScoreRow struct {
GroupKey string
LibraryID int64
LibraryName string
LibraryPath string
SampleFilePath string
TrackCount int64
AlbumName string
AlbumArtist string
DiscNumber int64
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
LastCheckedAt sql.NullTime
Status string
CreatedAt time.Time
}
func (q *Queries) ListPendingTaggingItemsByScore(ctx context.Context, arg ListPendingTaggingItemsByScoreParams) ([]ListPendingTaggingItemsByScoreRow, error) {
rows, err := q.db.QueryContext(ctx, listPendingTaggingItemsByScore,
arg.LibraryID,
arg.StatusFilter,
arg.RowOffset,
arg.RowLimit,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListPendingTaggingItemsByScoreRow
for rows.Next() {
var i ListPendingTaggingItemsByScoreRow
if err := rows.Scan(
&i.GroupKey,
&i.LibraryID,
&i.LibraryName,
&i.LibraryPath,
&i.SampleFilePath,
&i.TrackCount,
&i.AlbumName,
&i.AlbumArtist,
&i.DiscNumber,
&i.BestMatchReleaseMbid,
&i.Score,
&i.LastCheckedAt,
&i.Status,
&i.CreatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const setAudioFileTagStatus = `-- name: SetAudioFileTagStatus :exec
UPDATE audio_files SET tag_status = ? WHERE id = ?
`
type SetAudioFileTagStatusParams struct {
TagStatus string
ID int64
}
func (q *Queries) SetAudioFileTagStatus(ctx context.Context, arg SetAudioFileTagStatusParams) error {
_, err := q.db.ExecContext(ctx, setAudioFileTagStatus, arg.TagStatus, arg.ID)
return err
}
const setRecordingMBID = `-- name: SetRecordingMBID :exec
UPDATE recordings SET mbid = ? WHERE id = ?
`
type SetRecordingMBIDParams struct {
Mbid sql.NullString
ID int64
}
func (q *Queries) SetRecordingMBID(ctx context.Context, arg SetRecordingMBIDParams) error {
_, err := q.db.ExecContext(ctx, setRecordingMBID, arg.Mbid, arg.ID)
return err
}
const setReleaseGroupMBID = `-- name: SetReleaseGroupMBID :exec
UPDATE release_groups SET mbid = ? WHERE id = ?
`
type SetReleaseGroupMBIDParams struct {
Mbid sql.NullString
ID int64
}
func (q *Queries) SetReleaseGroupMBID(ctx context.Context, arg SetReleaseGroupMBIDParams) error {
_, err := q.db.ExecContext(ctx, setReleaseGroupMBID, arg.Mbid, arg.ID)
return err
}
const setTaggingItemBestMatch = `-- name: SetTaggingItemBestMatch :exec
UPDATE tagging_items
SET best_match_release_mbid = ?,
score = ?,
status = ?,
last_checked_at = CURRENT_TIMESTAMP
WHERE group_key = ?
`
type SetTaggingItemBestMatchParams struct {
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
Status string
GroupKey string
}
func (q *Queries) SetTaggingItemBestMatch(ctx context.Context, arg SetTaggingItemBestMatchParams) error {
_, err := q.db.ExecContext(ctx, setTaggingItemBestMatch,
arg.BestMatchReleaseMbid,
arg.Score,
arg.Status,
arg.GroupKey,
)
return err
}
const setTaggingItemScore = `-- name: SetTaggingItemScore :exec
UPDATE tagging_items
SET best_match_release_mbid = ?,
score = ?,
last_checked_at = CURRENT_TIMESTAMP
WHERE group_key = ?
`
type SetTaggingItemScoreParams struct {
BestMatchReleaseMbid sql.NullString
Score sql.NullFloat64
GroupKey string
}
func (q *Queries) SetTaggingItemScore(ctx context.Context, arg SetTaggingItemScoreParams) error {
_, err := q.db.ExecContext(ctx, setTaggingItemScore, arg.BestMatchReleaseMbid, arg.Score, arg.GroupKey)
return err
}
const setTaggingItemStatus = `-- name: SetTaggingItemStatus :exec
UPDATE tagging_items
SET status = ?,
last_checked_at = CURRENT_TIMESTAMP
WHERE group_key = ?
`
type SetTaggingItemStatusParams struct {
Status string
GroupKey string
}
func (q *Queries) SetTaggingItemStatus(ctx context.Context, arg SetTaggingItemStatusParams) error {
_, err := q.db.ExecContext(ctx, setTaggingItemStatus, arg.Status, arg.GroupKey)
return err
}
const upsertTaggingItemOnTrackAdd = `-- name: UpsertTaggingItemOnTrackAdd :exec
INSERT INTO tagging_items (
group_key, library_id, track_count,
album_name, album_artist, disc_number, status
)
VALUES (?, ?, 1, ?, ?, ?, 'pending')
ON CONFLICT(group_key) DO UPDATE SET
track_count = tagging_items.track_count + 1,
album_name = CASE
WHEN tagging_items.album_name = '' THEN excluded.album_name
ELSE tagging_items.album_name
END,
album_artist = CASE
WHEN tagging_items.album_artist = '' THEN excluded.album_artist
ELSE tagging_items.album_artist
END
`
type UpsertTaggingItemOnTrackAddParams struct {
GroupKey string
LibraryID int64
AlbumName string
AlbumArtist string
DiscNumber int64
}
func (q *Queries) UpsertTaggingItemOnTrackAdd(ctx context.Context, arg UpsertTaggingItemOnTrackAddParams) error {
_, err := q.db.ExecContext(ctx, upsertTaggingItemOnTrackAdd,
arg.GroupKey,
arg.LibraryID,
arg.AlbumName,
arg.AlbumArtist,
arg.DiscNumber,
)
return err
}