#9 Major routes refactor and expansion, #15 Added API for statistics, Added search cache backend and functionality tests, Backend sync improvements
Build / build (push) Successful in 56s

This commit is contained in:
Sansan committed 2026-09-26 16:48:40 +02:00
1 parent e86c0f8e04
commit a8a2602f50
34 files changed
+1819 -1294

No files matched your search

+10 -7
View File
@@ -7,6 +7,7 @@ package repository
import (
"time"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
@@ -20,13 +21,14 @@ type Session struct {
}
type Song struct {
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
TimesPlayed int32 `json:"times_played"`
Hash string `json:"hash"`
FileName *string `json:"file_name"`
ID pgtype.Int4 `json:"id"`
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
TimesPlayed int32 `json:"times_played"`
Hash string `json:"hash"`
FileName *string `json:"file_name"`
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
type SongList struct {
@@ -48,6 +50,7 @@ type Soundtrack struct {
LastPlayed *time.Time `json:"last_played"`
NumberOfSongs int32 `json:"number_of_songs"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
}
type Vgmq struct {
+93 -21
View File
@@ -8,7 +8,7 @@ package repository
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
"github.com/google/uuid"
)
const addHashToSong = `-- name: AddHashToSong :exec
@@ -27,15 +27,17 @@ func (q *Queries) AddHashToSong(ctx context.Context, arg AddHashToSongParams) er
}
const addSong = `-- name: AddSong :exec
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5)
INSERT INTO song(soundtrack_id, song_name, path, file_name, hash, uuid, soundtrack_uuid) VALUES ($1, $2, $3, $4, $5, $6, $7)
`
type AddSongParams struct {
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
FileName *string `json:"file_name"`
Hash string `json:"hash"`
SoundtrackID int32 `json:"soundtrack_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
FileName *string `json:"file_name"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
@@ -45,6 +47,8 @@ func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
arg.Path,
arg.FileName,
arg.Hash,
arg.Uuid,
arg.SoundtrackUuid,
)
return err
}
@@ -110,7 +114,7 @@ func (q *Queries) ClearSongsBySoundtrackId(ctx context.Context, soundtrackID int
}
const fetchAllSongs = `-- name: FetchAllSongs :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song
`
func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
@@ -129,7 +133,8 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
@@ -142,7 +147,7 @@ func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
}
const findSongsFromSoundtrack = `-- name: FindSongsFromSoundtrack :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid
FROM song
WHERE soundtrack_id = $1
`
@@ -163,7 +168,8 @@ func (q *Queries) FindSongsFromSoundtrack(ctx context.Context, soundtrackID int3
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
@@ -175,12 +181,12 @@ func (q *Queries) FindSongsFromSoundtrack(ctx context.Context, soundtrackID int3
return items, nil
}
const getSongById = `-- name: GetSongById :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song WHERE id = $1
const getSongByUUID = `-- name: GetSongByUUID :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song WHERE uuid = $1
`
func (q *Queries) GetSongById(ctx context.Context, id pgtype.Int4) (Song, error) {
row := q.db.QueryRow(ctx, getSongById, id)
func (q *Queries) GetSongByUUID(ctx context.Context, argUuid uuid.UUID) (Song, error) {
row := q.db.QueryRow(ctx, getSongByUUID, argUuid)
var i Song
err := row.Scan(
&i.SoundtrackID,
@@ -189,13 +195,43 @@ func (q *Queries) GetSongById(ctx context.Context, id pgtype.Int4) (Song, error)
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
)
return i, err
}
const getSongUUIDsBySoundtrackId = `-- name: GetSongUUIDsBySoundtrackId :many
SELECT uuid, soundtrack_uuid FROM song WHERE soundtrack_id = $1
`
type GetSongUUIDsBySoundtrackIdRow struct {
Uuid uuid.UUID `json:"uuid"`
SoundtrackUuid uuid.UUID `json:"soundtrack_uuid"`
}
func (q *Queries) GetSongUUIDsBySoundtrackId(ctx context.Context, soundtrackID int32) ([]GetSongUUIDsBySoundtrackIdRow, error) {
rows, err := q.db.Query(ctx, getSongUUIDsBySoundtrackId, soundtrackID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetSongUUIDsBySoundtrackIdRow
for rows.Next() {
var i GetSongUUIDsBySoundtrackIdRow
if err := rows.Scan(&i.Uuid, &i.SoundtrackUuid); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSongWithHash = `-- name: GetSongWithHash :one
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, id FROM song WHERE hash = $1
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid FROM song WHERE hash = $1
`
func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error) {
@@ -208,11 +244,47 @@ func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.ID,
&i.Uuid,
&i.SoundtrackUuid,
)
return i, err
}
const getSongsBySoundtrackUUID = `-- name: GetSongsBySoundtrackUUID :many
SELECT soundtrack_id, song_name, path, times_played, hash, file_name, uuid, soundtrack_uuid
FROM song
WHERE soundtrack_uuid = $1
`
func (q *Queries) GetSongsBySoundtrackUUID(ctx context.Context, soundtrackUuid uuid.UUID) ([]Song, error) {
rows, err := q.db.Query(ctx, getSongsBySoundtrackUUID, soundtrackUuid)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Song
for rows.Next() {
var i Song
if err := rows.Scan(
&i.SoundtrackID,
&i.SongName,
&i.Path,
&i.TimesPlayed,
&i.Hash,
&i.FileName,
&i.Uuid,
&i.SoundtrackUuid,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const removeBrokenSong = `-- name: RemoveBrokenSong :exec
DELETE FROM song WHERE soundtrack_id = $1 AND path = $2
`
@@ -228,11 +300,11 @@ func (q *Queries) RemoveBrokenSong(ctx context.Context, arg RemoveBrokenSongPara
}
const removeBrokenSongs = `-- name: RemoveBrokenSongs :exec
DELETE FROM song WHERE id = ANY($1)
DELETE FROM song WHERE uuid = ANY($1)
`
func (q *Queries) RemoveBrokenSongs(ctx context.Context, id pgtype.Int4) error {
_, err := q.db.Exec(ctx, removeBrokenSongs, id)
func (q *Queries) RemoveBrokenSongs(ctx context.Context, argUuid uuid.UUID) error {
_, err := q.db.Exec(ctx, removeBrokenSongs, argUuid)
return err
}
+65 -12
View File
@@ -7,6 +7,8 @@ package repository
import (
"context"
"github.com/google/uuid"
)
const addSoundtrackPlayed = `-- name: AddSoundtrackPlayed :exec
@@ -28,7 +30,7 @@ func (q *Queries) ClearSoundtracks(ctx context.Context) error {
}
const findAllSoundtracks = `-- name: FindAllSoundtracks :many
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE deleted IS NULL
ORDER BY soundtrack_name
@@ -54,6 +56,7 @@ func (q *Queries) FindAllSoundtracks(ctx context.Context) ([]Soundtrack, error)
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
); err != nil {
return nil, err
}
@@ -66,7 +69,7 @@ func (q *Queries) FindAllSoundtracks(ctx context.Context) ([]Soundtrack, error)
}
const getAllSoundtracksIncludingDeleted = `-- name: GetAllSoundtracksIncludingDeleted :many
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
ORDER BY soundtrack_name
`
@@ -91,6 +94,7 @@ func (q *Queries) GetAllSoundtracksIncludingDeleted(ctx context.Context) ([]Soun
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
); err != nil {
return nil, err
}
@@ -114,7 +118,7 @@ func (q *Queries) GetIdBySoundtrackName(ctx context.Context, soundtrackName stri
}
const getSoundtrackById = `-- name: GetSoundtrackById :one
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE id = $1
AND deleted IS NULL
@@ -134,6 +138,33 @@ func (q *Queries) GetSoundtrackById(ctx context.Context, id int32) (Soundtrack,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
)
return i, err
}
const getSoundtrackByUUID = `-- name: GetSoundtrackByUUID :one
SELECT id, soundtrack_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash, uuid
FROM soundtrack
WHERE uuid = $1
AND deleted IS NULL
`
func (q *Queries) GetSoundtrackByUUID(ctx context.Context, argUuid uuid.UUID) (Soundtrack, error) {
row := q.db.QueryRow(ctx, getSoundtrackByUUID, argUuid)
var i Soundtrack
err := row.Scan(
&i.ID,
&i.SoundtrackName,
&i.Added,
&i.Deleted,
&i.LastChanged,
&i.Path,
&i.TimesPlayed,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
&i.Uuid,
)
return i, err
}
@@ -149,21 +180,43 @@ func (q *Queries) GetSoundtrackNameById(ctx context.Context, id int32) (string,
return soundtrack_name, err
}
const getSoundtrackUUIDById = `-- name: GetSoundtrackUUIDById :one
SELECT uuid FROM soundtrack WHERE id = $1
`
func (q *Queries) GetSoundtrackUUIDById(ctx context.Context, id int32) (uuid.UUID, error) {
row := q.db.QueryRow(ctx, getSoundtrackUUIDById, id)
var uuid uuid.UUID
err := row.Scan(&uuid)
return uuid, err
}
const insertSoundtrack = `-- name: InsertSoundtrack :one
INSERT INTO soundtrack (soundtrack_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id
INSERT INTO soundtrack (soundtrack_name, path, hash, added, uuid) VALUES ($1, $2, $3, now(), $4) returning id, uuid
`
type InsertSoundtrackParams struct {
SoundtrackName string `json:"soundtrack_name"`
Path string `json:"path"`
Hash string `json:"hash"`
SoundtrackName string `json:"soundtrack_name"`
Path string `json:"path"`
Hash string `json:"hash"`
Uuid uuid.UUID `json:"uuid"`
}
func (q *Queries) InsertSoundtrack(ctx context.Context, arg InsertSoundtrackParams) (int32, error) {
row := q.db.QueryRow(ctx, insertSoundtrack, arg.SoundtrackName, arg.Path, arg.Hash)
var id int32
err := row.Scan(&id)
return id, err
type InsertSoundtrackRow struct {
ID int32 `json:"id"`
Uuid uuid.UUID `json:"uuid"`
}
func (q *Queries) InsertSoundtrack(ctx context.Context, arg InsertSoundtrackParams) (InsertSoundtrackRow, error) {
row := q.db.QueryRow(ctx, insertSoundtrack,
arg.SoundtrackName,
arg.Path,
arg.Hash,
arg.Uuid,
)
var i InsertSoundtrackRow
err := row.Scan(&i.ID, &i.Uuid)
return i, err
}
const insertSoundtrackWithExistingId = `-- name: InsertSoundtrackWithExistingId :exec
+65 -65
View File
@@ -66,63 +66,6 @@ func (q *Queries) GetLastPlayedSoundtracks(ctx context.Context, limit int32) ([]
return items, nil
}
const getLeastPlayedSoundtracksWithSongs = `-- name: GetLeastPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
json_agg(
json_build_object(
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played ASC, g.soundtrack_name
LIMIT $1
`
type GetLeastPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"`
Songs []byte `json:"songs"`
}
// Least played soundtracks with their songs
func (q *Queries) GetLeastPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetLeastPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getLeastPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetLeastPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetLeastPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
&i.SoundtrackPlayed,
&i.SoundtrackLastPlayed,
&i.Songs,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getLeastPlayedSongsWithSoundtrack = `-- name: GetLeastPlayedSongsWithSoundtrack :many
SELECT
s.soundtrack_id as soundtrack_id,
@@ -175,7 +118,7 @@ func (q *Queries) GetLeastPlayedSongsWithSoundtrack(ctx context.Context, limit i
return items, nil
}
const getMostPlayedSoundtracksWithSongs = `-- name: GetMostPlayedSoundtracksWithSongs :many
const getLeastPlayedSoundtracksWithSongs = `-- name: GetLeastPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
@@ -193,11 +136,11 @@ FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played DESC, g.soundtrack_name
ORDER BY g.times_played ASC, g.soundtrack_name
LIMIT $1
`
type GetMostPlayedSoundtracksWithSongsRow struct {
type GetLeastPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
@@ -205,16 +148,16 @@ type GetMostPlayedSoundtracksWithSongsRow struct {
Songs []byte `json:"songs"`
}
// Most played soundtracks with their songs
func (q *Queries) GetMostPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetMostPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getMostPlayedSoundtracksWithSongs, limit)
// Least played soundtracks with their songs
func (q *Queries) GetLeastPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetLeastPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getLeastPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetMostPlayedSoundtracksWithSongsRow
var items []GetLeastPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetMostPlayedSoundtracksWithSongsRow
var i GetLeastPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
@@ -284,6 +227,63 @@ func (q *Queries) GetMostPlayedSongsWithSoundtrack(ctx context.Context, limit in
return items, nil
}
const getMostPlayedSoundtracksWithSongs = `-- name: GetMostPlayedSoundtracksWithSongs :many
SELECT
g.id as soundtrack_id,
g.soundtrack_name,
g.times_played as soundtrack_played,
g.last_played as soundtrack_last_played,
json_agg(
json_build_object(
'song_name', s.song_name,
'path', s.path,
'times_played', s.times_played,
'file_name', s.file_name
)
) as songs
FROM soundtrack g
LEFT JOIN song s ON g.id = s.soundtrack_id
WHERE g.deleted IS NULL
GROUP BY g.id, g.soundtrack_name, g.times_played, g.last_played
ORDER BY g.times_played DESC, g.soundtrack_name
LIMIT $1
`
type GetMostPlayedSoundtracksWithSongsRow struct {
SoundtrackID int32 `json:"soundtrack_id"`
SoundtrackName string `json:"soundtrack_name"`
SoundtrackPlayed int32 `json:"soundtrack_played"`
SoundtrackLastPlayed *time.Time `json:"soundtrack_last_played"`
Songs []byte `json:"songs"`
}
// Most played soundtracks with their songs
func (q *Queries) GetMostPlayedSoundtracksWithSongs(ctx context.Context, limit int32) ([]GetMostPlayedSoundtracksWithSongsRow, error) {
rows, err := q.db.Query(ctx, getMostPlayedSoundtracksWithSongs, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetMostPlayedSoundtracksWithSongsRow
for rows.Next() {
var i GetMostPlayedSoundtracksWithSongsRow
if err := rows.Scan(
&i.SoundtrackID,
&i.SoundtrackName,
&i.SoundtrackPlayed,
&i.SoundtrackLastPlayed,
&i.Songs,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getNeverPlayedSoundtracks = `-- name: GetNeverPlayedSoundtracks :many
SELECT
g.id as soundtrack_id,