Initial commit

This commit is contained in:
Andy Hsu
2023-04-24 14:27:09 +08:00
commit 245c715c57
6 changed files with 425 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

72
ali.go Normal file
View File

@@ -0,0 +1,72 @@
package alist
import (
"api.nn.ci/apps/common"
"api.nn.ci/utils"
"github.com/gin-gonic/gin"
)
func Qr(c *gin.Context) {
url := "https://passport.aliyundrive.com/newlogin/qrcode/generate.do"
res, err := utils.RestyClient.R().SetQueryParams(map[string]string{
"appName": "aliyun_drive",
"fromSite": "52",
"appEntrance": "web",
"_csrf_token": "",
"umidToken": "",
"isMobile": "false",
"lang": "zh_CN",
"returnUrl": "",
"hsiz": "",
"bizParams": "",
"_bx-v": "2.0.31",
}).Get(url)
if err != nil {
common.Error(c, err)
return
}
c.Header("Content-Type", "application/json")
c.Writer.Write(res.Body())
}
type CK struct {
T string `json:"t"`
Ck string `json:"ck"`
}
func Ck(c *gin.Context) {
var ck CK
err := c.ShouldBind(&ck)
if err != nil {
common.Error(c, err)
return
}
res, err := utils.RestyClient.R().SetFormData(map[string]string{
"t": ck.T,
"ck": ck.Ck,
"ua": "140#ApzoT1O+zzPDRQo245+u33Sc2qq3vOsx37btKgtYp/+IQTwpilmRWL7UklKiXOSxEgmrlBPw4oOKU3hqzzngEzCNOa+xzWz8ijlulFzx2DD3VthqzFHcHbzum51xxD2iVP//lbzx2dfHKCUI1wba7XElyb98FLkGcBq9NLTwSgAzL+yICWq/l5WrYJ+B3qlPPFJg+BxuOJkpm+kszeUq29TiOuclegGQGrpKbFQOPCQE+u94nT7aL8G9Aq84NbL7nhfeFD9BpnzRPrEJrbCbpA3Kk7IsEW3gDIgSC4pQVKuM1VwwGaIuNdotnVtfuCceOFxWedDGMKHlr9NLAu9JKzRJBASFHRNdObSUeSklxZdXIHnupibAkG9mTwAEtajstVuX75Y7icOS5KhgQFP7iNuqEEeARX3DiMkI0pDw0Ybj5Q5JrXCz9AL6CTW3t0Zw5lE68UmECpi1eMwuY46BXykk4ET7+Jm7a+RVUTnWP5vfFV0omNauBNpsVggw/MYMxy4czMfMRiQwglJGBIVw+Mr18S+BAvJzqaUXg+HDUphISFsirUND0/u3zg+FM06Zc6rsVmxE2eSffE3cpgfVYoN/Hf24yFJCOVnVlIEagQF2CPxBQIDL+Q9E/f1l3lfQktqrC0GgxdPNv5ifjzp9IDb3t4h75O2daoJDnKcYhDfbKFvpqUgwkUCzzYspDRPv4XXAhsNq6KQZr3nP1AKdSjEL4XQSAGh4HCE1zHrvKPz93BYl68ZHZig9975vH+/fQlgzMRQE3NRaPBSh1a2If53LnMFj6f1g5OH1ZEPIZBq+K6RSGs6RJJ8NRKibX8weXQEXwVar9UeBKxIwGPW4Nysitb9/Le2NYpEf0oKIrGB/T0AEyieR1BNv8M8pNDIJ9M/lPDyoN4kB5sxD0E+=",
"appName": "aliyun_drive",
"appEntrance": "web",
"_csrf_token": "uJPMkz6XudG40RXo6xCuW5",
"umidToken": "6795f5c4caafbf6e9623941b8a3056b3e318c1fd",
"isMobile": "false",
"lang": "zh_CN",
"returnUrl": "",
"hsiz": "10918f04a35e8c83cf032e462eb88647",
"fromSite": "52",
"bizParams": "",
"navlanguage": "zh-CN",
"navUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
"navPlatform": "Win32",
}).
SetHeaders(map[string]string{
"origin": "https://passport.aliyundrive.com",
"referer": "https://passport.aliyundrive.com/mini_login.htm?&appName=aliyun_drive",
}).
Post("https://passport.aliyundrive.com/newlogin/qrcode/query.do?appName=aliyun_drive&fromSite=52&_bx-v=2.0.31")
//data := utils.Json.Get(res.Body(), "content", "data")
//loginResult := data.Get("loginResult").ToString()
//bizExt := data.Get("bizExt").ToString()
c.Header("Content-Type", "application/json")
c.Writer.Write(res.Body())
}

138
ali_open.go Normal file
View File

