Files
MusicServer/musicFacade.go

349 lines
8.1 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"strconv"
"time"
)
var currentSong = -1
var games []GameData
var songQue []SongData
var lastFetched 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 addLatestToQue() {
if lastFetched.path != "" {
currentSong = len(songQue)
songQue = append(songQue, lastFetched)
lastFetched = SongData{}
}
}
func getRandomSong() string {
if games == nil || len(games) == 0 {
games = findAllGames()
}
song := getSongFromList(games)
lastFetched = song
return song.path
}
func getSongFromList(games []GameData) SongData {
songFound := false
var song SongData
for !songFound {
game := getRandomGame(games)
songs := findSongsFromGame(game.id)
song = songs[rand.Intn(len(songs))]
//Check if file exists and open
openFile, err := os.Open(song.path)
if err != nil {
//File not found
log.Fatal("Song not found, maybe delete song and/or game" + song.songName + " songPath: " + song.path)
} else {
songFound = true
}
err = openFile.Close()
if err != nil {
log.Fatal(err)
}
}
return song
}
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)
}
}
}
song := getSongFromList(listOfGames)
lastFetched = song
return song.path
}
func getSongInfo() SongInfo {
if songQue == nil {
return 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 getAllGamesRandom() []string {
if games == nil || len(games) == 0 {
games = findAllGames()
}
var jsonArray []string
for _, game := range games {
jsonArray = append(jsonArray, game.gameName)
}
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(jsonArray), func(i, j int) { jsonArray[i], jsonArray[j] = jsonArray[j], jsonArray[i] })
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 songQue == nil {
return ""
}
if currentSong == len(songQue)-1 || currentSong == -1 {
var songData = songQue[currentSong]
return songData.path
} else {
currentSong = currentSong + 1
var songData = songQue[currentSong]
return songData.path
}
}
func getPreviousSong() string {
if songQue == nil {
return ""
}
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)
sendSong(w, s)
}
} else if r.URL.Path == "/music/first" && r.Method == http.MethodGet {
song := getSoundCheckSong()
sendSong(w, song)
} 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()
sendSong(w, song)
} else if r.URL.Path == "/music/rand/low" && r.Method == http.MethodGet {
chance := getRandomSongLowChance()
sendSong(w, 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()
sendSong(w, song)
} else if r.URL.Path == "/music/previous" {
song := getPreviousSong()
sendSong(w, 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/all/random" && r.Method == http.MethodGet {
w.Header().Add("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(getAllGamesRandom())
} 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)
} else if r.URL.Path == "/music/addQue" && r.Method == http.MethodGet {
addLatestToQue()
w.WriteHeader(http.StatusOK)
}
}
func sendSong(writer http.ResponseWriter, Filename string) {
fmt.Println("Client requests: " + Filename)
//Check if file exists and open
openFile, err := os.Open(Filename)
if err != nil {
//File not found, send 404
http.Error(writer, "Song not found.", 404)
return
}
defer func(openFile *os.File) {
_ = openFile.Close()
}(openFile) //Close after function 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))]
}