From 0e9f53bb409ed75f27b1de4982f2fbd3abb41ba8 Mon Sep 17 00:00:00 2001 From: zijiren233 Date: Wed, 1 Nov 2023 17:30:58 +0800 Subject: [PATCH] Opt: fast get buvid --- vendors/bilibili/buvid.go | 87 ++++++++++++++++++++++++++++++++++++++ vendors/bilibili/client.go | 40 ++++-------------- vendors/bilibili/login.go | 6 ++- 3 files changed, 99 insertions(+), 34 deletions(-) create mode 100644 vendors/bilibili/buvid.go diff --git a/vendors/bilibili/buvid.go b/vendors/bilibili/buvid.go new file mode 100644 index 0000000..5ccdf52 --- /dev/null +++ b/vendors/bilibili/buvid.go @@ -0,0 +1,87 @@ +package bilibili + +import ( + "errors" + "net/http" + "sync" + "time" + + json "github.com/json-iterator/go" + "github.com/synctv-org/synctv/utils" +) + +var ( + bLock sync.RWMutex + b3, b4 string + bLastUpdateTime time.Time +) + +func getBuvidCookies() ([]*http.Cookie, error) { + b3, b4, err := getBuvid() + if err != nil { + return nil, err + } + return []*http.Cookie{ + { + Name: "buvid3", + Value: b3, + }, + { + Name: "buvid4", + Value: b4, + }, + }, nil +} + +func getBuvid() (string, string, error) { + bLock.RLock() + if time.Since(bLastUpdateTime) < time.Hour { + bLock.RUnlock() + return b3, b4, nil + } + bLock.RUnlock() + bLock.Lock() + defer bLock.Unlock() + if time.Since(bLastUpdateTime) < time.Hour { + return b3, b4, nil + } + var err error + b3, b4, err = newBuvid() + if err != nil { + return "", "", err + } + bLastUpdateTime = time.Now() + return b3, b4, nil +} + +type buvid struct { + Code int `json:"code"` + Data struct { + B3 string `json:"b_3"` + B4 string `json:"b_4"` + } `json:"data"` + Message string `json:"message"` +} + +func newBuvid() (string, string, error) { + r, err := http.NewRequest(http.MethodGet, "https://api.bilibili.com/x/frontend/finger/spi", nil) + if err != nil { + return "", "", err + } + r.Header.Set("User-Agent", utils.UA) + r.Header.Set("Referer", "https://www.bilibili.com") + resp, err := http.DefaultClient.Do(r) + if err != nil { + return "", "", err + } + defer resp.Body.Close() + var b buvid + err = json.NewDecoder(resp.Body).Decode(&b) + if err != nil { + return "", "", err + } + if b.Code != 0 { + return "", "", errors.New(b.Message) + } + return b.Data.B3, b.Data.B4, nil +} diff --git a/vendors/bilibili/client.go b/vendors/bilibili/client.go index 563b950..61f7687 100644 --- a/vendors/bilibili/client.go +++ b/vendors/bilibili/client.go @@ -2,10 +2,8 @@ package bilibili import ( "context" - "errors" "io" "net/http" - "sync" "github.com/synctv-org/synctv/utils" ) @@ -13,8 +11,7 @@ import ( type Client struct { httpClient *http.Client cookies []*http.Cookie - buvid3 *http.Cookie - once sync.Once + buvid []*http.Cookie ctx context.Context } @@ -33,10 +30,15 @@ func WithContext(ctx context.Context) ClientConfig { } func NewClient(cookies []*http.Cookie, conf ...ClientConfig) (*Client, error) { + b, err := getBuvidCookies() + if err != nil { + return nil, err + } cli := &Client{ httpClient: http.DefaultClient, cookies: cookies, ctx: context.Background(), + buvid: b, } for _, v := range conf { v(cli) @@ -44,32 +46,6 @@ func NewClient(cookies []*http.Cookie, conf ...ClientConfig) (*Client, error) { return cli, nil } -func (c *Client) InitBuvid3() (err error) { - c.once.Do(func() { - c.buvid3, err = newBuvid3(c.ctx) - }) - return -} - -func newBuvid3(ctx context.Context) (*http.Cookie, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://www.bilibili.com/", nil) - if err != nil { - return nil, err - } - req.Header.Set("User-Agent", utils.UA) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - for _, c := range resp.Cookies() { - if c.Name == "buvid3" { - return c, nil - } - } - return nil, errors.New("no buvid3 cookie") -} - func (c *Client) SetCookies(cookies []*http.Cookie) { c.cookies = cookies } @@ -107,8 +83,8 @@ func (c *Client) NewRequest(method, url string, body io.Reader, conf ...RequestO if err != nil { return nil, err } - if c.buvid3 != nil { - req.AddCookie(c.buvid3) + for _, cookie := range c.buvid { + req.AddCookie(cookie) } for _, cookie := range c.cookies { req.AddCookie(cookie) diff --git a/vendors/bilibili/login.go b/vendors/bilibili/login.go index b663bcf..748291e 100644 --- a/vendors/bilibili/login.go +++ b/vendors/bilibili/login.go @@ -116,7 +116,7 @@ type sms struct { } func NewSMS(ctx context.Context, tel, token, challenge, validate string) (captchaKey string, err error) { - buvid3, err := newBuvid3(ctx) + b, err := getBuvidCookies() if err != nil { return "", err } @@ -136,7 +136,9 @@ func NewSMS(ctx context.Context, tel, token, challenge, validate string) (captch req.Header.Set("Referer", "https://passport.bilibili.com/login") req.Header.Set("User-Agent", utils.UA) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.AddCookie(buvid3) + for _, c := range b { + req.AddCookie(c) + } resp, err := http.DefaultClient.Do(req) if err != nil {