Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
15619 committed May 24, 2022
0 parents commit 0d2ea6b
Show file tree
Hide file tree
Showing 9 changed files with 649 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
__pycache__
# *.go
*.json
test.py
go.mod
go.sum
77 changes: 77 additions & 0 deletions README.md
@@ -0,0 +1,77 @@
<p align="center">
<img src="https://s1.ax1x.com/2022/05/24/XPx1tx.png" width="200" height="200" alt="">
</p>
<div align="center">
<h1> 新 B 站粉丝牌助手
</h1>
<p>当前版本:0.1.0</p>
</div>

**TODO**

- [x] 每日直播区签到
- [x] 每日点赞3次直播间 (200*3 亲密度)
- [x] 每日分享5次直播间 (100*5 亲密度)
- [x] 每日弹幕打卡 (100 亲密度)
- [x] 多账号支持
- [ ] 每日观看30分钟
- [ ] 微信推送通知

<small>ps: 新版B站粉丝牌的亲密度每一个牌子都将单独计算 </small>

---

### 使用说明

##### 环境需求:Python 版本大于 3.8

> 克隆本项目 安装依赖
```shell
git clone https://github.com/XiaoMiku01/fansMedalHelper.git
cd fansMedalHelper
pip install -r requirements.txt
```

> 获取B站账号的 access_key
...

> 填写配置文件 users.yaml
```shell
vim users.yaml
```

```yaml
USERS:
- access_key: XXXXXX # 注意冒号后的空格 否则会读取失败
shared_uid: 123,456 # 需要分享房间的房主UID!不是房间号! 多个用逗号分隔,最多28个

- access_key:
shared_uid:
# 多用户以上格式添加
```

> 运行主程序
```shell
python main.py
```

