mirror of
https://git.maid.zone/stuff/soundcloak.git
synced 2025-12-14 07:39:38 +05:00
started working on playlists support
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<select name="type">
|
||||
<option value="tracks">Tracks</option>
|
||||
<option value="users">Users</option>
|
||||
<option value="playlists">Playlists</option>
|
||||
</select>
|
||||
|
||||
<input type="submit" value="Search">
|
||||
|
||||
@@ -16,6 +16,9 @@ const UserTTL = 5 * time.Minute
|
||||
// time-to-live for track cache
|
||||
const TrackTTL = 5 * time.Minute
|
||||
|
||||
// time-to-live for playlist cache
|
||||
const PlaylistTTL = 5 * time.Minute
|
||||
|
||||
// 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"
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ var httpc = fasthttp.HostClient{
|
||||
|
||||
var usersCache = map[string]cached[User]{}
|
||||
var tracksCache = map[string]cached[Track]{}
|
||||
var userSearchCache = map[string]cached[Paginated[User]]{}
|
||||
var trackSearchCache = map[string]cached[Paginated[Track]]{}
|
||||
var playlistsCache = map[string]cached[Playlist]{}
|
||||
|
||||
var verRegex = regexp.MustCompile(`(?m)^<script>window\.__sc_version="([0-9]{10})"</script>$`)
|
||||
var scriptsRegex = regexp.MustCompile(`(?m)^<script crossorigin src="(https://a-v2\.sndcdn\.com/assets/.+\.js)"></script>$`)
|
||||
@@ -340,3 +339,39 @@ func SearchUsers(args string) (*Paginated[User], error) {
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func SearchPlaylists(args string) (*Paginated[Playlist], error) {
|
||||
cid, err := GetClientID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p := Paginated[Playlist]{Next: "https://api-v2.soundcloud.com/search/playlists" + args + "&client_id=" + cid}
|
||||
err = p.Proceed()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func GetPlaylist(permalink string) (Playlist, error) {
|
||||
if cell, ok := playlistsCache[permalink]; ok && cell.Expires.After(time.Now()) {
|
||||
return cell.Value, nil
|
||||
}
|
||||
|
||||
var u Playlist
|
||||
err := Resolve(permalink, &u)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
||||
if u.Kind != "playlist" {
|
||||
fmt.Println(u.Kind)
|
||||
return u, ErrKindNotCorrect
|
||||
}
|
||||
|
||||
playlistsCache[permalink] = cached[Playlist]{Value: u, Expires: time.Now().Add(cfg.PlaylistTTL)}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
@@ -80,3 +80,18 @@ type Paginated[T any] struct {
|
||||
type Stream struct {
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type Playlist struct {
|
||||
Artwork string `json:"artwork_url"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Description string `json:"description"`
|
||||
Kind string `json:"kind"` // should always be "playlist"!
|
||||
LastModified string `json:"last_modified"`
|
||||
ReleaseDate string `json:"release_date"`
|
||||
TagList string `json:"tag_list"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"set_type"`
|
||||
Album bool `json:"is_album"`
|
||||
Author User `json:"user"`
|
||||
Tracks []Track `json:"tracks"`
|
||||
}
|
||||
|
||||
21
main.go
21
main.go
@@ -53,6 +53,16 @@ func main() {
|
||||
|
||||
c.Set("Content-Type", "text/html")
|
||||
return templates.Base("users: "+q, templates.SearchUsers(p)).Render(context.Background(), c)
|
||||
|
||||
case "playlists":
|
||||
p, err := sc.SearchPlaylists("?q=" + url.QueryEscape(q))
|
||||
if err != nil {
|
||||
fmt.Printf("error getting users for %s: %s\n", q, err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.Set("Content-Type", "text/html")
|
||||
return templates.Base("playlists: "+q, templates.SearchPlaylists(p)).Render(context.Background(), c)
|
||||
}
|
||||
|
||||
return c.SendStatus(404)
|
||||
@@ -95,5 +105,16 @@ func main() {
|
||||
return templates.Base(usr.Username, templates.User(usr, p)).Render(context.Background(), c)
|
||||
})
|
||||
|
||||
app.Get("/:user/sets/:playlist", func(c *fiber.Ctx) error {
|
||||
playlist, err := sc.GetPlaylist(c.Params("user") + "/sets/" + c.Params("playlist"))
|
||||
if err != nil {
|
||||
fmt.Printf("error getting %s playlist from %s: %s\n", c.Params("playlist"), c.Params("user"), err)
|
||||
return err
|
||||
}
|
||||
|
||||
c.Set("Content-Type", "text/html")
|
||||
return templates.Base(playlist.Title+" by "+playlist.Author.Username, templates.Playlist(playlist)).Render(context.Background(), c)
|
||||
})
|
||||
|
||||
log.Fatal(app.Listen(cfg.Addr))
|
||||
}
|
||||
|
||||
7
templates/playlist.templ
Normal file
7
templates/playlist.templ
Normal file
@@ -0,0 +1,7 @@
|
||||
package templates
|
||||
|
||||
import "github.com/maid-zone/soundcloak/lib/sc"
|
||||
|
||||
templ Playlist(p sc.Playlist) {
|
||||
<h1>{p.Title}</h1>
|
||||
}
|
||||
10
templates/searchPlaylists.templ
Normal file
10
templates/searchPlaylists.templ
Normal file
@@ -0,0 +1,10 @@
|
||||
package templates
|
||||
|
||||
import "github.com/maid-zone/soundcloak/lib/sc"
|
||||
|
||||
|
||||
templ SearchPlaylists(p *sc.Paginated[sc.Playlist]) {
|
||||
for _, playlist := range p.Collection {
|
||||
<h1>{playlist.Title}</h1>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user