Added a new sync that uses hash
Added a new sync that uses hash and sqlc for the queries. Added db migration. Started adding a config file.
This commit is contained in:
@@ -8,7 +8,6 @@ import (
|
||||
//go:embed swagger
|
||||
var swagger embed.FS
|
||||
|
||||
|
||||
//go:embed search
|
||||
var search embed.FS
|
||||
|
||||
|
||||
4
db/migrations/000001_create_tables.down.sql
Normal file
4
db/migrations/000001_create_tables.down.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
DROP TABLE game;
|
||||
DROP TABLE song;
|
||||
DROP TABLE song_list;
|
||||
DROP TABLE vgmq;
|
||||
43
db/migrations/000001_create_tables.up.sql
Normal file
43
db/migrations/000001_create_tables.up.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
CREATE TABLE game (
|
||||
id serial4 NOT NULL,
|
||||
game_name varchar NOT NULL,
|
||||
added timestamp NOT NULL,
|
||||
deleted timestamp NULL,
|
||||
last_changed timestamp NULL,
|
||||
"path" varchar NOT NULL,
|
||||
times_played int4 DEFAULT 0 NULL,
|
||||
last_played timestamp NULL,
|
||||
number_of_songs int4 NULL,
|
||||
hash varchar NULL,
|
||||
CONSTRAINT game_pkey PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE song (
|
||||
game_id int4 NOT NULL,
|
||||
song_name varchar NOT NULL,
|
||||
"path" varchar NOT NULL,
|
||||
times_played int4 DEFAULT 0 NULL,
|
||||
hash varchar NULL,
|
||||
file_name varchar NULL,
|
||||
CONSTRAINT song_pkey PRIMARY KEY (game_id, path)
|
||||
);
|
||||
|
||||
CREATE TABLE vgmq (
|
||||
song_no int4 NOT NULL,
|
||||
"path" varchar(50) NULL,
|
||||
clue varchar(200) NULL,
|
||||
answered bool DEFAULT false NOT NULL,
|
||||
answer varchar(50) NULL,
|
||||
CONSTRAINT vgmq_pk PRIMARY KEY (song_no)
|
||||
);
|
||||
CREATE UNIQUE INDEX vgmq_song_no_uindex ON vgmq USING btree (song_no);
|
||||
|
||||
CREATE TABLE song_list (
|
||||
match_date date NOT NULL,
|
||||
match_id int4 NOT NULL,
|
||||
song_no int4 NOT NULL,
|
||||
game_name varchar(50) NULL,
|
||||
song_name varchar(50) NULL,
|
||||
CONSTRAINT song_list_pkey PRIMARY KEY (match_date, match_id, song_no)
|
||||
);
|
||||
CREATE INDEX song_list_game_name_idx ON song_list USING btree (game_name);
|
||||
3
db/migrations/000002_adjust_fields_for_sqlc.down.sql
Normal file
3
db/migrations/000002_adjust_fields_for_sqlc.down.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
Alter table game
|
||||
alter column number_of_songs set null,
|
||||
alter column hash set null;
|
||||
19
db/migrations/000002_adjust_fields_for_sqlc.up.sql
Normal file
19
db/migrations/000002_adjust_fields_for_sqlc.up.sql
Normal file
@@ -0,0 +1,19 @@
|
||||
BEGIN;
|
||||
UPDATE game
|
||||
SET number_of_songs = 0
|
||||
WHERE number_of_songs IS NULL;
|
||||
UPDATE game
|
||||
SET hash = ''
|
||||
WHERE hash IS NULL;
|
||||
UPDATE song
|
||||
SET hash = ''
|
||||
WHERE hash IS NULL;
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
Alter table game
|
||||
alter column number_of_songs set not null,
|
||||
alter column number_of_songs set default 0,
|
||||
ALTER COLUMN hash SET NOT NULL;
|
||||
ALTER TABLE song
|
||||
ALTER COLUMN hash SET NOT NULL;
|
||||
COMMIT;
|
||||
49
db/queries/game.sql
Normal file
49
db/queries/game.sql
Normal file
@@ -0,0 +1,49 @@
|
||||
-- name: ResetGameIdSeq :one
|
||||
SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1);
|
||||
|
||||
-- name: GetGameNameById :one
|
||||
SELECT game_name FROM game WHERE id = $1;
|
||||
|
||||
-- name: GetGameById :one
|
||||
SELECT *
|
||||
FROM game
|
||||
WHERE id = $1
|
||||
AND deleted IS NULL;
|
||||
|
||||
-- name: SetGameDeletionDate :exec
|
||||
UPDATE game SET deleted=now() WHERE deleted IS NULL;
|
||||
|
||||
-- name: ClearGames :exec
|
||||
DELETE FROM game;
|
||||
|
||||
-- name: UpdateGameName :exec
|
||||
UPDATE game SET game_name=sqlc.arg(name), path=sqlc.arg(path), last_changed=now() WHERE id=sqlc.arg(id);
|
||||
|
||||
-- name: UpdateGameHash :exec
|
||||
UPDATE game SET hash=sqlc.arg(hash), last_changed=now() WHERE id=sqlc.arg(id);
|
||||
|
||||
-- name: RemoveDeletionDate :exec
|
||||
UPDATE game SET deleted=NULL WHERE id=$1;
|
||||
|
||||
-- name: GetIdByGameName :one
|
||||
SELECT id FROM game WHERE game_name = $1;
|
||||
|
||||
-- name: InsertGame :one
|
||||
INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id;
|
||||
|
||||
-- name: InsertGameWithExistingId :exec
|
||||
INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now());
|
||||
|
||||
-- name: FindAllGames :many
|
||||
SELECT *
|
||||
FROM game
|
||||
WHERE deleted IS NULL
|
||||
ORDER BY game_name;
|
||||
|
||||
-- name: GetAllGamesIncludingDeleted :many
|
||||
SELECT *
|
||||
FROM game
|
||||
ORDER BY game_name;
|
||||
|
||||
-- name: AddGamePlayed :exec
|
||||
UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1;
|
||||
41
db/queries/song.sql
Normal file
41
db/queries/song.sql
Normal file
@@ -0,0 +1,41 @@
|
||||
-- name: ClearSongs :exec
|
||||
DELETE FROM song;
|
||||
|
||||
-- name: ClearSongsByGameId :exec
|
||||
DELETE FROM song WHERE game_id = $1;
|
||||
|
||||
-- name: AddSong :exec
|
||||
INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5);
|
||||
|
||||
-- name: CheckSong :one
|
||||
SELECT COUNT(*) FROM song WHERE path = $1;
|
||||
|
||||
-- name: CheckSongWithHash :one
|
||||
SELECT COUNT(*) FROM song WHERE hash = $1;
|
||||
|
||||
-- name: GetSongWithHash :one
|
||||
SELECT * FROM song WHERE hash = $1;
|
||||
|
||||
-- name: UpdateSong :exec
|
||||
UPDATE song SET song_name=$1, file_name=$2, path=$3 where hash=$4;
|
||||
|
||||
-- name: AddHashToSong :exec
|
||||
UPDATE song SET hash=$1 where path=$2;
|
||||
|
||||
-- name: FindSongsFromGame :many
|
||||
SELECT *
|
||||
FROM song
|
||||
WHERE game_id = $1;
|
||||
|
||||
-- name: AddSongPlayed :exec
|
||||
UPDATE song SET times_played = times_played + 1
|
||||
WHERE game_id = $1 AND song_name = $2;
|
||||
|
||||
-- name: FetchAllSongs :many
|
||||
SELECT * FROM song;
|
||||
|
||||
-- name: RemoveBrokenSong :exec
|
||||
DELETE FROM song WHERE path = $1;
|
||||
|
||||
-- name: RemoveBrokenSongs :exec
|
||||
DELETE FROM song where path = any (sqlc.slice('paths'));
|
||||
9
db/queries/song_list.sql
Normal file
9
db/queries/song_list.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
-- name: InsertSongInList :exec
|
||||
INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name)
|
||||
VALUES ($1, $2, $3, $4, $5);
|
||||
|
||||
-- name: GetSongList :many
|
||||
SELECT *
|
||||
FROM song_list
|
||||
WHERE match_date = $1
|
||||
ORDER BY song_no DESC;
|
||||
0
db/queries/vgmq.sql
Normal file
0
db/queries/vgmq.sql
Normal file
32
db/repository/db.go
Normal file
32
db/repository/db.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
246
db/repository/game.sql.go
Normal file
246
db/repository/game.sql.go
Normal file
@@ -0,0 +1,246 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// source: game.sql
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const addGamePlayed = `-- name: AddGamePlayed :exec
|
||||
UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) AddGamePlayed(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, addGamePlayed, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const clearGames = `-- name: ClearGames :exec
|
||||
DELETE FROM game
|
||||
`
|
||||
|
||||
func (q *Queries) ClearGames(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, clearGames)
|
||||
return err
|
||||
}
|
||||
|
||||
const findAllGames = `-- name: FindAllGames :many
|
||||
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
|
||||
FROM game
|
||||
WHERE deleted IS NULL
|
||||
ORDER BY game_name
|
||||
`
|
||||
|
||||
func (q *Queries) FindAllGames(ctx context.Context) ([]Game, error) {
|
||||
rows, err := q.db.Query(ctx, findAllGames)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Game
|
||||
for rows.Next() {
|
||||
var i Game
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.GameName,
|
||||
&i.Added,
|
||||
&i.Deleted,
|
||||
&i.LastChanged,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.LastPlayed,
|
||||
&i.NumberOfSongs,
|
||||
&i.Hash,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getAllGamesIncludingDeleted = `-- name: GetAllGamesIncludingDeleted :many
|
||||
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
|
||||
FROM game
|
||||
ORDER BY game_name
|
||||
`
|
||||
|
||||
func (q *Queries) GetAllGamesIncludingDeleted(ctx context.Context) ([]Game, error) {
|
||||
rows, err := q.db.Query(ctx, getAllGamesIncludingDeleted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Game
|
||||
for rows.Next() {
|
||||
var i Game
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.GameName,
|
||||
&i.Added,
|
||||
&i.Deleted,
|
||||
&i.LastChanged,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.LastPlayed,
|
||||
&i.NumberOfSongs,
|
||||
&i.Hash,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getGameById = `-- name: GetGameById :one
|
||||
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
|
||||
FROM game
|
||||
WHERE id = $1
|
||||
AND deleted IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) GetGameById(ctx context.Context, id int32) (Game, error) {
|
||||
row := q.db.QueryRow(ctx, getGameById, id)
|
||||
var i Game
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.GameName,
|
||||
&i.Added,
|
||||
&i.Deleted,
|
||||
&i.LastChanged,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.LastPlayed,
|
||||
&i.NumberOfSongs,
|
||||
&i.Hash,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getGameNameById = `-- name: GetGameNameById :one
|
||||
SELECT game_name FROM game WHERE id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetGameNameById(ctx context.Context, id int32) (string, error) {
|
||||
row := q.db.QueryRow(ctx, getGameNameById, id)
|
||||
var game_name string
|
||||
err := row.Scan(&game_name)
|
||||
return game_name, err
|
||||
}
|
||||
|
||||
const getIdByGameName = `-- name: GetIdByGameName :one
|
||||
SELECT id FROM game WHERE game_name = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetIdByGameName(ctx context.Context, gameName string) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, getIdByGameName, gameName)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const insertGame = `-- name: InsertGame :one
|
||||
INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id
|
||||
`
|
||||
|
||||
type InsertGameParams struct {
|
||||
GameName string `json:"game_name"`
|
||||
Path string `json:"path"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertGame(ctx context.Context, arg InsertGameParams) (int32, error) {
|
||||
row := q.db.QueryRow(ctx, insertGame, arg.GameName, arg.Path, arg.Hash)
|
||||
var id int32
|
||||
err := row.Scan(&id)
|
||||
return id, err
|
||||
}
|
||||
|
||||
const insertGameWithExistingId = `-- name: InsertGameWithExistingId :exec
|
||||
INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now())
|
||||
`
|
||||
|
||||
type InsertGameWithExistingIdParams struct {
|
||||
ID int32 `json:"id"`
|
||||
GameName string `json:"game_name"`
|
||||
Path string `json:"path"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertGameWithExistingId(ctx context.Context, arg InsertGameWithExistingIdParams) error {
|
||||
_, err := q.db.Exec(ctx, insertGameWithExistingId,
|
||||
arg.ID,
|
||||
arg.GameName,
|
||||
arg.Path,
|
||||
arg.Hash,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const removeDeletionDate = `-- name: RemoveDeletionDate :exec
|
||||
UPDATE game SET deleted=NULL WHERE id=$1
|
||||
`
|
||||
|
||||
func (q *Queries) RemoveDeletionDate(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, removeDeletionDate, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const resetGameIdSeq = `-- name: ResetGameIdSeq :one
|
||||
SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1)
|
||||
`
|
||||
|
||||
func (q *Queries) ResetGameIdSeq(ctx context.Context) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, resetGameIdSeq)
|
||||
var setval int64
|
||||
err := row.Scan(&setval)
|
||||
return setval, err
|
||||
}
|
||||
|
||||
const setGameDeletionDate = `-- name: SetGameDeletionDate :exec
|
||||
UPDATE game SET deleted=now() WHERE deleted IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) SetGameDeletionDate(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, setGameDeletionDate)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateGameHash = `-- name: UpdateGameHash :exec
|
||||
UPDATE game SET hash=$1, last_changed=now() WHERE id=$2
|
||||
`
|
||||
|
||||
type UpdateGameHashParams struct {
|
||||
Hash string `json:"hash"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateGameHash(ctx context.Context, arg UpdateGameHashParams) error {
|
||||
_, err := q.db.Exec(ctx, updateGameHash, arg.Hash, arg.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateGameName = `-- name: UpdateGameName :exec
|
||||
UPDATE game SET game_name=$1, path=$2, last_changed=now() WHERE id=$3
|
||||
`
|
||||
|
||||
type UpdateGameNameParams struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
ID int32 `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateGameName(ctx context.Context, arg UpdateGameNameParams) error {
|
||||
_, err := q.db.Exec(ctx, updateGameName, arg.Name, arg.Path, arg.ID)
|
||||
return err
|
||||
}
|
||||
47
db/repository/models.go
Normal file
47
db/repository/models.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
ID int32 `json:"id"`
|
||||
GameName string `json:"game_name"`
|
||||
Added time.Time `json:"added"`
|
||||
Deleted *time.Time `json:"deleted"`
|
||||
LastChanged *time.Time `json:"last_changed"`
|
||||
Path string `json:"path"`
|
||||
TimesPlayed *int32 `json:"times_played"`
|
||||
LastPlayed *time.Time `json:"last_played"`
|
||||
NumberOfSongs int32 `json:"number_of_songs"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
type Song struct {
|
||||
GameID int32 `json:"game_id"`
|
||||
SongName string `json:"song_name"`
|
||||
Path string `json:"path"`
|
||||
TimesPlayed *int32 `json:"times_played"`
|
||||
Hash string `json:"hash"`
|
||||
FileName *string `json:"file_name"`
|
||||
}
|
||||
|
||||
type SongList struct {
|
||||
MatchDate time.Time `json:"match_date"`
|
||||
MatchID int32 `json:"match_id"`
|
||||
SongNo int32 `json:"song_no"`
|
||||
GameName *string `json:"game_name"`
|
||||
SongName *string `json:"song_name"`
|
||||
}
|
||||
|
||||
type Vgmq struct {
|
||||
SongNo int32 `json:"song_no"`
|
||||
Path *string `json:"path"`
|
||||
Clue *string `json:"clue"`
|
||||
Answered bool `json:"answered"`
|
||||
Answer *string `json:"answer"`
|
||||
}
|
||||
223
db/repository/song.sql.go
Normal file
223
db/repository/song.sql.go
Normal file
@@ -0,0 +1,223 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// source: song.sql
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const addHashToSong = `-- name: AddHashToSong :exec
|
||||
UPDATE song SET hash=$1 where path=$2
|
||||
`
|
||||
|
||||
type AddHashToSongParams struct {
|
||||
Hash string `json:"hash"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddHashToSong(ctx context.Context, arg AddHashToSongParams) error {
|
||||
_, err := q.db.Exec(ctx, addHashToSong, arg.Hash, arg.Path)
|
||||
return err
|
||||
}
|
||||
|
||||
const addSong = `-- name: AddSong :exec
|
||||
INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5)
|
||||
`
|
||||
|
||||
type AddSongParams struct {
|
||||
GameID int32 `json:"game_id"`
|
||||
SongName string `json:"song_name"`
|
||||
Path string `json:"path"`
|
||||
FileName *string `json:"file_name"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
|
||||
_, err := q.db.Exec(ctx, addSong,
|
||||
arg.GameID,
|
||||
arg.SongName,
|
||||
arg.Path,
|
||||
arg.FileName,
|
||||
arg.Hash,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
const addSongPlayed = `-- name: AddSongPlayed :exec
|
||||
UPDATE song SET times_played = times_played + 1
|
||||
WHERE game_id = $1 AND song_name = $2
|
||||
`
|
||||
|
||||
type AddSongPlayedParams struct {
|
||||
GameID int32 `json:"game_id"`
|
||||
SongName string `json:"song_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) AddSongPlayed(ctx context.Context, arg AddSongPlayedParams) error {
|
||||
_, err := q.db.Exec(ctx, addSongPlayed, arg.GameID, arg.SongName)
|
||||
return err
|
||||
}
|
||||
|
||||
const checkSong = `-- name: CheckSong :one
|
||||
SELECT COUNT(*) FROM song WHERE path = $1
|
||||
`
|
||||
|
||||
func (q *Queries) CheckSong(ctx context.Context, path string) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, checkSong, path)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const checkSongWithHash = `-- name: CheckSongWithHash :one
|
||||
SELECT COUNT(*) FROM song WHERE hash = $1
|
||||
`
|
||||
|
||||
func (q *Queries) CheckSongWithHash(ctx context.Context, hash string) (int64, error) {
|
||||
row := q.db.QueryRow(ctx, checkSongWithHash, hash)
|
||||
var count int64
|
||||
err := row.Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
const clearSongs = `-- name: ClearSongs :exec
|
||||
DELETE FROM song
|
||||
`
|
||||
|
||||
func (q *Queries) ClearSongs(ctx context.Context) error {
|
||||
_, err := q.db.Exec(ctx, clearSongs)
|
||||
return err
|
||||
}
|
||||
|
||||
const clearSongsByGameId = `-- name: ClearSongsByGameId :exec
|
||||
DELETE FROM song WHERE game_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) ClearSongsByGameId(ctx context.Context, gameID int32) error {
|
||||
_, err := q.db.Exec(ctx, clearSongsByGameId, gameID)
|
||||
return err
|
||||
}
|
||||
|
||||
const fetchAllSongs = `-- name: FetchAllSongs :many
|
||||
SELECT game_id, song_name, path, times_played, hash, file_name FROM song
|
||||
`
|
||||
|
||||
func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
|
||||
rows, err := q.db.Query(ctx, fetchAllSongs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Song
|
||||
for rows.Next() {
|
||||
var i Song
|
||||
if err := rows.Scan(
|
||||
&i.GameID,
|
||||
&i.SongName,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.Hash,
|
||||
&i.FileName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const findSongsFromGame = `-- name: FindSongsFromGame :many
|
||||
SELECT game_id, song_name, path, times_played, hash, file_name
|
||||
FROM song
|
||||
WHERE game_id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) FindSongsFromGame(ctx context.Context, gameID int32) ([]Song, error) {
|
||||
rows, err := q.db.Query(ctx, findSongsFromGame, gameID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Song
|
||||
for rows.Next() {
|
||||
var i Song
|
||||
if err := rows.Scan(
|
||||
&i.GameID,
|
||||
&i.SongName,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.Hash,
|
||||
&i.FileName,
|
||||
); 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 game_id, song_name, path, times_played, hash, file_name FROM song WHERE hash = $1
|
||||
`
|
||||
|
||||
func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error) {
|
||||
row := q.db.QueryRow(ctx, getSongWithHash, hash)
|
||||
var i Song
|
||||
err := row.Scan(
|
||||
&i.GameID,
|
||||
&i.SongName,
|
||||
&i.Path,
|
||||
&i.TimesPlayed,
|
||||
&i.Hash,
|
||||
&i.FileName,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const removeBrokenSong = `-- name: RemoveBrokenSong :exec
|
||||
DELETE FROM song WHERE path = $1
|
||||
`
|
||||
|
||||
func (q *Queries) RemoveBrokenSong(ctx context.Context, path string) error {
|
||||
_, err := q.db.Exec(ctx, removeBrokenSong, path)
|
||||
return err
|
||||
}
|
||||
|
||||
const removeBrokenSongs = `-- name: RemoveBrokenSongs :exec
|
||||
DELETE FROM song where path = any ($1)
|
||||
`
|
||||
|
||||
func (q *Queries) RemoveBrokenSongs(ctx context.Context, paths []string) error {
|
||||
_, err := q.db.Exec(ctx, removeBrokenSongs, paths)
|
||||
return err
|
||||
}
|
||||
|
||||
const updateSong = `-- name: UpdateSong :exec
|
||||
UPDATE song SET song_name=$1, file_name=$2, path=$3 where hash=$4
|
||||
`
|
||||
|
||||
type UpdateSongParams struct {
|
||||
SongName string `json:"song_name"`
|
||||
FileName *string `json:"file_name"`
|
||||
Path string `json:"path"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateSong(ctx context.Context, arg UpdateSongParams) error {
|
||||
_, err := q.db.Exec(ctx, updateSong,
|
||||
arg.SongName,
|
||||
arg.FileName,
|
||||
arg.Path,
|
||||
arg.Hash,
|
||||
)
|
||||
return err
|
||||
}
|
||||
68
db/repository/song_list.sql.go
Normal file
68
db/repository/song_list.sql.go
Normal file
@@ -0,0 +1,68 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// source: song_list.sql
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
const getSongList = `-- name: GetSongList :many
|
||||
SELECT match_date, match_id, song_no, game_name, song_name
|
||||
FROM song_list
|
||||
WHERE match_date = $1
|
||||
ORDER BY song_no DESC
|
||||
`
|
||||
|
||||
func (q *Queries) GetSongList(ctx context.Context, matchDate time.Time) ([]SongList, error) {
|
||||
rows, err := q.db.Query(ctx, getSongList, matchDate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SongList
|
||||
for rows.Next() {
|
||||
var i SongList
|
||||
if err := rows.Scan(
|
||||
&i.MatchDate,
|
||||
&i.MatchID,
|
||||
&i.SongNo,
|
||||
&i.GameName,
|
||||
&i.SongName,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const insertSongInList = `-- name: InsertSongInList :exec
|
||||
INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
`
|
||||
|
||||
type InsertSongInListParams struct {
|
||||
MatchDate time.Time `json:"match_date"`
|
||||
MatchID int32 `json:"match_id"`
|
||||
SongNo int32 `json:"song_no"`
|
||||
GameName *string `json:"game_name"`
|
||||
SongName *string `json:"song_name"`
|
||||
}
|
||||
|
||||
func (q *Queries) InsertSongInList(ctx context.Context, arg InsertSongInListParams) error {
|
||||
_, err := q.db.Exec(ctx, insertSongInList,
|
||||
arg.MatchDate,
|
||||
arg.MatchID,
|
||||
arg.SongNo,
|
||||
arg.GameName,
|
||||
arg.SongName,
|
||||
)
|
||||
return err
|
||||
}
|
||||
20
go.mod
20
go.mod
@@ -3,10 +3,14 @@ module music-server
|
||||
go 1.22.2
|
||||
|
||||
require (
|
||||
github.com/MShekow/directory-checksum v1.4.6
|
||||
github.com/gin-contrib/static v1.1.2
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible
|
||||
github.com/jackc/pgtype v1.14.3
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/spf13/afero v1.11.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -14,12 +18,19 @@ require (
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/distribution/reference v0.6.0 // indirect
|
||||
github.com/docker/docker v27.3.1+incompatible // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
|
||||
@@ -27,18 +38,23 @@ require (
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lib/pq v1.10.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
62
go.sum
62
go.sum
@@ -1,5 +1,9 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/MShekow/directory-checksum v1.4.6 h1:2fhlCYbpjEN1iH9S0tdmEM0p1wvNT9x5x0rIchGI7nE=
|
||||
github.com/MShekow/directory-checksum v1.4.6/go.mod h1:bMfFBkaIlNk7O9VgEi8D2X7Q2Jfk3c7d67z3t6cpIi4=
|
||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@@ -15,6 +19,16 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
|
||||
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
@@ -23,8 +37,14 @@ github.com/gin-contrib/static v1.1.2 h1:c3kT4bFkUJn2aoRU3s6XnMjJT8J6nNWJkR0Nglqm
|
||||
github.com/gin-contrib/static v1.1.2/go.mod h1:Fw90ozjHCmZBWbgrsqrDvO28YbhKEKzKp8GixhR4yLw=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
@@ -37,8 +57,12 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
|
||||
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
@@ -98,6 +122,7 @@ github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
@@ -126,13 +151,20 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -147,6 +179,8 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9Nz
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
@@ -168,8 +202,18 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
@@ -201,12 +245,16 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
@@ -215,9 +263,12 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -228,6 +279,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -264,13 +316,15 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"music-server/pkg/server"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Sync struct {
|
||||
@@ -25,6 +26,12 @@ func (s *Sync) SyncGamesQuick(ctx *gin.Context) {
|
||||
ctx.JSON(http.StatusOK, "Games are synced")
|
||||
}
|
||||
|
||||
func (s *Sync) SyncGamesNew(ctx *gin.Context) {
|
||||
response := server.SyncGamesNew()
|
||||
server.Reset()
|
||||
ctx.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
func (s *Sync) ResetGames(ctx *gin.Context) {
|
||||
server.ResetDB()
|
||||
ctx.JSON(http.StatusOK, "Games and songs are deleted from the database")
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"music-server/pkg/api"
|
||||
"music-server/pkg/db"
|
||||
"music-server/pkg/helpers"
|
||||
"music-server/pkg/server"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
@@ -15,6 +16,12 @@ import (
|
||||
)
|
||||
|
||||
func SetupDb() {
|
||||
|
||||
/*err := server.ReadConf("conf.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}*/
|
||||
|
||||
// Get the value of an Environment Variable
|
||||
host := os.Getenv("DB_HOST")
|
||||
dbPort, dbPortErr := strconv.Atoi(os.Getenv("DB_PORT"))
|
||||
@@ -35,16 +42,35 @@ func SetupDb() {
|
||||
dbPort = 5432
|
||||
}
|
||||
if username == "" {
|
||||
username = "sebastian"
|
||||
username = "postgres"
|
||||
}
|
||||
if password == "" {
|
||||
password = "950100"
|
||||
password = "postgres"
|
||||
}
|
||||
if dbName == "" {
|
||||
dbName = "music_dev_local"
|
||||
dbName = "music_test_local"
|
||||
}
|
||||
|
||||
db.Migrate_db(host, dbPort, username, password, dbName)
|
||||
|
||||
db.InitDB(host, dbPort, username, password, dbName)
|
||||
|
||||
var dir string
|
||||
if host != "localhost" {
|
||||
dir = "/sorted/"
|
||||
} else {
|
||||
dir = "/Users/sebastian/ResilioSync/Sorterat_test/"
|
||||
}
|
||||
|
||||
server.Conf = &server.Config{
|
||||
Host: host,
|
||||
Port: dbPort,
|
||||
User: username,
|
||||
Password: password,
|
||||
Dbname: dbName,
|
||||
Path: dir,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func CloseDb() {
|
||||
@@ -60,6 +86,7 @@ func SetupRestServer(swagger embed.FS, search embed.FS) {
|
||||
syncGroup := router.Group("/sync")
|
||||
{
|
||||
syncGroup.GET("", sync.SyncGames)
|
||||
syncGroup.GET("/new", sync.SyncGamesNew)
|
||||
syncGroup.GET("/quick", sync.SyncGamesQuick)
|
||||
syncGroup.GET("/reset", sync.ResetGames)
|
||||
}
|
||||
|
||||
@@ -2,14 +2,21 @@ package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var dbpool *pgxpool.Pool
|
||||
var ctx = context.Background()
|
||||
var Dbpool *pgxpool.Pool
|
||||
var Ctx = context.Background()
|
||||
|
||||
func InitDB(host string, port int, user string, password string, dbname string) {
|
||||
|
||||
@@ -20,14 +27,14 @@ func InitDB(host string, port int, user string, password string, dbname string)
|
||||
fmt.Println(psqlInfo)
|
||||
|
||||
var err error
|
||||
dbpool, err = pgxpool.New(ctx, psqlInfo)
|
||||
Dbpool, err = pgxpool.New(Ctx, psqlInfo)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var success string
|
||||
err = dbpool.QueryRow(ctx, "select 'Successfully connected!'").Scan(&success)
|
||||
err = Dbpool.QueryRow(Ctx, "select 'Successfully connected!'").Scan(&success)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
@@ -37,11 +44,11 @@ func InitDB(host string, port int, user string, password string, dbname string)
|
||||
}
|
||||
|
||||
func CloseDb() {
|
||||
dbpool.Close()
|
||||
Dbpool.Close()
|
||||
}
|
||||
|
||||
func Testf() {
|
||||
rows, dbErr := dbpool.Query(ctx, "select game_name from game")
|
||||
rows, dbErr := Dbpool.Query(Ctx, "select game_name from game")
|
||||
if dbErr != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", dbErr)
|
||||
os.Exit(1)
|
||||
@@ -57,8 +64,60 @@ func Testf() {
|
||||
}
|
||||
|
||||
func resetGameIdSeq() {
|
||||
_, err := dbpool.Query(ctx, "SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1);")
|
||||
_, err := Dbpool.Query(Ctx, "SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1);")
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Migrate_db(host string, port int, user string, password string, dbname string) {
|
||||
migrationInfo := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable",
|
||||
user, password, host, port, dbname)
|
||||
|
||||
fmt.Println("Migration Info: ", migrationInfo)
|
||||
|
||||
db, err := sql.Open("postgres", migrationInfo)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
driver, err := postgres.WithInstance(db, &postgres.Config{})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
m, err := migrate.NewWithDatabaseInstance(
|
||||
"file://./db/migrations/",
|
||||
"postgres", driver)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
version, _, err := m.Version()
|
||||
if err != nil {
|
||||
log.Println("Migration version err: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("Migration version before: ", version)
|
||||
|
||||
err = m.Force(1)
|
||||
//err = m.Up() // or m.Steps(2) if you want to explicitly set the number of migrations to run
|
||||
if err != nil {
|
||||
log.Println("Force err: ", err)
|
||||
}
|
||||
|
||||
err = m.Migrate(2)
|
||||
//err = m.Up() // or m.Steps(2) if you want to explicitly set the number of migrations to run
|
||||
if err != nil {
|
||||
log.Println("Migration err: ", err)
|
||||
}
|
||||
|
||||
versionAfter, _, err := m.Version()
|
||||
if err != nil {
|
||||
log.Println("Migration version err: ", err)
|
||||
}
|
||||
|
||||
fmt.Println("Migration version after: ", versionAfter)
|
||||
|
||||
fmt.Println("Migration done")
|
||||
|
||||
db.Close()
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
func GetGameName(gameId int) string {
|
||||
var gameName = ""
|
||||
err := dbpool.QueryRow(ctx,
|
||||
err := Dbpool.QueryRow(Ctx,
|
||||
"SELECT game_name FROM game WHERE id = $1", gameId).Scan(&gameName)
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
@@ -28,7 +28,7 @@ func GetGameById(gameId int) (models.GameData, error) {
|
||||
var numberOfSongs pgtype.Int4
|
||||
var gameName, path string
|
||||
var added, deleted, lastChanged, lastPlayed pgtype.Timestamp
|
||||
err := dbpool.QueryRow(ctx,
|
||||
err := Dbpool.QueryRow(Ctx,
|
||||
"SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs "+
|
||||
"FROM game WHERE id = $1 AND deleted IS NULL ", gameId).Scan(&id, &gameName, &added, &deleted, &lastChanged, &path, ×Played, &lastPlayed, &numberOfSongs)
|
||||
if err != nil {
|
||||
@@ -51,7 +51,7 @@ func GetGameById(gameId int) (models.GameData, error) {
|
||||
}
|
||||
|
||||
func SetGameDeletionDate() {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE game SET deleted=$1 WHERE deleted IS NULL", time.Now())
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
@@ -59,14 +59,14 @@ func SetGameDeletionDate() {
|
||||
}
|
||||
|
||||
func ClearGames() {
|
||||
_, err := dbpool.Exec(ctx, "DELETE FROM game")
|
||||
_, err := Dbpool.Exec(Ctx, "DELETE FROM game")
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateGameName(id int, name string, path string) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE game SET game_name=$1, path=$2, last_changed=$3 WHERE id=$4",
|
||||
name, path, time.Now(), id)
|
||||
if err != nil {
|
||||
@@ -75,7 +75,7 @@ func UpdateGameName(id int, name string, path string) {
|
||||
}
|
||||
|
||||
func RemoveDeletionDate(id int) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE game SET deleted=null WHERE id=$1", id)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
@@ -84,7 +84,7 @@ func RemoveDeletionDate(id int) {
|
||||
|
||||
func GetIdByGameName(name string) int {
|
||||
var gameId = -1
|
||||
err := dbpool.QueryRow(ctx,
|
||||
err := Dbpool.QueryRow(Ctx,
|
||||
"SELECT id FROM game WHERE game_name = $1", name).Scan(&gameId)
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
@@ -97,7 +97,7 @@ func GetIdByGameName(name string) int {
|
||||
|
||||
func InsertGame(name string, path string) int {
|
||||
gameId := -1
|
||||
err := dbpool.QueryRow(ctx,
|
||||
err := Dbpool.QueryRow(Ctx,
|
||||
"INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id",
|
||||
name, path, time.Now()).Scan(&gameId)
|
||||
if err != nil {
|
||||
@@ -105,7 +105,7 @@ func InsertGame(name string, path string) int {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err)
|
||||
}
|
||||
resetGameIdSeq()
|
||||
err2 := dbpool.QueryRow(ctx,
|
||||
err2 := Dbpool.QueryRow(Ctx,
|
||||
"INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id",
|
||||
name, path, time.Now()).Scan(&gameId)
|
||||
if err2 != nil {
|
||||
@@ -119,7 +119,7 @@ func InsertGame(name string, path string) int {
|
||||
}
|
||||
|
||||
func InsertGameWithExistingId(id int, name string, path string) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"INSERT INTO game(id, game_name, path, added) VALUES ($1, $2, $3, $4)",
|
||||
id, name, path, time.Now())
|
||||
if err != nil {
|
||||
@@ -128,7 +128,7 @@ func InsertGameWithExistingId(id int, name string, path string) {
|
||||
}
|
||||
|
||||
func FindAllGames() []models.GameData {
|
||||
rows, err := dbpool.Query(ctx,
|
||||
rows, err := Dbpool.Query(Ctx,
|
||||
"SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs "+
|
||||
"FROM game WHERE deleted IS NULL "+
|
||||
"ORDER BY game_name")
|
||||
@@ -165,7 +165,7 @@ func FindAllGames() []models.GameData {
|
||||
}
|
||||
|
||||
func AddGamePlayed(id int) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE game SET times_played=times_played+1, last_played=now() WHERE id=$1", id)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
|
||||
@@ -12,12 +12,12 @@ var compareError = errors.New("no rows in result set")
|
||||
|
||||
func ClearSongs(gameId int) {
|
||||
if gameId == -1 {
|
||||
_, err := dbpool.Exec(ctx, "DELETE FROM song")
|
||||
_, err := Dbpool.Exec(Ctx, "DELETE FROM song")
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
} else {
|
||||
_, err := dbpool.Exec(ctx, "DELETE FROM song where game_id=$1", gameId)
|
||||
_, err := Dbpool.Exec(Ctx, "DELETE FROM song where game_id=$1", gameId)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func ClearSongs(gameId int) {
|
||||
}
|
||||
|
||||
func AddSong(song models.SongData) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"INSERT INTO song(game_id, song_name, path, file_name) VALUES ($1, $2, $3, $4)",
|
||||
song.GameId, song.SongName, song.Path, song.FileName)
|
||||
if err != nil {
|
||||
@@ -35,7 +35,7 @@ func AddSong(song models.SongData) {
|
||||
|
||||
func CheckSong(songPath string) bool {
|
||||
var path string
|
||||
err := dbpool.QueryRow(ctx,
|
||||
err := Dbpool.QueryRow(Ctx,
|
||||
"SELECT path FROM song WHERE path = $1", songPath).Scan(&path)
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
@@ -46,7 +46,7 @@ func CheckSong(songPath string) bool {
|
||||
}
|
||||
|
||||
func UpdateSong(songName string, fileName string, path string) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE song SET song_name=$1, file_name=$2 WHERE path = $3",
|
||||
songName, fileName, path)
|
||||
if err != nil {
|
||||
@@ -55,7 +55,7 @@ func UpdateSong(songName string, fileName string, path string) {
|
||||
}
|
||||
|
||||
func FindSongsFromGame(id int) []models.SongData {
|
||||
rows, err := dbpool.Query(ctx,
|
||||
rows, err := Dbpool.Query(Ctx,
|
||||
"SELECT song_name, path, file_name, times_played FROM song WHERE game_id = $1", id)
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
@@ -90,7 +90,7 @@ func FindSongsFromGame(id int) []models.SongData {
|
||||
}
|
||||
|
||||
func AddSongPlayed(id int, name string) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
"UPDATE song SET times_played=times_played+1 WHERE game_id=$1 AND song_name=$2", id, name)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
@@ -98,7 +98,7 @@ func AddSongPlayed(id int, name string) {
|
||||
}
|
||||
|
||||
func FetchAllSongs() []models.SongData {
|
||||
rows, err := dbpool.Query(ctx,
|
||||
rows, err := Dbpool.Query(Ctx,
|
||||
"SELECT song_name, path FROM song")
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
@@ -128,7 +128,7 @@ func FetchAllSongs() []models.SongData {
|
||||
}
|
||||
|
||||
func RemoveBrokenSong(song models.SongData) {
|
||||
_, err := dbpool.Exec(ctx, "DELETE FROM song where path=$1", song.Path)
|
||||
_, err := Dbpool.Exec(Ctx, "DELETE FROM song where path=$1", song.Path)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
@@ -141,7 +141,7 @@ func RemoveBrokenSongs(songs []models.SongData) {
|
||||
}
|
||||
joined = strings.TrimSuffix(joined, ",")
|
||||
|
||||
_, err := dbpool.Exec(ctx, "DELETE FROM song where path in ($1)", joined)
|
||||
_, err := Dbpool.Exec(Ctx, "DELETE FROM song where path in ($1)", joined)
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func InsertSongInList(song models.SongListData) {
|
||||
_, err := dbpool.Exec(ctx,
|
||||
_, err := Dbpool.Exec(Ctx,
|
||||
`INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name) VALUES ($1, $2, $3, $4, $5)`,
|
||||
song.MatchDate, song.MatchId, song.SongNo, song.GameName, song.SongName)
|
||||
if err != nil {
|
||||
@@ -17,7 +17,7 @@ func InsertSongInList(song models.SongListData) {
|
||||
}
|
||||
|
||||
func GetSongList(matchId int) []models.SongListData {
|
||||
rows, err := dbpool.Query(ctx,
|
||||
rows, err := Dbpool.Query(Ctx,
|
||||
"SELECT match_date, match_id, song_no, game_name, song_name "+
|
||||
"FROM song_list WHERE match_date = $1"+
|
||||
"ORDER BY song_no DESC", matchId)
|
||||
|
||||
34
pkg/server/config.go
Normal file
34
pkg/server/config.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Host string
|
||||
Port int
|
||||
User string
|
||||
Password string
|
||||
Dbname string
|
||||
Path string
|
||||
}
|
||||
|
||||
var Conf *Config
|
||||
|
||||
func ReadConf(filename string) error {
|
||||
buf, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c := &Config{}
|
||||
err = yaml.Unmarshal(buf, c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("in file %q: %w", filename, err)
|
||||
}
|
||||
Conf = c
|
||||
return err
|
||||
}
|
||||
@@ -48,6 +48,9 @@ func GetRandomSong() string {
|
||||
if games == nil || len(games) == 0 {
|
||||
games = db.FindAllGames()
|
||||
}
|
||||
if games == nil || len(games) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
song := getSongFromList(games)
|
||||
lastFetched = song
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"music-server/db/repository"
|
||||
"music-server/pkg/db"
|
||||
"music-server/pkg/models"
|
||||
"os"
|
||||
@@ -11,17 +16,65 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/MShekow/directory-checksum/directory_checksum"
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
var allGames []repository.Game
|
||||
var gamesBeforeSync []repository.Game
|
||||
var gamesAfterSync []repository.Game
|
||||
var gamesAdded []string
|
||||
var gamesReAdded []string
|
||||
var gamesChangedTitle map[string]string
|
||||
var gamesChangedContent []string
|
||||
var gamesRemoved []string
|
||||
var catchedErrors []string
|
||||
var brokenSongs []string
|
||||
|
||||
type Response struct {
|
||||
GamesAdded []string `json:"games_added"`
|
||||
GamesReAdded []string `json:"games_re_added"`
|
||||
GamesChangedTitle map[string]string `json:"games_changed_title"`
|
||||
GamesChangedContent []string `json:"games_changed_content"`
|
||||
GamesRemoved []string `json:"games_removed"`
|
||||
CatchedErrors []string `json:"catched_errors"`
|
||||
}
|
||||
|
||||
type GameStatus int
|
||||
|
||||
const (
|
||||
NotChanged GameStatus = iota
|
||||
TitleChanged
|
||||
GameChanged
|
||||
NewGame
|
||||
)
|
||||
|
||||
var statusName = map[GameStatus]string{
|
||||
NotChanged: "Not changed",
|
||||
TitleChanged: "Title changed",
|
||||
GameChanged: "Game changed",
|
||||
NewGame: "New game",
|
||||
}
|
||||
|
||||
func (gs GameStatus) String() string {
|
||||
return statusName[gs]
|
||||
}
|
||||
|
||||
var syncWg sync.WaitGroup
|
||||
var repo *repository.Queries
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
func SyncGames() {
|
||||
start := time.Now()
|
||||
host := os.Getenv("DB_HOST")
|
||||
var dir string
|
||||
if host != "" {
|
||||
dir = "/sorted/"
|
||||
} else {
|
||||
dir = "/Users/sebastian/Resilio Sync/Sorterat_test/"
|
||||
dir = "/Users/sebastian/ResilioSync/Sorterat_test/"
|
||||
}
|
||||
fmt.Printf("dir: %s\n", dir)
|
||||
foldersToSkip := []string{".sync", "dist", "old"}
|
||||
@@ -37,15 +90,21 @@ func SyncGames() {
|
||||
for _, file := range files {
|
||||
syncGame(file, foldersToSkip, dir)
|
||||
}
|
||||
finished := time.Now()
|
||||
totalTime := finished.Sub(start)
|
||||
out := time.Time{}.Add(totalTime)
|
||||
fmt.Printf("\nTotal time: %v\n", totalTime)
|
||||
fmt.Printf("Total time: %v\n", out.Format("15:04:05.00000"))
|
||||
}
|
||||
|
||||
func SyncGamesQuick() {
|
||||
start := time.Now()
|
||||
host := os.Getenv("DB_HOST")
|
||||
var dir string
|
||||
if host != "" {
|
||||
dir = "/sorted/"
|
||||
} else {
|
||||
dir = "/Users/sebastian/Resilio Sync/Sorterat_test/"
|
||||
dir = "/Users/sebastian/ResilioSync/Sorterat_test/"
|
||||
}
|
||||
fmt.Printf("dir: %s\n", dir)
|
||||
foldersToSkip := []string{".sync", "dist", "old"}
|
||||
@@ -66,6 +125,11 @@ func SyncGamesQuick() {
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
finished := time.Now()
|
||||
totalTime := finished.Sub(start)
|
||||
out := time.Time{}.Add(totalTime)
|
||||
fmt.Printf("\nTotal time: %v\n", totalTime)
|
||||
fmt.Printf("Total time: %v\n", out.Format("15:04:05.00000"))
|
||||
}
|
||||
|
||||
func syncGame(file os.DirEntry, foldersToSkip []string, dir string) {
|
||||
@@ -133,7 +197,10 @@ func checkIfChanged(id int, name string, path string) {
|
||||
|
||||
func addNewGame(name string, path string) {
|
||||
newId := db.GetIdByGameName(name)
|
||||
if newId == -1 {
|
||||
if newId != -1 {
|
||||
checkBrokenSongs()
|
||||
db.RemoveDeletionDate(newId)
|
||||
} else {
|
||||
newId = db.InsertGame(name, path)
|
||||
}
|
||||
|
||||
@@ -194,6 +261,401 @@ func checkBrokenSongs() {
|
||||
db.RemoveBrokenSongs(brokenSongs)
|
||||
}
|
||||
|
||||
func SyncGamesNew() Response {
|
||||
repo = repository.New(db.Dbpool)
|
||||
start := time.Now()
|
||||
fmt.Printf("dir: %s\n", Conf.Path)
|
||||
foldersToSkip := []string{".sync", "dist", "old"}
|
||||
fmt.Println(foldersToSkip)
|
||||
|
||||
var err error
|
||||
|
||||
gamesBeforeSync, err = repo.FindAllGames(db.Ctx)
|
||||
handleError("FindAllGames Before", err, "")
|
||||
fmt.Printf("Games Before: %d\n", len(gamesBeforeSync))
|
||||
|
||||
allGames, err = repo.GetAllGamesIncludingDeleted(db.Ctx)
|
||||
handleError("GetAllGamesIncludingDeleted", err, "")
|
||||
err = repo.SetGameDeletionDate(db.Ctx)
|
||||
handleError("SetGameDeletionDate", err, "")
|
||||
|
||||
directories, err := os.ReadDir(Conf.Path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
syncWg.Add(len(directories))
|
||||
for _, dir := range directories {
|
||||
go func() {
|
||||
defer syncWg.Done()
|
||||
syncGameNew(dir, foldersToSkip, Conf.Path)
|
||||
}()
|
||||
}
|
||||
syncWg.Wait()
|
||||
checkBrokenSongsNew()
|
||||
|
||||
gamesAfterSync, err = repo.FindAllGames(db.Ctx)
|
||||
handleError("FindAllGames After", err, "")
|
||||
|
||||
fmt.Printf("\nGames Before: %d\n", len(gamesBeforeSync))
|
||||
fmt.Printf("Games After: %d\n", len(gamesAfterSync))
|
||||
|
||||
fmt.Printf("\nGames added: \n")
|
||||
for _, game := range gamesAdded {
|
||||
fmt.Printf("%s\n", game)
|
||||
}
|
||||
|
||||
fmt.Printf("\nGames readded: \n")
|
||||
for _, game := range gamesReAdded {
|
||||
fmt.Printf("%s\n", game)
|
||||
}
|
||||
|
||||
fmt.Printf("\nGames with changed title: \n")
|
||||
for key, value := range gamesChangedTitle {
|
||||
fmt.Printf("The game: %s changed title to: %s\n", key, value)
|
||||
}
|
||||
|
||||
fmt.Printf("\nGames with changed content: \n")
|
||||
for _, game := range gamesChangedContent {
|
||||
fmt.Printf("%s\n", game)
|
||||
}
|
||||
|
||||
fmt.Printf("\n\n")
|
||||
var gamesRemovedTemp []string
|
||||
for _, beforeGame := range gamesBeforeSync {
|
||||
var found bool = false
|
||||
for _, afterGame := range gamesAfterSync {
|
||||
if beforeGame.GameName == afterGame.GameName {
|
||||
found = true
|
||||
fmt.Printf("Game: %s, Found: %v break\n", beforeGame.GameName, found)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
fmt.Printf("Game: %s, Found: %v\n", beforeGame.GameName, found)
|
||||
gamesRemovedTemp = append(gamesRemovedTemp, beforeGame.GameName)
|
||||
}
|
||||
}
|
||||
|
||||
for _, game := range gamesRemovedTemp {
|
||||
var found bool = false
|
||||
for key, _ := range gamesChangedTitle {
|
||||
if game == key {
|
||||
found = true
|
||||
fmt.Printf("Game: %s, Found: %v break2\n", game, found)
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
gamesRemoved = append(gamesRemoved, game)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\nGames removed: \n")
|
||||
for _, game := range gamesRemoved {
|
||||
fmt.Printf("%s\n", game)
|
||||
}
|
||||
|
||||
fmt.Printf("\nErrors catched: \n")
|
||||
for _, error := range catchedErrors {
|
||||
fmt.Printf("%s\n", error)
|
||||
}
|
||||
|
||||
finished := time.Now()
|
||||
totalTime := finished.Sub(start)
|
||||
out := time.Time{}.Add(totalTime)
|
||||
fmt.Printf("\nTotal time: %v\n", totalTime)
|
||||
fmt.Printf("Total time: %v\n", out.Format("15:04:05.00000"))
|
||||
|
||||
return Response{
|
||||
GamesAdded: gamesAdded,
|
||||
GamesReAdded: gamesReAdded,
|
||||
GamesChangedTitle: gamesChangedTitle,
|
||||
GamesChangedContent: gamesChangedContent,
|
||||
GamesRemoved: gamesRemoved,
|
||||
CatchedErrors: catchedErrors,
|
||||
}
|
||||
}
|
||||
|
||||
func checkBrokenSongsNew() {
|
||||
allSongs, err := repo.FetchAllSongs(db.Ctx)
|
||||
handleError("FetchAllSongs", err, "")
|
||||
var brokenWg sync.WaitGroup
|
||||
brokenWg.Add(len(allSongs))
|
||||
for _, song := range allSongs {
|
||||
go func() {
|
||||
defer brokenWg.Done()
|
||||
checkBrokenSongNew(song)
|
||||
}()
|
||||
}
|
||||
brokenWg.Wait()
|
||||
err = repo.RemoveBrokenSongs(db.Ctx, brokenSongs)
|
||||
handleError("RemoveBrokenSongs", err, "")
|
||||
}
|
||||
|
||||
func checkBrokenSongNew(song repository.Song) {
|
||||
//Check if file exists and open
|
||||
openFile, err := os.Open(song.Path)
|
||||
if err != nil {
|
||||
//File not found
|
||||
brokenSongs = append(brokenSongs, song.Path)
|
||||
fmt.Printf("song broken: %v\n", song.Path)
|
||||
} else {
|
||||
err = openFile.Close()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string) {
|
||||
if file.IsDir() && !contains(foldersToSkip, file.Name()) {
|
||||
gameDir := baseDir + file.Name() + "/"
|
||||
|
||||
dirHash := getHashForDir(gameDir)
|
||||
|
||||
var status GameStatus = NewGame
|
||||
var oldGame repository.Game
|
||||
var id int32 = -1
|
||||
|
||||
//fmt.Printf("Games before: %d\n", len(gamesBeforeSync))
|
||||
|
||||
for _, currentGame := range allGames {
|
||||
oldGame = currentGame
|
||||
//fmt.Printf("%s | %s\n", oldGame.GameName, oldGame.Hash)
|
||||
if oldGame.GameName == file.Name() && oldGame.Hash == dirHash {
|
||||
status = NotChanged
|
||||
id = oldGame.ID
|
||||
//fmt.Printf("Game not changed\n")
|
||||
break
|
||||
} else if oldGame.GameName == file.Name() && oldGame.Hash != dirHash {
|
||||
status = GameChanged
|
||||
id = oldGame.ID
|
||||
//fmt.Printf("Game changed\n")
|
||||
break
|
||||
} else if oldGame.GameName != file.Name() && oldGame.Hash == dirHash {
|
||||
status = TitleChanged
|
||||
id = oldGame.ID
|
||||
//fmt.Printf("GameName changed\n")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n\nID: %d | GameName: %s | GameHash: %s | Status: %s\n", id, file.Name(), dirHash, status)
|
||||
|
||||
entries, err := os.ReadDir(gameDir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
switch status {
|
||||
case NewGame:
|
||||
if id != -1 {
|
||||
for _, entry := range entries {
|
||||
fileInfo, err := entry.Info()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
id = getIdFromFileNew(fileInfo)
|
||||
if id != -1 {
|
||||
break
|
||||
}
|
||||
}
|
||||
err = repo.InsertGameWithExistingId(db.Ctx, repository.InsertGameWithExistingIdParams{ID: id, GameName: file.Name(), Path: gameDir, Hash: dirHash})
|
||||
handleError("InsertGameWithExistingId", err, "")
|
||||
if err != nil {
|
||||
fmt.Printf("id = %v\n", id)
|
||||
fileName := gameDir + "/." + strconv.Itoa(int(id)) + ".id"
|
||||
fmt.Printf("fileName = %v\n", fileName)
|
||||
|
||||
err := os.Remove(fileName)
|
||||
if err != nil {
|
||||
fmt.Printf("%s\n", err)
|
||||
}
|
||||
|
||||
newDirHash := getHashForDir(gameDir)
|
||||
|
||||
id = insertGameNew(file.Name(), gameDir, newDirHash)
|
||||
}
|
||||
} else {
|
||||
id = insertGameNew(file.Name(), gameDir, dirHash)
|
||||
}
|
||||
gamesAdded = append(gamesAdded, file.Name())
|
||||
newCheckSongs(entries, gameDir, id)
|
||||
case GameChanged:
|
||||
err = repo.UpdateGameHash(db.Ctx, repository.UpdateGameHashParams{Hash: dirHash, ID: id})
|
||||
handleError("UpdateGameHash", err, "")
|
||||
gamesChangedContent = append(gamesChangedContent, file.Name())
|
||||
newCheckSongs(entries, gameDir, id)
|
||||
case TitleChanged:
|
||||
//println("TitleChanged")
|
||||
err = repo.UpdateGameName(db.Ctx, repository.UpdateGameNameParams{Name: file.Name(), Path: gameDir, ID: id})
|
||||
handleError("UpdateGameName", err, "")
|
||||
newCheckSongs(entries, gameDir, id)
|
||||
if gamesChangedTitle == nil {
|
||||
gamesChangedTitle = make(map[string]string)
|
||||
}
|
||||
gamesChangedTitle[oldGame.GameName] = file.Name()
|
||||
case NotChanged:
|
||||
//println("NotChanged")
|
||||
var found bool = false
|
||||
for _, beforeGame := range gamesBeforeSync {
|
||||
if dirHash == beforeGame.Hash {
|
||||
found = true
|
||||
//fmt.Printf("Game %s | %s | %s | %s | %v\n", beforeGame.GameName, beforeGame.Hash, dirHash, status, beforeGame.Deleted)
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
newCheckSongs(entries, gameDir, id)
|
||||
gamesReAdded = append(gamesReAdded, file.Name())
|
||||
|
||||
}
|
||||
}
|
||||
err = repo.RemoveDeletionDate(db.Ctx, id)
|
||||
handleError("RemoveDeletionDate", err, "")
|
||||
}
|
||||
}
|
||||
|
||||
func insertGameNew(name string, path string, hash string) int32 {
|
||||
var duplicateError = errors.New("ERROR: duplicate key value violates unique")
|
||||
id, err := repo.InsertGame(db.Ctx, repository.InsertGameParams{GameName: name, Path: path, Hash: hash})
|
||||
handleError("InsertGame", err, "")
|
||||
if err != nil {
|
||||
fmt.Printf("Handle id busy\n")
|
||||
if strings.HasPrefix(err.Error(), duplicateError.Error()) {
|
||||
fmt.Printf("Handeling this id\n")
|
||||
_, err = repo.ResetGameIdSeq(db.Ctx)
|
||||
handleError("ResetGameIdSeq", err, "")
|
||||
id = insertGameNew(name, path, hash)
|
||||
}
|
||||
}
|
||||
return id
|
||||
|
||||
}
|
||||
|
||||
func newCheckSongs(entries []os.DirEntry, gameDir string, id int32) int32 {
|
||||
//hasher := md5.New()
|
||||
var numberOfSongs int32
|
||||
var songWg sync.WaitGroup
|
||||
songWg.Add(len(entries))
|
||||
for _, entry := range entries {
|
||||
go func() {
|
||||
defer songWg.Done()
|
||||
newCheckSong(entry, gameDir, id)
|
||||
}()
|
||||
}
|
||||
songWg.Wait()
|
||||
return numberOfSongs
|
||||
}
|
||||
|
||||
func newCheckSong(entry os.DirEntry, gameDir string, id int32) {
|
||||
fileInfo, err := entry.Info()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if isSong(fileInfo) {
|
||||
path := gameDir + entry.Name()
|
||||
|
||||
songHash := getHashForFile(path)
|
||||
//numberOfSongs++
|
||||
|
||||
fileName := entry.Name()
|
||||
songName, _ := strings.CutSuffix(fileName, ".mp3")
|
||||
|
||||
song, err := repo.GetSongWithHash(db.Ctx, songHash)
|
||||
handleError("GetSongWithHash", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
if err == nil {
|
||||
if song.SongName == songName && song.Path == path {
|
||||
return
|
||||
}
|
||||
}
|
||||
fmt.Printf("Song Changed\n")
|
||||
|
||||
fmt.Printf("Path: %s | SongHash: %s\n", path, songHash)
|
||||
|
||||
count, err := repo.CheckSongWithHash(db.Ctx, songHash)
|
||||
handleError("CheckSongWithHash", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
if err != nil {
|
||||
count2, err := repo.CheckSong(db.Ctx, path)
|
||||
handleError("CheckSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
if count2 > 0 {
|
||||
err = repo.AddHashToSong(db.Ctx, repository.AddHashToSongParams{Hash: songHash, Path: path})
|
||||
handleError("AddHashToSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
count, err = repo.CheckSongWithHash(db.Ctx, songHash)
|
||||
handleError("CheckSongWithHash 2", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
}
|
||||
}
|
||||
|
||||
//count, _ := repo.CheckSong(ctx, path)
|
||||
if count > 0 {
|
||||
err = repo.UpdateSong(db.Ctx, repository.UpdateSongParams{SongName: songName, FileName: &fileName, Path: path, Hash: songHash})
|
||||
handleError("UpdateSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
} else {
|
||||
count2, err := repo.CheckSong(db.Ctx, path)
|
||||
handleError("CheckSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
if count2 > 0 {
|
||||
err = repo.AddHashToSong(db.Ctx, repository.AddHashToSongParams{Hash: songHash, Path: path})
|
||||
handleError("AddHashToSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
} else {
|
||||
err = repo.AddSong(db.Ctx, repository.AddSongParams{GameID: id, SongName: songName, Path: path, FileName: &fileName, Hash: songHash})
|
||||
handleError("AddSong", err, fmt.Sprintf("GameID: %d | Path: %s | SongName: %s | SongHash: %s\n", id, path, entry.Name(), songHash))
|
||||
|
||||
}
|
||||
}
|
||||
} else if isCoverImage(fileInfo) {
|
||||
//TODO: Later add cover art image here in db
|
||||
}
|
||||
}
|
||||
|
||||
func handleError(funcName string, err error, msg string) {
|
||||
var compareError = errors.New("no rows in result set")
|
||||
if err != nil {
|
||||
if compareError.Error() != err.Error() {
|
||||
fmt.Printf("%s Error: %s\n", funcName, err)
|
||||
if msg != "" {
|
||||
fmt.Printf("%s\n", msg)
|
||||
catchedErrors = append(catchedErrors, fmt.Sprintf("Func: %s\nError message: %s\nDebug message: %s\n", funcName, err, msg))
|
||||
} else {
|
||||
catchedErrors = append(catchedErrors, fmt.Sprintf("Func: %s\nError message: %s\n", funcName, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getHashForDir(gameDir string) string {
|
||||
directory, _ := directory_checksum.ScanDirectory(gameDir, afero.NewOsFs())
|
||||
hash, _ := directory.ComputeDirectoryChecksums()
|
||||
|
||||
//fmt.Printf("Hash: |%s|\n", hash)
|
||||
return hash
|
||||
}
|
||||
|
||||
func getHashForFile(path string) string {
|
||||
hasher := md5.New()
|
||||
readFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer readFile.Close()
|
||||
hasher.Reset()
|
||||
_, err = io.Copy(hasher, readFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
|
||||
func getIdFromFileNew(file os.FileInfo) int32 {
|
||||
name := file.Name()
|
||||
if !file.IsDir() && strings.HasSuffix(name, ".id") {
|
||||
name = strings.Replace(name, ".id", "", 1)
|
||||
name = strings.Replace(name, ".", "", 1)
|
||||
i, _ := strconv.Atoi(name)
|
||||
return int32(i)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func isSong(entry fs.FileInfo) bool {
|
||||
return !entry.IsDir() && strings.HasSuffix(entry.Name(), ".mp3")
|
||||
}
|
||||
|
||||
37
sqlc.yaml
Normal file
37
sqlc.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "postgresql"
|
||||
queries: "./db/queries"
|
||||
schema: "./db/migrations"
|
||||
gen:
|
||||
go:
|
||||
emit_json_tags: true
|
||||
package: "repository"
|
||||
out: "db/repository"
|
||||
sql_package: "pgx/v5"
|
||||
overrides:
|
||||
- db_type: "pg_catalog.timestamp"
|
||||
go_type:
|
||||
import: "time"
|
||||
type: "Time"
|
||||
- db_type: "pg_catalog.timestamp"
|
||||
nullable: true
|
||||
go_type:
|
||||
pointer: true
|
||||
import: "time"
|
||||
type: "Time"
|
||||
- db_type: "pg_catalog.varchar"
|
||||
nullable: true
|
||||
go_type:
|
||||
pointer: true
|
||||
type: "string"
|
||||
- db_type: "int4"
|
||||
nullable: true
|
||||
go_type:
|
||||
pointer: true
|
||||
type: "int32"
|
||||
- db_type: "date"
|
||||
nullable: false
|
||||
go_type:
|
||||
import: "time"
|
||||
type: "Time"
|
||||
Reference in New Issue
Block a user