small restructuring in preparation for something

This commit is contained in:
Laptop 2024-12-23 18:57:32 +02:00
parent 8adb7a8b41
commit 491aa6028c
9 changed files with 148 additions and 125 deletions

View file

@ -1,6 +1,16 @@
Dockerfile
*.yaml
build
.github
.gitignore
soundcloak.example.json
LICENSE
README.md
*.yaml
docs
*.fiber.gz
node_modules
*_templ.go
regexp2_codegen.go
regexp2_codegen.go
main

View file

@ -2,16 +2,13 @@ package cfg
import (
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/goccy/go-json"
"github.com/valyala/fasthttp"
)
// You can now use a soundcloak.json file to configure!
@ -19,64 +16,6 @@ import (
// it's not needed to specify every key in your config, it will use the default values for keys you haven't specified
// also, when specifying time, specify it in seconds (instead of nanoseconds as time.Duration)
const (
// Downloads the HLS stream on the backend, and restreams it to frontend as a file. Requires no JS, but less stable client-side
RestreamPlayer string = "restream"
// Downloads the HLS stream on the frontend (proxying can be enabled). Requires JS, more stable client-side
HLSPlayer string = "hls"
// Disables the song player
NonePlayer string = "none"
)
const (
// Just plays every song in order, one after another
AutoplayNormal string = "normal"
// Randomly selects a song to play from the playlist
AutoplayRandom string = "random"
)
const (
// choose best for quality/size (AudioAAC over AudioOpus over AudioMP3)
AudioBest string = "best"
// 160kbps m4a AAC audio, rarely available (fallback to AudioMP3 if unavailable)
AudioAAC string = "aac"
// 72kbps ogg opus audio, usually available 99% of the time (fallback to AudioMP3 if unavailable)
AudioOpus string = "opus"
// 128kbps mp3 audio, always available, good for compatibility
AudioMP3 string = "mpeg"
)
type Preferences struct {
Player *string
ProxyStreams *bool
// fully loads the track on page load
// this option is here since the stream expires after some time (5 minutes? correct me if im wrong)
// if the stream isn't fully loaded before it expires - you'll need to reload the page
FullyPreloadTrack *bool
ProxyImages *bool
// Highlight @username, https://example.com and email@example.com in text as clickable links
ParseDescriptions *bool
// Automatically play next track in playlists
AutoplayNextTrack *bool
DefaultAutoplayMode *string // "normal" or "random"
// Check line 38 for constants
// Probably best to keep all at "mpeg" by default for compatibility
HLSAudio *string // Please don't use "opus" or "best". hls.js doesn't work with ogg/opus
RestreamAudio *string // You can actually use anything here
DownloadAudio *string // "aac" may not play well with some players
ShowAudio *bool // display audio (aac, opus, mpeg etc) under track player
}
// // config // //
// Retrieve links users set in their profile (social media, website, etc)
@ -565,44 +504,4 @@ func init() {
}
}
// seems soundcloud has 4 of these (i1, i2, i3, i4)
// they point to the same ip from my observations, and they all serve the same files
const ImageCDN = "i1.sndcdn.com"
const HLSCDN = "cf-hls-media.sndcdn.com"
const HLSAACCDN = "playback.media-streaming.soundcloud.cloud"
var True = true
var False = false
var prpool = sync.Pool{
New: func() any {
return &ProxyReader{}
},
}
func AcquireProxyReader() *ProxyReader {
return prpool.Get().(*ProxyReader)
}
type ProxyReader struct {
Reader io.Reader
Resp *fasthttp.Response
}
func (pr *ProxyReader) Read(p []byte) (int, error) {
return pr.Reader.Read(p)
}
func (pr *ProxyReader) Close() error {
defer fasthttp.ReleaseResponse(pr.Resp)
defer prpool.Put(pr)
return pr.Resp.CloseBodyStream()
}
const Debug = false
func Log(what ...any) {
if Debug {
fmt.Println(what...)
}
}

68
lib/cfg/misc.go Normal file
View file

