mirror of
https://codeberg.org/Hyperpipe/hyperpipe-backend
synced 2024-12-06 19:26:30 +01:00
323 lines
5.5 KiB
Go
323 lines
5.5 KiB
Go
package lib
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
type Thumbnail struct {
|
|
Height int64 `json:"height"`
|
|
Width int64 `json:"width"`
|
|
Url string `json:"url"`
|
|
}
|
|
|
|
type Item struct {
|
|
Id string `json:"id"`
|
|
Title string `json:"title"`
|
|
Sub string `json:"subtitle,omitempty"`
|
|
SubId string `json:"subId,omitempty"`
|
|
Thumbnails []Thumbnail `json:"thumbnails,omitempty"`
|
|
}
|
|
|
|
func RunsText(j gjson.Result) string {
|
|
|
|
var s []string
|
|
|
|
a := j.Get("runs.#.text").Array()
|
|
|
|
for i := 0; i < len(a); i++ {
|
|
s = append(s, a[i].String())
|
|
}
|
|
|
|
return strings.Join(s, "")
|
|
}
|
|
|
|
func parseUrl(raw string) (string, error) {
|
|
|
|
u, err := url.Parse(raw)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
prehost := u.Host
|
|
|
|
u.Scheme = "https"
|
|
u.Host = os.Getenv("HYP_PROXY")
|
|
|
|
q := u.Query()
|
|
q.Set("host", prehost)
|
|
u.RawQuery = q.Encode()
|
|
|
|
return u.String(), nil
|
|
}
|
|
|
|
func GetThumbnails(j gjson.Result) []Thumbnail {
|
|
|
|
t := make([]Thumbnail, j.Get("#").Int())
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
j.ForEach(
|
|
func(n, j gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
u, err := parseUrl(v.Get("url").String())
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
t[i] = Thumbnail{
|
|
Url: u,
|
|
Width: v.Get("width").Int(),
|
|
Height: v.Get("height").Int(),
|
|
}
|
|
}(n.Int(), j)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return t
|
|
}
|
|
|
|
func TwoRowItemRenderer(a gjson.Result, t bool) []Item {
|
|
|
|
id := "menu.menuRenderer.items.#(menuNavigationItemRenderer.text.runs.0.text == Shuffle play).menuNavigationItemRenderer.navigationEndpoint.watchPlaylistEndpoint.playlistId"
|
|
|
|
if !t {
|
|
id = "navigationEndpoint.browseEndpoint.browseId"
|
|
}
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
v := a.Get("#.musicTwoRowItemRenderer")
|
|
|
|
r := make([]Item, v.Get("#").Int())
|
|
|
|
v.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, j gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
gid := j.Get(id).String()
|
|
|
|
if len(gid) > 2 && gid[:2] == "VL" {
|
|
gid = gid[2:]
|
|
}
|
|
|
|
r[i] = Item{
|
|
Id: gid,
|
|
Title: RunsText(j.Get("title")),
|
|
Sub: RunsText(j.Get("subtitle")),
|
|
Thumbnails: GetThumbnails(
|
|
j.Get("thumbnailRenderer.musicThumbnailRenderer.thumbnail.thumbnails"),
|
|
),
|
|
}
|
|
|
|
}(n.Int(), s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|
|
|
|
func ResponsiveListItemRenderer(s gjson.Result) []Item {
|
|
|
|
r := make([]Item, s.Get("#").Int())
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
s.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
j := v.Get("musicResponsiveListItemRenderer")
|
|
flex := j.Get(
|
|
"flexColumns.#.musicResponsiveListItemFlexColumnRenderer.text.runs.0",
|
|
)
|
|
|
|
r[i] = Item{
|
|
Id: j.Get("playlistItemData.videoId").String(),
|
|
Title: flex.Get("#(navigationEndpoint.watchEndpoint.videoId).text").String(),
|
|
SubId: flex.Get(
|
|
"#.navigationEndpoint.browseEndpoint.browseId.0",
|
|
).String(),
|
|
Sub: flex.Get(
|
|
"#(navigationEndpoint.browseEndpoint.browseId).text",
|
|
).String(),
|
|
Thumbnails: GetThumbnails(
|
|
j.Get("thumbnail.musicThumbnailRenderer.thumbnail.thumbnails"),
|
|
),
|
|
}
|
|
|
|
}(n.Int(), s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|
|
|
|
func ResponsiveListItemRendererCH(s gjson.Result) []Item {
|
|
|
|
r := make([]Item, s.Get("#").Int())
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
s.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
j := v.Get("musicResponsiveListItemRenderer")
|
|
flex := j.Get(
|
|
"flexColumns.#.musicResponsiveListItemFlexColumnRenderer.text.runs.0.text",
|
|
)
|
|
|
|
r[i] = Item{
|
|
Id: j.Get("navigationEndpoint.browseEndpoint.browseId").String(),
|
|
Title: flex.Get("0").String() + " • " + flex.Get("1").String(),
|
|
Thumbnails: GetThumbnails(
|
|
j.Get("thumbnail.musicThumbnailRenderer.thumbnail.thumbnails"),
|
|
),
|
|
}
|
|
|
|
}(n.Int(), s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|
|
|
|
func NavigationButton(s gjson.Result) []Item {
|
|
|
|
r := make([]Item, s.Get("#").Int())
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
s.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
j := v.Get("musicNavigationButtonRenderer")
|
|
|
|
color := j.Get("solid.leftStripeColor").Uint() & 0xffffff
|
|
|
|
r[i] = Item{
|
|
Id: j.Get("clickCommand.browseEndpoint.params").String(),
|
|
Title: RunsText(j.Get("buttonText")),
|
|
Sub: fmt.Sprintf("#%06x", color),
|
|
}
|
|
}(n.Int(), s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|
|
|
|
func MultiSelectMenuItemRenderer(j, ref gjson.Result) []Item {
|
|
|
|
r := make([]Item, j.Get("#").Int())
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
j.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(i int64, v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
steg := v.Get("formItemEntityKey").String()
|
|
|
|
id := ref.Get(
|
|
"#(entityKey == " + steg + ")",
|
|
).Get("payload.musicFormBooleanChoice.opaqueToken")
|
|
|
|
r[i] = Item{
|
|
Id: id.String(),
|
|
Title: RunsText(v.Get("title")),
|
|
}
|
|
}(n.Int(), s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|
|
|
|
func ShelfRenderer(j gjson.Result) map[string]interface{} {
|
|
|
|
r := make(map[string]interface{})
|
|
|
|
wg := sync.WaitGroup{}
|
|
|
|
j.ForEach(
|
|
func(n, s gjson.Result) bool {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(v gjson.Result) {
|
|
defer wg.Done()
|
|
|
|
title := RunsText(
|
|
v.Get("header.musicCarouselShelfBasicHeaderRenderer.title"),
|
|
)
|
|
|
|
r[title] = TwoRowItemRenderer(v.Get("contents"), false)
|
|
}(s)
|
|
|
|
return true
|
|
},
|
|
)
|
|
|
|
wg.Wait()
|
|
|
|
return r
|
|
}
|