Replaced the gin framwwork with echo

This commit is contained in:
2025-01-13 11:57:48 +01:00
parent 8e2d22b899
commit 034ba35fbb
32 changed files with 348 additions and 266 deletions

View File

@@ -1,10 +1,10 @@
package api
import (
"github.com/gin-gonic/gin"
"music-server/pkg/helpers"
"music-server/pkg/server"
"net/http"
"github.com/labstack/echo"
)
type Index struct {
@@ -14,16 +14,15 @@ func NewIndex() *Index {
return &Index{}
}
func (i *Index) GetVersion(ctx *gin.Context) {
func (i *Index) GetVersion(ctx echo.Context) error {
versionHistory := server.GetVersionHistory()
if versionHistory.Version == "" {
helpers.NewError(ctx, http.StatusNotFound, nil)
return
return ctx.JSON(http.StatusNotFound, "version not found")
}
ctx.JSON(http.StatusOK, versionHistory)
return ctx.JSON(http.StatusOK, versionHistory)
}
func (i *Index) GetDBTest(ctx *gin.Context) {
func (i *Index) GetDBTest(ctx echo.Context) error {
server.TestDB()
ctx.JSON(http.StatusOK, "TestedDB")
return ctx.JSON(http.StatusOK, "TestedDB")
}

View File

@@ -1,11 +1,12 @@
package api
import (
"github.com/gin-gonic/gin"
"music-server/pkg/helpers"
"music-server/pkg/models"
"music-server/pkg/server"
"net/http"
"github.com/labstack/echo"
)
type Music struct {
@@ -15,86 +16,87 @@ func NewMusic() *Music {
return &Music{}
}
func (m *Music) GetSong(ctx *gin.Context) {
song := ctx.Query("song")
func (m *Music) GetSong(ctx echo.Context) error {
song := ctx.QueryParam("song")
if song == "" {
ctx.String(http.StatusBadRequest, "song can't be empty")
return ctx.String(http.StatusBadRequest, "song can't be empty")
}
s := server.GetSong(song)
helpers.SendSong(ctx, s)
return helpers.SendSong(ctx, s)
}
func (m *Music) GetSoundCheckSong(ctx *gin.Context) {
func (m *Music) GetSoundCheckSong(ctx echo.Context) error {
song := server.GetSoundCheckSong()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) ResetMusic(ctx *gin.Context) {
func (m *Music) ResetMusic(ctx echo.Context) error {
server.Reset()
ctx.Status(http.StatusOK)
return ctx.NoContent(http.StatusOK)
}
func (m *Music) GetRandomSong(ctx *gin.Context) {
func (m *Music) GetRandomSong(ctx echo.Context) error {
song := server.GetRandomSong()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) GetRandomSongLowChance(ctx *gin.Context) {
func (m *Music) GetRandomSongLowChance(ctx echo.Context) error {
song := server.GetRandomSongLowChance()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) GetRandomSongClassic(ctx *gin.Context) {
func (m *Music) GetRandomSongClassic(ctx echo.Context) error {
song := server.GetRandomSongClassic()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) GetSongInfo(ctx *gin.Context) {
func (m *Music) GetSongInfo(ctx echo.Context) error {
song := server.GetSongInfo()
ctx.JSON(http.StatusOK, song)
return ctx.JSON(http.StatusOK, song)
}
func (m *Music) GetPlayedSongs(ctx *gin.Context) {
func (m *Music) GetPlayedSongs(ctx echo.Context) error {
songList := server.GetPlayedSongs()
ctx.JSON(http.StatusOK, songList)
return ctx.JSON(http.StatusOK, songList)
}
func (m *Music) GetNextSong(ctx *gin.Context) {
func (m *Music) GetNextSong(ctx echo.Context) error {
song := server.GetNextSong()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) GetPreviousSong(ctx *gin.Context) {
func (m *Music) GetPreviousSong(ctx echo.Context) error {
song := server.GetPreviousSong()
helpers.SendSong(ctx, song)
return helpers.SendSong(ctx, song)
}
func (m *Music) GetAllGames(ctx *gin.Context) {
func (m *Music) GetAllGames(ctx echo.Context) error {
gameList := server.GetAllGames()
ctx.JSON(http.StatusOK, gameList)
return ctx.JSON(http.StatusOK, gameList)
}
func (m *Music) GetAllGamesRandom(ctx *gin.Context) {
func (m *Music) GetAllGamesRandom(ctx echo.Context) error {
gameList := server.GetAllGamesRandom()
ctx.JSON(http.StatusOK, gameList)
return ctx.JSON(http.StatusOK, gameList)
}
func (m *Music) PutPlayed(ctx *gin.Context) {
func (m *Music) PutPlayed(ctx echo.Context) error {
var played models.Played
if err := ctx.ShouldBindJSON(&played); err != nil {
helpers.NewError(ctx, http.StatusBadRequest, err)
return
err := ctx.Bind(&played)
if err != nil {
//helpers.NewError(ctx, http.StatusBadRequest, err)
return ctx.JSON(http.StatusBadRequest, err)
}
server.SetPlayed(played.Song)
ctx.Status(http.StatusOK)
return ctx.NoContent(http.StatusOK)
}
func (m *Music) AddLatestToQue(ctx *gin.Context) {
func (m *Music) AddLatestToQue(ctx echo.Context) error {
server.AddLatestToQue()
ctx.Status(http.StatusOK)
return ctx.NoContent(http.StatusOK)
}
func (m *Music) AddLatestPlayed(ctx *gin.Context) {
func (m *Music) AddLatestPlayed(ctx echo.Context) error {
server.AddLatestPlayed()
ctx.Status(http.StatusOK)
return ctx.NoContent(http.StatusOK)
}

View File

@@ -1,10 +1,11 @@
package api
import (
"log"
"music-server/pkg/server"
"net/http"
"github.com/gin-gonic/gin"
"github.com/labstack/echo"
)
type Sync struct {
@@ -14,25 +15,33 @@ func NewSync() *Sync {
return &Sync{}
}
func (s *Sync) SyncGames(ctx *gin.Context) {
func (s *Sync) SyncGames(ctx echo.Context) error {
server.SyncGames()
server.Reset()
ctx.JSON(http.StatusOK, "Games are synced")
return ctx.JSON(http.StatusOK, "Games are synced")
}
func (s *Sync) SyncGamesQuick(ctx *gin.Context) {
func (s *Sync) SyncGamesQuick(ctx echo.Context) error {
server.SyncGamesQuick()
server.Reset()
ctx.JSON(http.StatusOK, "Games are synced")
return ctx.JSON(http.StatusOK, "Games are synced")
}
func (s *Sync) SyncGamesNew(ctx *gin.Context) {
response := server.SyncGamesNew()
func (s *Sync) SyncGamesNewOnlyChanges(ctx echo.Context) error {
log.Println("Syncing games new")
response := server.SyncGamesNewOnlyChanges()
server.Reset()
ctx.JSON(http.StatusOK, response)
return 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")
func (s *Sync) SyncGamesNewFull(ctx echo.Context) error {
log.Println("Syncing games new full")
response := server.SyncGamesNewFull()
server.Reset()
return ctx.JSON(http.StatusOK, response)
}
func (s *Sync) ResetGames(ctx echo.Context) error {
server.ResetDB()
return ctx.JSON(http.StatusOK, "Games and songs are deleted from the database")
}

View File

@@ -1,146 +1,38 @@
package conf
import (
"embed"
"fmt"
"io/fs"
"log"
"music-server/cmd/web"
"music-server/pkg/api"
"music-server/pkg/db"
"music-server/pkg/helpers"
"music-server/pkg/server"
"net/http"
"os"
"strconv"
)
"github.com/a-h/templ"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
var (
host = os.Getenv("DB_HOST")
dbPort = os.Getenv("DB_PORT")
database = os.Getenv("DB_NAME")
username = os.Getenv("DB_USERNAME")
password = os.Getenv("DB_PASSWORD")
musicPath = os.Getenv("MUSIC_PATH")
)
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"))
if dbPortErr != nil {
dbPort = 0
if host == "" || dbPort == "" || username == "" || password == "" || database == "" || musicPath == "" {
log.Fatal("Invalid settings")
}
username := os.Getenv("DB_USERNAME")
password := os.Getenv("DB_PASSWORD")
dbName := os.Getenv("DB_NAME")
fmt.Printf("host: %s, dbPort: %v, username: %s, password: %s, dbName: %s\n",
host, dbPort, username, password, dbName)
host, dbPort, username, password, database)
if host == "" {
host = "localhost"
}
if dbPort == 0 {
dbPort = 5432
}
if username == "" {
username = "postgres"
}
if password == "" {
password = "postgres"
}
if dbName == "" {
dbName = "music_test_local"
}
log.Printf("Path: %s\n", musicPath)
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,
}
db.Migrate_db(host, dbPort, username, password, database)
db.InitDB(host, dbPort, username, password, database)
}
func CloseDb() {
defer db.CloseDb()
}
func SetupRestServer(swagger embed.FS) {
router := gin.Default()
router.Use(helpers.SetCorsAndNoCacheHeaders())
sync := api.NewSync()
syncGroup := router.Group("/sync")
{
syncGroup.GET("", sync.SyncGames)
syncGroup.GET("/new", sync.SyncGamesNew)
syncGroup.GET("/quick", sync.SyncGamesQuick)
syncGroup.GET("/reset", sync.ResetGames)
}
music := api.NewMusic()
musicGroup := router.Group("/music")
{
musicGroup.GET("", music.GetSong)
musicGroup.GET("soundTest", music.GetSoundCheckSong)
musicGroup.GET("reset", music.ResetMusic)
musicGroup.GET("rand", music.GetRandomSong)
musicGroup.GET("rand/low", music.GetRandomSongLowChance)
musicGroup.GET("rand/classic", music.GetRandomSongClassic)
musicGroup.GET("info", music.GetSongInfo)
musicGroup.GET("list", music.GetPlayedSongs)
musicGroup.GET("next", music.GetNextSong)
musicGroup.GET("previous", music.GetPreviousSong)
musicGroup.GET("all", music.GetAllGamesRandom)
musicGroup.GET("all/order", music.GetAllGames)
musicGroup.GET("all/random", music.GetAllGamesRandom)
musicGroup.PUT("played", music.PutPlayed)
musicGroup.GET("addQue", music.AddLatestToQue)
musicGroup.GET("addPlayed", music.AddLatestPlayed)
}
index := api.NewIndex()
router.GET("/version", index.GetVersion)
router.GET("/health", index.GetDBTest)
router.StaticFS("/swagger", helpers.EmbedFolder(swagger, "swagger", false))
router.Use(static.Serve("/", static.LocalFile("/frontend", true)))
router.Use(static.Serve("/new", static.LocalFile("/newFrontend", true)))
staticFiles, _ := fs.Sub(web.Files, "assets")
router.StaticFS("/assets", http.FS(staticFiles))
router.GET("/search", func(c *gin.Context) {
templ.Handler(web.HelloForm()).ServeHTTP(c.Writer, c.Request)
})
router.POST("/find", func(c *gin.Context) {
web.FindGameWebHandler(c.Writer, c.Request)
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Open http://localhost:%s in the browser", port)
err := router.Run(fmt.Sprintf(":%s", port))
if err != nil {
panic(err)
}
fmt.Println("Closing connection to database")
db.CloseDb()
}

View File

@@ -20,9 +20,9 @@ import (
var Dbpool *pgxpool.Pool
var Ctx = context.Background()
func InitDB(host string, port int, user string, password string, dbname string) {
func InitDB(host string, port string, user string, password string, dbname string) {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
psqlInfo := fmt.Sprintf("host=%s port=%s user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
@@ -72,8 +72,8 @@ func resetGameIdSeq() {
}
}
func Migrate_db(host string, port int, user string, password string, dbname string) {
migrationInfo := fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=disable",
func Migrate_db(host string, port string, user string, password string, dbname string) {
migrationInfo := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable",
user, password, host, port, dbname)
fmt.Println("Migration Info: ", migrationInfo)

View File

@@ -3,7 +3,6 @@ package helpers
import (
"embed"
"fmt"
"io"
"io/fs"
"net/http"
"os"
@@ -12,6 +11,7 @@ import (
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
"github.com/labstack/echo"
)
func SetCorsAndNoCacheHeaders() gin.HandlerFunc {
@@ -61,15 +61,15 @@ func EmbedFolder(fsEmbed embed.FS, targetPath string, index bool) static.ServeFi
}
}
func SendSong(ctx *gin.Context, Filename string) {
func SendSong(ctx echo.Context, Filename string) error {
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(ctx.Writer, "Song not found.", 404)
return
//http.Error(ctx.Writer, "Song not found.", 404)
return ctx.String(http.StatusNotFound, "Song not found.")
}
defer func(openFile *os.File) {
_ = openFile.Close()
@@ -91,13 +91,13 @@ func SendSong(ctx *gin.Context, Filename string) {
//Send the headers
//writer.Header().Set("Content-Disposition", "attachment; filename="+Filename)
ctx.Writer.Header().Set("Content-Type", "audio/mpeg")
ctx.Writer.Header().Set("Content-Length", FileSize)
ctx.Writer.Header().Set("Expires", "Tue, 03 Jul 2001 06:00:00 GMT")
ctx.Writer.Header().Set("Last-Modified", time.Now().String()+" GMT")
ctx.Writer.Header().Set("Cache-Control", "no-cache, no-store, private, max-age=0")
ctx.Writer.Header().Set("Pragma", "no-cache")
ctx.Writer.Header().Set("X-Accel-Expires", "0")
ctx.Response().Header().Set("Content-Type", "audio/mpeg")
ctx.Response().Header().Set("Content-Length", FileSize)
ctx.Response().Header().Set("Expires", "Tue, 03 Jul 2001 06:00:00 GMT")
ctx.Response().Header().Set("Last-Modified", time.Now().String()+" GMT")
ctx.Response().Header().Set("Cache-Control", "no-cache, no-store, private, max-age=0")
ctx.Response().Header().Set("Pragma", "no-cache")
ctx.Response().Header().Set("X-Accel-Expires", "0")
var etagHeaders = []string{
"ETag",
@@ -109,14 +109,14 @@ func SendSong(ctx *gin.Context, Filename string) {
}
for _, v := range etagHeaders {
if ctx.Request.Header.Get(v) != "" {
ctx.Request.Header.Del(v)
if ctx.Request().Header.Get(v) != "" {
ctx.Request().Header.Del(v)
}
}
//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(ctx.Writer, openFile) //'Copy' the file to the client
return
//_, _ = io.Copy(ctx.Writer, openFile) //'Copy' the file to the client
return ctx.Stream(http.StatusOK, "audio/mpeg", openFile)
}

View File

@@ -1,34 +0,0 @@
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
}

View File

@@ -260,15 +260,30 @@ func checkBrokenSongs() {
}
db.RemoveBrokenSongs(brokenSongs)
}
func SyncGamesNewFull() Response {
return syncGamesNew(true)
}
func SyncGamesNew() Response {
func SyncGamesNewOnlyChanges() Response {
return syncGamesNew(false)
}
func syncGamesNew(full bool) Response {
musicPath := os.Getenv("MUSIC_PATH")
fmt.Printf("dir: %s\n", musicPath)
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
gamesAdded = nil
gamesReAdded = nil
gamesChangedTitle = nil
gamesChangedContent = nil
gamesRemoved = nil
catchedErrors = nil
brokenSongs = nil
gamesBeforeSync, err = repo.FindAllGames(db.Ctx)
handleError("FindAllGames Before", err, "")
@@ -279,7 +294,7 @@ func SyncGamesNew() Response {
err = repo.SetGameDeletionDate(db.Ctx)
handleError("SetGameDeletionDate", err, "")
directories, err := os.ReadDir(Conf.Path)
directories, err := os.ReadDir(musicPath)
if err != nil {
log.Fatal(err)
}
@@ -288,7 +303,7 @@ func SyncGamesNew() Response {
for _, dir := range directories {
go func() {
defer syncWg.Done()
syncGameNew(dir, foldersToSkip, Conf.Path)
syncGameNew(dir, foldersToSkip, musicPath, full)
}()
}
syncWg.Wait()
@@ -339,7 +354,7 @@ func SyncGamesNew() Response {
for _, game := range gamesRemovedTemp {
var found bool = false
for key, _ := range gamesChangedTitle {
for key := range gamesChangedTitle {
if game == key {
found = true
//fmt.Printf("Game: %s, Found: %v break2\n", game, found)
@@ -408,7 +423,7 @@ func checkBrokenSongNew(song repository.Song) {
}
}
func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string) {
func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string, full bool) {
if file.IsDir() && !contains(foldersToSkip, file.Name()) {
gameDir := baseDir + file.Name() + "/"
@@ -441,6 +456,9 @@ func syncGameNew(file os.DirEntry, foldersToSkip []string, baseDir string) {
}
}
if full {
status = TitleChanged
}
entries, err := os.ReadDir(gameDir)
if err != nil {
log.Println(err)