Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass visitorData to requests #355

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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())
}