Koito/internal/repository/release.sql.go
Gabe Farrell 36f984a1a2
Pre-release version v0.0.14 (#96)
* add dev branch container to workflow

* correctly set the default range of ActivityGrid

* fix: set name/short_name to koito (#61)

* fix dev container push workflow

* fix: race condition with using getComputedStyle primary color for dynamic activity grid darkening (#76)

* Fix race condition with using getComputedStyle primary color for dynamic activity grid darkening

Instead just use the color from the current theme directly. Tested works on initial load and theme changes.
Fixes https://github.com/gabehf/Koito/issues/75

* Rework theme provider to provide the actual Theme object throughtout the app, in addition to the name
Split name out of the Theme struct to simplify custom theme saving/reading

* fix: set first artist listed as primary by default (#81)

* feat: add server-side configuration with default theme (#90)

* docs: add example for usage of the main listenbrainz instance (#71)

* docs: add example for usage of the main listenbrainz instance

* Update scrobbler.md

---------

Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>

* feat: add server-side cfg and default theme

* fix: repair custom theme

---------

Co-authored-by: m0d3rnX <jesper@posteo.de>

* docs: add default theme cfg option to docs

* feat: add ability to manually scrobble track (#91)

* feat: add button to manually scrobble from ui

* fix: ensure timestamp is in the past, log fix

* test: add integration test

* feat: add first listened to dates for media items (#92)

* fix: ensure error checks for ErrNoRows

* feat: add now playing endpoint and ui (#93)

* wip

* feat: add now playing

* fix: set default theme when config is not set

* feat: fetch images from subsonic server (#94)

* fix: useQuery instead of useEffect for now playing

* feat: custom artist separator regex (#95)

* Fix race condition with using getComputedStyle primary color for dynamic activity grid darkening

Instead just use the color from the current theme directly. Tested works on initial load and theme changes.
Fixes https://github.com/gabehf/Koito/issues/75

* Rework theme provider to provide the actual Theme object throughtout the app, in addition to the name
Split name out of the Theme struct to simplify custom theme saving/reading

* feat: add server-side configuration with default theme (#90)

* docs: add example for usage of the main listenbrainz instance (#71)

* docs: add example for usage of the main listenbrainz instance

* Update scrobbler.md

---------

Co-authored-by: Gabe Farrell <90876006+gabehf@users.noreply.github.com>

* feat: add server-side cfg and default theme

* fix: repair custom theme

---------

Co-authored-by: m0d3rnX <jesper@posteo.de>

* fix: rebase errors

---------

Co-authored-by: pet <128837728+againstpetra@users.noreply.github.com>
Co-authored-by: mlandry <mike.landry@gmail.com>
Co-authored-by: m0d3rnX <jesper@posteo.de>
2025-11-19 20:26:56 -05:00

493 lines
12 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: release.sql
package repository
import (
"context"
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
const associateArtistToRelease = `-- name: AssociateArtistToRelease :exec
INSERT INTO artist_releases (artist_id, release_id, is_primary)
VALUES ($1, $2, $3)
ON CONFLICT DO NOTHING
`
type AssociateArtistToReleaseParams struct {
ArtistID int32
ReleaseID int32
IsPrimary bool
}
func (q *Queries) AssociateArtistToRelease(ctx context.Context, arg AssociateArtistToReleaseParams) error {
_, err := q.db.Exec(ctx, associateArtistToRelease, arg.ArtistID, arg.ReleaseID, arg.IsPrimary)
return err
}
const countReleasesFromArtist = `-- name: CountReleasesFromArtist :one
SELECT COUNT(*)
FROM releases r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE ar.artist_id = $1
`
func (q *Queries) CountReleasesFromArtist(ctx context.Context, artistID int32) (int64, error) {
row := q.db.QueryRow(ctx, countReleasesFromArtist, artistID)
var count int64
err := row.Scan(&count)
return count, err
}
const countTopReleases = `-- name: CountTopReleases :one
SELECT COUNT(DISTINCT r.id) AS total_count
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
`
type CountTopReleasesParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
}
func (q *Queries) CountTopReleases(ctx context.Context, arg CountTopReleasesParams) (int64, error) {
row := q.db.QueryRow(ctx, countTopReleases, arg.ListenedAt, arg.ListenedAt_2)
var total_count int64
err := row.Scan(&total_count)
return total_count, err
}
const deleteRelease = `-- name: DeleteRelease :exec
DELETE FROM releases WHERE id = $1
`
func (q *Queries) DeleteRelease(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, deleteRelease, id)
return err
}
const deleteReleasesFromArtist = `-- name: DeleteReleasesFromArtist :exec
DELETE FROM releases r
USING artist_releases ar
WHERE ar.release_id = r.id
AND ar.artist_id = $1
`
func (q *Queries) DeleteReleasesFromArtist(ctx context.Context, artistID int32) error {
_, err := q.db.Exec(ctx, deleteReleasesFromArtist, artistID)
return err
}
const getRelease = `-- name: GetRelease :one
SELECT
id, musicbrainz_id, image, various_artists, image_source, title,
get_artists_for_release(id) AS artists
FROM releases_with_title
WHERE id = $1 LIMIT 1
`
type GetReleaseRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
Artists []byte
}
func (q *Queries) GetRelease(ctx context.Context, id int32) (GetReleaseRow, error) {
row := q.db.QueryRow(ctx, getRelease, id)
var i GetReleaseRow
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.Artists,
)
return i, err
}
const getReleaseByArtistAndTitle = `-- name: GetReleaseByArtistAndTitle :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = $1 AND ar.artist_id = $2
LIMIT 1
`
type GetReleaseByArtistAndTitleParams struct {
Title string
ArtistID int32
}
func (q *Queries) GetReleaseByArtistAndTitle(ctx context.Context, arg GetReleaseByArtistAndTitleParams) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByArtistAndTitle, arg.Title, arg.ArtistID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleaseByArtistAndTitles = `-- name: GetReleaseByArtistAndTitles :one
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
FROM releases_with_title r
JOIN artist_releases ar ON r.id = ar.release_id
WHERE r.title = ANY ($1::TEXT[]) AND ar.artist_id = $2
LIMIT 1
`
type GetReleaseByArtistAndTitlesParams struct {
Column1 []string
ArtistID int32
}
func (q *Queries) GetReleaseByArtistAndTitles(ctx context.Context, arg GetReleaseByArtistAndTitlesParams) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByArtistAndTitles, arg.Column1, arg.ArtistID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleaseByImageID = `-- name: GetReleaseByImageID :one
SELECT id, musicbrainz_id, image, various_artists, image_source FROM releases
WHERE image = $1 LIMIT 1
`
func (q *Queries) GetReleaseByImageID(ctx context.Context, image *uuid.UUID) (Release, error) {
row := q.db.QueryRow(ctx, getReleaseByImageID, image)
var i Release
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
)
return i, err
}
const getReleaseByMbzID = `-- name: GetReleaseByMbzID :one
SELECT id, musicbrainz_id, image, various_artists, image_source, title FROM releases_with_title
WHERE musicbrainz_id = $1 LIMIT 1
`
func (q *Queries) GetReleaseByMbzID(ctx context.Context, musicbrainzID *uuid.UUID) (ReleasesWithTitle, error) {
row := q.db.QueryRow(ctx, getReleaseByMbzID, musicbrainzID)
var i ReleasesWithTitle
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
)
return i, err
}
const getReleasesWithoutImages = `-- name: GetReleasesWithoutImages :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
get_artists_for_release(r.id) AS artists
FROM releases_with_title r
WHERE r.image IS NULL
AND r.id > $2
ORDER BY r.id ASC
LIMIT $1
`
type GetReleasesWithoutImagesParams struct {
Limit int32
ID int32
}
type GetReleasesWithoutImagesRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
Artists []byte
}
func (q *Queries) GetReleasesWithoutImages(ctx context.Context, arg GetReleasesWithoutImagesParams) ([]GetReleasesWithoutImagesRow, error) {
rows, err := q.db.Query(ctx, getReleasesWithoutImages, arg.Limit, arg.ID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetReleasesWithoutImagesRow
for rows.Next() {
var i GetReleasesWithoutImagesRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopReleasesFromArtist = `-- name: GetTopReleasesFromArtist :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
COUNT(*) AS listen_count,
get_artists_for_release(r.id) AS artists
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases_with_title r ON t.release_id = r.id
JOIN artist_releases ar ON r.id = ar.release_id
WHERE ar.artist_id = $5
AND l.listened_at BETWEEN $1 AND $2
GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
ORDER BY listen_count DESC, r.id
LIMIT $3 OFFSET $4
`
type GetTopReleasesFromArtistParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
ArtistID int32
}
type GetTopReleasesFromArtistRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopReleasesFromArtist(ctx context.Context, arg GetTopReleasesFromArtistParams) ([]GetTopReleasesFromArtistRow, error) {
rows, err := q.db.Query(ctx, getTopReleasesFromArtist,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
arg.ArtistID,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopReleasesFromArtistRow
for rows.Next() {
var i GetTopReleasesFromArtistRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getTopReleasesPaginated = `-- name: GetTopReleasesPaginated :many
SELECT
r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title,
COUNT(*) AS listen_count,
get_artists_for_release(r.id) AS artists
FROM listens l
JOIN tracks t ON l.track_id = t.id
JOIN releases_with_title r ON t.release_id = r.id
WHERE l.listened_at BETWEEN $1 AND $2
GROUP BY r.id, r.title, r.musicbrainz_id, r.various_artists, r.image, r.image_source
ORDER BY listen_count DESC, r.id
LIMIT $3 OFFSET $4
`
type GetTopReleasesPaginatedParams struct {
ListenedAt time.Time
ListenedAt_2 time.Time
Limit int32
Offset int32
}
type GetTopReleasesPaginatedRow struct {
ID int32
MusicBrainzID *uuid.UUID
Image *uuid.UUID
VariousArtists bool
ImageSource pgtype.Text
Title string
ListenCount int64
Artists []byte
}
func (q *Queries) GetTopReleasesPaginated(ctx context.Context, arg GetTopReleasesPaginatedParams) ([]GetTopReleasesPaginatedRow, error) {
rows, err := q.db.Query(ctx, getTopReleasesPaginated,
arg.ListenedAt,
arg.ListenedAt_2,
arg.Limit,
arg.Offset,
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetTopReleasesPaginatedRow
for rows.Next() {
var i GetTopReleasesPaginatedRow
if err := rows.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
&i.Title,
&i.ListenCount,
&i.Artists,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertRelease = `-- name: InsertRelease :one
INSERT INTO releases (musicbrainz_id, various_artists, image, image_source)
VALUES ($1, $2, $3, $4)
RETURNING id, musicbrainz_id, image, various_artists, image_source
`
type InsertReleaseParams struct {
MusicBrainzID *uuid.UUID
VariousArtists bool
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) InsertRelease(ctx context.Context, arg InsertReleaseParams) (Release, error) {
row := q.db.QueryRow(ctx, insertRelease,
arg.MusicBrainzID,
arg.VariousArtists,
arg.Image,
arg.ImageSource,
)
var i Release
err := row.Scan(
&i.ID,
&i.MusicBrainzID,
&i.Image,
&i.VariousArtists,
&i.ImageSource,
)
return i, err
}
const updateReleaseImage = `-- name: UpdateReleaseImage :exec
UPDATE releases SET image = $2, image_source = $3
WHERE id = $1
`
type UpdateReleaseImageParams struct {
ID int32
Image *uuid.UUID
ImageSource pgtype.Text
}
func (q *Queries) UpdateReleaseImage(ctx context.Context, arg UpdateReleaseImageParams) error {
_, err := q.db.Exec(ctx, updateReleaseImage, arg.ID, arg.Image, arg.ImageSource)
return err
}
const updateReleaseMbzID = `-- name: UpdateReleaseMbzID :exec
UPDATE releases SET musicbrainz_id = $2
WHERE id = $1
`
type UpdateReleaseMbzIDParams struct {
ID int32
MusicBrainzID *uuid.UUID
}
func (q *Queries) UpdateReleaseMbzID(ctx context.Context, arg UpdateReleaseMbzIDParams) error {
_, err := q.db.Exec(ctx, updateReleaseMbzID, arg.ID, arg.MusicBrainzID)
return err
}
const updateReleasePrimaryArtist = `-- name: UpdateReleasePrimaryArtist :exec
UPDATE artist_releases SET is_primary = $3
WHERE artist_id = $1 AND release_id = $2
`
type UpdateReleasePrimaryArtistParams struct {
ArtistID int32
ReleaseID int32
IsPrimary bool
}
func (q *Queries) UpdateReleasePrimaryArtist(ctx context.Context, arg UpdateReleasePrimaryArtistParams) error {
_, err := q.db.Exec(ctx, updateReleasePrimaryArtist, arg.ArtistID, arg.ReleaseID, arg.IsPrimary)
return err
}
const updateReleaseVariousArtists = `-- name: UpdateReleaseVariousArtists :exec
UPDATE releases SET various_artists = $2
WHERE id = $1
`
type UpdateReleaseVariousArtistsParams struct {
ID int32
VariousArtists bool
}
func (q *Queries) UpdateReleaseVariousArtists(ctx context.Context, arg UpdateReleaseVariousArtistsParams) error {
_, err := q.db.Exec(ctx, updateReleaseVariousArtists, arg.ID, arg.VariousArtists)
return err
}