port to fiber v3, optimize static assets serving

This commit is contained in:
Laptop
2024-12-31 16:22:23 +02:00
parent f122c45fec
commit 1d5ec4353e
13 changed files with 176 additions and 92 deletions

View File

@@ -8,7 +8,10 @@ LICENSE
README.md
docs
*.fiber.gz
.compression
.br
.gzip
.zstd
*_templ.go
regexp2_codegen.go
main

5
.gitignore vendored
View File

@@ -10,7 +10,10 @@ compose.yaml
fly.toml
# created by soundcloak/dependencies
*.fiber.gz
.compression
*.br
*.gzip
*.zstd
# codegen
*_templ.go

View File

@@ -1,4 +1,4 @@
ARG GO_VERSION=1.22.10
ARG GO_VERSION=1.23.4
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION} AS build
ARG TARGETOS
@@ -20,6 +20,7 @@ RUN soundcloakctl js download
RUN templ generate
RUN go generate ./lib/*
RUN soundcloakctl config codegen
RUN soundcloakctl -nozstd -notable precompress
RUN CGO_ENABLED=0 GOARCH=${TARGETARCH} GOOS=${TARGETOS} go build -ldflags "-s -w -extldflags '-static'" -o ./app
RUN echo "soundcloak:x:5000:5000:Soundcloak user:/:/sbin/nologin" > /etc/minimal-passwd && \

View File

@@ -1,6 +1,6 @@
# Setup
## Prerequisites
1. [golang](https://go.dev) (I recommend version 1.22.10. Technically, you need 1.21.4 or higher)
1. [golang](https://go.dev) (I recommend version 1.23.4)
2. [git](https://git-scm.com)
## The setup
@@ -90,9 +90,9 @@ soundcloakctl js download # re-download JS modules
3. Clean precompressed static files
Those are created by the webserver in order to more efficiently serve static files. They have the `.fiber.gz` extension. You can easily remove them from all directories like this:
Those are created by the webserver in order to more efficiently serve static files. They have the `.br` and `.gzip` extension. You can easily remove them from all directories using soundcloakctl:
```sh
find . -name \*.fiber.gz -type f -delete
soundcloakctl clean
```
4. Run codegen and build the binary:

7
go.mod
View File

@@ -1,6 +1,6 @@
module git.maid.zone/stuff/soundcloak
go 1.22.10
go 1.23.4
require (
github.com/a-h/templ v0.2.793
@@ -9,7 +9,7 @@ require (
github.com/gcottom/mp4meta v0.0.4
github.com/gcottom/oggmeta v0.0.7
github.com/goccy/go-json v0.10.4
github.com/gofiber/fiber/v2 v2.52.5
github.com/gofiber/fiber/v3 v3.0.0-beta.3
github.com/valyala/fasthttp v1.58.0
)
@@ -17,12 +17,11 @@ require (
github.com/abema/go-mp4 v1.2.0 // indirect
github.com/aler9/writerseeker v1.1.0 // indirect
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/gofiber/utils/v2 v2.0.0-beta.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sunfish-shogi/bufseekio v0.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect

11
go.sum
View File

@@ -20,8 +20,10 @@ github.com/gcottom/oggmeta v0.0.7 h1:6mKm/9xhDeKKIOrB0K+daJoXOLbyRq84e5xV3dndDt8
github.com/gcottom/oggmeta v0.0.7/go.mod h1:ifdINhphaEW587BIgA+m5TJwCoVk88JuZMCHwXc/gpM=
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/fiber/v3 v3.0.0-beta.3 h1:7Q2I+HsIqnIEEDB+9oe7Gadpakh6ZLhXpTYz/L20vrg=
github.com/gofiber/fiber/v3 v3.0.0-beta.3/go.mod h1:kcMur0Dxqk91R7p4vxEpJfDWZ9u5IfvrtQc8Bvv/JmY=
github.com/gofiber/utils/v2 v2.0.0-beta.4 h1:1gjbVFFwVwUb9arPcqiB6iEjHBwo7cHsyS41NeIW3co=
github.com/gofiber/utils/v2 v2.0.0-beta.4/go.mod h1:sdRsPU1FXX6YiDGGxd+q2aPJRMzpsxdzCXo9dz+xtOY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -38,15 +40,10 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e h1:s2RNOM/IGdY0Y6qfTeUKhDawdHDpK9RGBdx80qN4Ttw=
github.com/orcaman/writerseeker v0.0.0-20200621085525-1d3f536ff85e/go.mod h1:nBdnFKj15wFbf94Rwfq4m30eAcyY9V/IyKAGQFtqkW0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=

View File

@@ -538,7 +538,7 @@ func init() {
}
}
const Debug = false
const Debug = true
const Commit = "unknown"
const Repo = "unknown"
const CommitURL = "unknown"

View File

@@ -8,7 +8,7 @@ import (
"git.maid.zone/stuff/soundcloak/lib/cfg"
"git.maid.zone/stuff/soundcloak/templates"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
)
func Defaults(dst *cfg.Preferences) {
@@ -61,7 +61,7 @@ func Defaults(dst *cfg.Preferences) {
}
}
func Get(c *fiber.Ctx) (cfg.Preferences, error) {
func Get(c fiber.Ctx) (cfg.Preferences, error) {
rawprefs := c.Cookies("prefs", "{}")
var p cfg.Preferences
@@ -94,7 +94,7 @@ type Export struct {
}
func Load(r fiber.Router) {
r.Get("/_/preferences", func(c *fiber.Ctx) error {
r.Get("/_/preferences", func(c fiber.Ctx) error {
p, err := Get(c)
if err != nil {
return err
@@ -104,9 +104,9 @@ func Load(r fiber.Router) {
return templates.Base("preferences", templates.Preferences(p), nil).Render(context.Background(), c)
})
r.Post("/_/preferences", func(c *fiber.Ctx) error {
r.Post("/_/preferences", func(c fiber.Ctx) error {
var p PrefsForm
err := c.BodyParser(&p)
err := c.Bind().Body(&p)
if err != nil {
return err
}
@@ -193,10 +193,10 @@ func Load(r fiber.Router) {
SameSite: "strict",
})
return c.Redirect("/_/preferences")
return c.Redirect().To("/_/preferences")
})
r.Get("/_/preferences/reset", func(c *fiber.Ctx) error {
r.Get("/_/preferences/reset", func(c fiber.Ctx) error {
// c.ClearCookie("prefs")
c.Cookie(&fiber.Cookie{ // I've had some issues with c.ClearCookie() method, so using this workaround for now
Name: "prefs",
@@ -206,10 +206,10 @@ func Load(r fiber.Router) {
SameSite: "strict",
})
return c.Redirect("/_/preferences")
return c.Redirect().To("/_/preferences")
})
r.Get("/_/preferences/export", func(c *fiber.Ctx) error {
r.Get("/_/preferences/export", func(c fiber.Ctx) error {
p, err := Get(c)
if err != nil {
return err
@@ -218,7 +218,7 @@ func Load(r fiber.Router) {
return c.JSON(Export{Preferences: &p})
})
r.Post("/_/preferences/import", func(c *fiber.Ctx) error {
r.Post("/_/preferences/import", func(c fiber.Ctx) error {
f, err := c.FormFile("prefs")
if err != nil {
return err
@@ -257,6 +257,6 @@ func Load(r fiber.Router) {
SameSite: "strict",
})
return c.Redirect("/_/preferences")
return c.Redirect().To("/_/preferences")
})
}

View File

@@ -6,7 +6,7 @@ import (
"git.maid.zone/stuff/soundcloak/lib/cfg"
"git.maid.zone/stuff/soundcloak/lib/misc"
"git.maid.zone/stuff/soundcloak/lib/sc"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/valyala/fasthttp"
)
@@ -32,7 +32,7 @@ func Load(r fiber.Router) {
StreamResponseBody: true,
}
r.Get("/_/proxy/images", func(c *fiber.Ctx) error {
r.Get("/_/proxy/images", func(c fiber.Ctx) error {
url := c.Query("url")
if url == "" {
return fiber.ErrBadRequest

View File

@@ -7,7 +7,7 @@ import (
"git.maid.zone/stuff/soundcloak/lib/cfg"
"git.maid.zone/stuff/soundcloak/lib/misc"
"git.maid.zone/stuff/soundcloak/lib/sc"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/valyala/fasthttp"
)
@@ -33,7 +33,7 @@ func Load(r fiber.Router) {
StreamResponseBody: true,
}
r.Get("/_/proxy/streams", func(c *fiber.Ctx) error {
r.Get("/_/proxy/streams", func(c fiber.Ctx) error {
ur := c.Query("url")
if ur == "" {
return fiber.ErrBadRequest
@@ -72,7 +72,7 @@ func Load(r fiber.Router) {
return c.SendStream(pr)
})
r.Get("/_/proxy/streams/aac", func(c *fiber.Ctx) error {
r.Get("/_/proxy/streams/aac", func(c fiber.Ctx) error {
ur := c.Query("url")
if ur == "" {
return fiber.ErrBadRequest
@@ -110,7 +110,7 @@ func Load(r fiber.Router) {
return c.SendStream(pr)
})
r.Get("/_/proxy/streams/playlist", func(c *fiber.Ctx) error {
r.Get("/_/proxy/streams/playlist", func(c fiber.Ctx) error {
ur := c.Query("url")
if ur == "" {
return fiber.ErrBadRequest
@@ -161,7 +161,7 @@ func Load(r fiber.Router) {
return c.Send(bytes.Join(sp, []byte("\n")))
})
r.Get("/_/proxy/streams/playlist/aac", func(c *fiber.Ctx) error {
r.Get("/_/proxy/streams/playlist/aac", func(c fiber.Ctx) error {
ur := c.Query("url")
if ur == "" {
return fiber.ErrBadRequest

View File

@@ -13,7 +13,7 @@ import (
"github.com/bogem/id3v2/v2"
"github.com/gcottom/mp4meta"
"github.com/gcottom/oggmeta"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v3"
"github.com/valyala/fasthttp"
)
@@ -220,7 +220,7 @@ func Load(r fiber.Router) {
StreamResponseBody: true,
}
r.Get("/_/restream/:author/:track", func(c *fiber.Ctx) error {
r.Get("/_/restream/:author/:track", func(c fiber.Ctx) error {
p, err := preferences.Get(c)
if err != nil {
return err

188
main.go
View File

@@ -1,18 +1,19 @@
package main
import (
"io/fs"
"log"
"math/rand"
"net/http"
"net/url"
"os"
"strings"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"git.maid.zone/stuff/soundcloak/lib/misc"
"github.com/gofiber/fiber/v3"
"github.com/goccy/go-json"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/fiber/v3/middleware/compress"
"github.com/gofiber/fiber/v3/middleware/recover"
"github.com/valyala/fasthttp"
"git.maid.zone/stuff/soundcloak/lib/cfg"
@@ -21,13 +22,81 @@ import (
proxystreams "git.maid.zone/stuff/soundcloak/lib/proxy_streams"
"git.maid.zone/stuff/soundcloak/lib/restream"
"git.maid.zone/stuff/soundcloak/lib/sc"
"git.maid.zone/stuff/soundcloak/static"
static_files "git.maid.zone/stuff/soundcloak/static"
"git.maid.zone/stuff/soundcloak/templates"
)
type osfs struct{}
func (osfs) Open(name string) (fs.File, error) {
misc.Log("osfs:", name)
if strings.HasPrefix(name, "js/") {
return os.Open("static/external/" + name[3:])
}
f, err := os.Open("static/instance/" + name)
if err == nil {
return f, nil
}
f, err = os.Open("static/assets/" + name)
return f, err
}
type staticfs struct {
}
func (staticfs) Open(name string) (fs.File, error) {
misc.Log("staticfs:", name)
if strings.HasPrefix(name, "js/") {
return static_files.External.Open("external/" + name[3:])
}
f, err := static_files.Instance.Open("instance/" + name)
if err == nil {
return f, nil
}
f, err = static_files.Assets.Open("assets/" + name)
return f, err
}
// stubby implementation of static middleware
// why? mainly because of the pathrewrite
// i hate seeing it trying to get root directory
func ServeFromFS(r fiber.Router, path string, filesystem fs.FS, cachecontrol string, compress bool) {
l := len(path)
fs := fasthttp.FS{
FS: filesystem,
PathRewrite: func(ctx *fasthttp.RequestCtx) []byte {
return ctx.Path()[l:]
},
Compress: compress,
CompressBrotli: compress,
CompressedFileSuffixes: map[string]string{
"gzip": ".gzip",
"br": ".br",
"zstd": ".zstd",
},
}
handler := fs.NewRequestHandler()
r.Use(path, func(c fiber.Ctx) error {
handler(c.Context())
if c.Context().Response.StatusCode() == 200 {
c.Set("Cache-Control", cachecontrol)
}
return nil
})
}
func main() {
app := fiber.New(fiber.Config{
Prefork: cfg.Prefork,
//Prefork: cfg.Prefork, // moved to ListenConfig in v3
JSONEncoder: json.Marshal,
JSONDecoder: json.Unmarshal,
@@ -38,29 +107,35 @@ func main() {
if !cfg.Debug { // you wanna catch any possible panics as soon as possible
app.Use(recover.New())
}
app.Use(compress.New(compress.Config{Level: compress.LevelBestSpeed}))
app.Use(compress.New(compress.Config{
Next: func(c fiber.Ctx) bool {
return strings.HasPrefix(c.Path(), "/_/static")
},
Level: compress.LevelBestSpeed,
}))
// Just for easy inspection of cache in development. Since debug is constant, the compiler will just remove the code below if it's set to false, so this has no runtime overhead.
if cfg.Debug {
app.Get("/_/cachedump/tracks", func(c *fiber.Ctx) error {
app.Get("/_/cachedump/tracks", func(c fiber.Ctx) error {
return c.JSON(sc.TracksCache)
})
app.Get("/_/cachedump/playlists", func(c *fiber.Ctx) error {
app.Get("/_/cachedump/playlists", func(c fiber.Ctx) error {
return c.JSON(sc.PlaylistsCache)
})
app.Get("/_/cachedump/users", func(c *fiber.Ctx) error {
app.Get("/_/cachedump/users", func(c fiber.Ctx) error {
return c.JSON(sc.UsersCache)
})
app.Get("/_/cachedump/clientId", func(c *fiber.Ctx) error {
app.Get("/_/cachedump/clientId", func(c fiber.Ctx) error {
return c.JSON(sc.ClientIDCache)
})
}
{
mainPageHandler := func(c *fiber.Ctx) error {
mainPageHandler := func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -74,20 +149,25 @@ func main() {
app.Get("/index.html", mainPageHandler)
}
const InstanceMaxAge = 7200 // 2hrs
const AssetsMaxAge = 14400 // 4hrs
const ExternalMaxAge = 28800 // 8hrs
const AssetsCacheControl = "public, max-age=28800" // 8hrs
if cfg.EmbedFiles {
app.Use("/_/static/", filesystem.New(filesystem.Config{Root: http.FS(static.Instance), PathPrefix: "instance", MaxAge: InstanceMaxAge}))
app.Use("/_/static/", filesystem.New(filesystem.Config{Root: http.FS(static.Assets), PathPrefix: "assets", MaxAge: AssetsMaxAge}))
app.Use("/_/static/js/", filesystem.New(filesystem.Config{Root: http.FS(static.External), PathPrefix: "external", MaxAge: ExternalMaxAge}))
misc.Log("using embedded files")
ServeFromFS(app, "/_/static", staticfs{}, AssetsCacheControl, true)
} else {
app.Static("/_/static/", "static/instance", fiber.Static{Compress: true, MaxAge: InstanceMaxAge})
app.Static("/_/static/", "static/assets", fiber.Static{Compress: true, MaxAge: AssetsMaxAge})
app.Static("/_/static/js/", "static/external", fiber.Static{Compress: true, MaxAge: ExternalMaxAge})
misc.Log("loading files dynamically")
ServeFromFS(app, "/_/static", osfs{}, AssetsCacheControl, true)
}
app.Get("/search", func(c *fiber.Ctx) error {
// why? because when you load a page without link rel="icon" the browser will
// try to load favicon from default location,
// and this path loads the user "favicon.ico" by default
if cfg.Debug {
app.Get("favicon.ico", func(c fiber.Ctx) error {
return c.Redirect().To("/_/static/favicon.ico")
})
}
app.Get("/search", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -132,15 +212,15 @@ func main() {
// someone is trying to hit those endpoints on sc.maid.zone at like 4am lol
// those are authentication-only, planning to make something similar later on
app.Get("/stream", func(c *fiber.Ctx) error {
return c.Redirect("/")
app.Get("/stream", func(c fiber.Ctx) error {
return c.Redirect().To("/")
})
app.Get("/feed", func(c *fiber.Ctx) error {
return c.Redirect("/")
app.Get("/feed", func(c fiber.Ctx) error {
return c.Redirect().To("/")
})
app.Get("/on/:id", func(c *fiber.Ctx) error {
app.Get("/on/:id", func(c fiber.Ctx) error {
id := c.Params("id")
if id == "" {
return fiber.ErrNotFound
@@ -173,10 +253,10 @@ func main() {
return err
}
return c.Redirect(u.Path)
return c.Redirect().To(u.Path)
})
app.Get("/w/player", func(c *fiber.Ctx) error {
app.Get("/w/player", func(c fiber.Ctx) error {
u := c.Query("url")
if u == "" {
return fiber.ErrNotFound
@@ -222,7 +302,7 @@ func main() {
return templates.TrackEmbed(prefs, track, stream, displayErr).Render(c.Context(), c)
})
app.Get("/tags/:tag", func(c *fiber.Ctx) error {
app.Get("/tags/:tag", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -244,7 +324,7 @@ func main() {
return templates.Base("Recent tracks tagged "+tag, templates.RecentTracks(tag, p), nil).Render(c.Context(), c)
})
app.Get("/tags/:tag/popular-tracks", func(c *fiber.Ctx) error {
app.Get("/tags/:tag/popular-tracks", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -266,7 +346,7 @@ func main() {
return templates.Base("Popular tracks tagged "+tag, templates.PopularTracks(tag, p), nil).Render(c.Context(), c)
})
app.Get("/tags/:tag/playlists", func(c *fiber.Ctx) error {
app.Get("/tags/:tag/playlists", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -289,7 +369,7 @@ func main() {
return templates.Base("Playlists tagged "+tag, templates.TaggedPlaylists(tag, p), nil).Render(c.Context(), c)
})
app.Get("/_/featured", func(c *fiber.Ctx) error {
app.Get("/_/featured", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -305,7 +385,7 @@ func main() {
return templates.Base("Featured Tracks", templates.FeaturedTracks(tracks), nil).Render(c.Context(), c)
})
app.Get("/discover", func(c *fiber.Ctx) error {
app.Get("/discover", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -353,7 +433,7 @@ func main() {
log.Fatalln("failed to marshal info: ", err)
}
app.Get("/_/info", func(c *fiber.Ctx) error {
app.Get("/_/info", func(c fiber.Ctx) error {
c.Set("Content-Type", "application/json")
return c.Send(inf)
})
@@ -365,7 +445,7 @@ func main() {
preferences.Load(app)
app.Get("/_/searchSuggestions", func(c *fiber.Ctx) error {
app.Get("/_/searchSuggestions", func(c fiber.Ctx) error {
q := c.Query("q")
if q == "" {
return fiber.ErrBadRequest
@@ -380,11 +460,11 @@ func main() {
})
// Currently, /:user is the tracks page
app.Get("/:user/tracks", func(c *fiber.Ctx) error {
return c.Redirect("/" + c.Params("user"))
app.Get("/:user/tracks", func(c fiber.Ctx) error {
return c.Redirect().To("/" + c.Params("user"))
})
app.Get("/:user/sets", func(c *fiber.Ctx) error {
app.Get("/:user/sets", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -412,7 +492,7 @@ func main() {
return templates.Base(user.Username, templates.UserPlaylists(prefs, user, pl), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/albums", func(c *fiber.Ctx) error {
app.Get("/:user/albums", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -440,7 +520,7 @@ func main() {
return templates.Base(user.Username, templates.UserAlbums(prefs, user, pl), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/reposts", func(c *fiber.Ctx) error {
app.Get("/:user/reposts", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -468,7 +548,7 @@ func main() {
return templates.Base(user.Username, templates.UserReposts(prefs, user, p), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/likes", func(c *fiber.Ctx) error {
app.Get("/:user/likes", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -496,7 +576,7 @@ func main() {
return templates.Base(user.Username, templates.UserLikes(prefs, user, p), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/popular-tracks", func(c *fiber.Ctx) error {
app.Get("/:user/popular-tracks", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -524,7 +604,7 @@ func main() {
return templates.Base(user.Username, templates.UserTopTracks(prefs, user, p), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/followers", func(c *fiber.Ctx) error {
app.Get("/:user/followers", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -552,7 +632,7 @@ func main() {
return templates.Base(user.Username, templates.UserFollowers(prefs, user, p), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/following", func(c *fiber.Ctx) error {
app.Get("/:user/following", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -580,7 +660,7 @@ func main() {
return templates.Base(user.Username, templates.UserFollowing(prefs, user, p), templates.UserHeader(user)).Render(c.Context(), c)
})
app.Get("/:user/:track", func(c *fiber.Ctx) error {
app.Get("/:user/:track", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -674,7 +754,7 @@ func main() {
return templates.Base(track.Title+" by "+track.Author.Username, templates.Track(prefs, track, stream, displayErr, c.Query("autoplay") == "true", playlist, nextTrack, c.Query("volume"), mode, audio), templates.TrackHeader(prefs, track, true)).Render(c.Context(), c)
})
app.Get("/:user", func(c *fiber.Ctx) error {
app.Get("/:user", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -702,7 +782,7 @@ func main() {
return templates.Base(usr.Username, templates.User(prefs, usr, p), templates.UserHeader(usr)).Render(c.Context(), c)
})
app.Get("/:user/sets/:playlist", func(c *fiber.Ctx) error {
app.Get("/:user/sets/:playlist", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -742,7 +822,7 @@ func main() {
return templates.Base(playlist.Title+" by "+playlist.Author.Username, templates.Playlist(prefs, playlist), templates.PlaylistHeader(playlist)).Render(c.Context(), c)
})
app.Get("/:user/_/related", func(c *fiber.Ctx) error {
app.Get("/:user/_/related", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -771,7 +851,7 @@ func main() {
})
// I'd like to make this "related" but keeping it "recommended" to have the same url as soundcloud
app.Get("/:user/:track/recommended", func(c *fiber.Ctx) error {
app.Get("/:user/:track/recommended", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -799,7 +879,7 @@ func main() {
return templates.Base(track.Title+" by "+track.Author.Username, templates.RelatedTracks(track, r), templates.TrackHeader(prefs, track, false)).Render(c.Context(), c)
})
app.Get("/:user/:track/sets", func(c *fiber.Ctx) error {
app.Get("/:user/:track/sets", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -827,7 +907,7 @@ func main() {
return templates.Base(track.Title+" by "+track.Author.Username, templates.TrackInPlaylists(track, p), templates.TrackHeader(prefs, track, false)).Render(c.Context(), c)
})
app.Get("/:user/:track/albums", func(c *fiber.Ctx) error {
app.Get("/:user/:track/albums", func(c fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
return err
@@ -858,5 +938,5 @@ func main() {
if cfg.CodegenConfig {
log.Println("Warning: you have CodegenConfig enabled, but the config was loaded dynamically.")
}
log.Fatal(app.Listen(cfg.Addr))
log.Fatal(app.Listen(cfg.Addr, fiber.ListenConfig{EnablePrefork: cfg.Prefork}))
}

View File

@@ -10,6 +10,7 @@ templ Base(title string, content templ.Component, head templ.Component) {
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="/_/static/global.css"/>
<link rel="stylesheet" href="/_/static/instance.css"/>
<link rel="icon" href="/_/static/favicon.ico"/>
if title != "" {
<title>{ title } ~ soundcloak</title>
} else {