package main import ( "log" "net/http" "os" "strings" _ "main/migrations" "github.com/labstack/echo/v5" "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/daos" "github.com/pocketbase/pocketbase/models" "github.com/pocketbase/pocketbase/plugins/migratecmd" ) func main() { tunesCollectionName := "tunes" iniFilesCollectionName := "iniFiles" stargazersCollectionName := "stargazers" app := pocketbase.New() // loosely check if it was executed using "go run" isGoRun := strings.HasPrefix(os.Args[0], os.TempDir()) migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{ // enable auto creation of migration files when making collection changes in the Admin UI // (the isGoRun check is to enable it only during development) Automigrate: isGoRun, }) app.OnBeforeServe().Add(func(e *core.ServeEvent) error { e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/custom/tunes/byTuneId/:tuneId", Handler: func(c echo.Context) error { record, _err := app.Dao().FindFirstRecordByData(tunesCollectionName, "tuneId", c.PathParam("tuneId")) if _err != nil { return apis.NewNotFoundError("Tune not found", nil) } if err := apis.EnrichRecord(c, app.Dao(), record, "author"); err != nil { return err } return c.JSON(http.StatusOK, record) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), }, }) e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/custom/iniFiles/bySignature/:signature", Handler: func(c echo.Context) error { record, _err := app.Dao().FindFirstRecordByData(iniFilesCollectionName, "signature", c.PathParam("signature")) if _err != nil { return c.JSON(http.StatusNotFound, _err) } return c.JSON(http.StatusOK, record) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), }, }) e.Router.AddRoute(echo.Route{ Method: http.MethodPost, Path: "/api/custom/stargazers/toggleStar", Handler: func(c echo.Context) (err error) { auth := c.Get(apis.ContextAuthRecordKey).(*models.Record) isStarred := false type Stargazer struct { User string Tune string `json:"tune" form:"tune" query:"tune"` } stargazer := new(Stargazer) if err = c.Bind(stargazer); err != nil { return c.String(http.StatusBadRequest, "Bad request") } stargazer.User = auth.Id _err := app.Dao().RunInTransaction(func(txDao *daos.Dao) error { collection, err := app.Dao().FindCollectionByNameOrId(stargazersCollectionName) if err != nil { return err } stargazerRecord := models.NewRecord(collection) stargazerRecord.Set("user", stargazer.User) stargazerRecord.Set("tune", stargazer.Tune) tune, _err := app.Dao().FindFirstRecordByData(tunesCollectionName, "id", stargazer.Tune) if _err != nil { return apis.NewNotFoundError("Tune not found", nil) } _err = txDao.SaveRecord(stargazerRecord) // UNIQUE constraint failed most likely, try to unstar if _err != nil { currentStargazerRecords, _err := app.Dao().FindRecordsByExpr( stargazersCollectionName, dbx.HashExp{"user": stargazer.User}, dbx.HashExp{"tune": stargazer.Tune}, ) if _err != nil || len(currentStargazerRecords) == 0 { return _err } _err = txDao.DeleteRecord(currentStargazerRecords[0]) if _err != nil { return _err } isStarred = false tune.Set("stars", tune.Get("stars").(float64)-1) } else { isStarred = true tune.Set("stars", tune.Get("stars").(float64)+1) } _err = txDao.SaveRecord(tune) if _err != nil { return _err } return nil }) if _err != nil { return apis.NewNotFoundError("Tune not found or already starred", nil) } // fetch again and return current state tune, _err := app.Dao().FindFirstRecordByData(tunesCollectionName, "id", stargazer.Tune) if _err != nil { return apis.NewNotFoundError("Tune not found", nil) } return c.JSON(http.StatusOK, map[string]any{ "stars": tune.Get("stars").(float64), "isStarred": isStarred, }) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), apis.LoadAuthContext(app.App), apis.RequireAdminOrRecordAuth("users"), }, }) e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/custom/stargazers/starredByMe/:tune", Handler: func(c echo.Context) (err error) { auth := c.Get(apis.ContextAuthRecordKey).(*models.Record) isStarred := true type Stargazer struct { User string Tune string } stargazer := new(Stargazer) stargazer.User = auth.Id stargazer.Tune = c.PathParam("tune") stargazerRecords, _err := app.Dao().FindRecordsByExpr( stargazersCollectionName, dbx.HashExp{"user": stargazer.User}, dbx.HashExp{"tune": stargazer.Tune}, ) if _err != nil || len(stargazerRecords) == 0 { isStarred = false } return c.JSON(http.StatusOK, map[string]any{ "isStarred": isStarred, }) }, Middlewares: []echo.MiddlewareFunc{ apis.ActivityLogger(app), apis.LoadAuthContext(app.App), apis.RequireAdminOrRecordAuth("users"), }, }) return nil }) if err := app.Start(); err != nil { log.Fatal(err) } }