From e4f6d7f608c56094f270cdc090a732219e79b9fa Mon Sep 17 00:00:00 2001 From: Laptop Date: Sun, 22 Dec 2024 00:02:23 +0200 Subject: [PATCH] add support for /tags/:tag and other endpoints --- README.md | 1 + lib/sc/track.go | 15 +++++++++ main.go | 67 ++++++++++++++++++++++++++++++++++++++ templates/base.templ | 2 +- templates/tags.templ | 75 +++++++++++++++++++++++++++++++++++++++++++ templates/track.templ | 2 +- 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 templates/tags.templ diff --git a/README.md b/README.md index 111eb0b..d7f7174 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ wip alternative frontend for soundcloud - Content proxying (images, audio) - View featured tracks, playlists - Users can change their preferences (should proxying be enabled, what method of playing the song should be used etc) +- Viewing popular/recent tracks/playlists with a certain tag/genre (actually working for playlists, unlike soundcloud itself!) ## In the works diff --git a/lib/sc/track.go b/lib/sc/track.go index b50f1d4..72c6265 100644 --- a/lib/sc/track.go +++ b/lib/sc/track.go @@ -466,3 +466,18 @@ func (t Track) DownloadImage() ([]byte, string, error) { func (t Track) Href() string { return "/" + t.Author.Permalink + "/" + t.Permalink } + +func RecentTracks(cid string, prefs cfg.Preferences, tag string, args string) (*Paginated[*Track], error) { + p := Paginated[*Track]{Next: "https://" + api + "/recent-tracks/" + tag + args} + err := p.Proceed(cid, true) + if err != nil { + return nil, err + } + + for _, t := range p.Collection { + t.Fix(false, false) + t.Postfix(prefs, false) + } + + return &p, nil +} diff --git a/main.go b/main.go index 0695250..8c96f7c 100644 --- a/main.go +++ b/main.go @@ -188,6 +188,73 @@ func main() { return templates.TrackEmbed(prefs, track, stream, displayErr).Render(context.Background(), c) }) + app.Get("/tags/:tag", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + cid, err := sc.GetClientID() + if err != nil { + return err + } + + tag := c.Params("tag") + p, err := sc.RecentTracks(cid, prefs, tag, c.Query("pagination", "?limit=20")) + if err != nil { + log.Printf("error getting %s tagged recent-tracks: %s\n", tag, err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base("Recent tracks tagged "+tag, templates.RecentTracks(tag, p), nil).Render(context.Background(), c) + }) + + app.Get("/tags/:tag/popular-tracks", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + cid, err := sc.GetClientID() + if err != nil { + return err + } + + tag := c.Params("tag") + p, err := sc.SearchTracks(cid, prefs, "?q=*&filter.genre_or_tag="+tag+"&sort=popular") + if err != nil { + log.Printf("error getting %s tagged popular-tracks: %s\n", tag, err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base("Popular tracks tagged "+tag, templates.PopularTracks(tag, p), nil).Render(context.Background(), c) + }) + + app.Get("/tags/:tag/playlists", func(c *fiber.Ctx) error { + prefs, err := preferences.Get(c) + if err != nil { + return err + } + + cid, err := sc.GetClientID() + if err != nil { + return err + } + + tag := c.Params("tag") + // Using a different method, since /playlists/discovery endpoint seems to be broken :P + p, err := sc.SearchPlaylists(cid, prefs, "?q=*&filter.genre_or_tag="+tag) + if err != nil { + log.Printf("error getting %s tagged playlists: %s\n", tag, err) + return err + } + + c.Set("Content-Type", "text/html") + return templates.Base("Playlists tagged "+tag, templates.TaggedPlaylists(tag, p), nil).Render(context.Background(), c) + }) + app.Get("/_/featured", func(c *fiber.Ctx) error { prefs, err := preferences.Get(c) if err != nil { diff --git a/templates/base.templ b/templates/base.templ index 4cf7ef0..ece6b96 100644 --- a/templates/base.templ +++ b/templates/base.templ @@ -12,7 +12,7 @@ templ Base(title string, content templ.Component, head templ.Component) { - + if title != "" { { title } ~ soundcloak } else { diff --git a/templates/tags.templ b/templates/tags.templ new file mode 100644 index 0000000..afa6541 --- /dev/null +++ b/templates/tags.templ @@ -0,0 +1,75 @@ +package templates + +import ( + "github.com/maid-zone/soundcloak/lib/sc" + "net/url" + "strings" + "strconv" +) + +templ TagsButtons(current string, tag string) { +
+ for _, b := range [...]btn{{"recent tracks", "", false},{"popular tracks", "/popular-tracks", false},{"playlists", "/playlists",false}} { + if b.text == current { + { b.text } + } else { + { b.text } + } + } +
+
+} + +templ RecentTracks(tag string, p *sc.Paginated[*sc.Track]) { +

Recent tracks tagged {url.PathUnescape(tag)}

+ @TagsButtons("recent tracks", tag) + if len(p.Collection) == 0 { +

no more tracks

+ } else { + for _, track := range p.Collection { + @TrackItem(track, true, "") + } + if p.Next != "" { + more tracks + } + } +} + +templ PopularTracks(tag string, p *sc.Paginated[*sc.Track]) { +

Popular tracks tagged {url.PathUnescape(tag)}

+ @TagsButtons("popular tracks", tag) + Found { strconv.FormatInt(p.Total, 10) } tracks +
+
+ if len(p.Collection) == 0 { +

no more tracks

+ } else { + for _, track := range p.Collection { + @TrackItem(track, true, "") + } + if p.Next != "" { + more tracks + } + } +} + +templ TaggedPlaylists(tag string, p *sc.Paginated[*sc.Playlist]) { +

Playlists tagged {url.PathUnescape(tag)}

+ @TagsButtons("playlists", tag) + Found { strconv.FormatInt(p.Total, 10) } playlists +
+
+ if len(p.Collection) == 0 { + if p.Total != 0 { +

no more results

+ } + } else { + for _, playlist := range p.Collection { + @PlaylistItem(playlist, true) + } + if p.Next != "" && len(p.Collection) != int(p.Total) { + more playlists + } + } +} + diff --git a/templates/track.templ b/templates/track.templ index 579e59b..6504254 100644 --- a/templates/track.templ +++ b/templates/track.templ @@ -133,7 +133,7 @@ templ Track(prefs cfg.Preferences, t sc.Track, stream string, displayErr string,

{ t.Title }

@TrackPlayer(prefs, t, stream, displayErr, autoplay, nextTrack, playlist, volume, mode, audio) if t.Genre != "" { -

{ t.Genre }

+

{ t.Genre }

} if playlist != nil {