yetey commited on
Commit
5757554
1 Parent(s): b28e52d

Upload 45 files

Browse files
.gitignore ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ tools/authenticator/100-ACCOUNTS_COMPILED.txt
2
+ tools/authenticator/accounts.txt
3
+ tools/authenticator/proxies.txt
4
+ tools/authenticator/authenticated_accounts.txt
5
+ tools/authenticator/access_tokens.txt
6
+ *.txt
7
+ aurora
8
+ chatgpttoapi
9
+ tools/authenticator/.proxies.txt.swp
10
+ .env
11
+ *.har
12
+ .idea/
13
+ /logs/
14
+ /target/
15
+ /bin/
Dockerfile ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 使用 Go 1.21 官方镜像作为构建环境
2
+ FROM golang:1.21 AS builder
3
+
4
+ # 禁用 CGO
5
+ ENV CGO_ENABLED=0
6
+
7
+ # 设置工作目录
8
+ WORKDIR /app
9
+
10
+ # 复制 go.mod 和 go.sum 并下载依赖
11
+ COPY go.mod go.sum ./
12
+ RUN go mod download
13
+
14
+ # 复制源代码并构建应用
15
+ COPY . .
16
+ RUN go build -ldflags "-s -w" -o /app/duck2api .
17
+
18
+ # 使用 Alpine Linux 作为最终镜像
19
+ FROM alpine:latest
20
+
21
+ # 设置工作目录
22
+ WORKDIR /app
23
+ RUN apk add --no-cache tzdata
24
+
25
+ # 从构建阶段复制编译好的应用和资源
26
+ COPY --from=builder /app/duck2api /app/duck2api
27
+ COPY harPool /app/harPool
28
+
29
+ # 暴露端口
30
+ EXPOSE 8080
31
+
32
+ CMD ["/app/duck2api"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 aurora-develop
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
Procfile ADDED
@@ -0,0 +1 @@
 
 
1
+ web: aurora
VERSION ADDED
@@ -0,0 +1 @@
 
 
1
+ 2.0.0
api/router.go ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package api
2
+
3
+ import (
4
+ "aurora/initialize"
5
+ "github.com/gin-gonic/gin"
6
+ "net/http"
7
+ )
8
+
9
+ var router *gin.Engine
10
+
11
+ func init() {
12
+ // 初始化gin
13
+ router = initialize.RegisterRouter()
14
+ }
15
+
16
+ func Listen(w http.ResponseWriter, r *http.Request) {
17
+ router.ServeHTTP(w, r)
18
+ }
build.sh ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ export GOPROXY=https://goproxy.io
4
+
5
+ go get
6
+
7
+ export CGO_ENABLED=0
8
+ PKG=aurora
9
+
10
+ targets=(
11
+ "windows/amd64"
12
+ "linux/amd64"
13
+ "darwin/amd64"
14
+ "windows/386"
15
+ "linux/386"
16
+ "darwin/386"
17
+ "linux/arm"
18
+ "linux/arm64"
19
+ "linux/s390x"
20
+ )
21
+
22
+ upxPath=$(command -v upx)
23
+
24
+ for target in "${targets[@]}"; do
25
+ GOOS=${target%/*}
26
+ GOARCH=${target#*/}
27
+ outputDir="bin/${GOOS}_${GOARCH}"
28
+ outputFile="${outputDir}/${PKG}"
29
+ archiveName="${PKG}-${GOOS}-${GOARCH}.tar.gz"
30
+ mkdir -p $(dirname ${outputFile})
31
+ GOOS=$GOOS GOARCH=$GOARCH go build -ldflags="-s -w -extldflags '-static'" -o ${outputFile} *.go
32
+ if [ -n "$upxPath" ]; then
33
+ $upxPath -9 ${outputFile}
34
+ fi
35
+ # Archive the binary
36
+ if [ "$GOOS" = "windows" ]; then
37
+ zip -j "${outputDir}/${PKG}-${GOOS}-${GOARCH}.zip" "${outputFile}"
38
+ else
39
+ tar -C "${outputDir}" -czf "${outputDir}/${archiveName}" "${PKG}"
40
+ fi
41
+ done
conversion/requests/chatgpt/convert.go ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package chatgpt
2
+
3
+ import (
4
+ "fmt"
5
+ "strings"
6
+
7
+ "aurora/internal/tokens"
8
+ chatgpt_types "aurora/typings/chatgpt"
9
+ official_types "aurora/typings/official"
10
+
11
+ arkose "github.com/xqdoo00o/funcaptcha"
12
+ )
13
+
14
+ func ConvertAPIRequest(api_request official_types.APIRequest, secret *tokens.Secret, requireArk bool, proxy string) chatgpt_types.ChatGPTRequest {
15
+ chatgpt_request := chatgpt_types.NewChatGPTRequest()
16
+ var api_version int
17
+ if secret.PUID == "" {
18
+ api_request.Model = "gpt-3.5"
19
+ }
20
+ if strings.HasPrefix(api_request.Model, "gpt-3.5") {
21
+ api_version = 3
22
+ chatgpt_request.Model = "text-davinci-002-render-sha"
23
+ } else if strings.HasPrefix(api_request.Model, "gpt-4") {
24
+ api_version = 4
25
+ chatgpt_request.Model = api_request.Model
26
+ // Cover some models like gpt-4-32k
27
+ if len(api_request.Model) >= 7 && api_request.Model[6] >= 48 && api_request.Model[6] <= 57 {
28
+ chatgpt_request.Model = "gpt-4"
29
+ }
30
+ }
31
+ if requireArk {
32
+ token, err := arkose.GetOpenAIToken(api_version, secret.PUID, "", proxy)
33
+ if err == nil {
34
+ chatgpt_request.ArkoseToken = token
35
+ } else {
36
+ fmt.Println("Error getting Arkose token: ", err)
37
+ }
38
+ }
39
+
40
+ if api_request.PluginIDs != nil {
41
+ chatgpt_request.PluginIDs = api_request.PluginIDs
42
+ chatgpt_request.Model = "gpt-4-plugins"
43
+ }
44
+ for _, api_message := range api_request.Messages {
45
+ if api_message.Role == "system" {
46
+ api_message.Role = "critic"
47
+ }
48
+ chatgpt_request.AddMessage(api_message.Role, api_message.Content)
49
+ }
50
+ return chatgpt_request
51
+ }
52
+
53
+ func RenewTokenForRequest(request *chatgpt_types.ChatGPTRequest, puid string, proxy string) {
54
+ var api_version int
55
+ if strings.HasPrefix(request.Model, "gpt-4") {
56
+ api_version = 4
57
+ } else {
58
+ api_version = 3
59
+ }
60
+ token, err := arkose.GetOpenAIToken(api_version, puid, "", proxy)
61
+ if err == nil {
62
+ request.ArkoseToken = token
63
+ } else {
64
+ fmt.Println("Error getting Arkose token: ", err)
65
+ }
66
+ }
conversion/response/chatgpt/convert.go ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package chatgpt
2
+
3
+ import (
4
+ "strings"
5
+
6
+ "aurora/typings"
7
+ chatgpt_types "aurora/typings/chatgpt"
8
+ official_types "aurora/typings/official"
9
+ )
10
+
11
+ func ConvertToString(chatgpt_response *chatgpt_types.ChatGPTResponse, previous_text *typings.StringStruct, role bool) string {
12
+ translated_response := official_types.NewChatCompletionChunk(strings.Replace(chatgpt_response.Message.Content.Parts[0].(string), previous_text.Text, "", 1))
13
+ if role {
14
+ translated_response.Choices[0].Delta.Role = chatgpt_response.Message.Author.Role
15
+ } else if translated_response.Choices[0].Delta.Content == "" || (strings.HasPrefix(chatgpt_response.Message.Metadata.ModelSlug, "gpt-4") && translated_response.Choices[0].Delta.Content == "【") {
16
+ return translated_response.Choices[0].Delta.Content
17
+ }
18
+ previous_text.Text = chatgpt_response.Message.Content.Parts[0].(string)
19
+ return "data: " + translated_response.String() + "\n\n"
20
+ }
docker-compose.yml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ version: '3'
2
+
3
+ services:
4
+ app:
5
+ image: ghcr.io/aurora-develop/aurora:latest
6
+ container_name: aurora
7
+ restart: unless-stopped
8
+ ports:
9
+ - '8080:8080'
duckgo/convert.go ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package duckgo
2
+
3
+ import (
4
+ officialtypes "aurora/typings/official"
5
+ "strings"
6
+ )
7
+
8
+ func ConvertAPIRequest(api_request officialtypes.APIRequest) ApiRequest {
9
+ duckgo_request := NewApiRequest(api_request.Model)
10
+ if strings.HasPrefix(duckgo_request.Model, "gpt-3.5") {
11
+ duckgo_request.Model = GPT3
12
+ }
13
+ if strings.HasPrefix(duckgo_request.Model, "claude") {
14
+ duckgo_request.Model = Claude
15
+ }
16
+ content := ""
17
+ for _, apiMessage := range api_request.Messages {
18
+ if apiMessage.Role == "user" {
19
+ content += "user:" + apiMessage.Content + "\r\n"
20
+ }
21
+ if apiMessage.Role == "system" {
22
+ content += "system:" + apiMessage.Content + "\r\n"
23
+ }
24
+ if apiMessage.Role == "assistant" {
25
+ content += "assistant:" + apiMessage.Content + "\r\n"
26
+ }
27
+ }
28
+ duckgo_request.AddMessage("user", content)
29
+ return duckgo_request
30
+ }
duckgo/request.go ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package duckgo
2
+
3
+ import (
4
+ "aurora/httpclient"
5
+ officialtypes "aurora/typings/official"
6
+ "bufio"
7
+ "bytes"
8
+ "encoding/json"
9
+ "errors"
10
+ "github.com/gin-gonic/gin"
11
+ "io"
12
+ "net/http"
13
+ "strings"
14
+ "sync"
15
+ "time"
16
+ )
17
+
18
+ type ApiRequest struct {
19
+ Model string `json:"model"`
20
+ Messages []struct {
21
+ Role string `json:"role"`
22
+ Content string `json:"content"`
23
+ } `json:"messages"`
24
+ }
25
+
26
+ func (a *ApiRequest) AddMessage(role string, content string) {
27
+ a.Messages = append(a.Messages, struct {
28
+ Role string `json:"role"`
29
+ Content string `json:"content"`
30
+ }{
31
+ Role: role,
32
+ Content: content,
33
+ })
34
+ }
35
+
36
+ func NewApiRequest(model string) ApiRequest {
37
+ return ApiRequest{
38
+ Model: model,
39
+ }
40
+ }
41
+
42
+ func InitXVQD(client httpclient.AuroraHttpClient, proxyUrl string) (string, error) {
43
+ if Token == nil {
44
+ Token = &XqdgToken{
45
+ Token: "",
46
+ M: sync.Mutex{},
47
+ }
48
+ }
49
+ Token.M.Lock()
50
+ defer Token.M.Unlock()
51
+ if Token.Token == "" || Token.ExpireAt.Before(time.Now()) {
52
+ status, err := postStatus(client, proxyUrl)
53
+ if err != nil {
54
+ return "", err
55
+ }
56
+ defer status.Body.Close()
57
+ token := status.Header.Get("x-vqd-4")
58
+ if token == "" {
59
+ return "", errors.New("no x-vqd-4 token")
60
+ }
61
+ Token.Token = token
62
+ Token.ExpireAt = time.Now().Add(time.Minute * 5)
63
+ }
64
+
65
+ return Token.Token, nil
66
+ }
67
+
68
+ func postStatus(client httpclient.AuroraHttpClient, proxyUrl string) (*http.Response, error) {
69
+ if proxyUrl != "" {
70
+ client.SetProxy(proxyUrl)
71
+ }
72
+ header := createHeader()
73
+ header.Set("accept", "*/*")
74
+ header.Set("x-vqd-accept", "1")
75
+ response, err := client.Request(httpclient.GET, "https://duckduckgo.com/duckchat/v1/status", header, nil, nil)
76
+ if err != nil {
77
+ return nil, err
78
+ }
79
+ return response, nil
80
+ }
81
+
82
+ func POSTconversation(client httpclient.AuroraHttpClient, request ApiRequest, token string, proxyUrl string) (*http.Response, error) {
83
+ if proxyUrl != "" {
84
+ client.SetProxy(proxyUrl)
85
+ }
86
+ body_json, err := json.Marshal(request)
87
+ if err != nil {
88
+ return &http.Response{}, err
89
+ }
90
+ header := createHeader()
91
+ header.Set("accept", "text/event-stream")
92
+ header.Set("x-vqd-4", token)
93
+ response, err := client.Request(httpclient.POST, "https://duckduckgo.com/duckchat/v1/chat", header, nil, bytes.NewBuffer(body_json))
94
+ if err != nil {
95
+ return nil, err
96
+ }
97
+ return response, nil
98
+ }
99
+
100
+ func Handle_request_error(c *gin.Context, response *http.Response) bool {
101
+ if response.StatusCode == 400 {
102
+ c.JSON(400, gin.H{"error": gin.H{
103
+ "message": "Request must be proper JSON",
104
+ "type": "invalid_request_error",
105
+ "param": nil,
106
+ "code": response.Status,
107
+ }})
108
+ return true
109
+ }
110
+ return false
111
+ }
112
+
113
+ func createHeader() httpclient.AuroraHeaders {
114
+ header := make(httpclient.AuroraHeaders)
115
+ header.Set("accept-language", "zh-CN,zh;q=0.9")
116
+ header.Set("content-type", "application/json")
117
+ header.Set("origin", "https://duckduckgo.com")
118
+ header.Set("referer", "https://duckduckgo.com/")
119
+ header.Set("sec-ch-ua", `"Chromium";v="120", "Google Chrome";v="120", "Not-A.Brand";v="99"`)
120
+ header.Set("sec-ch-ua-mobile", "?0")
121
+ header.Set("sec-ch-ua-platform", `"Windows"`)
122
+ header.Set("user-agent", UA)
123
+ return header
124
+ }
125
+
126
+ func Handler(c *gin.Context, response *http.Response, stream bool) string {
127
+ reader := bufio.NewReader(response.Body)
128
+ if stream {
129
+ // Response content type is text/event-stream
130
+ c.Header("Content-Type", "text/event-stream")
131
+ } else {
132
+ // Response content type is application/json
133
+ c.Header("Content-Type", "application/json")
134
+ }
135
+ var originalResponse ApiResponse
136
+ var previousText = ""
137
+ for {
138
+ line, err := reader.ReadString('\n')
139
+ if err != nil {
140
+ if err == io.EOF {
141
+ break
142
+ }
143
+ return ""
144
+ }
145
+ if len(line) < 6 {
146
+ continue
147
+ }
148
+ line = line[6:]
149
+ if !strings.HasPrefix(line, "[DONE]") {
150
+ err = json.Unmarshal([]byte(line), &originalResponse)
151
+ if err != nil {
152
+ continue
153
+ }
154
+ if originalResponse.Action != "success" {
155
+ c.JSON(500, gin.H{"error": "Error"})
156
+ return ""
157
+ }
158
+ responseString := ""
159
+ if originalResponse.Message != "" {
160
+ previousText += originalResponse.Message
161
+ translatedResponse := officialtypes.NewChatCompletionChunkWithModel(originalResponse.Message, originalResponse.Model)
162
+ responseString = "data: " + translatedResponse.String() + "\n\n"
163
+ }
164
+
165
+ if responseString == "" {
166
+ continue
167
+ }
168
+
169
+ if stream {
170
+ _, err = c.Writer.WriteString(responseString)
171
+ if err != nil {
172
+ return ""
173
+ }
174
+ c.Writer.Flush()
175
+ }
176
+ } else {
177
+ if stream {
178
+ final_line := officialtypes.StopChunkWithModel("stop", originalResponse.Model)
179
+ c.Writer.WriteString("data: " + final_line.String() + "\n\n")
180
+ }
181
+ }
182
+ }
183
+ return previousText
184
+ }
duckgo/response.go ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ package duckgo
2
+
3
+ type ApiResponse struct {
4
+ Message string `json:"message"`
5
+ Created int `json:"created"`
6
+ Id string `json:"id"`
7
+ Action string `json:"action"`
8
+ Model string `json:"model"`
9
+ }
duckgo/var.go ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package duckgo
2
+
3
+ import (
4
+ "sync"
5
+ "time"
6
+ )
7
+
8
+ const (
9
+ Claude = "claude-instant-1.2"
10
+ GPT3 = "gpt-3.5-turbo-0125"
11
+ UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
12
+ )
13
+
14
+ var (
15
+ Token *XqdgToken
16
+ )
17
+
18
+ type XqdgToken struct {
19
+ Token string `json:"token"`
20
+ M sync.Mutex `json:"-"`
21
+ ExpireAt time.Time `json:"expire"`
22
+ }
env.template ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ SERVER_HOST=0.0.0.0
2
+ SERVER_PORT=8080
3
+ FREE_ACCOUNTS=true
4
+ FREE_ACCOUNTS_NUM=1024
5
+ Authorization=
6
+ TLS_CERT=
7
+ TLS_KEY=
8
+ PROXY_URL=
go.mod ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module aurora
2
+
3
+ go 1.21
4
+
5
+ require (
6
+ github.com/EDDYCJY/fake-useragent v0.2.0
7
+ github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd
8
+ github.com/bogdanfinn/fhttp v0.5.27
9
+ github.com/bogdanfinn/tls-client v1.7.2
10
+ github.com/gin-gonic/gin v1.9.1
11
+ github.com/go-resty/resty/v2 v2.12.0
12
+ github.com/google/uuid v1.6.0
13
+ github.com/gorilla/websocket v1.5.1
14
+ github.com/joho/godotenv v1.5.1
15
+ github.com/pkoukk/tiktoken-go v0.1.6
16
+ github.com/xqdoo00o/funcaptcha v0.0.0-20240403090732-1b604d808f6c
17
+ )
18
+
19
+ require (
20
+ github.com/PuerkitoBio/goquery v1.9.1 // indirect
21
+ github.com/andybalholm/brotli v1.0.5 // indirect
22
+ github.com/andybalholm/cascadia v1.3.2 // indirect
23
+ github.com/bogdanfinn/utls v1.6.1 // indirect
24
+ github.com/bytedance/sonic v1.10.1 // indirect
25
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
26
+ github.com/chenzhuoyu/iasm v0.9.0 // indirect
27
+ github.com/cloudflare/circl v1.3.6 // indirect
28
+ github.com/dlclark/regexp2 v1.10.0 // indirect
29
+ github.com/gabriel-vasile/mimetype v1.4.2 // indirect
30
+ github.com/gin-contrib/sse v0.1.0 // indirect
31
+ github.com/go-playground/locales v0.14.1 // indirect
32
+ github.com/go-playground/universal-translator v0.18.1 // indirect
33
+ github.com/go-playground/validator/v10 v10.15.4 // indirect
34
+ github.com/goccy/go-json v0.10.2 // indirect
35
+ github.com/json-iterator/go v1.1.12 // indirect
36
+ github.com/klauspost/compress v1.17.0 // indirect
37
+ github.com/klauspost/cpuid/v2 v2.2.5 // indirect
38
+ github.com/kr/text v0.2.0 // indirect
39
+ github.com/leodido/go-urn v1.2.4 // indirect
40
+ github.com/mattn/go-isatty v0.0.19 // indirect
41
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
42
+ github.com/modern-go/reflect2 v1.0.2 // indirect
43
+ github.com/pelletier/go-toml/v2 v2.1.0 // indirect
44
+ github.com/quic-go/quic-go v0.37.4 // indirect
45
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
46
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
47
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
48
+ github.com/ugorji/go/codec v1.2.11 // indirect
49
+ golang.org/x/arch v0.5.0 // indirect
50
+ golang.org/x/crypto v0.21.0 // indirect
51
+ golang.org/x/net v0.22.0 // indirect
52
+ golang.org/x/sys v0.18.0 // indirect
53
+ golang.org/x/text v0.14.0 // indirect
54
+ google.golang.org/protobuf v1.31.0 // indirect
55
+ gopkg.in/yaml.v3 v3.0.1 // indirect
56
+ )
go.sum ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ github.com/EDDYCJY/fake-useragent v0.2.0 h1:Jcnkk2bgXmDpX0z+ELlUErTkoLb/mxFBNd2YdcpvJBs=
2
+ github.com/EDDYCJY/fake-useragent v0.2.0/go.mod h1:5wn3zzlDxhKW6NYknushqinPcAqZcAPHy8lLczCdJdc=
3
+ github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI=
4
+ github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
5
+ github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd h1:oIpfrRhD7Jus41dotbK+SQjWSFRnf1cLZUYCZpF/o/4=
6
+ github.com/acheong08/endless v0.0.0-20230615162514-90545c7793fd/go.mod h1:0yO7neMeJLvKk/B/fq5votDY8rByrOPDubpvU+6saKo=
7
+ github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
8
+ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
9
+ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
10
+ github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
11
+ github.com/bogdanfinn/fhttp v0.5.27 h1:+glR3k8v5nxfUSk7+J3M246zEQ2yadhS0vLq1utK71A=
12
+ github.com/bogdanfinn/fhttp v0.5.27/go.mod h1:oJiYPG3jQTKzk/VFmogH8jxjH5yiv2rrOH48Xso2lrE=
13
+ github.com/bogdanfinn/tls-client v1.7.2 h1:vpL5qBYUfT9ueygEf1yLfymrXyUEZQatL25amfqGV8M=
14
+ github.com/bogdanfinn/tls-client v1.7.2/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
15
+ github.com/bogdanfinn/utls v1.6.1 h1:dKDYAcXEyFFJ3GaWaN89DEyjyRraD1qb4osdEK89ass=
16
+ github.com/bogdanfinn/utls v1.6.1/go.mod h1:VXIbRZaiY/wHZc6Hu+DZ4O2CgTzjhjCg/Ou3V4r/39Y=
17
+ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
18
+ github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
19
+ github.com/bytedance/sonic v1.10.1 h1:7a1wuFXL1cMy7a3f7/VFcEtriuXQnUBhtoVfOZiaysc=
20
+ github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
21
+ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
22
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
23
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
24
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
25
+ github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
26
+ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
27
+ github.com/cloudflare/circl v1.3.6 h1:/xbKIqSHbZXHwkhbrhrt2YOHIwYJlXH94E3tI/gDlUg=
28
+ github.com/cloudflare/circl v1.3.6/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
29
+ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
30
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
31
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
32
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
+ github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
34
+ github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
35
+ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
36
+ github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
37
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
38
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
39
+ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
40
+ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
41
+ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
42
+ github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
43
+ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
44
+ github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
45
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
46
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
47
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
48
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
49
+ github.com/go-playground/validator/v10 v10.15.4 h1:zMXza4EpOdooxPel5xDqXEdXG5r+WggpvnAKMsalBjs=
50
+ github.com/go-playground/validator/v10 v10.15.4/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
51
+ github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA=
52
+ github.com/go-resty/resty/v2 v2.12.0/go.mod h1:o0yGPrkS3lOe1+eFajk6kBW8ScXzwU3hD69/gt2yB/0=
53
+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
54
+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
55
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
56
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
57
+ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
58
+ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
59
+ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
60
+ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
61
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
62
+ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
63
+ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
64
+ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
65
+ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
66
+ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
67
+ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
68
+ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
69
+ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
70
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
71
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
72
+ github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
73
+ github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
74
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
75
+ github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
76
+ github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
77
+ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
78
+ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
79
+ github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
80
+ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
81
+ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
82
+ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
83
+ github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
84
+ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
85
+ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
86
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
87
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
88
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
89
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
90
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
91
+ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
92
+ github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
93
+ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
94
+ github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
95
+ github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
96
+ github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
97
+ github.com/pkoukk/tiktoken-go v0.1.6 h1:JF0TlJzhTbrI30wCvFuiw6FzP2+/bR+FIxUdgEAcUsw=
98
+ github.com/pkoukk/tiktoken-go v0.1.6/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg=
99
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
100
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
101
+ github.com/quic-go/quic-go v0.37.4 h1:ke8B73yMCWGq9MfrCCAw0Uzdm7GaViC3i39dsIdDlH4=
102
+ github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
103
+ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
104
+ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
105
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
106
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
107
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
108
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
109
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
110
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
111
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
112
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
113
+ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
114
+ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
115
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
116
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
117
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
118
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
119
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
120
+ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
121
+ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
122
+ github.com/xqdoo00o/funcaptcha v0.0.0-20240403090732-1b604d808f6c h1:nj17XsSTwprsZUDXLldOUZmqz7VlHsLCeXXFOE6Q+Mk=
123
+ github.com/xqdoo00o/funcaptcha v0.0.0-20240403090732-1b604d808f6c/go.mod h1:7aCyoW5MHDUsoooMVLqKe0F7W9HMPUvDG3bXqw++8XA=
124
+ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
125
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
126
+ golang.org/x/arch v0.5.0 h1:jpGode6huXQxcskEIpOCvrU+tzo81b6+oFLUYXWtH/Y=
127
+ golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
128
+ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
129
+ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
130
+ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
131
+ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
132
+ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
133
+ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
134
+ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
135
+ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
136
+ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
137
+ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
138
+ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
139
+ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
140
+ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
141
+ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
142
+ golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
143
+ golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
144
+ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
145
+ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
146
+ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
147
+ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
148
+ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
149
+ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
150
+ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
151
+ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
152
+ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
153
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
154
+ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
155
+ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
156
+ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
157
+ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
158
+ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
159
+ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
160
+ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
161
+ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
162
+ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
163
+ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
164
+ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
165
+ golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
166
+ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
167
+ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
168
+ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
169
+ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
170
+ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
171
+ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
172
+ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
173
+ golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
174
+ golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
175
+ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
176
+ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
177
+ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
178
+ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
179
+ golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
180
+ golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
181
+ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
182
+ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
183
+ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
184
+ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
185
+ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
186
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
187
+ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
188
+ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
189
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
190
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
191
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
192
+ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
193
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
harPool/HAR ADDED
File without changes
httpclient/Iaurorahttpclient.go ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package httpclient
2
+
3
+ import (
4
+ "io"
5
+ "net/http"
6
+ )
7
+
8
+ type AuroraHttpClient interface {
9
+ Request(method HttpMethod, url string, headers AuroraHeaders, cookies []*http.Cookie, body io.Reader) (*http.Response, error)
10
+ SetProxy(url string) error
11
+ }
12
+
13
+ type HttpMethod string
14
+
15
+ const (
16
+ GET HttpMethod = "GET"
17
+ POST HttpMethod = "POST"
18
+ PUT HttpMethod = "PUT"
19
+ HEAD HttpMethod = "HEAD"
20
+ DELETE HttpMethod = "DELETE"
21
+ OPTIONS HttpMethod = "OPTIONS"
22
+ )
23
+
24
+ type AuroraHeaders map[string]string
25
+
26
+ func (a AuroraHeaders) Set(key, value string) {
27
+ a[key] = value
28
+ }
httpclient/bogdanfinn/tls_client.go ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package bogdanfinn
2
+
3
+ import (
4
+ "aurora/httpclient"
5
+ "io"
6
+ "net/http"
7
+
8
+ fhttp "github.com/bogdanfinn/fhttp"
9
+ tls_client "github.com/bogdanfinn/tls-client"
10
+ "github.com/bogdanfinn/tls-client/profiles"
11
+ )
12
+
13
+ type TlsClient struct {
14
+ Client tls_client.HttpClient
15
+ ReqBefore handler
16
+ }
17
+
18
+ type handler func(r *fhttp.Request) error
19
+
20
+ func NewStdClient() *TlsClient {
21
+ client, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), []tls_client.HttpClientOption{
22
+ tls_client.WithCookieJar(tls_client.NewCookieJar()),
23
+ tls_client.WithTimeoutSeconds(600),
24
+ tls_client.WithClientProfile(profiles.Safari_15_6_1),
25
+ }...)
26
+
27
+ stdClient := &TlsClient{Client: client}
28
+ return stdClient
29
+ }
30
+
31
+ func convertResponse(resp *fhttp.Response) *http.Response {
32
+ response := &http.Response{
33
+ Status: resp.Status,
34
+ StatusCode: resp.StatusCode,
35
+ Proto: resp.Proto,
36
+ ProtoMajor: resp.ProtoMajor,
37
+ ProtoMinor: resp.ProtoMinor,
38
+ Header: http.Header(resp.Header),
39
+ Body: resp.Body,
40
+ ContentLength: resp.ContentLength,
41
+ TransferEncoding: resp.TransferEncoding,
42
+ Close: resp.Close,
43
+ Uncompressed: resp.Uncompressed,
44
+ Trailer: http.Header(resp.Trailer),
45
+ }
46
+ return response
47
+ }
48
+
49
+ func (t *TlsClient) handleHeaders(req *fhttp.Request, headers httpclient.AuroraHeaders) {
50
+ if headers == nil {
51
+ return
52
+ }
53
+ for k, v := range headers {
54
+ req.Header.Set(k, v)
55
+ }
56
+ }
57
+
58
+ func (t *TlsClient) handleCookies(req *fhttp.Request, cookies []*http.Cookie) {
59
+ if cookies == nil {
60
+ return
61
+ }
62
+ for _, c := range cookies {
63
+ req.AddCookie(&fhttp.Cookie{
64
+ Name: c.Name,
65
+ Value: c.Value,
66
+ Path: c.Path,
67
+ Domain: c.Domain,
68
+ Expires: c.Expires,
69
+ RawExpires: c.RawExpires,
70
+ MaxAge: c.MaxAge,
71
+ Secure: c.Secure,
72
+ HttpOnly: c.HttpOnly,
73
+ SameSite: fhttp.SameSite(c.SameSite),
74
+ Raw: c.Raw,
75
+ Unparsed: c.Unparsed,
76
+ })
77
+ }
78
+ }
79
+
80
+ func (t *TlsClient) Request(method httpclient.HttpMethod, url string, headers httpclient.AuroraHeaders, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
81
+ req, err := fhttp.NewRequest(string(method), url, body)
82
+ if err != nil {
83
+ return nil, err
84
+ }
85
+ t.handleHeaders(req, headers)
86
+ t.handleCookies(req, cookies)
87
+ if t.ReqBefore != nil {
88
+ if err := t.ReqBefore(req); err != nil {
89
+ return nil, err
90
+ }
91
+ }
92
+ do, err := t.Client.Do(req)
93
+ if err != nil {
94
+ return nil, err
95
+ }
96
+ return convertResponse(do), nil
97
+ }
98
+
99
+ func (t *TlsClient) SetProxy(url string) error {
100
+ return t.Client.SetProxy(url)
101
+ }
httpclient/bogdanfinn/tls_client_test.go ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package bogdanfinn
2
+
3
+ import (
4
+ "aurora/httpclient"
5
+ chatgpt_types "aurora/typings/chatgpt"
6
+ "encoding/json"
7
+ "fmt"
8
+ "io"
9
+ "net/http"
10
+ "os"
11
+ "strings"
12
+ "testing"
13
+
14
+ "github.com/joho/godotenv"
15
+ )
16
+
17
+ var BaseURL string
18
+
19
+ func init() {
20
+ _ = godotenv.Load(".env")
21
+ BaseURL = os.Getenv("BASE_URL")
22
+ if BaseURL == "" {
23
+ BaseURL = "https://chat.openai.com/backend-anon"
24
+ }
25
+ }
26
+ func TestTlsClient_Request(t *testing.T) {
27
+ client := NewStdClient()
28
+ userAgent := "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
29
+ proxy := "http://127.0.0.1:7990"
30
+ client.SetProxy(proxy)
31
+
32
+ apiUrl := BaseURL + "/sentinel/chat-requirements"
33
+ payload := strings.NewReader(`{"conversation_mode_kind":"primary_assistant"}`)
34
+ header := make(httpclient.AuroraHeaders)
35
+ header.Set("Content-Type", "application/json")
36
+ header.Set("User-Agent", userAgent)
37
+ header.Set("Accept", "*/*")
38
+ header.Set("oai-language", "en-US")
39
+ header.Set("origin", "https://chat.openai.com")
40
+ header.Set("referer", "https://chat.openai.com/")
41
+ header.Set("oai-device-id", "c83b24f0-5a9e-4c43-8915-3f67d4332609")
42
+ response, err := client.Request(http.MethodPost, apiUrl, header, nil, payload)
43
+ if err != nil {
44
+ return
45
+ }
46
+ defer response.Body.Close()
47
+ fmt.Println(response.StatusCode)
48
+ if response.StatusCode != 200 {
49
+ fmt.Println("Error: ", response.StatusCode)
50
+ }
51
+ var result chatgpt_types.RequirementsResponse
52
+ if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
53
+ return
54
+ }
55
+ fmt.Println(result.Token)
56
+ }
57
+
58
+ func TestChatGPTModel(t *testing.T) {
59
+ client := NewStdClient()
60
+ userAgent := "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
61
+ proxy := "http://127.0.0.1:7990"
62
+ client.SetProxy(proxy)
63
+ apiUrl := "https://chat.openai.com/backend-anon/models"
64
+
65
+ header := make(httpclient.AuroraHeaders)
66
+ header.Set("Content-Type", "application/json")
67
+ header.Set("User-Agent", userAgent)
68
+ header.Set("Accept", "*/*")
69
+ header.Set("oai-language", "en-US")
70
+ header.Set("origin", "https://chat.openai.com")
71
+ header.Set("referer", "https://chat.openai.com/")
72
+ header.Set("oai-device-id", "c83b24f0-5a9e-4c43-8915-3f67d4332609")
73
+ response, err := client.Request(http.MethodGet, apiUrl, header, nil, nil)
74
+ if err != nil {
75
+ return
76
+ }
77
+ defer response.Body.Close()
78
+ fmt.Println(response.StatusCode)
79
+ if response.StatusCode != 200 {
80
+ fmt.Println("Error: ", response.StatusCode)
81
+ body, _ := io.ReadAll(response.Body)
82
+ fmt.Println(string(body))
83
+ return
84
+ }
85
+
86
+ type EnginesData struct {
87
+ Models []struct {
88
+ Slug string `json:"slug"`
89
+ MaxTokens int `json:"max_tokens"`
90
+ Title string `json:"title"`
91
+ Description string `json:"description"`
92
+ Tags []string `json:"tags"`
93
+ Capabilities struct {
94
+ } `json:"capabilities,omitempty"`
95
+ ProductFeatures struct {
96
+ } `json:"product_features,omitempty"`
97
+ } `json:"models"`
98
+ Categories []struct {
99
+ Category string `json:"category"`
100
+ HumanCategoryName string `json:"human_category_name"`
101
+ SubscriptionLevel string `json:"subscription_level"`
102
+ DefaultModel string `json:"default_model"`
103
+ CodeInterpreterModel string `json:"code_interpreter_model,omitempty"`
104
+ PluginsModel string `json:"plugins_model"`
105
+ } `json:"categories"`
106
+ }
107
+
108
+ var result EnginesData
109
+ json.NewDecoder(response.Body).Decode(&result)
110
+ fmt.Println(result)
111
+ }
httpclient/resty/resty_client.go ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package resty
2
+
3
+ import (
4
+ "aurora/util"
5
+ "crypto/tls"
6
+ browser "github.com/EDDYCJY/fake-useragent"
7
+ "github.com/go-resty/resty/v2"
8
+ "net/http"
9
+ "time"
10
+ )
11
+
12
+ type RestyClient struct {
13
+ Client *resty.Client
14
+ }
15
+
16
+ func NewStdClient() *RestyClient {
17
+ client := &RestyClient{
18
+ Client: resty.NewWithClient(&http.Client{
19
+ Transport: &http.Transport{
20
+ // 禁用长连接
21
+ DisableKeepAlives: true,
22
+ // 配置TLS设置,跳过证书验证
23
+ TLSClientConfig: &tls.Config{
24
+ InsecureSkipVerify: true,
25
+ },
26
+ },
27
+ }),
28
+ }
29
+ client.Client.SetBaseURL("https://chat.openai.com")
30
+ client.Client.SetRetryCount(3)
31
+ client.Client.SetRetryWaitTime(5 * time.Second)
32
+ client.Client.SetRetryMaxWaitTime(20 * time.Second)
33
+
34
+ client.Client.SetTimeout(600 * time.Second)
35
+ client.Client.SetHeader("user-agent", browser.Random()).
36
+ SetHeader("accept", "*/*").
37
+ SetHeader("accept-language", "en-US,en;q=0.9").
38
+ SetHeader("cache-control", "no-cache").
39
+ SetHeader("content-type", "application/json").
40
+ SetHeader("oai-language", util.RandomLanguage()).
41
+ SetHeader("pragma", "no-cache").
42
+ SetHeader("sec-ch-ua", `"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"`).
43
+ SetHeader("sec-ch-ua-mobile", "?0").
44
+ SetHeader("sec-ch-ua-platform", "Windows").
45
+ SetHeader("sec-fetch-dest", "empty").
46
+ SetHeader("sec-fetch-mode", "cors").
47
+ SetHeader("sec-fetch-site", "same-origin")
48
+ return client
49
+ }
50
+
51
+ //func (c *RestyClient) Request(method string, url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
52
+ //}
53
+
54
+ //func (c *RestyClient) Post(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
55
+ //}
56
+ //
57
+ //func (c *RestyClient) Get(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
58
+ //}
59
+ //
60
+ //func (c *RestyClient) Head(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
61
+ //}
62
+ //
63
+ //func (c *RestyClient) Options(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
64
+ //}
65
+ //
66
+ //func (c *RestyClient) Put(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
67
+ //}
68
+ //
69
+ //func (c *RestyClient) Delete(url string, headers map[string]string, cookies []*http.Cookie, body io.Reader) (*http.Response, error) {
70
+ //}
71
+ //
72
+ //func (c *RestyClient) SetProxy(url string) error {}
initialize/auth.go ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package initialize
2
+
3
+ import (
4
+ "aurora/internal/tokens"
5
+ "bufio"
6
+ "fmt"
7
+ "os"
8
+ "strconv"
9
+
10
+ "github.com/google/uuid"
11
+ )
12
+
13
+ func readAccessToken() *tokens.AccessToken {
14
+ var Secrets []*tokens.Secret
15
+ // Read accounts.txt and create a list of accounts
16
+ if _, err := os.Stat("access_tokens.txt"); err == nil {
17
+ // Each line is a proxy, put in proxies array
18
+ file, _ := os.Open("access_tokens.txt")
19
+ defer file.Close()
20
+ scanner := bufio.NewScanner(file)
21
+ for scanner.Scan() {
22
+ // Split by :
23
+ token := scanner.Text()
24
+ if len(token) == 0 {
25
+ continue
26
+ }
27
+ // Append to accounts
28
+ Secrets = append(Secrets, tokens.NewSecret(token))
29
+ }
30
+ }
31
+
32
+ // 增加自定义free_tokens.txt,支持文件设置每个账号的uuid
33
+ if _, err := os.Stat("free_tokens.txt"); err == nil {
34
+ // Each line is a proxy, put in proxies array
35
+ file, _ := os.Open("free_tokens.txt")
36
+ defer file.Close()
37
+ scanner := bufio.NewScanner(file)
38
+ for scanner.Scan() {
39
+ // Split by :
40
+ token := scanner.Text()
41
+ if len(token) == 0 {
42
+ continue
43
+ }
44
+ // Append to accounts
45
+ Secrets = append(Secrets, tokens.NewSecretWithFree(token))
46
+ }
47
+ }
48
+
49
+ if os.Getenv("FREE_ACCOUNTS") == "" || os.Getenv("FREE_ACCOUNTS") == "true" {
50
+ freeAccountsNumStr := os.Getenv("FREE_ACCOUNTS_NUM")
51
+ numAccounts := 1024
52
+ if freeAccountsNumStr != "" {
53
+ if freeAccountsNum, err := strconv.Atoi(freeAccountsNumStr); err == nil && freeAccountsNum > 0 {
54
+ numAccounts = freeAccountsNum
55
+ } else {
56
+ fmt.Println("Invalid FREE_ACCOUNTS_NUM:", err)
57
+ }
58
+ }
59
+ for i := 0; i < numAccounts; i++ {
60
+ uid := uuid.NewString()
61
+ Secrets = append(Secrets, tokens.NewSecretWithFree(uid))
62
+ }
63
+ }
64
+
65
+ token := tokens.NewAccessToken(Secrets)
66
+ return &token
67
+ }
initialize/handlers.go ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package initialize
2
+
3
+ import (
4
+ chatgptrequestconverter "aurora/conversion/requests/chatgpt"
5
+ "aurora/duckgo"
6
+ "aurora/httpclient/bogdanfinn"
7
+ "aurora/internal/chatgpt"
8
+ "aurora/internal/proxys"
9
+ "aurora/internal/tokens"
10
+ chatgpt_types "aurora/typings/chatgpt"
11
+ officialtypes "aurora/typings/official"
12
+ "aurora/util"
13
+ "io"
14
+ "os"
15
+ "strings"
16
+
17
+ "github.com/gin-gonic/gin"
18
+ "github.com/google/uuid"
19
+ )
20
+
21
+ type Handler struct {
22
+ proxy *proxys.IProxy
23
+ token *tokens.AccessToken
24
+ }
25
+
26
+ func NewHandle(proxy *proxys.IProxy, token *tokens.AccessToken) *Handler {
27
+ return &Handler{proxy: proxy, token: token}
28
+ }
29
+
30
+ func (h *Handler) refresh(c *gin.Context) {
31
+ var refreshToken officialtypes.OpenAIRefreshToken
32
+ err := c.BindJSON(&refreshToken)
33
+ if err != nil {
34
+ c.JSON(400, gin.H{"error": gin.H{
35
+ "message": "Request must be proper JSON",
36
+ "type": "invalid_request_error",
37
+ "param": nil,
38
+ "code": err.Error(),
39
+ }})
40
+ return
41
+ }
42
+ proxyUrl := h.proxy.GetProxyIP()
43
+ client := bogdanfinn.NewStdClient()
44
+ openaiRefreshToken, status, err := chatgpt.GETTokenForRefreshToken(client, refreshToken.RefreshToken, proxyUrl)
45
+ if err != nil {
46
+ c.JSON(400, gin.H{
47
+ "message": "Request must be proper JSON",
48
+ "type": "invalid_request_error",
49
+ "param": nil,
50
+ "code": err.Error(),
51
+ })
52
+ return
53
+ }
54
+ c.JSON(status, openaiRefreshToken)
55
+ }
56
+
57
+ func (h *Handler) session(c *gin.Context) {
58
+ var sessionToken officialtypes.OpenAISessionToken
59
+ err := c.BindJSON(&sessionToken)
60
+ if err != nil {
61
+ c.JSON(400, gin.H{
62
+ "message": "Request must be proper JSON",
63
+ "type": "invalid_request_error",
64
+ "param": nil,
65
+ "code": err.Error(),
66
+ })
67
+ return
68
+ }
69
+ proxy_url := h.proxy.GetProxyIP()
70
+ client := bogdanfinn.NewStdClient()
71
+ openaiSessionToken, status, err := chatgpt.GETTokenForSessionToken(client, sessionToken.SessionToken, proxy_url)
72
+ if err != nil {
73
+ c.JSON(400, gin.H{"error": gin.H{
74
+ "message": "Request must be proper JSON",
75
+ "type": "invalid_request_error",
76
+ "param": nil,
77
+ "code": err.Error(),
78
+ }})
79
+ return
80
+ }
81
+ c.JSON(status, openaiSessionToken)
82
+ }
83
+
84
+ func optionsHandler(c *gin.Context) {
85
+ // Set headers for CORS
86
+ c.Header("Access-Control-Allow-Origin", "*")
87
+ c.Header("Access-Control-Allow-Methods", "POST")
88
+ c.Header("Access-Control-Allow-Headers", "*")
89
+ c.JSON(200, gin.H{
90
+ "message": "pong",
91
+ })
92
+ }
93
+
94
+ func (h *Handler) refresh_handler(c *gin.Context) {
95
+ var refresh_token officialtypes.OpenAIRefreshToken
96
+ err := c.BindJSON(&refresh_token)
97
+ if err != nil {
98
+ c.JSON(400, gin.H{"error": gin.H{
99
+ "message": "Request must be proper JSON",
100
+ "type": "invalid_request_error",
101
+ "param": nil,
102
+ "code": err.Error(),
103
+ }})
104
+ return
105
+ }
106
+
107
+ proxy_url := h.proxy.GetProxyIP()
108
+ client := bogdanfinn.NewStdClient()
109
+ openaiRefreshToken, status, err := chatgpt.GETTokenForRefreshToken(client, refresh_token.RefreshToken, proxy_url)
110
+ if err != nil {
111
+ c.JSON(400, gin.H{
112
+ "message": "Request must be proper JSON",
113
+ "type": "invalid_request_error",
114
+ "param": nil,
115
+ "code": err.Error(),
116
+ })
117
+ return
118
+ }
119
+ c.JSON(status, openaiRefreshToken)
120
+ }
121
+
122
+ func (h *Handler) session_handler(c *gin.Context) {
123
+ var session_token officialtypes.OpenAISessionToken
124
+ err := c.BindJSON(&session_token)
125
+ if err != nil {
126
+ c.JSON(400, gin.H{
127
+ "message": "Request must be proper JSON",
128
+ "type": "invalid_request_error",
129
+ "param": nil,
130
+ "code": err.Error(),
131
+ })
132
+ return
133
+ }
134
+ proxy_url := h.proxy.GetProxyIP()
135
+ client := bogdanfinn.NewStdClient()
136
+ openaiSessionToken, status, err := chatgpt.GETTokenForSessionToken(client, session_token.SessionToken, proxy_url)
137
+ if err != nil {
138
+ c.JSON(400, gin.H{"error": gin.H{
139
+ "message": "Request must be proper JSON",
140
+ "type": "invalid_request_error",
141
+ "param": nil,
142
+ "code": err.Error(),
143
+ }})
144
+ return
145
+ }
146
+ c.JSON(status, openaiSessionToken)
147
+ }
148
+
149
+ func (h *Handler) duckduckgo(c *gin.Context) {
150
+ var original_request officialtypes.APIRequest
151
+ err := c.BindJSON(&original_request)
152
+ if err != nil {
153
+ c.JSON(400, gin.H{"error": gin.H{
154
+ "message": "Request must be proper JSON",
155
+ "type": "invalid_request_error",
156
+ "param": nil,
157
+ "code": err.Error(),
158
+ }})
159
+ return
160
+ }
161
+ proxyUrl := h.proxy.GetProxyIP()
162
+ client := bogdanfinn.NewStdClient()
163
+ token, err := duckgo.InitXVQD(client, proxyUrl)
164
+ if err != nil {
165
+ c.JSON(500, gin.H{
166
+ "error": err.Error(),
167
+ })
168
+ return
169
+ }
170
+
171
+ translated_request := duckgo.ConvertAPIRequest(original_request)
172
+ response, err := duckgo.POSTconversation(client, translated_request, token, proxyUrl)
173
+ if err != nil {
174
+ c.JSON(500, gin.H{
175
+ "error": "request conversion error",
176
+ })
177
+ return
178
+ }
179
+
180
+ defer response.Body.Close()
181
+ if duckgo.Handle_request_error(c, response) {
182
+ return
183
+ }
184
+ var response_part string
185
+ response_part = duckgo.Handler(c, response, original_request.Stream)
186
+ if c.Writer.Status() != 200 {
187
+ return
188
+ }
189
+ if !original_request.Stream {
190
+ c.JSON(200, officialtypes.NewChatCompletionWithModel(response_part, translated_request.Model))
191
+ } else {
192
+ c.String(200, "data: [DONE]\n\n")
193
+ }
194
+
195
+ }
196
+
197
+ func (h *Handler) nightmare(c *gin.Context) {
198
+ var original_request officialtypes.APIRequest
199
+ err := c.BindJSON(&original_request)
200
+ input_tokens := util.CountToken(original_request.Messages[0].Content)
201
+ if err != nil {
202
+ c.JSON(400, gin.H{"error": gin.H{
203
+ "message": "Request must be proper JSON",
204
+ "type": "invalid_request_error",
205
+ "param": nil,
206
+ "code": err.Error(),
207
+ }})
208
+ return
209
+ }
210
+ proxyUrl := h.proxy.GetProxyIP()
211
+ secret := h.token.GetSecret()
212
+ authHeader := c.GetHeader("Authorization")
213
+ if authHeader != "" {
214
+ customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
215
+ if strings.HasPrefix(customAccessToken, "eyJhbGciOiJSUzI1NiI") {
216
+ secret = h.token.GenerateTempToken(customAccessToken)
217
+ }
218
+ }
219
+ if secret == nil {
220
+ c.JSON(400, gin.H{"error": "Not Account Found."})
221
+ c.Abort()
222
+ return
223
+ }
224
+
225
+ uid := uuid.NewString()
226
+ client := bogdanfinn.NewStdClient()
227
+ //err = chatgpt.InitCfClearance(proxyUrl)
228
+ //if err != nil {
229
+ // c.JSON(500, gin.H{"error": err.Error()})
230
+ // c.Abort()
231
+ // return
232
+ //}
233
+ turnStile, status, err := chatgpt.InitTurnStile(client, secret, proxyUrl)
234
+ if err != nil {
235
+ c.JSON(status, gin.H{
236
+ "message": err.Error(),
237
+ "type": "InitTurnStile_request_error",
238
+ "param": err,
239
+ "code": status,
240
+ })
241
+ return
242
+ }
243
+ if !secret.IsFree {
244
+ err = chatgpt.InitWSConn(client, secret.Token, uid, proxyUrl)
245
+ if err != nil {
246
+ c.JSON(500, gin.H{"error": "unable to create ws tunnel"})
247
+ return
248
+ }
249
+ }
250
+
251
+ // Convert the chat request to a ChatGPT request
252
+ translated_request := chatgptrequestconverter.ConvertAPIRequest(original_request, secret, turnStile.Arkose, proxyUrl)
253
+
254
+ response, err := chatgpt.POSTconversation(client, translated_request, secret, turnStile, proxyUrl)
255
+
256
+ if err != nil {
257
+ c.JSON(500, gin.H{
258
+ "error": "request conversion error",
259
+ })
260
+ return
261
+ }
262
+ defer response.Body.Close()
263
+ if chatgpt.Handle_request_error(c, response) {
264
+ return
265
+ }
266
+ var full_response string
267
+
268
+ if os.Getenv("STREAM_MODE") == "false" {
269
+ original_request.Stream = false
270
+ }
271
+ for i := 3; i > 0; i-- {
272
+ var continue_info *chatgpt.ContinueInfo
273
+ var response_part string
274
+ response_part, continue_info = chatgpt.Handler(c, response, client, secret, uid, translated_request, original_request.Stream)
275
+ full_response += response_part
276
+ if continue_info == nil {
277
+ break
278
+ }
279
+ translated_request.Messages = nil
280
+ translated_request.Action = "continue"
281
+ translated_request.ConversationID = continue_info.ConversationID
282
+ translated_request.ParentMessageID = continue_info.ParentID
283
+
284
+ if turnStile.Arkose {
285
+ chatgptrequestconverter.RenewTokenForRequest(&translated_request, secret.PUID, proxyUrl)
286
+ }
287
+ response, err = chatgpt.POSTconversation(client, translated_request, secret, turnStile, proxyUrl)
288
+
289
+ if err != nil {
290
+ c.JSON(500, gin.H{
291
+ "error": "request conversion error",
292
+ })
293
+ return
294
+ }
295
+ defer response.Body.Close()
296
+ if chatgpt.Handle_request_error(c, response) {
297
+ return
298
+ }
299
+ }
300
+ if c.Writer.Status() != 200 {
301
+ return
302
+ }
303
+ if !original_request.Stream {
304
+ output_tokens := util.CountToken(full_response)
305
+ c.JSON(200, officialtypes.NewChatCompletion(full_response, input_tokens, output_tokens))
306
+ } else {
307
+ c.String(200, "data: [DONE]\n\n")
308
+ }
309
+ chatgpt.UnlockSpecConn(secret.Token, uid)
310
+ }
311
+
312
+ func (h *Handler) engines(c *gin.Context) {
313
+ proxyUrl := h.proxy.GetProxyIP()
314
+ secret := h.token.GetSecret()
315
+ authHeader := c.GetHeader("Authorization")
316
+ if authHeader != "" {
317
+ customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
318
+ // Check if customAccessToken starts with sk-
319
+ if strings.HasPrefix(customAccessToken, "eyJhbGciOiJSUzI1NiI") {
320
+ secret = h.token.GenerateTempToken(customAccessToken)
321
+ }
322
+ }
323
+ if secret == nil || secret.Token == "" {
324
+ c.JSON(400, gin.H{"error": "Not Account Found."})
325
+ return
326
+ }
327
+ client := bogdanfinn.NewStdClient()
328
+ resp, status, err := chatgpt.GETengines(client, secret, proxyUrl)
329
+ if err != nil {
330
+ c.JSON(500, gin.H{
331
+ "error": "error sending request",
332
+ })
333
+ return
334
+ }
335
+
336
+ type ResData struct {
337
+ ID string `json:"id"`
338
+ Object string `json:"object"`
339
+ Created int `json:"created"`
340
+ OwnedBy string `json:"owned_by"`
341
+ }
342
+
343
+ type JSONData struct {
344
+ Object string `json:"object"`
345
+ Data []ResData `json:"data"`
346
+ }
347
+
348
+ modelS := JSONData{
349
+ Object: "list",
350
+ }
351
+ var resModelList []ResData
352
+ if len(resp.Models) > 2 {
353
+ res_data := ResData{
354
+ ID: "gpt-4-mobile",
355
+ Object: "model",
356
+ Created: 1685474247,
357
+ OwnedBy: "openai",
358
+ }
359
+ resModelList = append(resModelList, res_data)
360
+ }
361
+ for _, model := range resp.Models {
362
+ res_data := ResData{
363
+ ID: model.Slug,
364
+ Object: "model",
365
+ Created: 1685474247,
366
+ OwnedBy: "openai",
367
+ }
368
+ if model.Slug == "text-davinci-002-render-sha" {
369
+ res_data.ID = "gpt-3.5-turbo"
370
+ }
371
+ resModelList = append(resModelList, res_data)
372
+ }
373
+ modelS.Data = resModelList
374
+ c.JSON(status, modelS)
375
+ }
376
+
377
+ func (h *Handler) chatgptConversation(c *gin.Context) {
378
+ var original_request chatgpt_types.ChatGPTRequest
379
+ err := c.BindJSON(&original_request)
380
+ if err != nil {
381
+ c.JSON(400, gin.H{"error": gin.H{
382
+ "message": "Request must be proper JSON",
383
+ "type": "invalid_request_error",
384
+ "param": nil,
385
+ "code": err.Error(),
386
+ }})
387
+ return
388
+ }
389
+ if original_request.Messages[0].Author.Role == "" {
390
+ original_request.Messages[0].Author.Role = "user"
391
+ }
392
+
393
+ proxyUrl := h.proxy.GetProxyIP()
394
+
395
+ var secret *tokens.Secret
396
+
397
+ isUUID := func(str string) bool {
398
+ _, err := uuid.Parse(str)
399
+ return err == nil
400
+ }
401
+
402
+ authHeader := c.GetHeader("Authorization")
403
+ if authHeader != "" {
404
+ customAccessToken := strings.Replace(authHeader, "Bearer ", "", 1)
405
+ if strings.HasPrefix(customAccessToken, "eyJhbGciOiJSUzI1NiI") {
406
+ secret = h.token.GenerateTempToken(customAccessToken)
407
+ }
408
+ if isUUID(customAccessToken) {
409
+ secret = h.token.GenerateDeviceId(customAccessToken)
410
+ }
411
+ }
412
+
413
+ if secret == nil {
414
+ secret = h.token.GetSecret()
415
+ }
416
+
417
+ client := bogdanfinn.NewStdClient()
418
+ turnStile, status, err := chatgpt.InitTurnStile(client, secret, proxyUrl)
419
+ if err != nil {
420
+ c.JSON(status, gin.H{
421
+ "message": err.Error(),
422
+ "type": "InitTurnStile_request_error",
423
+ "param": err,
424
+ "code": status,
425
+ })
426
+ return
427
+ }
428
+
429
+ response, err := chatgpt.POSTconversation(client, original_request, secret, turnStile, proxyUrl)
430
+ if err != nil {
431
+ c.JSON(500, gin.H{
432
+ "error": "error sending request",
433
+ })
434
+ return
435
+ }
436
+ defer response.Body.Close()
437
+
438
+ if chatgpt.Handle_request_error(c, response) {
439
+ return
440
+ }
441
+
442
+ c.Header("Content-Type", response.Header.Get("Content-Type"))
443
+ if cacheControl := response.Header.Get("Cache-Control"); cacheControl != "" {
444
+ c.Header("Cache-Control", cacheControl)
445
+ }
446
+
447
+ _, err = io.Copy(c.Writer, response.Body)
448
+ if err != nil {
449
+ c.JSON(500, gin.H{"error": "Error sending response"})
450
+ }
451
+ }
initialize/proxy.go ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package initialize
2
+
3
+ import (
4
+ "aurora/internal/proxys"
5
+ "bufio"
6
+ "log/slog"
7
+ "net/url"
8
+ "os"
9
+ )
10
+
11
+ func checkProxy() *proxys.IProxy {
12
+ var proxies []string
13
+ proxyUrl := os.Getenv("PROXY_URL")
14
+ if proxyUrl != "" {
15
+ proxies = append(proxies, proxyUrl)
16
+ }
17
+
18
+ if _, err := os.Stat("proxies.txt"); err == nil {
19
+ file, _ := os.Open("proxies.txt")
20
+ defer file.Close()
21
+ scanner := bufio.NewScanner(file)
22
+ for scanner.Scan() {
23
+ proxy := scanner.Text()
24
+ parsedURL, err := url.Parse(proxy)
25
+ if err != nil {
26
+ slog.Warn("proxy url is invalid", "url", proxy, "err", err)
27
+ continue
28
+ }
29
+
30
+ // 如果缺少端口信息,不是完整的代理链接
31
+ if parsedURL.Port() != "" {
32
+ proxies = append(proxies, proxy)
33
+ } else {
34
+ continue
35
+ }
36
+ }
37
+ }
38
+
39
+ if len(proxies) == 0 {
40
+ proxy := os.Getenv("http_proxy")
41
+ if proxy != "" {
42
+ proxies = append(proxies, proxy)
43
+ }
44
+ }
45
+
46
+ proxyIP := proxys.NewIProxyIP(proxies)
47
+ return &proxyIP
48
+ }
initialize/router.go ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package initialize
2
+
3
+ import (
4
+ "aurora/middlewares"
5
+
6
+ "github.com/gin-gonic/gin"
7
+ )
8
+
9
+ func RegisterRouter() *gin.Engine {
10
+ handler := NewHandle(
11
+ checkProxy(),
12
+ readAccessToken(),
13
+ )
14
+
15
+ router := gin.Default()
16
+ router.Use(middlewares.Cors)
17
+
18
+ router.GET("/", func(c *gin.Context) {
19
+ c.JSON(200, gin.H{
20
+ "message": "Hello, world!",
21
+ })
22
+ })
23
+
24
+ router.GET("/ping", func(c *gin.Context) {
25
+ c.JSON(200, gin.H{
26
+ "message": "pong",
27
+ })
28
+ })
29
+
30
+ router.POST("/auth/session", handler.session)
31
+ router.POST("/auth/refresh", handler.refresh)
32
+ router.OPTIONS("/api/v1/chat/completions", optionsHandler)
33
+
34
+ authGroup := router.Group("").Use(middlewares.Authorization)
35
+ authGroup.POST("/api/v1/chat/completions", handler.duckduckgo)
36
+ authGroup.GET("/api/v1/models", handler.engines)
37
+ authGroup.POST("/backend-api/conversation", handler.chatgptConversation)
38
+ return router
39
+ }
internal/chatgpt/request.go ADDED
@@ -0,0 +1,949 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package chatgpt
2
+
3
+ import (
4
+ "aurora/conversion/response/chatgpt"
5
+ "aurora/httpclient"
6
+ "aurora/internal/tokens"
7
+ "aurora/typings"
8
+ chatgpt_types "aurora/typings/chatgpt"
9
+ official_types "aurora/typings/official"
10
+ "aurora/util"
11
+ "bufio"
12
+ "bytes"
13
+ "context"
14
+ "encoding/base64"
15
+ "encoding/hex"
16
+ "encoding/json"
17
+ "errors"
18
+ "fmt"
19
+ "math/rand"
20
+ "net/http"
21
+
22
+ "golang.org/x/crypto/sha3"
23
+
24
+ //http "github.com/bogdanfinn/fhttp"
25
+ "io"
26
+ "net/url"
27
+ "os"
28
+ "strconv"
29
+ "strings"
30
+ "sync"
31
+ "time"
32
+
33
+ "github.com/gin-gonic/gin"
34
+ "github.com/google/uuid"
35
+ "github.com/gorilla/websocket"
36
+ "github.com/joho/godotenv"
37
+ )
38
+
39
+ var BaseURL string
40
+
41
+ func init() {
42
+ _ = godotenv.Load(".env")
43
+ BaseURL = os.Getenv("BASE_URL")
44
+ if BaseURL == "" {
45
+ BaseURL = "https://chat.openai.com/backend-anon"
46
+ }
47
+ }
48
+
49
+ type connInfo struct {
50
+ conn *websocket.Conn
51
+ uuid string
52
+ expire time.Time
53
+ ticker *time.Ticker
54
+ lock bool
55
+ }
56
+
57
+ var (
58
+ API_REVERSE_PROXY = os.Getenv("API_REVERSE_PROXY")
59
+ FILES_REVERSE_PROXY = os.Getenv("FILES_REVERSE_PROXY")
60
+ connPool = map[string][]*connInfo{}
61
+ poolMutex = sync.Mutex{}
62
+ TurnStilePool = map[string]*TurnStile{}
63
+ userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.0.0 Safari/537.36"
64
+ cores = []int{8, 12, 16, 24}
65
+ screens = []int{3000, 4000, 6000}
66
+ timeLocation, _ = time.LoadLocation("Asia/Shanghai")
67
+ timeLayout = "Mon Jan 2 2006 15:04:05"
68
+ cf_clearance *CfClearance
69
+ )
70
+
71
+ type CfClearance struct {
72
+ cfClearance string
73
+ ExpireAt time.Time
74
+ }
75
+
76
+ func getWSURL(client httpclient.AuroraHttpClient, token string, retry int) (string, error) {
77
+ requestURL := BaseURL + "/register-websocket"
78
+ header := make(httpclient.AuroraHeaders)
79
+ header.Set("User-Agent", userAgent)
80
+ header.Set("Accept", "*/*")
81
+ header.Set("Oai-Language", "en-US")
82
+ if token != "" {
83
+ header.Set("Authorization", "Bearer "+token)
84
+ }
85
+ response, err := client.Request(http.MethodPost, requestURL, header, nil, nil)
86
+ if err != nil {
87
+ if retry > 3 {
88
+ return "", err
89
+ }
90
+ time.Sleep(time.Second) // wait 1s to get ws url
91
+ return getWSURL(client, token, retry+1)
92
+ }
93
+ defer response.Body.Close()
94
+ var WSSResp chatgpt_types.ChatGPTWSSResponse
95
+ err = json.NewDecoder(response.Body).Decode(&WSSResp)
96
+ if err != nil {
97
+ return "", err
98
+ }
99
+ return WSSResp.WssUrl, nil
100
+ }
101
+
102
+ func createWSConn(client httpclient.AuroraHttpClient, url string, connInfo *connInfo, retry int) error {
103
+ dialer := websocket.DefaultDialer
104
+ dialer.EnableCompression = true
105
+ dialer.Subprotocols = []string{"json.reliable.webpubsub.azure.v1"}
106
+ conn, _, err := dialer.Dial(url, nil)
107
+ if err != nil {
108
+ if retry > 3 {
109
+ return err
110
+ }
111
+ time.Sleep(time.Second) // wait 1s to recreate ws
112
+ return createWSConn(client, url, connInfo, retry+1)
113
+ }
114
+ connInfo.conn = conn
115
+ connInfo.expire = time.Now().Add(time.Minute * 30)
116
+ ticker := time.NewTicker(time.Second * 8)
117
+ connInfo.ticker = ticker
118
+ go func(ticker *time.Ticker) {
119
+ defer ticker.Stop()
120
+ for {
121
+ <-ticker.C
122
+ if err := connInfo.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
123
+ connInfo.conn.Close()
124
+ connInfo.conn = nil
125
+ break
126
+ }
127
+ }
128
+ }(ticker)
129
+ return nil
130
+ }
131
+
132
+ func findAvailConn(token string, uuid string) *connInfo {
133
+ for _, value := range connPool[token] {
134
+ if !value.lock {
135
+ value.lock = true
136
+ value.uuid = uuid
137
+ return value
138
+ }
139
+ }
140
+ newConnInfo := connInfo{uuid: uuid, lock: true}
141
+ connPool[token] = append(connPool[token], &newConnInfo)
142
+ return &newConnInfo
143
+ }
144
+ func findSpecConn(token string, uuid string) *connInfo {
145
+ for _, value := range connPool[token] {
146
+ if value.uuid == uuid {
147
+ return value
148
+ }
149
+ }
150
+ return &connInfo{}
151
+ }
152
+ func UnlockSpecConn(token string, uuid string) {
153
+ for _, value := range connPool[token] {
154
+ if value.uuid == uuid {
155
+ value.lock = false
156
+ }
157
+ }
158
+ }
159
+
160
+ func InitWSConn(client httpclient.AuroraHttpClient, token string, uuid string, proxy string) error {
161
+ connInfo := findAvailConn(token, uuid)
162
+ conn := connInfo.conn
163
+ isExpired := connInfo.expire.IsZero() || time.Now().After(connInfo.expire)
164
+ if conn == nil || isExpired {
165
+ if proxy != "" {
166
+ client.SetProxy(proxy)
167
+ }
168
+ if conn != nil {
169
+ connInfo.ticker.Stop()
170
+ conn.Close()
171
+ connInfo.conn = nil
172
+ }
173
+ wssURL, err := getWSURL(client, token, 0)
174
+ if err != nil {
175
+ return err
176
+ }
177
+ err = createWSConn(client, wssURL, connInfo, 0)
178
+ if err != nil {
179
+ return err
180
+ }
181
+ return nil
182
+ } else {
183
+ ctx, cancelFunc := context.WithTimeout(context.Background(), time.Millisecond*100)
184
+ go func() {
185
+ defer cancelFunc()
186
+ for {
187
+ _, _, err := conn.NextReader()
188
+ if err != nil {
189
+ break
190
+ }
191
+ if ctx.Err() != nil {
192
+ break
193
+ }
194
+ }
195
+ }()
196
+ <-ctx.Done()
197
+ err := ctx.Err()
198
+ if err != nil {
199
+ switch err {
200
+ case context.Canceled:
201
+ connInfo.ticker.Stop()
202
+ conn.Close()
203
+ connInfo.conn = nil
204
+ connInfo.lock = false
205
+ return InitWSConn(client, token, uuid, proxy)
206
+ case context.DeadlineExceeded:
207
+ return nil
208
+ default:
209
+ return nil
210
+ }
211
+ }
212
+ return nil
213
+ }
214
+ }
215
+
216
+ type ChatRequire struct {
217
+ Token string `json:"token"`
218
+ Arkose struct {
219
+ Required bool `json:"required"`
220
+ DX string `json:"dx,omitempty"`
221
+ } `json:"arkose"`
222
+
223
+ Turnstile struct {
224
+ Required bool `json:"required"`
225
+ }
226
+ }
227
+
228
+ type TurnStile struct {
229
+ TurnStileToken string
230
+ ProofOfWorkToken string
231
+ Arkose bool
232
+ ExpireAt time.Time
233
+ }
234
+
235
+ type ProofWork struct {
236
+ Difficulty string `json:"difficulty,omitempty"`
237
+ Required bool `json:"required"`
238
+ Seed string `json:"seed,omitempty"`
239
+ }
240
+
241
+ func getParseTime() string {
242
+ now := time.Now()
243
+ now = now.In(timeLocation)
244
+ return now.Format(timeLayout) + " GMT+0800 (中国标准时间)"
245
+ }
246
+ func getConfig() []interface{} {
247
+ rand.New(rand.NewSource(time.Now().UnixNano()))
248
+ core := cores[rand.Intn(4)]
249
+ rand.New(rand.NewSource(time.Now().UnixNano()))
250
+ screen := screens[rand.Intn(3)]
251
+ return []interface{}{core + screen, getParseTime(), int64(4294705152), 0, userAgent}
252
+
253
+ }
254
+ func CalcProofToken(seed string, diff string) string {
255
+ config := getConfig()
256
+ diffLen := len(diff) / 2
257
+ hasher := sha3.New512()
258
+ for i := 0; i < 100000; i++ {
259
+ config[3] = i
260
+ json, _ := json.Marshal(config)
261
+ base := base64.StdEncoding.EncodeToString(json)
262
+ hasher.Write([]byte(seed + base))
263
+ hash := hasher.Sum(nil)
264
+ hasher.Reset()
265
+ if hex.EncodeToString(hash[:diffLen]) <= diff {
266
+ return "gAAAAAB" + base
267
+ }
268
+ }
269
+ return "gAAAAABwQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D" + base64.StdEncoding.EncodeToString([]byte(`"`+seed+`"`))
270
+ }
271
+
272
+ func InitCfClearance(proxy string) error {
273
+ poolMutex.Lock()
274
+ defer poolMutex.Unlock()
275
+ if cf_clearance == nil || cf_clearance.ExpireAt.Before(time.Now()) {
276
+ resp, err := getCf(proxy)
277
+ if err != nil {
278
+ return err
279
+ }
280
+ cf_clearance = &CfClearance{
281
+ cfClearance: resp,
282
+ ExpireAt: time.Now().Add(30 * time.Minute),
283
+ }
284
+ }
285
+ return nil
286
+ }
287
+
288
+ func InitTurnStile(client httpclient.AuroraHttpClient, secret *tokens.Secret, proxy string) (*TurnStile, int, error) {
289
+ poolMutex.Lock()
290
+ defer poolMutex.Unlock()
291
+ currTurnToken := TurnStilePool[secret.Token]
292
+ if currTurnToken == nil || currTurnToken.ExpireAt.Before(time.Now()) {
293
+ response, err := POSTTurnStile(client, secret, proxy, 0)
294
+ if err != nil {
295
+ return nil, http.StatusInternalServerError, err
296
+ }
297
+ defer response.Body.Close()
298
+ if response.StatusCode != 200 {
299
+ return nil, response.StatusCode, fmt.Errorf("failed to get chat requirements")
300
+ }
301
+ var result chatgpt_types.RequirementsResponse
302
+ if err := json.NewDecoder(response.Body).Decode(&result); err != nil {
303
+ return nil, response.StatusCode, err
304
+ }
305
+
306
+ currTurnToken = &TurnStile{
307
+ TurnStileToken: result.Token,
308
+ Arkose: result.Arkose.Required,
309
+ ExpireAt: time.Now().Add(5 * time.Second),
310
+ }
311
+ if result.Proof.Required == true {
312
+ currTurnToken.ProofOfWorkToken = CalcProofToken(result.Proof.Seed, result.Proof.Difficulty)
313
+ }
314
+
315
+ // 如果是免登账号,将其放入池子
316
+ if secret.IsFree {
317
+ TurnStilePool[secret.Token] = currTurnToken
318
+ }
319
+ }
320
+ return currTurnToken, 0, nil
321
+ }
322
+ func POSTTurnStile(client httpclient.AuroraHttpClient, secret *tokens.Secret, proxy string, retry int) (*http.Response, error) {
323
+ if proxy != "" {
324
+ client.SetProxy(proxy)
325
+ }
326
+ apiUrl := BaseURL + "/sentinel/chat-requirements"
327
+ payload := strings.NewReader(`{"conversation_mode_kind":"primary_assistant"}`)
328
+
329
+ header := createBaseHeader()
330
+ header.Set("content-type", "application/json")
331
+ if !secret.IsFree && secret.Token != "" {
332
+ header.Set("Authorization", "Bearer "+secret.Token)
333
+ }
334
+ if secret.IsFree {
335
+ header.Set("oai-device-id", secret.Token)
336
+ }
337
+ var cookie *http.Cookie
338
+ // 补全伪装环境参数,无实质用处。
339
+ cookie = &http.Cookie{Name: "cf_clearance", Value: cf_clearance.cfClearance}
340
+ response, err := client.Request(http.MethodPost, apiUrl, header, []*http.Cookie{cookie}, payload)
341
+ if err != nil {
342
+ return &http.Response{}, err
343
+ }
344
+ if response.StatusCode == 401 && secret.IsFree {
345
+ if retry > 3 {
346
+ return response, err
347
+ }
348
+ time.Sleep(time.Second * 2)
349
+ secret.Token = uuid.NewString()
350
+ return POSTTurnStile(client, secret, proxy, retry+1)
351
+ }
352
+ return response, err
353
+ }
354
+
355
+ var urlAttrMap = make(map[string]string)
356
+
357
+ type urlAttr struct {
358
+ Url string `json:"url"`
359
+ Attribution string `json:"attribution"`
360
+ }
361
+
362
+ func getURLAttribution(client httpclient.AuroraHttpClient, access_token string, puid string, url string) string {
363
+ requestURL := BaseURL + "/attributions"
364
+ payload := bytes.NewBuffer([]byte(`{"urls":["` + url + `"]}`))
365
+ header := createBaseHeader()
366
+ if puid != "" {
367
+ header.Set("Cookie", "_puid="+puid+";")
368
+ }
369
+ header.Set("Content-Type", "application/json")
370
+ if access_token != "" {
371
+ header.Set("Authorization", "Bearer "+access_token)
372
+ }
373
+ response, err := client.Request(http.MethodPost, requestURL, header, nil, payload)
374
+ if err != nil {
375
+ return ""
376
+ }
377
+ defer response.Body.Close()
378
+ var attr urlAttr
379
+ err = json.NewDecoder(response.Body).Decode(&attr)
380
+ if err != nil {
381
+ return ""
382
+ }
383
+ return attr.Attribution
384
+ }
385
+
386
+ func getCf(proxy string) (string, error) {
387
+ client := &http.Client{}
388
+ if proxy != "" {
389
+ client.Transport = &http.Transport{
390
+ Proxy: func(req *http.Request) (*url.URL, error) {
391
+ return url.Parse(proxy)
392
+ },
393
+ }
394
+ }
395
+
396
+ var data = strings.NewReader(`{}`)
397
+ req, err := http.NewRequest("POST", "https://chat.openai.com/cdn-cgi/challenge-platform/h/b/jsd/r/"+util.RandomHexadecimalString(), data)
398
+ if err != nil {
399
+ return "", err
400
+ }
401
+ req.Header.Set("accept", "*/*")
402
+ req.Header.Set("accept-language", "zh-CN,zh;q=0.9")
403
+ req.Header.Set("content-type", "application/json")
404
+ req.Header.Set("origin", "https://chat.openai.com")
405
+ req.Header.Set("sec-ch-ua", `"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"`)
406
+ req.Header.Set("sec-ch-ua-mobile", "?0")
407
+ req.Header.Set("sec-ch-ua-platform", `"Windows"`)
408
+ req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.0.0 Safari/537.36")
409
+ resp, err := client.Do(req)
410
+ if err != nil {
411
+ return "", err
412
+ }
413
+ defer resp.Body.Close()
414
+ if resp.StatusCode != 200 {
415
+ return "", errors.New("failed to get cf clearance")
416
+ }
417
+ for _, cookie := range resp.Cookies() {
418
+ if cookie.Name == "cf_clearance" {
419
+ return cookie.Value, nil
420
+ }
421
+ }
422
+ return "", errors.New("ailed to get cf clearance")
423
+ }
424
+
425
+ func POSTconversation(client httpclient.AuroraHttpClient, message chatgpt_types.ChatGPTRequest, secret *tokens.Secret, chat_token *TurnStile, proxy string) (*http.Response, error) {
426
+ if proxy != "" {
427
+ client.SetProxy(proxy)
428
+ }
429
+ apiUrl := BaseURL + "/conversation"
430
+ if API_REVERSE_PROXY != "" {
431
+ apiUrl = API_REVERSE_PROXY
432
+ }
433
+ arkoseToken := message.ArkoseToken
434
+ message.ArkoseToken = ""
435
+
436
+ // JSONify the body and add it to the request
437
+ body_json, err := json.Marshal(message)
438
+ if err != nil {
439
+ return &http.Response{}, err
440
+ }
441
+ header := createBaseHeader()
442
+ header.Set("content-type", "application/json")
443
+ // Clear cookies
444
+ if secret.PUID != "" {
445
+ header.Set("Cookie", "_puid="+secret.PUID+";")
446
+ }
447
+ if chat_token.Arkose {
448
+ header.Set("openai-sentinel-arkose-token", arkoseToken)
449
+ }
450
+ if chat_token.TurnStileToken != "" {
451
+ header.Set("Openai-Sentinel-Chat-Requirements-Token", chat_token.TurnStileToken)
452
+ }
453
+ if chat_token.ProofOfWorkToken != "" {
454
+ header.Set("Openai-Sentinel-Proof-Token", chat_token.ProofOfWorkToken)
455
+ }
456
+ if !secret.IsFree && secret.Token != "" {
457
+ header.Set("Authorization", "Bearer "+secret.Token)
458
+ }
459
+ if secret.IsFree {
460
+ header.Set("oai-device-id", secret.Token)
461
+ }
462
+ var cookie *http.Cookie
463
+ // 补全伪装环境参数,无实质用处。
464
+ cookie = &http.Cookie{Name: "cf_clearance", Value: cf_clearance.cfClearance}
465
+ response, err := client.Request(http.MethodPost, apiUrl, header, []*http.Cookie{cookie}, bytes.NewBuffer(body_json))
466
+ if err != nil {
467
+ return nil, err
468
+ }
469
+ return response, nil
470
+ }
471
+
472
+ type EnginesData struct {
473
+ Models []struct {
474
+ Slug string `json:"slug"`
475
+ MaxTokens int `json:"max_tokens"`
476
+ Title string `json:"title"`
477
+ Description string `json:"description"`
478
+ Tags []string `json:"tags"`
479
+ Capabilities struct {
480
+ } `json:"capabilities,omitempty"`
481
+ ProductFeatures struct {
482
+ } `json:"product_features,omitempty"`
483
+ } `json:"models"`
484
+ Categories []struct {
485
+ Category string `json:"category"`
486
+ HumanCategoryName string `json:"human_category_name"`
487
+ SubscriptionLevel string `json:"subscription_level"`
488
+ DefaultModel string `json:"default_model"`
489
+ CodeInterpreterModel string `json:"code_interpreter_model,omitempty"`
490
+ PluginsModel string `json:"plugins_model"`
491
+ } `json:"categories"`
492
+ }
493
+
494
+ func GETengines(client httpclient.AuroraHttpClient, secret *tokens.Secret, proxy string) (*EnginesData, int, error) {
495
+ if proxy != "" {
496
+ client.SetProxy(proxy)
497
+ }
498
+ reqUrl := BaseURL + "/models"
499
+ header := make(httpclient.AuroraHeaders)
500
+ header.Set("Content-Type", "application/json")
501
+ header.Set("User-Agent", userAgent)
502
+ header.Set("Accept", "*/*")
503
+ header.Set("oai-language", "en-US")
504
+ header.Set("origin", "https://chat.openai.com")
505
+ header.Set("referer", "https://chat.openai.com/")
506
+
507
+ if !secret.IsFree && secret.Token != "" {
508
+ header.Set("Authorization", "Bearer "+secret.Token)
509
+ }
510
+ if secret.IsFree {
511
+ header.Set("Oai-Device-Id", secret.Token)
512
+ }
513
+ if secret.PUID != "" {
514
+ header.Set("Cookie", "_puid="+secret.PUID+";")
515
+ }
516
+ resp, err := client.Request(http.MethodGet, reqUrl, header, nil, nil)
517
+ if err != nil {
518
+ return nil, 0, err
519
+ }
520
+ defer resp.Body.Close()
521
+
522
+ var result EnginesData
523
+ json.NewDecoder(resp.Body).Decode(&result)
524
+ return &result, resp.StatusCode, nil
525
+ }
526
+
527
+ func Handle_request_error(c *gin.Context, response *http.Response) bool {
528
+ if response.StatusCode != 200 {
529
+ // Try read response body as JSON
530
+ var error_response map[string]interface{}
531
+ err := json.NewDecoder(response.Body).Decode(&error_response)
532
+ if err != nil {
533
+ // Read response body
534
+ body, _ := io.ReadAll(response.Body)
535
+ c.JSON(response.StatusCode, gin.H{"error": gin.H{
536
+ "message": "Unknown error",
537
+ "type": "internal_server_error",
538
+ "param": nil,
539
+ "code": "500",
540
+ "details": string(body),
541
+ }})
542
+ return true
543
+ }
544
+ c.JSON(response.StatusCode, gin.H{"error": gin.H{
545
+ "message": error_response["detail"],
546
+ "type": response.Status,
547
+ "param": nil,
548
+ "code": "error",
549
+ }})
550
+ return true
551
+ }
552
+ return false
553
+ }
554
+
555
+ type ContinueInfo struct {
556
+ ConversationID string `json:"conversation_id"`
557
+ ParentID string `json:"parent_id"`
558
+ }
559
+
560
+ type fileInfo struct {
561
+ DownloadURL string `json:"download_url"`
562
+ Status string `json:"status"`
563
+ }
564
+
565
+ func GetImageSource(client httpclient.AuroraHttpClient, wg *sync.WaitGroup, url string, prompt string, token string, puid string, idx int, imgSource []string) {
566
+ defer wg.Done()
567
+ header := make(httpclient.AuroraHeaders)
568
+ // Clear cookies
569
+ if puid != "" {
570
+ header.Set("Cookie", "_puid="+puid+";")
571
+ }
572
+ header.Set("User-Agent", userAgent)
573
+ header.Set("Accept", "*/*")
574
+ if token != "" {
575
+ header.Set("Authorization", "Bearer "+token)
576
+ }
577
+ response, err := client.Request(http.MethodGet, url, header, nil, nil)
578
+ if err != nil {
579
+ return
580
+ }
581
+ defer response.Body.Close()
582
+ var file_info fileInfo
583
+ err = json.NewDecoder(response.Body).Decode(&file_info)
584
+ if err != nil || file_info.Status != "success" {
585
+ return
586
+ }
587
+ imgSource[idx] = "[![image](" + file_info.DownloadURL + " \"" + prompt + "\")](" + file_info.DownloadURL + ")"
588
+ }
589
+
590
+ func Handler(c *gin.Context, response *http.Response, client httpclient.AuroraHttpClient, secret *tokens.Secret, uuid string, translated_request chatgpt_types.ChatGPTRequest, stream bool) (string, *ContinueInfo) {
591
+ max_tokens := false
592
+
593
+ // Create a bufio.Reader from the response body
594
+ reader := bufio.NewReader(response.Body)
595
+
596
+ // Read the response byte by byte until a newline character is encountered
597
+ if stream {
598
+ // Response content type is text/event-stream
599
+ c.Header("Content-Type", "text/event-stream")
600
+ } else {
601
+ // Response content type is application/json
602
+ c.Header("Content-Type", "application/json")
603
+ }
604
+ var finish_reason string
605
+ var previous_text typings.StringStruct
606
+ var original_response chatgpt_types.ChatGPTResponse
607
+ var isRole = true
608
+ var waitSource = false
609
+ var isEnd = false
610
+ var imgSource []string
611
+ var isWSS = false
612
+ var convId string
613
+ var respId string
614
+ var wssUrl string
615
+ var connInfo *connInfo
616
+ var wsSeq int
617
+ var isWSInterrupt bool = false
618
+ var interruptTimer *time.Timer
619
+
620
+ if !strings.Contains(response.Header.Get("Content-Type"), "text/event-stream") {
621
+ isWSS = true
622
+ connInfo = findSpecConn(secret.Token, uuid)
623
+ if connInfo.conn == nil {
624
+ c.JSON(500, gin.H{"error": "No websocket connection"})
625
+ return "", nil
626
+ }
627
+ var wssResponse chatgpt_types.ChatGPTWSSResponse
628
+ json.NewDecoder(response.Body).Decode(&wssResponse)
629
+ wssUrl = wssResponse.WssUrl
630
+ respId = wssResponse.ResponseId
631
+ convId = wssResponse.ConversationId
632
+ }
633
+ for {
634
+ var line string
635
+ var err error
636
+ if isWSS {
637
+ var messageType int
638
+ var message []byte
639
+ if isWSInterrupt {
640
+ if interruptTimer == nil {
641
+ interruptTimer = time.NewTimer(10 * time.Second)
642
+ }
643
+ select {
644
+ case <-interruptTimer.C:
645
+ c.JSON(500, gin.H{"error": "WS interrupt & new WS timeout"})
646
+ return "", nil
647
+ default:
648
+ goto reader
649
+ }
650
+ }
651
+ reader:
652
+ messageType, message, err = connInfo.conn.ReadMessage()
653
+ if err != nil {
654
+ connInfo.ticker.Stop()
655
+ connInfo.conn.Close()
656
+ connInfo.conn = nil
657
+ err := createWSConn(client, wssUrl, connInfo, 0)
658
+ if err != nil {
659
+ c.JSON(500, gin.H{"error": err.Error()})
660
+ return "", nil
661
+ }
662
+ isWSInterrupt = true
663
+ connInfo.conn.WriteMessage(websocket.TextMessage, []byte("{\"type\":\"sequenceAck\",\"sequenceId\":"+strconv.Itoa(wsSeq)+"}"))
664
+ continue
665
+ }
666
+ if messageType == websocket.TextMessage {
667
+ var wssMsgResponse chatgpt_types.WSSMsgResponse
668
+ json.Unmarshal(message, &wssMsgResponse)
669
+ if wssMsgResponse.Data.ResponseId != respId {
670
+ continue
671
+ }
672
+ wsSeq = wssMsgResponse.SequenceId
673
+ if wsSeq%50 == 0 {
674
+ connInfo.conn.WriteMessage(websocket.TextMessage, []byte("{\"type\":\"sequenceAck\",\"sequenceId\":"+strconv.Itoa(wsSeq)+"}"))
675
+ }
676
+ base64Body := wssMsgResponse.Data.Body
677
+ bodyByte, err := base64.StdEncoding.DecodeString(base64Body)
678
+ if err != nil {
679
+ continue
680
+ }
681
+ if isWSInterrupt {
682
+ isWSInterrupt = false
683
+ interruptTimer.Stop()
684
+ }
685
+ line = string(bodyByte)
686
+ }
687
+ } else {
688
+ line, err = reader.ReadString('\n')
689
+ if err != nil {
690
+ if err == io.EOF {
691
+ break
692
+ }
693
+ return "", nil
694
+ }
695
+ }
696
+ if len(line) < 6 {
697
+ continue
698
+ }
699
+ // Remove "data: " from the beginning of the line
700
+ line = line[6:]
701
+ // Check if line starts with [DONE]
702
+ if !strings.HasPrefix(line, "[DONE]") {
703
+ // Parse the line as JSON
704
+ err = json.Unmarshal([]byte(line), &original_response)
705
+ if err != nil {
706
+ continue
707
+ }
708
+ if original_response.Error != nil {
709
+ c.JSON(500, gin.H{"error": original_response.Error})
710
+ return "", nil
711
+ }
712
+ if original_response.ConversationID != convId {
713
+ if convId == "" {
714
+ convId = original_response.ConversationID
715
+ } else {
716
+ continue
717
+ }
718
+ }
719
+ if !(original_response.Message.Author.Role == "assistant" || (original_response.Message.Author.Role == "tool" && original_response.Message.Content.ContentType != "text")) || original_response.Message.Content.Parts == nil {
720
+ continue
721
+ }
722
+ if original_response.Message.Metadata.MessageType == "" {
723
+ continue
724
+ }
725
+ if original_response.Message.Metadata.MessageType != "next" && original_response.Message.Metadata.MessageType != "continue" || !strings.HasSuffix(original_response.Message.Content.ContentType, "text") {
726
+ continue
727
+ }
728
+ if original_response.Message.EndTurn != nil {
729
+ if waitSource {
730
+ waitSource = false
731
+ }
732
+ isEnd = true
733
+ }
734
+ if len(original_response.Message.Metadata.Citations) != 0 {
735
+ r := []rune(original_response.Message.Content.Parts[0].(string))
736
+ if waitSource {
737
+ if string(r[len(r)-1:]) == "】" {
738
+ waitSource = false
739
+ } else {
740
+ continue
741
+ }
742
+ }
743
+ offset := 0
744
+ for _, citation := range original_response.Message.Metadata.Citations {
745
+ rl := len(r)
746
+ attr := urlAttrMap[citation.Metadata.URL]
747
+ if attr == "" {
748
+ u, _ := url.Parse(citation.Metadata.URL)
749
+ BaseURL := u.Scheme + "://" + u.Host + "/"
750
+ attr = getURLAttribution(client, secret.Token, secret.PUID, BaseURL)
751
+ if attr != "" {
752
+ urlAttrMap[citation.Metadata.URL] = attr
753
+ }
754
+ }
755
+ original_response.Message.Content.Parts[0] = string(r[:citation.StartIx+offset]) + " ([" + attr + "](" + citation.Metadata.URL + " \"" + citation.Metadata.Title + "\"))" + string(r[citation.EndIx+offset:])
756
+ r = []rune(original_response.Message.Content.Parts[0].(string))
757
+ offset += len(r) - rl
758
+ }
759
+ } else if waitSource {
760
+ continue
761
+ }
762
+ response_string := ""
763
+ if original_response.Message.Recipient != "all" {
764
+ continue
765
+ }
766
+ if original_response.Message.Content.ContentType == "multimodal_text" {
767
+ apiUrl := BaseURL + "/files/"
768
+ if FILES_REVERSE_PROXY != "" {
769
+ apiUrl = FILES_REVERSE_PROXY
770
+ }
771
+ imgSource = make([]string, len(original_response.Message.Content.Parts))
772
+ var wg sync.WaitGroup
773
+ for index, part := range original_response.Message.Content.Parts {
774
+ jsonItem, _ := json.Marshal(part)
775
+ var dalle_content chatgpt_types.DalleContent
776
+ err = json.Unmarshal(jsonItem, &dalle_content)
777
+ if err != nil {
778
+ continue
779
+ }
780
+ url := apiUrl + strings.Split(dalle_content.AssetPointer, "//")[1] + "/download"
781
+ wg.Add(1)
782
+ go GetImageSource(client, &wg, url, dalle_content.Metadata.Dalle.Prompt, secret.Token, secret.PUID, index, imgSource)
783
+ }
784
+ wg.Wait()
785
+ translated_response := official_types.NewChatCompletionChunk(strings.Join(imgSource, ""))
786
+ if isRole {
787
+ translated_response.Choices[0].Delta.Role = original_response.Message.Author.Role
788
+ }
789
+ response_string = "data: " + translated_response.String() + "\n\n"
790
+ }
791
+ if response_string == "" {
792
+ response_string = chatgpt.ConvertToString(&original_response, &previous_text, isRole)
793
+ }
794
+ if response_string == "" {
795
+ if isEnd {
796
+ goto endProcess
797
+ } else {
798
+ continue
799
+ }
800
+ }
801
+ if response_string == "【" {
802
+ waitSource = true
803
+ continue
804
+ }
805
+ endProcess:
806
+ isRole = false
807
+ if stream {
808
+ _, err = c.Writer.WriteString(response_string)
809
+ if err != nil {
810
+ return "", nil
811
+ }
812
+ c.Writer.Flush()
813
+ }
814
+
815
+ if original_response.Message.Metadata.FinishDetails != nil {
816
+ if original_response.Message.Metadata.FinishDetails.Type == "max_tokens" {
817
+ max_tokens = true
818
+ }
819
+ finish_reason = original_response.Message.Metadata.FinishDetails.Type
820
+ }
821
+ if isEnd {
822
+ if stream {
823
+ final_line := official_types.StopChunk(finish_reason)
824
+ c.Writer.WriteString("data: " + final_line.String() + "\n\n")
825
+ }
826
+ break
827
+ }
828
+ }
829
+ }
830
+ if !max_tokens {
831
+ return strings.Join(imgSource, "") + previous_text.Text, nil
832
+ }
833
+ return strings.Join(imgSource, "") + previous_text.Text, &ContinueInfo{
834
+ ConversationID: original_response.ConversationID,
835
+ ParentID: original_response.Message.ID,
836
+ }
837
+ }
838
+
839
+ type AuthSession struct {
840
+ User struct {
841
+ Id string `json:"id"`
842
+ Name string `json:"name"`
843
+ Email string `json:"email"`
844
+ Image string `json:"image"`
845
+ Picture string `json:"picture"`
846
+ Idp string `json:"idp"`
847
+ Iat int `json:"iat"`
848
+ Mfa bool `json:"mfa"`
849
+ Groups []interface{} `json:"groups"`
850
+ IntercomHash string `json:"intercom_hash"`
851
+ } `json:"user"`
852
+ Expires time.Time `json:"expires"`
853
+ AccessToken string `json:"accessToken"`
854
+ AuthProvider string `json:"authProvider"`
855
+ }
856
+
857
+ func GETTokenForRefreshToken(client httpclient.AuroraHttpClient, refresh_token string, proxy string) (interface{}, int, error) {
858
+ if proxy != "" {
859
+ client.SetProxy(proxy)
860
+ }
861
+ rawUrl := "https://auth0.openai.com/oauth/token"
862
+
863
+ data := map[string]interface{}{
864
+ "redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback",
865
+ "grant_type": "refresh_token",
866
+ "client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh",
867
+ "refresh_token": refresh_token,
868
+ }
869
+
870
+ reqBody, err := json.Marshal(data)
871
+ if err != nil {
872
+ return nil, 0, err
873
+ }
874
+
875
+ header := make(httpclient.AuroraHeaders)
876
+ //req, _ := http.NewRequest("POST", url, bytes.NewBuffer(reqBody))
877
+ header.Set("authority", "auth0.openai.com")
878
+ header.Set("Accept-Language", "en-US,en;q=0.9")
879
+ header.Set("Content-Type", "application/json")
880
+ 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")
881
+ header.Set("Accept", "*/*")
882
+ resp, err := client.Request(http.MethodPost, rawUrl, header, nil, bytes.NewBuffer(reqBody))
883
+ if err != nil {
884
+ return nil, 0, err
885
+ }
886
+ defer resp.Body.Close()
887
+ var result interface{}
888
+ err = json.NewDecoder(resp.Body).Decode(&result)
889
+ if err != nil {
890
+ return nil, 0, err
891
+ }
892
+ return result, resp.StatusCode, nil
893
+ }
894
+
895
+ func GETTokenForSessionToken(client httpclient.AuroraHttpClient, session_token string, proxy string) (interface{}, int, error) {
896
+ if proxy != "" {
897
+ client.SetProxy(proxy)
898
+ }
899
+ url := "https://chat.openai.com/api/auth/session"
900
+ header := make(httpclient.AuroraHeaders)
901
+ header.Set("authority", "chat.openai.com")
902
+ header.Set("accept-language", "zh-CN,zh;q=0.9")
903
+ header.Set("User-Agent", userAgent)
904
+ header.Set("Accept", "*/*")
905
+ header.Set("oai-language", "en-US")
906
+ header.Set("origin", "https://chat.openai.com")
907
+ header.Set("referer", "https://chat.openai.com/")
908
+ header.Set("cookie", "__Secure-next-auth.session-token="+session_token)
909
+ resp, err := client.Request(http.MethodGet, url, header, nil, nil)
910
+ if err != nil {
911
+ return nil, 0, err
912
+ }
913
+ defer resp.Body.Close()
914
+ var result AuthSession
915
+ json.NewDecoder(resp.Body).Decode(&result)
916
+
917
+ cookies := parseCookies(resp.Cookies())
918
+ if value, ok := cookies["__Secure-next-auth.session-token"]; ok {
919
+ session_token = value
920
+ }
921
+ openai_sessionToken := official_types.NewOpenAISessionToken(session_token, result.AccessToken)
922
+ return openai_sessionToken, resp.StatusCode, nil
923
+ }
924
+
925
+ func parseCookies(cookies []*http.Cookie) map[string]string {
926
+ cookieDict := make(map[string]string)
927
+ for _, cookie := range cookies {
928
+ cookieDict[cookie.Name] = cookie.Value
929
+ }
930
+ return cookieDict
931
+ }
932
+
933
+ func createBaseHeader() httpclient.AuroraHeaders {
934
+ header := make(httpclient.AuroraHeaders)
935
+ // 完善补充完整的请求头
936
+ header.Set("accept", "*/*")
937
+ header.Set("accept-language", "en-US,en;q=0.9")
938
+ header.Set("oai-language", util.RandomLanguage())
939
+ header.Set("origin", "https://chat.openai.com")
940
+ header.Set("referer", "https://chat.openai.com/")
941
+ header.Set("sec-ch-ua", `"Google Chrome";v="44", "Not:A-Brand";v="8", "Chromium";v="44"`)
942
+ header.Set("sec-ch-ua-mobile", "?0")
943
+ header.Set("sec-ch-ua-platform", `"Linux"`)
944
+ header.Set("sec-fetch-dest", "empty")
945
+ header.Set("sec-fetch-mode", "cors")
946
+ header.Set("sec-fetch-site", "same-origin")
947
+ header.Set("user-agent", userAgent)
948
+ return header
949
+ }
internal/proxys/proxys.go ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package proxys
2
+
3
+ import "sync"
4
+
5
+ type IProxy struct {
6
+ ips []string
7
+ lock sync.Mutex
8
+ }
9
+
10
+ func NewIProxyIP(ips []string) IProxy {
11
+ return IProxy{
12
+ ips: ips,
13
+ }
14
+ }
15
+
16
+ func (p *IProxy) GetIPS() int {
17
+ return len(p.ips)
18
+ }
19
+
20
+ func (p *IProxy) GetProxyIP() string {
21
+ if p == nil {
22
+ return ""
23
+ }
24
+
25
+ p.lock.Lock()
26
+ defer p.lock.Unlock()
27
+
28
+ if len(p.ips) == 0 {
29
+ return ""
30
+ }
31
+
32
+ proxyIp := p.ips[0]
33
+ p.ips = append(p.ips[1:], proxyIp)
34
+ return proxyIp
35
+ }
internal/tokens/tokens.go ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package tokens
2
+
3
+ import (
4
+ "sync"
5
+ )
6
+
7
+ type Secret struct {
8
+ Token string `json:"token"`
9
+ PUID string `json:"puid"`
10
+ IsFree bool `json:"isFree"`
11
+ }
12
+ type AccessToken struct {
13
+ tokens []*Secret
14
+ lock sync.Mutex
15
+ }
16
+
17
+ func NewSecret(token string) *Secret {
18
+ return &Secret{Token: token, PUID: "", IsFree: false}
19
+ }
20
+
21
+ func NewSecretWithFree(token string) *Secret {
22
+ return &Secret{Token: token, PUID: "", IsFree: true}
23
+ }
24
+
25
+ func NewAccessToken(tokens []*Secret) AccessToken {
26
+ return AccessToken{
27
+ tokens: tokens,
28
+ }
29
+ }
30
+
31
+ func (a *AccessToken) GetSecret() *Secret {
32
+ if a == nil {
33
+ return &Secret{}
34
+ }
35
+
36
+ a.lock.Lock()
37
+ defer a.lock.Unlock()
38
+
39
+ if len(a.tokens) == 0 {
40
+ return &Secret{}
41
+ }
42
+
43
+ secret := a.tokens[0]
44
+ a.tokens = append(a.tokens[1:], secret)
45
+ return secret
46
+ }
47
+
48
+ // UpdateSecret 更新tokens
49
+ func (a *AccessToken) UpdateSecret(tokens []*Secret) {
50
+ a.lock.Lock()
51
+ defer a.lock.Unlock()
52
+ if len(tokens) == 0 {
53
+ return
54
+ }
55
+ a.tokens = tokens
56
+ }
57
+
58
+ func (a *AccessToken) GenerateTempToken(token string) *Secret {
59
+ return &Secret{Token: token, PUID: "", IsFree: false}
60
+ }
61
+
62
+ func (a *AccessToken) GenerateDeviceId(token string) *Secret {
63
+ return &Secret{Token: token, PUID: "", IsFree: true}
64
+ }
main.go ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "aurora/initialize"
5
+ "embed"
6
+ "io/fs"
7
+ "log"
8
+ "net/http"
9
+ "os"
10
+
11
+ "github.com/gin-gonic/gin"
12
+
13
+ "github.com/acheong08/endless"
14
+ "github.com/joho/godotenv"
15
+ )
16
+
17
+ //go:embed web/*
18
+ var staticFiles embed.FS
19
+
20
+ func main() {
21
+ gin.SetMode(gin.ReleaseMode)
22
+ router := initialize.RegisterRouter()
23
+ subFS, err := fs.Sub(staticFiles, "web")
24
+ if err != nil {
25
+ log.Fatal(err)
26
+ }
27
+ router.StaticFS("/web", http.FS(subFS))
28
+
29
+ _ = godotenv.Load(".env")
30
+ host := os.Getenv("SERVER_HOST")
31
+ port := os.Getenv("SERVER_PORT")
32
+ tlsCert := os.Getenv("TLS_CERT")
33
+ tlsKey := os.Getenv("TLS_KEY")
34
+
35
+ if host == "" {
36
+ host = "0.0.0.0"
37
+ }
38
+ if port == "" {
39
+ port = os.Getenv("PORT")
40
+ if port == "" {
41
+ port = "8080"
42
+ }
43
+ }
44
+
45
+ if tlsCert != "" && tlsKey != "" {
46
+ _ = endless.ListenAndServeTLS(host+":"+port, tlsCert, tlsKey, router)
47
+ } else {
48
+ _ = endless.ListenAndServe(host+":"+port, router)
49
+ }
50
+ }
middlewares/auth.go ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package middlewares
2
+
3
+ import (
4
+ "github.com/gin-gonic/gin"
5
+ "os"
6
+ "strings"
7
+ )
8
+
9
+ func Authorization(c *gin.Context) {
10
+ customer_key := os.Getenv("Authorization")
11
+ if customer_key != "" {
12
+ authHeader := c.GetHeader("Authorization")
13
+ if authHeader == "" {
14
+ c.JSON(401, gin.H{"error": "Unauthorized"})
15
+ c.Abort()
16
+ return
17
+ }
18
+ tokenParts := strings.Split(strings.Replace(authHeader, "Bearer ", "", 1)," ")
19
+ customAccessToken := tokenParts[0]
20
+ if customer_key != customAccessToken {
21
+ c.JSON(401, gin.H{"error": "Unauthorized"})
22
+ c.Abort()
23
+ return
24
+ }
25
+ if len(tokenParts) > 1 {
26
+ openaiAccessToken := tokenParts[1]
27
+ c.Request.Header.Set("Authorization", "Bearer " + openaiAccessToken)
28
+ }
29
+ }
30
+ c.Next()
31
+ }
middlewares/cors.go ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ package middlewares
2
+
3
+ import "github.com/gin-gonic/gin"
4
+
5
+ func Cors(c *gin.Context) {
6
+ c.Header("Access-Control-Allow-Origin", "*")
7
+ c.Header("Access-Control-Allow-Methods", "*")
8
+ c.Header("Access-Control-Allow-Headers", "*")
9
+ c.Next()
10
+ }
release.bat ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ SETLOCAL
3
+
4
+ REM 指定编码为 UTF-8
5
+ chcp 65001
6
+
7
+ REM 设置要生成的可执行文件的名称
8
+ set OUTPUT_NAME=aurora
9
+
10
+ REM 设置 Go 源文件的名称
11
+ SET GOFILE=aurora
12
+
13
+ REM 设置输出目录
14
+ SET OUTPUTDIR=target
15
+
16
+ REM 确保输出目录存在
17
+ IF NOT EXIST %OUTPUTDIR% MKDIR %OUTPUTDIR%
18
+
19
+ REM 编译为 Windows/amd64
20
+ echo 开始编译 Windows/amd64
21
+ SET GOOS=windows
22
+ SET GOARCH=amd64
23
+ go build -o %OUTPUTDIR%/%OUTPUT_NAME%_windows_amd64.exe %GOFILE%
24
+ echo 编译完成 Windows/amd64
25
+
26
+ REM 编译为 Windows/386
27
+ echo 开始编译 Windows/386
28
+ SET GOOS=windows
29
+ SET GOARCH=386
30
+ go build -o %OUTPUTDIR%/%OUTPUT_NAME%_windows_386.exe %GOFILE%
31
+ echo 编译完成 Windows/386
32
+
33
+ REM 编译为 Linux/amd64
34
+ echo 开始编译 Linux/amd64
35
+ SET GOOS=linux
36
+ SET GOARCH=amd64
37
+ go build -o %OUTPUTDIR%/%OUTPUT_NAME%_linux_amd64 %GOFILE%
38
+ echo 编译完成 Linux/amd64
39
+
40
+ REM 编译为 macOS/amd64
41
+ echo 开始编译 macOS/amd64
42
+ SET GOOS=darwin
43
+ SET GOARCH=amd64
44
+ go build -o %OUTPUTDIR%/%OUTPUT_NAME%_macos_amd64 %GOFILE%
45
+ echo 编译完成 macOS/amd64
46
+
47
+ REM 编译为 freebsd/amd64
48
+ echo 开始编译 freebsd/amd64
49
+ SET GOOS=freebsd
50
+ SET GOARCH=amd64
51
+ go build -o %OUTPUTDIR%/%OUTPUT_NAME%_freebsd_amd64 %GOFILE%
52
+ echo 编译完成 freebsd/amd64
53
+
54
+ REM 结束批处理脚本
55
+ ENDLOCAL
56
+ echo 编译完成!
render.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ services:
2
+ - type: web
3
+ name: aurora
4
+ env: docker
5
+ dockerfilePath: ./Dockerfile
6
+ plan: free
7
+
typings/chatgpt/request.go ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package chatgpt
2
+
3
+ import (
4
+ "os"
5
+
6
+ "github.com/google/uuid"
7
+ )
8
+
9
+ type chatgpt_message struct {
10
+ ID uuid.UUID `json:"id"`
11
+ Author chatgpt_author `json:"author"`
12
+ Content chatgpt_content `json:"content"`
13
+ }
14
+
15
+ type chatgpt_content struct {
16
+ ContentType string `json:"content_type"`
17
+ Parts []string `json:"parts"`
18
+ }
19
+
20
+ type chatgpt_author struct {
21
+ Role string `json:"role"`
22
+ }
23
+
24
+ type ChatGPTRequest struct {
25
+ Action string `json:"action"`
26
+ Messages []chatgpt_message `json:"messages,omitempty"`
27
+ ParentMessageID string `json:"parent_message_id,omitempty"`
28
+ ConversationID string `json:"conversation_id,omitempty"`
29
+ Model string `json:"model"`
30
+ HistoryAndTrainingDisabled bool `json:"history_and_training_disabled"`
31
+ ArkoseToken string `json:"arkose_token,omitempty"`
32
+ PluginIDs []string `json:"plugin_ids,omitempty"`
33
+ }
34
+
35
+ func NewChatGPTRequest() ChatGPTRequest {
36
+ disable_history := os.Getenv("ENABLE_HISTORY") != "true"
37
+ return ChatGPTRequest{
38
+ Action: "next",
39
+ ParentMessageID: uuid.NewString(),
40
+ Model: "text-davinci-002-render-sha",
41
+ HistoryAndTrainingDisabled: disable_history,
42
+ }
43
+ }
44
+
45
+ func (c *ChatGPTRequest) AddMessage(role string, content string) {
46
+ c.Messages = append(c.Messages, chatgpt_message{
47
+ ID: uuid.New(),
48
+ Author: chatgpt_author{Role: role},
49
+ Content: chatgpt_content{ContentType: "text", Parts: []string{content}},
50
+ })
51
+ }
typings/chatgpt/response.go ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package chatgpt
2
+
3
+ type ChatGPTResponse struct {
4
+ Message Message `json:"message"`
5
+ ConversationID string `json:"conversation_id"`
6
+ Error interface{} `json:"error"`
7
+ }
8
+ type ChatGPTWSSResponse struct {
9
+ WssUrl string `json:"wss_url"`
10
+ ConversationId string `json:"conversation_id,omitempty"`
11
+ ResponseId string `json:"response_id,omitempty"`
12
+ }
13
+
14
+ type WSSMsgResponse struct {
15
+ SequenceId int `json:"sequenceId"`
16
+ Type string `json:"type"`
17
+ From string `json:"from"`
18
+ DataType string `json:"dataType"`
19
+ Data WSSMsgResponseData `json:"data"`
20
+ }
21
+
22
+ type WSSMsgResponseData struct {
23
+ Type string `json:"type"`
24
+ Body string `json:"body"`
25
+ MoreBody bool `json:"more_body"`
26
+ ResponseId string `json:"response_id"`
27
+ ConversationId string `json:"conversation_id"`
28
+ }
29
+
30
+ type Message struct {
31
+ ID string `json:"id"`
32
+ Author Author `json:"author"`
33
+ CreateTime float64 `json:"create_time"`
34
+ UpdateTime interface{} `json:"update_time"`
35
+ Content Content `json:"content"`
36
+ EndTurn interface{} `json:"end_turn"`
37
+ Weight float64 `json:"weight"`
38
+ Metadata Metadata `json:"metadata"`
39
+ Recipient string `json:"recipient"`
40
+ }
41
+
42
+ type Content struct {
43
+ ContentType string `json:"content_type"`
44
+ Parts []interface{} `json:"parts"`
45
+ }
46
+
47
+ type Author struct {
48
+ Role string `json:"role"`
49
+ Name interface{} `json:"name"`
50
+ Metadata map[string]interface{} `json:"metadata"`
51
+ }
52
+
53
+ type Metadata struct {
54
+ Timestamp string `json:"timestamp_"`
55
+ Citations []Citation `json:"citations,omitempty"`
56
+ MessageType string `json:"message_type"`
57
+ FinishDetails *FinishDetails `json:"finish_details"`
58
+ ModelSlug string `json:"model_slug"`
59
+ }
60
+ type Citation struct {
61
+ Metadata CitaMeta `json:"metadata"`
62
+ StartIx int `json:"start_ix"`
63
+ EndIx int `json:"end_ix"`
64
+ }
65
+ type CitaMeta struct {
66
+ URL string `json:"url"`
67
+ Title string `json:"title"`
68
+ }
69
+ type FinishDetails struct {
70
+ Type string `json:"type"`
71
+ Stop string `json:"stop"`
72
+ }
73
+ type DalleContent struct {
74
+ AssetPointer string `json:"asset_pointer"`
75
+ Metadata struct {
76
+ Dalle struct {
77
+ Prompt string `json:"prompt"`
78
+ } `json:"dalle"`
79
+ } `json:"metadata"`
80
+ }
81
+
82
+ type ProofWork struct {
83
+ Difficulty string `json:"difficulty,omitempty"`
84
+ Required bool `json:"required"`
85
+ Seed string `json:"seed,omitempty"`
86
+ }
87
+
88
+ type RequirementsResponse struct {
89
+ Arkose struct {
90
+ Required bool `json:"required"`
91
+ Dx interface{} `json:"dx"`
92
+ } `json:"arkose"`
93
+ Proof ProofWork `json:"proofofwork,omitempty"`
94
+ Turnstile struct {
95
+ Required bool `json:"required"`
96
+ } `json:"turnstile"`
97
+ Token string `json:"token"`
98
+ }
typings/official/request.go ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package official
2
+
3
+ type APIRequest struct {
4
+ Messages []api_message `json:"messages"`
5
+ Stream bool `json:"stream"`
6
+ Model string `json:"model"`
7
+ PluginIDs []string `json:"plugin_ids"`
8
+ }
9
+
10
+ type api_message struct {
11
+ Role string `json:"role"`
12
+ Content string `json:"content"`
13
+ }
14
+
15
+ type OpenAISessionToken struct {
16
+ SessionToken string `json:"session_token"`
17
+ }
18
+
19
+ type OpenAIRefreshToken struct {
20
+ RefreshToken string `json:"refresh_token"`
21
+ }
typings/official/response.go ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package official
2
+
3
+ import "encoding/json"
4
+
5
+ type ChatCompletionChunk struct {
6
+ ID string `json:"id"`
7
+ Object string `json:"object"`
8
+ Created int64 `json:"created"`
9
+ Model string `json:"model"`
10
+ Choices []Choices `json:"choices"`
11
+ }
12
+
13
+ func (chunk *ChatCompletionChunk) String() string {
14
+ resp, _ := json.Marshal(chunk)
15
+ return string(resp)
16
+ }
17
+
18
+ type Choices struct {
19
+ Delta Delta `json:"delta"`
20
+ Index int `json:"index"`
21
+ FinishReason interface{} `json:"finish_reason"`
22
+ }
23
+
24
+ type Delta struct {
25
+ Content string `json:"content,omitempty"`
26
+ Role string `json:"role,omitempty"`
27
+ }
28
+
29
+ func NewChatCompletionChunk(text string) ChatCompletionChunk {
30
+ return ChatCompletionChunk{
31
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
32
+ Object: "chat.completion.chunk",
33
+ Created: 0,
34
+ Model: "gpt-3.5-turbo-0301",
35
+ Choices: []Choices{
36
+ {
37
+ Index: 0,
38
+ Delta: Delta{
39
+ Content: text,
40
+ },
41
+ FinishReason: nil,
42
+ },
43
+ },
44
+ }
45
+ }
46
+
47
+ func NewChatCompletionChunkWithModel(text string, model string) ChatCompletionChunk {
48
+ return ChatCompletionChunk{
49
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
50
+ Object: "chat.completion.chunk",
51
+ Created: 0,
52
+ Model: model,
53
+ Choices: []Choices{
54
+ {
55
+ Index: 0,
56
+ Delta: Delta{
57
+ Content: text,
58
+ },
59
+ FinishReason: nil,
60
+ },
61
+ },
62
+ }
63
+ }
64
+
65
+ func StopChunkWithModel(reason string, model string) ChatCompletionChunk {
66
+ return ChatCompletionChunk{
67
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
68
+ Object: "chat.completion.chunk",
69
+ Created: 0,
70
+ Model: model,
71
+ Choices: []Choices{
72
+ {
73
+ Index: 0,
74
+ FinishReason: reason,
75
+ },
76
+ },
77
+ }
78
+ }
79
+
80
+ func StopChunk(reason string) ChatCompletionChunk {
81
+ return ChatCompletionChunk{
82
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
83
+ Object: "chat.completion.chunk",
84
+ Created: 0,
85
+ Model: "gpt-3.5-turbo-0125",
86
+ Choices: []Choices{
87
+ {
88
+ Index: 0,
89
+ FinishReason: reason,
90
+ },
91
+ },
92
+ }
93
+ }
94
+
95
+ type ChatCompletion struct {
96
+ ID string `json:"id"`
97
+ Object string `json:"object"`
98
+ Created int64 `json:"created"`
99
+ Model string `json:"model"`
100
+ Usage usage `json:"usage"`
101
+ Choices []Choice `json:"choices"`
102
+ }
103
+ type Msg struct {
104
+ Role string `json:"role"`
105
+ Content string `json:"content"`
106
+ }
107
+ type Choice struct {
108
+ Index int `json:"index"`
109
+ Message Msg `json:"message"`
110
+ FinishReason interface{} `json:"finish_reason"`
111
+ }
112
+ type usage struct {
113
+ PromptTokens int `json:"prompt_tokens"`
114
+ CompletionTokens int `json:"completion_tokens"`
115
+ TotalTokens int `json:"total_tokens"`
116
+ }
117
+
118
+ func NewChatCompletionWithModel(text string, model string) ChatCompletion {
119
+ return ChatCompletion{
120
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
121
+ Object: "chat.completion",
122
+ Created: int64(0),
123
+ Model: model,
124
+ Usage: usage{
125
+ PromptTokens: 0,
126
+ CompletionTokens: 0,
127
+ TotalTokens: 0,
128
+ },
129
+ Choices: []Choice{
130
+ {
131
+ Message: Msg{
132
+ Content: text,
133
+ Role: "assistant",
134
+ },
135
+ Index: 0,
136
+ },
137
+ },
138
+ }
139
+ }
140
+
141
+ func NewChatCompletion(full_test string, input_tokens, output_tokens int) ChatCompletion {
142
+ return ChatCompletion{
143
+ ID: "chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK",
144
+ Object: "chat.completion",
145
+ Created: int64(0),
146
+ Model: "gpt-3.5-turbo-0125",
147
+ Usage: usage{
148
+ PromptTokens: input_tokens,
149
+ CompletionTokens: output_tokens,
150
+ TotalTokens: input_tokens + output_tokens,
151
+ },
152
+ Choices: []Choice{
153
+ {
154
+ Message: Msg{
155
+ Content: full_test,
156
+ Role: "assistant",
157
+ },
158
+ Index: 0,
159
+ },
160
+ },
161
+ }
162
+ }
163
+
164
+ type OpenAIAccessTokenWithSession struct {
165
+ SessionToken string `json:"session_token"`
166
+ AccessToken string `json:"access_token"`
167
+ }
168
+
169
+ func NewOpenAISessionToken(session_token string, access_token string) *OpenAIAccessTokenWithSession {
170
+ return &OpenAIAccessTokenWithSession{
171
+ SessionToken: session_token,
172
+ AccessToken: access_token,
173
+ }
174
+ }
typings/typings.go ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ package typings
2
+
3
+ type GenericResponseLine struct {
4
+ Line string `json:"line"`
5
+ Error string `json:"error"`
6
+ }
7
+
8
+ type StringStruct struct {
9
+ Text string `json:"text"`
10
+ }
util/util.go ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package util
2
+
3
+ import (
4
+ "github.com/pkoukk/tiktoken-go"
5
+ "log/slog"
6
+ "math/rand"
7
+ "time"
8
+ )
9
+
10
+ func RandomLanguage() string {
11
+ // 初始化随机数生成器
12
+ rand.Seed(time.Now().UnixNano())
13
+ // 语言列表
14
+ languages := []string{"af", "am", "ar-sa", "as", "az-Latn", "be", "bg", "bn-BD", "bn-IN", "bs", "ca", "ca-ES-valencia", "cs", "cy", "da", "de", "de-de", "el", "en-GB", "en-US", "es", "es-ES", "es-US", "es-MX", "et", "eu", "fa", "fi", "fil-Latn", "fr", "fr-FR", "fr-CA", "ga", "gd-Latn", "gl", "gu", "ha-Latn", "he", "hi", "hr", "hu", "hy", "id", "ig-Latn", "is", "it", "it-it", "ja", "ka", "kk", "km", "kn", "ko", "kok", "ku-Arab", "ky-Cyrl", "lb", "lt", "lv", "mi-Latn", "mk", "ml", "mn-Cyrl", "mr", "ms", "mt", "nb", "ne", "nl", "nl-BE", "nn", "nso", "or", "pa", "pa-Arab", "pl", "prs-Arab", "pt-BR", "pt-PT", "qut-Latn", "quz", "ro", "ru", "rw", "sd-Arab", "si", "sk", "sl", "sq", "sr-Cyrl-BA", "sr-Cyrl-RS", "sr-Latn-RS", "sv", "sw", "ta", "te", "tg-Cyrl", "th", "ti", "tk-Latn", "tn", "tr", "tt-Cyrl", "ug-Arab", "uk", "ur", "uz-Latn", "vi", "wo", "xh", "yo-Latn", "zh-Hans", "zh-Hant", "zu"}
15
+ // 随机选择一个语言
16
+ randomIndex := rand.Intn(len(languages))
17
+ return languages[randomIndex]
18
+ }
19
+
20
+ func RandomHexadecimalString() string {
21
+ rand.Seed(time.Now().UnixNano())
22
+ const charset = "0123456789abcdef"
23
+ const length = 16 // The length of the string you want to generate
24
+ b := make([]byte, length)
25
+ for i := range b {
26
+ b[i] = charset[rand.Intn(len(charset))]
27
+ }
28
+ return string(b)
29
+ }
30
+ func CountToken(input string) int {
31
+ encoding := "gpt-3.5-turbo"
32
+ tkm, err := tiktoken.EncodingForModel(encoding)
33
+ if err != nil {
34
+ slog.Warn("tiktoken.EncodingForModel error:", err)
35
+ return 0
36
+ }
37
+ token := tkm.Encode(input, nil, nil)
38
+ return len(token)
39
+ }
40
+
41
+ func RandomIntStr(num int) string {
42
+ rand.Seed(time.Now().UnixNano())
43
+ const charset = "0123456789"
44
+ var length = 16 // The length of the string you want to generate
45
+ if num > 0 {
46
+ length = num
47
+ }
48
+ b := make([]byte, length)
49
+ for i := range b {
50
+ b[i] = charset[rand.Intn(len(charset))]
51
+ }
52
+ return string(b)
53
+ }
util/utils_test.go ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package util
2
+
3
+ import (
4
+ "fmt"
5
+ "testing"
6
+ )
7
+
8
+ func TestRandomHexadecimalString(t *testing.T) {
9
+ var str = RandomHexadecimalString()
10
+ fmt.Println(str)
11
+ }
12
+
13
+ func TestRandomIntStr(t *testing.T) {
14
+ var str = RandomIntStr(39)
15
+ fmt.Println(str)
16
+ }
vercel.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "routes": [
3
+ {
4
+ "src": "/.*",
5
+ "dest": "/api/router.go"
6
+ }
7
+ ]
8
+ }
web/avatar.png ADDED
web/icon.png ADDED
web/index.html ADDED
The diff for this file is too large to render. See raw diff