package main import ( "encoding/json" "fmt" "io" "io/ioutil" "log" "math/rand" "net/http" "os" "strconv" ) var currentSong = -1 var games []GameData var songQue []SongData func getSoundCheckSong() string { reset() files, err := ioutil.ReadDir("songs") if err != nil { log.Fatal(err) } fileInfo := files[rand.Intn(len(files))] return "songs/" + fileInfo.Name() } func reset() { songQue = nil currentSong = -1 games = findAllGames() } func getRandomSong() string { if games == nil || len(games) == 0 { games = findAllGames() } game := getRandomGame(games) songs := findSongsFromGame(game.id) song := songs[rand.Intn(len(songs))] currentSong = len(songQue) songQue = append(songQue, song) return song.path } func getRandomSongLowChance() string { gameList := findAllGames() var listOfGames []GameData var averagePlayed = getAveragePlayed(gameList) for _, data := range gameList { var timesToAdd = averagePlayed - data.timesPlayed if timesToAdd <= 0 { listOfGames = append(listOfGames, data) } else { for i := 0; i < timesToAdd; i++ { listOfGames = append(listOfGames, data) } } } game := getRandomGame(listOfGames) songs := findSongsFromGame(game.id) song := songs[rand.Intn(len(songs))] currentSong = len(songQue) songQue = append(songQue, song) return song.path } func getSongInfo() SongInfo { var currentSongData = songQue[currentSong] currentGameData := getCurrentGame(currentSongData) return SongInfo{ Game: currentGameData.gameName, GamePlayed: currentGameData.timesPlayed, Song: currentSongData.songName, SongPlayed: currentSongData.timesPlayed, CurrentlyPlaying: true, SongNo: currentSong, } } func getPlayedSongs() []SongInfo { var songList []SongInfo for i, song := range songQue { gameData := getCurrentGame(song) songList = append(songList, SongInfo{ Game: gameData.gameName, GamePlayed: gameData.timesPlayed, Song: song.songName, SongPlayed: song.timesPlayed, CurrentlyPlaying: i == currentSong, SongNo: i, }) } return songList } func getSong(song string) string { currentSong, _ = strconv.Atoi(song) if currentSong >= len(songQue) { currentSong = len(songQue) - 1 } else if currentSong < 0 { currentSong = 0 } var songData = songQue[currentSong] return songData.path } func getAllGames() []string { if games == nil || len(games) == 0 { games = findAllGames() } var jsonArray []string for _, game := range games { jsonArray = append(jsonArray, game.gameName) } return jsonArray } func setPlayed(songNumber int) { if songQue == nil || len(songQue) == 0 || songNumber >= len(songQue) { return } var songData = songQue[songNumber] addGamePlayed(songData.gameId) addSongPlayed(songData.gameId, songData.songName) } func getNextSong() string { if currentSong == len(songQue)-1 || currentSong == -1 { return getRandomSong() } else { currentSong = currentSong + 1 var songData = songQue[currentSong] return songData.path } } func getPreviousSong() string { if currentSong == -1 || currentSong == 0 { var songData = songQue[0] return songData.path } else { currentSong = currentSong - 1 var songData = songQue[currentSong] return songData.path } } func musicHandler(w http.ResponseWriter, r *http.Request) { setCorsAndNoCacheHeaders(&w, r) if r.URL.Path == "/music" && r.Method == http.MethodGet { song := r.URL.Query().Get("song") if song == "" { w.WriteHeader(http.StatusBadRequest) _, err := fmt.Fprint(w, "song can't be empty") if err != nil { w.WriteHeader(http.StatusInternalServerError) } } else { s := getSong(song) sendFile(w, r, s) //http.ServeFile(w, r, s) } } else if r.URL.Path == "/music/first" && r.Method == http.MethodGet { song := getSoundCheckSong() sendFile(w, r, song) //http.ServeFile(w, r, getSoundCheckSong()) } else if r.URL.Path == "/music/reset" && r.Method == http.MethodGet { reset() w.WriteHeader(http.StatusOK) } else if r.URL.Path == "/music/rand" && r.Method == http.MethodGet { song := getRandomSong() sendFile(w, r, song) /*file, _ := os.Open(song) seeker := io.ReadSeeker(file) http.ServeContent(w, r, song, time.Time{}, seeker)*/ } else if r.URL.Path == "/music/rand/low" && r.Method == http.MethodGet { chance := getRandomSongLowChance() //http.ServeFile(w, r, chance) sendFile(w, r, chance) } else if r.URL.Path == "/music/info" && r.Method == http.MethodGet { w.Header().Add("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(getSongInfo()) } else if r.URL.Path == "/music/list" && r.Method == http.MethodGet { w.Header().Add("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(getPlayedSongs()) } else if r.URL.Path == "/music/next" { song := getNextSong() //http.ServeFile(w, r, song) sendFile(w, r, song) } else if r.URL.Path == "/music/previous" { song := getPreviousSong() //http.ServeFile(w, r, song) sendFile(w, r, song) } else if r.URL.Path == "/music/all" && r.Method == http.MethodGet { w.Header().Add("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(getAllGames()) } else if r.URL.Path == "/music/played" && r.Method == http.MethodPut { var p Played err := json.NewDecoder(r.Body).Decode(&p) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } setPlayed(p.song) w.WriteHeader(http.StatusOK) } } func sendFile(writer http.ResponseWriter, request *http.Request, Filename string) { fmt.Println("Client requests: " + Filename) //Check if file exists and open Openfile, err := os.Open(Filename) defer Openfile.Close() //Close after function return if err != nil { //File not found, send 404 http.Error(writer, "File not found.", 404) return } //File is found, create and send the correct headers //Get the Content-Type of the file //Create a buffer to store the header of the file in FileHeader := make([]byte, 512) //Copy the headers into the FileHeader buffer _, _ = Openfile.Read(FileHeader) //Get content type of file //FileContentType := http.DetectContentType(FileHeader) //Get the file size FileStat, _ := Openfile.Stat() //Get info from file FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string //Send the headers writer.Header().Set("Content-Disposition", "attachment; filename="+Filename) writer.Header().Set("Content-Type", "audio/mpeg") writer.Header().Set("Content-Length", FileSize) //Send the file //We read 512 bytes from the file already, so we reset the offset back to 0 _, _ = Openfile.Seek(0, 0) _, _ = io.Copy(writer, Openfile) //'Copy' the file to the client return } type Played struct { song int } func getCurrentGame(currentSongData SongData) GameData { for _, game := range games { if game.id == currentSongData.gameId { return game } } return GameData{} } func getAveragePlayed(gameList []GameData) int { var sum int for _, data := range gameList { sum += data.timesPlayed } return sum / len(gameList) } func getRandomGame(listOfGames []GameData) GameData { return listOfGames[rand.Intn(len(listOfGames))] }