diff --git a/server/handlers/init.go b/server/handlers/init.go index 686c371..eb8bf90 100644 --- a/server/handlers/init.go +++ b/server/handlers/init.go @@ -152,6 +152,8 @@ func Init(e *gin.Engine) { bilibili.POST("/login", Vbilibili.Login) bilibili.POST("/parse", Vbilibili.Parse) + + bilibili.GET("/me", Vbilibili.Me) } } } diff --git a/server/handlers/vendors/bilibili/me.go b/server/handlers/vendors/bilibili/me.go new file mode 100644 index 0000000..756c102 --- /dev/null +++ b/server/handlers/vendors/bilibili/me.go @@ -0,0 +1,40 @@ +package Vbilibili + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/synctv-org/synctv/internal/db" + dbModel "github.com/synctv-org/synctv/internal/model" + "github.com/synctv-org/synctv/internal/op" + "github.com/synctv-org/synctv/server/model" + "github.com/synctv-org/synctv/vendors/bilibili" +) + +type MeResp struct { + IsLogin bool `json:"isLogin"` + Username string `json:"username"` + Face string `json:"face"` + IsVip bool `json:"isVip"` +} + +func Me(ctx *gin.Context) { + user := ctx.MustGet("user").(*op.User) + vendor, err := db.FirstOrCreateVendorByUserIDAndVendor(user.ID, dbModel.StreamingVendorBilibili) + if err != nil { + ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) + return + } + cli := bilibili.NewClient(vendor.Cookies) + nav, err := cli.UserInfo() + if err != nil { + ctx.AbortWithStatusJSON(http.StatusInternalServerError, model.NewApiErrorResp(err)) + return + } + ctx.JSON(http.StatusOK, model.NewApiDataResp(MeResp{ + IsLogin: nav.Data.IsLogin, + Username: nav.Data.Uname, + Face: nav.Data.Face, + IsVip: nav.Data.VipStatus == 1, + })) +} diff --git a/vendors/bilibili/bilibili.go b/vendors/bilibili/bilibili.go index 70e546c..bf467d8 100644 --- a/vendors/bilibili/bilibili.go +++ b/vendors/bilibili/bilibili.go @@ -813,15 +813,111 @@ type pgcURLInfo struct { } `json:"result"` } -type wbi struct { +type Nav struct { Code int `json:"code"` Message string `json:"message"` TTL int `json:"ttl"` Data struct { - IsLogin bool `json:"isLogin"` - WbiImg struct { + IsLogin bool `json:"isLogin"` + EmailVerified int `json:"email_verified"` + Face string `json:"face"` + FaceNft int `json:"face_nft"` + FaceNftType int `json:"face_nft_type"` + LevelInfo struct { + CurrentLevel int `json:"current_level"` + CurrentMin int `json:"current_min"` + CurrentExp int `json:"current_exp"` + NextExp string `json:"next_exp"` + } `json:"level_info"` + Mid int `json:"mid"` + MobileVerified int `json:"mobile_verified"` + Money int `json:"money"` + Moral int `json:"moral"` + Official struct { + Role int `json:"role"` + Title string `json:"title"` + Desc string `json:"desc"` + Type int `json:"type"` + } `json:"official"` + OfficialVerify struct { + Type int `json:"type"` + Desc string `json:"desc"` + } `json:"officialVerify"` + Pendant struct { + Pid int `json:"pid"` + Name string `json:"name"` + Image string `json:"image"` + Expire int `json:"expire"` + ImageEnhance string `json:"image_enhance"` + ImageEnhanceFrame string `json:"image_enhance_frame"` + NPid int `json:"n_pid"` + } `json:"pendant"` + Scores int `json:"scores"` + Uname string `json:"uname"` + VipDueDate int64 `json:"vipDueDate"` + VipStatus int `json:"vipStatus"` + VipType int `json:"vipType"` + VipPayType int `json:"vip_pay_type"` + VipThemeType int `json:"vip_theme_type"` + VipLabel struct { + Path string `json:"path"` + Text string `json:"text"` + LabelTheme string `json:"label_theme"` + TextColor string `json:"text_color"` + BgStyle int `json:"bg_style"` + BgColor string `json:"bg_color"` + BorderColor string `json:"border_color"` + UseImgLabel bool `json:"use_img_label"` + ImgLabelURIHans string `json:"img_label_uri_hans"` + ImgLabelURIHant string `json:"img_label_uri_hant"` + ImgLabelURIHansStatic string `json:"img_label_uri_hans_static"` + ImgLabelURIHantStatic string `json:"img_label_uri_hant_static"` + } `json:"vip_label"` + VipAvatarSubscript int `json:"vip_avatar_subscript"` + VipNicknameColor string `json:"vip_nickname_color"` + Vip struct { + Type int `json:"type"` + Status int `json:"status"` + DueDate int64 `json:"due_date"` + VipPayType int `json:"vip_pay_type"` + ThemeType int `json:"theme_type"` + Label struct { + Path string `json:"path"` + Text string `json:"text"` + LabelTheme string `json:"label_theme"` + TextColor string `json:"text_color"` + BgStyle int `json:"bg_style"` + BgColor string `json:"bg_color"` + BorderColor string `json:"border_color"` + UseImgLabel bool `json:"use_img_label"` + ImgLabelURIHans string `json:"img_label_uri_hans"` + ImgLabelURIHant string `json:"img_label_uri_hant"` + ImgLabelURIHansStatic string `json:"img_label_uri_hans_static"` + ImgLabelURIHantStatic string `json:"img_label_uri_hant_static"` + } `json:"label"` + AvatarSubscript int `json:"avatar_subscript"` + NicknameColor string `json:"nickname_color"` + Role int `json:"role"` + AvatarSubscriptURL string `json:"avatar_subscript_url"` + TvVipStatus int `json:"tv_vip_status"` + TvVipPayType int `json:"tv_vip_pay_type"` + TvDueDate int `json:"tv_due_date"` + } `json:"vip"` + Wallet struct { + Mid int `json:"mid"` + BcoinBalance int `json:"bcoin_balance"` + CouponBalance int `json:"coupon_balance"` + CouponDueTime int `json:"coupon_due_time"` + } `json:"wallet"` + HasShop bool `json:"has_shop"` + ShopURL string `json:"shop_url"` + AllowanceCount int `json:"allowance_count"` + AnswerStatus int `json:"answer_status"` + IsSeniorMember int `json:"is_senior_member"` + WbiImg struct { ImgURL string `json:"img_url"` SubURL string `json:"sub_url"` } `json:"wbi_img"` + IsJury bool `json:"is_jury"` } `json:"data"` } diff --git a/vendors/bilibili/client.go b/vendors/bilibili/client.go index 565e4c4..b8b0131 100644 --- a/vendors/bilibili/client.go +++ b/vendors/bilibili/client.go @@ -31,12 +31,36 @@ func NewClient(cookies []*http.Cookie, conf ...ClientConfig) *Client { return c } -func (c *Client) NewRequest(method, url string, body io.Reader) (*http.Request, error) { - url, err := signAndGenerateURL(url) - if err != nil { - return nil, err +type RequestConfig struct { + wbi bool +} + +func defaultRequestConfig() *RequestConfig { + return &RequestConfig{ + wbi: true, + } +} + +type RequestOption func(*RequestConfig) + +func WithoutWbi() RequestOption { + return func(c *RequestConfig) { + c.wbi = false + } +} + +func (c *Client) NewRequest(method, url string, body io.Reader, conf ...RequestOption) (req *http.Request, err error) { + config := defaultRequestConfig() + for _, v := range conf { + v(config) + } + if config.wbi { + url, err = signAndGenerateURL(url) + if err != nil { + return nil, err + } } - req, err := http.NewRequest(method, url, body) + req, err = http.NewRequest(method, url, body) if err != nil { return nil, err } diff --git a/vendors/bilibili/user.go b/vendors/bilibili/user.go new file mode 100644 index 0000000..9dedae3 --- /dev/null +++ b/vendors/bilibili/user.go @@ -0,0 +1,24 @@ +package bilibili + +import ( + "net/http" + + json "github.com/json-iterator/go" +) + +func (c *Client) UserInfo() (*Nav, error) { + req, err := c.NewRequest(http.MethodGet, "https://api.bilibili.com/x/web-interface/nav", nil, WithoutWbi()) + if err != nil { + return nil, err + } + resp, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + var nav Nav + err = json.NewDecoder(resp.Body).Decode(&nav) + if err != nil { + return nil, err + } + return &nav, nil +} diff --git a/vendors/bilibili/wbi.go b/vendors/bilibili/wbi.go index 628ef31..3b2bc84 100644 --- a/vendors/bilibili/wbi.go +++ b/vendors/bilibili/wbi.go @@ -127,7 +127,7 @@ func getWbiKeys() (string, string, error) { return "", "", err } defer resp.Body.Close() - info := wbi{} + info := Nav{} err = json.NewDecoder(resp.Body).Decode(&info) if err != nil { return "", "", err