mirror of
https://git.maid.zone/stuff/soundcloak.git
synced 2025-12-10 05:39:38 +05:00
Compare commits
4 Commits
39787b6cc9
...
0cf9f0d53f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cf9f0d53f | ||
|
|
fd571bc23c | ||
|
|
0474290010 | ||
|
|
e0bfcaadba |
@@ -105,4 +105,6 @@ If you want to add a new feature that's not in [the todo list](https://git.maid.
|
||||
|
||||
If you have updated go dependencies or added new ones, please run `go mod tidy` before commiting.
|
||||
|
||||
If you update structs, please run [betteralign](https://github.com/dkorunic/betteralign) to make sure memory layout is optimized.
|
||||
|
||||
Any security vulnerabilities should first be disclosed privately to the maintainer ([different ways to contact me are listed here](https://laptopc.at))
|
||||
@@ -15,14 +15,14 @@ import (
|
||||
const defaultPartsCapacity = 24
|
||||
|
||||
type reader struct {
|
||||
duration *uint32
|
||||
|
||||
req *fasthttp.Request
|
||||
resp *fasthttp.Response
|
||||
client *fasthttp.HostClient
|
||||
parts [][]byte
|
||||
leftover []byte
|
||||
index int
|
||||
duration *uint32
|
||||
|
||||
req *fasthttp.Request
|
||||
resp *fasthttp.Response
|
||||
client *fasthttp.HostClient
|
||||
}
|
||||
|
||||
var readerpool = sync.Pool{
|
||||
|
||||
@@ -1,13 +1,65 @@
|
||||
package sc
|
||||
|
||||
import "git.maid.zone/stuff/soundcloak/lib/cfg"
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
// Functions/structions related to featured/suggested content
|
||||
"git.maid.zone/stuff/soundcloak/lib/cfg"
|
||||
)
|
||||
|
||||
// Functions/structures related to featured/suggested content
|
||||
|
||||
type PlaylistOrUser struct {
|
||||
Kind string `json:"kind"` // "playlist" or "system-playlist" or "user"
|
||||
Permalink string `json:"permalink"`
|
||||
|
||||
// User-specific
|
||||
Avatar string `json:"avatar_url"`
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
|
||||
// Playlist-specific
|
||||
Title string `json:"title"`
|
||||
Author struct {
|
||||
Permalink string `string:"permalink"`
|
||||
} `json:"user"`
|
||||
Artwork string `json:"artwork_url"`
|
||||
TrackCount int64 `json:"track_count"`
|
||||
}
|
||||
|
||||
func (p PlaylistOrUser) Href() string {
|
||||
switch p.Kind {
|
||||
case "system-playlist":
|
||||
return "/discover/sets/" + p.Permalink
|
||||
case "playlist":
|
||||
return "/" + p.Author.Permalink + "/sets/" + p.Permalink
|
||||
default:
|
||||
return "/" + p.Permalink
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PlaylistOrUser) Fix(prefs cfg.Preferences) {
|
||||
switch p.Kind {
|
||||
case "user":
|
||||
if p.Avatar == "https://a1.sndcdn.com/images/default_avatar_large.png" {
|
||||
p.Avatar = ""
|
||||
} else {
|
||||
p.Avatar = strings.Replace(p.Avatar, "-large.", "-t200x200.", 1)
|
||||
}
|
||||
default:
|
||||
if p.Artwork != "" {
|
||||
p.Artwork = strings.Replace(p.Artwork, "-large.", "-t200x200.", 1)
|
||||
if cfg.ProxyImages && *prefs.ProxyImages {
|
||||
p.Artwork = "/_/proxy/images?url=" + url.QueryEscape(p.Artwork)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Selection struct {
|
||||
Title string `json:"title"`
|
||||
Kind string `json:"kind"` // should always be "selection"!
|
||||
Items Paginated[*Playlist] `json:"items"` // ?? why
|
||||
Title string `json:"title"`
|
||||
Kind string `json:"kind"` // should always be "selection"!
|
||||
Items Paginated[*PlaylistOrUser] `json:"items"` // ?? why
|
||||
}
|
||||
|
||||
func GetSelections(cid string, prefs cfg.Preferences) (*Paginated[*Selection], error) {
|
||||
@@ -27,7 +79,6 @@ func GetSelections(cid string, prefs cfg.Preferences) (*Paginated[*Selection], e
|
||||
|
||||
func (s *Selection) Fix(prefs cfg.Preferences) {
|
||||
for _, p := range s.Items.Collection {
|
||||
p.Fix("", false, false)
|
||||
p.Postfix(prefs, false, false)
|
||||
p.Fix(prefs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
)
|
||||
|
||||
type clientIdCache struct {
|
||||
NextCheck time.Time
|
||||
ClientID string
|
||||
Version string
|
||||
NextCheck time.Time
|
||||
}
|
||||
|
||||
var ClientIDCache clientIdCache
|
||||
@@ -342,9 +342,9 @@ func Resolve(cid string, path string, out any) error {
|
||||
}
|
||||
|
||||
type Paginated[T any] struct {
|
||||
Next string `json:"next_href"`
|
||||
Collection []T `json:"collection"`
|
||||
Total int64 `json:"total_results"`
|
||||
Next string `json:"next_href"`
|
||||
}
|
||||
|
||||
func (p *Paginated[T]) Proceed(cid string, shouldUnfold bool) error {
|
||||
|
||||
@@ -16,23 +16,21 @@ var playlistsCacheLock = &sync.RWMutex{}
|
||||
// Functions/structures related to playlists
|
||||
|
||||
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"! or "system-playlist"
|
||||
LastModified string `json:"last_modified"`
|
||||
Likes int64 `json:"likes_count"`
|
||||
Permalink string `json:"permalink"`
|
||||
//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"`
|
||||
TrackCount int64 `json:"track_count"`
|
||||
|
||||
MissingTracks string `json:"-"`
|
||||
Artwork string `json:"artwork_url"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Description string `json:"description"`
|
||||
Kind string `json:"kind"` // should always be "playlist"! or "system-playlist"
|
||||
LastModified string `json:"last_modified"`
|
||||
Permalink string `json:"permalink"`
|
||||
TagList string `json:"tag_list"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"set_type"`
|
||||
MissingTracks string `json:"-"`
|
||||
Tracks []Track `json:"tracks"`
|
||||
Author User `json:"user"`
|
||||
Likes int64 `json:"likes_count"`
|
||||
TrackCount int64 `json:"track_count"`
|
||||
Album bool `json:"is_album"`
|
||||
}
|
||||
|
||||
func GetPlaylist(cid string, permalink string) (Playlist, error) {
|
||||
|
||||
@@ -25,26 +25,26 @@ var tracksCacheLock = &sync.RWMutex{}
|
||||
|
||||
type Track struct {
|
||||
Artwork string `json:"artwork_url"`
|
||||
Comments int `json:"comment_count"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Description string `json:"description"`
|
||||
Duration uint32 `json:"full_duration"`
|
||||
Genre string `json:"genre"`
|
||||
Kind string `json:"kind"` // should always be "track"!
|
||||
LastModified string `json:"last_modified"`
|
||||
License string `json:"license"`
|
||||
Likes int64 `json:"likes_count"`
|
||||
Permalink string `json:"permalink"`
|
||||
Played int64 `json:"playback_count"`
|
||||
Reposted int64 `json:"reposts_count"`
|
||||
TagList string `json:"tag_list"`
|
||||
Title string `json:"title"`
|
||||
ID json.Number `json:"id"`
|
||||
Media Media `json:"media"`
|
||||
Authorization string `json:"track_authorization"`
|
||||
Author User `json:"user"`
|
||||
Policy TrackPolicy `json:"policy"`
|
||||
Station string `json:"station_permalink"`
|
||||
Media Media `json:"media"`
|
||||
Author User `json:"user"`
|
||||
Comments int `json:"comment_count"`
|
||||
Likes int64 `json:"likes_count"`
|
||||
Played int64 `json:"playback_count"`
|
||||
Reposted int64 `json:"reposts_count"`
|
||||
Duration uint32 `json:"full_duration"`
|
||||
}
|
||||
|
||||
type TrackPolicy string
|
||||
@@ -89,8 +89,8 @@ type Stream struct {
|
||||
type Comment struct {
|
||||
Kind string `json:"kind"` // "comment"
|
||||
Body string `json:"body"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
Author User `json:"user"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
}
|
||||
|
||||
func (m Media) SelectCompatible(mode string, opus bool) (*Transcoding, string) {
|
||||
|
||||
@@ -23,21 +23,20 @@ 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 json.Number `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Verified bool `json:"verified"`
|
||||
Station string `json:"station_permalink"`
|
||||
|
||||
WebProfiles []Link `json:",omitempty"`
|
||||
WebProfiles []Link `json:",omitempty"`
|
||||
Followers int64 `json:"followers_count"`
|
||||
Following int64 `json:"followings_count"`
|
||||
Liked int64 `json:"likes_count"`
|
||||
Playlists int64 `json:"playlist_count"`
|
||||
Tracks int64 `json:"track_count"`
|
||||
Verified bool `json:"verified"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
@@ -54,10 +53,9 @@ const (
|
||||
|
||||
// not worthy of its own file
|
||||
type Repost struct {
|
||||
Type RepostType
|
||||
|
||||
Track *Track // type == track-report
|
||||
Playlist *Playlist // type == playlist-repost
|
||||
Type RepostType
|
||||
}
|
||||
|
||||
func (r Repost) Fix(prefs cfg.Preferences) {
|
||||
|
||||
2
main.go
2
main.go
@@ -554,13 +554,13 @@ Disallow: /`)
|
||||
|
||||
if cfg.InstanceInfo {
|
||||
type info struct {
|
||||
DefaultPreferences cfg.Preferences
|
||||
Commit string
|
||||
Repo string
|
||||
ProxyImages bool
|
||||
ProxyStreams bool
|
||||
Restream bool
|
||||
GetWebProfiles bool
|
||||
DefaultPreferences cfg.Preferences
|
||||
EnableAPI bool
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,33 @@ import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
templ PlaylistOrUserItem(pl *sc.PlaylistOrUser) {
|
||||
<a class="listing" href={ templ.SafeURL(pl.Href()) }>
|
||||
{{
|
||||
img := pl.Artwork
|
||||
if pl.Kind == "user" {
|
||||
img = pl.Avatar
|
||||
}
|
||||
}}
|
||||
if img != "" {
|
||||
<img loading="lazy" fetchpriority="low" src={ img }/>
|
||||
} else {
|
||||
<img loading="lazy" fetchpriority="low" src="/_/static/placeholder.jpg"/>
|
||||
}
|
||||
<div class="meta">
|
||||
if pl.Kind == "user" {
|
||||
<h3>{ pl.Username }</h3>
|
||||
if pl.FullName != "" {
|
||||
<span>{ pl.FullName }</span>
|
||||
}
|
||||
} else {
|
||||
<h3>{ pl.Title }</h3>
|
||||
<p>{ strconv.FormatInt(pl.TrackCount, 10) } tracks</p>
|
||||
}
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
templ Discover(p *sc.Paginated[*sc.Selection]) {
|
||||
<h1>Discover Playlists</h1> // also tracks apparently? haven't seen any
|
||||
<span>Got { strconv.FormatInt(int64(len(p.Collection)), 10) } selections</span>
|
||||
@@ -17,8 +44,7 @@ templ Discover(p *sc.Paginated[*sc.Selection]) {
|
||||
|
||||
<h2>{selection.Title}</h2>
|
||||
for _, pl := range selection.Items.Collection {
|
||||
// We don't need the username
|
||||
@PlaylistItem(pl, false)
|
||||
@PlaylistOrUserItem(pl)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user