diff --git a/internal/op/movie.go b/internal/op/movie.go index 05e2d6b..e9fbf7f 100644 --- a/internal/op/movie.go +++ b/internal/op/movie.go @@ -2,6 +2,7 @@ package op import ( "errors" + "fmt" "net/url" "sync" "time" @@ -30,6 +31,10 @@ func (m *movie) Channel() (*rtmps.Channel, error) { } func (m *movie) init() (err error) { + err = m.validateVendorMovie() + if err != nil { + return + } switch { case m.Base.RtmpSource && m.Base.Proxy: return errors.New("rtmp source and proxy can't be true at the same time") @@ -142,6 +147,73 @@ func (m *movie) init() (err error) { return nil } +func (m *movie) validateVendorMovie() (err error) { + if m.Base.VendorInfo.Vendor == "" { + return + } + switch m.Base.VendorInfo.Vendor { + case model.StreamingVendorBilibili: + info := map[string]any{} + bvidI := m.Base.VendorInfo.Info["bvid"] + epIdI := m.Base.VendorInfo.Info["epId"] + if bvidI != nil && epIdI != nil { + return fmt.Errorf("bvid(%v) and epId(%v) can't be used at the same time", bvidI, epIdI) + } + + if bvidI != nil { + bvid, ok := bvidI.(string) + if !ok { + return fmt.Errorf("bvid is not string") + } + info["bvid"] = bvid + } else if epIdI != nil { + epId, ok := epIdI.(float64) + if !ok { + return fmt.Errorf("epId is not number") + } + info["epId"] = epId + } else { + return fmt.Errorf("bvid and epId is empty") + } + + qnI, ok := m.Base.VendorInfo.Info["qn"] + if ok { + qn, ok := qnI.(float64) + if !ok { + return fmt.Errorf("qn is not number") + } + info["qn"] = qn + } + + if bvidI != nil { + cidI := m.Base.VendorInfo.Info["cid"] + if cidI == nil { + return fmt.Errorf("cid is empty") + } + cid, ok := cidI.(float64) + if !ok { + return fmt.Errorf("cid is not number") + } + info["cid"] = cid + + m.Base.Url = "" + m.Base.Proxy = false + m.Base.RtmpSource = false + m.Base.VendorInfo.Info = info + return nil + } else { + m.Base.Url = "" + m.Base.RtmpSource = false + m.Base.Proxy = true + m.Base.VendorInfo.Info = info + return nil + } + + default: + return fmt.Errorf("vendor not support") + } +} + func (m *movie) Terminate() { m.lock.Lock() defer m.lock.Unlock() diff --git a/server/handlers/movie.go b/server/handlers/movie.go index 2bcc4d0..1dbecff 100644 --- a/server/handlers/movie.go +++ b/server/handlers/movie.go @@ -550,9 +550,9 @@ func ProxyVendorMovie(ctx *gin.Context, m *dbModel.Movie) { var ( bvid string epId float64 - cid float64 ok bool ) + if bvidI != nil { bvid, ok = bvidI.(string) if !ok { @@ -570,17 +570,6 @@ func ProxyVendorMovie(ctx *gin.Context, m *dbModel.Movie) { return } - cidI := m.Base.VendorInfo.Info["cid"] - if cidI == nil { - ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cid is empty")) - return - } - cid, ok = cidI.(float64) - if !ok { - ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cid is not number")) - return - } - vendor, err := db.AssignFirstOrCreateVendorByUserIDAndVendor(m.CreatorID, dbModel.StreamingVendorBilibili) if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) @@ -590,14 +579,25 @@ func ProxyVendorMovie(ctx *gin.Context, m *dbModel.Movie) { var mu *bilibili.VideoURL if bvid != "" { + cidI := m.Base.VendorInfo.Info["cid"] + if cidI == nil { + ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cid is empty")) + return + } + cid, ok := cidI.(float64) + if !ok { + ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("cid is not number")) + return + } mu, err = cli.GetVideoURL(0, bvid, uint(cid)) } else { - mu, err = cli.GetPGCURL(uint(epId), uint(cid)) + mu, err = cli.GetPGCURL(uint(epId), 0) } if err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) return } + hrs := proxy.NewBufferedHttpReadSeeker(128*1024, mu.URL, proxy.WithContext(ctx), proxy.WithAppendHeaders(map[string]string{ @@ -628,10 +628,9 @@ func parse2VendorMovie(user *op.User, movie *dbModel.Movie) (err error) { var ( bvid string - // epId float64 - cid float64 - ok bool + ok bool ) + if bvidI != nil { bvid, ok = bvidI.(string) if !ok { @@ -642,46 +641,44 @@ func parse2VendorMovie(user *op.User, movie *dbModel.Movie) (err error) { if !ok { return fmt.Errorf("epId is not number") } + return } else { return fmt.Errorf("bvid and epId is empty") } + id := user.ID + if movie.Base.VendorInfo.Shared { + id = movie.CreatorID + } + vendor, err := db.AssignFirstOrCreateVendorByUserIDAndVendor(id, dbModel.StreamingVendorBilibili) + if err != nil { + return err + } + cli := bilibili.NewClient(vendor.Cookies) + var qn float64 = float64(bilibili.Q1080PP) + qnI, ok := movie.Base.VendorInfo.Info["qn"] + if ok { + qn, ok = qnI.(float64) + if !ok { + return fmt.Errorf("qn is not number") + } + } + cidI := movie.Base.VendorInfo.Info["cid"] if cidI == nil { return fmt.Errorf("cid is empty") } - cid, ok = cidI.(float64) + cid, ok := cidI.(float64) if !ok { return fmt.Errorf("cid is not number") } - if bvid != "" { - id := user.ID - if movie.Base.VendorInfo.Shared { - id = movie.CreatorID - } - vendor, err := db.AssignFirstOrCreateVendorByUserIDAndVendor(id, dbModel.StreamingVendorBilibili) - if err != nil { - return err - } - cli := bilibili.NewClient(vendor.Cookies) - var qn float64 = float64(bilibili.Q1080PP) - qnI, ok := movie.Base.VendorInfo.Info["qn"] - if ok { - qn, ok = qnI.(float64) - if !ok { - return fmt.Errorf("qn is not number") - } - } - mu, err := cli.GetVideoURL(0, bvid, uint(cid), bilibili.WithQuality(uint(qn))) - if err != nil { - return err - } - movie.Base.Url = mu.URL - return nil - } else { - return nil + mu, err := cli.GetVideoURL(0, bvid, uint(cid), bilibili.WithQuality(uint(qn))) + if err != nil { + return err } + movie.Base.Url = mu.URL + return nil default: return fmt.Errorf("vendor not support") diff --git a/vendors/bilibili/movie.go b/vendors/bilibili/movie.go index 6cb61af..79c3060 100644 --- a/vendors/bilibili/movie.go +++ b/vendors/bilibili/movie.go @@ -233,7 +233,16 @@ func (c *Client) GetPGCURL(ep_id, cid uint, conf ...GetVideoURLConfig) (*VideoUR for _, v := range conf { v(config) } - url := fmt.Sprintf("https://api.bilibili.com/pgc/player/web/playurl?ep_id=%d&cid=%d&qn=%d&fourk=1&fnval=0", ep_id, cid, config.Quality) + + var url string + if ep_id != 0 { + url = fmt.Sprintf("https://api.bilibili.com/pgc/player/web/playurl?ep_id=%d&qn=%d&fourk=1&fnval=0", ep_id, config.Quality) + } else if cid != 0 { + url = fmt.Sprintf("https://api.bilibili.com/pgc/player/web/playurl?cid=%d&qn=%d&fourk=1&fnval=0", cid, config.Quality) + } else { + return nil, fmt.Errorf("edId and season_id are both empty") + } + req, err := c.NewRequest(http.MethodGet, url, nil) if err != nil { return nil, err