From 21cd1f0aef408354af6104030e0448fdf5be0c23 Mon Sep 17 00:00:00 2001 From: xiaofei <122727418+xiaozhou26@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:47:03 +0800 Subject: [PATCH] Pull1 (#54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update README.md * up * 修正聊天接口自动continue功能,添加authorization中间件,增加Authorization系统变量。 * 修正聊天接口自动continue功能,添加authorization中间件,增加Authorization系统变量。 * 优化authorization中间件,增加自定义free_tokens.txt文件,由于有些uuid和正常账号重复了,会导致401 * 优化authorization中间件,新增自定义free_tokens.txt文件。 * 优化authorization中间件,新增自定义free_tokens.txt文件。 * docs: readme.md update docker-compose.yml (#43) * Create LICENSE (#44) * 增加session_token刷新access_token,和refresh刷新。 * 修复解析代理地址时未判断错误。 * fix: default free accounts * doc: remove useless readme * doc: readme * doc: readme * Update response.go (#49) * Delete README.md * Delete .env.template --------- Co-authored-by: lishihua <893164876@qq.com> Co-authored-by: madoka Co-authored-by: LanQian <5499636+LanQian528@users.noreply.github.com> --- README.md | 2 - auth.go | 5 +- docker-compose.yml | 3 +- handlers.go | 52 ++++++++++++++++++++ internal/chatgpt/request.go | 93 ++++++++++++++++++++++++++++++++++++ main.go | 4 +- typings/official/request.go | 8 ++++ typings/official/response.go | 12 +++++ 8 files changed, 172 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cafdc126..3eb670ca 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ # AURORA - 免费的GPT3.5 api - ## Deploy diff --git a/auth.go b/auth.go index 63b56ff0..c40788a1 100644 --- a/auth.go +++ b/auth.go @@ -4,9 +4,10 @@ import ( "aurora/internal/tokens" "bufio" "fmt" - "github.com/google/uuid" "os" "strconv" + + "github.com/google/uuid" ) func readAccessToken() { @@ -28,7 +29,7 @@ func readAccessToken() { } } - // 增加自定义free_tokens.txt,支持文件游客账号的uuid + // 增加自定义free_tokens.txt,支持文件设置每个账号的uuid if _, err := os.Stat("free_tokens.txt"); err == nil { // Each line is a proxy, put in proxies array file, _ := os.Open("free_tokens.txt") diff --git a/docker-compose.yml b/docker-compose.yml index d4838be0..5a94c5f6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,5 +6,4 @@ services: container_name: aurora restart: unless-stopped ports: - - - '8080:8080' + - '8080:8080' \ No newline at end of file diff --git a/handlers.go b/handlers.go index 77e1b028..0abf868c 100644 --- a/handlers.go +++ b/handlers.go @@ -21,6 +21,58 @@ func optionsHandler(c *gin.Context) { }) } +func refresh_handler(c *gin.Context) { + var refresh_token official_types.OpenAIRefreshToken + err := c.BindJSON(&refresh_token) + if err != nil { + c.JSON(400, gin.H{"error": gin.H{ + "message": "Request must be proper JSON", + "type": "invalid_request_error", + "param": nil, + "code": err.Error(), + }}) + return + } + proxy_url := ProxyIP.GetProxyIP() + openaiRefreshToken, status, err := chatgpt.GETTokenForRefreshToken(refresh_token.RefreshToken, proxy_url) + if err != nil { + c.JSON(400, gin.H{ + "message": "Request must be proper JSON", + "type": "invalid_request_error", + "param": nil, + "code": err.Error(), + }) + return + } + c.JSON(status, openaiRefreshToken) +} + +func session_handler(c *gin.Context) { + var session_token official_types.OpenAISessionToken + err := c.BindJSON(&session_token) + if err != nil { + c.JSON(400, gin.H{ + "message": "Request must be proper JSON", + "type": "invalid_request_error", + "param": nil, + "code": err.Error(), + }) + return + } + proxy_url := ProxyIP.GetProxyIP() + openaiSessionToken, status, err := chatgpt.GETTokenForSessionToken(session_token.SessionToken, proxy_url) + if err != nil { + c.JSON(400, gin.H{"error": gin.H{ + "message": "Request must be proper JSON", + "type": "invalid_request_error", + "param": nil, + "code": err.Error(), + }}) + return + } + c.JSON(status, openaiSessionToken) +} + func nightmare(c *gin.Context) { var original_request official_types.APIRequest err := c.BindJSON(&original_request) diff --git a/internal/chatgpt/request.go b/internal/chatgpt/request.go index daeafe9f..87604b9d 100644 --- a/internal/chatgpt/request.go +++ b/internal/chatgpt/request.go @@ -722,3 +722,96 @@ func Handler(c *gin.Context, response *http.Response, secret *tokens.Secret, uui ParentID: original_response.Message.ID, } } + +type AuthSession struct { + User struct { + Id string `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + Image string `json:"image"` + Picture string `json:"picture"` + Idp string `json:"idp"` + Iat int `json:"iat"` + Mfa bool `json:"mfa"` + Groups []interface{} `json:"groups"` + IntercomHash string `json:"intercom_hash"` + } `json:"user"` + Expires time.Time `json:"expires"` + AccessToken string `json:"accessToken"` + AuthProvider string `json:"authProvider"` +} + +func GETTokenForRefreshToken(refresh_token string, proxy string) (interface{}, int, error) { + if proxy != "" { + client.SetProxy(proxy) + } + url := "https://auth0.openai.com/oauth/token" + + data := map[string]interface{}{ + "redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback", + "grant_type": "refresh_token", + "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh", + "refresh_token": refresh_token, + } + + reqBody, err := json.Marshal(data) + if err != nil { + return nil, 0, err + } + + req, _ := http.NewRequest("POST", url, bytes.NewBuffer(reqBody)) + req.Header.Set("authority", "auth0.openai.com") + req.Header.Add("Accept-Language", "en-US,en;q=0.9") + req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36") + req.Header.Set("Accept", "*/*") + resp, err := client.Do(req) + if err != nil { + return nil, 0, err + } + defer resp.Body.Close() + var result interface{} + err = json.NewDecoder(resp.Body).Decode(&result) + if err != nil { + return nil, 0, err + } + return result, resp.StatusCode, nil +} + +func GETTokenForSessionToken(session_token string, proxy string) (interface{}, int, error) { + if proxy != "" { + client.SetProxy(proxy) + } + url := "https://chat.openai.com/api/auth/session" + req, _ := http.NewRequest("GET", url, nil) + req.Header.Set("authority", "chat.openai.com") + req.Header.Set("accept-language", "zh-CN,zh;q=0.9") + req.Header.Set("User-Agent", userAgent) + req.Header.Set("Accept", "*/*") + req.Header.Set("oai-language", "en-US") + req.Header.Set("origin", "https://chat.openai.com") + req.Header.Set("referer", "https://chat.openai.com/") + req.Header.Set("cookie", "__Secure-next-auth.session-token="+session_token) + resp, err := client.Do(req) + if err != nil { + return nil, 0, err + } + defer resp.Body.Close() + var result AuthSession + json.NewDecoder(resp.Body).Decode(&result) + + cookies := parseCookies(resp.Cookies()) + if value, ok := cookies["__Secure-next-auth.session-token"]; ok { + session_token = value + } + openai_sessionToken := official_types.NewOpenAISessionToken(session_token, result.AccessToken) + return openai_sessionToken, resp.StatusCode, nil +} + +func parseCookies(cookies []*http.Cookie) map[string]string { + cookieDict := make(map[string]string) + for _, cookie := range cookies { + cookieDict[cookie.Name] = cookie.Value + } + return cookieDict +} diff --git a/main.go b/main.go index f77bbc42..2da429dd 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,7 @@ func checkProxy() { scanner := bufio.NewScanner(file) for scanner.Scan() { proxy := scanner.Text() - parsedURL, _ := url.Parse(proxy) + parsedURL, err := url.Parse(proxy) if err != nil { fmt.Println("无法解析URL:", err) return @@ -95,6 +95,8 @@ func main() { }) }) + router.POST("/auth/session", session_handler) + router.POST("/auth/refresh", refresh_handler) router.OPTIONS("/v1/chat/completions", optionsHandler) router.POST("/v1/chat/completions", Authorization, nightmare) router.GET("/v1/models", Authorization, engines_handler) diff --git a/typings/official/request.go b/typings/official/request.go index b81dc857..43ee3ea7 100644 --- a/typings/official/request.go +++ b/typings/official/request.go @@ -11,3 +11,11 @@ type api_message struct { Role string `json:"role"` Content string `json:"content"` } + +type OpenAISessionToken struct { + SessionToken string `json:"session_token"` +} + +type OpenAIRefreshToken struct { + RefreshToken string `json:"refresh_token"` +} diff --git a/typings/official/response.go b/typings/official/response.go index 8d29e662..5af3fd9a 100644 --- a/typings/official/response.go +++ b/typings/official/response.go @@ -104,3 +104,15 @@ func NewChatCompletion(full_test string) ChatCompletion { }, } } + +type OpenAIAccessTokenWithSession struct { + SessionToken string `json:"session_token"` + AccessToken string `json:"access_token"` +} + +func NewOpenAISessionToken(session_token string, access_token string) *OpenAIAccessTokenWithSession { + return &OpenAIAccessTokenWithSession{ + SessionToken: session_token, + AccessToken: access_token, + } +}