Skip to content

Commit ea6eb4d

Browse files
committed
✨ 添加视频下载
1 parent 109b766 commit ea6eb4d

File tree

4 files changed

+102
-13
lines changed

4 files changed

+102
-13
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.20
44

55
require (
66
github.com/Baidu-AIP/golang-sdk v1.1.1
7-
github.com/FloatTech/AnimeAPI v1.7.1-0.20250217140215-4856397458c9
7+
github.com/FloatTech/AnimeAPI v1.7.1-0.20250423082452-e16339a3962c
88
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024
99
github.com/FloatTech/gg v1.1.3
1010
github.com/FloatTech/imgfactory v0.2.2-0.20230413152719-e101cc3606ef

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
github.com/Baidu-AIP/golang-sdk v1.1.1 h1:RQsAmgDSAkiq22I6n7XJ2t3afgzFeqjY46FGhvrx4cw=
22
github.com/Baidu-AIP/golang-sdk v1.1.1/go.mod h1:bXnGw7xPeKt8aF7UCELKrV6UZ/46spItONK1RQBQj1Y=
33
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
4-
github.com/FloatTech/AnimeAPI v1.7.1-0.20250217140215-4856397458c9 h1:tI9GgG8fdMK2WazFiEbMXAXjwMCckIfDaXbig9B6DdA=
5-
github.com/FloatTech/AnimeAPI v1.7.1-0.20250217140215-4856397458c9/go.mod h1:XXG1eBJf+eeWacQx5azsQKL5Gg7jDYTFyyZGIa/56js=
4+
github.com/FloatTech/AnimeAPI v1.7.1-0.20250423082452-e16339a3962c h1:bEe8VP2aHLR2NHk1BsBQFtP0XE3cxquvr0tW0CkKcDk=
5+
github.com/FloatTech/AnimeAPI v1.7.1-0.20250423082452-e16339a3962c/go.mod h1:XXG1eBJf+eeWacQx5azsQKL5Gg7jDYTFyyZGIa/56js=
66
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024 h1:mrvWpiwfRklt9AyiQjKgDGJjf4YL6FZ3yC+ydbkuF2o=
77
github.com/FloatTech/floatbox v0.0.0-20241106130736-5aea0a935024/go.mod h1:+P3hs+Cvl10/Aj3SNE96TuBvKAXCe+XD1pKphTZyiwk=
88
github.com/FloatTech/gg v1.1.3 h1:+GlL02lTKsxJQr4WCuNwVxC1/eBZrCvypCIBtxuOFb4=

plugin/bilibili/bilibili_parse.go

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@
22
package bilibili
33

44
import (
5+
"bytes"
56
"encoding/json"
67
"fmt"
78
"net/http"
9+
"os"
10+
"os/exec"
811
"regexp"
912
"strings"
1013
"time"
1114

1215
bz "github.com/FloatTech/AnimeAPI/bilibili"
16+
"github.com/FloatTech/floatbox/file"
1317
"github.com/FloatTech/floatbox/web"
1418
ctrl "github.com/FloatTech/zbpctrl"
1519
"github.com/FloatTech/zbputils/control"
1620
"github.com/FloatTech/zbputils/ctxext"
21+
"github.com/pkg/errors"
1722
zero "github.com/wdvxdr1123/ZeroBot"
1823
"github.com/wdvxdr1123/ZeroBot/message"
1924
)
2025

2126
const (
22-
enableHex = 0x10
23-
unableHex = 0x7fffffff_fffffffd
27+
enableHex = 0x10
28+
unableHex = 0x7fffffff_fffffffd
29+
bilibiliparseReferer = "https://www.bilibili.com"
2430
)
2531

2632
var (
@@ -42,10 +48,14 @@ func init() {
4248
Brief: "b站链接解析",
4349
Help: "例:- t.bilibili.com/642277677329285174\n- bilibili.com/read/cv17134450\n- bilibili.com/video/BV13B4y1x7pS\n- live.bilibili.com/22603245 ",
4450
})
51+
cachePath := en.DataFolder() + "cache/"
52+
_ = os.RemoveAll(cachePath)
53+
_ = os.MkdirAll(cachePath, 0755)
4554
en.OnRegex(`((b23|acg).tv|bili2233.cn)\\?/[0-9a-zA-Z]+`).SetBlock(true).Limit(limit.LimitByGroup).
4655
Handle(func(ctx *zero.Ctx) {
4756
u := ctx.State["regex_matched"].([]string)[0]
4857
u = strings.ReplaceAll(u, "\\", "")
58+
ctx.State["cache_path"] = cachePath
4959
realurl, err := bz.GetRealURL("https://" + u)
5060
if err != nil {
5161
ctx.SendChain(message.Text("ERROR: ", err))
@@ -95,10 +105,22 @@ func init() {
95105
}
96106
ctx.SendChain(message.Text("已", option, "视频总结"))
97107
})
98-
en.OnRegex(searchVideo).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
99-
en.OnRegex(searchDynamic).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
100-
en.OnRegex(searchArticle).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
101-
en.OnRegex(searchLiveRoom).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleLive)
108+
en.OnRegex(searchVideo, func(ctx *zero.Ctx) bool {
109+
ctx.State["cache_path"] = cachePath
110+
return true
111+
}).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleVideo)
112+
en.OnRegex(searchDynamic, func(ctx *zero.Ctx) bool {
113+
ctx.State["cache_path"] = cachePath
114+
return true
115+
}).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleDynamic)
116+
en.OnRegex(searchArticle, func(ctx *zero.Ctx) bool {
117+
ctx.State["cache_path"] = cachePath
118+
return true
119+
}).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleArticle)
120+
en.OnRegex(searchLiveRoom, func(ctx *zero.Ctx) bool {
121+
ctx.State["cache_path"] = cachePath
122+
return true
123+
}).SetBlock(true).Limit(limit.LimitByGroup).Handle(handleLive)
102124
}
103125