@ -0,0 +1,68 @@
package cfg
// seems soundcloud has 4 of these (i1, i2, i3, i4)
// they point to the same ip from my observations, and they all serve the same files
const ImageCDN = "i1.sndcdn.com"
const HLSCDN = "cf-hls-media.sndcdn.com"
const HLSAACCDN = "playback.media-streaming.soundcloud.cloud"
var True = true
var False = false
const (
// Downloads the HLS stream on the backend, and restreams it to frontend as a file. Requires no JS, but less stable client-side
RestreamPlayer string = "restream"
// Downloads the HLS stream on the frontend (proxying can be enabled). Requires JS, more stable client-side
HLSPlayer string = "hls"
// Disables the song player
NonePlayer string = "none"
)
const (
// Just plays every song in order, one after another
AutoplayNormal string = "normal"
// Randomly selects a song to play from the playlist
AutoplayRandom string = "random"
)
const (
// choose best for quality/size (AudioAAC over AudioOpus over AudioMP3)
AudioBest string = "best"
// 160kbps m4a AAC audio, rarely available (fallback to AudioMP3 if unavailable)
AudioAAC string = "aac"
// 72kbps ogg opus audio, usually available 99% of the time (fallback to AudioMP3 if unavailable)
AudioOpus string = "opus"
// 128kbps mp3 audio, always available, good for compatibility
AudioMP3 string = "mpeg"
)
type Preferences struct {
Player *string
ProxyStreams *bool
// fully loads the track on page load
// this option is here since the stream expires after some time (5 minutes? correct me if im wrong)
// if the stream isn't fully loaded before it expires - you'll need to reload the page
FullyPreloadTrack *bool
ProxyImages *bool
// Highlight @username, https://example.com and email@example.com in text as clickable links
ParseDescriptions *bool
// Automatically play next track in playlists
AutoplayNextTrack *bool
DefaultAutoplayMode *string // "normal" or "random"
// Check line 38 for constants
// Probably best to keep all at "mpeg" by default for compatibility
HLSAudio *string // Please don't use "opus" or "best". hls.js doesn't work with ogg/opus
RestreamAudio *string // You can actually use anything here
DownloadAudio *string // "aac" may not play well with some players
ShowAudio *bool // display audio (aac, opus, mpeg etc) under track player
}

41
lib/misc/init.go Normal file
View file

@ -0,0 +1,41 @@
package misc
import (
"fmt"
"io"
"sync"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/valyala/fasthttp"
)
var prpool = sync.Pool{
New: func() any {
return &ProxyReader{}
},
}
func AcquireProxyReader() *ProxyReader {
return prpool.Get().(*ProxyReader)
}
type ProxyReader struct {
Reader io.Reader
Resp *fasthttp.Response
}
func (pr *ProxyReader) Read(p []byte) (int, error) {
return pr.Reader.Read(p)
}
func (pr *ProxyReader) Close() error {
defer fasthttp.ReleaseResponse(pr.Resp)
defer prpool.Put(pr)
return pr.Resp.CloseBodyStream()
}
func Log(what ...any) {
if cfg.Debug {
fmt.Println(what...)
}
}

View file

