👍 添加查成分功能,修改bilibili插件的正则 (#171)

* 添加查成分功能

* 🚨修lint

* 🚨减少空格

* 🐛修改网址

* 🐛修改vup数量错误问题

* 🐛图片读取不了,就不读了

* 🐛 固定头像大小,bilibilipush调公有库

* 🎨 修改json转换

Co-authored-by: Guohuiyuan <haibaraguo@yeahka.com>
This commit is contained in:
himawari 2022-03-29 13:03:46 +08:00 committed by GitHub
parent 7be1a61347
commit 006ef6f672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 577 additions and 140 deletions

View File

@ -268,8 +268,11 @@ print("run[CQ:image,file="+j["img"]+"]")
- [x] 个人猜单词
- [x] 团队猜单词
- **bilibili** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/bilibili"`
- [x] >vup info [名字 | uid]
- [x] >user info [名字 | uid]
- [x] >vup info [xxx]
- [x] >user info [xxx]
- [x] 查成分 [xxx]
- [x] 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31
- [x] 更新vup
- **嘉然** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/diana"`
- [x] 小作文
- [x] 发大病
@ -371,12 +374,12 @@ print("run[CQ:image,file="+j["img"]+"]")
- api早上8点更新推荐定时在8点30后。配合插件`job`中的记录在"cron"触发的指令使用
- [x] /启用 zaobao
- [x] /禁用 zaobao
- **舔狗日记** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
- [x] 舔狗日记
```
记录在"00 9 * * *"触发的指令
今日早报
```
- **舔狗日记** `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/tiangou"`
- [x] 舔狗日记
- **TODO...**
## 使用方法

179
plugin/bilibili/api.go Normal file
View File

@ -0,0 +1,179 @@
package bilibili
import (
"encoding/json"
"errors"
"fmt"
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/web"
"github.com/tidwall/gjson"
"io"
"net/http"
)
var (
errNeedCookie = errors.New("该api需要设置b站cookie请发送命令设置cookie例如\"设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\"")
)
type searchResult struct {
Mid int64 `json:"mid"`
Uname string `json:"uname"`
Gender int64 `json:"gender"`
Usign string `json:"usign"`
Level int64 `json:"level"`
}
// 搜索api通过把触发指令传入的昵称找出uid返回
func search(keyword string) (r []searchResult, err error) {
searchURL := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&keyword=" + keyword
data, err := web.GetData(searchURL)
if err != nil {
return
}
j := gjson.ParseBytes(data)
if j.Get("data.numResults").Int() == 0 {
err = errors.New("查无此人")
return
}
err = json.Unmarshal(binary.StringToBytes(j.Get("data.result").Raw), &r)
if err != nil {
return
}
return
}
type follower struct {
Mid int `json:"mid"`
Uname string `json:"uname"`
Video int `json:"video"`
Roomid int `json:"roomid"`
Rise int `json:"rise"`
Follower int `json:"follower"`
GuardNum int `json:"guardNum"`
AreaRank int `json:"areaRank"`
}
// 请求api
func fansapi(uid string) (result follower, err error) {
fanURL := "https://api.vtbs.moe/v1/detail/" + uid
data, err := web.GetData(fanURL)
if err != nil {
return
}
if err = json.Unmarshal(data, &result); err != nil {
return
}
return
}
func followings(uid string) (s string, err error) {
followingURL := "https://api.bilibili.com/x/relation/same/followings?vmid=" + uid
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, followingURL, nil)
if err != nil {
return
}
c := vdb.getBilibiliCookie()
req.Header.Add("cookie", c.Value)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return
}
json := gjson.ParseBytes(body)
s = json.Get("data.list.#.uname").Raw
if json.Get("code").Int() == -101 {
err = errNeedCookie
return
}
if json.Get("code").Int() != 0 {
err = errors.New(json.Get("message").String())
return
}
return
}
type userinfo struct {
Name string `json:"name"`
Mid string `json:"mid"`
Face string `json:"face"`
Fans int64 `json:"fans"`
Attentions []int64 `json:"attentions"`
}
type medalInfo struct {
Mid int64 `json:"target_id"`
MedalName string `json:"medal_name"`
Level int64 `json:"level"`
MedalColorStart int64 `json:"medal_color_start"`
MedalColorEnd int64 `json:"medal_color_end"`
MedalColorBorder int64 `json:"medal_color_border"`
}
type medal struct {
Uname string `json:"target_name"`
medalInfo `json:"medal_info"`
}
type medalSlice []medal
func (m medalSlice) Len() int {
return len(m)
}
func (m medalSlice) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}
func (m medalSlice) Less(i, j int) bool {
return m[i].Level > m[j].Level
}
// 获取详情
func card(uid string) (result userinfo, err error) {
cardURL := "https://account.bilibili.com/api/member/getCardByMid?mid=" + uid
data, err := web.GetData(cardURL)
if err != nil {
return
}
err = json.Unmarshal(binary.StringToBytes(gjson.ParseBytes(data).Get("card").Raw), &result)
if err != nil {
return
}
return
}
// 获得牌子
func medalwall(uid string) (result []medal, err error) {
medalwallURL := "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=" + uid
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, medalwallURL, nil)
if err != nil {
return
}
c := vdb.getBilibiliCookie()
req.Header.Add("cookie", c.Value)
res, err := client.Do(req)
if err != nil {
return
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
return
}
fmt.Println("medalwall:", binary.BytesToString(data))
j := gjson.ParseBytes(data)
if j.Get("code").Int() == -101 {
err = errNeedCookie
return
}
if j.Get("code").Int() != 0 {
err = errors.New(j.Get("message").String())
}
_ = json.Unmarshal(binary.StringToBytes(j.Get("data.list").Raw), &result)
return
}

