caching improvements; add more ways to get track for widget player

This commit is contained in:
Laptop
2024-10-09 19:15:38 +03:00
parent 2b66f6b273
commit 1207f193e8
6 changed files with 104 additions and 23 deletions

View File

@@ -11,9 +11,9 @@ wip alternative frontend for soundcloud
- Resolving shortened links (`https://on.soundcloud.com/boiKDP46fayYDoVK9` -> `https://sc.maid.zone/on/boiKDP46fayYDoVK9`)
## In the works
- Track player embeds (`https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/id` -> `https://sc.maid.zone/w/player/?url=https%3A//api.soundcloud.com/tracks/id`)
- Track player embeds (`https://w.soundcloud.com/player/` -> `https://sc.maid.zone/w/player/`)
The UI isn't really done yet. All parameters other than url are unsupported. You can also specify track by permalink instead of id (`https://sc.maid.zone/w/player/?url=username/track`)
The UI isn't really done yet. All parameters other than url are unsupported. You can also specify track without the `soundcloud.com` part: `https://sc.maid.zone/w/player/?url=<id>` or `https://sc.maid.zone/w/player/?url=<user>/<track>`
# Contributing
Contributions are appreciated! This includes feedback, feature requests, issues, pull requests and etc.

View File

@@ -33,7 +33,7 @@ h4,
h5,
h6 {
font-family: "fixed", monospace, system-ui;
font-weight: normal;
font-weight: normal !important;
}
/* header {

View File

@@ -16,13 +16,22 @@ const FullyPreloadTrack = false
const ClientIDTTL = 30 * time.Minute
// time-to-live for user profile cache
const UserTTL = 5 * time.Minute
const UserTTL = 10 * time.Minute
// delay between cleanup of user cache
const UserCacheCleanDelay = UserTTL / 4
// time-to-live for track cache
const TrackTTL = 5 * time.Minute
const TrackTTL = 10 * time.Minute
// delay between cleanup of track cache
const TrackCacheCleanDelay = TrackTTL / 4
// time-to-live for playlist cache
const PlaylistTTL = 5 * time.Minute
const PlaylistTTL = 10 * time.Minute
// delay between cleanup of playlist cache
const PlaylistCacheCleanDelay = PlaylistTTL / 4
// default fasthttp one was causing connections to be stuck? todo make it cycle browser useragents or just choose random at startup
const UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.3"

View File

@@ -245,7 +245,7 @@ func TagListParser(taglist string) (res []string) {
// could probably make a generic function, whatever
func init() {
go func() {
ticker := time.NewTicker(cfg.UserTTL)
ticker := time.NewTicker(cfg.UserCacheCleanDelay)
for range ticker.C {
usersCacheLock.Lock()
@@ -260,7 +260,7 @@ func init() {
}()
go func() {
ticker := time.NewTicker(cfg.TrackTTL)
ticker := time.NewTicker(cfg.TrackCacheCleanDelay)
for range ticker.C {
tracksCacheLock.Lock()
@@ -275,7 +275,7 @@ func init() {
}()
go func() {
ticker := time.NewTicker(cfg.PlaylistTTL)
ticker := time.NewTicker(cfg.PlaylistCacheCleanDelay)
for range ticker.C {
playlistsCacheLock.Lock()

View File

@@ -3,6 +3,7 @@ package sc
import (
"errors"
"fmt"
"net/url"
"strconv"
"strings"
"sync"
@@ -107,6 +108,89 @@ func GetTrack(permalink string) (Track, error) {
return t, nil
}
// Currently supports:
// http/https links:
// - api.soundcloud.com/tracks/<id> (api-v2 subdomain also supported)
// - soundcloud.com/<user>/<track>
//
// plain permalink/id:
// - <user>/<track>
// - <id>
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(u.Path[8:])
}
if u.Host == "soundcloud.com" {
if len(u.Path) < 4 {
return Track{}, ErrNoURL
}
u.Path = u.Path[1:]
if u.Path[len(u.Path)-1] == '/' {
u.Path = u.Path[:len(u.Path)-1]
}
var n uint = 0
for _, c := range u.Path {
if c == '/' {
n++
}
}
if n != 1 {
return Track{}, ErrKindNotCorrect
}
return GetTrack(u.Path)
}
}
}
valid := true
for _, n := range data {
if n < '0' || n > '9' {
valid = false
break
}
}
if valid {
return GetTrackByID(data)
}
// this should be at the end since it manipulates data
if len(data) < 4 {
return Track{}, ErrNoURL
}
if data[0] == '/' {
data = data[1:]
}
if data[len(data)-1] == '/' {
data = data[:len(data)-1]
}
var n uint = 0
for _, c := range data {
if c == '/' {
n++
}
}
fmt.Println(data)
if n == 1 {
return GetTrack(data)
}
// failed to find a data point
return Track{}, ErrKindNotCorrect
}
func SearchTracks(args string) (*Paginated[*Track], error) {
cid, err := GetClientID()
if err != nil {
@@ -291,7 +375,7 @@ func GetTrackByID(id string) (Track, error) {
t.Fix(true)
tracksCacheLock.Lock()
tracksCache[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

14
main.go
View File

@@ -116,19 +116,7 @@ func main() {
return fiber.ErrNotFound
}
var (
track sc.Track
err error
)
if strings.HasPrefix(u, "https://") {
if !strings.HasPrefix(u, "https://api.soundcloud.com/tracks/") {
return fiber.ErrUnsupportedMediaType
}
track, err = sc.GetTrackByID(u[34:]) // len("https://api.soundcloud.com/tracks/") == 34
} else {
track, err = sc.GetTrack(u)
}
track, err := sc.GetArbitraryTrack(u)
if err != nil {
fmt.Printf("error getting %s: %s\n", u, err)