104126
func handleVideo(ctx *zero.Ctx) {
@@ -126,6 +148,13 @@ func handleVideo(ctx *zero.Ctx) {
126148
}
127149
}
128150
ctx.SendChain(msg...)
151+
cachePath := ctx.State["cache_path"].(string)
152+
downLoadMsg, err := getVideoDownload(cfg, card, cachePath)
153+
if err != nil {
154+
ctx.SendChain(message.Text("ERROR: ", err))
155+
return
156+
}
157+
ctx.SendChain(downLoadMsg...)
129158
}
130159

131160
func handleDynamic(ctx *zero.Ctx) {
@@ -189,3 +218,48 @@ func getVideoSummary(cookiecfg *bz.CookieConfig, card bz.Card) (msg []message.Se
189218
}
190219
return
191220
}
221+
222+
func getVideoDownload(cookiecfg *bz.CookieConfig, card bz.Card, cachePath string) (msg []message.Segment, err error) {
223+
var (
224+
data []byte
225+
videoDownload bz.VideoDownload
226+
stderr bytes.Buffer
227+
)
228+
today := time.Now().Format("20060102")
229+
videoFile := fmt.Sprintf("%s%s%s.mp4", cachePath, card.BvID, today)
230+
if file.IsExist(videoFile) {
231+
msg = append(msg, message.Video("file:///"+file.BOTPATH+"/"+videoFile))
232+
return
233+
}
234+
data, err = web.RequestDataWithHeaders(web.NewDefaultClient(), bz.SignURL(fmt.Sprintf(bz.VideoDownloadURL, card.BvID, card.CID)), "GET", func(req *http.Request) error {
235+
if cookiecfg != nil {
236+
cookie := ""
237+
cookie, err = cookiecfg.Load()
238+
if err != nil {
239+
return err
240+
}
241+
req.Header.Add("cookie", cookie)
242+
}
243+
req.Header.Set("User-Agent", ua)
244+
return nil
245+
}, nil)
246+
if err != nil {
247+
return
248+
}
249+
err = json.Unmarshal(data, &videoDownload)
250+
if err != nil {
251+
return
252+
}
253+
headers := fmt.Sprintf("User-Agent: %s\nReferer: %s", ua, bilibiliparseReferer)
254+
// 限制最多下载8分钟视频
255+
cmd := exec.Command("ffmpeg", "-ss", "0", "-t", "480", "-headers", headers, "-i", videoDownload.Data.Durl[0].URL, "-c", "copy", videoFile)
256+
cmd.Stderr = &stderr
257+
err = cmd.Run()
258+
if err != nil {
259+
err = errors.Errorf("未配置ffmpeg,%s", stderr.String())
260+
return
261+
}
262+
msg = append(msg, message.Video("file:///"+file.BOTPATH+"/"+videoFile))
263+
return
264+
265+
}

