-func GetArbitraryTrack(prefs cfg.Preferences, data string) (Track, error) {
+func GetArbitraryTrack(data string) (Track, error) {
if len(data) > 8 && (data[:8] == "https://" || data[:7] == "http://") {
u, err := url.Parse(data)
if err == nil {
if (u.Host == "api.soundcloud.com" || u.Host == "api-v2.soundcloud.com") && len(u.Path) > 8 && u.Path[:8] == "/tracks/" {
- return GetTrackByID(prefs, u.Path[8:])
+ return GetTrackByID(u.Path[8:])
}
if u.Host == "soundcloud.com" {
@@ -158,7 +158,7 @@ func GetArbitraryTrack(prefs cfg.Preferences, data string) (Track, error) {
return Track{}, ErrKindNotCorrect
}
- return GetTrack(prefs, u.Path)
+ return GetTrack(u.Path)
}
} else {
return Track{}, err
@@ -174,7 +174,7 @@ func GetArbitraryTrack(prefs cfg.Preferences, data string) (Track, error) {
}
if valid {
- return GetTrackByID(prefs, data)
+ return GetTrackByID(data)
}
// this part should be at the end since it manipulates data
@@ -197,7 +197,7 @@ func GetArbitraryTrack(prefs cfg.Preferences, data string) (Track, error) {
}
if n == 1 {
- return GetTrack(prefs, data)
+ return GetTrack(data)
}
// failed to find a data point
@@ -217,13 +217,14 @@ func SearchTracks(prefs cfg.Preferences, args string) (*Paginated[*Track], error
}
for _, t := range p.Collection {
- t.Fix(prefs, false)
+ t.Fix(false)
+ t.Postfix(prefs)
}
return &p, nil
}
-func GetTracks(prefs cfg.Preferences, ids string) ([]*Track, error) {
+func GetTracks(ids string) ([]Track, error) {
cid, err := GetClientID()
if err != nil {
return nil, err
@@ -249,10 +250,11 @@ func GetTracks(prefs cfg.Preferences, ids string) ([]*Track, error) {
data = resp.Body()
}
- var res []*Track
+ var res []Track
err = json.Unmarshal(data, &res)
- for _, t := range res {
- t.Fix(prefs, false)
+ for i, t := range res {
+ t.Fix(false)
+ res[i] = t
}
return res, err
}
@@ -304,7 +306,7 @@ func (tr Transcoding) GetStream(prefs cfg.Preferences, authorization string) (st
return s.URL, nil
}
-func (t *Track) Fix(prefs cfg.Preferences, large bool) {
+func (t *Track) Fix(large bool) {
if large {
t.Artwork = strings.Replace(t.Artwork, "-large.", "-t500x500.", 1)
} else {
@@ -318,11 +320,14 @@ func (t *Track) Fix(prefs cfg.Preferences, large bool) {
t.ID = ls[len(ls)-1]
}
+ t.Author.Fix(false)
+}
+
+func (t *Track) Postfix(prefs cfg.Preferences) {
if cfg.ProxyImages && *prefs.ProxyImages && t.Artwork != "" {
t.Artwork = "/_/proxy/images?url=" + url.QueryEscape(t.Artwork)
}
-
- t.Author.Fix(prefs, false)
+ t.Author.Postfix(prefs)
}
func (t Track) FormatDescription() string {
@@ -344,14 +349,14 @@ func (t Track) FormatDescription() string {
return desc
}
-func GetTrackByID(prefs cfg.Preferences, id string) (Track, error) {
+func GetTrackByID(id string) (Track, error) {
cid, err := GetClientID()
if err != nil {
return Track{}, err
}
tracksCacheLock.RLock()
- for _, cell := range tracksCache {
+ for _, cell := range TracksCache {
if cell.Value.ID == id && cell.Expires.After(time.Now()) {
tracksCacheLock.RUnlock()
return cell.Value, nil
@@ -389,11 +394,37 @@ func GetTrackByID(prefs cfg.Preferences, id string) (Track, error) {
return t, ErrKindNotCorrect
}
- t.Fix(prefs, true)
+ t.Fix(true)
tracksCacheLock.Lock()
- tracksCache[t.Author.Permalink+"/"+t.Permalink] = cached[Track]{Value: t, Expires: time.Now().Add(cfg.TrackTTL)}
+ TracksCache[t.Author.Permalink+"/"+t.Permalink] = cached[Track]{Value: t, Expires: time.Now().Add(cfg.TrackTTL)}
tracksCacheLock.Unlock()
return t, nil
}
+
+func (t Track) DownloadImage() ([]byte, string, error) {
+ req := fasthttp.AcquireRequest()
+ defer fasthttp.ReleaseRequest(req)
+
+ req.SetRequestURI(t.Artwork)
+ req.Header.Set("User-Agent", cfg.UserAgent)
+ req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd")
+
+ resp := fasthttp.AcquireResponse()
+ defer fasthttp.ReleaseResponse(resp)
+
+ err := DoWithRetry(ImageClient, req, resp)
+ if err != nil {
+ fmt.Println(t.Artwork)
+ fmt.Println("hi", err)
+ return nil, "", err
+ }
+
+ data, err := resp.BodyUncompressed()
+ if err != nil {
+ data = resp.Body()
+ }
+
+ return data, string(resp.Header.Peek("Content-Type")), nil
+}
diff --git a/lib/sc/user.go b/lib/sc/user.go
index a22347f..117e2fa 100644
--- a/lib/sc/user.go
+++ b/lib/sc/user.go
@@ -12,7 +12,7 @@ import (
// Functions/structures related to users
-var usersCache = map[string]cached[User]{}
+var UsersCache = map[string]cached[User]{}
var usersCacheLock = &sync.RWMutex{}
type User struct {
@@ -52,20 +52,22 @@ func (r *Repost) Fix(prefs cfg.Preferences) {
switch r.Type {
case TrackRepost:
if r.Track != nil {
- r.Track.Fix(prefs, false)
+ r.Track.Fix(false)
+ r.Track.Postfix(prefs)
}
return
case PlaylistRepost:
if r.Playlist != nil {
- r.Playlist.Fix(prefs, false) // err always nil if cached == false
+ r.Playlist.Fix(false) // err always nil if cached == false
+ r.Playlist.Postfix(prefs)
}
return
}
}
-func GetUser(prefs cfg.Preferences, permalink string) (User, error) {
+func GetUser(permalink string) (User, error) {
usersCacheLock.RLock()
- if cell, ok := usersCache[permalink]; ok && cell.Expires.After(time.Now()) {
+ if cell, ok := UsersCache[permalink]; ok && cell.Expires.After(time.Now()) {
usersCacheLock.RUnlock()
return cell.Value, nil
}
@@ -83,10 +85,10 @@ func GetUser(prefs cfg.Preferences, permalink string) (User, error) {
return u, err
}
- u.Fix(prefs, true)
+ u.Fix(true)
usersCacheLock.Lock()
- usersCache[permalink] = cached[User]{Value: u, Expires: time.Now().Add(cfg.UserTTL)}
+ UsersCache[permalink] = cached[User]{Value: u, Expires: time.Now().Add(cfg.UserTTL)}
usersCacheLock.Unlock()
return u, err
@@ -105,7 +107,8 @@ func SearchUsers(prefs cfg.Preferences, args string) (*Paginated[*User], error)
}
for _, u := range p.Collection {
- u.Fix(prefs, false)
+ u.Fix(false)
+ u.Postfix(prefs)
}
return &p, nil
@@ -121,8 +124,9 @@ func (u User) GetTracks(prefs cfg.Preferences, args string) (*Paginated[*Track],
return nil, err
}
- for _, u := range p.Collection {
- u.Fix(prefs, false)
+ for _, t := range p.Collection {
+ t.Fix(false)
+ t.Postfix(prefs)
}
return &p, nil
@@ -151,7 +155,7 @@ func (u User) FormatUsername() string {
return res
}
-func (u *User) Fix(prefs cfg.Preferences, large bool) {
+func (u *User) Fix(large bool) {
if large {
u.Avatar = strings.Replace(u.Avatar, "-large.", "-t500x500.", 1)
} else {
@@ -163,12 +167,14 @@ func (u *User) Fix(prefs cfg.Preferences, large bool) {
u.Avatar = ""
}
+ ls := strings.Split(u.ID, ":")
+ u.ID = ls[len(ls)-1]
+}
+
+func (u *User) Postfix(prefs cfg.Preferences) {
if cfg.ProxyImages && *prefs.ProxyImages && u.Avatar != "" {
u.Avatar = "/_/proxy/images?url=" + url.QueryEscape(u.Avatar)
}
-
- ls := strings.Split(u.ID, ":")
- u.ID = ls[len(ls)-1]
}
func (u *User) GetPlaylists(prefs cfg.Preferences, args string) (*Paginated[*Playlist], error) {
@@ -182,7 +188,8 @@ func (u *User) GetPlaylists(prefs cfg.Preferences, args string) (*Paginated[*Pla
}
for _, pl := range p.Collection {
- pl.Fix(prefs, false)
+ pl.Fix(false)
+ pl.Postfix(prefs)
}
return &p, nil
@@ -199,7 +206,8 @@ func (u *User) GetAlbums(prefs cfg.Preferences, args string) (*Paginated[*Playli
}
for _, pl := range p.Collection {
- pl.Fix(prefs, false)
+ pl.Fix(false)
+ pl.Postfix(prefs)
}
return &p, nil
diff --git a/main.go b/main.go
index c8137a2..a46ccb3 100644
--- a/main.go
+++ b/main.go
@@ -37,6 +37,26 @@ func main() {
app.Static("/", "assets", fiber.Static{Compress: true, MaxAge: 3600}) // 1hour
app.Static("/js/hls.js/", "node_modules/hls.js/dist", fiber.Static{Compress: true, MaxAge: 28800}) // 8 hours
+ // 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.
+ const debug = false
+ if debug {
+ app.Get("/_/cachedump/tracks", func(c *fiber.Ctx) error {
+ return c.JSON(sc.TracksCache)
+ })
+
+ app.Get("/_/cachedump/playlists", func(c *fiber.Ctx) error {
+ return c.JSON(sc.PlaylistsCache)
+ })
+
+ app.Get("/_/cachedump/users", func(c *fiber.Ctx) error {
+ return c.JSON(sc.UsersCache)
+ })
+
+ app.Get("/_/cachedump/clientId", func(c *fiber.Ctx) error {
+ return c.JSON(sc.ClientIDCache)
+ })
+ }
+
app.Get("/search", func(c *fiber.Ctx) error {
prefs, err := preferences.Get(c)
if err != nil {
@@ -127,12 +147,13 @@ func main() {
return err
}
- track, err := sc.GetArbitraryTrack(prefs, u)
-
+ track, err := sc.GetArbitraryTrack(u)
if err != nil {
log.Printf("error getting %s: %s\n", u, err)
return err
}
+ track.Postfix(prefs)
+
displayErr := ""
stream := ""
@@ -226,11 +247,12 @@ func main() {
return err
}
- user, err := sc.GetUser(prefs, c.Params("user"))
+ user, err := sc.GetUser(c.Params("user"))
if err != nil {
log.Printf("error getting %s (playlists): %s\n", c.Params("user"), err)
return err
}
+ user.Postfix(prefs)
pl, err := user.GetPlaylists(prefs, c.Query("pagination", "?limit=20"))
if err != nil {
@@ -248,11 +270,12 @@ func main() {
return err
}
- user, err := sc.GetUser(prefs, c.Params("user"))
+ user, err := sc.GetUser(c.Params("user"))
if err != nil {
log.Printf("error getting %s (albums): %s\n", c.Params("user"), err)
return err
}
+ user.Postfix(prefs)
pl, err := user.GetAlbums(prefs, c.Query("pagination", "?limit=20"))
if err != nil {
@@ -270,11 +293,12 @@ func main() {
return err
}
- user, err := sc.GetUser(prefs, c.Params("user"))
+ user, err := sc.GetUser(c.Params("user"))
if err != nil {
log.Printf("error getting %s (reposts): %s\n", c.Params("user"), err)
return err
}
+ user.Postfix(prefs)
p, err := user.GetReposts(prefs, c.Query("pagination", "?limit=20"))
if err != nil {
@@ -292,11 +316,13 @@ func main() {
return err
}
- track, err := sc.GetTrack(prefs, c.Params("user")+"/"+c.Params("track"))
+ track, err := sc.GetTrack(c.Params("user") + "/" + c.Params("track"))
if err != nil {
log.Printf("error getting %s from %s: %s\n", c.Params("track"), c.Params("user"), err)
return err
}
+ track.Postfix(prefs)
+
displayErr := ""
stream := ""
@@ -327,11 +353,12 @@ func main() {
}
//h := time.Now()
- usr, err := sc.GetUser(prefs, c.Params("user"))
+ usr, err := sc.GetUser(c.Params("user"))
if err != nil {
log.Printf("error getting %s: %s\n", c.Params("user"), err)
return err
}
+ usr.Postfix(prefs)
//fmt.Println("getuser", time.Since(h))
//h = time.Now()
@@ -352,20 +379,27 @@ func main() {
return err
}
- playlist, err := sc.GetPlaylist(prefs, c.Params("user")+"/sets/"+c.Params("playlist"))
+ playlist, err := sc.GetPlaylist(c.Params("user") + "/sets/" + c.Params("playlist"))
if err != nil {
log.Printf("error getting %s playlist from %s: %s\n", c.Params("playlist"), c.Params("user"), err)
return err
}
+ // Don't ask why
+ playlist.Tracks = playlist.Postfix(prefs)
p := c.Query("pagination")
if p != "" {
- tracks, next, err := sc.GetNextMissingTracks(prefs, p)
+ tracks, next, err := sc.GetNextMissingTracks(p)
if err != nil {
log.Printf("error getting %s playlist tracks from %s: %s\n", c.Params("playlist"), c.Params("user"), err)
return err
}
+ for i, track := range tracks {
+ track.Postfix(prefs)
+ tracks[i] = track
+ }
+
playlist.Tracks = tracks
playlist.MissingTracks = strings.Join(next, ",")
}
diff --git a/templates/playlist.templ b/templates/playlist.templ
index c4c977e..33f4a2c 100644
--- a/templates/playlist.templ
+++ b/templates/playlist.templ
@@ -51,7 +51,7 @@ templ Playlist(prefs cfg.Preferences, p sc.Playlist) {
for _, track := range p.Tracks {
- @TrackItem(track, true)
+ @TrackItem(&track, true)
}
if len(p.MissingTracks) != 0 {
diff --git a/templates/track.templ b/templates/track.templ
index 79b4998..f50c5d8 100644
--- a/templates/track.templ
+++ b/templates/track.templ
@@ -82,8 +82,11 @@ templ Track(prefs cfg.Preferences, t sc.Track, stream string, displayErr string)
}
@UserItem(&t.Author)
//
-
+
if t.Description != "" {