Moved around more code. Implemented more sqlc. Added support to generate swagger.

Added support for profiling. Removed the pkg module altogether.
Everything except old sync is now using code generated by sqlc.
This commit is contained in:
2025-01-15 16:04:14 +01:00
parent db8214cb02
commit d653463f58
43 changed files with 947 additions and 1133 deletions

View File

@@ -1,18 +1,23 @@
package backend
import (
"music-server/pkg/db"
"music-server/pkg/models"
"music-server/internal/db"
)
func TestDB() {
db.Testf()
}
func GetVersionHistory() models.VersionData {
data := models.VersionData{Version: "3.2",
type VersionData struct {
Version string `json:"version" example:"1.0.0"`
Changelog string `json:"changelog" example:"account name"`
History []VersionData `json:"history"`
}
func GetVersionHistory() VersionData {
data := VersionData{Version: "3.2",
Changelog: "Upgraded Go version and the version of all dependencies. Fixed som more bugs.",
History: []models.VersionData{
History: []VersionData{
{
Version: "3.1",
Changelog: "Fixed some bugs with songs not found made the application crash. Now checking if song exists and if not, remove song from DB and find another one. Frontend is now decoupled from the backend.",

View File

@@ -3,17 +3,48 @@ package backend
import (
"log"
"math/rand"
"music-server/pkg/db"
"music-server/pkg/models"
"music-server/internal/db"
"music-server/internal/db/repository"
"os"
"strconv"
"strings"
)
type SongInfo struct {
Game string `json:"Game"`
GamePlayed int32 `json:"GamePlayed"`
Song string `json:"Song"`
SongPlayed int32 `json:"SongPlayed"`
CurrentlyPlaying bool `json:"CurrentlyPlaying"`
SongNo int `json:"SongNo"`
}
var currentSong = -1
var games []models.GameData
var songQue []models.SongData
var lastFetched models.SongData
// var games []models.GameData
var gamesNew []repository.Game
// var songQue []models.SongData
var songQueNew []repository.Song
// var lastFetched models.SongData
var lastFetchedNew repository.Song
var repo *repository.Queries
func initRepo() {
if repo == nil {
repo = repository.New(db.Dbpool)
}
}
func getAllGames() []repository.Game {
if len(gamesNew) == 0 {
initRepo()
gamesNew, _ = repo.FindAllGames(db.Ctx)
}
return gamesNew
}
func GetSoundCheckSong() string {
files, err := os.ReadDir("songs")
@@ -25,105 +56,125 @@ func GetSoundCheckSong() string {
}
func Reset() {
songQue = nil
songQueNew = nil
currentSong = -1
games = db.FindAllGames()
initRepo()
gamesNew, _ = repo.FindAllGames(db.Ctx)
//games = db.FindAllGames()
}
func AddLatestToQue() {
if lastFetched.Path != "" {
currentSong = len(songQue)
songQue = append(songQue, lastFetched)
lastFetched = models.SongData{}
if lastFetchedNew.Path != "" {
currentSong = len(songQueNew)
songQueNew = append(songQueNew, lastFetchedNew)
lastFetchedNew = repository.Song{}
}
}
func AddLatestPlayed() {
if len(songQue) == 0 {
if len(songQueNew) == 0 {
return
}
var currentSongData = songQue[currentSong]
currentSongData := songQueNew[currentSong]
db.AddGamePlayed(currentSongData.GameId)
db.AddSongPlayed(currentSongData.GameId, currentSongData.SongName)
initRepo()
repo.AddGamePlayed(db.Ctx, currentSongData.GameID)
repo.AddSongPlayed(db.Ctx, repository.AddSongPlayedParams{GameID: currentSongData.GameID, SongName: currentSongData.SongName})
//db.AddGamePlayed(currentSongData.GameId)
//db.AddSongPlayed(currentSongData.GameId, currentSongData.SongName)
}
func SetPlayed(songNumber int) {
if len(songQue) == 0 || songNumber >= len(songQue) {
if len(songQueNew) == 0 || songNumber >= len(songQueNew) {
return
}
var songData = songQue[songNumber]
db.AddGamePlayed(songData.GameId)
db.AddSongPlayed(songData.GameId, songData.SongName)
songData := songQueNew[songNumber]
initRepo()
repo.AddGamePlayed(db.Ctx, songData.GameID)
repo.AddSongPlayed(db.Ctx, repository.AddSongPlayedParams{GameID: songData.GameID, SongName: songData.SongName})
//db.AddGamePlayed(songData.GameId)
//db.AddSongPlayed(songData.GameId, songData.SongName)
}
func GetRandomSong() string {
if len(games) == 0 {
/*if len(games) == 0 {
games = db.FindAllGames()
}
if len(games) == 0 {
}*/
getAllGames()
if len(gamesNew) == 0 {
return ""
}
song := getSongFromList(games)
lastFetched = song
song := getSongFromList(gamesNew)
lastFetchedNew = song
return song.Path
}
func GetRandomSongLowChance() string {
if len(games) == 0 {
/*if len(games) == 0 {
games = db.FindAllGames()
}
}*/
getAllGames()
var listOfGames []models.GameData
//var listOfGames []models.GameData
var listOfGames []repository.Game
var averagePlayed = getAveragePlayed(games)
var averagePlayed = getAveragePlayed()
for _, data := range games {
var timesToAdd = averagePlayed - data.TimesPlayed
for _, data := range gamesNew {
timesToAdd := averagePlayed - data.TimesPlayed
if timesToAdd <= 0 {
listOfGames = append(listOfGames, data)
} else {
for i := 0; i < timesToAdd; i++ {
for i := int32(0); i < timesToAdd; i++ {
listOfGames = append(listOfGames, data)
}
}
}
song := getSongFromList(listOfGames)
lastFetched = song
lastFetchedNew = song
return song.Path
}
func GetRandomSongClassic() string {
if games == nil || len(games) == 0 {
/*if games == nil || len(games) == 0 {
games = db.FindAllGames()
}
}*/
var listOfAllSongs []models.SongData
for _, game := range games {
listOfAllSongs = append(listOfAllSongs, db.FindSongsFromGame(game.Id)...)
getAllGames()
var listOfAllSongs []repository.Song
for _, game := range gamesNew {
//listOfAllSongs = append(listOfAllSongs, db.FindSongsFromGame(game.Id)...)
songList, _ := repo.FindSongsFromGame(db.Ctx, game.ID)
listOfAllSongs = append(listOfAllSongs, songList...)
}
songFound := false
var song models.SongData
var song repository.Song
for !songFound {
song = listOfAllSongs[rand.Intn(len(listOfAllSongs))]
gameData, err := db.GetGameById(song.GameId)
//gameData, err := db.GetGameById(song.GameId)
gameData, err := repo.GetGameById(db.Ctx, song.GameID)
if err != nil {
db.RemoveBrokenSong(song)
log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + gameData.GameName + "' FileName: " + song.FileName)
//db.RemoveBrokenSong(song)
repo.RemoveBrokenSong(db.Ctx, song.Path)
//log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + gameData.GameName + "' FileName: " + song.FileName)
log.Printf("Song not found, song '%s' deleted from game '%s' FileName: %v\n", song.SongName, gameData.GameName, song.FileName)
continue
}
//Check if file exists and open
openFile, err := os.Open(song.Path)
if err != nil || gameData.Path+song.FileName != song.Path {
if err != nil || (song.FileName != nil && gameData.Path+*song.FileName != song.Path) {
//File not found
db.RemoveBrokenSong(song)
log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + gameData.GameName + "' FileName: " + song.FileName)
//db.RemoveBrokenSong(song)
repo.RemoveBrokenSong(db.Ctx, song.Path)
//log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + gameData.GameName + "' FileName: " + song.FileName)
log.Printf("Song not found, song '%s' deleted from game '%s' FileName: %v\n", song.SongName, gameData.GameName, song.FileName)
} else {
songFound = true
}
@@ -132,19 +183,19 @@ func GetRandomSongClassic() string {
log.Println(err)
}
}
lastFetched = song
lastFetchedNew = song
return song.Path
}
func GetSongInfo() models.SongInfo {
if songQue == nil {
return models.SongInfo{}
func GetSongInfo() SongInfo {
if songQueNew == nil {
return SongInfo{}
}
var currentSongData = songQue[currentSong]
var currentSongData = songQueNew[currentSong]
currentGameData := getCurrentGame(currentSongData)
return models.SongInfo{
return SongInfo{
Game: currentGameData.GameName,
GamePlayed: currentGameData.TimesPlayed,
Song: currentSongData.SongName,
@@ -154,12 +205,12 @@ func GetSongInfo() models.SongInfo {
}
}
func GetPlayedSongs() []models.SongInfo {
var songList []models.SongInfo
func GetPlayedSongs() []SongInfo {
var songList []SongInfo
for i, song := range songQue {
for i, song := range songQueNew {
gameData := getCurrentGame(song)
songList = append(songList, models.SongInfo{
songList = append(songList, SongInfo{
Game: gameData.GameName,
GamePlayed: gameData.TimesPlayed,
Song: song.SongName,
@@ -173,34 +224,36 @@ func GetPlayedSongs() []models.SongInfo {
func GetSong(song string) string {
currentSong, _ = strconv.Atoi(song)
if currentSong >= len(songQue) {
currentSong = len(songQue) - 1
if currentSong >= len(songQueNew) {
currentSong = len(songQueNew) - 1
} else if currentSong < 0 {
currentSong = 0
}
var songData = songQue[currentSong]
songData := songQueNew[currentSong]
return songData.Path
}
func GetAllGames() []string {
if games == nil || len(games) == 0 {
/*if games == nil || len(games) == 0 {
games = db.FindAllGames()
}
}*/
getAllGames()
var jsonArray []string
for _, game := range games {
for _, game := range gamesNew {
jsonArray = append(jsonArray, game.GameName)
}
return jsonArray
}
func GetAllGamesRandom() []string {
if games == nil || len(games) == 0 {
/*if games == nil || len(games) == 0 {
games = db.FindAllGames()
}
}*/
getAllGames()
var jsonArray []string
for _, game := range games {
for _, game := range gamesNew {
jsonArray = append(jsonArray, game.GameName)
}
rand.Shuffle(len(jsonArray), func(i, j int) { jsonArray[i], jsonArray[j] = jsonArray[j], jsonArray[i] })
@@ -208,40 +261,41 @@ func GetAllGamesRandom() []string {
}
func GetNextSong() string {
if songQue == nil {
if songQueNew == nil {
return ""
}
if currentSong == len(songQue)-1 || currentSong == -1 {
var songData = songQue[currentSong]
if currentSong == len(songQueNew)-1 || currentSong == -1 {
songData := songQueNew[currentSong]
return songData.Path
} else {
currentSong = currentSong + 1
var songData = songQue[currentSong]
songData := songQueNew[currentSong]
return songData.Path
}
}
func GetPreviousSong() string {
if songQue == nil {
if songQueNew == nil {
return ""
}
if currentSong == -1 || currentSong == 0 {
var songData = songQue[0]
songData := songQueNew[0]
return songData.Path
} else {
currentSong = currentSong - 1
var songData = songQue[currentSong]
songData := songQueNew[currentSong]
return songData.Path
}
}
func getSongFromList(games []models.GameData) models.SongData {
func getSongFromList(games []repository.Game) repository.Song {
songFound := false
var song models.SongData
var song repository.Song
for !songFound {
game := getRandomGame(games)
//log.Println("game = ", game)
songs := db.FindSongsFromGame(game.Id)
//songs := db.FindSongsFromGame(game.Id)
songs, _ := repo.FindSongsFromGame(db.Ctx, game.ID)
//log.Println("songs = ", songs)
if len(songs) == 0 {
continue
@@ -254,10 +308,12 @@ func getSongFromList(games []models.GameData) models.SongData {
//log.Println("game.Path+song.FileName: ", game.Path+song.FileName)
//log.Println("song.Path: ", song.Path)
//log.Println("game.Path+song.FileName != song.Path: ", game.Path+song.FileName != song.Path)
if err != nil || game.Path+song.FileName != song.Path || strings.HasSuffix(song.FileName, ".wav") {
if err != nil || (song.FileName != nil && game.Path+*song.FileName != song.Path) || (song.FileName != nil && strings.HasSuffix(*song.FileName, ".wav")) {
//File not found
db.RemoveBrokenSong(song)
log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + game.GameName + "' FileName: " + song.FileName)
//db.RemoveBrokenSong(song)
repo.RemoveBrokenSong(db.Ctx, song.Path)
//log.Println("Song not found, song '" + song.SongName + "' deleted from game '" + game.GameName + "' FileName: " + song.FileName)
log.Printf("Song not found, song '%s' deleted from game '%s' FileName: %v\n", song.SongName, game.GameName, song.FileName)
} else {
songFound = true
}
@@ -270,23 +326,24 @@ func getSongFromList(games []models.GameData) models.SongData {
return song
}
func getCurrentGame(currentSongData models.SongData) models.GameData {
for _, game := range games {
if game.Id == currentSongData.GameId {
func getCurrentGame(currentSongData repository.Song) repository.Game {
for _, game := range gamesNew {
if game.ID == currentSongData.GameID {
return game
}
}
return models.GameData{}
return repository.Game{}
}
func getAveragePlayed(gameList []models.GameData) int {
var sum int
for _, data := range gameList {
func getAveragePlayed() int32 {
getAllGames()
var sum int32
for _, data := range gamesNew {
sum += data.TimesPlayed
}
return sum / len(gameList)
return sum / int32(len(gamesNew))
}
func getRandomGame(listOfGames []models.GameData) models.GameData {
func getRandomGame(listOfGames []repository.Game) repository.Game {
return listOfGames[rand.Intn(len(listOfGames))]
}

View File

@@ -8,9 +8,8 @@ import (
"io"
"io/fs"
"log"
"music-server/db/repository"
"music-server/pkg/db"
"music-server/pkg/models"
"music-server/internal/db"
"music-server/internal/db/repository"
"os"
"sort"
"strconv"
@@ -63,203 +62,14 @@ func (gs GameStatus) String() string {
}
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/ResilioSync/Sorterat_test/"
}
fmt.Printf("dir: %s\n", dir)
foldersToSkip := []string{".sync", "dist", "old", "characters"}
fmt.Println(foldersToSkip)
db.SetGameDeletionDate()
checkBrokenSongs()
files, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
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/ResilioSync/Sorterat_test/"
}
fmt.Printf("dir: %s\n", dir)
foldersToSkip := []string{".sync", "dist", "old", "characters"}
fmt.Println(foldersToSkip)
db.SetGameDeletionDate()
checkBrokenSongs()
files, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
wg.Add(1)
go func() {
defer wg.Done()
syncGame(file, foldersToSkip, dir)
}()
}
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) {
if file.IsDir() && !contains(foldersToSkip, file.Name()) {
fmt.Println(file.Name())
path := dir + file.Name() + "/"
fmt.Println(path)
entries, err := os.ReadDir(path)
if err != nil {
log.Println(err)
}
id := -1
for _, entry := range entries {
fileInfo, err := entry.Info()
if err != nil {
log.Println(err)
}
id = getIdFromFile(fileInfo)
if id != -1 {
break
}
}
if id == -1 {
addNewGame(file.Name(), path)
} else {
checkIfChanged(id, file.Name(), path)
checkSongs(path, id)
}
}
}
func ResetDB() {
db.ClearSongs(-1)
db.ClearGames()
//db.ClearSongs(-1)
repo.ClearSongs(db.Ctx)
//db.ClearGames()
repo.ClearGames(db.Ctx)
}
func getIdFromFile(file os.FileInfo) int {
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 i
}
return -1
}
func checkIfChanged(id int, name string, path string) {
fmt.Printf("Id from file: %v\n", id)
nameFromDb := db.GetGameName(id)
fmt.Printf("Name from file: %v\n", name)
fmt.Printf("Name from DB: %v\n", nameFromDb)
if nameFromDb == "" {
fmt.Println("Not in db")
db.InsertGameWithExistingId(id, name, path)
fmt.Println("Added to db")
} else if name != nameFromDb {
fmt.Println("Diff name")
db.UpdateGameName(id, name, path)
checkBrokenSongs()
}
db.RemoveDeletionDate(id)
}
func addNewGame(name string, path string) {
newId := db.GetIdByGameName(name)
if newId != -1 {
checkBrokenSongs()
db.RemoveDeletionDate(newId)
} else {
newId = db.InsertGame(name, path)
}
fmt.Printf("newId = %v", newId)
fileName := path + "/." + strconv.Itoa(newId) + ".id"
fmt.Printf("fileName = %v", fileName)
err := os.WriteFile(fileName, nil, 0644)
if err != nil {
panic(err)
}
checkSongs(path, newId)
}
func checkSongs(gameDir string, gameId int) {
files, err := os.ReadDir(gameDir)
if err != nil {
log.Println(err)
}
for _, file := range files {
entry, err := file.Info()
if err != nil {
log.Println(err)
}
if isSong(entry) {
path := gameDir + entry.Name()
fileName := entry.Name()
songName, _ := strings.CutSuffix(fileName, ".mp3")
if db.CheckSong(path) {
db.UpdateSong(songName, fileName, path)
} else {
db.AddSong(models.SongData{GameId: gameId, SongName: songName, Path: path, FileName: fileName})
}
} else if isCoverImage(entry) {
//TODO: Later add cover art image here in db
}
}
//TODO: Add number of songs here
}
func checkBrokenSongs() {
allSongs := db.FetchAllSongs()
var brokenSongs []models.SongData
for _, song := range allSongs {
//Check if file exists and open
openFile, err := os.Open(song.Path)
if err != nil {
//File not found
brokenSongs = append(brokenSongs, song)
fmt.Printf("song broken: %v", song.Path)
} else {
err = openFile.Close()
if err != nil {
log.Println(err)
}
}
}
db.RemoveBrokenSongs(brokenSongs)
}
func SyncGamesNewFull() Response {
return syncGamesNew(true)
}
@@ -271,7 +81,7 @@ func SyncGamesNewOnlyChanges() Response {
func syncGamesNew(full bool) Response {
musicPath := os.Getenv("MUSIC_PATH")
fmt.Printf("dir: %s\n", musicPath)
repo = repository.New(db.Dbpool)
initRepo()
start := time.Now()
foldersToSkip := []string{".sync", "dist", "old", "characters"}
fmt.Println(foldersToSkip)