Skip to content

Commit

Permalink
Change ClientType into clientInfo struct
Browse files Browse the repository at this point in the history
  • Loading branch information
corny committed Mar 12, 2022
1 parent 97303eb commit bc29310
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 54 deletions.
96 changes: 44 additions & 52 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (c *Client) GetVideoContext(ctx context.Context, url string) (*Video, error
}

func (c *Client) videoFromID(ctx context.Context, id string) (*Video, error) {
body, err := c.videoDataByInnertube(ctx, id, Web)
body, err := c.videoDataByInnertube(ctx, id, webClient)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -66,7 +66,7 @@ func (c *Client) videoFromID(ctx context.Context, id string) (*Video, error) {

// If the uploader marked the video as inappropriate for some ages, use embed player
if err == ErrLoginRequired {
bodyEmbed, errEmbed := c.videoDataByInnertube(ctx, id, EmbeddedClient)
bodyEmbed, errEmbed := c.videoDataByInnertube(ctx, id, embeddedClient)
if errEmbed == nil {
errEmbed = v.parseVideoInfo(bodyEmbed)
}
Expand Down Expand Up @@ -115,14 +115,29 @@ type innertubeClient struct {
ClientVersion string `json:"clientVersion"`
}

type ClientType string
// client info for the innertube API
type clientInfo struct {
name string
key string
version string
}

var (
// might add ANDROID and other in future, but i don't see reason yet
webClient = clientInfo{
name: "WEB",
version: "2.20210617.01.00",
key: "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
}

const (
Web ClientType = "WEB"
EmbeddedClient ClientType = "WEB_EMBEDDED_PLAYER"
embeddedClient = clientInfo{
name: "WEB_EMBEDDED_PLAYER",
version: "1.19700101",
key: "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8", // seems like same key works for both clients
}
)

func (c *Client) videoDataByInnertube(ctx context.Context, id string, clientType ClientType) ([]byte, error) {
func (c *Client) videoDataByInnertube(ctx context.Context, id string, clientInfo clientInfo) ([]byte, error) {
config, err := c.getPlayerConfig(ctx, id)
if err != nil {
return nil, err
Expand All @@ -134,63 +149,40 @@ func (c *Client) videoDataByInnertube(ctx context.Context, id string, clientType
return nil, err
}

data, keyToken := prepareInnertubeVideoData(id, sts, clientType)
return c.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/player?key="+keyToken, data)
}

var innertubeClientInfo = map[ClientType]map[string]string{
// might add ANDROID and other in future, but i don't see reason yet
Web: {
"version": "2.20210617.01.00",
"key": "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
},
EmbeddedClient: {
"version": "1.19700101",
// seems like same key works for both clients
"key": "AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
},
}
context := prepareInnertubeContext(clientInfo)

func prepareInnertubeContext(clientType ClientType) (inntertubeContext, string) {
cInfo, ok := innertubeClientInfo[clientType]
if !ok {
// if provided clientType not exist - use Web as fallback option
clientType = Web
cInfo = innertubeClientInfo[clientType]
data := innertubeRequest{
VideoID: id,
Context: context,
PlaybackContext: playbackContext{
ContentPlaybackContext: contentPlaybackContext{
SignatureTimestamp: sts,
},
},
}

return c.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/player?key="+clientInfo.key, data)
}

func prepareInnertubeContext(clientInfo clientInfo) inntertubeContext {
return inntertubeContext{
Client: innertubeClient{
HL: "en",
GL: "US",
ClientName: string(clientType),
ClientVersion: cInfo["version"],
ClientName: clientInfo.name,
ClientVersion: clientInfo.version,
},
}, cInfo["key"]
}

func prepareInnertubeVideoData(videoID string, sts string, clientType ClientType) (innertubeRequest, string) {
context, key := prepareInnertubeContext(clientType)

return innertubeRequest{
VideoID: videoID,
Context: context,
PlaybackContext: playbackContext{
ContentPlaybackContext: contentPlaybackContext{
SignatureTimestamp: sts,
},
},
}, key
}
}

func prepareInnertubePlaylistData(ID string, continuation bool, clientType ClientType) (innertubeRequest, string) {
context, key := prepareInnertubeContext(clientType)
func prepareInnertubePlaylistData(ID string, continuation bool, clientInfo clientInfo) innertubeRequest {
context := prepareInnertubeContext(clientInfo)

if continuation {
return innertubeRequest{Context: context, Continuation: ID}, key
return innertubeRequest{Context: context, Continuation: ID}
}

return innertubeRequest{Context: context, BrowseID: "VL" + ID}, key
return innertubeRequest{Context: context, BrowseID: "VL" + ID}
}

// GetPlaylist fetches playlist metadata
Expand All @@ -207,8 +199,8 @@ func (c *Client) GetPlaylistContext(ctx context.Context, url string) (*Playlist,
return nil, fmt.Errorf("extractPlaylistID failed: %w", err)
}

data, key := prepareInnertubePlaylistData(id, false, Web)
body, err := c.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/browse?key="+key, data)
data := prepareInnertubePlaylistData(id, false, webClient)
body, err := c.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/browse?key="+webClient.key, data)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ func (p *Playlist) parsePlaylistInfo(ctx context.Context, client *Client, body [
p.Videos = entries

for continuation != "" {
data, key := prepareInnertubePlaylistData(continuation, true, Web)
data := prepareInnertubePlaylistData(continuation, true, webClient)

body, err := client.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/browse?key="+key, data)
body, err := client.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/browse?key="+webClient.key, data)
if err != nil {
return err
}
Expand Down

0 comments on commit bc29310

Please sign in to comment.