Skip to content

Commit

Permalink
Pass visitorData to requests
Browse files Browse the repository at this point in the history
This is a nearly verbatim copy of [1], for now the code is pretty rough and
I'm not even sure that this data should be passed for all requests but it
does seem to unblock the iOS client for now.

[1] TeamNewPipe/NewPipeExtractor#1262
  • Loading branch information
jdesgats committed Jan 21, 2025
1 parent 51b72ca commit daf3b49
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
33 changes: 33 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"sync/atomic"
"time"
)

const (
Expand All @@ -23,6 +25,8 @@ const (
playerParams = "CgIQBg=="
)

const CONTENT_PLAYBACK_NONCE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"

var ErrNoFormat = errors.New("no video format provided")

// DefaultClient type to use. No reason to change but you could if you wanted to.
Expand Down Expand Up @@ -157,6 +161,7 @@ type innertubeClient struct {
TimeZone string `json:"timeZone"`
UTCOffset int `json:"utcOffsetMinutes"`
DeviceModel string `json:"deviceModel,omitempty"`
VisitorData string `json:"visitorData,omitempty"`
}

// client info for the innertube API
Expand Down Expand Up @@ -232,6 +237,33 @@ func (c *Client) transcriptDataByInnertube(ctx context.Context, id string, lang
return c.httpPostBodyBytes(ctx, "https://www.youtube.com/youtubei/v1/get_transcript?key="+c.client.key, data)
}

func randString(alphabet string, sz int) string {
var buf strings.Builder
buf.Grow(sz)
for i := 0; i < sz; i++ {
buf.WriteByte(alphabet[rand.Intn(len(alphabet))])
}
return buf.String()
}

func randomVisitorData(countryCode string) string {
var pbE2 ProtoBuilder

pbE2.String(2, "")
pbE2.Varint(4, int64(rand.Intn(255)+1))

var pbE ProtoBuilder
pbE.String(1, countryCode)
pbE.Bytes(2, pbE2.ToBytes())

var pb ProtoBuilder
pb.String(1, randString(CONTENT_PLAYBACK_NONCE_ALPHABET, 11))
pb.Varint(5, time.Now().Unix()-int64(rand.Intn(600000)))
pb.Bytes(6, pbE.ToBytes())

return pb.ToUrlEncodedBase64()
}

func prepareInnertubeContext(clientInfo clientInfo) inntertubeContext {
return inntertubeContext{
Client: innertubeClient{
Expand All @@ -243,6 +275,7 @@ func prepareInnertubeContext(clientInfo clientInfo) inntertubeContext {
ClientVersion: clientInfo.version,
AndroidSDKVersion: clientInfo.androidVersion,
UserAgent: clientInfo.userAgent,
VisitorData: randomVisitorData("US"),
},
}
}
Expand Down
73 changes: 73 additions & 0 deletions protobuilder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package youtube

import (
"bytes"
"encoding/base64"
"net/url"
)

type ProtoBuilder struct {
byteBuffer bytes.Buffer
}

func (pb *ProtoBuilder) ToBytes() []byte {
return pb.byteBuffer.Bytes()
}

func (pb *ProtoBuilder) ToUrlEncodedBase64() string {
b64 := base64.URLEncoding.EncodeToString(pb.ToBytes())
return url.QueryEscape(b64)
}

func (pb *ProtoBuilder) writeVarint(val int64) error {
if val == 0 {
_, err := pb.byteBuffer.Write([]byte{0})
return err
}
for {
b := byte(val & 0x7F)
val >>= 7
if val != 0 {
b |= 0x80
}
_, err := pb.byteBuffer.Write([]byte{b})
if err != nil {
return err
}
if val == 0 {
break
}
}
return nil
}

func (pb *ProtoBuilder) field(field int, wireType byte) error {
val := int64(field<<3) | int64(wireType&0x07)
return pb.writeVarint(val)
}

func (pb *ProtoBuilder) Varint(field int, val int64) error {
err := pb.field(field, 0)
if err != nil {
return err
}
return pb.writeVarint(val)
}

func (pb *ProtoBuilder) String(field int, stringVal string) error {
strBts := []byte(stringVal)
return pb.Bytes(field, strBts)
}

func (pb *ProtoBuilder) Bytes(field int, bytesVal []byte) error {
if err := pb.field(field, 2); err != nil {
return err
}

if err := pb.writeVarint(int64(len(bytesVal))); err != nil {
return err
}

_, err := pb.byteBuffer.Write(bytesVal)
return err
}
18 changes: 18 additions & 0 deletions protobuilder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package youtube

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestProtoBuilder(t *testing.T) {
var pb ProtoBuilder

pb.Varint(1, 128)
pb.Varint(2, 1234567890)
pb.Varint(3, 1234567890123456789)
pb.String(4, "Hello")
pb.Bytes(5, []byte{1, 2, 3})
assert.Equal(t, "CIABENKF2MwEGJWCpu_HnoSRESIFSGVsbG8qAwECAw%3D%3D", pb.ToUrlEncodedBase64())
}

0 comments on commit daf3b49

Please sign in to comment.