@@ -0,0 +1,138 @@
package alist
import (
"fmt"
"strings"
"api.nn.ci/apps/common"
"api.nn.ci/utils"
"github.com/gin-gonic/gin"
)
var (
aliClientID string
aliClientSecret string
aliMinutes int
aliMax int
)
type AliAccessTokenReq struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
GrantType string `json:"grant_type"`
Code string `json:"code"`
RefreshToken string `json:"refresh_token"`
}
type AliAccessTokenErr struct {
Code string `json:"code"`
Message string `json:"message"`
Error string `json:"error"`
}
func aliAccessToken(c *gin.Context) {
var req AliAccessTokenReq
err := c.ShouldBind(&req)
if err != nil {
common.ErrorJson(c, AliAccessTokenErr{
Code: "InternalError",
Message: err.Error(),
Error: err.Error(),
})
return
}
if req.ClientID == "" {
req.ClientID = aliClientID
req.ClientSecret = aliClientSecret
}
if req.GrantType != "authorization_code" && req.GrantType != "refresh_token" {
common.ErrorJson(c, AliAccessTokenErr{
Code: "Invalid request",
Message: "Incorrect GrantType",
Error: "Incorrect GrantType",
}, 400)
return
}
if len(req.RefreshToken) == 32 {
common.ErrorJson(c, AliAccessTokenErr{
Code: "Invalid request",
Message: "You should use the token that request with aliyundrive open insted of aliyundrive",
Error: "You should use the token that request with aliyundrive open insted of aliyundrive",
}, 400)
return
}
if req.GrantType == "authorization_code" && req.Code == "" {
common.ErrorJson(c, AliAccessTokenErr{
Code: "Invalid request",
Message: "Code missed",
Error: "Code missed",
}, 400)
return
}
if req.GrantType == "refresh_token" && strings.Count(req.RefreshToken, ".") != 2 {
common.ErrorJson(c, AliAccessTokenErr{
Code: "Invalid request",
Message: "Incorrect refresh_token or missed",
Error: "Incorrect refresh_token or missed",
}, 400)
return
}
var e AliAccessTokenErr
res, err := utils.RestyClient.R().SetBody(req).SetError(&e).Post("https://open.aliyundrive.com/oauth/access_token")
if err != nil {
common.ErrorJson(c, AliAccessTokenErr{
Code: "InternalError",
Message: err.Error(),
Error: err.Error(),
})
return
}
if e.Code != "" {
e.Error = fmt.Sprintf("%s: %s", e.Code, e.Message)
common.ErrorJson(c, e, res.StatusCode())
return
}
common.JsonBytes(c, res.Body())
}
type aliQrcodeReq struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Scopes []string `json:"scopes"`
}
func aliQrcode(c *gin.Context) {
var req aliQrcodeReq
err := c.ShouldBind(&req)
if err != nil {
c.JSON(500, AliAccessTokenErr{
Code: "InternalError",
Message: err.Error(),
Error: err.Error(),
})
return
}
if req.ClientID == "" {
req.ClientID = aliClientID
req.ClientSecret = aliClientSecret
}
if req.Scopes == nil || len(req.Scopes) == 0 {
req.Scopes = []string{"user:base", "file:all:read", "file:all:write"}
}
var e AliAccessTokenErr
res, err := utils.RestyClient.R().SetBody(req).SetError(&e).Post("https://open.aliyundrive.com/oauth/authorize/qrcode")
if err != nil {
c.JSON(500, AliAccessTokenErr{
Code: "InternalError",
Message: err.Error(),
Error: err.Error(),
})
return
}
if e.Code != "" {
e.Error = fmt.Sprintf("%s: %s", e.Code, e.Message)
c.JSON(res.StatusCode(), e)
return
}
common.JsonBytes(c, res.Body())
}

32
baidu.go Normal file
View File

@@ -0,0 +1,32 @@
package alist
import (
"fmt"
"api.nn.ci/apps/common"
"api.nn.ci/utils"
"github.com/gin-gonic/gin"
)
var (
baiduClientId string
baiduClientSecret string
baiduCallbackUri = "https://alist.nn.ci/tool/baidu/callback"
)
func baiduToken(c *gin.Context) {
code := c.Query("code")
if code == "" {
common.ErrorStr(c, "no code")
return
}
res, err := utils.RestyClient.R().
Get(fmt.Sprintf(
"https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=%s&client_id=%s&client_secret=%s&redirect_uri=%s",
code, baiduClientId, baiduClientSecret, baiduCallbackUri))
if err != nil {
common.Error(c, err)
return
}
common.JsonBytes(c, res.Body())
}

108
onedrive.go Normal file
View File

