From 5e7af981ad8a0290303bbb785b38d2378694b35c Mon Sep 17 00:00:00 2001 From: mei Date: Mon, 6 Oct 2025 20:02:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8F=91=E9=80=81bilibili=E5=8A=A8?= =?UTF-8?q?=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + configs/config.go | 1 + go.mod | 7 +++ go.sum | 24 +++++++ internal/bilibili.go | 146 +++++++++++++++++++++++++++++++++++++++++++ main.go | 17 +++++ 6 files changed, 196 insertions(+) create mode 100644 internal/bilibili.go diff --git a/.gitignore b/.gitignore index 85cf1d4..6f4aae7 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ go.work goodBaby config.json +cookies.txt diff --git a/configs/config.go b/configs/config.go index 624b519..a738e3e 100644 --- a/configs/config.go +++ b/configs/config.go @@ -18,6 +18,7 @@ type Config struct { SMTPConfig SMTPConfig `json:"smtp_config"` MailContent string `json:"mail_content"` GithubConfig GithubConfig `json:"github_config"` + BiliMsg string `json:"bili_msg"` } type SMTPConfig struct { diff --git a/go.mod b/go.mod index 48127cf..0fbc6ff 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,13 @@ go 1.24.0 toolchain go1.24.7 require ( + github.com/CuteReimu/bilibili/v2 v2.3.5 github.com/gin-gonic/gin v1.11.0 github.com/wneessen/go-mail v0.7.2 ) require ( + github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f // indirect github.com/bytedance/sonic v1.14.0 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -18,17 +20,22 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/go-resty/resty/v2 v2.16.5 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.18.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/quic-go v0.54.0 // indirect + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect + github.com/spf13/cast v1.9.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect go.uber.org/mock v0.5.0 // indirect diff --git a/go.sum b/go.sum index 53ab2c3..a04caac 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII= +github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk= +github.com/CuteReimu/bilibili/v2 v2.3.5 h1:0MpBOJL6Q7kP3lFItC7NQ3MLG/I1uIzZBjemXIE0CRM= +github.com/CuteReimu/bilibili/v2 v2.3.5/go.mod h1:FHKH1cc04M/qpQhF+DaFIBFleLtvgMwYfZCNhHK/kBQ= github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= @@ -7,6 +11,8 @@ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gE github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= @@ -21,6 +27,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM= +github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= @@ -32,8 +40,14 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= @@ -42,12 +56,20 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +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/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= +github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -80,6 +102,8 @@ golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= diff --git a/internal/bilibili.go b/internal/bilibili.go new file mode 100644 index 0000000..d61aab1 --- /dev/null +++ b/internal/bilibili.go @@ -0,0 +1,146 @@ +package internal + +import ( + "log" + "net/http" + "os" + "strings" + "time" + + "github.com/CuteReimu/bilibili/v2" + "github.com/ssdomei232/goodBaby/configs" +) + +func isCookiesExpired(cookiesString string) bool { + // 解析cookie中的过期时间 + lines := strings.SplitSeq(cookiesString, "\n") + for line := range lines { + if strings.Contains(line, "Expires=") { + // 提取过期时间字符串 + expireStr := "" + parts := strings.Split(line, ";") + for _, part := range parts { + part = strings.TrimSpace(part) + if strings.HasPrefix(part, "Expires=") { + expireStr = strings.TrimPrefix(part, "Expires=") + break + } + } + + if expireStr != "" { + // 解析过期时间 + expireTime, err := http.ParseTime(expireStr) + if err != nil { + log.Printf("解析过期时间失败: %v", err) + return true // 如果解析失败,认为已过期 + } + + // 比较过期时间和当前时间 + if time.Now().After(expireTime) { + return true // 已过期 + } + } + } + } + + return false // 未过期 +} + +// 二维码登录 +func LoginWithQRCode(biliClient *bilibili.Client) { + qrCode, err := biliClient.GetQRCode() + if err != nil { + log.Printf("获取二维码失败: %v", err) + return + } + + log.Println("请使用哔哩哔哩APP扫码登录") + qrCode.Print() + + result, err := biliClient.LoginWithQRCode(bilibili.LoginWithQRCodeParam{ + QrcodeKey: qrCode.QrcodeKey, + }) + if err != nil || result.Code != 0 { + log.Printf("登录失败: %v", err) + return + } + + log.Println("登录成功") + + // 保存新获取的cookie + saveCookies(biliClient) +} + +// 保存cookie到文件 +func saveCookies(client *bilibili.Client) { + cookiesString := client.GetCookiesString() + err := os.WriteFile("cookies.txt", []byte(cookiesString), 0644) + if err != nil { + log.Printf("保存cookie失败: %v", err) + } +} + +// 从文件加载cookie并验证有效性 +func LoadCookies(client *bilibili.Client) bool { + // 检查cookie文件是否存在 + if _, err := os.Stat("cookies.txt"); os.IsNotExist(err) { + return false + } + + // 读取cookie + cookiesBytes, err := os.ReadFile("cookies.txt") + if err != nil { + log.Printf("读取cookie文件失败: %v", err) + return false + } + + cookiesString := string(cookiesBytes) + client.SetCookiesString(cookiesString) + + // 验证cookie是否过期 + if isCookiesExpired(cookiesString) { + log.Println("cookie已过期") + return false + } + + return true +} + +func SendBili(biliClient *bilibili.Client) { + config, err := configs.GetConfig() + if err != nil { + log.Printf("获取配置文件失败: %v", err) + return + } + + var dynamicParams bilibili.CreateDynamicParam + dynamicParams = bilibili.CreateDynamicParam{ + DynamicId: 0, + Type: 4, + Rid: 0, + Content: config.BiliMsg, + } + + // 重试机制 + retryCount := 10 // 重试次数 + delay := time.Second * 2 // 初始重试延迟 + + for i := 0; i <= retryCount; i++ { + _, err := biliClient.CreateDynamic(dynamicParams) + if err == nil { + log.Println("动态发送成功") + return + } + + log.Printf("动态发送失败 (尝试 %d/%d): %v", i+1, retryCount+1, err) + + // 如果不是最后一次尝试,则等待后重试 + if i < retryCount { + log.Printf("等待 %v 后进行第 %d 次重试", delay, i+2) + time.Sleep(delay) + delay *= 2 // 指数退避 + } + } + + log.Println("动态发送最终失败,已达到最大重试次数") +} diff --git a/main.go b/main.go index f32d6de..130e3f6 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "log" "time" + "github.com/CuteReimu/bilibili/v2" "github.com/gin-gonic/gin" "github.com/ssdomei232/goodBaby/configs" "github.com/ssdomei232/goodBaby/internal" @@ -11,6 +12,7 @@ import ( var timer *time.Timer var duration time.Duration +var biliClient *bilibili.Client func init() { config, err := configs.GetConfig() @@ -29,12 +31,17 @@ func init() { <-timer.C trigger() }() + + // 初始化bilibili客户端 + biliClient = bilibili.New() + initBilibili() } func trigger() { go internal.SendQQ() go internal.SendMail() go internal.Github() + go internal.SendBili(biliClient) } func main() { @@ -62,3 +69,13 @@ func main() { }) r.Run(":8088") } + +func initBilibili() { + // 尝试加载已存储的cookie + if !internal.LoadCookies(biliClient) { + // 如果没有有效cookie,则进行二维码登录 + internal.LoginWithQRCode(biliClient) + } else { + log.Println("使用已存储的有效cookie登录") + } +}