bilibili/subtitles/client.go
timerzz adf418f016
All checks were successful
Build image / build (push) Successful in 35s
feat 添加没有获取到字幕的情况
2024-07-01 18:13:58 +08:00

135 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"github.com/gofiber/fiber/v3/client"
"net/url"
"regexp"
"strconv"
"strings"
)
var headers = map[string][]string{
"Accept": {"application/json"},
"Content-Type": {"application/json"},
"User-Agent": {"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"},
"Host": {"api.bilibili.com"},
}
type Client struct {
cli *client.Client
}
func NewClient(sessData string) *Client {
return &Client{
cli: client.New().AddHeaders(headers).SetCookie("SESSDATA", sessData),
}
}
func (c *Client) GetSubtitles(url string) (string, error) {
vid, page, err := parseBilibiliUrl(url)
if err != nil {
return "", err
}
data, err := c.callView(vid)
if err != nil {
return "", err
}
var aid, cid = data.Data.Stat.Aid, 0
for _, p := range data.Data.Pages {
if p.Page == page {
cid = p.Cid
}
}
player, err := c.callPlayer(aid, cid)
if err != nil {
return "", err
}
subTitlesUrl := ""
for _, sub := range player.Data.Subtitle.Subtitles {
if sub.SubtitleUrl != "" {
subTitlesUrl = fmt.Sprintf("https:%s", sub.SubtitleUrl)
break
}
}
if subTitlesUrl == "" {
return "", fmt.Errorf("没有找到字幕")
}
subtitles, err := c.callSubtitles(subTitlesUrl)
if err != nil {
return "", err
}
var subtitlesList = make([]string, 0, len(subtitles.Body))
for _, sub := range subtitles.Body {
subtitlesList = append(subtitlesList, sub.Content)
}
return strings.Join(subtitlesList, "\n"), nil
}
func (c *Client) callView(vid string) (data Response[ViewResponseData], err error) {
var r = c.cli.R()
if strings.HasPrefix(vid, "av") {
r.AddParam("aid", vid[2:])
} else {
r.AddParam("bvid", vid)
}
resp, err := r.Get("https://api.bilibili.com/x/web-interface/view")
if err != nil {
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
}
err = resp.JSON(&data)
return data, err
}
func (c *Client) callPlayer(aid, cid int) (data Response[PlayerResponseData], err error) {
var r = c.cli.R()
r.AddParam("aid", strconv.Itoa(aid))
r.AddParam("cid", strconv.Itoa(cid))
resp, err := r.Get("https://api.bilibili.com/x/player/v2")
if err != nil {
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
}
err = resp.JSON(&data)
return data, err
}
func (c *Client) callSubtitles(url string) (data SubtitlesResponse, err error) {
var r = c.cli.R()
resp, err := r.Get(url)
if err != nil {
return data, fmt.Errorf("请求 %s 出错:%v", r.URL(), err)
}
err = resp.JSON(&data)
return data, err
}
func parseBilibiliUrl(bu string) (vid string, page int, err error) {
u, err := url.Parse(bu)
if err != nil {
return "", 0, err
}
if u.Host != "www.bilibili.com" && u.Host != "m.bilibili.com" {
return "", 0, fmt.Errorf("链接似乎不是bilibili的视频链接")
}
re := regexp.MustCompile("/video/(?P<vid>[a-zA-Z0-9]+)")
parts := re.FindStringSubmatch(u.Path)
names := re.SubexpNames()
for _, name := range names {
if name == "vid" {
vid = parts[re.SubexpIndex(name)]
}
}
if vid == "" {
return "", 0, fmt.Errorf("链接似乎不是bilibili的视频链接未获取到视频id")
}
query := u.Query()
if query.Get("p") != "" {
pageStr := query.Get("p")
page, _ = strconv.Atoi(pageStr)
} else {
page = 1
}
return vid, page, nil
}