Opt: fast get buvid

pull/31/head
zijiren233 3 years ago
parent c870d640de
commit 0e9f53bb40

@ -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
}

@ -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)

@ -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 {

Loading…
Cancel
Save