plugin/bilibili/card2msg.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package bilibili
22

33
import (
44
"encoding/json"
5+
"fmt"
56
"time"
67

78
bz "github.com/FloatTech/AnimeAPI/bilibili"
89
"github.com/FloatTech/floatbox/binary"
10+
"github.com/FloatTech/floatbox/web"
911
"github.com/wdvxdr1123/ZeroBot/message"
1012
)
1113

@@ -303,7 +305,10 @@ func liveCard2msg(card bz.RoomCard) (msg []message.Segment) {
303305

304306
// videoCard2msg 视频卡片转消息
305307
func videoCard2msg(card bz.Card) (msg []message.Segment, err error) {
306-
var mCard bz.MemberCard
308+
var (
309+
mCard bz.MemberCard
310+
onlineTotal bz.OnlineTotal
311+
)
307312
msg = make([]message.Segment, 0, 16)
308313
mCard, err = bz.GetMemberCard(card.Owner.Mid)
309314
msg = append(msg, message.Text("标题: ", card.Title, "\n"))
@@ -319,10 +324,20 @@ func videoCard2msg(card bz.Card) (msg []message.Segment, err error) {
319324
msg = append(msg, message.Text("UP主: ", card.Owner.Name, " 粉丝: ", bz.HumanNum(mCard.Fans), "\n"))
320325
}
321326
}
322-
msg = append(msg, message.Text("播放: ", bz.HumanNum(card.Stat.View), " 弹幕: ", bz.HumanNum(card.Stat.Danmaku)))
323327
msg = append(msg, message.Image(card.Pic))
324-
msg = append(msg, message.Text("\n点赞: ", bz.HumanNum(card.Stat.Like), " 投币: ", bz.HumanNum(card.Stat.Coin), "\n",
325-
"收藏: ", bz.HumanNum(card.Stat.Favorite), " 分享: ", bz.HumanNum(card.Stat.Share), "\n",
328+
data, err := web.GetData(fmt.Sprintf(bz.OnlineTotalURL, card.BvID, card.CID))
329+
if err != nil {
330+
return
331+
}
332+
err = json.Unmarshal(data, &onlineTotal)
333+
if err != nil {
334+
return
335+
}
336+
msg = append(msg, message.Text("👀播放: ", bz.HumanNum(card.Stat.View), " 💬弹幕: ", bz.HumanNum(card.Stat.Danmaku),
337+
"\n👍点赞: ", bz.HumanNum(card.Stat.Like), " 💰投币: ", bz.HumanNum(card.Stat.Coin),
338+
"\n📁收藏: ", bz.HumanNum(card.Stat.Favorite), " 🔗分享: ", bz.HumanNum(card.Stat.Share),
339+
"\n📝简介: ", card.Desc,
340+
"\n🏄‍♂️ 总共 ", onlineTotal.Data.Total, " 人在观看,", onlineTotal.Data.Count, " 人在网页端观看\n",
326341
bz.VURL, card.BvID, "\n\n"))
327342
return
328343
}

0 commit comments

Comments
 (0)