fix: alist proxy subtile and ali m3u8 proxy

pull/232/merge v0.7.12
zijiren233 8 months ago
parent 301604704e
commit 2892f1475f

@ -82,7 +82,7 @@ func AlistAuthorizationCacheWithConfigInitFunc(ctx context.Context, v *model.Ali
type AlistMovieCache = refreshcache1.RefreshCache[*AlistMovieCacheData, *AlistMovieCacheFuncArgs]
func NewAlistMovieCache(movie *model.Movie, subPath string) *AlistMovieCache {
return refreshcache1.NewRefreshCache(NewAlistMovieCacheInitFunc(movie, subPath), time.Minute*14)
return refreshcache1.NewRefreshCache(NewAlistMovieCacheInitFunc(movie, subPath), -1)
}
type AlistProvider = string
@ -100,18 +100,22 @@ type AlistSubtitle struct {
}
type AlistMovieCacheData struct {
Ali *AlistAliCache
Ali *refreshcache0.RefreshCache[*AlistAliCache]
URL string
Provider string
Subtitles []*AlistSubtitle
}
type AlistAliCache struct {
URL string
M3U8ListFile []byte
Subtitles []*AlistSubtitle
}
type SubtitleDataCache = refreshcache0.RefreshCache[[]byte]
const subtitleMaxLength = 15 * 1024 * 1024
func newAliSubtitles(list []*alist.FsOtherResp_VideoPreviewPlayInfo_LiveTranscodingSubtitleTaskList) []*AlistSubtitle {
caches := make([]*AlistSubtitle, len(list))
for i, v := range list {
@ -133,7 +137,10 @@ func newAliSubtitles(list []*alist.FsOtherResp_VideoPreviewPlayInfo_LiveTranscod
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status code: %d", resp.StatusCode)
}
return io.ReadAll(resp.Body)
if resp.ContentLength > subtitleMaxLength {
return nil, fmt.Errorf("subtitle too large, got: %d, max: %d", resp.ContentLength, subtitleMaxLength)
}
return io.ReadAll(io.LimitReader(resp.Body, subtitleMaxLength))
}, -1),
Name: v.Language,
URL: v.Url,
@ -201,9 +208,7 @@ func NewAlistMovieCacheInitFunc(movie *model.Movie, subPath string) func(ctx con
}
if fg.Provider == AlistProviderAli {
if err := processAliProvider(ctx, cli, aucd, truePath, movie.MovieBase.VendorInfo.Alist.Password, cache); err != nil {
return nil, err
}
processAliProvider(ctx, fg.RawUrl, cli, aucd, truePath, movie.MovieBase.VendorInfo.Alist.Password, cache)
}
return cache, nil
@ -291,24 +296,44 @@ func fetchSubtitleContent(ctx context.Context, url string) ([]byte, error) {
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status code: %d", resp.StatusCode)
}
return io.ReadAll(resp.Body)
}
func processAliProvider(ctx context.Context, cli alist.AlistHTTPServer, aucd *AlistUserCacheData, truePath, password string, cache *AlistMovieCacheData) error {
fo, err := cli.FsOther(ctx, &alist.FsOtherReq{
Host: aucd.Host,
Token: aucd.Token,
Path: truePath,
Password: password,
Method: "video_preview",
})
if err != nil {
return err
if resp.ContentLength > subtitleMaxLength {
return nil, fmt.Errorf("subtitle too large, got: %d, max: %d", resp.ContentLength, subtitleMaxLength)
}
return io.ReadAll(io.LimitReader(resp.Body, subtitleMaxLength))
}
cache.Ali = &AlistAliCache{
M3U8ListFile: genAliM3U8ListFile(fo.VideoPreviewPlayInfo.LiveTranscodingTaskList),
}
cache.Subtitles = append(cache.Subtitles, newAliSubtitles(fo.VideoPreviewPlayInfo.LiveTranscodingSubtitleTaskList)...)
return nil
func processAliProvider(_ context.Context, firstURL string, cli alist.AlistHTTPServer, aucd *AlistUserCacheData, truePath, password string, cache *AlistMovieCacheData) {
cache.Ali = refreshcache0.NewRefreshCache(func(ctx context.Context) (*AlistAliCache, error) {
var url string
if firstURL != "" {
url = firstURL
firstURL = ""
} else {
u, err := cli.FsGet(ctx, &alist.FsGetReq{
Host: aucd.Host,
Token: aucd.Token,
Path: truePath,
Password: password,
})
if err != nil {
return nil, err
}
url = u.RawUrl
}
fo, err := cli.FsOther(ctx, &alist.FsOtherReq{
Host: aucd.Host,
Token: aucd.Token,
Path: truePath,
Password: password,
Method: "video_preview",
})
if err != nil {
return nil, err
}
return &AlistAliCache{
URL: url,
M3U8ListFile: genAliM3U8ListFile(fo.VideoPreviewPlayInfo.LiveTranscodingTaskList),
Subtitles: newAliSubtitles(fo.VideoPreviewPlayInfo.LiveTranscodingSubtitleTaskList),
}, nil
}, 14*time.Minute)
}

@ -46,7 +46,7 @@ func (m *Movie) ExpireID() uint64 {
case m.Movie.MovieBase.VendorInfo.Vendor == model.VendorAlist:
amcd, _ := m.AlistCache().Raw()
if amcd != nil && amcd.Ali != nil {
return uint64(m.AlistCache().Last())
return uint64(amcd.Ali.Last())
}
case m.Movie.MovieBase.Live && m.Movie.MovieBase.VendorInfo.Vendor == model.VendorBilibili:
return uint64(m.BilibiliCache().Live.Last())
@ -62,7 +62,7 @@ func (m *Movie) CheckExpired(expireID uint64) bool {
case m.Movie.MovieBase.VendorInfo.Vendor == model.VendorAlist:
amcd, _ := m.AlistCache().Raw()
if amcd != nil && amcd.Ali != nil {
return time.Now().UnixNano()-int64(expireID) > m.AlistCache().MaxAge()
return time.Now().UnixNano()-int64(amcd.Ali.Last()) > amcd.Ali.MaxAge()
}
case m.Movie.MovieBase.Live && m.Movie.MovieBase.VendorInfo.Vendor == model.VendorBilibili:
return time.Now().UnixNano()-int64(expireID) > m.BilibiliCache().Live.MaxAge()

@ -634,13 +634,6 @@ func ServeM3u8(ctx *gin.Context) {
return
}
if m.Movie.MovieBase.VendorInfo.Vendor != "" {
err := errors.New("vendor is not supported")
log.Errorf("get vendor service error: %v", err)
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorResp(err))
return
}
if m.Movie.MovieBase.RtmpSource {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("this movie is rtmp source, not support use this method proxy"))
return

@ -56,6 +56,42 @@ func NewM3u8TargetToken(targetURL, roomID, movieID string, isM3u8File bool) (str
const maxM3u8FileSize = 3 * 1024 * 1024 //
func M3u8Data(ctx *gin.Context, data []byte, baseURL string, token, roomID, movieID string) error {
hasM3u8File := false
err := m3u8.RangeM3u8SegmentsWithBaseURL(stream.BytesToString(data), baseURL, func(segmentUrl string) (bool, error) {
if utils.IsM3u8Url(segmentUrl) {
hasM3u8File = true
return false, nil
}
return true, nil
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest,
model.NewAPIErrorStringResp(
fmt.Sprintf("range m3u8 segments with base url error: %v", err),
),
)
return fmt.Errorf("range m3u8 segments with base url error: %w", err)
}
m3u8Str, err := m3u8.ReplaceM3u8SegmentsWithBaseURL(stream.BytesToString(data), baseURL, func(segmentUrl string) (string, error) {
targetToken, err := NewM3u8TargetToken(segmentUrl, roomID, movieID, hasM3u8File)
if err != nil {
return "", err
}
return fmt.Sprintf("/api/room/movie/proxy/%s/m3u8/%s?token=%s&roomId=%s", movieID, targetToken, token, roomID), nil
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest,
model.NewAPIErrorStringResp(
fmt.Sprintf("replace m3u8 segments with base url error: %v", err),
),
)
return fmt.Errorf("replace m3u8 segments with base url error: %w", err)
}
ctx.Data(http.StatusOK, hls.M3U8ContentType, stream.StringToBytes(m3u8Str))
return nil
}
// only cache non-m3u8 files
func M3u8(ctx *gin.Context, u string, headers map[string]string, isM3u8File bool, token, roomID, movieID string, opts ...Option) error {
if !isM3u8File {
@ -110,37 +146,5 @@ func M3u8(ctx *gin.Context, u string, headers map[string]string, isM3u8File bool
)
return fmt.Errorf("read response body error: %w", err)
}
hasM3u8File := false
err = m3u8.RangeM3u8SegmentsWithBaseURL(stream.BytesToString(b), u, func(segmentUrl string) (bool, error) {
if utils.IsM3u8Url(segmentUrl) {
hasM3u8File = true
return false, nil
}
return true, nil
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest,
model.NewAPIErrorStringResp(
fmt.Sprintf("range m3u8 segments with base url error: %v", err),
),
)
return fmt.Errorf("range m3u8 segments with base url error: %w", err)
}
m3u8Str, err := m3u8.ReplaceM3u8SegmentsWithBaseURL(stream.BytesToString(b), u, func(segmentUrl string) (string, error) {
targetToken, err := NewM3u8TargetToken(segmentUrl, roomID, movieID, hasM3u8File)
if err != nil {
return "", err
}
return fmt.Sprintf("/api/room/movie/proxy/%s/m3u8/%s?token=%s&roomId=%s", movieID, targetToken, token, roomID), nil
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest,
model.NewAPIErrorStringResp(
fmt.Sprintf("replace m3u8 segments with base url error: %v", err),
),
)
return fmt.Errorf("replace m3u8 segments with base url error: %w", err)
}
ctx.Data(http.StatusOK, hls.M3U8ContentType, stream.StringToBytes(m3u8Str))
return nil
return M3u8Data(ctx, b, u, token, roomID, movieID)
}

@ -266,7 +266,7 @@ func (c *SliceCacheProxy) fetchFromSource(offset int64) (*CacheItem, error) {
return nil, fmt.Errorf("failed to get content total length from source: %w", err)
}
if total != offset+int64(n) {
return nil, fmt.Errorf("source content total length mismatch, got: %d, expected: %d, %w", total, offset+int64(n), err)
return nil, fmt.Errorf("source content total length mismatch, got: %d, expected: %d, %w", total, offset+int64(n), io.ErrUnexpectedEOF)
}
}

@ -114,8 +114,8 @@ func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.U
func (s *AlistVendorService) ProxyMovie(ctx *gin.Context) {
log := ctx.MustGet("log").(*logrus.Entry)
// Get user and cache data
data, err := s.getUserAndCacheData(ctx)
// Get cache data
data, err := s.getCacheData(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
@ -133,7 +133,7 @@ func (s *AlistVendorService) ProxyMovie(ctx *gin.Context) {
}
}
func (s *AlistVendorService) getUserAndCacheData(ctx *gin.Context) (*cache.AlistMovieCacheData, error) {
func (s *AlistVendorService) getCacheData(ctx *gin.Context) (*cache.AlistMovieCacheData, error) {
u, err := op.LoadOrInitUserByID(s.movie.Movie.CreatorID)
if err != nil {
return nil, err
@ -154,21 +154,79 @@ func (s *AlistVendorService) handleAliProvider(ctx *gin.Context, log *logrus.Ent
t := ctx.Query("t")
switch t {
case "":
ctx.Data(http.StatusOK, "audio/mpegurl", data.Ali.M3U8ListFile)
b, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
if s.movie.Movie.MovieBase.Proxy {
err := proxy.M3u8Data(ctx, b.M3U8ListFile, "", ctx.GetString("token"), s.movie.RoomID, s.movie.ID)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
}
} else {
ctx.Data(http.StatusOK, "audio/mpegurl", b.M3U8ListFile)
}
case "raw":
s.proxyURL(ctx, log, data.URL)
b, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
if s.movie.Movie.MovieBase.Proxy {
s.proxyURL(ctx, log, b.URL)
} else {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
}
case "subtitle":
s.handleSubtitle(ctx, log, data)
s.handleAliSubtitle(ctx, log, data)
}
}
func (s *AlistVendorService) handleDefaultProvider(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
if !s.movie.Movie.MovieBase.Proxy {
log.Errorf("proxy vendor movie error: %v", "proxy is not enabled")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
t := ctx.Query("t")
switch t {
case "subtitle":
idS := ctx.Query("id")
if idS == "" {
log.Errorf("proxy vendor movie error: %v", "id is empty")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id is empty"))
return
}
id, err := strconv.Atoi(idS)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorResp(err))
return
}
if id >= len(data.Subtitles) {
log.Errorf("proxy vendor movie error: %v", "id out of range")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id out of range"))
return
}
subtitle := data.Subtitles[id]
b, err := subtitle.Cache.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
http.ServeContent(ctx.Writer, ctx.Request, subtitle.Name, time.Now(), bytes.NewReader(b))
default:
if !s.movie.Movie.MovieBase.Proxy {
log.Errorf("proxy vendor movie error: %v", "proxy is not enabled")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
}
s.proxyURL(ctx, log, data.URL)
}
s.proxyURL(ctx, log, data.URL)
}
func (s *AlistVendorService) proxyURL(ctx *gin.Context, log *logrus.Entry, url string) {
@ -186,7 +244,7 @@ func (s *AlistVendorService) proxyURL(ctx *gin.Context, log *logrus.Entry, url s
}
}
func (s *AlistVendorService) handleSubtitle(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
func (s *AlistVendorService) handleAliSubtitle(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
idS := ctx.Query("id")
if idS == "" {
log.Errorf("proxy vendor movie error: %v", "id is empty")
@ -201,20 +259,32 @@ func (s *AlistVendorService) handleSubtitle(ctx *gin.Context, log *logrus.Entry,
return
}
if id >= len(data.Subtitles) {
ali, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
var subtitle *cache.AlistSubtitle
if id < len(data.Subtitles) {
subtitle = data.Subtitles[id]
} else if id < len(data.Subtitles)+len(ali.Subtitles) {
subtitle = ali.Subtitles[id-len(data.Subtitles)]
} else {
log.Errorf("proxy vendor movie error: %v", "id out of range")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id out of range"))
return
}
b, err := data.Subtitles[id].Cache.Get(ctx)
b, err := subtitle.Cache.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
http.ServeContent(ctx.Writer, ctx.Request, data.Subtitles[id].Name, time.Now(), bytes.NewReader(b))
http.ServeContent(ctx.Writer, ctx.Request, subtitle.Name, time.Now(), bytes.NewReader(b))
}
func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, userAgent, userToken string) (*dbModel.Movie, error) {
@ -238,18 +308,22 @@ func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, us
return nil, err
}
for _, subt := range data.Subtitles {
for i, subt := range data.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: subt.URL,
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
Type: subt.Type,
}
}
switch data.Provider {
case cache.AlistProviderAli:
ali, err := data.Ali.Get(ctx)
if err != nil {
return nil, err
}
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "m3u8"
@ -262,12 +336,12 @@ func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, us
},
}
for i, subt := range data.Subtitles {
for i, subt := range ali.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, len(data.Subtitles)+i, userToken, movie.RoomID),
Type: subt.Type,
}
}
@ -314,18 +388,22 @@ func (s *AlistVendorService) GenProxyMovieInfo(ctx context.Context, user *op.Use
return nil, err
}
for _, subt := range data.Subtitles {
for i, subt := range data.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: subt.URL,
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
Type: subt.Type,
}
}
switch data.Provider {
case cache.AlistProviderAli:
ali, err := data.Ali.Get(ctx)
if err != nil {
return nil, err
}
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "m3u8"
@ -338,12 +416,12 @@ func (s *AlistVendorService) GenProxyMovieInfo(ctx context.Context, user *op.Use
},
}
for i, subt := range data.Subtitles {
for i, subt := range ali.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, len(data.Subtitles)+i, userToken, movie.RoomID),
Type: subt.Type,
}
}