View File

@ -2,64 +2,290 @@
package bilibili
import (
"io"
"net/http"
"encoding/binary"
"fmt"
"image/color"
"os"
"sort"
"strconv"
"time"
control "github.com/FloatTech/zbputils/control"
"github.com/tidwall/gjson"
"github.com/FloatTech/zbputils/control/order"
"github.com/FloatTech/zbputils/file"
"github.com/FloatTech/zbputils/img"
"github.com/FloatTech/zbputils/img/text"
"github.com/FloatTech/zbputils/img/writer"
"github.com/FloatTech/zbputils/web"
"github.com/fogleman/gg"
log "github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/zbputils/control/order"
)
var engine = control.Register("bilibili", order.AcquirePrio(), &control.Options{
DisableOnDefault: false,
Help: "bilibili\n" +
"- >vup info [名字 | uid]\n" +
"- >user info [名字 | uid]",
"- >vup info [xxx]\n" +
"- >user info [xxx]\n" +
"- 查成分 [xxx]\n" +
"- 设置b站cookie SESSDATA=82da790d,1663822823,06ecf*31\n" +
"- 更新vup",
PublicDataFolder: "Bilibili",
})
// 查成分的
func init() {
engine.OnRegex(`^>(?:user|vup)\s?info\s?(.{1,25})$`).SetBlock(true).
cachePath := engine.DataFolder() + "cache/"
dbfile := engine.DataFolder() + "bilibili.db"
go func() {
_ = os.MkdirAll(cachePath, 0755)
_, _ = file.GetLazyData(dbfile, false, false)
vdb = initialize(dbfile)
}()
engine.OnRegex(`^>user info\s?(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
rest, err := uid(keyword)
uidRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := rest.Get("data.result.0.mid").String()
url := "https://api.bilibili.com/x/relation/same/followings?vmid=" + id
method := "GET"
client := &http.Client{}
req, err := http.NewRequest(method, url, nil)
id := strconv.FormatInt(uidRes[0].Mid, 10)
follwings, err := followings(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
req.Header.Add("cookie", "CURRENT_FNVAL=80; _uuid=772B88E8-3ED1-D589-29BB-F6CB5214239A06137infoc; blackside_state=1; bfe_id=6f285c892d9d3c1f8f020adad8bed553; rpdid=|(umY~Jkl|kJ0J'uYkR|)lu|); fingerprint=0ec2b1140fb30b56d7b5e415bc3b5fb1; buvid_fp=C91F5265-3DF4-4D5A-9FF3-C546370B14C0143096infoc; buvid_fp_plain=C91F5265-3DF4-4D5A-9FF3-C546370B14C0143096infoc; SESSDATA=9e0266f6%2C1639637127%2Cb0172%2A61; bili_jct=96ddbd7e22d527abdc0501339a12d4d3; DedeUserID=695737880; DedeUserID__ckMd5=0117660e75db7b01; sid=5labuhaf; PVID=1; bfe_id=1e33d9ad1cb29251013800c68af42315")
res, err := client.Do(req)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
data := string(body)
ctx.SendChain(message.Text(
"uid: ", rest.Get("data.result.0.mid").Int(), "\n",
"name: ", rest.Get("data.result.0.uname").Str, "\n",
"sex: ", []string{"", "", "女", "男"}[rest.Get("data.result.0.gender").Int()], "\n",
"sign: ", rest.Get("data.result.0.usign").Str, "\n",
"level: ", rest.Get("data.result.0.level").Int(), "\n",
"follow: ", gjson.Get(data, "data.list.#.uname"),
"search: ", uidRes[0].Mid, "\n",
"name: ", uidRes[0].Uname, "\n",
"sex: ", []string{"", "男", "女", "未知"}[uidRes[0].Gender], "\n",
"sign: ", uidRes[0].Usign, "\n",
"level: ", uidRes[0].Level, "\n",
"follow: ", follwings,
))
})
engine.OnRegex(`^>vup info\s?(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
res, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := strconv.FormatInt(res[0].Mid, 10)
// 获取详情
fo, err := fansapi(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(
"search: ", fo.Mid, "\n",
"名字: ", fo.Uname, "\n",
"当前粉丝数: ", fo.Follower, "\n",
"24h涨粉数: ", fo.Rise, "\n",
"视频投稿数: ", fo.Video, "\n",
"直播间id: ", fo.Roomid, "\n",
"舰队: ", fo.GuardNum, "\n",
"直播总排名: ", fo.AreaRank, "\n",
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
))
})
engine.OnRegex(`^查成分\s?(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
searchRes, err := search(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := strconv.FormatInt(searchRes[0].Mid, 10)
today := time.Now().Format("20060102")
drawedFile := cachePath + id + today + "vupLike.png"
if file.IsExist(drawedFile) {
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
return
}
u, err := card(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
vups, err := vdb.filterVup(u.Attentions)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
vupLen := len(vups)
medals, err := medalwall(id)
sort.Sort(medalSlice(medals))
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
}
frontVups := make([]vup, 0)
medalMap := make(map[int64]medal)
for _, v := range medals {
up := vup{
Mid: v.Mid,
Uname: v.Uname,
}
frontVups = append(frontVups, up)
medalMap[v.Mid] = v
}
vups = append(vups, frontVups...)
copy(vups[len(frontVups):], vups[:])
copy(vups[:], frontVups)
for i := len(frontVups); i < len(vups); i++ {
if _, ok := medalMap[vups[i].Mid]; ok {
vups = append(vups[:i], vups[i+1:]...)
i--
}
}
facePath := cachePath + id + "vupFace.png"
initFacePic(facePath, u.Face)
var backX int
var backY int
back, err := gg.LoadImage(facePath)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
backX = 500
backY = 500
} else {
back = img.Limit(back, 500, 500)
backX = back.Bounds().Size().X
backY = back.Bounds().Size().Y
}
if len(vups) > 50 {
ctx.SendChain(message.Text(u.Name + "关注的up主太多了只展示前50个up"))
vups = vups[:50]
}
canvas := gg.NewContext(backX*3, int(float64(backY)*(1.1+float64(len(vups))/3)))
fontSize := float64(backX) * 0.1
canvas.SetColor(color.White)
canvas.Clear()
if back != nil {
canvas.DrawImage(back, 0, 0)
}
canvas.SetColor(color.Black)
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
sl, _ := canvas.MeasureString("好")
length, h := canvas.MeasureString(u.Mid)
n, _ := canvas.MeasureString(u.Name)
canvas.DrawString(u.Name, float64(backX)*1.1, float64(backY)/3-h)
canvas.DrawRoundedRectangle(float64(backX)*1.2+n-length*0.1, float64(backY)/3-h*2.5, length*1.2, h*2, fontSize*0.2)
canvas.SetRGB255(221, 221, 221)
canvas.Fill()
canvas.SetColor(color.Black)
canvas.DrawString(u.Mid, float64(backX)*1.2+n, float64(backY)/3-h)
canvas.DrawString(fmt.Sprintf("粉丝:%d", u.Fans), float64(backX)*1.1, float64(backY)/3*2-2.5*h)
canvas.DrawString(fmt.Sprintf("关注:%d", len(u.Attentions)), float64(backX)*2, float64(backY)/3*2-2.5*h)
canvas.DrawString(fmt.Sprintf("管人痴成分:%.2f%%%d/%d", float64(vupLen)/float64(len(u.Attentions))*100, vupLen, len(u.Attentions)), float64(backX)*1.1, float64(backY)-4*h)
canvas.DrawString("日期:"+time.Now().Format("2006-01-02"), float64(backX)*1.1, float64(backY)-h)
for i, v := range vups {
if i%2 == 1 {
canvas.SetRGB255(245, 245, 245)
canvas.DrawRectangle(0, float64(backY)*1.1+float64(i)*float64(backY)/3, float64(backX*3), float64(backY)/3)
canvas.Fill()
}
canvas.SetColor(color.Black)
nl, _ := canvas.MeasureString(v.Uname)
canvas.DrawString(v.Uname, float64(backX)*0.1, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
ml, _ := canvas.MeasureString(strconv.FormatInt(v.Mid, 10))
canvas.DrawRoundedRectangle(nl-0.1*ml+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-h*3.5, ml*1.2, h*2, fontSize*0.2)
canvas.SetRGB255(221, 221, 221)
canvas.Fill()
canvas.SetColor(color.Black)
canvas.DrawString(strconv.FormatInt(v.Mid, 10), nl+float64(backX)*0.2, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
if m, ok := medalMap[v.Mid]; ok {
mnl, _ := canvas.MeasureString(m.MedalName)
grad := gg.NewLinearGradient(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h, nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
r, g, b := int2rbg(m.MedalColorStart)
grad.AddColorStop(0, color.RGBA{uint8(r), uint8(g), uint8(b), 255})
r, g, b = int2rbg(m.MedalColorEnd)
grad.AddColorStop(1, color.RGBA{uint8(r), uint8(g), uint8(b), 255})
canvas.SetFillStyle(grad)
canvas.SetLineWidth(4)
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.ClosePath()
canvas.Fill()
canvas.SetColor(color.White)
canvas.DrawString(m.MedalName, nl+ml+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
r, g, b = int2rbg(m.MedalColorBorder)
canvas.SetRGB255(int(r), int(g), int(b))
canvas.DrawString(strconv.FormatInt(m.Level, 10), nl+ml+mnl+sl+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-2*h)
mll, _ := canvas.MeasureString(strconv.FormatInt(m.Level, 10))
canvas.SetLineWidth(4)
canvas.MoveTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-3.5*h)
canvas.LineTo(nl+ml+mnl+mll+sl/2+float64(backX)*0.5, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.LineTo(nl+ml-sl/2+float64(backX)*0.4, float64(backY)*1.1+float64(i+1)*float64(backY)/3-1.5*h)
canvas.ClosePath()
canvas.Stroke()
}
}
f, err := os.Create(drawedFile)
if err != nil {
log.Errorln("[bilibili]", err)
data, cl := writer.ToBytes(canvas.Image())
ctx.SendChain(message.ImageBytes(data))
cl()
return
}
_, err = writer.WriteTo(canvas.Image(), f)
_ = f.Close()
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Image("file:///" + file.BOTPATH + "/" + drawedFile))
})
engine.OnRegex(`^设置b站cookie?\s+(.{1,100})$`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
cookie := ctx.State["regex_matched"].([]string)[1]
err := vdb.setBilibiliCookie(cookie)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text("成功设置b站cookie为" + cookie))
})
engine.OnFullMatch("更新vup", zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("少女祈祷中..."))
updateVup()
ctx.SendChain(message.Text("vup已更新"))
})
}
func initFacePic(filename, faceURL string) {
if file.IsNotExist(filename) {
data, err := web.GetData(faceURL)
if err != nil {
log.Errorln("[bilibili]", err)
}
err = os.WriteFile(filename, data, 0666)
if err != nil {
log.Errorln("[bilibili]", err)
}
}
}
func int2rbg(t int64) (int64, int64, int64) {
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], uint64(t))
b, g, r := int64(buf[0]), int64(buf[1]), int64(buf[2])
return r, g, b
}

View File

@ -1,85 +0,0 @@
package bilibili
import (
"encoding/json"
"errors"
"net/http"
"time"
"github.com/FloatTech/zbputils/web"
"github.com/tidwall/gjson"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
// 查vup粉丝数据
func init() {
engine.OnRegex(`^>vup info\s?(.{1,25})$`).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
keyword := ctx.State["regex_matched"].([]string)[1]
res, err := uid(keyword)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
id := res.Get("data.result.0.mid").String()
// 获取详情
fo, err := fansapi(id)
if err != nil {
ctx.SendChain(message.Text("ERROR:", err))
return
}
ctx.SendChain(message.Text(
"uid: ", fo.Mid, "\n",
"名字: ", fo.Uname, "\n",
"当前粉丝数: ", fo.Follower, "\n",
"24h涨粉数: ", fo.Rise, "\n",
"视频投稿数: ", fo.Video, "\n",
"直播间id: ", fo.Roomid, "\n",
"舰队: ", fo.GuardNum, "\n",
"直播总排名: ", fo.AreaRank, "\n",
"数据来源: ", "https://vtbs.moe/detail/", fo.Mid, "\n",
"数据获取时间: ", time.Now().Format("2006-01-02 15:04:05"),
))
})
}
// 搜索api通过把触发指令传入的昵称找出uid返回
func uid(keyword string) (*gjson.Result, error) {
api := "http://api.bilibili.com/x/web-interface/search/type?search_type=bili_user&&user_type=1&keyword=" + keyword
data, err := web.GetData(api)
if err != nil {
return nil, err
}
json := gjson.ParseBytes(data)
if json.Get("data.numResults").Int() == 0 {
return nil, errors.New("查无此人")
}
return &json, nil
}
type follower struct {
Mid int `json:"mid"`
Uname string `json:"uname"`
Video int `json:"video"`
Roomid int `json:"roomid"`
Rise int `json:"rise"`
Follower int `json:"follower"`
GuardNum int `json:"guardNum"`
AreaRank int `json:"areaRank"`
}
// 请求api
func fansapi(uid string) (*follower, error) {
url := "https://api.vtbs.moe/v1/detail/" + uid
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
result := &follower{}
if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
return nil, err
}
return result, nil
}

129
plugin/bilibili/model.go Normal file
View File

@ -0,0 +1,129 @@
package bilibili
import (
"github.com/FloatTech/zbputils/binary"
"github.com/FloatTech/zbputils/web"
_ "github.com/fumiama/sqlite3" // use sql
"github.com/jinzhu/gorm"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"os"
)
const (
bilibiliCookie = "bilbili_cookie"
)
var (
vtbURLs = [...]string{"https://api.vtbs.moe/v1/short", "https://api.tokyo.vtbs.moe/v1/short", "https://vtbs.musedash.moe/v1/short"}
vdb *vupdb
)
// vupdb 分数数据库
type vupdb gorm.DB
type vup struct {
Mid int64 `gorm:"column:mid;primary_key"`
Uname string `gorm:"column:uname"`
Roomid int64 `gorm:"column:roomid"`
}
func (vup) TableName() string {
return "vup"
}
type config struct {
Key string `gorm:"column:key;primary_key"`
Value string `gorm:"column:value"`
}
func (config) TableName() string {
return "config"
}
// initialize 初始化vtb数据库
func initialize(dbpath string) *vupdb {
if _, err := os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.Debug().AutoMigrate(&vup{}).AutoMigrate(&config{})
return (*vupdb)(gdb)
}
func (vdb *vupdb) insertVupByMid(mid int64, uname string, roomid int64) (err error) {
db := (*gorm.DB)(vdb)
v := vup{
Mid: mid,
Uname: uname,
Roomid: roomid,
}
if err = db.Debug().Model(&vup{}).First(&v, "mid = ? ", mid).Error; err != nil {
if gorm.IsRecordNotFoundError(err) {
err = db.Debug().Model(&vup{}).Create(&v).Error
}
}
return
}
// filterVup 筛选vup
func (vdb *vupdb) filterVup(ids []int64) (vups []vup, err error) {
db := (*gorm.DB)(vdb)
if err = db.Debug().Model(&vup{}).Find(&vups, "mid in (?)", ids).Error; err != nil {
return vups, err
}
return
}
func updateVup() {
for _, v := range vtbURLs {
data, err := web.GetData(v)
if err != nil {
log.Errorln("[bilibili]:", err)
}
gjson.Get(binary.BytesToString(data), "@this").ForEach(func(key, value gjson.Result) bool {
mid := value.Get("mid").Int()
uname := value.Get("uname").String()
roomid := value.Get("roomid").Int()
err = vdb.insertVupByMid(mid, uname, roomid)
if err != nil {
log.Errorln("[bilibili]:", err)
}
return true
})
}
}
func (vdb *vupdb) setBilibiliCookie(cookie string) (err error) {
db := (*gorm.DB)(vdb)
c := config{
Key: bilibiliCookie,
Value: cookie,
}
if err = db.Debug().Model(&config{}).First(&c, "key = ? ", bilibiliCookie).Error; err != nil {
// error handling...
if gorm.IsRecordNotFoundError(err) {
err = db.Debug().Model(&config{}).Create(&c).Error
}
} else {
err = db.Debug().Model(&config{}).Where("key = ? ", bilibiliCookie).Update(
map[string]interface{}{
"value": cookie,
}).Error
}
return
}
func (vdb *vupdb) getBilibiliCookie() (c config) {
db := (*gorm.DB)(vdb)
db.Debug().Model(&config{}).First(&c, "key = ?", bilibiliCookie)
return
}

View File

@ -5,8 +5,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"time"
@ -300,20 +298,7 @@ func getLiveList(uids ...int64) string {
m := make(map[string]interface{})
m["uids"] = uids
b, _ := json.Marshal(m)
client := &http.Client{}
// 提交请求
request, err := http.NewRequest("POST", liveListURL, bytes.NewBuffer(b))
if err != nil {
log.Errorln("[bilibilipush]:", err)
}
request.Header.Add("Referer", referer)
request.Header.Add("User-Agent", ua)
response, err := client.Do(request)
if err != nil {
log.Errorln("[bilibilipush]:", err)
}
defer response.Body.Close()
data, err := io.ReadAll(response.Body)
data, err := web.PostData(liveListURL, "application/json", bytes.NewReader(b))
if err != nil {
log.Errorln("[bilibilipush]:", err)
}