feat: bilibili video danmuku

main v0.9.8
zijiren233 2 weeks ago
parent b4740d5eb4
commit 5978c583a9

@ -2,10 +2,12 @@ package cache
import (
"bytes"
"compress/flate"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net/http"
"time"
@ -353,8 +355,6 @@ func translateBilibiliSubtitleToSrt(ctx context.Context, url string) ([]byte, er
return convertToSRT(&srt), nil
}
type BilibiliLiveCache struct{}
func NewBilibiliLiveCacheInitFunc(movie *model.Movie) func(ctx context.Context) ([]byte, error) {
return func(ctx context.Context) ([]byte, error) {
return BilibiliLiveCacheInitFunc(ctx, movie)
@ -387,11 +387,41 @@ func BilibiliLiveCacheInitFunc(ctx context.Context, movie *model.Movie) ([]byte,
return genBilibiliLiveM3U8ListFile(resp.LiveStreams), nil
}
func NewBilibiliDanmuCacheInitFunc(movie *model.Movie) func(ctx context.Context) ([]byte, error) {
return func(ctx context.Context) ([]byte, error) {
return BilibiliDanmuCacheInitFunc(ctx, movie)
}
}
func BilibiliDanmuCacheInitFunc(ctx context.Context, movie *model.Movie) ([]byte, error) {
u := fmt.Sprintf("https://comment.bilibili.com/%d.xml", movie.VendorInfo.Bilibili.Cid)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status code: %d", resp.StatusCode)
}
gz := flate.NewReader(resp.Body)
defer gz.Close()
data, err := io.ReadAll(gz)
if err != nil {
return nil, err
}
return data, nil
}
type BilibiliMovieCache struct {
NoSharedMovie *MapCache[string, *BilibiliUserCache]
SharedMpd *refreshcache1.RefreshCache[*BilibiliMpdCache, *BilibiliUserCache]
Subtitle *refreshcache1.RefreshCache[BilibiliSubtitleCache, *BilibiliUserCache]
Live *refreshcache0.RefreshCache[[]byte]
Danmu *refreshcache0.RefreshCache[[]byte]
}
func NewBilibiliMovieCache(movie *model.Movie) *BilibiliMovieCache {
@ -400,6 +430,7 @@ func NewBilibiliMovieCache(movie *model.Movie) *BilibiliMovieCache {
SharedMpd: refreshcache1.NewRefreshCache(NewBilibiliSharedMpdCacheInitFunc(movie), time.Minute*55),
Subtitle: refreshcache1.NewRefreshCache(NewBilibiliSubtitleCacheInitFunc(movie), -1),
Live: refreshcache0.NewRefreshCache(NewBilibiliLiveCacheInitFunc(movie), time.Minute*55),
Danmu: refreshcache0.NewRefreshCache(NewBilibiliDanmuCacheInitFunc(movie), -1),
}
}

@ -60,9 +60,21 @@ func (s *BilibiliVendorService) ProxyMovie(ctx *gin.Context) {
s.handleVideoProxy(ctx, log, t)
case "subtitle":
s.handleSubtitleProxy(ctx, log)
case "danmu":
s.handleDanmuProxy(ctx, log)
}
}
func (s *BilibiliVendorService) handleDanmuProxy(ctx *gin.Context, log *logrus.Entry) {
danmu, err := s.movie.BilibiliCache().Danmu.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
ctx.Data(http.StatusOK, "application/xml", danmu)
}
func (s *BilibiliVendorService) handleLiveProxy(ctx *gin.Context, log *logrus.Entry) {
data, err := s.movie.BilibiliCache().Live.Get(ctx)
if err != nil {
@ -219,6 +231,8 @@ func (s *BilibiliVendorService) GenMovieInfo(ctx context.Context, user *op.User,
return movie, nil
}
movie.Danmu = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&t=danmu&roomId=%s", movie.ID, userToken, movie.RoomID)
var str string
if movie.MovieBase.VendorInfo.Bilibili.Shared {
var u *op.UserEntry
@ -267,6 +281,8 @@ func (s *BilibiliVendorService) GenProxyMovieInfo(ctx context.Context, user *op.
return movie, nil
}
movie.Danmu = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&t=danmu&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "mpd"
movie.MovieBase.MoreSources = []*dbModel.MoreSource{

@ -60,9 +60,21 @@ func (s *BilibiliVendorService) ProxyMovie(ctx *gin.Context) {
s.handleVideoProxy(ctx, log, t)
case "subtitle":
s.handleSubtitleProxy(ctx, log)
case "danmu":
s.handleDanmuProxy(ctx, log)
}
}
func (s *BilibiliVendorService) handleDanmuProxy(ctx *gin.Context, log *logrus.Entry) {
danmu, err := s.movie.BilibiliCache().Danmu.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
ctx.Data(http.StatusOK, "application/xml", danmu)
}
func (s *BilibiliVendorService) handleLiveProxy(ctx *gin.Context, log *logrus.Entry) {
data, err := s.movie.BilibiliCache().Live.Get(ctx)
if err != nil {
@ -219,6 +231,8 @@ func (s *BilibiliVendorService) GenMovieInfo(ctx context.Context, user *op.User,
return movie, nil
}
movie.Danmu = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&t=danmu&roomId=%s", movie.ID, userToken, movie.RoomID)
var str string
if movie.MovieBase.VendorInfo.Bilibili.Shared {
var u *op.UserEntry
@ -267,6 +281,8 @@ func (s *BilibiliVendorService) GenProxyMovieInfo(ctx context.Context, user *op.
return movie, nil
}
movie.Danmu = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&t=danmu&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "mpd"
movie.MovieBase.MoreSources = []*dbModel.MoreSource{

Loading…
Cancel
Save