diff --git a/lib/proxy_images/init.go b/lib/proxy_images/init.go index d106dbe..b2b8ba6 100644 --- a/lib/proxy_images/init.go +++ b/lib/proxy_images/init.go @@ -45,7 +45,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetURI(parsed) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) //req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") images not big enough to be compressed resp := fasthttp.AcquireResponse() diff --git a/lib/proxy_streams/init.go b/lib/proxy_streams/init.go index 07714d2..d4493a9 100644 --- a/lib/proxy_streams/init.go +++ b/lib/proxy_streams/init.go @@ -54,7 +54,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetURI(parsed) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -93,7 +93,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetURI(parsed) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -131,7 +131,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetURI(parsed) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -182,7 +182,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetURI(parsed) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() diff --git a/lib/restream/init.go b/lib/restream/init.go index 5e26262..47fc988 100644 --- a/lib/restream/init.go +++ b/lib/restream/init.go @@ -4,6 +4,7 @@ import ( "bytes" "image/jpeg" "io" + "sync" "github.com/bogem/id3v2/v2" "github.com/gcottom/mp4meta" @@ -29,6 +30,16 @@ type reader struct { client *fasthttp.HostClient } +var readerpool = sync.Pool{ + New: func() any { + return &reader{} + }, +} + +func acquireReader() *reader { + return readerpool.Get().(*reader) +} + func clone(buf []byte) []byte { out := make([]byte, len(buf)) copy(out, buf) @@ -40,7 +51,7 @@ func (r *reader) Setup(url string, aac bool) error { r.resp = fasthttp.AcquireResponse() r.req.SetRequestURI(url) - r.req.Header.Set("User-Agent", cfg.UserAgent) + r.req.Header.SetUserAgent(cfg.UserAgent) r.req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") if aac { @@ -59,7 +70,10 @@ func (r *reader) Setup(url string, aac bool) error { data = r.resp.Body() } - r.parts = make([][]byte, 0, 16) + if r.parts == nil { + cfg.Log("make() r.parts") + r.parts = make([][]byte, 0, 16) + } if aac { // clone needed to mitigate memory skill issues here for _, s := range bytes.Split(data, []byte{'\n'}) { @@ -89,6 +103,27 @@ func (r *reader) Setup(url string, aac bool) error { return nil } +func (r *reader) Close() error { + cfg.Log("closed :D") + if r.req != nil { + fasthttp.ReleaseRequest(r.req) + r.req = nil + } + + if r.resp != nil { + fasthttp.ReleaseResponse(r.resp) + r.resp = nil + } + + r.client = nil + r.leftover = nil + r.index = 0 + r.parts = r.parts[:0] + + readerpool.Put(r) + return nil +} + // you could prob make this a bit faster by concurrency (make a bunch of workers => make them download the parts => temporarily add them to a map => fully assemble the result => make reader.Read() read out the result as the parts are coming in) but whatever, fine for now func (r *reader) Read(buf []byte) (n int, err error) { if len(r.leftover) != 0 { @@ -113,8 +148,6 @@ func (r *reader) Read(buf []byte) (n int, err error) { } if r.index == len(r.parts) { - fasthttp.ReleaseRequest(r.req) - fasthttp.ReleaseResponse(r.resp) err = io.EOF return } @@ -224,7 +257,7 @@ func Load(r fiber.Router) { if isDownload { switch audio { case cfg.AudioMP3: - r := reader{} + r := acquireReader() if err := r.Setup(u, false); err != nil { return err } @@ -252,14 +285,14 @@ func Load(r fiber.Router) { r.leftover = col.data // id3 is quite flexible and the files streamed by soundcloud don't have it so its easy to restream the stuff like this - return c.SendStream(&r) + return c.SendStream(r) case cfg.AudioOpus: req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) req.SetRequestURI(u) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -338,7 +371,7 @@ func Load(r fiber.Router) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI(u) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -422,11 +455,11 @@ func Load(r fiber.Router) { } } - r := reader{} + r := acquireReader() if err := r.Setup(u, audio == cfg.AudioAAC); err != nil { return err } - return c.SendStream(&r) + return c.SendStream(r) }) } diff --git a/lib/sc/init.go b/lib/sc/init.go index 47f34b0..bd75455 100644 --- a/lib/sc/init.go +++ b/lib/sc/init.go @@ -68,7 +68,7 @@ func processFile(wg *sync.WaitGroup, ch chan string, uri string, isDone *bool) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI(uri) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -134,7 +134,7 @@ func GetClientID() (string, error) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI("https://soundcloud.com/h") // 404 page - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -292,7 +292,7 @@ func Resolve(cid string, path string, out any) error { defer fasthttp.ReleaseRequest(req) req.SetRequestURI("https://" + api + "/resolve?url=https%3A%2F%2Fsoundcloud.com%2F" + url.QueryEscape(path) + "&client_id=" + cid) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -335,7 +335,7 @@ func (p *Paginated[T]) Proceed(cid string, shouldUnfold bool) error { oldNext := p.Next req.SetRequestURI(p.Next + "&client_id=" + cid) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() diff --git a/lib/sc/playlist.go b/lib/sc/playlist.go index 3e6c447..702a207 100644 --- a/lib/sc/playlist.go +++ b/lib/sc/playlist.go @@ -190,7 +190,7 @@ func (p *Playlist) GetMissingTracks(cid string) error { missing := []MissingTrack{} for i, track := range p.Tracks { if track.Title == "" { - missing = append(missing, MissingTrack{ID: strconv.FormatInt(int64(track.IDint), 10), Index: i}) + missing = append(missing, MissingTrack{ID: string(track.ID), Index: i}) } } @@ -205,7 +205,7 @@ func (p *Playlist) GetMissingTracks(cid string) error { for _, oldTrack := range missing { for _, newTrack := range res { - if newTrack.ID == oldTrack.ID { + if string(newTrack.ID) == string(oldTrack.ID) { p.Tracks[oldTrack.Index] = newTrack } } diff --git a/lib/sc/track.go b/lib/sc/track.go index 12dbbb7..7311979 100644 --- a/lib/sc/track.go +++ b/lib/sc/track.go @@ -38,13 +38,11 @@ type Track struct { Reposted int64 `json:"reposts_count"` TagList string `json:"tag_list"` Title string `json:"title"` - ID string `json:"urn"` + ID json.Number `json:"id"` Media Media `json:"media"` Authorization string `json:"track_authorization"` Author User `json:"user"` Policy TrackPolicy `json:"policy"` - - IDint int64 `json:"id"` } type TrackPolicy string @@ -260,7 +258,7 @@ func GetTracks(cid string, ids string) ([]Track, error) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI("https://" + api + "/tracks?ids=" + ids + "&client_id=" + cid) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -298,7 +296,7 @@ func (tr Transcoding) GetStream(cid string, prefs cfg.Preferences, authorization defer fasthttp.ReleaseRequest(req) req.SetRequestURI(tr.URL + "?client_id=" + cid + "&track_authorization=" + authorization) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -348,13 +346,6 @@ func (t *Track) Fix(large bool, fixAuthor bool) { t.Artwork = strings.Replace(t.Artwork, "-large.", "-t200x200.", 1) } - if t.ID == "" { - t.ID = strconv.FormatInt(t.IDint, 10) - } else { - ls := strings.Split(t.ID, ":") - t.ID = ls[len(ls)-1] - } - if fixAuthor { t.Author.Fix(false) } @@ -392,7 +383,7 @@ func (t Track) FormatDescription() string { func GetTrackByID(cid string, id string) (Track, error) { tracksCacheLock.RLock() for _, cell := range TracksCache { - if cell.Value.ID == id && cell.Expires.After(time.Now()) { + if string(cell.Value.ID) == string(id) && cell.Expires.After(time.Now()) { tracksCacheLock.RUnlock() return cell.Value, nil } @@ -412,7 +403,7 @@ func GetTrackByID(cid string, id string) (Track, error) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI("https://" + api + "/tracks/" + id + "?client_id=" + cid) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -451,7 +442,7 @@ func (t Track) DownloadImage() ([]byte, string, error) { defer fasthttp.ReleaseRequest(req) req.SetRequestURI(t.Artwork) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) //req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") images not big enough to be compressed resp := fasthttp.AcquireResponse() diff --git a/lib/sc/user.go b/lib/sc/user.go index 1493916..67c61f5 100644 --- a/lib/sc/user.go +++ b/lib/sc/user.go @@ -20,21 +20,21 @@ var UsersCache = map[string]cached[User]{} var usersCacheLock = &sync.RWMutex{} type User struct { - Avatar string `json:"avatar_url"` - CreatedAt string `json:"created_at"` - Description string `json:"description"` - Followers int64 `json:"followers_count"` - Following int64 `json:"followings_count"` - FullName string `json:"full_name"` - Kind string `json:"kind"` // should always be "user"! - LastModified string `json:"last_modified"` - Liked int64 `json:"likes_count"` - Permalink string `json:"permalink"` - Playlists int64 `json:"playlist_count"` - Tracks int64 `json:"track_count"` - ID string `json:"urn"` - Username string `json:"username"` - Verified bool `json:"verified"` + Avatar string `json:"avatar_url"` + CreatedAt string `json:"created_at"` + Description string `json:"description"` + Followers int64 `json:"followers_count"` + Following int64 `json:"followings_count"` + FullName string `json:"full_name"` + Kind string `json:"kind"` // should always be "user"! + LastModified string `json:"last_modified"` + Liked int64 `json:"likes_count"` + Permalink string `json:"permalink"` + Playlists int64 `json:"playlist_count"` + Tracks int64 `json:"track_count"` + ID json.Number `json:"id"` + Username string `json:"username"` + Verified bool `json:"verified"` WebProfiles []Link } @@ -151,7 +151,7 @@ func SearchUsers(cid string, prefs cfg.Preferences, args string) (*Paginated[*Us func (u User) GetTracks(cid string, prefs cfg.Preferences, args string) (*Paginated[*Track], error) { p := Paginated[*Track]{ - Next: "https://" + api + "/users/" + u.ID + "/tracks" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/tracks" + args, } err := p.Proceed(cid, true) @@ -202,9 +202,6 @@ func (u *User) Fix(large bool) { u.Avatar = "" } - ls := strings.Split(u.ID, ":") - u.ID = ls[len(ls)-1] - for i, l := range u.WebProfiles { if textparsing.IsEmail(l.URL) { l.URL = "mailto:" + l.URL @@ -233,7 +230,7 @@ func (u *User) Postfix(prefs cfg.Preferences) { func (u User) GetPlaylists(cid string, prefs cfg.Preferences, args string) (*Paginated[*Playlist], error) { p := Paginated[*Playlist]{ - Next: "https://" + api + "/users/" + u.ID + "/playlists_without_albums" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/playlists_without_albums" + args, } err := p.Proceed(cid, true) @@ -251,7 +248,7 @@ func (u User) GetPlaylists(cid string, prefs cfg.Preferences, args string) (*Pag func (u User) GetAlbums(cid string, prefs cfg.Preferences, args string) (*Paginated[*Playlist], error) { p := Paginated[*Playlist]{ - Next: "https://" + api + "/users/" + u.ID + "/albums" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/albums" + args, } err := p.Proceed(cid, true) @@ -269,7 +266,7 @@ func (u User) GetAlbums(cid string, prefs cfg.Preferences, args string) (*Pagina func (u User) GetReposts(cid string, prefs cfg.Preferences, args string) (*Paginated[*Repost], error) { p := Paginated[*Repost]{ - Next: "https://" + api + "/stream/users/" + u.ID + "/reposts" + args, + Next: "https://" + api + "/stream/users/" + string(u.ID) + "/reposts" + args, } err := p.Proceed(cid, true) @@ -286,7 +283,7 @@ func (u User) GetReposts(cid string, prefs cfg.Preferences, args string) (*Pagin func (u User) GetLikes(cid string, prefs cfg.Preferences, args string) (*Paginated[*Like], error) { p := Paginated[*Like]{ - Next: "https://" + api + "/users/" + u.ID + "/likes" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/likes" + args, } err := p.Proceed(cid, true) @@ -313,8 +310,8 @@ func (u *User) GetWebProfiles(cid string) error { req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) - req.SetRequestURI("https://" + api + "/users/" + u.ID + "/web-profiles?client_id=" + cid) - req.Header.Set("User-Agent", cfg.UserAgent) + req.SetRequestURI("https://" + api + "/users/soundcloud:users:" + string(u.ID) + "/web-profiles?client_id=" + cid) + req.Header.SetUserAgent(cfg.UserAgent) req.Header.Set("Accept-Encoding", "gzip, deflate, br, zstd") resp := fasthttp.AcquireResponse() @@ -339,7 +336,7 @@ func (u *User) GetWebProfiles(cid string) error { func (u *User) GetRelated(cid string, prefs cfg.Preferences) ([]*User, error) { p := Paginated[*User]{ - Next: "https://" + api + "/users/" + u.ID + "/relatedartists?page_size=20", + Next: "https://" + api + "/users/" + string(u.ID) + "/relatedartists?page_size=20", } err := p.Proceed(cid, true) @@ -357,7 +354,7 @@ func (u *User) GetRelated(cid string, prefs cfg.Preferences) ([]*User, error) { func (u *User) GetTopTracks(cid string, prefs cfg.Preferences) ([]*Track, error) { p := Paginated[*Track]{ - Next: "https://" + api + "/users/" + u.ID + "/toptracks?limit=10", + Next: "https://" + api + "/users/" + string(u.ID) + "/toptracks?limit=10", } err := p.Proceed(cid, true) @@ -375,7 +372,7 @@ func (u *User) GetTopTracks(cid string, prefs cfg.Preferences) ([]*Track, error) func (u User) GetFollowers(cid string, prefs cfg.Preferences, args string) (*Paginated[*User], error) { p := Paginated[*User]{ - Next: "https://" + api + "/users/" + u.ID + "/followers" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/followers" + args, } err := p.Proceed(cid, true) @@ -393,7 +390,7 @@ func (u User) GetFollowers(cid string, prefs cfg.Preferences, args string) (*Pag func (u User) GetFollowing(cid string, prefs cfg.Preferences, args string) (*Paginated[*User], error) { p := Paginated[*User]{ - Next: "https://" + api + "/users/" + u.ID + "/followings" + args, + Next: "https://" + api + "/users/" + string(u.ID) + "/followings" + args, } err := p.Proceed(cid, true) diff --git a/main.go b/main.go index 112c4e4..28afe78 100644 --- a/main.go +++ b/main.go @@ -116,7 +116,7 @@ func main() { req.Header.SetMethod("HEAD") req.SetRequestURI("https://on.soundcloud.com/" + id) - req.Header.Set("User-Agent", cfg.UserAgent) + req.Header.SetUserAgent(cfg.UserAgent) resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) @@ -531,7 +531,7 @@ func main() { playlist = &p if nextTrack.Title == "" { - nt, err := sc.GetTrackByID(cid, nextTrack.ID) + nt, err := sc.GetTrackByID(cid, string(nextTrack.ID)) if err != nil { return err } diff --git a/templates/base.templ b/templates/base.templ index 4a17f8a..cc6c971 100644 --- a/templates/base.templ +++ b/templates/base.templ @@ -22,6 +22,9 @@ templ Base(title string, content templ.Component, head templ.Component) { }
+ if cfg.Debug { +