@@ -0,0 +1,108 @@
package alist
import (
"encoding/base64"
"net/url"
"strings"
"api.nn.ci/apps/common"
"api.nn.ci/utils"
"github.com/gin-gonic/gin"
)
type Zone struct {
Oauth string
Api string
}
var zones = map[string]Zone{
"global": {
Oauth: "https://login.microsoftonline.com",
Api: "https://graph.microsoft.com",
},
"cn": {
Oauth: "https://login.chinacloudapi.cn",
Api: "https://microsoftgraph.chinacloudapi.cn",
},
"us": {
Oauth: "https://login.microsoftonline.us",
Api: "https://graph.microsoft.us",
},
"de": {
Oauth: "https://login.microsoftonline.de",
Api: "https://graph.microsoft.de",
},
}
func onedriveToken(c *gin.Context) {
req := struct {
Code string `json:"code"`
Client string `json:"client"`
}{}
err := c.ShouldBind(&req)
if err != nil {
common.Error(c, err)
return
}
data, err := base64.StdEncoding.DecodeString(req.Client)
if err != nil {
common.Error(c, err)
return
}
clients := strings.Split(string(data), "::")
if len(clients) < 3 {
common.ErrorStr(c, "client error")
return
}
if zone, ok := zones[clients[2]]; ok {
res, err := utils.RestyClient.R().
SetFormData(map[string]string{
"client_id": clients[0],
"client_secret": clients[1],
"code": req.Code,
"grant_type": "authorization_code",
"redirect_uri": "https://alist.nn.ci/tool/onedrive/callback",
}).
Post(zone.Oauth + "/common/oauth2/v2.0/token")
if err != nil {
common.Error(c, err)
return
}
common.JsonBytes(c, res.Body())
return
}
common.ErrorStr(c, "zone doesn't exist")
return
}
func spSiteID(c *gin.Context) {
req := struct {
AccessToken string `json:"access_token"`
SiteUrl string `json:"site_url"`
Zone string `json:"zone"`
}{}
err := c.ShouldBind(&req)
if err != nil {
common.Error(c, err)
return
}
u, err := url.Parse(req.SiteUrl)
if err != nil {
common.Error(c, err)
return
}
siteName := u.Path
if zone, ok := zones[req.Zone]; ok {
res, err := utils.RestyClient.R().
SetHeader("Authorization", "Bearer "+req.AccessToken).
Get(zone.Api + "/v1.0/sites/root:/" + siteName)
if err != nil {
common.Error(c, err)
return
}
common.JsonBytes(c, res.Body())
return
}
common.ErrorStr(c, "zone doesn't exist")
return
}

73
setup.go Normal file
View File

@@ -0,0 +1,73 @@
package alist
import (
"os"
"strconv"
"time"
"github.com/axiaoxin-com/ratelimiter"
"github.com/gin-gonic/gin"
)
func initVar() {
s := os.Getenv("ALI_LIMIT_MINUTES")
v, err := strconv.Atoi(s)
if err != nil {
panic(err)
}
aliMinutes = v
s = os.Getenv("ALI_LIMIT_MAX")
v, err = strconv.Atoi(s)
if err != nil {
panic(err)
}
aliMax = v
// client
aliClientID = os.Getenv("ALI_DRIVE_CLIENT_ID")
aliClientSecret = os.Getenv("ALI_DRIVE_CLIENT_SECRET")
baiduClientId = os.Getenv("BAIDU_CLIENT_ID")
baiduClientSecret = os.Getenv("BAIDU_CLIENT_SECRET")
}
func Setup(g *gin.RouterGroup) {
initVar()
g.GET("/ali/qr", Qr)
g.POST("/ali/ck", Ck)
g.POST("/onedrive/get_refresh_token", onedriveToken)
g.POST("/onedrive/get_site_id", spSiteID)
g.GET("/baidu/get_refresh_token", baiduToken)
aliOpen := g.Group("/ali_open")
aliOpen.Any("/limit", func(ctx *gin.Context) {
ctx.JSON(200, gin.H{
"minutes": aliMinutes,
"max": aliMax,
})
})
aliOpenLimit := aliOpen.Group("")
aliOpenLimit.Use(ratelimiter.GinMemRatelimiter(ratelimiter.GinRatelimiterConfig{
LimitKey: func(ctx *gin.Context) string {
return ctx.ClientIP()
},
LimitedHandler: func(ctx *gin.Context) {
ctx.JSON(429, gin.H{
"code": "Too Many Requests",
"message": "Too Many Requests",
"error": "Too Many Requests",
})
ctx.Abort()
},
TokenBucketConfig: func(context *gin.Context) (time.Duration, int) {
return time.Duration(aliMinutes) * time.Minute, aliMax
},
}))
aliOpenLimit.Any("/test", func(c *gin.Context) {
c.JSON(200, gin.H{
"ClientIP": c.ClientIP(),
"RemoteIP": c.RemoteIP(),
})
})
aliOpenLimit.Any("/token", aliAccessToken)
aliOpenLimit.Any("/refresh", aliAccessToken)
aliOpenLimit.Any("/code", aliAccessToken)
aliOpenLimit.Any("/qr", aliQrcode)
}