package database import ( "fmt" "io/fs" "log" "os" "sort" "strconv" "strings" "sync" "time" ) var wg sync.WaitGroup func SyncGames() { start := time.Now() dir := os.Getenv("MUSIC_PATH") fmt.Printf("dir: %s\n", dir) foldersToSkip := []string{".sync", "dist", "old", "characters"} fmt.Println(foldersToSkip) 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() dir := os.Getenv("MUSIC_PATH") fmt.Printf("dir: %s\n", dir) foldersToSkip := []string{".sync", "dist", "old", "characters"} fmt.Println(foldersToSkip) 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 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 := 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") InsertGameWithExistingId(id, name, path) fmt.Println("Added to db") } else if name != nameFromDb { fmt.Println("Diff name") UpdateGameName(id, name, path) checkBrokenSongs() } RemoveDeletionDate(id) } func addNewGame(name string, path string) { newId := GetIdByGameName(name) if newId != -1 { checkBrokenSongs() RemoveDeletionDate(newId) } else { newId = 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 CheckSong(path) { UpdateSong(songName, fileName, path) } else { AddSong(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 := FetchAllSongs() var brokenSongs []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) } } } RemoveBrokenSongs(brokenSongs) } func isSong(entry fs.FileInfo) bool { return !entry.IsDir() && strings.HasSuffix(entry.Name(), ".mp3") } func isCoverImage(entry fs.FileInfo) bool { return !entry.IsDir() && strings.Contains(entry.Name(), "cover") && (strings.HasSuffix(entry.Name(), ".jpg") || strings.HasSuffix(entry.Name(), ".png")) } func contains(s []string, searchTerm string) bool { i := sort.SearchStrings(s, searchTerm) return i < len(s) && s[i] == searchTerm }