@ -322,6 +322,7 @@ func (s *EmbyVendorService) GenProxyMovieInfo(ctx context.Context, user *op.User
&dbModel.MoreSource{
Name: es.Name,
URL: u.String(),
Type: utils.GetURLExtension(es.URL),
},
)
}

@ -114,8 +114,8 @@ func (s *AlistVendorService) ListDynamicMovie(ctx context.Context, reqUser *op.U
func (s *AlistVendorService) ProxyMovie(ctx *gin.Context) {
log := ctx.MustGet("log").(*logrus.Entry)
// Get user and cache data
data, err := s.getUserAndCacheData(ctx)
// Get cache data
data, err := s.getCacheData(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
@ -133,7 +133,7 @@ func (s *AlistVendorService) ProxyMovie(ctx *gin.Context) {
}
}
func (s *AlistVendorService) getUserAndCacheData(ctx *gin.Context) (*cache.AlistMovieCacheData, error) {
func (s *AlistVendorService) getCacheData(ctx *gin.Context) (*cache.AlistMovieCacheData, error) {
u, err := op.LoadOrInitUserByID(s.movie.Movie.CreatorID)
if err != nil {
return nil, err
@ -154,21 +154,79 @@ func (s *AlistVendorService) handleAliProvider(ctx *gin.Context, log *logrus.Ent
t := ctx.Query("t")
switch t {
case "":
ctx.Data(http.StatusOK, "audio/mpegurl", data.Ali.M3U8ListFile)
b, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
if s.movie.Movie.MovieBase.Proxy {
err := proxy.M3u8Data(ctx, b.M3U8ListFile, "", ctx.GetString("token"), s.movie.RoomID, s.movie.ID)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
}
} else {
ctx.Data(http.StatusOK, "audio/mpegurl", b.M3U8ListFile)
}
case "raw":
s.proxyURL(ctx, log, data.URL)
b, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
if s.movie.Movie.MovieBase.Proxy {
s.proxyURL(ctx, log, b.URL)
} else {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
}
case "subtitle":
s.handleSubtitle(ctx, log, data)
s.handleAliSubtitle(ctx, log, data)
}
}
func (s *AlistVendorService) handleDefaultProvider(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
if !s.movie.Movie.MovieBase.Proxy {
log.Errorf("proxy vendor movie error: %v", "proxy is not enabled")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
t := ctx.Query("t")
switch t {
case "subtitle":
idS := ctx.Query("id")
if idS == "" {
log.Errorf("proxy vendor movie error: %v", "id is empty")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id is empty"))
return
}
id, err := strconv.Atoi(idS)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorResp(err))
return
}
if id >= len(data.Subtitles) {
log.Errorf("proxy vendor movie error: %v", "id out of range")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id out of range"))
return
}
subtitle := data.Subtitles[id]
b, err := subtitle.Cache.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
http.ServeContent(ctx.Writer, ctx.Request, subtitle.Name, time.Now(), bytes.NewReader(b))
default:
if !s.movie.Movie.MovieBase.Proxy {
log.Errorf("proxy vendor movie error: %v", "proxy is not enabled")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("proxy is not enabled"))
return
}
s.proxyURL(ctx, log, data.URL)
}
s.proxyURL(ctx, log, data.URL)
}
func (s *AlistVendorService) proxyURL(ctx *gin.Context, log *logrus.Entry, url string) {
@ -186,7 +244,7 @@ func (s *AlistVendorService) proxyURL(ctx *gin.Context, log *logrus.Entry, url s
}
}
func (s *AlistVendorService) handleSubtitle(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
func (s *AlistVendorService) handleAliSubtitle(ctx *gin.Context, log *logrus.Entry, data *cache.AlistMovieCacheData) {
idS := ctx.Query("id")
if idS == "" {
log.Errorf("proxy vendor movie error: %v", "id is empty")
@ -201,20 +259,32 @@ func (s *AlistVendorService) handleSubtitle(ctx *gin.Context, log *logrus.Entry,
return
}
if id >= len(data.Subtitles) {
ali, err := data.Ali.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
var subtitle *cache.AlistSubtitle
if id < len(data.Subtitles) {
subtitle = data.Subtitles[id]
} else if id < len(data.Subtitles)+len(ali.Subtitles) {
subtitle = ali.Subtitles[id-len(data.Subtitles)]
} else {
log.Errorf("proxy vendor movie error: %v", "id out of range")
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewAPIErrorStringResp("id out of range"))
return
}
b, err := data.Subtitles[id].Cache.Get(ctx)
b, err := subtitle.Cache.Get(ctx)
if err != nil {
log.Errorf("proxy vendor movie error: %v", err)
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewAPIErrorResp(err))
return
}
http.ServeContent(ctx.Writer, ctx.Request, data.Subtitles[id].Name, time.Now(), bytes.NewReader(b))
http.ServeContent(ctx.Writer, ctx.Request, subtitle.Name, time.Now(), bytes.NewReader(b))
}
func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, userAgent, userToken string) (*dbModel.Movie, error) {
@ -238,18 +308,22 @@ func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, us
return nil, err
}
for _, subt := range data.Subtitles {
for i, subt := range data.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: subt.URL,
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
Type: subt.Type,
}
}
switch data.Provider {
case cache.AlistProviderAli:
ali, err := data.Ali.Get(ctx)
if err != nil {
return nil, err
}
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "m3u8"
@ -262,12 +336,12 @@ func (s *AlistVendorService) GenMovieInfo(ctx context.Context, user *op.User, us
},
}
for i, subt := range data.Subtitles {
for i, subt := range ali.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, len(data.Subtitles)+i, userToken, movie.RoomID),
Type: subt.Type,
}
}
@ -314,18 +388,22 @@ func (s *AlistVendorService) GenProxyMovieInfo(ctx context.Context, user *op.Use
return nil, err
}
for _, subt := range data.Subtitles {
for i, subt := range data.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: subt.URL,
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
Type: subt.Type,
}
}
switch data.Provider {
case cache.AlistProviderAli:
ali, err := data.Ali.Get(ctx)
if err != nil {
return nil, err
}
movie.MovieBase.URL = fmt.Sprintf("/api/room/movie/proxy/%s?token=%s&roomId=%s", movie.ID, userToken, movie.RoomID)
movie.MovieBase.Type = "m3u8"
@ -338,12 +416,12 @@ func (s *AlistVendorService) GenProxyMovieInfo(ctx context.Context, user *op.Use
},
}
for i, subt := range data.Subtitles {
for i, subt := range ali.Subtitles {
if movie.MovieBase.Subtitles == nil {
movie.MovieBase.Subtitles = make(map[string]*dbModel.Subtitle, len(data.Subtitles))
}
movie.MovieBase.Subtitles[subt.Name] = &dbModel.Subtitle{
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, i, userToken, movie.RoomID),
URL: fmt.Sprintf("/api/room/movie/proxy/%s?t=subtitle&id=%d&token=%s&roomId=%s", movie.ID, len(data.Subtitles)+i, userToken, movie.RoomID),
Type: subt.Type,
}
}

@ -322,6 +322,7 @@ func (s *EmbyVendorService) GenProxyMovieInfo(ctx context.Context, user *op.User
&dbModel.MoreSource{
Name: es.Name,
URL: u.String(),
Type: utils.GetURLExtension(es.URL),
},
)
}

Loading…
Cancel
Save