From e568218c145d79ccbc824fdc66b0ac446f89b894 Mon Sep 17 00:00:00 2001 From: zijiren233 Date: Thu, 18 Apr 2024 12:26:13 +0800 Subject: [PATCH] Fix: alist 115 drive --- go.mod | 2 +- go.sum | 2 + internal/cache/alist.go | 43 +++++++++++----- server/handlers/movie.go | 107 ++++++++++++++++++++++++++------------- 4 files changed, 106 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index b79ae710..fbd91103 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.8.0 - github.com/synctv-org/vendors v0.3.3-0.20240416113343-ddc34bc4b8bb + github.com/synctv-org/vendors v0.3.3-0.20240418030630-39789ec55bd2 github.com/ulule/limiter/v3 v3.11.2 github.com/zencoder/go-dash/v3 v3.0.3 github.com/zijiren233/gencontainer v0.0.0-20240331174346-b5e420773df7 diff --git a/go.sum b/go.sum index df73ce40..19642a09 100644 --- a/go.sum +++ b/go.sum @@ -392,6 +392,8 @@ github.com/synctv-org/vendors v0.3.3-0.20240415060029-ef65de81bf8a h1:ikBOrImiBE github.com/synctv-org/vendors v0.3.3-0.20240415060029-ef65de81bf8a/go.mod h1:WlKzamZ0Nfim/8983x9EQLN1FuxbNS8+n9yTSmMIO+8= github.com/synctv-org/vendors v0.3.3-0.20240416113343-ddc34bc4b8bb h1:PbwjtwbhlaGBtbu4fFtnLB1FsAv5sDqeZ7k6szQ0TIA= github.com/synctv-org/vendors v0.3.3-0.20240416113343-ddc34bc4b8bb/go.mod h1:ysM3NZawuFF+zTwc1Qz70UcHA0b5uE0aIsrSvHybowE= +github.com/synctv-org/vendors v0.3.3-0.20240418030630-39789ec55bd2 h1:ReE/Mz7Ycipo70yRn1DbMCXfq+dgTHLj3Rqugnit1lU= +github.com/synctv-org/vendors v0.3.3-0.20240418030630-39789ec55bd2/go.mod h1:ysM3NZawuFF+zTwc1Qz70UcHA0b5uE0aIsrSvHybowE= github.com/tetratelabs/wazero v1.7.0 h1:jg5qPydno59wqjpGrHph81lbtHzTrWzwwtD4cD88+hQ= github.com/tetratelabs/wazero v1.7.0/go.mod h1:ytl6Zuh20R/eROuyDaGPkp82O9C/DJfXAwJfQ3X6/7Y= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= diff --git a/internal/cache/alist.go b/internal/cache/alist.go index 2ec2f878..c44b8602 100644 --- a/internal/cache/alist.go +++ b/internal/cache/alist.go @@ -76,15 +76,23 @@ func AlistAuthorizationCacheWithConfigInitFunc(ctx context.Context, v *model.Ali } } -type AlistMovieCache = refreshcache.RefreshCache[*AlistMovieCacheData, *AlistUserCache] +type AlistMovieCache = refreshcache.RefreshCache[*AlistMovieCacheData, *AlistMovieCacheFuncArgs] func NewAlistMovieCache(movie *model.Movie) *AlistMovieCache { return refreshcache.NewRefreshCache(NewAlistMovieCacheInitFunc(movie), time.Minute*14) } +type AlistProvider = string + +const ( + AlistProviderAli = "AliyundriveOpen" + AlistProvider115 = "115 Cloud" +) + type AlistMovieCacheData struct { - URL string - Ali *AlistAliCache + URL string + Provider string + Ali *AlistAliCache } type AlistAliCache struct { @@ -142,11 +150,20 @@ func genAliM3U8ListFile(urls []*alist.FsOtherResp_VideoPreviewPlayInfo_LiveTrans return buf.Bytes() } -func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, args ...*AlistUserCache) (*AlistMovieCacheData, error) { - return func(ctx context.Context, args ...*AlistUserCache) (*AlistMovieCacheData, error) { +type AlistMovieCacheFuncArgs struct { + UserCache *AlistUserCache + UserAgent string +} + +func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, args ...*AlistMovieCacheFuncArgs) (*AlistMovieCacheData, error) { + return func(ctx context.Context, args ...*AlistMovieCacheFuncArgs) (*AlistMovieCacheData, error) { if len(args) == 0 { return nil, errors.New("need alist user cache") } + userCache := args[0].UserCache + if userCache == nil { + return nil, errors.New("need alist user cache") + } var ( serverID string err error @@ -156,7 +173,7 @@ func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, ar if err != nil { return nil, err } - aucd, err := args[0].LoadOrStore(ctx, serverID) + aucd, err := userCache.LoadOrStore(ctx, serverID) if err != nil { return nil, err } @@ -165,10 +182,11 @@ func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, ar } cli := vendor.LoadAlistClient(movie.Base.VendorInfo.Backend) fg, err := cli.FsGet(ctx, &alist.FsGetReq{ - Host: aucd.Host, - Token: aucd.Token, - Path: truePath, - Password: movie.Base.VendorInfo.Alist.Password, + Host: aucd.Host, + Token: aucd.Token, + Path: truePath, + Password: movie.Base.VendorInfo.Alist.Password, + UserAgent: args[0].UserAgent, }) if err != nil { return nil, err @@ -179,9 +197,10 @@ func NewAlistMovieCacheInitFunc(movie *model.Movie) func(ctx context.Context, ar } cache := &AlistMovieCacheData{ - URL: fg.RawUrl, + URL: fg.RawUrl, + Provider: fg.Provider, } - if fg.Provider == "AliyundriveOpen" { + if fg.Provider == AlistProviderAli { fo, err := cli.FsOther(ctx, &alist.FsOtherReq{ Host: aucd.Host, Token: aucd.Token, diff --git a/server/handlers/movie.go b/server/handlers/movie.go index cf8c1e90..7ca4422d 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -18,6 +18,7 @@ import ( "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" + "github.com/synctv-org/synctv/internal/cache" "github.com/synctv-org/synctv/internal/conf" dbModel "github.com/synctv-org/synctv/internal/model" "github.com/synctv-org/synctv/internal/op" @@ -81,17 +82,13 @@ func GetPageItems[T any](ctx *gin.Context, items []T) ([]T, error) { // })) // } -func genCurrentResp(ctx context.Context, user *op.User, room *op.Room) (*model.CurrentMovieResp, error) { - return genCurrentRespWithCurrent(ctx, user, room, room.Current()) -} - -func genCurrentMovieInfo(ctx context.Context, user *op.User, room *op.Room, opMovie *op.Movie) (*model.MovieResp, error) { +func genMovieInfo(ctx context.Context, user *op.User, room *op.Room, opMovie *op.Movie, userAgent string) (*model.MovieResp, error) { if opMovie == nil || opMovie.ID == "" { return &model.MovieResp{}, nil } var movie = *opMovie.Movie if movie.Base.VendorInfo.Vendor != "" { - vendorMovie, err := genVendorMovie(ctx, user, opMovie) + vendorMovie, err := genVendorMovie(ctx, user, opMovie, userAgent) if err != nil { return nil, err } @@ -123,7 +120,7 @@ func genCurrentMovieInfo(ctx context.Context, user *op.User, room *op.Room, opMo return resp, nil } -func genCurrentRespWithCurrent(ctx context.Context, user *op.User, room *op.Room, current *op.Current) (*model.CurrentMovieResp, error) { +func genCurrentRespWithCurrent(ctx context.Context, user *op.User, room *op.Room, current *op.Current, userAgent string) (*model.CurrentMovieResp, error) { if current.MovieID == "" { return &model.CurrentMovieResp{ Movie: &model.MovieResp{}, @@ -133,7 +130,7 @@ func genCurrentRespWithCurrent(ctx context.Context, user *op.User, room *op.Room if err != nil { return nil, fmt.Errorf("get current movie error: %w", err) } - mr, err := genCurrentMovieInfo(ctx, user, room, opMovie) + mr, err := genMovieInfo(ctx, user, room, opMovie, userAgent) if err != nil { return nil, fmt.Errorf("gen current movie info error: %w", err) } @@ -150,7 +147,7 @@ func CurrentMovie(ctx *gin.Context) { user := ctx.MustGet("user").(*op.UserEntry).Value() log := ctx.MustGet("log").(*logrus.Entry) - currentResp, err := genCurrentResp(ctx, user, room) + currentResp, err := genCurrentRespWithCurrent(ctx, user, room, room.Current(), ctx.GetHeader("User-Agent")) if err != nil { log.Errorf("gen current resp error: %v", err) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) @@ -939,17 +936,21 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - alistC, err := movie.AlistCache().Get(ctx, u.Value().AlistCache()) + data, err := movie.AlistCache().Get(ctx, &cache.AlistMovieCacheFuncArgs{ + UserCache: u.Value().AlistCache(), + UserAgent: utils.UA, + }) if err != nil { log.Errorf("proxy vendor movie error: %v", err) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } - if alistC.Ali != nil { + switch data.Provider { + case cache.AlistProviderAli: t := ctx.Query("t") switch t { case "": - ctx.Data(http.StatusOK, "audio/mpegurl", alistC.Ali.M3U8ListFile) + ctx.Data(http.StatusOK, "audio/mpegurl", data.Ali.M3U8ListFile) return case "subtitle": idS := ctx.Query("id") @@ -964,12 +965,12 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err)) return } - if id >= len(alistC.Ali.Subtitles) { + if id >= len(data.Ali.Subtitles) { log.Errorf("proxy vendor movie error: %v", "id out of range") ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("id out of range")) return } - data, err := alistC.Ali.Subtitles[id].Cache.Get(ctx) + data, err := data.Ali.Subtitles[id].Cache.Get(ctx) if err != nil { log.Errorf("proxy vendor movie error: %v", err) ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) @@ -977,15 +978,21 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { } ctx.Data(http.StatusOK, "text/plain; charset=utf-8", data) } - } else if !movie.Movie.Base.Proxy { - log.Errorf("proxy vendor movie error: %v", "not support movie proxy") - ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support movie proxy")) - return - } else { - err = proxyURL(ctx, alistC.URL, nil) - if err != nil { - log.Errorf("proxy vendor movie error: %v", err) + + case cache.AlistProvider115: + fallthrough + default: + if !movie.Movie.Base.Proxy { + log.Errorf("proxy vendor movie error: %v", "not support movie proxy") + ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("not support movie proxy")) + return + } else { + err = proxyURL(ctx, data.URL, nil) + if err != nil { + log.Errorf("proxy vendor movie error: %v", err) + } } + } return @@ -1092,7 +1099,7 @@ func proxyVendorMovie(ctx *gin.Context, movie *op.Movie) { } // user is the api requester -func genVendorMovie(ctx context.Context, user *op.User, opMovie *op.Movie) (*dbModel.Movie, error) { +func genVendorMovie(ctx context.Context, user *op.User, opMovie *op.Movie, userAgent string) (*dbModel.Movie, error) { movie := *opMovie.Movie var err error switch movie.Base.VendorInfo.Vendor { @@ -1152,12 +1159,17 @@ func genVendorMovie(ctx context.Context, user *op.User, opMovie *op.Movie) (*dbM if err != nil { return nil, err } - data, err := opMovie.AlistCache().Get(ctx, creator.Value().AlistCache()) + alistCache := opMovie.AlistCache() + data, err := alistCache.Get(ctx, &cache.AlistMovieCacheFuncArgs{ + UserCache: creator.Value().AlistCache(), + UserAgent: utils.UA, + }) if err != nil { return nil, err } - if data.Ali != nil { + switch data.Provider { + case cache.AlistProviderAli: rawPath, err := url.JoinPath("/api/movie/proxy", movie.RoomID, movie.ID) if err != nil { return nil, err @@ -1177,19 +1189,44 @@ func genVendorMovie(ctx context.Context, user *op.User, opMovie *op.Movie) (*dbM Type: utils.GetUrlExtension(s.Raw.Url), } } - } else if !movie.Base.Proxy { - movie.Base.Url = data.URL - } else { - rawPath, err := url.JoinPath("/api/movie/proxy", movie.RoomID, movie.ID) - if err != nil { - return nil, err + case cache.AlistProvider115: + if movie.Base.Proxy { + rawPath, err := url.JoinPath("/api/movie/proxy", movie.RoomID, movie.ID) + if err != nil { + return nil, err + } + u := url.URL{ + Path: rawPath, + } + movie.Base.Url = u.String() + movie.Base.Type = utils.GetUrlExtension(data.URL) + } else { + data, err = alistCache.GetRefreshFunc()(ctx, &cache.AlistMovieCacheFuncArgs{ + UserCache: creator.Value().AlistCache(), + UserAgent: userAgent, + }) + if err != nil { + return nil, fmt.Errorf("refresh 115 movie cache error: %w", err) + } + movie.Base.Url = data.URL } - u := url.URL{ - Path: rawPath, + + default: + if !movie.Base.Proxy { + movie.Base.Url = data.URL + } else { + rawPath, err := url.JoinPath("/api/movie/proxy", movie.RoomID, movie.ID) + if err != nil { + return nil, err + } + u := url.URL{ + Path: rawPath, + } + movie.Base.Url = u.String() + movie.Base.Type = utils.GetUrlExtension(data.URL) } - movie.Base.Url = u.String() - movie.Base.Type = utils.GetUrlExtension(data.URL) } + movie.Base.VendorInfo.Alist.Password = "" return &movie, nil