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

✨feat(client): login with qrcode #9

Open
wants to merge 1 commit into
base: v0
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
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,35 @@ func main() {
}
```

或者可以使用扫码登录,此时无需手动指定cookie
```go
package main

import (
bg "github.com/iyear/biligo"
"fmt"
"time"
)

func main() {
b, err := bg.NewBiliClientScanQrcode(&bg.BiliSetting{
// DEBUG 模式将输出请求和响应
DebugMode: true,
// Client: myClient,
// UserAgent: "My UA",
})

if err != nil {
log.Fatal("failed to make new bili client; error: ", err)
return
}

fmt.Printf("mid: %d, uname: %s,userID: %s,rank: %s\n", b.Me.MID, b.Me.UName, b.Me.UserID, b.Me.Rank)
fmt.Printf("birthday: %s,sex: %s\n", b.Me.Birthday, b.Me.Sex)
fmt.Printf("sign: %s\n", b.Me.Sign)
}
```

### 例子

同目录下的 `example` 文件夹
Expand Down
30 changes: 30 additions & 0 deletions bili_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,36 @@ func NewBiliClient(setting *BiliSetting) (*BiliClient, error) {
return bili, nil
}

// NewBiliClientScanQrcode
//
// 通过扫描二维码获取Cookie无需手动设置Cookies
func NewBiliClientScanQrcode(setting *BiliSetting) (*BiliClient, error) {
cookies := util.GetCookie()
bili := &BiliClient{
auth: &CookieAuth{
DedeUserID: cookies.DedeUserID,
SESSDATA: cookies.SESSDATA,
BiliJCT: cookies.Bili_jct,
DedeUserIDCkMd5: cookies.DedeUserID__ckMd5,
},
baseClient: newBaseClient(&baseSetting{
Client: setting.Client,
DebugMode: setting.DebugMode,
UserAgent: setting.UserAgent,
Prefix: "BiliClient ",
}),
}

account, err := bili.GetMe()
if err != nil {
return nil, err
}

bili.Me = account

return bili, nil
}

// GetMe
//
// 获取个人基本信息
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.16
require (
github.com/golang/protobuf v1.5.2
github.com/pkg/errors v0.9.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tidwall/gjson v1.8.1
github.com/tidwall/pretty v1.2.0 // indirect
google.golang.org/protobuf v1.27.1
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU=
github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk=
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
Expand Down
162 changes: 162 additions & 0 deletions internal/util/login_by_qrcode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package util

import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"

qrcode "github.com/skip2/go-qrcode"
)

type Cookie struct {
SESSDATA string
Bili_jct string
DedeUserID string
DedeUserID__ckMd5 string
Sid string
}

type GetQrcodeResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Ttl int `json:"ttl"`
Data struct {
URL string `json:"url"`
QrcodeKey string `json:"qrcode_key"`
} `json:"data"`
}

type ScanResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Ttl int `json:"ttl"`
Data struct {
URL string `json:"url"`
RefreshToken string `json:"refresh_token"`
Timestamp int `json:"timestamp"`
Code int `json:"code"`
Message string `json:"message"`
} `json:"data"`
}

func getQrcode() *GetQrcodeResponse {
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Timeout: time.Second * 30,
}

req, err := http.NewRequest("GET", "https://passport.bilibili.com/x/passport-login/web/qrcode/generate", nil)
if err != nil {
panic(err)
}

req.Header = http.Header{
"Referer": []string{"https://passport.bilibili.com/login?from_spm_id=333.851.top_bar.login_window"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.51 Safari/537.36 Edg/93.0.961.27"},
}

// Send the GET request
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()

// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}

// Parse the JSON data
var getQrcodeResp *GetQrcodeResponse
if err := json.Unmarshal(body, &getQrcodeResp); err != nil {
panic(err)
}

qr, err := qrcode.New(getQrcodeResp.Data.URL, qrcode.Medium)
if err != nil {
fmt.Println("无法生成二维码:", err)
return nil
}

// 打印二维码到控制台
fmt.Println(qr.ToSmallString(false))

return getQrcodeResp
}

func getCookie(getQrcodeResp *GetQrcodeResponse) *Cookie {
// 等待扫码
fmt.Println("请在8秒内完成扫码...")
time.Sleep(time.Second * 8)
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
Timeout: time.Second * 30,
}

url := "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + getQrcodeResp.Data.QrcodeKey
req, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}

req.Header = http.Header{
"Referer": []string{"https://passport.bilibili.com/login?from_spm_id=333.851.top_bar.login_window"},
"User-Agent": []string{"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.51 Safari/537.36 Edg/93.0.961.27"},
}

// Send the GET request
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()

// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}

// 解析 JSON 数据
var scanResp *ScanResponse
if err := json.Unmarshal(body, &scanResp); err != nil {
panic(err)
}

if scanResp.Message != "0" {
fmt.Println("扫码失败")
}

cookies := resp.Cookies()
result := &Cookie{}
for _, cookie := range cookies {
switch cookie.Name {
case "SESSDATA":
result.SESSDATA = cookie.Value
case "bili_jct":
result.Bili_jct = cookie.Value
case "DedeUserID":
result.DedeUserID = cookie.Value
case "DedeUserID__ckMd5":
result.DedeUserID__ckMd5 = cookie.Value
case "sid":
result.Sid = cookie.Value
}
}
return result
}

func GetCookie() *Cookie {
resp := getQrcode()
cookies := getCookie(resp)
return cookies
}