@ -5,6 +5,7 @@ import (
"github.com/gofiber/fiber/v2"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/maid-zone/soundcloak/lib/misc"
"github.com/maid-zone/soundcloak/lib/sc"
"github.com/valyala/fasthttp"
)
@ -59,7 +60,7 @@ func Load(r fiber.Router) {
c.Set("Content-Type", "image/jpeg")
c.Set("Cache-Control", cfg.ImageCacheControl)
//return c.Send(resp.Body())
pr := cfg.AcquireProxyReader()
pr := misc.AcquireProxyReader()
pr.Reader = resp.BodyStream()
pr.Resp = resp
return c.SendStream(pr)

View file

@ -6,6 +6,7 @@ import (
"github.com/gofiber/fiber/v2"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/maid-zone/soundcloak/lib/misc"
"github.com/maid-zone/soundcloak/lib/sc"
"github.com/valyala/fasthttp"
)
@ -65,7 +66,7 @@ func Load(r fiber.Router) {
return err
}
//return c.Send(resp.Body())
pr := cfg.AcquireProxyReader()
pr := misc.AcquireProxyReader()
pr.Reader = resp.BodyStream()
pr.Resp = resp
return c.SendStream(pr)
@ -103,7 +104,7 @@ func Load(r fiber.Router) {
return err
}
pr := cfg.AcquireProxyReader()
pr := misc.AcquireProxyReader()
pr.Reader = resp.BodyStream()
pr.Resp = resp
return c.SendStream(pr)

View file

@ -11,6 +11,7 @@ import (
"github.com/gcottom/oggmeta"
"github.com/gofiber/fiber/v2"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/maid-zone/soundcloak/lib/misc"
"github.com/maid-zone/soundcloak/lib/preferences"
"github.com/maid-zone/soundcloak/lib/sc"
"github.com/valyala/fasthttp"
@ -73,10 +74,10 @@ func (r *reader) Setup(url string, aac bool) error {
}
if r.parts == nil {
cfg.Log("make() r.parts")
misc.Log("make() r.parts")
r.parts = make([][]byte, 0, defaultPartsCapacity)
} else {
cfg.Log(cap(r.parts), len(r.parts))
misc.Log(cap(r.parts), len(r.parts))
}
if aac {
// clone needed to mitigate memory skill issues here
@ -108,7 +109,7 @@ func (r *reader) Setup(url string, aac bool) error {
}
func (r *reader) Close() error {
cfg.Log("closed :D")
misc.Log("closed :D")
if r.req != nil {
fasthttp.ReleaseRequest(r.req)
r.req = nil

View file

@ -12,6 +12,7 @@ import (
"github.com/dlclark/regexp2"
"github.com/goccy/go-json"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/maid-zone/soundcloak/lib/misc"
"github.com/valyala/fasthttp"
)
@ -61,9 +62,9 @@ type cached[T any] struct {
Expires time.Time
}
// don't be spooked by cfg.Log, it will be removed during compilation if cfg.Debug == false
// don't be spooked by misc.Log, it will be removed during compilation if cfg.Debug == false
func processFile(wg *sync.WaitGroup, ch chan string, uri string, isDone *bool) {
cfg.Log(uri)
misc.Log(uri)
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
@ -77,18 +78,18 @@ func processFile(wg *sync.WaitGroup, ch chan string, uri string, isDone *bool) {
defer wg.Done()
if *isDone {
cfg.Log("early 1")
misc.Log("early 1")
return
}
err := DoWithRetryAll(genericClient, req, resp)
if err != nil {
cfg.Log(err)
misc.Log(err)
return
}
if *isDone {
cfg.Log("early 2")
misc.Log("early 2")
return
}
@ -98,7 +99,7 @@ func processFile(wg *sync.WaitGroup, ch chan string, uri string, isDone *bool) {
}
if *isDone {
cfg.Log("early 3")
misc.Log("early 3")
return
}
@ -107,17 +108,17 @@ func processFile(wg *sync.WaitGroup, ch chan string, uri string, isDone *bool) {
g := m2.GroupByNumber(1)
if g != nil {
if *isDone {
cfg.Log("early 4")
misc.Log("early 4")
return
}
ch <- g.String()
cfg.Log("found in", uri)
misc.Log("found in", uri)
return
}
}
cfg.Log("not found in", uri)
misc.Log("not found in", uri)
}
// Experimental method, which asserts that the clientId is inside the file that starts with "0-"
@ -126,7 +127,7 @@ const experimental_GetClientID = true
// inspired by github.com/imputnet/cobalt (mostly stolen lol)
func GetClientID() (string, error) {
if ClientIDCache.NextCheck.After(time.Now()) {
cfg.Log("clientidcache hit @ 1")
misc.Log("clientidcache hit @ 1")
return ClientIDCache.ClientID, nil
}
@ -162,7 +163,7 @@ func GetClientID() (string, error) {
ver := g.String()
if ver == ClientIDCache.Version {
cfg.Log("clientidcache hit @ ver")
misc.Log("clientidcache hit @ ver")
ClientIDCache.NextCheck = time.Now().Add(cfg.ClientIDTTL)
return ClientIDCache.ClientID, nil
}
@ -190,7 +191,7 @@ func GetClientID() (string, error) {
ClientIDCache.ClientID = g.String()
ClientIDCache.Version = ver
ClientIDCache.NextCheck = time.Now().Add(cfg.ClientIDTTL)
cfg.Log(ClientIDCache)
misc.Log(ClientIDCache)
return ClientIDCache.ClientID, nil
}
}
@ -214,7 +215,7 @@ func GetClientID() (string, error) {
go func() {
defer func() {
err := recover()
cfg.Log("-- GetClientID recovered:", err)
misc.Log("-- GetClientID recovered:", err)
}()
wg.Wait()
@ -234,7 +235,7 @@ func GetClientID() (string, error) {
ClientIDCache.ClientID = res
ClientIDCache.Version = ver
ClientIDCache.NextCheck = time.Now().Add(cfg.ClientIDTTL)
cfg.Log(ClientIDCache)
misc.Log(ClientIDCache)
}
return res, err
@ -273,7 +274,7 @@ func DoWithRetry(httpc *fasthttp.HostClient, req *fasthttp.Request, resp *fastht
return
}
cfg.Log("we failed haha", err)
misc.Log("we failed haha", err)
}
return

View file

@ -11,6 +11,7 @@ import (
"github.com/goccy/go-json"
"github.com/maid-zone/soundcloak/lib/cfg"
"github.com/maid-zone/soundcloak/lib/misc"
"github.com/valyala/fasthttp"
)
@ -324,7 +325,7 @@ func (tr Transcoding) GetStream(cid string, prefs cfg.Preferences, authorization
return "", err
}
cfg.Log(s)
misc.Log(s)
if s.URL == "" {
return "", ErrNoURL