mirror of https://github.com/synctv-org/synctv
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.
177 lines
3.7 KiB
Go
177 lines
3.7 KiB
Go
package aggregations
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
json "github.com/json-iterator/go"
|
|
"github.com/synctv-org/synctv/internal/provider"
|
|
"github.com/zijiren233/go-uhc"
|
|
)
|
|
|
|
var _ provider.AggregationProviderInterface = (*Rainbow)(nil)
|
|
|
|
const DefaultRainbowAPI = "https://u.cccyun.cc"
|
|
|
|
type Rainbow struct {
|
|
api string
|
|
}
|
|
|
|
func (r *Rainbow) SetAPI(api string) {
|
|
r.api = api
|
|
}
|
|
|
|
func (r *Rainbow) Provider() provider.OAuth2Provider {
|
|
return "rainbow"
|
|
}
|
|
|
|
func (r *Rainbow) Providers() []provider.OAuth2Provider {
|
|
return []provider.OAuth2Provider{
|
|
"qq",
|
|
"wx",
|
|
"alipay",
|
|
"baidu",
|
|
"microsoft",
|
|
}
|
|
}
|
|
|
|
type rainbowGenericProvider struct {
|
|
parent *Rainbow
|
|
t string
|
|
conf provider.Oauth2Option
|
|
}
|
|
|
|
func (r *Rainbow) newGenericProvider(t string) provider.Interface {
|
|
return &rainbowGenericProvider{
|
|
parent: r,
|
|
t: t,
|
|
}
|
|
}
|
|
|
|
func (p *rainbowGenericProvider) Init(c provider.Oauth2Option) {
|
|
p.conf = c
|
|
}
|
|
|
|
func (p *rainbowGenericProvider) Provider() provider.OAuth2Provider {
|
|
switch p.t {
|
|
case "wx":
|
|
return "wechat"
|
|
default:
|
|
return p.t
|
|
}
|
|
}
|
|
|
|
func (p *rainbowGenericProvider) NewAuthURL(ctx context.Context, state string) (string, error) {
|
|
result, err := url.JoinPath(p.parent.api, "/connect.php")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
u, err := url.Parse(result)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
query := url.Values{}
|
|
query.Set("act", "login")
|
|
query.Set("appid", p.conf.ClientID)
|
|
query.Set("appkey", p.conf.ClientSecret)
|
|
query.Set("type", p.t)
|
|
query.Set("redirect_uri", p.conf.RedirectURL)
|
|
query.Set("state", state)
|
|
u.RawQuery = query.Encode()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
resp, err := uhc.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
data := rainbowNewAuthURLResp{}
|
|
err = json.NewDecoder(resp.Body).Decode(&data)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if data.Code != 0 {
|
|
return "", fmt.Errorf("error code: %d, msg: %s", data.ErrCode, data.Msg)
|
|
}
|
|
return data.URL, nil
|
|
}
|
|
|
|
type rainbowNewAuthURLResp struct {
|
|
Msg string `json:"msg"`
|
|
Type string `json:"type"`
|
|
URL string `json:"url"`
|
|
Code int `json:"code"`
|
|
ErrCode int `json:"errcode"`
|
|
}
|
|
|
|
func (p *rainbowGenericProvider) GetUserInfo(
|
|
ctx context.Context,
|
|
code string,
|
|
) (*provider.UserInfo, error) {
|
|
result, err := url.JoinPath(p.parent.api, "/connect.php")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
u, err := url.Parse(result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
query := url.Values{}
|
|
query.Set("act", "callback")
|
|
query.Set("appid", p.conf.ClientID)
|
|
query.Set("appkey", p.conf.ClientSecret)
|
|
query.Set("type", p.t)
|
|
query.Set("code", code)
|
|
u.RawQuery = query.Encode()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
resp, err := uhc.Do(req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
data := rainbowUserInfo{}
|
|
err = json.NewDecoder(resp.Body).Decode(&data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if data.Code != 0 {
|
|
return nil, fmt.Errorf("error code: %d, msg: %s", data.ErrCode, data.Msg)
|
|
}
|
|
return &provider.UserInfo{
|
|
Username: data.Nickname,
|
|
ProviderUserID: data.SocialUID,
|
|
}, nil
|
|
}
|
|
|
|
//nolint:tagliatelle
|
|
type rainbowUserInfo struct {
|
|
Msg string `json:"msg"`
|
|
Type string `json:"type"`
|
|
SocialUID string `json:"social_uid"`
|
|
Nickname string `json:"nickname"`
|
|
Code int `json:"code"`
|
|
ErrCode int `json:"errcode"`
|
|
}
|
|
|
|
func (r *Rainbow) ExtractProvider(p provider.OAuth2Provider) (provider.Interface, error) {
|
|
switch p {
|
|
case "qq", "wx", "alipay", "baidu", "microsoft":
|
|
return r.newGenericProvider(p), nil
|
|
default:
|
|
return nil, fmt.Errorf("provider %s not supported", p)
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
addAggregation(new(Rainbow))
|
|
}
|