diff --git a/builder.go b/builder.go index daceaa7..4104b3a 100644 --- a/builder.go +++ b/builder.go @@ -1,11 +1,48 @@ package main import ( + "fmt" + "log" "sync" "github.com/tidwall/gjson" ) +func GetThumbnails(j gjson.Result) []Thumbnail { + + t := []Thumbnail{} + + wg := sync.WaitGroup{} + + j.ForEach( + func(_, v gjson.Result) bool { + + wg.Add(1) + + go func() { + defer wg.Done() + + u, err := ParseUrl(v.Get("url").String()) + if err != nil { + log.Fatal(err) + } + + t = append(t, Thumbnail{ + Url: u, + Width: v.Get("width").Int(), + Height: v.Get("height").Int(), + }) + }() + + wg.Wait() + + return true + }, + ) + + return t +} + func TwoRowItemRenderer(t string, a gjson.Result) []Item { r := []Item{} @@ -13,7 +50,9 @@ func TwoRowItemRenderer(t string, a gjson.Result) []Item { var id string if t == "album" || t == "singles" { - id = "menu.menuRenderer.items.#(menuNavigationItemRenderer.text.runs.0.text == Shuffle play).menuNavigationItemRenderer.navigationEndpoint.watchPlaylistEndpoint.playlistId" + id = "menu.menuRenderer.items.#(menuNavigationItemRenderer" + + ".text.runs.0.text == Shuffle play).menuNavigationItemRenderer" + + ".navigationEndpoint.watchPlaylistEndpoint.playlistId" } else { id = "navigationEndpoint.browseEndpoint.browseId" } @@ -30,11 +69,18 @@ func TwoRowItemRenderer(t string, a gjson.Result) []Item { go func() { defer wg.Done() + gid := j.Get(id).String() + + if len(gid) > 2 && gid[:2] == "VL" { + gid = gid[2:] + } + r = append(r, Item{ - Id: j.Get(id).String(), - Title: RunsText(j.Get("title")), - Sub: RunsText(j.Get("subtitle")), - Thumbnails: GetThumbnails(j.Get("thumbnailRenderer.musicThumbnailRenderer.thumbnail.thumbnails")), + Id: gid, + Title: RunsText(j.Get("title")), + Sub: RunsText(j.Get("subtitle")), + Thumbnails: GetThumbnails(j.Get("thumbnailRenderer" + + ".musicThumbnailRenderer.thumbnail.thumbnails")), }) }() @@ -48,25 +94,6 @@ func TwoRowItemRenderer(t string, a gjson.Result) []Item { return r } -func CarouselShelfRenderer(i gjson.Result) map[string]interface{} { - - shelf := make(map[string]interface{}) - - shelf["title"] = RunsText(i.Get("header.musicCarouselShelfBasicHeaderRenderer.title")) - - ct := i.Get("contents") - - if ct.Get("#(musicTwoRowItemRenderer)").Exists() { - shelf["contents"] = TwoRowItemRenderer("", ct) - } else if ct.Get("#(musicResponsiveListItemRenderer)").Exists() { - shelf["contents"] = ResponsiveListItemRenderer(ct) - } - - shelf["raw"] = ct.Value() - - return shelf -} - func ResponsiveListItemRenderer(s gjson.Result) []Item { r := []Item{} @@ -82,14 +109,19 @@ func ResponsiveListItemRenderer(s gjson.Result) []Item { defer wg.Done() j := v.Get("musicResponsiveListItemRenderer") - flex := j.Get("flexColumns.#.musicResponsiveListItemFlexColumnRenderer.text.runs.0") + flex := j.Get("flexColumns.#.musicResponsiveListItemFlexColumnRenderer" + + ".text.runs.0") r = append(r, Item{ - Id: j.Get("playlistItemData.videoId").String(), - Title: flex.Get("#(navigationEndpoint.watchEndpoint.videoId).text").String(), - SubId: flex.Get("#.navigationEndpoint.browseEndpoint").Get("#(browseId).browseId").String(), - Sub: flex.Get("#(navigationEndpoint.browseEndpoint.browseId).text").String(), - Thumbnails: GetThumbnails(j.Get("thumbnail.musicThumbnailRenderer.thumbnail.thumbnails")), + Id: j.Get("playlistItemData.videoId").String(), + Title: flex.Get("#(navigationEndpoint.watchEndpoint" + + ".videoId).text").String(), + SubId: flex.Get("#.navigationEndpoint.browseEndpoint" + + ".#(browseId).browseId").String(), + Sub: flex.Get("#(navigationEndpoint.browseEndpoint" + + ".browseId).text").String(), + Thumbnails: GetThumbnails(j.Get("thumbnail.musicThumbnailRenderer" + + ".thumbnail.thumbnails")), }) }() @@ -102,3 +134,37 @@ func ResponsiveListItemRenderer(s gjson.Result) []Item { return r } + +func NavigationButton(s gjson.Result) []Item { + + r := []Item{} + + wg := sync.WaitGroup{} + + s.ForEach( + func(_, v gjson.Result) bool { + + wg.Add(1) + + go func() { + defer wg.Done() + + j := v.Get("musicNavigationButtonRenderer") + + color := j.Get("solid.leftStripeColor").Uint() & 0xffffff + + r = append(r, Item{ + Id: j.Get("clickCommand.browseEndpoint.params").String(), + Title: RunsText(j.Get("buttonText")), + Sub: fmt.Sprintf("#%06x", color), + }) + }() + + wg.Wait() + + return true + }, + ) + + return r +} diff --git a/fetch.go b/fetch.go index 7c6e7b0..ada8c4b 100644 --- a/fetch.go +++ b/fetch.go @@ -11,19 +11,9 @@ import ( "github.com/tidwall/gjson" ) -func Fetch(path string, data []byte, c string) (string, int, error) { +func Fetch(path string, data []byte) (string, int, error) { - var query string - - if c != "" { - query = "&ctoken=" + c + "&continuation=" + c + "&type=next" - } else { - query = "" - } - - url := "https://music.youtube.com/youtubei/v1/" + path + "?key=AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30" + query + "&prettyPrint=false" - - log.Println(url) + url := "https://music.youtube.com/youtubei/v1/" + path + "?key=AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30&prettyPrint=false" req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) if err != nil { @@ -54,14 +44,14 @@ func Fetch(path string, data []byte, c string) (string, int, error) { return string(body), resp.StatusCode, nil } -func FetchBrowse(id string, c string, browse BrowseData) (string, int) { +func FetchBrowse(id string, browse BrowseData) (string, int) { data, err := json.Marshal(browse) if err != nil { return ErrorMessage(err), 500 } - raw, status, err := Fetch("browse", data, c) + raw, status, err := Fetch("browse", data) if err != nil { return ErrorMessage(err), 500 } @@ -70,39 +60,13 @@ func FetchBrowse(id string, c string, browse BrowseData) (string, int) { } -func FetchHome(c string) (string, int) { - - /* WIP */ - - id := "FEmusic_home" - - if c != "" { - id = "" - } - - log.Println(id) - - context := GetTypeBrowse("home", id) - - raw, status := FetchBrowse(id, c, context) - - /*res, err := ParseHome(raw) - if err != nil { - return ErrorMessage(err), 500 - }*/ - - return raw, status -} - func FetchExplore() (string, int) { id := "FEmusic_explore" - log.Println(id) + context := GetTypeBrowse("", id, "") - context := GetTypeBrowse("", id) - - raw, status := FetchBrowse(id, "", context) + raw, status := FetchBrowse(id, context) res, err := ParseExplore(raw) if err != nil { @@ -112,26 +76,43 @@ func FetchExplore() (string, int) { return res, status } -func FetchMoods() (string, int) { - - /* WIP */ +func FetchGenres() (string, int) { id := "FEmusic_moods_and_genres" - log.Println(id) + context := GetTypeBrowse("", id, "") - context := GetTypeBrowse("", id) + raw, status := FetchBrowse(id, context) - raw, status := FetchBrowse(id, "", context) + res, err := ParseGenres(raw) + if err != nil { + return ErrorMessage(err), 500 + } - return raw, status + return res, status +} + +func FetchGenre(param string) (string, int) { + + id := "FEmusic_moods_and_genres_category" + + context := GetTypeBrowse("", id, param) + + raw, status := FetchBrowse(id, context) + + res, err := ParseGenre(raw) + if err != nil { + return ErrorMessage(err), 500 + } + + return res, status } func FetchArtist(id string) (string, int) { - context := GetTypeBrowse("artist", id) + context := GetTypeBrowse("artist", id, "") - raw, status := FetchBrowse(id, "", context) + raw, status := FetchBrowse(id, context) res, err := ParseArtist(raw) if err != nil { @@ -143,9 +124,9 @@ func FetchArtist(id string) (string, int) { func FetchLyrics(id string) (string, int) { - context := GetTypeBrowse("lyrics", id) + context := GetTypeBrowse("lyrics", id, "") - raw, status := FetchBrowse(id, "", context) + raw, status := FetchBrowse(id, context) res, err := ParseLyrics(raw) if err != nil { @@ -155,20 +136,11 @@ func FetchLyrics(id string) (string, int) { return res, status } -func FetchPlaylist(id string) (string, int) { - - context := GetTypeBrowse("playlist", id) - - raw, status := FetchBrowse(id, "", context) - - return raw, status -} - func FetchAlbum(id string) (string, int) { - context := GetTypeBrowse("album", id) + context := GetTypeBrowse("album", id, "") - raw, status := FetchBrowse(id, "", context) + raw, status := FetchBrowse(id, context) url := gjson.Parse(raw).Get("microformat.microformatDataRenderer.urlCanonical").String() @@ -186,7 +158,7 @@ func FetchNext(id string) (string, int) { return ErrorMessage(err), 500 } - raw, status, err := Fetch("next", data, "") + raw, status, err := Fetch("next", data) if err != nil { return ErrorMessage(err), 500 } diff --git a/main.go b/main.go index 66be1d5..675b9cb 100644 --- a/main.go +++ b/main.go @@ -24,14 +24,6 @@ func HandleHealth(c *fiber.Ctx) error { return c.SendStatus(204) } -func HandleHome(c *fiber.Ctx) error { - defer calc(c.OriginalURL())() - - res, status := FetchHome(c.Params("id")) - - return c.Status(status).SendString(res) -} - func HandleExplore(c *fiber.Ctx) error { defer calc(c.OriginalURL())() @@ -48,11 +40,31 @@ func HandleNext(c *fiber.Ctx) error { return c.Status(status).SendString(res) } +func HandleGenres(c *fiber.Ctx) error { + defer calc(c.OriginalURL())() + + res, status := FetchGenres() + + return c.Status(status).SendString(res) +} + +func HandleGenre(c *fiber.Ctx) error { + defer calc(c.OriginalURL())() + + res, status := FetchGenre(c.Params("id")) + + return c.Status(status).SendString(res) +} + func HandleBrowse(c *fiber.Ctx) error { defer calc(c.OriginalURL())() id := c.Params("id") + if len(id) < 4 { + return c.Status(500).SendString("{\"error\": \"Browse Id is too Short\"}") + } + switch { case id[:2] == "UC": res, status := FetchArtist(id) @@ -63,11 +75,8 @@ func HandleBrowse(c *fiber.Ctx) error { case id[:4] == "MPRE": res, status := FetchAlbum(id) return c.Status(status).SendString(res) - case id[:4] == "VLRD" || id[:2] == "RD": - res, status := FetchPlaylist(id) - return c.Status(status).SendString(res) default: - return c.SendString("{\"error\": \"Invalid Browse URL\"}") + return c.Status(500).SendString("{\"error\": \"Invalid Browse URL\"}") } } @@ -86,9 +95,9 @@ func main() { app.Use(recover.New()) app.Get("/healthz", HandleHealth) - app.Get("/home", HandleHome) - app.Get("/home/:id", HandleHome) app.Get("/explore", HandleExplore) + app.Get("/genres", HandleGenres) + app.Get("/genres/:id", HandleGenre) app.Get("/next/:id", HandleNext) app.Get("/browse/:id", HandleBrowse) app.Get("/channel/:id", HandleArtist) diff --git a/parser.go b/parser.go index aaabf40..a7ac537 100644 --- a/parser.go +++ b/parser.go @@ -2,61 +2,11 @@ package main import ( "encoding/json" - "log" - "strings" "sync" "github.com/tidwall/gjson" ) -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 GetThumbnails(j gjson.Result) []Thumbnail { - - t := []Thumbnail{} - - wg := sync.WaitGroup{} - - j.ForEach( - func(_, v gjson.Result) bool { - - wg.Add(1) - - go func() { - defer wg.Done() - - u, err := ParseUrl(v.Get("url").String()) - if err != nil { - log.Fatal(err) - } - - t = append(t, Thumbnail{ - Url: u, - Width: v.Get("width").Int(), - Height: v.Get("height").Int(), - }) - }() - - wg.Wait() - - return true - }, - ) - - return t -} - func GetNextSongs(n gjson.Result) []Item { r := []Item{} @@ -88,47 +38,24 @@ func GetNextSongs(n gjson.Result) []Item { return r } -func ParseHome(raw string) (string, error) { +func ParseExplore(raw string) (string, error) { j := gjson.Parse(raw) - c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer.content.sectionListRenderer") + c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer.content" + + ".tabRenderer.content.sectionListRenderer.contents.#.musicCarouselShelfRenderer") - m := c.Get("contents") - n := c.Get("continuations.0.nextContinuationData.continuation").String() + a := c.Get("#(header.musicCarouselShelfBasicHeaderRenderer" + + ".title.runs.0.text == New albums & singles)") + t := c.Get("#(header.musicCarouselShelfBasicHeaderRenderer" + + ".title.runs.0.text == Trending)") - var body []map[string]interface{} - - m.ForEach( - func(key, value gjson.Result) bool { - - var v map[string]interface{} - - icsr := value.Get("musicImmersiveCarouselShelfRenderer") - csr := value.Get("musicCarouselShelfRenderer") - - switch { - case icsr.Exists(): - v = CarouselShelfRenderer(icsr) - case csr.Exists(): - v = CarouselShelfRenderer(csr) - default: - v = make(map[string]interface{}) - v["raw"] = value.Value() - } - - body = append(body, v) - - return true - }, - ) - - data := Home{ - Contents: body, - Continue: n, + val := Explore{ + Albums: TwoRowItemRenderer("album", a.Get("contents")), + Trending: ResponsiveListItemRenderer(t.Get("contents")), } - res, err := json.Marshal(data) + res, err := json.Marshal(val) if err != nil { return "", err } @@ -136,18 +63,45 @@ func ParseHome(raw string) (string, error) { return string(res), nil } -func ParseExplore(raw string) (string, error) { +func ParseGenres(raw string) (string, error) { j := gjson.Parse(raw) - c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer.content.sectionListRenderer.contents") + c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer" + + ".content.sectionListRenderer.contents.#.gridRenderer") - a := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs.0.text == New albums & singles).musicCarouselShelfRenderer") - t := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs.0.text == Trending).musicCarouselShelfRenderer") + m := c.Get("#(header.gridHeaderRenderer.title.runs.0.text == Moods & moments)") + g := c.Get("#(header.gridHeaderRenderer.title.runs.0.text == Genres)") - val := Explore{ - Albums: TwoRowItemRenderer("album", a.Get("contents")), - Trending: ResponsiveListItemRenderer(t.Get("contents")), + val := Genres{ + Moods: NavigationButton(m.Get("items")), + Genres: NavigationButton(g.Get("items")), + } + + res, err := json.Marshal(val) + if err != nil { + return "", err + } + + return string(res), nil +} + +func ParseGenre(raw string) (string, error) { + + j := gjson.Parse(raw) + + c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer" + + ".content.sectionListRenderer.contents.#.gridRenderer") + + s := c.Get("#(header.gridHeaderRenderer.title.runs.0.text == Spotlight)") + f := c.Get("#(header.gridHeaderRenderer.title.runs.0.text == Featured playlists)") + cp := c.Get("#(header.gridHeaderRenderer.title.runs.0.text == Community playlists)") + + val := Genre{ + Title: RunsText(j.Get("header.musicHeaderRenderer.title")), + Spotlight: TwoRowItemRenderer("", s.Get("items")), + Featured: TwoRowItemRenderer("", f.Get("items")), + Community: TwoRowItemRenderer("", cp.Get("items")), } res, err := json.Marshal(val) @@ -163,20 +117,29 @@ func ParseArtist(raw string) (string, error) { j := gjson.Parse(raw) h := j.Get("header.musicImmersiveHeaderRenderer") - c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer.content.sectionListRenderer.contents") + c := j.Get("contents.singleColumnBrowseResultsRenderer.tabs.0.tabRenderer.content" + + ".sectionListRenderer.contents") s := c.Get("#(musicShelfRenderer.title.runs.0.text == Songs).musicShelfRenderer") - a := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs.0.text == Albums).musicCarouselShelfRenderer") - m := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs.0.text == Singles).musicCarouselShelfRenderer") - u := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer.title.runs.0.text == Fans might also like).musicCarouselShelfRenderer") + a := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer" + + ".title.runs.0.text == Albums).musicCarouselShelfRenderer") + m := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer" + + ".title.runs.0.text == Singles).musicCarouselShelfRenderer") + u := c.Get("#(musicCarouselShelfRenderer.header.musicCarouselShelfBasicHeaderRenderer" + + ".title.runs.0.text == Fans might also like).musicCarouselShelfRenderer") val := Artist{ - Title: RunsText(h.Get("title")), - Description: RunsText(h.Get("description")), - SubscriberCount: RunsText(h.Get("subscriptionButton.subscribeButtonRenderer.subscriberCountText")), - Thumbnails: GetThumbnails(h.Get("thumbnail.musicThumbnailRenderer.thumbnail.thumbnails")), - BrowsePlaylistId: h.Get("playButton.buttonRenderer.navigationEndpoint.watchEndpoint.playlistId").String(), - PlaylistId: s.Get("contents.0.musicResponsiveListItemRenderer.flexColumns.0.musicResponsiveListItemFlexColumnRenderer.text.runs.0.navigationEndpoint.watchEndpoint.playlistId").String(), + Title: RunsText(h.Get("title")), + Description: RunsText(h.Get("description")), + SubscriberCount: RunsText(h.Get("subscriptionButton" + + ".subscribeButtonRenderer.subscriberCountText")), + Thumbnails: GetThumbnails(h.Get("thumbnail.musicThumbnailRenderer" + + ".thumbnail.thumbnails")), + BrowsePlaylistId: h.Get("playButton.buttonRenderer.navigationEndpoint" + + ".watchEndpoint.playlistId").String(), + PlaylistId: s.Get("contents.0.musicResponsiveListItemRenderer" + + ".flexColumns.0.musicResponsiveListItemFlexColumnRenderer.text" + + ".runs.0.navigationEndpoint.watchEndpoint.playlistId").String(), Items: Items{ Songs: ResponsiveListItemRenderer(s.Get("contents")), Albums: TwoRowItemRenderer("album", a.Get("contents")), @@ -219,11 +182,15 @@ func ParseNext(raw string) (string, error) { j := gjson.Parse(raw) - c := j.Get("contents.singleColumnMusicWatchNextResultsRenderer.tabbedRenderer.watchNextTabbedResultsRenderer.tabs") - m := j.Get("playerOverlays.playerOverlayRenderer.browserMediaSession.browserMediaSessionRenderer") + c := j.Get("contents.singleColumnMusicWatchNextResultsRenderer." + + "tabbedRenderer.watchNextTabbedResultsRenderer.tabs") + m := j.Get("playerOverlays.playerOverlayRenderer.browserMediaSession" + + ".browserMediaSessionRenderer") - n := c.Get("#(tabRenderer.title == Up next).tabRenderer.content.musicQueueRenderer.content.playlistPanelRenderer") - l := c.Get("#(tabRenderer.title == Lyrics).tabRenderer.endpoint.browseEndpoint.browseId") + n := c.Get("#(tabRenderer.title == Up next).tabRenderer.content" + + ".musicQueueRenderer.content.playlistPanelRenderer") + l := c.Get("#(tabRenderer.title == Lyrics).tabRenderer.endpoint" + + ".browseEndpoint.browseId") val := Next{ LyricsId: l.String(), diff --git a/structs.go b/structs.go index c882040..6482409 100644 --- a/structs.go +++ b/structs.go @@ -10,9 +10,9 @@ type Thumbnail struct { type Item struct { Id string `json:"id"` Title string `json:"title"` - Sub string `json:"subtitle"` - SubId string `json:"subId"` - Thumbnails []Thumbnail `json:"thumbnails"` + Sub string `json:"subtitle,omitempty"` + SubId string `json:"subId,omitempty"` + Thumbnails []Thumbnail `json:"thumbnails,omitempty"` } type Items struct { @@ -22,22 +22,29 @@ type Items struct { Artists []Item `json:"recommendedArtists"` } -type Home struct { - Contents []map[string]interface{} `json:"contents"` - Continue string `json:"continue"` -} - type Explore struct { Albums []Item `json:"albums_and_singles"` Trending []Item `json:"trending"` } +type Genres struct { + Moods []Item `json:"moods"` + Genres []Item `json:"genres"` +} + +type Genre struct { + Title string `json:"title"` + Spotlight []Item `json:"spotlight"` + Featured []Item `json:"featured"` + Community []Item `json:"community"` +} + type Artist struct { Title string `json:"title"` - Description string `json:"description"` - BrowsePlaylistId string `json:"browsePlaylistId"` - PlaylistId string `json:"playlistId"` - SubscriberCount string `json:"subscriberCount"` + Description string `json:"description,omitempty"` + BrowsePlaylistId string `json:"browsePlaylistId,omitempty"` + PlaylistId string `json:"playlistId,omitempty"` + SubscriberCount string `json:"subscriberCount,omitempty"` Thumbnails []Thumbnail `json:"thumbnails"` Items Items `json:"items"` } @@ -60,38 +67,39 @@ type Lyrics struct { /* Structs and Types */ type Client struct { - Name string `json:"clientName"` - Version string `json:"clientVersion"` + Name string `json:"clientName,omitempty"` + Version string `json:"clientVersion,omitempty"` } type Context struct { - Client Client `json:"client"` + Client Client `json:"client",omitempty` } type PageType struct { - PageType string `json:"pageType"` + PageType string `json:"pageType",omitempty` } type BrowseMusicConfig struct { - MusicConfig PageType `json:"browseEndpointContextMusicConfig"` + MusicConfig PageType `json:"browseEndpointContextMusicConfig,omitempty"` } type WatchMusicConfig struct { - Panel bool `json:"hasPersistentPlaylistPanel"` - Type string `json:"musicVideoType"` + Panel bool `json:"hasPersistentPlaylistPanel,omitempty"` + Type string `json:"musicVideoType,omitempty"` } type BrowseData struct { - Context Context `json:"context"` - MusicConfig BrowseMusicConfig `json:"browseEndpointContextMusicConfig"` - BrowseId string `json:"browseId"` + Context Context `json:"context,omitempty"` + MusicConfig BrowseMusicConfig `json:"browseEndpointContextMusicConfig,omitempty"` + BrowseId string `json:"browseId,omitempty"` + Params string `json:"params,omitempty"` } type NextData struct { - Id string `json:"videoId"` - Context Context `json:"context"` - Audio bool `json:"isAudioOnly"` - Tuner string `json:"tunerSettingValue"` - Panel bool `json:"enablePersistentPlaylistPanel"` - MusicConfig WatchMusicConfig `json:"watchEndpointMusicConfig"` + Id string `json:"videoId,omitempty"` + Context Context `json:"context,omitempty"` + Audio bool `json:"isAudioOnly,omitempty"` + Tuner string `json:"tunerSettingValue,omitempty"` + Panel bool `json:"enablePersistentPlaylistPanel,omitempty"` + MusicConfig WatchMusicConfig `json:"watchEndpointMusicConfig,omitempty"` } diff --git a/types.go b/types.go index 585e8ba..416092c 100644 --- a/types.go +++ b/types.go @@ -9,7 +9,7 @@ var BaseContext = Context{ }, } -func GetTypeBrowse(t, id string) BrowseData { +func GetTypeBrowse(t, id string, params string) BrowseData { if t != "" { return BrowseData{ @@ -25,6 +25,7 @@ func GetTypeBrowse(t, id string) BrowseData { return BrowseData{ Context: BaseContext, BrowseId: id, + Params: params, } } diff --git a/utils.go b/utils.go index cfbc365..7764f50 100644 --- a/utils.go +++ b/utils.go @@ -2,10 +2,25 @@ package main import ( "fmt" + "github.com/tidwall/gjson" "net/url" + "strings" "time" ) +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) @@ -24,7 +39,9 @@ func ParseUrl(raw string) (string, error) { } func ErrorMessage(err error) string { - return fmt.Sprintf("{\"error\": \"%s\", \"message\": \"Please Report this error\"}", err) + data := url.QueryEscape(err.Error()) + fmt.Println(err) + return fmt.Sprintf("{\"error\":\"%s\",\"message\":\"Got Error: %s\"}", data) } func calc(url string) func() {