> 效果图
[![XiifQP.md.png](https://s1.ax1x.com/2022/05/24/XiifQP.md.png)](https://imgtu.com/i/XiifQP)

---

### 注意事项

- 本脚本暂时没有集成定时模块 还需要用户定时运行
- 由于B站分享接口并不是每次分享都会加亲密度,它会有10分钟的CD,所以设置一个拿满500需要40分钟,以此类推,但是得益于Python3的异步机制,多个账号将并发完成任务,例如:A账号设置了2个房间的分享任务,B账号设置了1个,所需时间为90分钟。所以一天24小时最多可以拿满28个房间的分享亲密度

---

### 赞助

![](http://i0.hdslb.com/bfs/album/c267037c9513b8e44bc6ec95dbf772ff0439dce6.jpg)
174 changes: 174 additions & 0 deletions login.go
@@ -0,0 +1,174 @@
package main

import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
"time"

qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go"
gjson "github.com/tidwall/gjson"
)

var AccessKey string

var Csrf string

var Cookies []*http.Cookie

func Login() {
filename := "login_info.json"
data, err := ioutil.ReadFile(filename)
if err != nil || len(data) == 0 {
fmt.Println("未登录,请扫码登录")
loginBili()
} else {
AccessKey = gjson.Parse(string(data)).Get("data.access_token").String()
for _, c := range gjson.Parse(string(data)).Get("data.cookie_info.cookies").Array() {
Cookies = append(Cookies, &http.Cookie{
Name: c.Get("name").String(),
Value: c.Get("value").String(),
})
if c.Get("name").String() == "bili_jct" {
Csrf = c.Get("value").String()
}
}
l, name := is_login()
if l {
fmt.Println("登录成功:", name)
} else {
fmt.Println("登录失败,请重新扫码登录")
loginBili()
}
}

}

func is_login() (bool, string) {
api := "https://api.bilibili.com/x/web-interface/nav"
client := http.Client{}
req, _ := http.NewRequest("GET", api, nil)
for _, c := range Cookies {
req.AddCookie(c)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
data := gjson.ParseBytes(body)
return data.Get("code").Int() == 0, data.Get("data.uname").String()
}

func get_tv_qrcode_url_and_auth_code() (string, string) {
api := "http://passport.bilibili.com/x/passport-tv-login/qrcode/auth_code"
data := make(map[string]string)
data["local_id"] = "0"
data["ts"] = fmt.Sprintf("%d", time.Now().Unix())
signature(&data)
data_string := strings.NewReader(map_to_string(data))
client := http.Client{}
req, _ := http.NewRequest("POST", api, data_string)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
code := gjson.Parse(string(body)).Get("code").Int()
if code == 0 {
qrcode_url := gjson.Parse(string(body)).Get("data.url").String()
auth_code := gjson.Parse(string(body)).Get("data.auth_code").String()
return qrcode_url, auth_code
} else {
panic("get_tv_qrcode_url_and_auth_code error")
}
}

func verify_login(auth_code string) {
api := "http://passport.bilibili.com/x/passport-tv-login/qrcode/poll"
data := make(map[string]string)
data["auth_code"] = auth_code
data["local_id"] = "0"
data["ts"] = fmt.Sprintf("%d", time.Now().Unix())
signature(&data)
data_string := strings.NewReader(map_to_string(data))
client := http.Client{}
req, _ := http.NewRequest("POST", api, data_string)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
for {
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
code := gjson.Parse(string(body)).Get("code").Int()
AccessKey = gjson.Parse(string(body)).Get("data.access_token").String()
if code == 0 {
fmt.Println("登录成功")
fmt.Println("access_key:", string(AccessKey))
filename := "login_info.txt"
err := ioutil.WriteFile(filename, []byte(string(AccessKey)), 0644)
if err != nil {
panic(err)
}
fmt.Println("access_key已保存在", filename)
break
} else {
fmt.Println(string(body))
time.Sleep(time.Second * 3)
}
}
}

var appkey = "4409e2ce8ffd12b8"
var appsec = "59b43e04ad6965f34319062b478f83dd"

func signature(params *map[string]string) {
var keys []string
(*params)["appkey"] = appkey
for k := range *params {
keys = append(keys, k)
}
sort.Strings(keys)
var query string
for _, k := range keys {
query += k + "=" + url.QueryEscape((*params)[k]) + "&"
}
query = query[:len(query)-1] + appsec
hash := md5.New()
hash.Write([]byte(query))
(*params)["sign"] = hex.EncodeToString(hash.Sum(nil))
}

func map_to_string(params map[string]string) string {
var query string
for k, v := range params {
query += k + "=" + v + "&"
}
query = query[:len(query)-1]
return query
}

func loginBili() {
fmt.Println("请最大化窗口,以确保二维码完整显示,回车继续")
fmt.Scanf("%s", "")
login_url, auth_code := get_tv_qrcode_url_and_auth_code()
qrcode := qrcodeTerminal.New()
qrcode.Get([]byte(login_url)).Print()
fmt.Println("或将此链接复制到手机B站打开:", login_url)
verify_login(auth_code)
}

func main() {
loginBili()
fmt.Scanf("%s", "")
}
21 changes: 21 additions & 0 deletions main.py
@@ -0,0 +1,21 @@

import asyncio
import yaml
from src import BiliUser


async def main():
initTasks = []
startTasks = []
with open('users.yaml', 'r', encoding='utf-8') as f:
users = yaml.load(f, Loader=yaml.FullLoader)
for user in users['USERS']:
if user['access_key']:
biliUser = BiliUser(user['access_key'], user['shared_uid'])
initTasks.append(biliUser.init())
startTasks.append(biliUser.start())
await asyncio.gather(*initTasks)
await asyncio.gather(*startTasks)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
2 changes: 2 additions & 0 deletions requirements.txt
@@ -0,0 +1,2 @@
aiohttp >=3.7.4
loguru >= 0.5.3
2 changes: 2 additions & 0 deletions src/__init__.py
@@ -0,0 +1,2 @@
from .user import BiliUser
from .api import BiliApi

0 comments on commit 0d2ea6b

Please sign in to comment.