You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
synctv/server/handlers/vendors/vendorBilibili/bilibili.go

143 lines
3.9 KiB
Go

package vendorBilibili
import (
"errors"
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/db"
"github.com/synctv-org/synctv/internal/op"
"github.com/synctv-org/synctv/internal/vendor"
"github.com/synctv-org/synctv/server/model"
"github.com/synctv-org/synctv/utils"
"github.com/synctv-org/vendors/api/bilibili"
)
type ParseReq struct {
URL string `json:"url"`
}
func (r *ParseReq) Validate() error {
if r.URL == "" {
return errors.New("url is empty")
}
return nil
}
func (r *ParseReq) Decode(ctx *gin.Context) error {
return json.NewDecoder(ctx.Request.Body).Decode(r)
}
func Parse(ctx *gin.Context) {
user := ctx.MustGet("user").(*op.UserEntry).Value()
req := ParseReq{}
if err := model.Decode(ctx, &req); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
var cli = vendor.LoadBilibiliClient(ctx.Query("backend"))
resp, err := cli.Match(ctx, &bilibili.MatchReq{
Url: req.URL,
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
// can be no login
var cookies []*http.Cookie
bucd, err := user.BilibiliCache().Get(ctx)
if err != nil {
if !errors.Is(err, db.ErrNotFound("vendor")) {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
} else {
cookies = bucd.Cookies
}
switch resp.Type {
case "bv":
resp, err := cli.ParseVideoPage(ctx, &bilibili.ParseVideoPageReq{
Cookies: utils.HttpCookieToMap(cookies),
Bvid: resp.Id,
Sections: ctx.DefaultQuery("sections", "false") == "true",
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))
case "av":
aid, err := strconv.ParseUint(resp.Id, 10, 64)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
resp, err := cli.ParseVideoPage(ctx, &bilibili.ParseVideoPageReq{
Cookies: utils.HttpCookieToMap(cookies),
Aid: aid,
Sections: ctx.DefaultQuery("sections", "false") == "true",
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))
case "ep":
epid, err := strconv.ParseUint(resp.Id, 10, 64)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
resp, err := cli.ParsePGCPage(ctx, &bilibili.ParsePGCPageReq{
Cookies: utils.HttpCookieToMap(cookies),
Epid: epid,
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))
case "ss":
ssid, err := strconv.ParseUint(resp.Id, 10, 64)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
resp, err := cli.ParsePGCPage(ctx, &bilibili.ParsePGCPageReq{
Cookies: utils.HttpCookieToMap(cookies),
Ssid: ssid,
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))
case "live":
roomid, err := strconv.ParseUint(resp.Id, 10, 64)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err))
return
}
resp, err := cli.ParseLivePage(ctx, &bilibili.ParseLivePageReq{
// Cookies: utils.HttpCookieToMap(cookies), // maybe no need login
RoomID: roomid,
})
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
}
ctx.JSON(http.StatusOK, model.NewApiDataResp(resp))
default:
ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorStringResp(fmt.Sprintf("unknown match type %s", resp.Type)))
return
}
}