bilibili/subtitles/client.go
timerzz c00090712d
Some checks failed
Build image / build (push) Failing after 3s
feat 初始化
2024-07-01 17:22:31 +08:00

130 lines
3.2 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
}
}
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)
}
return vid, page, nil
}