dvc890 commited on
Commit
581b6d4
1 Parent(s): 8f7a191

Upload 42 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM golang:1.21-alpine
2
+ LABEL authors="oliverkirk-sudo"
3
+
4
+ RUN apk add --update redis
5
+
6
+ WORKDIR /app
7
+
8
+ COPY go.mod ./
9
+ COPY go.sum ./
10
+
11
+ RUN go mod download
12
+
13
+ COPY . .
14
+
15
+ RUN go build -o warpgpt
16
+
17
+ CMD redis-server & sleep 3 & ./warpgpt
License ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
README.md CHANGED
@@ -1,10 +1,172 @@
1
- ---
2
- title: Go Chatgpt Api Plus
3
- emoji: 📊
4
- colorFrom: green
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Warp-GPT
2
+ 作为刚学go的一个练手项目,自用
3
+
4
+ - 将chatgpt前端进行逆向,实现绕过cloudflare
5
+ - 对官方api进行代理
6
+ - 实现前端接口转标准api(通过access_token实现标准api传入访问)
7
+
8
+ 端口列表
9
+ ```
10
+ /backend-api/* (前端逆向接口)
11
+ /backend-api/conversation/ws (前端WS逆向为原数据流格式)
12
+ /api/* (前端逆向接口)
13
+ /public-api/* (前端逆向接口)
14
+ /v1/* (官方api代理)
15
+ /r/v1/chat/completions (前端接口转标准api,支持流式)
16
+ /r/v1/chat/completions/ws (前端WS转标准api,支持流式)
17
+ /r/ws/v1/chat/completions (功能相同,提供兼容)
18
+ /r/v1/images/generations (前端接口转标准api,不支持流式,只支持gpt-4的账户)
19
+ /getsession (实现__Secure-next-auth.session-token刷新session,返回session,或输入username与password输出session)
20
+ /token (获取ArkoseToken)
21
+ ```
22
+ 目前ws逆向仅支持3.5,4有些问题,看ip纯度,纯度高就能输出
23
+ ```
24
+ /r/v1/chat/completions method:["GET", "POST", "OPTIONS"]
25
+ input:
26
+ {
27
+ "model": "gpt-3.5-turbo-16k",
28
+ "messages": [
29
+ {
30
+ "role": "user",
31
+ "content": "what can you do"
32
+ }
33
+ ]
34
+ }
35
+ output:
36
+ {
37
+ "id": "chatcmpl-m3mYrjKTZuoNARfQerON95UJlA9XSWBi",
38
+ "object": "chat.completion",
39
+ "created": 1701011706,
40
+ "model": "gpt-3.5-turbo-16k",
41
+ "choices": [
42
+ {
43
+ "index": 0,
44
+ "message": {
45
+ "role": "assistant",
46
+ "content": "I can do a wide range of tasks and provide information on various topics. Here are some of the things I can do:\n\n1. Answer Questions: I can provide information on a wide range of topics, including science, history, technology, mathematics, and more.\n\n2. Generate Text: I can generate text for various purposes, such as writing essays, creating stories, composing emails, and more.\n\n3. Language Translation: I can translate text from one language to another.\n\n4. Math Assistance: I can help with mathematical calculations, equations, and explanations.\n\n5. Programming Help: I can assist with coding and programming-related questions and problems.\n\n6. Writing Assistance: I can help with grammar and writing suggestions, including editing and proofreading.\n\n7. General Knowledge: I can provide general knowledge and facts on a wide variety of subjects.\n\n8. Recommendations: I can offer recommendations for books, movies, music, travel destinations, and more.\n\n9. Conversation and Chat: I can engage in casual conversation and chat on a variety of topics.\n\n10. Learning and Education: I can assist with learning and provide explanations on academic subjects.\n\n11. Problem Solving: I can help you brainstorm ideas, solve problems, and make decisions.\n\n12. Trivia and Quizzes: I can create and participate in trivia quizzes and answer trivia questions.\n\nPlease keep in mind that I do not have access to real-time information beyond my last knowledge update in January 2022, so some information may be outdated, and I cannot provide current news or events. If you have a specific task or question in mind, feel free to ask, and I'll do my best to assist you!"
47
+ },
48
+ "finish_reason": "stop"
49
+ }
50
+ ],
51
+ "usage": {
52
+ "prompt_tokens": 0,
53
+ "completion_tokens": 0,
54
+ "total_tokens": 0
55
+ }
56
+ }
57
+ ```
58
+ ```
59
+ /r/v1/images/generations method:["GET", "POST", "OPTIONS"]
60
+ input:
61
+ {
62
+ "model": "dall-e-3",
63
+ "prompt": "A cute baby sea otter",
64
+ "n": 1,
65
+ "size": "1024x1024"
66
+ }
67
+ output:
68
+ {
69
+ "created": 1701014049,
70
+ "data": [
71
+ {
72
+ "revised_prompt": "A cute baby sea otter, looking fluffy and adorable, with big, curious eyes, floating on its back in a calm blue ocean. The otter is holding a small shell in its tiny paws, and its fur is wet, giving it a shiny appearance under the sun. The background features a serene seascape with gentle waves and a clear sky.",
73
+ "url": "https://files.oaiusercontent.com/file-fqEmsHBijHGkBKo0CnYIAfCJ?se=2023-11-26T16%3A54%3A09Z&sp=r&sv=2021-08-06&sr=b&rscc=max-age%3D31536000%2C%20immutable&rscd=attachment%3B%20filename%3Daa87dac2-8142-419d-9fe1-afa90c0a376e.webp&sig=xjwmZhzC3fZSF7V6TJ5hTWkmxBOMiVQKs0v/wTJRvAM%3D"
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+ ```
79
+ /getsession methods:["POST"]
80
+ input:
81
+ {
82
+ "refreshCookie":""
83
+ }
84
+ or
85
+ {
86
+ "username":"",
87
+ "password":""
88
+ }
89
+ output:
90
+ {
91
+ "user": {
92
+ "id": "",
93
+ "name": "",
94
+ "email": "",
95
+ "image": "",
96
+ "picture": "",
97
+ "idp": "auth0",
98
+ "iat": 1701014297,
99
+ "mfa": false,
100
+ "groups": [],
101
+ "intercom_hash": ""
102
+ },
103
+ "expires": "2024-02-24T15:58:17.821Z",
104
+ "accessToken": "",
105
+ "authProvider": "auth0",
106
+ "models": [
107
+ {
108
+ "slug": "text-davinci-002-render-sha",
109
+ "max_tokens": 8191,
110
+ "title": "Default (GPT-3.5)",
111
+ "description": "Our fastest model, great for most everyday tasks.",
112
+ "tags": [
113
+ "gpt3.5"
114
+ ],
115
+ "capabilities": {},
116
+ "product_features": {}
117
+ }
118
+ ],
119
+ "refreshCookie": ""
120
+ }
121
+ ```
122
+ ```
123
+ /token/:id methods:["GET"]
124
+ eg: /token/0A1D34FC-659D-4E23-B17B-694DCFCF6A6C
125
+ output:
126
+ {
127
+ "token": ""
128
+ }
129
+ ```
130
+
131
+ ## 代码部署
132
+ ### 配置文件
133
+ - 在harPool目录中加入har文件,实现登录验证与gpt4对话验证([获取har教程](./getHar.md))
134
+ - 复制一份.env.temp,并修改名称为.env,修改配置项后保存
135
+ ``` python
136
+ proxy = "http://127.0.0.1:10809" #代理地址 (选填)
137
+ port = 5000 #程序运行端口
138
+ host = '127.0.0.1' #可访问ip,0.0.0.0允许所有ip
139
+ verify = false #是否对访问进行验证
140
+ auth_key = "" #若开启访问验证,则需要在Header中添加AuthKey字段,且值为auth_key的值才能访问 (选填)
141
+ arkose_must = false #是否强行gpt3.5进行验证
142
+ OpenAI_HOST = "chat.openai.com" #openai网页api接口地址 (选填)
143
+ openai_api_host = "api.openai.com" #openai官方api接口 (选填)
144
+ proxy_pool_url="" #ipidea代理池链接 (选填)
145
+ #示例http://api.proxy.ipidea.io/getProxyIp?num=10&return_type=json&lb=1&sb=0&flow=1&regions=us&protocol=http,根据访问频次设置num值
146
+ log_level = "debug" #日志等级
147
+
148
+ redis_address = "127.0.0.1:6379" #redis地址(若不开启代理池可选填)
149
+ redis_passwd = "" #redis密码
150
+ redis_db = 0 #选择的redis数据库
151
+ ```
152
+ 其中proxy_pool_url使用的是[ipidea](https://share.ipidea.net/8hPKah)的代理池,注册送100M流量,无限ip,一个月,测试足够
153
+ 使用代理池后需要填写redis信息,redis版本需要7以上
154
+ ### 运行
155
+
156
+ `go build && ./WarpGPT`
157
+
158
+ ## Docker部署
159
+ 首先克隆代码
160
+ ```shell
161
+ git clone https://github.com/oliverkirk-sudo/WarpGPT.git
162
+ cd WarpGPT
163
+ ```
164
+ 正确配置.env文件,在harPool中放入har文件
165
+ (其中host应该为0.0.0.0)
166
+ ```shell
167
+ docker build -t warpgpt .
168
+ docker run -d -p 5000:5000 warpgpt
169
+ ```
170
+
171
+ ## License
172
+ Apache-2.0
getHar.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 获取har文件
2
+
3
+ 1. 首先使用具**有gpt4资格**的帐号登录openai<br>
4
+ 打开开发者控制台(F12 或Ctrl+Shift+I)
5
+ ![img.png](static/img1.png)
6
+
7
+ 2. 随便问一个问题<br>
8
+ 确保请求中出现![img.png](static/img2.png)
9
+ https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147
10
+ 这个请求
11
+
12
+ 3. 右键这个请求,选择`以HAR格式保存所有内容`
13
+ ![img.png](static/img3.png)
14
+
15
+ 保存的内容就是har文件
go.mod ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module WarpGPT
2
+
3
+ go 1.21
4
+
5
+ require (
6
+ github.com/EDDYCJY/fake-useragent v0.2.0
7
+ github.com/bogdanfinn/fhttp v0.5.27
8
+ github.com/bogdanfinn/tls-client v1.7.2
9
+ github.com/gin-gonic/gin v1.9.1
10
+ github.com/google/uuid v1.6.0
11
+ github.com/gorilla/websocket v1.5.1
12
+ github.com/joho/godotenv v1.5.1
13
+ github.com/pkoukk/tiktoken-go v0.1.6
14
+ github.com/redis/go-redis/v9 v9.4.0
15
+ github.com/sirupsen/logrus v1.9.3
16
+ golang.org/x/net v0.21.0
17
+ )
18
+
19
+ require (
20
+ github.com/PuerkitoBio/goquery v1.8.1 // indirect
21
+ github.com/andybalholm/brotli v1.1.0 // indirect
22
+ github.com/andybalholm/cascadia v1.3.1 // indirect
23
+ github.com/bogdanfinn/utls v1.6.1 // indirect
24
+ github.com/bytedance/sonic v1.10.2 // indirect
25
+ github.com/cespare/xxhash/v2 v2.2.0 // indirect
26
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
27
+ github.com/chenzhuoyu/iasm v0.9.1 // indirect
28
+ github.com/cloudflare/circl v1.3.7 // indirect
29
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
30
+ github.com/dlclark/regexp2 v1.10.0 // indirect
31
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
32
+ github.com/gin-contrib/sse v0.1.0 // indirect
33
+ github.com/go-playground/locales v0.14.1 // indirect
34
+ github.com/go-playground/universal-translator v0.18.1 // indirect
35
+ github.com/go-playground/validator/v10 v10.18.0 // indirect
36
+ github.com/goccy/go-json v0.10.2 // indirect
37
+ github.com/google/go-cmp v0.6.0 // indirect
38
+ github.com/json-iterator/go v1.1.12 // indirect
39
+ github.com/klauspost/compress v1.17.6 // indirect
40
+ github.com/klauspost/cpuid/v2 v2.2.6 // indirect
41
+ github.com/kr/text v0.2.0 // indirect
42
+ github.com/leodido/go-urn v1.4.0 // indirect
43
+ github.com/mattn/go-isatty v0.0.20 // indirect
44
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
45
+ github.com/modern-go/reflect2 v1.0.2 // indirect
46
+ github.com/pelletier/go-toml/v2 v2.1.1 // indirect
47
+ github.com/quic-go/quic-go v0.41.0 // indirect
48
+ github.com/rogpeppe/go-internal v1.11.0 // indirect
49
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 // indirect
50
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
51
+ github.com/ugorji/go/codec v1.2.12 // indirect
52
+ golang.org/x/arch v0.7.0 // indirect
53
+ golang.org/x/crypto v0.19.0 // indirect
54
+ golang.org/x/sys v0.17.0 // indirect
55
+ golang.org/x/text v0.14.0 // indirect
56
+ google.golang.org/protobuf v1.32.0 // indirect
57
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
58
+ gopkg.in/yaml.v3 v3.0.1 // indirect
59
+ )
go.sum ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
4
+ github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
5
+ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
6
+ github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
7
+ github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
8
+ github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
9
+ github.com/bogdanfinn/fhttp v0.5.27 h1:+glR3k8v5nxfUSk7+J3M246zEQ2yadhS0vLq1utK71A=
10
+ github.com/bogdanfinn/fhttp v0.5.27/go.mod h1:oJiYPG3jQTKzk/VFmogH8jxjH5yiv2rrOH48Xso2lrE=
11
+ github.com/bogdanfinn/tls-client v1.7.2 h1:vpL5qBYUfT9ueygEf1yLfymrXyUEZQatL25amfqGV8M=
12
+ github.com/bogdanfinn/tls-client v1.7.2/go.mod h1:pOGa2euqTbEkGNqE5idx5jKKfs9ytlyn3fwEw8RSP+g=
13
+ github.com/bogdanfinn/utls v1.6.1 h1:dKDYAcXEyFFJ3GaWaN89DEyjyRraD1qb4osdEK89ass=
14
+ github.com/bogdanfinn/utls v1.6.1/go.mod h1:VXIbRZaiY/wHZc6Hu+DZ4O2CgTzjhjCg/Ou3V4r/39Y=
15
+ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
16
+ github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
17
+ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
18
+ github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
19
+ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
20
+ github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
21
+ github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
22
+ github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
23
+ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
24
+ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
25
+ github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
26
+ github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
27
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
28
+ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
29
+ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
30
+ github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
31
+ github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
32
+ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
33
+ github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
34
+ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
35
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
36
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
37
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
38
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
39
+ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
40
+ github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
41
+ github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
42
+ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
43
+ github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
44
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
45
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
46
+ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
47
+ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
48
+ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
49
+ github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
50
+ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
51
+ github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
52
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
53
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
54
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
55
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
56
+ github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
57
+ github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
58
+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
59
+ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
60
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
61
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
62
+ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
63
+ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
64
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
65
+ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
66
+ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
67
+ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
68
+ github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
69
+ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
70
+ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
71
+ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
72
+ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
73
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
74
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
75
+ github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI=
76
+ github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
77
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
78
+ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
79
+ github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
80
+ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
81
+ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
82
+ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
83
+ github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
84
+ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
85
+ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
86
+ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
87
+ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
88
+ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
89
+ github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
90
+ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
91
+ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
92
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
93
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
94
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
95
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
96
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
97
+ github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
98
+ github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
99
+ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
100
+ github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
101
+ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
102
+ github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
103
+ github.com/pkoukk/tiktoken-go v0.1.6 h1:JF0TlJzhTbrI30wCvFuiw6FzP2+/bR+FIxUdgEAcUsw=
104
+ github.com/pkoukk/tiktoken-go v0.1.6/go.mod h1:9NiV+i9mJKGj1rYOT+njbv+ZwA/zJxYdewGl6qVatpg=
105
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
106
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
107
+ github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
108
+ github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
109
+ github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk=
110
+ github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
111
+ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
112
+ github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
113
+ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
114
+ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
115
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
116
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
117
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
118
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
119
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
120
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
121
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
122
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
123
+ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
124
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
125
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5 h1:YqAladjX7xpA6BM04leXMWAEjS0mTZ5kUU9KRBriQJc=
126
+ github.com/tam7t/hpkp v0.0.0-20160821193359-2b70b4024ed5/go.mod h1:2JjD2zLQYH5HO74y5+aE3remJQvl6q4Sn6aWA2wD1Ng=
127
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
128
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
129
+ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
130
+ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
131
+ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
132
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
133
+ golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
134
+ golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
135
+ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
136
+ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
137
+ golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
138
+ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
139
+ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
140
+ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
141
+ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
142
+ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
143
+ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
144
+ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
145
+ golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
146
+ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
147
+ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
148
+ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
149
+ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
150
+ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
151
+ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
152
+ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
153
+ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
154
+ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
155
+ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
156
+ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
157
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
158
+ golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
159
+ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
160
+ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
161
+ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
162
+ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
163
+ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
164
+ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
165
+ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
166
+ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
167
+ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
168
+ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
169
+ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
170
+ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
171
+ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
172
+ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
173
+ golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
174
+ golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
175
+ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
176
+ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
177
+ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
178
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
179
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
180
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
181
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
182
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
183
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
184
+ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
185
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
harPool/put_har_in_this_folder ADDED
File without changes
main.go ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "WarpGPT/pkg/db"
5
+ "WarpGPT/pkg/env"
6
+ "WarpGPT/pkg/funcaptcha"
7
+ "WarpGPT/pkg/logger"
8
+ "WarpGPT/pkg/plugins"
9
+ "WarpGPT/pkg/plugins/api/arkosetoken"
10
+ "WarpGPT/pkg/plugins/api/backendapi"
11
+ "WarpGPT/pkg/plugins/api/officialapi"
12
+ "WarpGPT/pkg/plugins/api/publicapi"
13
+ "WarpGPT/pkg/plugins/api/rapi"
14
+ "WarpGPT/pkg/plugins/api/session"
15
+ "WarpGPT/pkg/plugins/api/unofficialapi"
16
+ "WarpGPT/pkg/plugins/service/proxypool"
17
+ "github.com/bogdanfinn/fhttp"
18
+ "github.com/gin-gonic/gin"
19
+ "strconv"
20
+ )
21
+
22
+ func CORSMiddleware() gin.HandlerFunc {
23
+ return func(c *gin.Context) {
24
+ c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
25
+ c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
26
+ c.Writer.Header().Set("Access-Control-Allow-Headers", "*")
27
+ c.Writer.Header().Set("Access-Control-Allow-Methods", "*")
28
+
29
+ if c.Request.Method == "OPTIONS" {
30
+ c.AbortWithStatus(http.StatusNoContent)
31
+ return
32
+ }
33
+
34
+ c.Next()
35
+ }
36
+ }
37
+ func AuthMiddleware() gin.HandlerFunc {
38
+ return func(c *gin.Context) {
39
+ apiKey := c.GetHeader("AuthKey")
40
+ if apiKey != env.E.AuthKey {
41
+ c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
42
+ return
43
+ }
44
+ c.Next()
45
+ }
46
+ }
47
+ func main() {
48
+ var router = gin.Default()
49
+ if env.E.Verify {
50
+ router.Use(AuthMiddleware())
51
+ }
52
+ router.Use(CORSMiddleware())
53
+ component := &plugins.Component{
54
+ Engine: router,
55
+ Db: db.DB{
56
+ GetRedisClient: db.GetRedisClient,
57
+ },
58
+ Logger: logger.Log,
59
+ Env: &env.E,
60
+ Auth: funcaptcha.GetOpenAIArkoseToken,
61
+ }
62
+ var plugin_list []plugins.Plugin
63
+ plugin_list = append(
64
+ plugin_list,
65
+ &arkosetoken.ArkoseTokenInstance,
66
+ &session.SessionTokenInstance,
67
+ &backendapi.BackendProcessInstance,
68
+ &officialapi.OfficialApiProcessInstance,
69
+ &unofficialapi.UnofficialApiProcessInstance,
70
+ &publicapi.PublicApiProcessInstance,
71
+ &rapi.ApiProcessInstance,
72
+ &proxypool.ProxyPoolInstance,
73
+ )
74
+ for _, plugin := range plugin_list {
75
+ plugin.Run(component)
76
+ }
77
+ router.Run(env.E.Host + ":" + strconv.Itoa(env.E.Port))
78
+ }
pkg/common/processBody.go ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package common
2
+
3
+ import (
4
+ "WarpGPT/pkg/logger"
5
+ fhttp "github.com/bogdanfinn/fhttp"
6
+ "github.com/gin-gonic/gin"
7
+ )
8
+
9
+ type ContextProcessor[T any] interface {
10
+ SetContext(conversation T)
11
+ GetContext() T
12
+ ProcessMethod()
13
+ }
14
+
15
+ func Do[T any](p ContextProcessor[T], conversation T) {
16
+ p.SetContext(conversation)
17
+ p.ProcessMethod()
18
+ }
19
+
20
+ func CopyResponseHeaders(response *fhttp.Response, ctx *gin.Context) {
21
+ logger.Log.Debug("CopyResponseHeaders")
22
+ if response == nil {
23
+ ctx.JSON(400, gin.H{"error": "response is empty"})
24
+ logger.Log.Warning("response is empty")
25
+ }
26
+ skipHeaders := map[string]bool{"Content-Encoding": true, "Content-Length": true, "transfer-encoding": true, "connection": true}
27
+ for name, values := range response.Header {
28
+ if !skipHeaders[name] {
29
+ for _, value := range values {
30
+ ctx.Writer.Header().Set(name, value)
31
+ }
32
+ }
33
+ }
34
+ }
pkg/common/request.go ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package common
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "WarpGPT/pkg/logger"
6
+ "WarpGPT/pkg/plugins/service/proxypool"
7
+ "encoding/json"
8
+ browser "github.com/EDDYCJY/fake-useragent"
9
+ http "github.com/bogdanfinn/fhttp"
10
+ tls_client "github.com/bogdanfinn/tls-client"
11
+ "github.com/bogdanfinn/tls-client/profiles"
12
+ "github.com/gin-gonic/gin"
13
+ "io"
14
+ "fmt"
15
+ "math/rand"
16
+ "sync"
17
+ )
18
+
19
+ type Context struct {
20
+ GinContext *gin.Context
21
+ RequestUrl string
22
+ RequestClient tls_client.HttpClient
23
+ RequestBody io.ReadCloser
24
+ RequestParam string
25
+ RequestMethod string
26
+ RequestHeaders http.Header
27
+ }
28
+
29
+ type APIError struct {
30
+ AccessToken string
31
+ StatusCode int
32
+ }
33
+
34
+ func (e *APIError) Error() string {
35
+ return fmt.Sprintf("HTTP status %d, AccessToken: %s", e.StatusCode, e.AccessToken)
36
+ }
37
+
38
+ var tu sync.Mutex
39
+
40
+ type RequestUrl interface {
41
+ Generate(path string, rawquery string) string
42
+ }
43
+
44
+ func GetContextPack[T RequestUrl](ctx *gin.Context, reqUrl T) Context {
45
+ conversation := Context{}
46
+ conversation.GinContext = ctx
47
+ conversation.RequestUrl = reqUrl.Generate(ctx.Param("path"), ctx.Request.URL.RawQuery)
48
+ conversation.RequestMethod = ctx.Request.Method
49
+ conversation.RequestBody = ctx.Request.Body
50
+ conversation.RequestParam = ctx.Param("path")
51
+ conversation.RequestClient = GetHttpClient()
52
+ conversation.RequestHeaders = http.Header(ctx.Request.Header)
53
+ return conversation
54
+ }
55
+ func getUserAgent() string {
56
+ tu.Lock()
57
+ defer tu.Unlock()
58
+ return browser.Safari()
59
+ }
60
+
61
+ func GetHttpClient() tls_client.HttpClient {
62
+ jar := tls_client.NewCookieJar()
63
+ userAgent := map[int]profiles.ClientProfile{
64
+ 1: profiles.Safari_15_6_1,
65
+ 2: profiles.Safari_16_0,
66
+ 3: profiles.Safari_IOS_15_5,
67
+ 4: profiles.Safari_IOS_15_6,
68
+ 5: profiles.Safari_IOS_16_0,
69
+ }
70
+
71
+ options := []tls_client.HttpClientOption{
72
+ tls_client.WithTimeoutSeconds(120),
73
+ tls_client.WithClientProfile(userAgent[rand.Intn(5)+1]),
74
+ tls_client.WithNotFollowRedirects(),
75
+ tls_client.WithCookieJar(jar),
76
+ tls_client.WithRandomTLSExtensionOrder(),
77
+ }
78
+ if env.E.ProxyPoolUrl != "" {
79
+ ip, err := proxypool.ProxyPoolInstance.GetIpInRedis()
80
+ if err != nil {
81
+ logger.Log.Warning(err.Error())
82
+ return nil
83
+ }
84
+ options = append(options, tls_client.WithProxyUrl(ip))
85
+ } else {
86
+ options = append(options, tls_client.WithProxyUrl(env.E.Proxy))
87
+ }
88
+ client, err := tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
89
+ if err != nil {
90
+ logger.Log.Error("Error creating http client:", err)
91
+ return nil
92
+ }
93
+ return client
94
+ }
95
+
96
+ func RequestOpenAI[T any](path string, body io.Reader, accessToken string, requestMethod string) (*T, error) {
97
+ url := "https://" + env.E.OpenaiHost + path
98
+ req, err := http.NewRequest(requestMethod, url, body)
99
+ if err != nil {
100
+ logger.Log.Error("Error creating request:", err)
101
+ return nil, err
102
+ }
103
+ userAgentStr := getUserAgent()
104
+ headers := map[string]string{
105
+ "Host": env.E.OpenaiHost,
106
+ "Origin": "https://" + env.E.OpenaiHost,
107
+ "Authorization": accessToken,
108
+ "Connection": "keep-alive",
109
+ "User-Agent": userAgentStr,
110
+ "Referer": "https://" + env.E.OpenaiHost,
111
+ "Content-Type": "application/json",
112
+ "Accept": "*/*",
113
+ "sec-fetch-dest": "empty",
114
+ "sec-fetch-site": "same-origin",
115
+ }
116
+ for key, value := range headers {
117
+ req.Header.Set(key, value)
118
+ }
119
+ resp, err := GetHttpClient().Do(req)
120
+ if err != nil {
121
+ logger.Log.Error("Error sending request:", err)
122
+ return nil, err
123
+ }
124
+ defer resp.Body.Close()
125
+ if resp.StatusCode != http.StatusOK {
126
+ apiError := &APIError{
127
+ AccessToken: accessToken,
128
+ StatusCode: resp.StatusCode,
129
+ }
130
+ return nil, apiError
131
+ }
132
+ var data T
133
+ readAll, err := io.ReadAll(resp.Body)
134
+ if err != nil {
135
+ logger.Log.Error("Read error:", err)
136
+ return nil, err
137
+ }
138
+ if readAll == nil {
139
+ return nil, nil
140
+ }
141
+ err = json.Unmarshal(readAll, &data)
142
+ if err != nil {
143
+ logger.Log.Error("Unmarshal error:", err)
144
+ return nil, err
145
+ }
146
+ return &data, nil
147
+ }
pkg/db/db.go ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ package db
2
+
3
+ import "github.com/redis/go-redis/v9"
4
+
5
+ type DB struct {
6
+ GetRedisClient func() (*redis.Client, error)
7
+ }
pkg/db/redis.go ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package db
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "WarpGPT/pkg/logger"
6
+ "context"
7
+ "github.com/redis/go-redis/v9"
8
+ )
9
+
10
+ func GetRedisClient() (*redis.Client, error) {
11
+
12
+ redisClient := redis.NewClient(&redis.Options{
13
+ Addr: env.E.RedisAddress,
14
+ Password: env.E.RedisPasswd,
15
+ DB: env.E.RedisDB,
16
+ MaxRetries: 3,
17
+ MaxActiveConns: 20,
18
+ })
19
+
20
+ _, err := redisClient.Ping(context.Background()).Result()
21
+ if err != nil {
22
+ return nil, err
23
+ }
24
+ logger.Log.Info("成功连接到Redis")
25
+
26
+ return redisClient, nil
27
+ }
pkg/env/env.go ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package env
2
+
3
+ import (
4
+ "flag"
5
+ "github.com/joho/godotenv"
6
+ "os"
7
+ "strconv"
8
+ )
9
+
10
+ type ENV struct {
11
+ Proxy string
12
+ Port int
13
+ Host string
14
+ Verify bool
15
+ AuthKey string
16
+ ArkoseMust bool
17
+ OpenaiHost string
18
+ OpenaiApiHost string
19
+ ProxyPoolUrl string
20
+ UserAgent string
21
+ LogLevel string
22
+ RedisAddress string
23
+ RedisPasswd string
24
+ RedisDB int
25
+ PostgreSQLDBURI string
26
+ CapSolver string
27
+ CapClientID string
28
+ }
29
+
30
+ var E ENV
31
+ var EnvFile string
32
+
33
+ func init() {
34
+ flag.StringVar(&EnvFile, "e", ".env", "The env file path")
35
+ flag.Parse()
36
+ err := godotenv.Load(EnvFile)
37
+ if err != nil {
38
+ return
39
+ }
40
+ port, err := strconv.Atoi(os.Getenv("port"))
41
+ if err != nil {
42
+ port = 5000
43
+ }
44
+ verify, err := strconv.ParseBool(os.Getenv("verify"))
45
+ if err != nil {
46
+ verify = false
47
+ }
48
+ arkoseMust, err := strconv.ParseBool(os.Getenv("verify"))
49
+ if err != nil {
50
+ arkoseMust = false
51
+ }
52
+ OpenaiHost := os.Getenv("openai_host")
53
+ if OpenaiHost == "" {
54
+ OpenaiHost = "chat.openai.com"
55
+ }
56
+ openaiApiHost := os.Getenv("openai_api_host")
57
+ if openaiApiHost == "" {
58
+ openaiApiHost = "api.openai.com"
59
+ }
60
+ loglevel := os.Getenv("log_level")
61
+ if loglevel == "" {
62
+ loglevel = "info"
63
+ }
64
+ proxyPoolUrl := os.Getenv("proxy_pool_url")
65
+ redisAddress := os.Getenv("redis_address")
66
+ if proxyPoolUrl != "" && redisAddress == "" {
67
+ panic("配置proxyPoolUrl后未配置redis_address")
68
+ }
69
+ redisDb, err := strconv.Atoi(os.Getenv("redis_db"))
70
+ if err != nil && proxyPoolUrl != "" {
71
+ panic("DB填写出现问题")
72
+ }
73
+ E = ENV{
74
+ Proxy: os.Getenv("proxy"),
75
+ Port: port,
76
+ Host: os.Getenv("host"),
77
+ Verify: verify,
78
+ AuthKey: os.Getenv("auth_key"),
79
+ ArkoseMust: arkoseMust,
80
+ OpenaiHost: OpenaiHost,
81
+ OpenaiApiHost: openaiApiHost,
82
+ ProxyPoolUrl: proxyPoolUrl,
83
+ UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15",
84
+ LogLevel: loglevel,
85
+ RedisAddress: redisAddress,
86
+ RedisPasswd: os.Getenv("redis_passwd"),
87
+ RedisDB: redisDb,
88
+ PostgreSQLDBURI: os.Getenv("postgreSQL_db_URI"),
89
+ CapSolver: os.Getenv("cap_solver"),
90
+ CapClientID: os.Getenv("cap_client_id"),
91
+ }
92
+ }
pkg/funcaptcha/api.go ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "encoding/base64"
5
+ "encoding/json"
6
+ "errors"
7
+ "fmt"
8
+ "math/rand"
9
+ "net/url"
10
+ "regexp"
11
+ "strconv"
12
+ "strings"
13
+ "time"
14
+
15
+ http "github.com/bogdanfinn/fhttp"
16
+ )
17
+
18
+ const arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/"
19
+ const arkAuthPreURL = "https://tcr9i.openai.com/fc/gt2/"
20
+
21
+ var arkURLIns, _ = url.Parse(arkPreURL)
22
+
23
+ type arkReq struct {
24
+ arkURL string
25
+ arkBx string
26
+ arkHeader http.Header
27
+ arkBody url.Values
28
+ arkCookies []*http.Cookie
29
+ userAgent string
30
+ }
31
+
32
+ type kvPair struct {
33
+ Name string `json:"name"`
34
+ Value string `json:"value"`
35
+ }
36
+ type cookie struct {
37
+ Name string `json:"name"`
38
+ Value string `json:"value"`
39
+ Expires string `json:"expires"`
40
+ }
41
+ type postBody struct {
42
+ Params []kvPair `json:"params"`
43
+ }
44
+ type request struct {
45
+ URL string `json:"url"`
46
+ Headers []kvPair `json:"headers,omitempty"`
47
+ PostData postBody `json:"postData,omitempty"`
48
+ Cookies []cookie `json:"cookies,omitempty"`
49
+ }
50
+ type entries struct {
51
+ StartedDateTime string `json:"startedDateTime"`
52
+ Request request `json:"request"`
53
+ }
54
+ type logData struct {
55
+ Entries []entries `json:"entries"`
56
+ }
57
+ type HARData struct {
58
+ Log logData `json:"log"`
59
+ }
60
+
61
+ func (s *Solver) GetOpenAIToken(version arkVer, puid string) (string, error) {
62
+ token, err := s.sendRequest(version, "", puid)
63
+ return token, err
64
+ }
65
+
66
+ func (s *Solver) GetOpenAITokenWithBx(version arkVer, bx string, puid string) (string, error) {
67
+ token, err := s.sendRequest(version, getBdaWitBx(bx), puid)
68
+ return token, err
69
+ }
70
+
71
+ func (s *Solver) sendRequest(arkType arkVer, bda string, puid string) (string, error) {
72
+ if len(s.arks[arkType]) == 0 {
73
+ return "", errors.New("a valid HAR file with arkType " + strconv.Itoa(int(arkType)) + " required")
74
+ }
75
+ var tmpArk *arkReq = &s.arks[arkType][0]
76
+ s.arks[arkType] = append(s.arks[arkType][1:], s.arks[arkType][0])
77
+ if tmpArk == nil || tmpArk.arkBx == "" || len(tmpArk.arkBody) == 0 || len(tmpArk.arkHeader) == 0 {
78
+ return "", errors.New("a valid HAR file required")
79
+ }
80
+ if bda == "" {
81
+ bda = s.getBDA(tmpArk)
82
+ }
83
+ tmpArk.arkBody.Set("bda", base64.StdEncoding.EncodeToString([]byte(bda)))
84
+ tmpArk.arkBody.Set("rnd", strconv.FormatFloat(rand.Float64(), 'f', -1, 64))
85
+ req, _ := http.NewRequest(http.MethodPost, tmpArk.arkURL, strings.NewReader(tmpArk.arkBody.Encode()))
86
+ req.Header = tmpArk.arkHeader.Clone()
87
+ (*s.client).GetCookieJar().SetCookies(arkURLIns, tmpArk.arkCookies)
88
+ if puid != "" {
89
+ req.Header.Set("cookie", "_puid="+puid+";")
90
+ }
91
+ resp, err := (*s.client).Do(req)
92
+ if err != nil {
93
+ return "", err
94
+ }
95
+ defer resp.Body.Close()
96
+ if resp.StatusCode != 200 {
97
+ return "", errors.New("status code " + resp.Status)
98
+ }
99
+
100
+ type arkoseResponse struct {
101
+ Token string `json:"token"`
102
+ }
103
+ var arkose arkoseResponse
104
+ err = json.NewDecoder(resp.Body).Decode(&arkose)
105
+ if err != nil {
106
+ return "", err
107
+ }
108
+ // Check if rid is empty
109
+ if !strings.Contains(arkose.Token, "pk=") {
110
+ return arkose.Token, errors.New("captcha required")
111
+ }
112
+
113
+ return arkose.Token, nil
114
+ }
115
+
116
+ //goland:noinspection SpellCheckingInspection
117
+ func (s *Solver) getBDA(arkReq *arkReq) string {
118
+ var bx string = arkReq.arkBx
119
+ if bx == "" {
120
+ bx = fmt.Sprintf(bx_template,
121
+ getF(),
122
+ getN(),
123
+ getWh(),
124
+ webglExtensions,
125
+ getWebglExtensionsHash(),
126
+ webglRenderer,
127
+ webglVendor,
128
+ webglVersion,
129
+ webglShadingLanguageVersion,
130
+ webglAliasedLineWidthRange,
131
+ webglAliasedPointSizeRange,
132
+ webglAntialiasing,
133
+ webglBits,
134
+ webglMaxParams,
135
+ webglMaxViewportDims,
136
+ webglUnmaskedVendor,
137
+ webglUnmaskedRenderer,
138
+ webglVsfParams,
139
+ webglVsiParams,
140
+ webglFsfParams,
141
+ webglFsiParams,
142
+ getWebglHashWebgl(),
143
+ s.initVer,
144
+ s.initHex,
145
+ getFe(),
146
+ getIfeHash(),
147
+ )
148
+ } else {
149
+ re := regexp.MustCompile(`"key"\:"n","value"\:"\S*?"`)
150
+ bx = re.ReplaceAllString(bx, `"key":"n","value":"`+getN()+`"`)
151
+ }
152
+ bt := getBt()
153
+ bw := getBw(bt)
154
+ return Encrypt(bx, arkReq.userAgent+bw)
155
+ }
156
+
157
+ func getBt() int64 {
158
+ return time.Now().UnixMicro() / 1000000
159
+ }
160
+
161
+ func getBw(bt int64) string {
162
+ return strconv.FormatInt(bt-(bt%21600), 10)
163
+ }
164
+
165
+ func getBdaWitBx(bx string) string {
166
+ bt := getBt()
167
+ bw := getBw(bt)
168
+ return Encrypt(bx, bv+bw)
169
+ }
pkg/funcaptcha/challenge.go ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "encoding/json"
5
+ "errors"
6
+ "fmt"
7
+ "io"
8
+ "log"
9
+ "math/rand"
10
+ "strconv"
11
+ "strings"
12
+ "time"
13
+
14
+ http "github.com/bogdanfinn/fhttp"
15
+ tls_client "github.com/bogdanfinn/tls-client"
16
+ "github.com/bogdanfinn/tls-client/profiles"
17
+ )
18
+
19
+ type Session struct {
20
+ Sid string `json:"sid"`
21
+ SessionToken string `json:"session_token"`
22
+ Hex string `json:"hex"`
23
+ ChallengeLogger challengeLogger `json:"challenge_logger"`
24
+ Challenge Challenge `json:"challenge"`
25
+ ConciseChallenge ConciseChallenge `json:"concise_challenge"`
26
+ Headers http.Header `json:"headers"`
27
+ Client *tls_client.HttpClient `json:"-"`
28
+ options []tls_client.HttpClientOption `json:"-"`
29
+ }
30
+
31
+ type ConciseChallenge struct {
32
+ GameType string `json:"game_type"`
33
+ URLs []string `json:"urls"`
34
+ Instructions string `json:"instructions"`
35
+ }
36
+ type Input struct {
37
+ Index int
38
+ }
39
+ type ValueFunc func(Input) Input
40
+ type KeyFunc func(Input) interface{}
41
+
42
+ var Yz = map[int]struct {
43
+ Value map[string]ValueFunc
44
+ Key map[string]KeyFunc
45
+ }{
46
+ 4: {
47
+ Value: map[string]ValueFunc{
48
+ "alpha": func(c Input) Input {
49
+ yValueStr := strconv.Itoa(c.Index) // 转换为字符串
50
+ combinedStr := yValueStr + strconv.Itoa(1) // 加1
51
+ combinedInt, _ := strconv.Atoi(combinedStr) // 将合并后的字符串转回为整数
52
+ return Input{Index: combinedInt - 2}
53
+ },
54
+ "beta": func(c Input) Input { return Input{Index: -c.Index} },
55
+ "gamma": func(c Input) Input { return Input{Index: 3 * (3 - c.Index)} },
56
+ "delta": func(c Input) Input { return Input{Index: 7 * c.Index} },
57
+ "epsilon": func(c Input) Input { return Input{Index: 2 * c.Index} },
58
+ "zeta": func(c Input) Input {
59
+ if c.Index != 0 {
60
+ return Input{Index: 100 / c.Index}
61
+ }
62
+ return Input{Index: c.Index}
63
+ },
64
+ },
65
+ Key: map[string]KeyFunc{
66
+ "alpha": func(c Input) interface{} {
67
+ return []int{rand.Intn(100), c.Index, rand.Intn(100)}
68
+ },
69
+ "beta": func(c Input) interface{} {
70
+ return map[string]int{
71
+ "size": 50 - c.Index,
72
+ "id": c.Index,
73
+ "limit": 10 * c.Index,
74
+ "req_timestamp": int(time.Now().UnixNano() / int64(time.Millisecond)),
75
+ }
76
+ },
77
+ "gamma": func(c Input) interface{} {
78
+ return c.Index
79
+ },
80
+ "delta": func(c Input) interface{} {
81
+ return map[string]int{"index": c.Index}
82
+ },
83
+ "epsilon": func(c Input) interface{} {
84
+ arr := make([]int, rand.Intn(5)+1)
85
+ randIndex := rand.Intn(len(arr))
86
+ for i := range arr {
87
+ if i == randIndex {
88
+ arr[i] = c.Index
89
+ } else {
90
+ arr[i] = rand.Intn(10)
91
+ }
92
+ }
93
+ return append(arr, randIndex)
94
+ },
95
+ "zeta": func(c Input) interface{} {
96
+ return append(make([]int, rand.Intn(5)+1), c.Index)
97
+ },
98
+ },
99
+ },
100
+ }
101
+
102
+ func YB(gameType int, apiBreaker *ApiBreaker) func(Input) interface{} {
103
+ return func(input Input) interface{} {
104
+ for _, valueFuncName := range apiBreaker.Value {
105
+ input = Yz[gameType].Value[valueFuncName](input)
106
+ }
107
+ return Yz[gameType].Key[apiBreaker.Key](input)
108
+ }
109
+ }
110
+
111
+ type Challenge struct {
112
+ SessionToken string `json:"session_token"`
113
+ ChallengeID string `json:"challengeID"`
114
+ ChallengeURL string `json:"challengeURL"`
115
+ AudioChallengeURLs []string `json:"audio_challenge_urls"`
116
+ AudioGameRateLimited interface{} `json:"audio_game_rate_limited"`
117
+ Sec int `json:"sec"`
118
+ EndURL interface{} `json:"end_url"`
119
+ GameData struct {
120
+ GameType int `json:"gameType"`
121
+ GameVariant string `json:"game_variant"`
122
+ InstructionString string `json:"instruction_string"`
123
+ CustomGUI struct {
124
+ ChallengeIMGs []string `json:"_challenge_imgs"`
125
+ ApiBreaker *ApiBreaker `json:"api_breaker"`
126
+ ApiBreakerV2Enabled int `json:"api_breaker_v2_enabled"`
127
+ } `json:"customGUI"`
128
+ } `json:"game_data"`
129
+ GameSID string `json:"game_sid"`
130
+ SID string `json:"sid"`
131
+ Lang string `json:"lang"`
132
+ StringTablePrefixes []interface{} `json:"string_table_prefixes"`
133
+ StringTable map[string]string `json:"string_table"`
134
+ EarlyVictoryMessage interface{} `json:"earlyVictoryMessage"`
135
+ FontSizeAdjustments interface{} `json:"font_size_adjustments"`
136
+ StyleTheme string `json:"style_theme"`
137
+ }
138
+
139
+ type challengeLogger struct {
140
+ Sid string `json:"sid"`
141
+ SessionToken string `json:"session_token"`
142
+ AnalyticsTier int `json:"analytics_tier"`
143
+ RenderType string `json:"render_type"`
144
+ Category string `json:"category"`
145
+ Action string `json:"action"`
146
+ // Omit if empty
147
+ GameToken string `json:"game_token,omitempty"`
148
+ GameType string `json:"game_type,omitempty"`
149
+ }
150
+
151
+ type requestChallenge struct {
152
+ Sid string `json:"sid"`
153
+ Token string `json:"token"`
154
+ AnalyticsTier int `json:"analytics_tier"`
155
+ RenderType string `json:"render_type"`
156
+ Lang string `json:"lang"`
157
+ IsAudioGame bool `json:"isAudioGame"`
158
+ APIBreakerVersion string `json:"apiBreakerVersion"`
159
+ }
160
+
161
+ type submitChallenge struct {
162
+ SessionToken string `json:"session_token"`
163
+ Sid string `json:"sid"`
164
+ GameToken string `json:"game_token"`
165
+ Guess string `json:"guess"`
166
+ RenderType string `json:"render_type"`
167
+ AnalyticsTier int `json:"analytics_tier"`
168
+ Bio string `json:"bio"`
169
+ }
170
+
171
+ type ApiBreaker struct {
172
+ Key string `json:"key"`
173
+ Value []string `json:"value"`
174
+ }
175
+
176
+ func StartChallenge(full_session, hex string) (*Session, error) {
177
+ fields := strings.Split(full_session, "|")
178
+ session_token := fields[0]
179
+ sid := strings.Split(fields[1], "=")[1]
180
+
181
+ session := Session{
182
+ Sid: sid,
183
+ SessionToken: session_token,
184
+ Hex: hex,
185
+ }
186
+ session.Headers = headers
187
+ session.Headers.Set("Referer", fmt.Sprintf("https://client-api.arkoselabs.com/fc/assets/ec-game-core/game-core/1.15.0/standard/index.html?session=%s", strings.Replace(full_session, "|", "&", -1)))
188
+ session.ChallengeLogger = challengeLogger{
189
+ Sid: sid,
190
+ SessionToken: session_token,
191
+ AnalyticsTier: 40,
192
+ RenderType: "canvas",
193
+ }
194
+ err := session.log("", 0, "Site URL", fmt.Sprintf("https://client-api.arkoselabs.com/v2/1.5.5/enforcement.%s.html", hex))
195
+ jar := tls_client.NewCookieJar()
196
+ session.options = []tls_client.HttpClientOption{
197
+ tls_client.WithTimeoutSeconds(360),
198
+ tls_client.WithClientProfile(profiles.Chrome_117),
199
+ tls_client.WithRandomTLSExtensionOrder(),
200
+ tls_client.WithNotFollowRedirects(),
201
+ tls_client.WithCookieJar(jar),
202
+ }
203
+ client, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), session.options...)
204
+ session.Client = &client
205
+ return &session, err
206
+ }
207
+
208
+ func (c *Session) RequestChallenge(isAudioGame bool) (*ApiBreaker, error) {
209
+ challenge_request := requestChallenge{
210
+ Sid: c.Sid,
211
+ Token: c.SessionToken,
212
+ AnalyticsTier: 40,
213
+ RenderType: "canvas",
214
+ Lang: "en-us",
215
+ IsAudioGame: isAudioGame,
216
+ APIBreakerVersion: "green",
217
+ }
218
+ payload := jsonToForm(toJSON(challenge_request))
219
+
220
+ req, _ := http.NewRequest(http.MethodPost, "https://client-api.arkoselabs.com/fc/gfct/", strings.NewReader(payload))
221
+ req.Header = c.Headers
222
+ req.Header.Set("X-NewRelic-Timestamp", getTimeStamp())
223
+ resp, err := (*c.Client).Do(req)
224
+ if err != nil {
225
+ return nil, err
226
+ }
227
+ defer resp.Body.Close()
228
+
229
+ if resp.StatusCode != 200 {
230
+ return nil, fmt.Errorf("status code %d", resp.StatusCode)
231
+ }
232
+
233
+ body, _ := io.ReadAll(resp.Body)
234
+ var challenge_data Challenge
235
+ err = json.Unmarshal(body, &challenge_data)
236
+ if err != nil {
237
+ return nil, err
238
+ }
239
+ err = c.log(challenge_data.ChallengeID, challenge_data.GameData.GameType, "loaded", "game loaded")
240
+ c.Challenge = challenge_data
241
+ // Build concise challenge
242
+ var challenge_type string
243
+ var challenge_urls []string
244
+ var key string
245
+ var apiBreaker *ApiBreaker
246
+ switch challenge_data.GameData.GameType {
247
+ case 4:
248
+ challenge_type = "image"
249
+ challenge_urls = challenge_data.GameData.CustomGUI.ChallengeIMGs
250
+ instruction_string := challenge_data.GameData.InstructionString
251
+ key = fmt.Sprintf("4.instructions-%s", instruction_string)
252
+ if challenge_data.GameData.CustomGUI.ApiBreakerV2Enabled == 1 {
253
+ apiBreaker = challenge_data.GameData.CustomGUI.ApiBreaker
254
+ }
255
+ case 101:
256
+ challenge_type = "audio"
257
+ challenge_urls = challenge_data.AudioChallengeURLs
258
+ instruction_string := challenge_data.GameData.GameVariant
259
+ key = fmt.Sprintf("audio_game.instructions-%s", instruction_string)
260
+
261
+ default:
262
+ challenge_type = "unknown"
263
+ challenge_urls = []string{}
264
+ }
265
+
266
+ c.ConciseChallenge = ConciseChallenge{
267
+ GameType: challenge_type,
268
+ URLs: challenge_urls,
269
+ Instructions: strings.ReplaceAll(strings.ReplaceAll(challenge_data.StringTable[key], "<strong>", ""), "</strong>", ""),
270
+ }
271
+ return apiBreaker, err
272
+ }
273
+
274
+ func (c *Session) SubmitAnswer(indices []int, isAudio bool, apiBreaker *ApiBreaker) error {
275
+ submission := submitChallenge{
276
+ SessionToken: c.SessionToken,
277
+ Sid: c.Sid,
278
+ GameToken: c.Challenge.ChallengeID,
279
+ RenderType: "canvas",
280
+ AnalyticsTier: 40,
281
+ Bio: "eyJtYmlvIjoiMTUwLDAsMTE3LDIzOTszMDAsMCwxMjEsMjIxOzMxNywwLDEyNCwyMTY7NTUwLDAsMTI5LDIxMDs1NjcsMCwxMzQsMjA3OzYxNywwLDE0NCwyMDU7NjUwLDAsMTU1LDIwNTs2NjcsMCwxNjUsMjA1OzY4NCwwLDE3MywyMDc7NzAwLDAsMTc4LDIxMjs4MzQsMCwyMjEsMjI4OzI2MDY3LDAsMTkzLDM1MTsyNjEwMSwwLDE4NSwzNTM7MjYxMDEsMCwxODAsMzU3OzI2MTM0LDAsMTcyLDM2MTsyNjE4NCwwLDE2NywzNjM7MjYyMTcsMCwxNjEsMzY1OzI2MzM0LDAsMTU2LDM2NDsyNjM1MSwwLDE1MiwzNTQ7MjYzNjcsMCwxNTIsMzQzOzI2Mzg0LDAsMTUyLDMzMTsyNjQ2NywwLDE1MSwzMjU7MjY0NjcsMCwxNTEsMzE3OzI2NTAxLDAsMTQ5LDMxMTsyNjY4NCwxLDE0NywzMDc7MjY3NTEsMiwxNDcsMzA3OzMwNDUxLDAsMzcsNDM3OzMwNDY4LDAsNTcsNDI0OzMwNDg0LDAsNjYsNDE0OzMwNTAxLDAsODgsMzkwOzMwNTAxLDAsMTA0LDM2OTszMDUxOCwwLDEyMSwzNDk7MzA1MzQsMCwxNDEsMzI0OzMwNTUxLDAsMTQ5LDMxNDszMDU4NCwwLDE1MywzMDQ7MzA2MTgsMCwxNTUsMjk2OzMwNzUxLDAsMTU5LDI4OTszMDc2OCwwLDE2NywyODA7MzA3ODQsMCwxNzcsMjc0OzMwODE4LDAsMTgzLDI3MDszMDg1MSwwLDE5MSwyNzA7MzA4ODQsMCwyMDEsMjY4OzMwOTE4LDAsMjA4LDI2ODszMTIzNCwwLDIwNCwyNjM7MzEyNTEsMCwyMDAsMjU3OzMxMzg0LDAsMTk1LDI1MTszMTQxOCwwLDE4OSwyNDk7MzE1NTEsMSwxODksMjQ5OzMxNjM0LDIsMTg5LDI0OTszMTcxOCwxLDE4OSwyNDk7MzE3ODQsMiwxODksMjQ5OzMxODg0LDEsMTg5LDI0OTszMTk2OCwyLDE4OSwyNDk7MzIyODQsMCwyMDIsMjQ5OzMyMzE4LDAsMjE2LDI0NzszMjMxOCwwLDIzNCwyNDU7MzIzMzQsMCwyNjksMjQ1OzMyMzUxLDAsMzAwLDI0NTszMjM2OCwwLDMzOSwyNDE7MzIzODQsMCwzODgsMjM5OzMyNjE4LDAsMzkwLDI0NzszMjYzNCwwLDM3NCwyNTM7MzI2NTEsMCwzNjUsMjU1OzMyNjY4LDAsMzUzLDI1NzszMjk1MSwxLDM0OCwyNTc7MzMwMDEsMiwzNDgsMjU3OzMzNTY4LDAsMzI4LDI3MjszMzU4NCwwLDMxOSwyNzg7MzM2MDEsMCwzMDcsMjg2OzMzNjUxLDAsMjk1LDI5NjszMzY1MSwwLDI5MSwzMDA7MzM2ODQsMCwyODEsMzA5OzMzNjg0LDAsMjcyLDMxNTszMzcxOCwwLDI2NiwzMTc7MzM3MzQsMCwyNTgsMzIzOzMzNzUxLDAsMjUyLDMyNzszMzc1MSwwLDI0NiwzMzM7MzM3NjgsMCwyNDAsMzM3OzMzNzg0LDAsMjM2LDM0MTszMzgxOCwwLDIyNywzNDc7MzM4MzQsMCwyMjEsMzUzOzM0MDUxLDAsMjE2LDM1NDszNDA2OCwwLDIxMCwzNDg7MzQwODQsMCwyMDQsMzQ0OzM0MTAxLDAsMTk4LDM0MDszNDEzNCwwLDE5NCwzMzY7MzQ1ODQsMSwxOTIsMzM0OzM0NjUxLDIsMTkyLDMzNDsiLCJ0YmlvIjoiIiwia2JpbyI6IiJ9",
282
+ }
283
+ var answerIndex []string
284
+ if isAudio {
285
+ for _, answer := range indices {
286
+ answerIndex = append(answerIndex, strconv.Itoa(answer))
287
+ }
288
+ } else {
289
+ for _, answer := range indices {
290
+ input := Input{Index: answer}
291
+ encoder := YB(4, apiBreaker)
292
+ result := encoder(input)
293
+ marshal, _ := json.Marshal(result)
294
+ answerIndex = append(answerIndex, string(marshal))
295
+ }
296
+ }
297
+ answer := "[" + strings.Join(answerIndex, ",") + "]"
298
+ submission.Guess = Encrypt(answer, c.SessionToken)
299
+ payload := jsonToForm(toJSON(submission))
300
+ req, _ := http.NewRequest(http.MethodPost, "https://client-api.arkoselabs.com/fc/ca/", strings.NewReader(payload))
301
+ req.Header = c.Headers
302
+ req.Header.Set("X-Requested-ID", getRequestId(c.SessionToken))
303
+ req.Header.Set("X-NewRelic-Timestamp", getTimeStamp())
304
+
305
+ resp, err := (*c.Client).Do(req)
306
+ if err != nil {
307
+ return err
308
+ }
309
+ defer resp.Body.Close()
310
+ body, _ := io.ReadAll(resp.Body)
311
+ var response struct {
312
+ Error string `json:"error"`
313
+ Response string `json:"response"`
314
+ Solved bool `json:"solved"`
315
+ IncorrectGuess string `json:"incorrect_guess"`
316
+ Score int `json:"score"`
317
+ }
318
+ log.Println(string(body))
319
+ err = json.Unmarshal(body, &response)
320
+ if err != nil {
321
+ return err
322
+ }
323
+ if response.Error != "" {
324
+ return errors.New(response.Error)
325
+ }
326
+ if !response.Solved {
327
+ return fmt.Errorf("incorrect guess: %s", response.IncorrectGuess)
328
+ }
329
+ // Set new client
330
+ cli, _ := tls_client.NewHttpClient(tls_client.NewNoopLogger(), c.options...)
331
+ c.Client = &cli
332
+ return nil
333
+ }
334
+
335
+ func (c *Session) log(game_token string, game_type int, category, action string) error {
336
+ v := c.ChallengeLogger
337
+ v.GameToken = game_token
338
+ if game_type != 0 {
339
+ v.GameType = fmt.Sprintf("%d", game_type)
340
+ }
341
+ v.Category = category
342
+ v.Action = action
343
+
344
+ request, _ := http.NewRequest(http.MethodPost, "https://client-api.arkoselabs.com/fc/a/", strings.NewReader(jsonToForm(toJSON(v))))
345
+ request.Header = headers
346
+ resp, err := (*c.Client).Do(request)
347
+ if err != nil {
348
+ return err
349
+ }
350
+ defer resp.Body.Close()
351
+
352
+ if resp.StatusCode != 200 {
353
+ return fmt.Errorf("status code %d", resp.StatusCode)
354
+ }
355
+ return nil
356
+ }
pkg/funcaptcha/constants.go ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import http "github.com/bogdanfinn/fhttp"
4
+
5
+ var bv = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
6
+ var headers = http.Header{
7
+ "Accept": []string{"*/*"},
8
+ "Accept-Encoding": []string{"gzip, deflate, br"},
9
+ "Accept-Language": []string{"en-US,en;q=0.5"},
10
+ "Cache-Control": []string{"no-cache"},
11
+ "Connection": []string{"keep-alive"},
12
+ "Content-Type": []string{"application/x-www-form-urlencoded; charset=UTF-8"},
13
+ "Host": []string{"client-api.arkoselabs.com"},
14
+ "Origin": []string{"https://client-api.arkoselabs.com"},
15
+ "User-Agent": []string{bv},
16
+ "X-Requested-With": []string{"XMLHttpRequest"},
17
+ }
18
+
19
+ const bx_template string = `
20
+ [{
21
+ "key": "api_type",
22
+ "value": "js"
23
+ }, {
24
+ "key": "p",
25
+ "value": 1
26
+ }, {
27
+ "key": "f",
28
+ "value": "%s"
29
+ }, {
30
+ "key": "n",
31
+ "value": "%s"
32
+ }, {
33
+ "key": "wh",
34
+ "value": "%s"
35
+ }, {
36
+ "key": "enhanced_fp",
37
+ "value": [{
38
+ "key": "webgl_extensions",
39
+ "value": "%s"
40
+ }, {
41
+ "key": "webgl_extensions_hash",
42
+ "value": "%s"
43
+ }, {
44
+ "key": "webgl_renderer",
45
+ "value": "%s"
46
+ }, {
47
+ "key": "webgl_vendor",
48
+ "value": "%s"
49
+ }, {
50
+ "key": "webgl_version",
51
+ "value": "%s"
52
+ }, {
53
+ "key": "webgl_shading_language_version",
54
+ "value": "%s"
55
+ }, {
56
+ "key": "webgl_aliased_line_width_range",
57
+ "value": "%s"
58
+ }, {
59
+ "key": "webgl_aliased_point_size_range",
60
+ "value": "%s"
61
+ }, {
62
+ "key": "webgl_antialiasing",
63
+ "value": "%s"
64
+ }, {
65
+ "key": "webgl_bits",
66
+ "value": "%s"
67
+ }, {
68
+ "key": "webgl_max_params",
69
+ "value": "%s"
70
+ }, {
71
+ "key": "webgl_max_viewport_dims",
72
+ "value": "%s"
73
+ }, {
74
+ "key": "webgl_unmasked_vendor",
75
+ "value": "%s"
76
+ }, {
77
+ "key": "webgl_unmasked_renderer",
78
+ "value": "%s"
79
+ }, {
80
+ "key": "webgl_vsf_params",
81
+ "value": "%s"
82
+ }, {
83
+ "key": "webgl_vsi_params",
84
+ "value": "%s"
85
+ }, {
86
+ "key": "webgl_fsf_params",
87
+ "value": "%s"
88
+ }, {
89
+ "key": "webgl_fsi_params",
90
+ "value": "%s"
91
+ }, {
92
+ "key": "webgl_hash_webgl",
93
+ "value": "%s"
94
+ }, {
95
+ "key": "user_agent_data_brands",
96
+ "value": "Not.A/Brand,Chromium,Google Chrome"
97
+ }, {
98
+ "key": "user_agent_data_mobile",
99
+ "value": false
100
+ }, {
101
+ "key": "navigator_connection_downlink",
102
+ "value": 10.0
103
+ }, {
104
+ "key": "navigator_connection_downlink_max",
105
+ "value": null
106
+ }, {
107
+ "key": "network_info_rtt",
108
+ "value": 150
109
+ }, {
110
+ "key": "network_info_save_data",
111
+ "value": false
112
+ }, {
113
+ "key": "network_info_rtt_type",
114
+ "value": null
115
+ }, {
116
+ "key": "screen_pixel_depth",
117
+ "value": 24
118
+ }, {
119
+ "key": "navigator_device_memory",
120
+ "value": 8
121
+ }, {
122
+ "key": "navigator_languages",
123
+ "value": "zh-CN,en"
124
+ }, {
125
+ "key": "window_inner_width",
126
+ "value": 0
127
+ }, {
128
+ "key": "window_inner_height",
129
+ "value": 0
130
+ }, {
131
+ "key": "window_outer_width",
132
+ "value": 1920
133
+ }, {
134
+ "key": "window_outer_height",
135
+ "value": 1057
136
+ }, {
137
+ "key": "browser_detection_firefox",
138
+ "value": false
139
+ }, {
140
+ "key": "browser_detection_brave",
141
+ "value": false
142
+ }, {
143
+ "key": "audio_codecs",
144
+ "value": "{\"ogg\":\"probably\",\"mp3\":\"probably\",\"wav\":\"probably\",\"m4a\":\"maybe\",\"aac\":\"probably\"}"
145
+ }, {
146
+ "key": "video_codecs",
147
+ "value": "{\"ogg\":\"probably\",\"h264\":\"probably\",\"webm\":\"probably\",\"mpeg4v\":\"\",\"mpeg4a\":\"\",\"theora\":\"\"}"
148
+ }, {
149
+ "key": "media_query_dark_mode",
150
+ "value": true
151
+ }, {
152
+ "key": "headless_browser_phantom",
153
+ "value": false
154
+ }, {
155
+ "key": "headless_browser_selenium",
156
+ "value": false
157
+ }, {
158
+ "key": "headless_browser_nightmare_js",
159
+ "value": false
160
+ }, {
161
+ "key": "document__referrer",
162
+ "value": ""
163
+ }, {
164
+ "key": "window__ancestor_origins",
165
+ "value": ["https://chat.openai.com"]
166
+ }, {
167
+ "key": "window__tree_index",
168
+ "value": [2]
169
+ }, {
170
+ "key": "window__tree_structure",
171
+ "value": "[[],[],[]]"
172
+ }, {
173
+ "key": "window__location_href",
174
+ "value": "https://tcr9i.chat.openai.com/v2/%s/enforcement.%s.html#35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
175
+ }, {
176
+ "key": "client_config__sitedata_location_href",
177
+ "value": "https://chat.openai.com"
178
+ }, {
179
+ "key": "client_config__surl",
180
+ "value": "https://tcr9i.chat.openai.com"
181
+ }, {
182
+ "key": "mobile_sdk__is_sdk"
183
+ }, {
184
+ "key": "client_config__language",
185
+ "value": null
186
+ }, {
187
+ "key": "navigator_battery_charging",
188
+ "value": true
189
+ }, {
190
+ "key": "audio_fingerprint",
191
+ "value": "124.04347527516074"
192
+ }]
193
+ }, {
194
+ "key": "fe",
195
+ "value": %s
196
+ }, {
197
+ "key": "ife_hash",
198
+ "value": "%s"
199
+ }, {
200
+ "key": "cs",
201
+ "value": 1
202
+ }, {
203
+ "key": "jsbd",
204
+ "value": "{\"HL\":5,\"NCE\":true,\"DT\":\"\",\"NWD\":\"false\",\"DOTO\":1,\"DMTO\":1}"
205
+ }]
206
+ `
207
+
208
+ // LinkedHashMap
209
+ var fe = []map[string]interface{}{
210
+ {"DNT": "1"},
211
+ {"L": "zh-CN"},
212
+ {"D": 24},
213
+ {"PR": 1}, // this.getPixelRatio();
214
+ {"S": "1920;1080"},
215
+ {"AS": "1920;1080"},
216
+ {"TO": -480},
217
+ {"SS": true},
218
+ {"LS": true},
219
+ {"IDB": true},
220
+ {"B": false},
221
+ {"ODB": true},
222
+ {"CPUC": "unknown"},
223
+ {"PK": "Linux x86_64"},
224
+ {"CFP": cfp},
225
+ {"FR": false},
226
+ {"FOS": false},
227
+ {"FB": false},
228
+ {"JSF": "Arial;Courier;Courier New;Helvetica;Times;Times New Roman"},
229
+ {"P": p},
230
+ {"T": "0;false;false"},
231
+ {"H": 16},
232
+ {"SWF": false},
233
+ }
234
+
235
+ const (
236
+ p = "Chrome PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf;Chromium PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf;Microsoft Edge PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf;PDF Viewer::Portable Document Format::application/pdf~pdf,text/pdf~pdf;WebKit built-in PDF::Portable Document Format::application/pdf~pdf,text/pdf~pdf"
237
+ )
238
+
239
+ const (
240
+ cfp = "canvas winding:yes~canvas fp:data:image/png;base64,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kd/P/miR4vw+1VKGAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECQyqwoQC9esx3dQu995vjBx1/b352xW5DulOL/05g6nG/zs2X79EHjiWt2+fL+lBLCQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAy5wHoD9KqzMuXZSab33OVL/35hFp3tBnrPkH0o8LKzFmTRZ/txA31GkeKsPnSkBAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBIaFwGAB+u6tW+ije+p26ysfzJPH7thTDZP7IzD6igfy5LE79VhsRev2+fwe65hOgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgACBYSOwwQC96rJMeWGSD/bUcbHk2aycsEVPNUzuj8Coxc+mHN/rWXylSHFafxpShQABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAsNDoJ0AfXKSWUle2FPLN271YA55xi30nhB7nHzTlg/m0Kd7PYMnqzepFynm9NiN6QQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBhWAoMG6FW3ZcrqPejV+9C7//zNa+blkl/s3X0BM3sWOOnV8/LPP+/1DM4qUszouRcFCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMMwE2g3QN2vdQp/Sdf87nbs49585oev5JvYusPM5i/PAJ3s5g9mt2+fP996MCgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBheAm0F6FXLZcqjk1zZffvzkv/dJ+klvu1+cTMXJ3npXUl6uoB+TJHiKpgECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBDYFAXaDtCrzZcp/ynJqV1DfGHsAzlj+U5dzzexe4HzxzyQjy7rxf4bRYr3dN+AmQQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIEBjeAp0G6BNbj3If19W2Dnjn3fnFd/bqaq5JvQm8+h1357Zvd2u/tPXo9gW9NWE2AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEhq9ARwF6tY0y5WlJLuhqS5vf/Gienrp9RnU126RuBVYm2WrWo3nu4O27LHF6keLCLueaRoAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgUYIdByg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ECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECDQF4ERE6APpFWm3DbJgdlpzhEp7jo0y5fumz/59cqMv+eZ7H5fmT2WvyB7P7pddk1WfVWfha2veds/ll+P+W3mv6TIkj22zP/tOSpjxt2Z7HNj7p9cvcv81iLF4305JUUIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQIECBAoHaBER2g165rAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBojIAAvTFHpVECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqFNAgF6nrtoECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0BgBAXpjjkqjBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCngAC9Tl21CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAxAgL0xhyVRgkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTgEBep26ahMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAYwQE6I05Ko0SIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ0CAvQ6ddUmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcYICNAbc1QaJUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6BQTodeqqTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKNERCgN+aoNEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQoI0OvUVZsAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEGiMgQG/MUWmUAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoUEKDXqas2AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDRGQIDemKPSKAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUKSBAr1NXbQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBojIAAvTFHpVECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqFNAgF6nrtoECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0BgBAXpjjkqjBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCngAC9Tl21CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAxAgL0xhyVRgkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTgEBep26ahMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAYwQE6I05Ko0SIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ0CAvQ6ddUmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcYICNAbc1QaJUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6BQTodeqqTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKNERCgN+aoNEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQoI0OvUVZsAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEGiMgQG/MUWmUAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoUEKDXqas2AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDRGQIDemKPSKAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUKSBAr1NXbQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBojIAAvTFHpVECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqFNAgF6nrtoECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0BgBAXpjjkqjBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIFCngAC9Tl21CRAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQKAxAgL0xhyVRgkQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECgTgEBep26ahMgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAYwQE6I05Ko0SIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAQJ0CAvQ6ddUmQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgcYICNAbc1QaJUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIE6BQTodeqqTYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQKNERCgN+aoNEqAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECdQoI0OvUVZsAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEGiMgQG/MUWmUAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBOoUEKDXqas2AQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECDRGQIDemKPSKAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAjUKSBAr1NXbQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBBojIAAvTFHpVECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQqFPg/wGfCrReV85ybQAAAABJRU5ErkJggg=="
241
+ )
pkg/funcaptcha/crypt.go ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "bytes"
5
+ "crypto/aes"
6
+ "crypto/cipher"
7
+ "crypto/md5"
8
+ "crypto/rand"
9
+ "encoding/base64"
10
+ "encoding/hex"
11
+ "encoding/json"
12
+ "errors"
13
+ "hash"
14
+ )
15
+
16
+ type encryptionData struct {
17
+ Ct string `json:"ct"`
18
+ Iv string `json:"iv"`
19
+ S string `json:"s"`
20
+ }
21
+
22
+ func Encrypt(data string, key string) string {
23
+ encData, _ := aesEncrypt(data, key)
24
+
25
+ encDataJson, err := json.Marshal(encData)
26
+ if err != nil {
27
+ panic(err)
28
+ }
29
+
30
+ return string(encDataJson)
31
+ }
32
+
33
+ func aesEncrypt(content string, password string) (*encryptionData, error) {
34
+ salt := make([]byte, 8)
35
+ _, err := rand.Read(salt)
36
+ if err != nil {
37
+ return nil, err
38
+ }
39
+ key, iv, err := defaultEvpKDF([]byte(password), salt)
40
+
41
+ if err != nil {
42
+ return nil, err
43
+ }
44
+
45
+ block, err := aes.NewCipher(key)
46
+ if err != nil {
47
+ return nil, err
48
+ }
49
+
50
+ mode := cipher.NewCBCEncrypter(block, iv)
51
+ cipherBytes := pKCS5Padding([]byte(content), aes.BlockSize)
52
+ mode.CryptBlocks(cipherBytes, cipherBytes)
53
+
54
+ //TODO: remove redundant code
55
+ md5Hash := md5.New()
56
+ salted := ""
57
+ var dx []byte
58
+
59
+ for i := 0; i < 3; i++ {
60
+ md5Hash.Write(dx)
61
+ md5Hash.Write([]byte(password))
62
+ md5Hash.Write(salt)
63
+
64
+ dx = md5Hash.Sum(nil)
65
+ md5Hash.Reset()
66
+
67
+ salted += hex.EncodeToString(dx)
68
+ }
69
+
70
+ cipherText := base64.StdEncoding.EncodeToString(cipherBytes)
71
+ encData := &encryptionData{
72
+ Ct: cipherText,
73
+ Iv: salted[64 : 64+32],
74
+ S: hex.EncodeToString(salt),
75
+ }
76
+ return encData, nil
77
+ }
78
+
79
+ // https://stackoverflow.com/questions/27677236/encryption-in-javascript-and-decryption-with-php/27678978#27678978
80
+ // https://github.com/brix/crypto-js/blob/8e6d15bf2e26d6ff0af5277df2604ca12b60a718/src/evpkdf.js#L55
81
+ func evpKDF(password []byte, salt []byte, keySize int, iterations int, hashAlgorithm string) ([]byte, error) {
82
+ var block []byte
83
+ var hasher hash.Hash
84
+ derivedKeyBytes := make([]byte, 0)
85
+ switch hashAlgorithm {
86
+ case "md5":
87
+ hasher = md5.New()
88
+ default:
89
+ return []byte{}, errors.New("not implement hasher algorithm")
90
+ }
91
+ for len(derivedKeyBytes) < keySize*4 {
92
+ if len(block) > 0 {
93
+ hasher.Write(block)
94
+ }
95
+ hasher.Write(password)
96
+ hasher.Write(salt)
97
+ block = hasher.Sum([]byte{})
98
+ hasher.Reset()
99
+
100
+ for i := 1; i < iterations; i++ {
101
+ hasher.Write(block)
102
+ block = hasher.Sum([]byte{})
103
+ hasher.Reset()
104
+ }
105
+ derivedKeyBytes = append(derivedKeyBytes, block...)
106
+ }
107
+ return derivedKeyBytes[:keySize*4], nil
108
+ }
109
+
110
+ func defaultEvpKDF(password []byte, salt []byte) (key []byte, iv []byte, err error) {
111
+ // https://github.com/brix/crypto-js/blob/8e6d15bf2e26d6ff0af5277df2604ca12b60a718/src/cipher-core.js#L775
112
+ keySize := 256 / 32
113
+ ivSize := 128 / 32
114
+ derivedKeyBytes, err := evpKDF(password, salt, keySize+ivSize, 1, "md5")
115
+ if err != nil {
116
+ return []byte{}, []byte{}, err
117
+ }
118
+ return derivedKeyBytes[:keySize*4], derivedKeyBytes[keySize*4:], nil
119
+ }
120
+ func pKCS5Padding(src []byte, blockSize int) []byte {
121
+ padding := blockSize - len(src)%blockSize
122
+ padtext := bytes.Repeat([]byte{byte(padding)}, padding)
123
+ return append(src, padtext...)
124
+ }
125
+
126
+ func Decrypt(data string, password string, fallbackPass string) string {
127
+ decDataText, err := AesDecrypt(data, password, fallbackPass)
128
+
129
+ if err != nil {
130
+ println(err.Error())
131
+ }
132
+
133
+ return decDataText
134
+ }
135
+
136
+ func AesDecrypt(baseText string, password string, fallbackPass string) (string, error) {
137
+ encBytes, err := base64.StdEncoding.DecodeString(baseText)
138
+ if err != nil {
139
+ return "", err
140
+ }
141
+ var encData encryptionData
142
+ err = json.Unmarshal(encBytes, &encData)
143
+ if err != nil {
144
+ return "", err
145
+ }
146
+ cipherBytes, err := base64.StdEncoding.DecodeString(encData.Ct)
147
+ if err != nil {
148
+ return "", err
149
+ }
150
+ salt, err := hex.DecodeString(encData.S)
151
+ if err != nil {
152
+ return "", err
153
+ }
154
+ dstBytes := make([]byte, len(cipherBytes))
155
+ decrypt:
156
+ key, _, err := DefaultEvpKDF([]byte(password), salt)
157
+ iv, _ := hex.DecodeString(encData.Iv)
158
+ if err != nil {
159
+ return "", err
160
+ }
161
+
162
+ block, err := aes.NewCipher(key)
163
+ if err != nil {
164
+ return "", err
165
+ }
166
+
167
+ mode := cipher.NewCBCDecrypter(block, iv)
168
+ mode.CryptBlocks(dstBytes, cipherBytes)
169
+ result := PKCS5UnPadding(dstBytes)
170
+ if !json.Valid(result) {
171
+ if password == fallbackPass {
172
+ return "", errors.New("decryption can't get the correct result")
173
+ } else {
174
+ password = fallbackPass
175
+ goto decrypt
176
+ }
177
+ }
178
+ return string(result), nil
179
+ }
180
+
181
+ // https://stackoverflow.com/questions/27677236/encryption-in-javascript-and-decryption-with-php/27678978#27678978
182
+ // https://github.com/brix/crypto-js/blob/8e6d15bf2e26d6ff0af5277df2604ca12b60a718/src/evpkdf.js#L55
183
+ func EvpKDF(password []byte, salt []byte, keySize int, iterations int, hashAlgorithm string) ([]byte, error) {
184
+ var block []byte
185
+ var hasher hash.Hash
186
+ derivedKeyBytes := make([]byte, 0)
187
+ switch hashAlgorithm {
188
+ case "md5":
189
+ hasher = md5.New()
190
+ default:
191
+ return []byte{}, errors.New("not implement hasher algorithm")
192
+ }
193
+ for len(derivedKeyBytes) < keySize*4 {
194
+ if len(block) > 0 {
195
+ hasher.Write(block)
196
+ }
197
+ hasher.Write(password)
198
+ hasher.Write(salt)
199
+ block = hasher.Sum([]byte{})
200
+ hasher.Reset()
201
+
202
+ for i := 1; i < iterations; i++ {
203
+ hasher.Write(block)
204
+ block = hasher.Sum([]byte{})
205
+ hasher.Reset()
206
+ }
207
+ derivedKeyBytes = append(derivedKeyBytes, block...)
208
+ }
209
+ return derivedKeyBytes[:keySize*4], nil
210
+ }
211
+
212
+ func DefaultEvpKDF(password []byte, salt []byte) (key []byte, iv []byte, err error) {
213
+ // https://github.com/brix/crypto-js/blob/8e6d15bf2e26d6ff0af5277df2604ca12b60a718/src/cipher-core.js#L775
214
+ keySize := 256 / 32
215
+ ivSize := 128 / 32
216
+ derivedKeyBytes, err := EvpKDF(password, salt, keySize+ivSize, 1, "md5")
217
+ if err != nil {
218
+ return []byte{}, []byte{}, err
219
+ }
220
+ return derivedKeyBytes[:keySize*4], derivedKeyBytes[keySize*4:], nil
221
+ }
222
+
223
+ // https://stackoverflow.com/questions/41579325/golang-how-do-i-decrypt-with-des-cbc-and-pkcs7
224
+ func PKCS5UnPadding(src []byte) []byte {
225
+ length := len(src)
226
+ unpadding := int(src[length-1])
227
+ return src[:(length - unpadding)]
228
+ }
229
+
230
+ func PKCS5Padding(src []byte, blockSize int) []byte {
231
+ padding := blockSize - len(src)%blockSize
232
+ padtext := bytes.Repeat([]byte{byte(padding)}, padding)
233
+ return append(src, padtext...)
234
+ }
pkg/funcaptcha/fingerprint.go ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "encoding/base64"
5
+ "encoding/json"
6
+ "fmt"
7
+ "strings"
8
+ "time"
9
+ )
10
+
11
+ func getF() string {
12
+ var res []string
13
+ for _, val := range fe {
14
+ for _, v := range val {
15
+ res = append(res, fmt.Sprintf("%v", v))
16
+ }
17
+ }
18
+ return getMurmur128String(strings.Join(res, "~~~"), 31)
19
+ }
20
+
21
+ func getN() string {
22
+ timestamp := fmt.Sprintf("%d", time.Now().UnixNano()/1000000000)
23
+ return base64.StdEncoding.EncodeToString([]byte(timestamp))
24
+ }
25
+
26
+ func getWh() string {
27
+ return fmt.Sprintf("%s|%s", getWindowHash(), getWindowProtoChainHash())
28
+ }
29
+
30
+ func getFe() string {
31
+ fe, _ := json.Marshal(getFeList())
32
+ return string(fe)
33
+ }
34
+
35
+ func getFeList() []string {
36
+ // var b6 = [];
37
+ var feList []string
38
+ for _, feMap := range fe {
39
+ for k, v := range feMap {
40
+ if k == "S" ||
41
+ k == "AS" ||
42
+ k == "JSF" ||
43
+ k == "T" {
44
+ v = strings.ReplaceAll(v.(string), ";", ",")
45
+ } else if k == "CFP" { // case dH(f_a_iI.X):
46
+ v = getCFPHash(cfp)
47
+ } else if k == "P" { // case 'P':
48
+ v = getP(p)
49
+ }
50
+ feList = append(feList, fmt.Sprintf("%v:%v", k, v))
51
+ }
52
+ }
53
+ return feList
54
+ }
55
+
56
+ func getP(p string) string {
57
+ var pList []string
58
+ for _, s := range strings.Split(p, ";") {
59
+ split := strings.Split(s, "::")
60
+ pList = append(pList, split[0])
61
+ }
62
+ return strings.Join(pList, ",")
63
+ }
pkg/funcaptcha/funcaptcha.go ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "encoding/json"
6
+ http "github.com/bogdanfinn/fhttp"
7
+ tls_client "github.com/bogdanfinn/tls-client"
8
+ "github.com/bogdanfinn/tls-client/profiles"
9
+ "net/url"
10
+ "os"
11
+ "path"
12
+ "path/filepath"
13
+ "strings"
14
+ "time"
15
+ )
16
+
17
+ type arkVer int
18
+
19
+ const (
20
+ ArkVerAuth arkVer = 0
21
+ ArkVerReg arkVer = 1
22
+ ArkVerChat3 arkVer = 3
23
+ ArkVerChat4 arkVer = 4
24
+ )
25
+
26
+ type Solver struct {
27
+ initVer string
28
+ initHex string
29
+ arks map[arkVer][]arkReq
30
+ client *tls_client.HttpClient
31
+ }
32
+
33
+ type solverArg func(*Solver)
34
+
35
+ func NewSolver(args ...solverArg) *Solver {
36
+ var (
37
+ jar = tls_client.NewCookieJar()
38
+ options = []tls_client.HttpClientOption{
39
+ tls_client.WithTimeoutSeconds(360),
40
+ tls_client.WithClientProfile(profiles.Chrome_117),
41
+ tls_client.WithRandomTLSExtensionOrder(),
42
+ tls_client.WithNotFollowRedirects(),
43
+ tls_client.WithCookieJar(jar),
44
+ }
45
+ client, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
46
+ )
47
+ s := &Solver{
48
+ arks: make(map[arkVer][]arkReq),
49
+ client: &client,
50
+ initVer: "1.5.4",
51
+ initHex: "cd12da708fe6cbe6e068918c38de2ad9",
52
+ }
53
+ for _, arg := range args {
54
+ arg(s)
55
+ }
56
+ return s
57
+ }
58
+
59
+ func WithInitVer(ver string) solverArg {
60
+ return func(s *Solver) {
61
+ s.initVer = ver
62
+ }
63
+ }
64
+
65
+ func WithProxy(proxy string) solverArg {
66
+ return func(s *Solver) {
67
+ (*s.client).SetProxy(proxy)
68
+ }
69
+ }
70
+
71
+ func WithInitHex(hex string) solverArg {
72
+ return func(s *Solver) {
73
+ s.initHex = hex
74
+ }
75
+ }
76
+
77
+ func WithClient(client *tls_client.HttpClient) solverArg {
78
+ return func(s *Solver) {
79
+ s.client = client
80
+ }
81
+ }
82
+
83
+ func WithHarData(harData HARData) solverArg {
84
+ return func(s *Solver) {
85
+ for _, v := range harData.Log.Entries {
86
+ if strings.HasPrefix(v.Request.URL, arkPreURL) || strings.HasPrefix(v.Request.URL, arkAuthPreURL) {
87
+ var tmpArk arkReq
88
+ tmpArk.arkURL = v.Request.URL
89
+ if v.StartedDateTime == "" {
90
+ println("Error: no arkose request!")
91
+ continue
92
+ }
93
+ t, _ := time.Parse(time.RFC3339, v.StartedDateTime)
94
+ bw := getBw(t.Unix())
95
+ fallbackBw := getBw(t.Unix() - 21600)
96
+ tmpArk.arkHeader = make(http.Header)
97
+ for _, h := range v.Request.Headers {
98
+ if !strings.EqualFold(h.Name, "content-length") && !strings.EqualFold(h.Name, "cookie") && !strings.HasPrefix(h.Name, ":") {
99
+ tmpArk.arkHeader.Set(h.Name, h.Value)
100
+ if strings.EqualFold(h.Name, "user-agent") {
101
+ tmpArk.userAgent = h.Value
102
+ }
103
+ }
104
+ }
105
+ tmpArk.arkCookies = []*http.Cookie{}
106
+ for _, cookie := range v.Request.Cookies {
107
+ expire, _ := time.Parse(time.RFC3339, cookie.Expires)
108
+ if expire.After(time.Now()) {
109
+ tmpArk.arkCookies = append(tmpArk.arkCookies, &http.Cookie{Name: cookie.Name, Value: cookie.Value, Expires: expire.UTC()})
110
+ }
111
+ }
112
+ var arkType string
113
+ tmpArk.arkBody = make(url.Values)
114
+ for _, p := range v.Request.PostData.Params {
115
+ if p.Name == "bda" {
116
+ cipher, err := url.QueryUnescape(p.Value)
117
+ if err != nil {
118
+ panic(err)
119
+ }
120
+ tmpArk.arkBx = Decrypt(cipher, tmpArk.userAgent+bw, tmpArk.userAgent+fallbackBw)
121
+ } else if p.Name != "rnd" {
122
+ query, err := url.QueryUnescape(p.Value)
123
+ if err != nil {
124
+ panic(err)
125
+ }
126
+ tmpArk.arkBody.Set(p.Name, query)
127
+ if p.Name == "public_key" {
128
+ if query == "0A1D34FC-659D-4E23-B17B-694DCFCF6A6C" {
129
+ arkType = "auth"
130
+ s.arks[ArkVerAuth] = append(s.arks[ArkVerAuth], tmpArk)
131
+ } else if query == "3D86FBBA-9D22-402A-B512-3420086BA6CC" {
132
+ arkType = "chat3"
133
+ s.arks[ArkVerChat3] = append(s.arks[ArkVerChat3], tmpArk)
134
+ } else if query == "35536E1E-65B4-4D96-9D97-6ADB7EFF8147" {
135
+ arkType = "chat4"
136
+ s.arks[ArkVerChat4] = append(s.arks[ArkVerChat4], tmpArk)
137
+ } else if query == "0655BC92-82E1-43D9-B32E-9DF9B01AF50C" {
138
+ arkType = "reg"
139
+ s.arks[ArkVerReg] = append(s.arks[ArkVerReg], tmpArk)
140
+ }
141
+ }
142
+ }
143
+ }
144
+ if tmpArk.arkBx != "" {
145
+ println("success read " + arkType + " arkose")
146
+ } else {
147
+ println("failed to decrypt HAR file")
148
+ }
149
+ }
150
+ }
151
+
152
+ }
153
+ }
154
+
155
+ func WithHarpool(s *Solver) {
156
+ dirPath := path.Join(path.Dir(env.EnvFile), "harPool")
157
+ var harPath []string
158
+ err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
159
+ if err != nil {
160
+ return err
161
+ }
162
+ if !info.IsDir() {
163
+ ext := filepath.Ext(info.Name())
164
+ if ext == ".har" {
165
+ harPath = append(harPath, path)
166
+ }
167
+ }
168
+ return nil
169
+ })
170
+ if err != nil {
171
+ println("Error: please put HAR files in harPool directory!")
172
+ }
173
+ for _, path := range harPath {
174
+ file, err := os.ReadFile(path)
175
+ if err != nil {
176
+ return
177
+ }
178
+ var harFile HARData
179
+ err = json.Unmarshal(file, &harFile)
180
+ if err != nil {
181
+ println("Error: not a HAR file!")
182
+ return
183
+ }
184
+ WithHarData(harFile)(s)
185
+ }
186
+
187
+ }
pkg/funcaptcha/get.go ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "WarpGPT/pkg/logger"
6
+ "WarpGPT/pkg/plugins/service/proxypool"
7
+ )
8
+
9
+ func GetOpenAIArkoseToken(arkType int, puid string) (string, error) {
10
+ logger.Log.Debug("GetArkoseToken")
11
+ var proxyArg solverArg
12
+ if env.E.ProxyPoolUrl != "" {
13
+ ip, err := proxypool.ProxyPoolInstance.GetIpInRedis()
14
+ if err != nil {
15
+ logger.Log.Warning(err.Error())
16
+ return "", nil
17
+ }
18
+ proxyArg = WithProxy(ip)
19
+ } else {
20
+ proxyArg = WithProxy(env.E.Proxy)
21
+ }
22
+
23
+ solver := NewSolver(proxyArg)
24
+ WithHarpool(solver)
25
+ token, err := solver.GetOpenAIToken(arkVer(arkType), puid)
26
+ if err != nil {
27
+ logger.Log.Warning(err)
28
+ return "", err
29
+ }
30
+ return token, nil
31
+ }
pkg/funcaptcha/hashing.go ADDED
@@ -0,0 +1,1380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // https://github.com/fingerprintjs/fingerprintjs/blob/master/src/utils/hashing.ts
2
+
3
+ package funcaptcha
4
+
5
+ import (
6
+ "fmt"
7
+ "sort"
8
+ "strings"
9
+ )
10
+
11
+ //goland:noinspection SpellCheckingInspection
12
+ func getWindowHash() string { // return aA(b1[df(f_a_hT.e)]()[df(f_a_hT.f)]('|'), 0x1a4);
13
+ // Object.getOwnPropertyNames(window);
14
+ b1 := []string{
15
+ "ALFCCJS",
16
+ "AbortController",
17
+ "AbortSignal",
18
+ "AbsoluteOrientationSensor",
19
+ "AbstractRange",
20
+ "Accelerometer",
21
+ "AggregateError",
22
+ "AnalyserNode",
23
+ "Animation",
24
+ "AnimationEffect",
25
+ "AnimationEvent",
26
+ "AnimationPlaybackEvent",
27
+ "AnimationTimeline",
28
+ "ArkoseEnforcement",
29
+ "Array",
30
+ "ArrayBuffer",
31
+ "Atomics",
32
+ "Attr",
33
+ "Audio",
34
+ "AudioBuffer",
35
+ "AudioBufferSourceNode",
36
+ "AudioContext",
37
+ "AudioData",
38
+ "AudioDecoder",
39
+ "AudioDestinationNode",
40
+ "AudioEncoder",
41
+ "AudioListener",
42
+ "AudioNode",
43
+ "AudioParam",
44
+ "AudioParamMap",
45
+ "AudioProcessingEvent",
46
+ "AudioScheduledSourceNode",
47
+ "AudioSinkInfo",
48
+ "AudioWorklet",
49
+ "AudioWorkletNode",
50
+ "AuthenticatorAssertionResponse",
51
+ "AuthenticatorAttestationResponse",
52
+ "AuthenticatorResponse",
53
+ "BackgroundFetchManager",
54
+ "BackgroundFetchRecord",
55
+ "BackgroundFetchRegistration",
56
+ "BarProp",
57
+ "BaseAudioContext",
58
+ "BatteryManager",
59
+ "BeforeInstallPromptEvent",
60
+ "BeforeUnloadEvent",
61
+ "BigInt",
62
+ "BigInt64Array",
63
+ "BigUint64Array",
64
+ "BiquadFilterNode",
65
+ "Blob",
66
+ "BlobEvent",
67
+ "Boolean",
68
+ "BroadcastChannel",
69
+ "BrowserCaptureMediaStreamTrack",
70
+ "ByteLengthQueuingStrategy",
71
+ "CDATASection",
72
+ "CSS",
73
+ "CSSAnimation",
74
+ "CSSConditionRule",
75
+ "CSSContainerRule",
76
+ "CSSCounterStyleRule",
77
+ "CSSFontFaceRule",
78
+ "CSSFontPaletteValuesRule",
79
+ "CSSGroupingRule",
80
+ "CSSImageValue",
81
+ "CSSImportRule",
82
+ "CSSKeyframeRule",
83
+ "CSSKeyframesRule",
84
+ "CSSKeywordValue",
85
+ "CSSLayerBlockRule",
86
+ "CSSLayerStatementRule",
87
+ "CSSMathClamp",
88
+ "CSSMathInvert",
89
+ "CSSMathMax",
90
+ "CSSMathMin",
91
+ "CSSMathNegate",
92
+ "CSSMathProduct",
93
+ "CSSMathSum",
94
+ "CSSMathValue",
95
+ "CSSMatrixComponent",
96
+ "CSSMediaRule",
97
+ "CSSNamespaceRule",
98
+ "CSSNumericArray",
99
+ "CSSNumericValue",
100
+ "CSSPageRule",
101
+ "CSSPerspective",
102
+ "CSSPositionValue",
103
+ "CSSPropertyRule",
104
+ "CSSRotate",
105
+ "CSSRule",
106
+ "CSSRuleList",
107
+ "CSSScale",
108
+ "CSSSkew",
109
+ "CSSSkewX",
110
+ "CSSSkewY",
111
+ "CSSStyleDeclaration",
112
+ "CSSStyleRule",
113
+ "CSSStyleSheet",
114
+ "CSSStyleValue",
115
+ "CSSSupportsRule",
116
+ "CSSTransformComponent",
117
+ "CSSTransformValue",
118
+ "CSSTransition",
119
+ "CSSTranslate",
120
+ "CSSUnitValue",
121
+ "CSSUnparsedValue",
122
+ "CSSVariableReferenceValue",
123
+ "Cache",
124
+ "CacheStorage",
125
+ "CanvasCaptureMediaStreamTrack",
126
+ "CanvasGradient",
127
+ "CanvasPattern",
128
+ "CanvasRenderingContext2D",
129
+ "CaptureController",
130
+ "ChannelMergerNode",
131
+ "ChannelSplitterNode",
132
+ "CharacterData",
133
+ "Clipboard",
134
+ "ClipboardEvent",
135
+ "ClipboardItem",
136
+ "CloseEvent",
137
+ "Comment",
138
+ "CompositionEvent",
139
+ "CompressionStream",
140
+ "ConstantSourceNode",
141
+ "ContentVisibilityAutoStateChangeEvent",
142
+ "ConvolverNode",
143
+ "CookieChangeEvent",
144
+ "CookieStore",
145
+ "CookieStoreManager",
146
+ "CountQueuingStrategy",
147
+ "Credential",
148
+ "CredentialsContainer",
149
+ "CropTarget",
150
+ "Crypto",
151
+ "CryptoKey",
152
+ "CustomElementRegistry",
153
+ "CustomEvent",
154
+ "CustomStateSet",
155
+ "DOMError",
156
+ "DOMException",
157
+ "DOMImplementation",
158
+ "DOMMatrix",
159
+ "DOMMatrixReadOnly",
160
+ "DOMParser",
161
+ "DOMPoint",
162
+ "DOMPointReadOnly",
163
+ "DOMQuad",
164
+ "DOMRect",
165
+ "DOMRectList",
166
+ "DOMRectReadOnly",
167
+ "DOMStringList",
168
+ "DOMStringMap",
169
+ "DOMTokenList",
170
+ "DataTransfer",
171
+ "DataTransferItem",
172
+ "DataTransferItemList",
173
+ "DataView",
174
+ "Date",
175
+ "DecompressionStream",
176
+ "DelayNode",
177
+ "DelegatedInkTrailPresenter",
178
+ "DeviceMotionEvent",
179
+ "DeviceMotionEventAcceleration",
180
+ "DeviceMotionEventRotationRate",
181
+ "DeviceOrientationEvent",
182
+ "Document",
183
+ "DocumentFragment",
184
+ "DocumentTimeline",
185
+ "DocumentType",
186
+ "DragEvent",
187
+ "DynamicsCompressorNode",
188
+ "Element",
189
+ "ElementInternals",
190
+ "EncodedAudioChunk",
191
+ "EncodedVideoChunk",
192
+ "Error",
193
+ "ErrorEvent",
194
+ "EvalError",
195
+ "Event",
196
+ "EventCounts",
197
+ "EventSource",
198
+ "EventTarget",
199
+ "External",
200
+ "EyeDropper",
201
+ "FeaturePolicy",
202
+ "FederatedCredential",
203
+ "File",
204
+ "FileList",
205
+ "FileReader",
206
+ "FileSystemDirectoryHandle",
207
+ "FileSystemFileHandle",
208
+ "FileSystemHandle",
209
+ "FileSystemWritableFileStream",
210
+ "FinalizationRegistry",
211
+ "Float32Array",
212
+ "Float64Array",
213
+ "FocusEvent",
214
+ "FontData",
215
+ "FontFace",
216
+ "FontFaceSetLoadEvent",
217
+ "FormData",
218
+ "FormDataEvent",
219
+ "FragmentDirective",
220
+ "FunCaptcha",
221
+ "Function",
222
+ "GPU",
223
+ "GPUAdapter",
224
+ "GPUAdapterInfo",
225
+ "GPUBindGroup",
226
+ "GPUBindGroupLayout",
227
+ "GPUBuffer",
228
+ "GPUBufferUsage",
229
+ "GPUCanvasContext",
230
+ "GPUColorWrite",
231
+ "GPUCommandBuffer",
232
+ "GPUCommandEncoder",
233
+ "GPUCompilationInfo",
234
+ "GPUCompilationMessage",
235
+ "GPUComputePassEncoder",
236
+ "GPUComputePipeline",
237
+ "GPUDevice",
238
+ "GPUDeviceLostInfo",
239
+ "GPUError",
240
+ "GPUExternalTexture",
241
+ "GPUInternalError",
242
+ "GPUMapMode",
243
+ "GPUOutOfMemoryError",
244
+ "GPUPipelineError",
245
+ "GPUPipelineLayout",
246
+ "GPUQuerySet",
247
+ "GPUQueue",
248
+ "GPURenderBundle",
249
+ "GPURenderBundleEncoder",
250
+ "GPURenderPassEncoder",
251
+ "GPURenderPipeline",
252
+ "GPUSampler",
253
+ "GPUShaderModule",
254
+ "GPUShaderStage",
255
+ "GPUSupportedFeatures",
256
+ "GPUSupportedLimits",
257
+ "GPUTexture",
258
+ "GPUTextureUsage",
259
+ "GPUTextureView",
260
+ "GPUUncapturedErrorEvent",
261
+ "GPUValidationError",
262
+ "GainNode",
263
+ "Gamepad",
264
+ "GamepadButton",
265
+ "GamepadEvent",
266
+ "GamepadHapticActuator",
267
+ "Geolocation",
268
+ "GeolocationCoordinates",
269
+ "GeolocationPosition",
270
+ "GeolocationPositionError",
271
+ "GravitySensor",
272
+ "Gyroscope",
273
+ "HID",
274
+ "HIDConnectionEvent",
275
+ "HIDDevice",
276
+ "HIDInputReportEvent",
277
+ "HTMLAllCollection",
278
+ "HTMLAnchorElement",
279
+ "HTMLAreaElement",
280
+ "HTMLAudioElement",
281
+ "HTMLBRElement",
282
+ "HTMLBaseElement",
283
+ "HTMLBodyElement",
284
+ "HTMLButtonElement",
285
+ "HTMLCanvasElement",
286
+ "HTMLCollection",
287
+ "HTMLDListElement",
288
+ "HTMLDataElement",
289
+ "HTMLDataListElement",
290
+ "HTMLDetailsElement",
291
+ "HTMLDialogElement",
292
+ "HTMLDirectoryElement",
293
+ "HTMLDivElement",
294
+ "HTMLDocument",
295
+ "HTMLElement",
296
+ "HTMLEmbedElement",
297
+ "HTMLFieldSetElement",
298
+ "HTMLFontElement",
299
+ "HTMLFormControlsCollection",
300
+ "HTMLFormElement",
301
+ "HTMLFrameElement",
302
+ "HTMLFrameSetElement",
303
+ "HTMLHRElement",
304
+ "HTMLHeadElement",
305
+ "HTMLHeadingElement",
306
+ "HTMLHtmlElement",
307
+ "HTMLIFrameElement",
308
+ "HTMLImageElement",
309
+ "HTMLInputElement",
310
+ "HTMLLIElement",
311
+ "HTMLLabelElement",
312
+ "HTMLLegendElement",
313
+ "HTMLLinkElement",
314
+ "HTMLMapElement",
315
+ "HTMLMarqueeElement",
316
+ "HTMLMediaElement",
317
+ "HTMLMenuElement",
318
+ "HTMLMetaElement",
319
+ "HTMLMeterElement",
320
+ "HTMLModElement",
321
+ "HTMLOListElement",
322
+ "HTMLObjectElement",
323
+ "HTMLOptGroupElement",
324
+ "HTMLOptionElement",
325
+ "HTMLOptionsCollection",
326
+ "HTMLOutputElement",
327
+ "HTMLParagraphElement",
328
+ "HTMLParamElement",
329
+ "HTMLPictureElement",
330
+ "HTMLPreElement",
331
+ "HTMLProgressElement",
332
+ "HTMLQuoteElement",
333
+ "HTMLScriptElement",
334
+ "HTMLSelectElement",
335
+ "HTMLSlotElement",
336
+ "HTMLSourceElement",
337
+ "HTMLSpanElement",
338
+ "HTMLStyleElement",
339
+ "HTMLTableCaptionElement",
340
+ "HTMLTableCellElement",
341
+ "HTMLTableColElement",
342
+ "HTMLTableElement",
343
+ "HTMLTableRowElement",
344
+ "HTMLTableSectionElement",
345
+ "HTMLTemplateElement",
346
+ "HTMLTextAreaElement",
347
+ "HTMLTimeElement",
348
+ "HTMLTitleElement",
349
+ "HTMLTrackElement",
350
+ "HTMLUListElement",
351
+ "HTMLUnknownElement",
352
+ "HTMLVideoElement",
353
+ "HashChangeEvent",
354
+ "Headers",
355
+ "Highlight",
356
+ "HighlightRegistry",
357
+ "History",
358
+ "IDBCursor",
359
+ "IDBCursorWithValue",
360
+ "IDBDatabase",
361
+ "IDBFactory",
362
+ "IDBIndex",
363
+ "IDBKeyRange",
364
+ "IDBObjectStore",
365
+ "IDBOpenDBRequest",
366
+ "IDBRequest",
367
+ "IDBTransaction",
368
+ "IDBVersionChangeEvent",
369
+ "IIRFilterNode",
370
+ "IdentityCredential",
371
+ "IdleDeadline",
372
+ "IdleDetector",
373
+ "Image",
374
+ "ImageBitmap",
375
+ "ImageBitmapRenderingContext",
376
+ "ImageCapture",
377
+ "ImageData",
378
+ "ImageDecoder",
379
+ "ImageTrack",
380
+ "ImageTrackList",
381
+ "Infinity",
382
+ "Ink",
383
+ "InputDeviceCapabilities",
384
+ "InputDeviceInfo",
385
+ "InputEvent",
386
+ "Int16Array",
387
+ "Int32Array",
388
+ "Int8Array",
389
+ "IntersectionObserver",
390
+ "IntersectionObserverEntry",
391
+ "Intl",
392
+ "JSON",
393
+ "Keyboard",
394
+ "KeyboardEvent",
395
+ "KeyboardLayoutMap",
396
+ "KeyframeEffect",
397
+ "LargestContentfulPaint",
398
+ "LaunchParams",
399
+ "LaunchQueue",
400
+ "LayoutShift",
401
+ "LayoutShiftAttribution",
402
+ "LinearAccelerationSensor",
403
+ "Location",
404
+ "Lock",
405
+ "LockManager",
406
+ "MIDIAccess",
407
+ "MIDIConnectionEvent",
408
+ "MIDIInput",
409
+ "MIDIInputMap",
410
+ "MIDIMessageEvent",
411
+ "MIDIOutput",
412
+ "MIDIOutputMap",
413
+ "MIDIPort",
414
+ "Map",
415
+ "Math",
416
+ "MathMLElement",
417
+ "MediaCapabilities",
418
+ "MediaDeviceInfo",
419
+ "MediaDevices",
420
+ "MediaElementAudioSourceNode",
421
+ "MediaEncryptedEvent",
422
+ "MediaError",
423
+ "MediaKeyMessageEvent",
424
+ "MediaKeySession",
425
+ "MediaKeyStatusMap",
426
+ "MediaKeySystemAccess",
427
+ "MediaKeys",
428
+ "MediaList",
429
+ "MediaMetadata",
430
+ "MediaQueryList",
431
+ "MediaQueryListEvent",
432
+ "MediaRecorder",
433
+ "MediaSession",
434
+ "MediaSource",
435
+ "MediaSourceHandle",
436
+ "MediaStream",
437
+ "MediaStreamAudioDestinationNode",
438
+ "MediaStreamAudioSourceNode",
439
+ "MediaStreamEvent",
440
+ "MediaStreamTrack",
441
+ "MediaStreamTrackEvent",
442
+ "MediaStreamTrackGenerator",
443
+ "MediaStreamTrackProcessor",
444
+ "MessageChannel",
445
+ "MessageEvent",
446
+ "MessagePort",
447
+ "MimeType",
448
+ "MimeTypeArray",
449
+ "MouseEvent",
450
+ "MutationEvent",
451
+ "MutationObserver",
452
+ "MutationRecord",
453
+ "NaN",
454
+ "NamedNodeMap",
455
+ "NavigateEvent",
456
+ "Navigation",
457
+ "NavigationCurrentEntryChangeEvent",
458
+ "NavigationDestination",
459
+ "NavigationHistoryEntry",
460
+ "NavigationPreloadManager",
461
+ "NavigationTransition",
462
+ "Navigator",
463
+ "NavigatorManagedData",
464
+ "NavigatorUAData",
465
+ "NetworkInformation",
466
+ "Node",
467
+ "NodeFilter",
468
+ "NodeIterator",
469
+ "NodeList",
470
+ "Notification",
471
+ "Number",
472
+ "OTPCredential",
473
+ "Object",
474
+ "OfflineAudioCompletionEvent",
475
+ "OfflineAudioContext",
476
+ "OffscreenCanvas",
477
+ "OffscreenCanvasRenderingContext2D",
478
+ "Option",
479
+ "OrientationSensor",
480
+ "OscillatorNode",
481
+ "OverconstrainedError",
482
+ "PageTransitionEvent",
483
+ "PannerNode",
484
+ "PasswordCredential",
485
+ "Path2D",
486
+ "PaymentAddress",
487
+ "PaymentManager",
488
+ "PaymentMethodChangeEvent",
489
+ "PaymentRequest",
490
+ "PaymentRequestUpdateEvent",
491
+ "PaymentResponse",
492
+ "Performance",
493
+ "PerformanceElementTiming",
494
+ "PerformanceEntry",
495
+ "PerformanceEventTiming",
496
+ "PerformanceLongTaskTiming",
497
+ "PerformanceMark",
498
+ "PerformanceMeasure",
499
+ "PerformanceNavigation",
500
+ "PerformanceNavigationTiming",
501
+ "PerformanceObserver",
502
+ "PerformanceObserverEntryList",
503
+ "PerformancePaintTiming",
504
+ "PerformanceResourceTiming",
505
+ "PerformanceServerTiming",
506
+ "PerformanceTiming",
507
+ "PeriodicSyncManager",
508
+ "PeriodicWave",
509
+ "PermissionStatus",
510
+ "Permissions",
511
+ "PictureInPictureEvent",
512
+ "PictureInPictureWindow",
513
+ "Plugin",
514
+ "PluginArray",
515
+ "PointerEvent",
516
+ "PopStateEvent",
517
+ "Presentation",
518
+ "PresentationAvailability",
519
+ "PresentationConnection",
520
+ "PresentationConnectionAvailableEvent",
521
+ "PresentationConnectionCloseEvent",
522
+ "PresentationConnectionList",
523
+ "PresentationReceiver",
524
+ "PresentationRequest",
525
+ "ProcessingInstruction",
526
+ "Profiler",
527
+ "ProgressEvent",
528
+ "Promise",
529
+ "PromiseRejectionEvent",
530
+ "Proxy",
531
+ "PublicKeyCredential",
532
+ "PushManager",
533
+ "PushSubscription",
534
+ "PushSubscriptionOptions",
535
+ "RTCCertificate",
536
+ "RTCDTMFSender",
537
+ "RTCDTMFToneChangeEvent",
538
+ "RTCDataChannel",
539
+ "RTCDataChannelEvent",
540
+ "RTCDtlsTransport",
541
+ "RTCEncodedAudioFrame",
542
+ "RTCEncodedVideoFrame",
543
+ "RTCError",
544
+ "RTCErrorEvent",
545
+ "RTCIceCandidate",
546
+ "RTCIceTransport",
547
+ "RTCPeerConnection",
548
+ "RTCPeerConnectionIceErrorEvent",
549
+ "RTCPeerConnectionIceEvent",
550
+ "RTCRtpReceiver",
551
+ "RTCRtpSender",
552
+ "RTCRtpTransceiver",
553
+ "RTCSctpTransport",
554
+ "RTCSessionDescription",
555
+ "RTCStatsReport",
556
+ "RTCTrackEvent",
557
+ "RadioNodeList",
558
+ "Range",
559
+ "RangeError",
560
+ "ReadableByteStreamController",
561
+ "ReadableStream",
562
+ "ReadableStreamBYOBReader",
563
+ "ReadableStreamBYOBRequest",
564
+ "ReadableStreamDefaultController",
565
+ "ReadableStreamDefaultReader",
566
+ "ReferenceError",
567
+ "Reflect",
568
+ "RegExp",
569
+ "RelativeOrientationSensor",
570
+ "RemotePlayback",
571
+ "ReportingObserver",
572
+ "Request",
573
+ "ResizeObserver",
574
+ "ResizeObserverEntry",
575
+ "ResizeObserverSize",
576
+ "Response",
577
+ "SVGAElement",
578
+ "SVGAngle",
579
+ "SVGAnimateElement",
580
+ "SVGAnimateMotionElement",
581
+ "SVGAnimateTransformElement",
582
+ "SVGAnimatedAngle",
583
+ "SVGAnimatedBoolean",
584
+ "SVGAnimatedEnumeration",
585
+ "SVGAnimatedInteger",
586
+ "SVGAnimatedLength",
587
+ "SVGAnimatedLengthList",
588
+ "SVGAnimatedNumber",
589
+ "SVGAnimatedNumberList",
590
+ "SVGAnimatedPreserveAspectRatio",
591
+ "SVGAnimatedRect",
592
+ "SVGAnimatedString",
593
+ "SVGAnimatedTransformList",
594
+ "SVGAnimationElement",
595
+ "SVGCircleElement",
596
+ "SVGClipPathElement",
597
+ "SVGComponentTransferFunctionElement",
598
+ "SVGDefsElement",
599
+ "SVGDescElement",
600
+ "SVGElement",
601
+ "SVGEllipseElement",
602
+ "SVGFEBlendElement",
603
+ "SVGFEColorMatrixElement",
604
+ "SVGFEComponentTransferElement",
605
+ "SVGFECompositeElement",
606
+ "SVGFEConvolveMatrixElement",
607
+ "SVGFEDiffuseLightingElement",
608
+ "SVGFEDisplacementMapElement",
609
+ "SVGFEDistantLightElement",
610
+ "SVGFEDropShadowElement",
611
+ "SVGFEFloodElement",
612
+ "SVGFEFuncAElement",
613
+ "SVGFEFuncBElement",
614
+ "SVGFEFuncGElement",
615
+ "SVGFEFuncRElement",
616
+ "SVGFEGaussianBlurElement",
617
+ "SVGFEImageElement",
618
+ "SVGFEMergeElement",
619
+ "SVGFEMergeNodeElement",
620
+ "SVGFEMorphologyElement",
621
+ "SVGFEOffsetElement",
622
+ "SVGFEPointLightElement",
623
+ "SVGFESpecularLightingElement",
624
+ "SVGFESpotLightElement",
625
+ "SVGFETileElement",
626
+ "SVGFETurbulenceElement",
627
+ "SVGFilterElement",
628
+ "SVGForeignObjectElement",
629
+ "SVGGElement",
630
+ "SVGGeometryElement",
631
+ "SVGGradientElement",
632
+ "SVGGraphicsElement",
633
+ "SVGImageElement",
634
+ "SVGLength",
635
+ "SVGLengthList",
636
+ "SVGLineElement",
637
+ "SVGLinearGradientElement",
638
+ "SVGMPathElement",
639
+ "SVGMarkerElement",
640
+ "SVGMaskElement",
641
+ "SVGMatrix",
642
+ "SVGMetadataElement",
643
+ "SVGNumber",
644
+ "SVGNumberList",
645
+ "SVGPathElement",
646
+ "SVGPatternElement",
647
+ "SVGPoint",
648
+ "SVGPointList",
649
+ "SVGPolygonElement",
650
+ "SVGPolylineElement",
651
+ "SVGPreserveAspectRatio",
652
+ "SVGRadialGradientElement",
653
+ "SVGRect",
654
+ "SVGRectElement",
655
+ "SVGSVGElement",
656
+ "SVGScriptElement",
657
+ "SVGSetElement",
658
+ "SVGStopElement",
659
+ "SVGStringList",
660
+ "SVGStyleElement",
661
+ "SVGSwitchElement",
662
+ "SVGSymbolElement",
663
+ "SVGTSpanElement",
664
+ "SVGTextContentElement",
665
+ "SVGTextElement",
666
+ "SVGTextPathElement",
667
+ "SVGTextPositioningElement",
668
+ "SVGTitleElement",
669
+ "SVGTransform",
670
+ "SVGTransformList",
671
+ "SVGUnitTypes",
672
+ "SVGUseElement",
673
+ "SVGViewElement",
674
+ "Sanitizer",
675
+ "Scheduler",
676
+ "Scheduling",
677
+ "Screen",
678
+ "ScreenDetailed",
679
+ "ScreenDetails",
680
+ "ScreenOrientation",
681
+ "ScriptProcessorNode",
682
+ "SecurityPolicyViolationEvent",
683
+ "Selection",
684
+ "Sensor",
685
+ "SensorErrorEvent",
686
+ "Serial",
687
+ "SerialPort",
688
+ "ServiceWorker",
689
+ "ServiceWorkerContainer",
690
+ "ServiceWorkerRegistration",
691
+ "Set",
692
+ "ShadowRoot",
693
+ "SharedWorker",
694
+ "SourceBuffer",
695
+ "SourceBufferList",
696
+ "SpeechSynthesisErrorEvent",
697
+ "SpeechSynthesisEvent",
698
+ "SpeechSynthesisUtterance",
699
+ "StaticRange",
700
+ "StereoPannerNode",
701
+ "Storage",
702
+ "StorageEvent",
703
+ "StorageManager",
704
+ "String",
705
+ "StylePropertyMap",
706
+ "StylePropertyMapReadOnly",
707
+ "StyleSheet",
708
+ "StyleSheetList",
709
+ "SubmitEvent",
710
+ "SubtleCrypto",
711
+ "Symbol",
712
+ "SyncManager",
713
+ "SyntaxError",
714
+ "TaskAttributionTiming",
715
+ "TaskController",
716
+ "TaskPriorityChangeEvent",
717
+ "TaskSignal",
718
+ "Text",
719
+ "TextDecoder",
720
+ "TextDecoderStream",
721
+ "TextEncoder",
722
+ "TextEncoderStream",
723
+ "TextEvent",
724
+ "TextMetrics",
725
+ "TextTrack",
726
+ "TextTrackCue",
727
+ "TextTrackCueList",
728
+ "TextTrackList",
729
+ "TimeRanges",
730
+ "ToggleEvent",
731
+ "Touch",
732
+ "TouchEvent",
733
+ "TouchList",
734
+ "TrackEvent",
735
+ "TransformStream",
736
+ "TransformStreamDefaultController",
737
+ "TransitionEvent",
738
+ "TreeWalker",
739
+ "TrustedHTML",
740
+ "TrustedScript",
741
+ "TrustedScriptURL",
742
+ "TrustedTypePolicy",
743
+ "TrustedTypePolicyFactory",
744
+ "TypeError",
745
+ "UIEvent",
746
+ "URIError",
747
+ "URL",
748
+ "URLPattern",
749
+ "URLSearchParams",
750
+ "USB",
751
+ "USBAlternateInterface",
752
+ "USBConfiguration",
753
+ "USBConnectionEvent",
754
+ "USBDevice",
755
+ "USBEndpoint",
756
+ "USBInTransferResult",
757
+ "USBInterface",
758
+ "USBIsochronousInTransferPacket",
759
+ "USBIsochronousInTransferResult",
760
+ "USBIsochronousOutTransferPacket",
761
+ "USBIsochronousOutTransferResult",
762
+ "USBOutTransferResult",
763
+ "Uint16Array",
764
+ "Uint32Array",
765
+ "Uint8Array",
766
+ "Uint8ClampedArray",
767
+ "UserActivation",
768
+ "VTTCue",
769
+ "ValidityState",
770
+ "VideoColorSpace",
771
+ "VideoDecoder",
772
+ "VideoEncoder",
773
+ "VideoFrame",
774
+ "VideoPlaybackQuality",
775
+ "ViewTransition",
776
+ "VirtualKeyboard",
777
+ "VirtualKeyboardGeometryChangeEvent",
778
+ "VisualViewport",
779
+ "WakeLock",
780
+ "WakeLockSentinel",
781
+ "WaveShaperNode",
782
+ "WeakMap",
783
+ "WeakRef",
784
+ "WeakSet",
785
+ "WebAssembly",
786
+ "WebGL2RenderingContext",
787
+ "WebGLActiveInfo",
788
+ "WebGLBuffer",
789
+ "WebGLContextEvent",
790
+ "WebGLFramebuffer",
791
+ "WebGLProgram",
792
+ "WebGLQuery",
793
+ "WebGLRenderbuffer",
794
+ "WebGLRenderingContext",
795
+ "WebGLSampler",
796
+ "WebGLShader",
797
+ "WebGLShaderPrecisionFormat",
798
+ "WebGLSync",
799
+ "WebGLTexture",
800
+ "WebGLTransformFeedback",
801
+ "WebGLUniformLocation",
802
+ "WebGLVertexArrayObject",
803
+ "WebKitCSSMatrix",
804
+ "WebKitMutationObserver",
805
+ "WebSocket",
806
+ "WebTransport",
807
+ "WebTransportBidirectionalStream",
808
+ "WebTransportDatagramDuplexStream",
809
+ "WebTransportError",
810
+ "WheelEvent",
811
+ "Window",
812
+ "WindowControlsOverlay",
813
+ "WindowControlsOverlayGeometryChangeEvent",
814
+ "Worker",
815
+ "Worklet",
816
+ "WritableStream",
817
+ "WritableStreamDefaultController",
818
+ "WritableStreamDefaultWriter",
819
+ "XMLDocument",
820
+ "XMLHttpRequest",
821
+ "XMLHttpRequestEventTarget",
822
+ "XMLHttpRequestUpload",
823
+ "XMLSerializer",
824
+ "XPathEvaluator",
825
+ "XPathExpression",
826
+ "XPathResult",
827
+ "XRAnchor",
828
+ "XRAnchorSet",
829
+ "XRBoundedReferenceSpace",
830
+ "XRCPUDepthInformation",
831
+ "XRCamera",
832
+ "XRDOMOverlayState",
833
+ "XRDepthInformation",
834
+ "XRFrame",
835
+ "XRHitTestResult",
836
+ "XRHitTestSource",
837
+ "XRInputSource",
838
+ "XRInputSourceArray",
839
+ "XRInputSourceEvent",
840
+ "XRInputSourcesChangeEvent",
841
+ "XRLayer",
842
+ "XRLightEstimate",
843
+ "XRLightProbe",
844
+ "XRPose",
845
+ "XRRay",
846
+ "XRReferenceSpace",
847
+ "XRReferenceSpaceEvent",
848
+ "XRRenderState",
849
+ "XRRigidTransform",
850
+ "XRSession",
851
+ "XRSessionEvent",
852
+ "XRSpace",
853
+ "XRSystem",
854
+ "XRTransientInputHitTestResult",
855
+ "XRTransientInputHitTestSource",
856
+ "XRView",
857
+ "XRViewerPose",
858
+ "XRViewport",
859
+ "XRWebGLBinding",
860
+ "XRWebGLDepthInformation",
861
+ "XRWebGLLayer",
862
+ "XSLTProcessor",
863
+ "__core-js_shared__",
864
+ "_countAA",
865
+ "ae",
866
+ "alert",
867
+ "api_target",
868
+ "api_target_sri",
869
+ "ark",
870
+ "async_fingerprints",
871
+ "atob",
872
+ "blur",
873
+ "btoa",
874
+ "caches",
875
+ "cancelAnimationFrame",
876
+ "cancelIdleCallback",
877
+ "capiMode",
878
+ "capiSettings",
879
+ "capiVersion",
880
+ "captureEvents",
881
+ "cdn",
882
+ "chrome",
883
+ "clearInterval",
884
+ "clearTimeout",
885
+ "clientInformation",
886
+ "close",
887
+ "closed",
888
+ "confirm",
889
+ "console",
890
+ "cookieStore",
891
+ "createImageBitmap",
892
+ "credentialless",
893
+ "crossOriginIsolated",
894
+ "crypto",
895
+ "customElements",
896
+ "decodeURI",
897
+ "decodeURIComponent",
898
+ "devicePixelRatio",
899
+ "doBBBd",
900
+ "document",
901
+ "encodeURI",
902
+ "encodeURIComponent",
903
+ "escape",
904
+ "eval",
905
+ "event",
906
+ "extended_fingerprinting_enabled",
907
+ "external",
908
+ "fc_api_server",
909
+ "fc_fp",
910
+ "fc_obj",
911
+ "fetch",
912
+ "find",
913
+ "find_onload",
914
+ "fingerprinting_enabled",
915
+ "focus",
916
+ "fp_result",
917
+ "frameElement",
918
+ "frames",
919
+ "getComputedStyle",
920
+ "getScreenDetails",
921
+ "getSelection",
922
+ "get_outer_html",
923
+ "get_query_data",
924
+ "globalThis",
925
+ "history",
926
+ "indexedDB",
927
+ "innerHeight",
928
+ "innerWidth",
929
+ "isFinite",
930
+ "isNaN",
931
+ "isSecureContext",
932
+ "launchQueue",
933
+ "length",
934
+ "loadedWithData",
935
+ "localStorage",
936
+ "location",
937
+ "locationbar",
938
+ "log",
939
+ "matchMedia",
940
+ "menubar",
941
+ "moveBy",
942
+ "moveTo",
943
+ "msie",
944
+ "name",
945
+ "navigation",
946
+ "navigator",
947
+ "offscreenBuffering",
948
+ "onabort",
949
+ "onafterprint",
950
+ "onanimationend",
951
+ "onanimationiteration",
952
+ "onanimationstart",
953
+ "onappinstalled",
954
+ "onauxclick",
955
+ "onbeforeinput",
956
+ "onbeforeinstallprompt",
957
+ "onbeforematch",
958
+ "onbeforeprint",
959
+ "onbeforetoggle",
960
+ "onbeforeunload",
961
+ "onbeforexrselect",
962
+ "onblur",
963
+ "oncancel",
964
+ "oncanplay",
965
+ "oncanplaythrough",
966
+ "onchange",
967
+ "onclick",
968
+ "onclose",
969
+ "oncontentvisibilityautostatechange",
970
+ "oncontextlost",
971
+ "oncontextmenu",
972
+ "oncontextrestored",
973
+ "oncuechange",
974
+ "ondblclick",
975
+ "ondevicemotion",
976
+ "ondeviceorientation",
977
+ "ondeviceorientationabsolute",
978
+ "ondrag",
979
+ "ondragend",
980
+ "ondragenter",
981
+ "ondragleave",
982
+ "ondragover",
983
+ "ondragstart",
984
+ "ondrop",
985
+ "ondurationchange",
986
+ "onemptied",
987
+ "onended",
988
+ "onerror",
989
+ "onfocus",
990
+ "onformdata",
991
+ "ongotpointercapture",
992
+ "onhashchange",
993
+ "oninput",
994
+ "oninvalid",
995
+ "onkeydown",
996
+ "onkeypress",
997
+ "onkeyup",
998
+ "onlanguagechange",
999
+ "onload",
1000
+ "onload_retry",
1001
+ "onloadeddata",
1002
+ "onloadedmetadata",
1003
+ "onloadstart",
1004
+ "onlostpointercapture",
1005
+ "onmessage",
1006
+ "onmessageerror",
1007
+ "onmousedown",
1008
+ "onmouseenter",
1009
+ "onmouseleave",
1010
+ "onmousemove",
1011
+ "onmouseout",
1012
+ "onmouseover",
1013
+ "onmouseup",
1014
+ "onmousewheel",
1015
+ "onoffline",
1016
+ "ononline",
1017
+ "onpagehide",
1018
+ "onpageshow",
1019
+ "onpause",
1020
+ "onplay",
1021
+ "onplaying",
1022
+ "onpointercancel",
1023
+ "onpointerdown",
1024
+ "onpointerenter",
1025
+ "onpointerleave",
1026
+ "onpointermove",
1027
+ "onpointerout",
1028
+ "onpointerover",
1029
+ "onpointerrawupdate",
1030
+ "onpointerup",
1031
+ "onpopstate",
1032
+ "onprogress",
1033
+ "onratechange",
1034
+ "onrejectionhandled",
1035
+ "onreset",
1036
+ "onresize",
1037
+ "onscroll",
1038
+ "onscrollend",
1039
+ "onsearch",
1040
+ "onsecuritypolicyviolation",
1041
+ "onseeked",
1042
+ "onseeking",
1043
+ "onselect",
1044
+ "onselectionchange",
1045
+ "onselectstart",
1046
+ "onslotchange",
1047
+ "onstalled",
1048
+ "onstorage",
1049
+ "onsubmit",
1050
+ "onsuspend",
1051
+ "ontimeupdate",
1052
+ "ontoggle",
1053
+ "ontransitioncancel",
1054
+ "ontransitionend",
1055
+ "ontransitionrun",
1056
+ "ontransitionstart",
1057
+ "onunhandledrejection",
1058
+ "onunload",
1059
+ "onvolumechange",
1060
+ "onwaiting",
1061
+ "onwebkitanimationend",
1062
+ "onwebkitanimationiteration",
1063
+ "onwebkitanimationstart",
1064
+ "onwebkittransitionend",
1065
+ "onwheel",
1066
+ "open",
1067
+ "openDatabase",
1068
+ "opener",
1069
+ "origin",
1070
+ "originAgentCluster",
1071
+ "outerHeight",
1072
+ "outerWidth",
1073
+ "pageXOffset",
1074
+ "pageYOffset",
1075
+ "parent",
1076
+ "parseFloat",
1077
+ "parseInt",
1078
+ "performance",
1079
+ "personalbar",
1080
+ "postMessage",
1081
+ "print",
1082
+ "prompt",
1083
+ "public_key",
1084
+ "queryLocalFonts",
1085
+ "query_data",
1086
+ "queueMicrotask",
1087
+ "releaseEvents",
1088
+ "reportError",
1089
+ "requestAnimationFrame",
1090
+ "requestIdleCallback",
1091
+ "resizeBy",
1092
+ "resizeTo",
1093
+ "scheduler",
1094
+ "screen",
1095
+ "screenLeft",
1096
+ "screenTop",
1097
+ "screenX",
1098
+ "screenY",
1099
+ "scroll",
1100
+ "scrollBy",
1101
+ "scrollTo",
1102
+ "scrollX",
1103
+ "scrollY",
1104
+ "scrollbars",
1105
+ "self",
1106
+ "sessionStorage",
1107
+ "setAPIInput",
1108
+ "setInterval",
1109
+ "setQueryDataInput",
1110
+ "setTimeout",
1111
+ "showDirectoryPicker",
1112
+ "showOpenFilePicker",
1113
+ "showSaveFilePicker",
1114
+ "siteData",
1115
+ "speechSynthesis",
1116
+ "startArkoseEnforcement",
1117
+ "status",
1118
+ "statusbar",
1119
+ "stop",
1120
+ "stringifyWithFloat",
1121
+ "structuredClone",
1122
+ "styleMedia",
1123
+ "target",
1124
+ "toolbar",
1125
+ "top",
1126
+ "trustedTypes",
1127
+ "undefined",
1128
+ "unescape",
1129
+ "visualViewport",
1130
+ "webkitCancelAnimationFrame",
1131
+ "webkitMediaStream",
1132
+ "webkitRTCPeerConnection",
1133
+ "webkitRequestAnimationFrame",
1134
+ "webkitRequestFileSystem",
1135
+ "webkitResolveLocalFileSystemURL",
1136
+ "webkitSpeechGrammar",
1137
+ "webkitSpeechGrammarList",
1138
+ "webkitSpeechRecognition",
1139
+ "webkitSpeechRecognitionError",
1140
+ "webkitSpeechRecognitionEvent",
1141
+ "webkitURL",
1142
+ "window",
1143
+ }
1144
+ sort.Strings(b1)
1145
+ result := strings.Join(b1, "|")
1146
+ return getMurmur128String(result, 420)
1147
+ }
1148
+
1149
+ func getWindowProtoChainHash() string { // return this[dh(f_a_hU.f)](b0[dh(f_a_hU.g)]('|'), 0x1a4);
1150
+ // Object.getPrototypeOf(window);
1151
+ b0 := []string{
1152
+ "TEMPORARY",
1153
+ "PERSISTENT",
1154
+ "constructor",
1155
+ "addEventListener",
1156
+ "dispatchEvent",
1157
+ "removeEventListener",
1158
+ "constructor",
1159
+ "constructor",
1160
+ "__defineGetter__",
1161
+ "__defineSetter__",
1162
+ "hasOwnProperty",
1163
+ "__lookupGetter__",
1164
+ "__lookupSetter__",
1165
+ "isPrototypeOf",
1166
+ "propertyIsEnumerable",
1167
+ "toString",
1168
+ "valueOf",
1169
+ "__proto__",
1170
+ "toLocaleString",
1171
+ }
1172
+ result2 := strings.Join(b0, "|")
1173
+ return x64hash128(result2, 420)
1174
+ }
1175
+
1176
+ func x64Add(m []uint32, n []uint32) []uint32 {
1177
+ m = []uint32{m[0] >> 16, m[0] & 0xffff, m[1] >> 16, m[1] & 0xffff}
1178
+ n = []uint32{n[0] >> 16, n[0] & 0xffff, n[1] >> 16, n[1] & 0xffff}
1179
+ o := []uint32{0, 0, 0, 0}
1180
+ o[3] += m[3] + n[3]
1181
+ o[2] += o[3] >> 16
1182
+ o[3] &= 0xffff
1183
+ o[2] += m[2] + n[2]
1184
+ o[1] += o[2] >> 16
1185
+ o[2] &= 0xffff
1186
+ o[1] += m[1] + n[1]
1187
+ o[0] += o[1] >> 16
1188
+ o[1] &= 0xffff
1189
+ o[0] += m[0] + n[0]
1190
+ o[0] &= 0xffff
1191
+ return []uint32{(o[0] << 16) | o[1], (o[2] << 16) | o[3]}
1192
+ }
1193
+
1194
+ func x64Multiply(m []uint32, n []uint32) []uint32 {
1195
+ m = []uint32{m[0] >> 16, m[0] & 0xffff, m[1] >> 16, m[1] & 0xffff}
1196
+ n = []uint32{n[0] >> 16, n[0] & 0xffff, n[1] >> 16, n[1] & 0xffff}
1197
+ o := []uint32{0, 0, 0, 0}
1198
+ o[3] += m[3] * n[3]
1199
+ o[2] += o[3] >> 16
1200
+ o[3] &= 0xffff
1201
+ o[2] += m[2] * n[3]
1202
+ o[1] += o[2] >> 16
1203
+ o[2] &= 0xffff
1204
+ o[2] += m[3] * n[2]
1205
+ o[1] += o[2] >> 16
1206
+ o[2] &= 0xffff
1207
+ o[1] += m[1] * n[3]
1208
+ o[0] += o[1] >> 16
1209
+ o[1] &= 0xffff
1210
+ o[1] += m[2] * n[2]
1211
+ o[0] += o[1] >> 16
1212
+ o[1] &= 0xffff
1213
+ o[1] += m[3] * n[1]
1214
+ o[0] += o[1] >> 16
1215
+ o[1] &= 0xffff
1216
+ o[0] += m[0]*n[3] + m[1]*n[2] + m[2]*n[1] + m[3]*n[0]
1217
+ o[0] &= 0xffff
1218
+ return []uint32{(o[0] << 16) | o[1], (o[2] << 16) | o[3]}
1219
+ }
1220
+
1221
+ //goland:noinspection SpellCheckingInspection
1222
+ func x64Rotl(m []uint32, n uint32) []uint32 {
1223
+ n %= 64
1224
+ if n == 32 {
1225
+ return []uint32{m[1], m[0]}
1226
+ } else if n < 32 {
1227
+ return []uint32{(m[0] << n) | (m[1] >> (32 - n)), (m[1] << n) | (m[0] >> (32 - n))}
1228
+ } else {
1229
+ n -= 32
1230
+ return []uint32{(m[1] << n) | (m[0] >> (32 - n)), (m[0] << n) | (m[1] >> (32 - n))}
1231
+ }
1232
+ }
1233
+
1234
+ func x64LeftShift(m []uint32, n uint32) []uint32 {
1235
+ n %= 64
1236
+ if n == 0 {
1237
+ return m
1238
+ } else if n < 32 {
1239
+ return []uint32{(m[0] << n) | (m[1] >> (32 - n)), m[1] << n}
1240
+ } else {
1241
+ return []uint32{m[1] << (n - 32), 0}
1242
+ }
1243
+ }
1244
+
1245
+ func x64Xor(m []uint32, n []uint32) []uint32 {
1246
+ return []uint32{m[0] ^ n[0], m[1] ^ n[1]}
1247
+ }
1248
+
1249
+ //goland:noinspection SpellCheckingInspection
1250
+ func x64Fmix(h []uint32) []uint32 {
1251
+ h = x64Xor(h, []uint32{0, h[0] >> 1})
1252
+ h = x64Multiply(h, []uint32{0xff51afd7, 0xed558ccd})
1253
+ h = x64Xor(h, []uint32{0, h[0] >> 1})
1254
+ h = x64Multiply(h, []uint32{0xc4ceb9fe, 0x1a85ec53})
1255
+ h = x64Xor(h, []uint32{0, h[0] >> 1})
1256
+ return h
1257
+ }
1258
+
1259
+ func x64hash128(key string, seed uint32) string {
1260
+ keyLength := len(key)
1261
+ remainder := keyLength % 16
1262
+ bytes := keyLength - remainder
1263
+
1264
+ var h1 = []uint32{0, seed}
1265
+ var h2 = []uint32{0, seed}
1266
+ var k1 = []uint32{0, 0}
1267
+ var k2 = []uint32{0, 0}
1268
+ var c1 = []uint32{0x87c37b91, 0x114253d5}
1269
+ var c2 = []uint32{0x4cf5ad43, 0x2745937f}
1270
+
1271
+ for i := 0; i < bytes; i += 16 {
1272
+ k1[0] = uint32(key[i+4])&0xff | (uint32(key[i+5])&0xff)<<8 | (uint32(key[i+6])&0xff)<<16 | (uint32(key[i+7])&0xff)<<24
1273
+ k1[1] = uint32(key[i])&0xff | (uint32(key[i+1])&0xff)<<8 | (uint32(key[i+2])&0xff)<<16 | (uint32(key[i+3])&0xff)<<24
1274
+
1275
+ k2[0] = uint32(key[i+12])&0xff | (uint32(key[i+13])&0xff)<<8 | (uint32(key[i+14])&0xff)<<16 | (uint32(key[i+15])&0xff)<<24
1276
+ k2[1] = uint32(key[i+8])&0xff | (uint32(key[i+9])&0xff)<<8 | (uint32(key[i+10])&0xff)<<16 | (uint32(key[i+11])&0xff)<<24
1277
+
1278
+ k1 = x64Multiply(k1, c1)
1279
+ k1 = x64Rotl(k1, 31)
1280
+ k1 = x64Multiply(k1, c2)
1281
+ h1 = x64Xor(h1, k1)
1282
+ h1 = x64Rotl(h1, 27)
1283
+ h1 = x64Add(h1, h2)
1284
+ h1 = x64Add(x64Multiply(h1, []uint32{0, 5}), []uint32{0, 0x52dce729})
1285
+
1286
+ k2 = x64Multiply(k2, c2)
1287
+ k2 = x64Rotl(k2, 33)
1288
+ k2 = x64Multiply(k2, c1)
1289
+ h2 = x64Xor(h2, k2)
1290
+ h2 = x64Rotl(h2, 31)
1291
+ h2 = x64Add(h2, h1)
1292
+ h2 = x64Add(x64Multiply(h2, []uint32{0, 5}), []uint32{0, 0x38495ab5})
1293
+ }
1294
+
1295
+ k1 = []uint32{0, 0}
1296
+ k2 = []uint32{0, 0}
1297
+
1298
+ switch remainder {
1299
+ case 15:
1300
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+14])}, 48))
1301
+ fallthrough
1302
+ case 14:
1303
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+13])}, 40))
1304
+ fallthrough
1305
+ case 13:
1306
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+12])}, 32))
1307
+ fallthrough
1308
+ case 12:
1309
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+11])}, 24))
1310
+ fallthrough
1311
+ case 11:
1312
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+10])}, 16))
1313
+ fallthrough
1314
+ case 10:
1315
+ k2 = x64Xor(k2, x64LeftShift([]uint32{0, uint32(key[bytes+9])}, 8))
1316
+ fallthrough
1317
+ case 9:
1318
+ k2 = x64Xor(k2, []uint32{0, uint32(key[bytes+8])})
1319
+ k2 = x64Multiply(k2, c2)
1320
+ k2 = x64Rotl(k2, 33)
1321
+ k2 = x64Multiply(k2, c1)
1322
+ h2 = x64Xor(h2, k2)
1323
+ fallthrough
1324
+ case 8:
1325
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+7])}, 56))
1326
+ fallthrough
1327
+ case 7:
1328
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+6])}, 48))
1329
+ fallthrough
1330
+ case 6:
1331
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+5])}, 40))
1332
+ fallthrough
1333
+ case 5:
1334
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+4])}, 32))
1335
+ fallthrough
1336
+ case 4:
1337
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+3])}, 24))
1338
+ fallthrough
1339
+ case 3:
1340
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+2])}, 16))
1341
+ fallthrough
1342
+ case 2:
1343
+ k1 = x64Xor(k1, x64LeftShift([]uint32{0, uint32(key[bytes+1])}, 8))
1344
+ fallthrough
1345
+ case 1:
1346
+ k1 = x64Xor(k1, []uint32{0, uint32(key[bytes])})
1347
+ k1 = x64Multiply(k1, c1)
1348
+ k1 = x64Rotl(k1, 31)
1349
+ k1 = x64Multiply(k1, c2)
1350
+ h1 = x64Xor(h1, k1)
1351
+ }
1352
+
1353
+ h1 = x64Xor(h1, []uint32{0, uint32(keyLength)})
1354
+ h2 = x64Xor(h2, []uint32{0, uint32(keyLength)})
1355
+ h1 = x64Add(h1, h2)
1356
+ h2 = x64Add(h2, h1)
1357
+ h1 = x64Fmix(h1)
1358
+ h2 = x64Fmix(h2)
1359
+ h1 = x64Add(h1, h2)
1360
+ h2 = x64Add(h2, h1)
1361
+
1362
+ return fmt.Sprintf("%08x%08x%08x%08x", h1[0], h1[1], h2[0], h2[1])
1363
+ }
1364
+
1365
+ func getCFPHash(cfp string) uint32 {
1366
+ //'this is the cfp: canvas xxx base64 image'.split('').reduce((b5, b6) => {
1367
+ // return b5 = (b5 << 5) - b5 + b6.charCodeAt(0), b5 & b5;
1368
+ //}, 0);
1369
+
1370
+ var b5 uint32
1371
+ for _, b6 := range cfp {
1372
+ b5 = (b5 << 5) - b5 + uint32(b6)
1373
+ b5 &= b5
1374
+ }
1375
+ return b5
1376
+ }
1377
+
1378
+ func getIfeHash() string {
1379
+ return x64hash128(strings.Join(getFeList(), ", "), 38)
1380
+ }
pkg/funcaptcha/murmur.go ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "encoding/binary"
5
+ "fmt"
6
+ )
7
+
8
+ type digest struct {
9
+ h1, h2 uint64
10
+ length int
11
+ seed uint64
12
+ }
13
+
14
+ func getMurmur128String(input string, seed uint64) string {
15
+ d := newWithSeed(seed)
16
+ d.Write([]byte(input))
17
+ h1, h2 := d.Sum()
18
+ return fmt.Sprintf("%016x%016x", h1, h2)
19
+ }
20
+
21
+ func newWithSeed(seed uint64) *digest {
22
+ d := new(digest)
23
+ d.seed = seed
24
+ d.h1 = seed
25
+ d.h2 = seed
26
+ return d
27
+ }
28
+
29
+ func (d *digest) Write(data []byte) {
30
+ length := len(data)
31
+ d.length += length
32
+
33
+ var (
34
+ h1 = d.h1
35
+ h2 = d.h2
36
+ c1 = uint64(0x87c37b91114253d5)
37
+ c2 = uint64(0x4cf5ad432745937f)
38
+ )
39
+
40
+ for len(data) >= 16 {
41
+ k1 := binary.LittleEndian.Uint64(data)
42
+ k2 := binary.LittleEndian.Uint64(data[8:])
43
+
44
+ k1 *= c1
45
+ k1 = (k1 << 31) | (k1 >> (64 - 31))
46
+ k1 *= c2
47
+ h1 ^= k1
48
+
49
+ h1 = (h1 << 27) | (h1 >> (64 - 27))
50
+ h1 += h2
51
+ h1 = h1*5 + 0x52dce729
52
+
53
+ k2 *= c2
54
+ k2 = (k2 << 33) | (k2 >> (64 - 33))
55
+ k2 *= c1
56
+ h2 ^= k2
57
+
58
+ h2 = (h2 << 31) | (h2 >> (64 - 31))
59
+ h2 += h1
60
+ h2 = h2*5 + 0x38495ab5
61
+
62
+ data = data[16:]
63
+ }
64
+
65
+ var k1, k2 uint64
66
+
67
+ switch len(data) {
68
+ case 15:
69
+ k2 ^= uint64(data[14]) << 48
70
+ fallthrough
71
+ case 14:
72
+ k2 ^= uint64(data[13]) << 40
73
+ fallthrough
74
+ case 13:
75
+ k2 ^= uint64(data[12]) << 32
76
+ fallthrough
77
+ case 12:
78
+ k2 ^= uint64(data[11]) << 24
79
+ fallthrough
80
+ case 11:
81
+ k2 ^= uint64(data[10]) << 16
82
+ fallthrough
83
+ case 10:
84
+ k2 ^= uint64(data[9]) << 8
85
+ fallthrough
86
+ case 9:
87
+ k2 ^= uint64(data[8])
88
+ k2 *= c2
89
+ k2 = (k2 << 33) | (k2 >> (64 - 33))
90
+ k2 *= c1
91
+ h2 ^= k2
92
+
93
+ fallthrough
94
+ case 8:
95
+ k1 ^= uint64(data[7]) << 56
96
+ fallthrough
97
+ case 7:
98
+ k1 ^= uint64(data[6]) << 48
99
+ fallthrough
100
+ case 6:
101
+ k1 ^= uint64(data[5]) << 40
102
+ fallthrough
103
+ case 5:
104
+ k1 ^= uint64(data[4]) << 32
105
+ fallthrough
106
+ case 4:
107
+ k1 ^= uint64(data[3]) << 24
108
+ fallthrough
109
+ case 3:
110
+ k1 ^= uint64(data[2]) << 16
111
+ fallthrough
112
+ case 2:
113
+ k1 ^= uint64(data[1]) << 8
114
+ fallthrough
115
+ case 1:
116
+ k1 ^= uint64(data[0])
117
+ k1 *= c1
118
+ k1 = (k1 << 31) | (k1 >> (64 - 31))
119
+ k1 *= c2
120
+ h1 ^= k1
121
+ }
122
+
123
+ h1 ^= uint64(length)
124
+ h2 ^= uint64(length)
125
+
126
+ h1 += h2
127
+ h2 += h1
128
+
129
+ h1 = fmix(h1)
130
+ h2 = fmix(h2)
131
+
132
+ h1 += h2
133
+ h2 += h1
134
+ d.h1 = h1
135
+ d.h2 = h2
136
+ }
137
+
138
+ func (d *digest) Sum() (h1, h2 uint64) {
139
+ return d.h1, d.h2
140
+ }
141
+
142
+ func fmix(k uint64) uint64 {
143
+ k ^= k >> 33
144
+ k *= 0xff51afd7ed558ccd
145
+ k ^= k >> 33
146
+ k *= 0xc4ceb9fe1a85ec53
147
+ k ^= k >> 33
148
+ return k
149
+ }
pkg/funcaptcha/util.go ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import (
4
+ "encoding/base64"
5
+ "encoding/json"
6
+ "fmt"
7
+ "io"
8
+ "net/url"
9
+ "os"
10
+ "strings"
11
+ "time"
12
+
13
+ http "github.com/bogdanfinn/fhttp"
14
+ )
15
+
16
+ func toJSON(data interface{}) string {
17
+ str, _ := json.Marshal(data)
18
+ return string(str)
19
+ }
20
+
21
+ func jsonToForm(data string) string {
22
+ // Unmarshal into map
23
+ var form_data map[string]interface{}
24
+ json.Unmarshal([]byte(data), &form_data)
25
+ // Use reflection to convert to form data
26
+ var form url.Values = url.Values{}
27
+ for k, v := range form_data {
28
+ form.Add(k, fmt.Sprintf("%v", v))
29
+ }
30
+ return form.Encode()
31
+ }
32
+
33
+ func (s *Session) DownloadChallenge(urls []string, b64 bool) ([]string, error) {
34
+ var b64_imgs []string = make([]string, len(urls))
35
+ for i, url := range urls {
36
+ req, _ := http.NewRequest(http.MethodGet, url, nil)
37
+ req.Header = headers
38
+ resp, err := (*s.Client).Do(req)
39
+ if err != nil {
40
+ return nil, err
41
+ }
42
+ defer resp.Body.Close()
43
+
44
+ if resp.StatusCode != 200 {
45
+ return nil, fmt.Errorf("status code %d", resp.StatusCode)
46
+ }
47
+
48
+ body, _ := io.ReadAll(resp.Body)
49
+ // Figure out filename from URL
50
+ url_paths := strings.Split(url, "/")
51
+ if !b64 {
52
+ filename := strings.Split(url_paths[len(url_paths)-1], "?")[0]
53
+ if filename == "image" {
54
+ filename = fmt.Sprintf("image_%s.png", getTimeStamp())
55
+ }
56
+ err = os.WriteFile(filename, body, 0644)
57
+ if err != nil {
58
+ return nil, err
59
+ }
60
+ } else {
61
+ // base64 encode body
62
+ b64_imgs[i] = base64.StdEncoding.EncodeToString(body)
63
+ }
64
+ }
65
+ return b64_imgs, nil
66
+ }
67
+
68
+ func getTimeStamp() string {
69
+ return fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond))
70
+ }
71
+
72
+ func getRequestId(sessionId string) string {
73
+ pwd := fmt.Sprintf("REQUESTED%sID", sessionId)
74
+ return Encrypt(`{"sc":[147,307]}`, pwd)
75
+ }
pkg/funcaptcha/webgl.go ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package funcaptcha
2
+
3
+ import "strings"
4
+
5
+ const (
6
+ webglExtensions = "ANGLE_instanced_arrays;EXT_blend_minmax;EXT_color_buffer_half_float;EXT_disjoint_timer_query;EXT_float_blend;EXT_frag_depth;EXT_shader_texture_lod;EXT_texture_compression_bptc;EXT_texture_compression_rgtc;EXT_texture_filter_anisotropic;EXT_sRGB;KHR_parallel_shader_compile;OES_element_index_uint;OES_fbo_render_mipmap;OES_standard_derivatives;OES_texture_float;OES_texture_float_linear;OES_texture_half_float;OES_texture_half_float_linear;OES_vertex_array_object;WEBGL_color_buffer_float;WEBGL_compressed_texture_s3tc;WEBGL_compressed_texture_s3tc_srgb;WEBGL_debug_renderer_info;WEBGL_debug_shaders;WEBGL_depth_texture;WEBGL_draw_buffers;WEBGL_lose_context;WEBGL_multi_draw" // this.getWebGLKeys();
7
+ webglRenderer = "WebKit WebGL"
8
+ webglVendor = "WebKit"
9
+ webglVersion = "WebGL 1.0 (OpenGL ES 2.0 Chromium)"
10
+ webglShadingLanguageVersion = "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)"
11
+ webglAliasedLineWidthRange = "[1, 10]"
12
+ webglAliasedPointSizeRange = "[1, 2047]"
13
+ webglAntialiasing = "yes"
14
+ webglBits = "8,8,24,8,8,0"
15
+ webglMaxParams = "16,64,32768,1024,32768,32,32768,31,16,32,1024"
16
+ webglMaxViewportDims = "[32768, 32768]"
17
+ webglUnmaskedVendor = "Google Inc. (NVIDIA Corporation)"
18
+ webglUnmaskedRenderer = "ANGLE (NVIDIA Corporation, NVIDIA GeForce RTX 3060 Ti/PCIe/SSE2, OpenGL 4.5.0)"
19
+ webglFsfParams = "23,127,127,10,15,15,10,15,15"
20
+ webglFsiParams = "0,31,30,0,31,30,0,31,30"
21
+ webglVsfParams = "23,127,127,10,15,15,10,15,15"
22
+ webglVsiParams = "0,31,30,0,31,30,0,31,30"
23
+ )
24
+
25
+ var (
26
+ webglExtensionsHash = getWebglExtensionsHash()
27
+ )
28
+
29
+ func getWebglExtensionsHash() string {
30
+ return x64hash128(webglExtensions, 0)
31
+ }
32
+
33
+ func getWebglHashWebgl() string {
34
+ //aZ['webgl_hash' + cr(f_a_gY.X)] = this['x64hash128'](aC(aZ, function(b3) {
35
+ // return b3;
36
+ //})[cr(f_a_gY.Y)](','));
37
+
38
+ var webglList []string
39
+ webglList = append(webglList, webglExtensions)
40
+ webglList = append(webglList, webglExtensionsHash)
41
+ webglList = append(webglList, webglRenderer)
42
+ webglList = append(webglList, webglVendor)
43
+ webglList = append(webglList, webglVersion)
44
+ webglList = append(webglList, webglShadingLanguageVersion)
45
+ webglList = append(webglList, webglAliasedLineWidthRange)
46
+ webglList = append(webglList, webglAliasedPointSizeRange)
47
+ webglList = append(webglList, webglAntialiasing)
48
+ webglList = append(webglList, webglBits)
49
+ webglList = append(webglList, webglMaxParams)
50
+ webglList = append(webglList, webglMaxViewportDims)
51
+ webglList = append(webglList, webglUnmaskedVendor)
52
+ webglList = append(webglList, webglUnmaskedRenderer)
53
+ webglList = append(webglList, webglFsfParams)
54
+ webglList = append(webglList, webglFsiParams)
55
+ webglList = append(webglList, webglVsfParams)
56
+ webglList = append(webglList, webglVsiParams)
57
+ return x64hash128(strings.Join(webglList, ","), 0)
58
+ }
pkg/logger/logger.go ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package logger
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "github.com/sirupsen/logrus"
6
+ "os"
7
+ )
8
+
9
+ var Log *logrus.Logger
10
+
11
+ func init() {
12
+ Log = logrus.New()
13
+ level, err := logrus.ParseLevel(env.E.LogLevel)
14
+ if err != nil {
15
+ return
16
+ }
17
+ Log.SetLevel(level)
18
+
19
+ Log.SetOutput(os.Stdout)
20
+
21
+ Log.SetFormatter(&logrus.TextFormatter{
22
+ FullTimestamp: true,
23
+ TimestampFormat: "2006-01-02 15:04:05",
24
+ })
25
+ }
pkg/plugins/api/arkosetoken/arkosetoken.go ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package arkosetoken
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/funcaptcha"
6
+ "WarpGPT/pkg/plugins"
7
+ http "github.com/bogdanfinn/fhttp"
8
+ tls_client "github.com/bogdanfinn/tls-client"
9
+ "github.com/gin-gonic/gin"
10
+ "io"
11
+ )
12
+
13
+ var context *plugins.Component
14
+ var ArkoseTokenInstance ArkoseToken
15
+
16
+ type Context struct {
17
+ GinContext *gin.Context
18
+ RequestUrl string
19
+ RequestClient tls_client.HttpClient
20
+ RequestBody io.ReadCloser
21
+ RequestParam string
22
+ RequestMethod string
23
+ RequestHeaders http.Header
24
+ }
25
+ type ArkoseToken struct {
26
+ Context Context
27
+ }
28
+
29
+ func (p *ArkoseToken) GetContext() Context {
30
+ p.Context.RequestClient = common.GetHttpClient()
31
+ return p.Context
32
+ }
33
+ func (p *ArkoseToken) SetContext(conversation Context) {
34
+ p.Context = conversation
35
+ }
36
+
37
+ func (p *ArkoseToken) ProcessMethod() {
38
+ context.Logger.Debug("ArkoseToken")
39
+ id := p.GetContext().GinContext.Param("id")
40
+ var (
41
+ token string
42
+ err error
43
+ )
44
+ if id == "35536E1E-65B4-4D96-9D97-6ADB7EFF8147" {
45
+ token, err = funcaptcha.GetOpenAIArkoseToken(4, p.GetContext().RequestHeaders.Get("puid"))
46
+ } else if id == "0A1D34FC-659D-4E23-B17B-694DCFCF6A6C" {
47
+ token, err = funcaptcha.GetOpenAIArkoseToken(0, p.GetContext().RequestHeaders.Get("puid"))
48
+ } else if id == "3D86FBBA-9D22-402A-B512-3420086BA6CC" {
49
+ token, err = funcaptcha.GetOpenAIArkoseToken(3, p.GetContext().RequestHeaders.Get("puid"))
50
+ } else {
51
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Invalid id"})
52
+ return
53
+ }
54
+ if err != nil {
55
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Unable to generate ArkoseToken"})
56
+ }
57
+ p.GetContext().GinContext.Header("Content-Type", "application/json")
58
+ p.GetContext().GinContext.JSON(200, gin.H{"token": token})
59
+ }
60
+
61
+ type NotHaveUrl struct {
62
+ }
63
+
64
+ func (u NotHaveUrl) Generate(path string, rawquery string) string {
65
+ return ""
66
+ }
67
+ func (p *ArkoseToken) Run(com *plugins.Component) {
68
+ context = com
69
+ context.Engine.GET("/token/:id", func(c *gin.Context) {
70
+ conversation := common.GetContextPack(c, NotHaveUrl{})
71
+ common.Do[Context](new(ArkoseToken), Context(conversation))
72
+ })
73
+ }
pkg/plugins/api/backendapi/backend.go ADDED
@@ -0,0 +1,288 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package backendapi
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/funcaptcha"
6
+ "WarpGPT/pkg/logger"
7
+ "WarpGPT/pkg/plugins"
8
+ "WarpGPT/pkg/plugins/service/wsstostream"
9
+ "WarpGPT/pkg/tools"
10
+ "bytes"
11
+ "encoding/json"
12
+ http "github.com/bogdanfinn/fhttp"
13
+ tls_client "github.com/bogdanfinn/tls-client"
14
+ "github.com/gin-gonic/gin"
15
+ "io"
16
+ shttp "net/http"
17
+ "strings"
18
+ "time"
19
+ )
20
+
21
+ var context *plugins.Component
22
+ var BackendProcessInstance BackendProcess
23
+
24
+ type Context struct {
25
+ GinContext *gin.Context
26
+ RequestUrl string
27
+ RequestClient tls_client.HttpClient
28
+ RequestBody io.ReadCloser
29
+ RequestParam string
30
+ RequestMethod string
31
+ RequestHeaders http.Header
32
+ }
33
+
34
+ type WsResponse struct {
35
+ ConversationId string `json:"conversation_id"`
36
+ ExpiresAt time.Time `json:"expires_at"`
37
+ ResponseId string `json:"response_id"`
38
+ WssUrl string `json:"wss_url"`
39
+ }
40
+
41
+ type BackendProcess struct {
42
+ ConversationId string
43
+ Context Context
44
+ }
45
+
46
+ func (p *BackendProcess) GetContext() Context {
47
+ return p.Context
48
+ }
49
+ func (p *BackendProcess) SetContext(conversation Context) {
50
+ p.Context = conversation
51
+ }
52
+
53
+ func (p *BackendProcess) ProcessMethod() {
54
+ context.Logger.Debug("ProcessBackendProcess")
55
+ var requestBody map[string]interface{}
56
+ var ws *wsstostream.WssToStream
57
+ err := p.decodeRequestBody(&requestBody)
58
+ if err != nil {
59
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Request json decode error"})
60
+ context.Logger.Error(err)
61
+ return
62
+ }
63
+ request, err := p.createRequest(requestBody)
64
+ if err != nil {
65
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Server error"})
66
+ context.Logger.Error(err)
67
+ return
68
+ }
69
+ if strings.Contains(p.Context.RequestParam, "/conversation/ws") {
70
+ ws = wsstostream.NewWssToStream(p.GetContext().RequestHeaders.Get("Authorization"))
71
+ err = ws.InitConnect()
72
+ }
73
+ if err != nil {
74
+ p.GetContext().GinContext.JSON(500, gin.H{"error": err.Error()})
75
+ context.Logger.Error(err)
76
+ return
77
+ }
78
+ context.Logger.Debug("Requesting to ", p.GetContext().RequestUrl)
79
+ response, err := p.GetContext().RequestClient.Do(request)
80
+ if err != nil {
81
+ var jsonData interface{}
82
+ err = json.NewDecoder(response.Body).Decode(&jsonData)
83
+ if err != nil {
84
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Request json decode error"})
85
+ context.Logger.Error(err)
86
+ return
87
+ }
88
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
89
+ context.Logger.Error(err)
90
+ return
91
+ }
92
+
93
+ common.CopyResponseHeaders(response, p.GetContext().GinContext)
94
+
95
+ if strings.Contains(response.Header.Get("Content-Type"), "text/event-stream") {
96
+ err = p.streamResponse(response)
97
+ if err != nil {
98
+ p.GetContext().GinContext.JSON(500, gin.H{"error": err.Error()})
99
+ context.Logger.Error(err)
100
+ return
101
+ }
102
+ }
103
+ if strings.Contains(response.Header.Get("Content-Type"), "application/json") {
104
+ if strings.Contains(p.Context.RequestParam, "/conversation/ws") {
105
+ context.Logger.Debug("WsToStreamResponse")
106
+ p.WsToStreamResponse(ws, response)
107
+ } else {
108
+ err = p.jsonResponse(response)
109
+ if err != nil {
110
+ p.GetContext().GinContext.JSON(500, gin.H{"error": err.Error()})
111
+ context.Logger.Error(err)
112
+ return
113
+ }
114
+ }
115
+ }
116
+ }
117
+ func (p *BackendProcess) WsToStreamResponse(ws *wsstostream.WssToStream, response *http.Response) {
118
+ var jsonData WsResponse
119
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
120
+ if err != nil {
121
+ context.Logger.Error(err)
122
+ }
123
+ ws.ResponseId = jsonData.ResponseId
124
+ ws.ConversationId = jsonData.ConversationId
125
+ p.GetContext().GinContext.Writer.Header().Set("Content-Type", "text/event-stream")
126
+ p.GetContext().GinContext.Writer.Header().Set("Cache-Control", "no-cache")
127
+ p.GetContext().GinContext.Writer.Header().Set("Connection", "keep-alive")
128
+ ctx := p.GetContext().GinContext.Request.Context()
129
+ for {
130
+ select {
131
+ case <-p.GetContext().GinContext.Writer.CloseNotify():
132
+ logger.Log.Debug("WsToStreamResponse Writer.CloseNotify")
133
+ return
134
+ case <-ctx.Done():
135
+ logger.Log.Debug("WsToStreamResponse ctx.Done")
136
+ return
137
+ default:
138
+ message, err := ws.ReadMessage()
139
+ if err != nil {
140
+ context.Logger.Error(err)
141
+ break
142
+ }
143
+ if message != nil {
144
+ data, err := io.ReadAll(message)
145
+ if err != nil {
146
+ context.Logger.Error(err)
147
+ return
148
+ }
149
+ _, writeErr := p.GetContext().GinContext.Writer.Write(data)
150
+ if writeErr != nil {
151
+ return
152
+ }
153
+ p.GetContext().GinContext.Writer.Flush()
154
+ if strings.Contains(string(data), "data: [DONE]") {
155
+ return
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+ func (p *BackendProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) {
162
+ context.Logger.Debug("BackendProcess createRequest")
163
+ var request *http.Request
164
+ if p.Context.RequestBody == shttp.NoBody {
165
+ request, _ = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil)
166
+ } else {
167
+ token, err := p.addArkoseTokenIfNeeded(&requestBody)
168
+ if err != nil {
169
+ return nil, err
170
+ }
171
+ bodyBytes, err := json.Marshal(requestBody)
172
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bytes.NewBuffer(bodyBytes))
173
+ if token != "" {
174
+ p.addArkoseTokenInHeaderIfNeeded(request, token)
175
+ }
176
+ if err != nil {
177
+ return nil, err
178
+ }
179
+ }
180
+ p.buildHeaders(request)
181
+ p.setCookies(request)
182
+ return request, nil
183
+ }
184
+ func (p *BackendProcess) buildHeaders(request *http.Request) {
185
+ context.Logger.Debug("BackendProcess buildHeaders")
186
+ headers := map[string]string{
187
+ "Host": context.Env.OpenaiHost,
188
+ "Origin": "https://" + context.Env.OpenaiHost + "/chat",
189
+ "Authorization": p.GetContext().GinContext.Request.Header.Get("Authorization"),
190
+ "Connection": "keep-alive",
191
+ "User-Agent": context.Env.UserAgent,
192
+ "Content-Type": p.GetContext().GinContext.Request.Header.Get("Content-Type"),
193
+ }
194
+
195
+ for key, value := range headers {
196
+ request.Header.Set(key, value)
197
+ }
198
+
199
+ if puid := p.GetContext().GinContext.Request.Header.Get("PUID"); puid != "" {
200
+ request.Header.Set("cookie", "_puid="+puid+";")
201
+ }
202
+ }
203
+ func (p *BackendProcess) jsonResponse(response *http.Response) error {
204
+ context.Logger.Debug("BackendProcess jsonResponse")
205
+ var jsonData interface{}
206
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
207
+ if err != nil {
208
+ return err
209
+ }
210
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
211
+ return nil
212
+ }
213
+
214
+ func (p *BackendProcess) streamResponse(response *http.Response) error {
215
+ context.Logger.Debug("BackendProcess streamResponse")
216
+ client := tools.NewSSEClient(response.Body)
217
+ events := client.Read()
218
+ for event := range events {
219
+ if _, err := p.GetContext().GinContext.Writer.Write([]byte("data: " + event.Data + "\n\n")); err != nil {
220
+ return err
221
+ }
222
+ p.GetContext().GinContext.Writer.Flush()
223
+ }
224
+ defer client.Close()
225
+ return nil
226
+ }
227
+ func (p *BackendProcess) addArkoseTokenInHeaderIfNeeded(request *http.Request, token string) {
228
+ context.Logger.Debug("BackendProcess addArkoseTokenInHeaderIfNeeded")
229
+ request.Header.Set("Openai-Sentinel-Arkose-Token", token)
230
+ }
231
+ func (p *BackendProcess) addArkoseTokenIfNeeded(requestBody *map[string]interface{}) (string, error) {
232
+ context.Logger.Debug("BackendProcess addArkoseTokenIfNeeded")
233
+ model, exists := (*requestBody)["model"]
234
+ if !exists {
235
+ return "", nil
236
+ }
237
+ if strings.HasPrefix(model.(string), "gpt-4") || context.Env.ArkoseMust {
238
+ token, err := funcaptcha.GetOpenAIArkoseToken(4, p.GetContext().RequestHeaders.Get("puid"))
239
+ if err != nil {
240
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Get ArkoseToken Failed"})
241
+ return "", err
242
+ }
243
+ (*requestBody)["arkose_token"] = token
244
+ return token, nil
245
+ }
246
+ return "", nil
247
+ }
248
+ func (p *BackendProcess) setCookies(request *http.Request) {
249
+ context.Logger.Debug("BackendProcess setCookies")
250
+ for _, cookie := range p.GetContext().GinContext.Request.Cookies() {
251
+ request.AddCookie(&http.Cookie{
252
+ Name: cookie.Name,
253
+ Value: cookie.Value,
254
+ })
255
+ }
256
+ }
257
+
258
+ func (p *BackendProcess) decodeRequestBody(requestBody *map[string]interface{}) error {
259
+ conversation := p.GetContext()
260
+ if conversation.RequestBody != shttp.NoBody {
261
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
262
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
263
+ return err
264
+ }
265
+ }
266
+ return nil
267
+ }
268
+
269
+ type ReverseBackendRequestUrl struct {
270
+ }
271
+
272
+ func (u ReverseBackendRequestUrl) Generate(path string, rawquery string) string {
273
+ if strings.Contains(path, "/ws") {
274
+ path = strings.ReplaceAll(path, "/ws", "")
275
+ }
276
+ if rawquery == "" {
277
+ return "https://" + context.Env.OpenaiHost + "/backend-api" + path
278
+ }
279
+ return "https://" + context.Env.OpenaiHost + "/backend-api" + path + "?" + rawquery
280
+ }
281
+
282
+ func (p *BackendProcess) Run(com *plugins.Component) {
283
+ context = com
284
+ context.Engine.Any("/backend-api/*path", func(c *gin.Context) {
285
+ conversation := common.GetContextPack(c, ReverseBackendRequestUrl{})
286
+ common.Do[Context](new(BackendProcess), Context(conversation))
287
+ })
288
+ }
pkg/plugins/api/officialapi/officialApi.go ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package officialapi
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/plugins"
6
+ "WarpGPT/pkg/tools"
7
+ "bytes"
8
+ "encoding/json"
9
+ http "github.com/bogdanfinn/fhttp"
10
+ tls_client "github.com/bogdanfinn/tls-client"
11
+ "github.com/gin-gonic/gin"
12
+ "io"
13
+ fhttp "net/http"
14
+ shttp "net/http"
15
+ "strings"
16
+ )
17
+
18
+ var context *plugins.Component
19
+ var OfficialApiProcessInstance OfficialApiProcess
20
+
21
+ type Context struct {
22
+ GinContext *gin.Context
23
+ RequestUrl string
24
+ RequestClient tls_client.HttpClient
25
+ RequestBody io.ReadCloser
26
+ RequestParam string
27
+ RequestMethod string
28
+ RequestHeaders http.Header
29
+ }
30
+ type OfficialApiProcess struct {
31
+ Context Context
32
+ }
33
+
34
+ func (p *OfficialApiProcess) SetContext(conversation Context) {
35
+ p.Context = conversation
36
+ }
37
+ func (p *OfficialApiProcess) GetContext() Context {
38
+ return p.Context
39
+ }
40
+ func (p *OfficialApiProcess) ProcessMethod() {
41
+ context.Logger.Debug("officialApi")
42
+ var requestBody map[string]interface{}
43
+ err := p.decodeRequestBody(&requestBody) //解析请求体
44
+ if err != nil {
45
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Incorrect json format"})
46
+ return
47
+ }
48
+
49
+ request, err := p.createRequest(requestBody) //创建请求
50
+ if err != nil {
51
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Server error"})
52
+ return
53
+ }
54
+
55
+ response, err := p.GetContext().RequestClient.Do(request) //发送请求
56
+ if err != nil {
57
+ context.Logger.Error(err)
58
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Server Error"})
59
+ return
60
+ }
61
+
62
+ common.CopyResponseHeaders(response, p.GetContext().GinContext) //设置响应头
63
+
64
+ if strings.Contains(response.Header.Get("Content-Type"), "text/event-stream") {
65
+ err = p.streamResponse(response)
66
+ if err != nil {
67
+ return
68
+ }
69
+ }
70
+ if strings.Contains(response.Header.Get("Content-Type"), "application/json") {
71
+ err = p.jsonResponse(response)
72
+ if err != nil {
73
+ context.Logger.Warning(err)
74
+ }
75
+ }
76
+ }
77
+
78
+ func (p *OfficialApiProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) {
79
+ context.Logger.Debug("officialApi createRequest")
80
+ bodyBytes, err := json.Marshal(requestBody)
81
+ if err != nil {
82
+ return nil, err
83
+ }
84
+ var request *http.Request
85
+ if p.Context.RequestBody == shttp.NoBody {
86
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil)
87
+ } else {
88
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bytes.NewBuffer(bodyBytes))
89
+ }
90
+ if err != nil {
91
+ return nil, err
92
+ }
93
+ p.WithHeaders(request)
94
+ return request, nil
95
+ }
96
+
97
+ func (p *OfficialApiProcess) WithHeaders(rsq *http.Request) {
98
+ rsq.Header.Set("Authorization", p.Context.RequestHeaders.Get("Authorization"))
99
+ rsq.Header.Set("Content-Type", p.Context.RequestHeaders.Get("Content-Type"))
100
+ }
101
+
102
+ func (p *OfficialApiProcess) jsonResponse(response *http.Response) error {
103
+ context.Logger.Debug("officialApi jsonResponse")
104
+ var jsonData interface{}
105
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
106
+ if err != nil {
107
+ return err
108
+ }
109
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
110
+ return nil
111
+ }
112
+
113
+ func (p *OfficialApiProcess) streamResponse(response *http.Response) error {
114
+ context.Logger.Debug("officialApi streamResponse")
115
+ context.Logger.Infoln("officialApiProcess stream Request")
116
+ client := tools.NewSSEClient(response.Body)
117
+ events := client.Read()
118
+ for event := range events {
119
+ if _, err := p.GetContext().GinContext.Writer.Write([]byte("data: " + event.Data + "\n\n")); err != nil {
120
+ return err
121
+ }
122
+ p.GetContext().GinContext.Writer.Flush()
123
+ }
124
+ defer client.Close()
125
+ return nil
126
+ }
127
+
128
+ type OfficialApiRequestUrl struct {
129
+ }
130
+
131
+ func (u OfficialApiRequestUrl) Generate(path string, rawquery string) string {
132
+ if rawquery == "" {
133
+ return "https://" + context.Env.OpenaiApiHost + "/v1" + path
134
+ }
135
+ return "https://" + context.Env.OpenaiApiHost + "/v1" + path + "?" + rawquery
136
+ }
137
+ func (p *OfficialApiProcess) decodeRequestBody(requestBody *map[string]interface{}) error {
138
+ context.Logger.Debug("officialApi decodeRequestBody")
139
+ conversation := p.GetContext()
140
+ if conversation.RequestBody != fhttp.NoBody {
141
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
142
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
143
+ return err
144
+ }
145
+ }
146
+ return nil
147
+ }
148
+
149
+ func (p *OfficialApiProcess) Run(com *plugins.Component) {
150
+ context = com
151
+ context.Engine.Any("/v1/*path", func(c *gin.Context) {
152
+ conversation := common.GetContextPack(c, OfficialApiRequestUrl{})
153
+ common.Do[Context](new(OfficialApiProcess), Context(conversation))
154
+ })
155
+ }
pkg/plugins/api/publicapi/publicapi.go ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package publicapi
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/plugins"
6
+ "bytes"
7
+ "encoding/json"
8
+ http "github.com/bogdanfinn/fhttp"
9
+ tls_client "github.com/bogdanfinn/tls-client"
10
+ "github.com/gin-gonic/gin"
11
+ "io"
12
+ shttp "net/http"
13
+ "strings"
14
+ )
15
+
16
+ var context *plugins.Component
17
+ var PublicApiProcessInstance PublicApiProcess
18
+
19
+ type Context struct {
20
+ GinContext *gin.Context
21
+ RequestUrl string
22
+ RequestClient tls_client.HttpClient
23
+ RequestBody io.ReadCloser
24
+ RequestParam string
25
+ RequestMethod string
26
+ RequestHeaders http.Header
27
+ }
28
+ type PublicApiProcess struct {
29
+ Context Context
30
+ }
31
+
32
+ func (p *PublicApiProcess) SetContext(conversation Context) {
33
+ p.Context = conversation
34
+ }
35
+ func (p *PublicApiProcess) GetContext() Context {
36
+ return p.Context
37
+ }
38
+ func (p *PublicApiProcess) ProcessMethod() {
39
+ context.Logger.Debug("PublicApiProcess")
40
+ var requestBody map[string]interface{}
41
+ err := p.decodeRequestBody(&requestBody) //解析请求体
42
+ if err != nil {
43
+ return
44
+ }
45
+ request, err := p.createRequest(requestBody) //创建请求
46
+ if err != nil {
47
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Server error"})
48
+ return
49
+ }
50
+ response, err := p.GetContext().RequestClient.Do(request) //发送请求
51
+ if err != nil {
52
+ var jsonData interface{}
53
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
54
+ if err != nil {
55
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Request json decode error"})
56
+ return
57
+ }
58
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
59
+ return
60
+ }
61
+ if strings.Contains(response.Header.Get("Content-Type"), "application/json") {
62
+ err := p.jsonResponse(response)
63
+ if err != nil {
64
+ context.Logger.Warning(err)
65
+ }
66
+ }
67
+ common.CopyResponseHeaders(response, p.GetContext().GinContext) //设置响应头
68
+ }
69
+ func (p *PublicApiProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) {
70
+ context.Logger.Debug("PublicApiProcess createRequest")
71
+ bodyBytes, err := json.Marshal(requestBody)
72
+ if err != nil {
73
+ return nil, err
74
+ }
75
+ bodyReader := bytes.NewReader(bodyBytes)
76
+ var request *http.Request
77
+ if p.Context.RequestBody == shttp.NoBody {
78
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil)
79
+ } else {
80
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bodyReader)
81
+ }
82
+ if err != nil {
83
+ return nil, err
84
+ }
85
+ p.buildHeaders(request)
86
+ p.setCookies(request)
87
+ return request, nil
88
+ }
89
+ func (p *PublicApiProcess) setCookies(request *http.Request) {
90
+ context.Logger.Debug("PublicApiProcess setCookies")
91
+ for _, cookie := range p.GetContext().GinContext.Request.Cookies() {
92
+ request.AddCookie(&http.Cookie{
93
+ Name: cookie.Name,
94
+ Value: cookie.Value,
95
+ })
96
+ }
97
+ }
98
+ func (p *PublicApiProcess) buildHeaders(request *http.Request) {
99
+ context.Logger.Debug("PublicApiProcess buildHeaders")
100
+ headers := map[string]string{
101
+ "Host": context.Env.OpenaiHost,
102
+ "Origin": "https://" + context.Env.OpenaiHost + "/chat",
103
+ "Authorization": p.GetContext().GinContext.Request.Header.Get("Authorization"),
104
+ "Connection": "keep-alive",
105
+ "User-Agent": context.Env.UserAgent,
106
+ "Content-Type": p.GetContext().GinContext.Request.Header.Get("Content-Type"),
107
+ }
108
+ for key, value := range headers {
109
+ request.Header.Set(key, value)
110
+ }
111
+ if puid := p.GetContext().GinContext.Request.Header.Get("PUID"); puid != "" {
112
+ request.Header.Set("cookie", "_puid="+puid+";")
113
+ }
114
+ }
115
+ func (p *PublicApiProcess) jsonResponse(response *http.Response) error {
116
+ context.Logger.Debug("PublicApiProcess jsonResponse")
117
+ var jsonData interface{}
118
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
119
+ if err != nil {
120
+ return err
121
+ }
122
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
123
+ return nil
124
+ }
125
+ func (p *PublicApiProcess) decodeRequestBody(requestBody *map[string]interface{}) error {
126
+ conversation := p.GetContext()
127
+ if conversation.RequestBody != shttp.NoBody {
128
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
129
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
130
+ return err
131
+ }
132
+ }
133
+ return nil
134
+ }
135
+
136
+ type ReversePublicApiRequestUrl struct {
137
+ }
138
+
139
+ func (u ReversePublicApiRequestUrl) Generate(path string, rawquery string) string {
140
+ if rawquery == "" {
141
+ return "https://" + context.Env.OpenaiHost + "/public-api" + path
142
+ }
143
+ return "https://" + context.Env.OpenaiHost + "/public-api" + path + "?" + rawquery
144
+ }
145
+
146
+ func (p *PublicApiProcess) Run(com *plugins.Component) {
147
+ context = com
148
+ context.Engine.Any("/public-api/*path", func(c *gin.Context) {
149
+ conversation := common.GetContextPack(c, ReversePublicApiRequestUrl{})
150
+ common.Do[Context](new(PublicApiProcess), Context(conversation))
151
+ })
152
+ }
pkg/plugins/api/rapi/api.go ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package rapi
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/plugins"
6
+ "bytes"
7
+ "encoding/json"
8
+ http "github.com/bogdanfinn/fhttp"
9
+ tls_client "github.com/bogdanfinn/tls-client"
10
+ "github.com/gin-gonic/gin"
11
+ "io"
12
+ shttp "net/http"
13
+ "strings"
14
+ )
15
+
16
+ var context *plugins.Component
17
+ var ApiProcessInstance ApiProcess
18
+
19
+ type Context struct {
20
+ GinContext *gin.Context
21
+ RequestUrl string
22
+ RequestClient tls_client.HttpClient
23
+ RequestBody io.ReadCloser
24
+ RequestParam string
25
+ RequestMethod string
26
+ RequestHeaders http.Header
27
+ }
28
+ type ApiProcess struct {
29
+ Context Context
30
+ }
31
+
32
+ func (p *ApiProcess) SetContext(conversation Context) {
33
+ p.Context = conversation
34
+ }
35
+ func (p *ApiProcess) GetContext() Context {
36
+ return p.Context
37
+ }
38
+ func (p *ApiProcess) ProcessMethod() {
39
+ context.Logger.Debug("ApiProcess")
40
+ var requestBody map[string]interface{}
41
+ err := p.decodeRequestBody(&requestBody) //解析请求体
42
+ if err != nil {
43
+ return
44
+ }
45
+ request, err := p.createRequest(requestBody) //创建请求
46
+ if err != nil {
47
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Server error"})
48
+ return
49
+ }
50
+ response, err := p.GetContext().RequestClient.Do(request) //发送请求
51
+ if err != nil {
52
+ var jsonData interface{}
53
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
54
+ if err != nil {
55
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Request json decode error"})
56
+ return
57
+ }
58
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
59
+ return
60
+ }
61
+ if strings.Contains(response.Header.Get("Content-Type"), "application/json") {
62
+ err := p.jsonResponse(response)
63
+ if err != nil {
64
+ context.Logger.Warning(err)
65
+ }
66
+ }
67
+ common.CopyResponseHeaders(response, p.GetContext().GinContext) //设置响应头
68
+ }
69
+ func (p *ApiProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) {
70
+ context.Logger.Debug("ApiProcess createRequest")
71
+ bodyBytes, err := json.Marshal(requestBody)
72
+ if err != nil {
73
+ return nil, err
74
+ }
75
+ bodyReader := bytes.NewReader(bodyBytes)
76
+ var request *http.Request
77
+ if p.Context.RequestBody == shttp.NoBody {
78
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil)
79
+ } else {
80
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bodyReader)
81
+ }
82
+ if err != nil {
83
+ return nil, err
84
+ }
85
+ p.buildHeaders(request)
86
+ p.setCookies(request)
87
+ return request, nil
88
+ }
89
+ func (p *ApiProcess) setCookies(request *http.Request) {
90
+ context.Logger.Debug("ApiProcess setCookies")
91
+ for _, cookie := range p.GetContext().GinContext.Request.Cookies() {
92
+ request.AddCookie(&http.Cookie{
93
+ Name: cookie.Name,
94
+ Value: cookie.Value,
95
+ })
96
+ }
97
+ }
98
+ func (p *ApiProcess) buildHeaders(request *http.Request) {
99
+ context.Logger.Debug("ApiProcess buildHeaders")
100
+ headers := map[string]string{
101
+ "Host": context.Env.OpenaiHost,
102
+ "Origin": "https://" + context.Env.OpenaiHost + "/chat",
103
+ "Authorization": p.GetContext().GinContext.Request.Header.Get("Authorization"),
104
+ "Connection": "keep-alive",
105
+ "User-Agent": context.Env.UserAgent,
106
+ "Content-Type": p.GetContext().GinContext.Request.Header.Get("Content-Type"),
107
+ }
108
+ for key, value := range headers {
109
+ request.Header.Set(key, value)
110
+ }
111
+ if puid := p.GetContext().GinContext.Request.Header.Get("PUID"); puid != "" {
112
+ request.Header.Set("cookie", "_puid="+puid+";")
113
+ }
114
+ }
115
+ func (p *ApiProcess) jsonResponse(response *http.Response) error {
116
+ context.Logger.Debug("ApiProcess jsonResponse")
117
+ var jsonData interface{}
118
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
119
+ if err != nil {
120
+ return err
121
+ }
122
+ p.GetContext().GinContext.JSON(response.StatusCode, jsonData)
123
+ return nil
124
+ }
125
+ func (p *ApiProcess) decodeRequestBody(requestBody *map[string]interface{}) error {
126
+ conversation := p.GetContext()
127
+ if conversation.RequestBody != shttp.NoBody {
128
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
129
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
130
+ return err
131
+ }
132
+ }
133
+ return nil
134
+ }
135
+
136
+ type ReverseApiRequestUrl struct {
137
+ }
138
+
139
+ func (u ReverseApiRequestUrl) Generate(path string, rawquery string) string {
140
+ if rawquery == "" {
141
+ return "https://" + context.Env.OpenaiHost + "/api" + path
142
+ }
143
+ return "https://" + context.Env.OpenaiHost + "/api" + path + "?" + rawquery
144
+ }
145
+
146
+ func (p *ApiProcess) Run(com *plugins.Component) {
147
+ context = com
148
+ context.Engine.Any("/api/*path", func(c *gin.Context) {
149
+ conversation := common.GetContextPack(c, ReverseApiRequestUrl{})
150
+ common.Do[Context](new(ApiProcess), Context(conversation))
151
+ })
152
+ }
pkg/plugins/api/session/session.go ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package session
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/plugins"
6
+ "WarpGPT/pkg/tools"
7
+ "encoding/json"
8
+ http "github.com/bogdanfinn/fhttp"
9
+ tls_client "github.com/bogdanfinn/tls-client"
10
+ "github.com/gin-gonic/gin"
11
+ "io"
12
+ shttp "net/http"
13
+ )
14
+
15
+ var context *plugins.Component
16
+ var SessionTokenInstance SessionToken
17
+
18
+ type Context struct {
19
+ GinContext *gin.Context
20
+ RequestUrl string
21
+ RequestClient tls_client.HttpClient
22
+ RequestBody io.ReadCloser
23
+ RequestParam string
24
+ RequestMethod string
25
+ RequestHeaders http.Header
26
+ }
27
+ type SessionToken struct {
28
+ Context Context
29
+ }
30
+
31
+ func (p *SessionToken) GetContext() Context {
32
+ return p.Context
33
+ }
34
+ func (p *SessionToken) SetContext(conversation Context) {
35
+ p.Context = conversation
36
+ }
37
+
38
+ func (p *SessionToken) ProcessMethod() {
39
+ context.Logger.Debug("SessionToken")
40
+ var requestBody map[string]interface{}
41
+ if err := p.decodeRequestBody(&requestBody); err != nil {
42
+ return
43
+ }
44
+ var auth *tools.Authenticator
45
+ username, usernameExists := requestBody["username"]
46
+ password, passwordExists := requestBody["password"]
47
+ puid, puidExists := requestBody["puid"]
48
+ refreshCookie, refreshCookieExists := requestBody["refreshCookie"]
49
+ if !refreshCookieExists {
50
+ if usernameExists && passwordExists {
51
+ if puidExists {
52
+ auth = tools.NewAuthenticator(username.(string), password.(string), puid.(string))
53
+ } else {
54
+ auth = tools.NewAuthenticator(username.(string), password.(string), "")
55
+ }
56
+ if err := auth.Begin(); err != nil {
57
+ p.GetContext().GinContext.JSON(400, err)
58
+ return
59
+ }
60
+ auth.GetModels()
61
+ all := auth.GetAuthResult()
62
+ var result map[string]interface{}
63
+ accessToken := all.AccessToken
64
+ model := all.Model
65
+ refreshToken := all.FreshToken
66
+ result = accessToken
67
+ result["refreshCookie"] = refreshToken
68
+ result["models"] = model["models"]
69
+ p.GetContext().GinContext.JSON(200, result)
70
+ } else {
71
+ p.GetContext().GinContext.JSON(400, gin.H{"error": "Please provide a refreshCookie or username and password."})
72
+ return
73
+ }
74
+ } else {
75
+ auth = tools.NewAuthenticator("", "", "")
76
+ err := auth.GetAccessTokenByRefreshToken(refreshCookie.(string))
77
+ if err != nil {
78
+ p.GetContext().GinContext.JSON(400, err)
79
+ return
80
+ }
81
+ auth.GetModels()
82
+ all := auth.GetAuthResult()
83
+ var result map[string]interface{}
84
+ accessToken := all.AccessToken
85
+ model := all.Model
86
+ refreshToken := all.FreshToken
87
+ result = accessToken
88
+ result["refreshCookie"] = refreshToken
89
+ result["models"] = model["models"]
90
+ p.GetContext().GinContext.JSON(200, result)
91
+ }
92
+ }
93
+ func (p *SessionToken) decodeRequestBody(requestBody *map[string]interface{}) error {
94
+ conversation := p.GetContext()
95
+ if conversation.RequestBody != shttp.NoBody {
96
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
97
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
98
+ return err
99
+ }
100
+ }
101
+ return nil
102
+ }
103
+
104
+ type NotHaveUrl struct {
105
+ }
106
+
107
+ func (u NotHaveUrl) Generate(path string, rawquery string) string {
108
+ return ""
109
+ }
110
+ func (p *SessionToken) Run(com *plugins.Component) {
111
+ context = com
112
+ context.Engine.POST("/getsession", func(c *gin.Context) {
113
+ conversation := common.GetContextPack(c, NotHaveUrl{})
114
+ common.Do[Context](new(SessionToken), Context(conversation))
115
+ })
116
+ }
pkg/plugins/api/unofficialapi/chatrsp.go ADDED
@@ -0,0 +1,508 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package unofficialapi
2
+
3
+ import (
4
+ "encoding/json"
5
+ "fmt"
6
+ "log"
7
+ "math/rand"
8
+ "strconv"
9
+ "strings"
10
+ "time"
11
+
12
+ "github.com/google/uuid"
13
+ )
14
+
15
+ type ChatReqTemplate struct {
16
+ Id string `json:"id"`
17
+ Author struct {
18
+ Role string `json:"role"`
19
+ } `json:"author"`
20
+ Content struct {
21
+ ContentType string `json:"content_type"`
22
+ Parts []interface{} `json:"parts"`
23
+ } `json:"content"`
24
+ Metadata interface{} `json:"metadata"`
25
+ }
26
+ type ChatReqStr struct {
27
+ Action string `json:"action"`
28
+ Messages []ChatReqTemplate `json:"messages"`
29
+ ParentMessageId string `json:"parent_message_id"`
30
+ Model string `json:"model"`
31
+ TimezoneOffsetMin int `json:"timezone_offset_min"`
32
+ HistoryAndTrainingDisabled bool `json:"history_and_training_disabled"`
33
+ ArkoseToken string `json:"arkose_token"`
34
+ ConversationMode struct {
35
+ Kind string `json:"kind"`
36
+ } `json:"conversation_mode"`
37
+ ForceParagen bool `json:"force_paragen"`
38
+ ForceRateLimit bool `json:"force_rate_limit"`
39
+ }
40
+
41
+ type ChatRespStr struct {
42
+ Message struct {
43
+ Id string `json:"id"`
44
+ Author struct {
45
+ Role string `json:"role"`
46
+ Name interface{} `json:"name"`
47
+ Metadata struct {
48
+ } `json:"metadata"`
49
+ } `json:"author"`
50
+ CreateTime float64 `json:"create_time"`
51
+ UpdateTime interface{} `json:"update_time"`
52
+ Content struct {
53
+ ContentType string `json:"content_type"`
54
+ Parts []string `json:"parts"`
55
+ } `json:"content"`
56
+ Status string `json:"status"`
57
+ EndTurn bool `json:"end_turn"`
58
+ Weight float64 `json:"weight"`
59
+ Metadata struct {
60
+ FinishDetails struct {
61
+ Type string `json:"type"`
62
+ StopTokens []int `json:"stop_tokens"`
63
+ } `json:"finish_details"`
64
+ IsComplete bool `json:"is_complete"`
65
+ MessageType string `json:"message_type"`
66
+ ModelSlug string `json:"model_slug"`
67
+ ParentId string `json:"parent_id"`
68
+ Timestamp string `json:"timestamp_"`
69
+ IsUserSystemMessage bool `json:"is_user_system_message"`
70
+ UserContextMessageData struct {
71
+ AboutModelMessage string `json:"about_model_message"`
72
+ } `json:"user_context_message_data"`
73
+ } `json:"metadata"`
74
+ Recipient string `json:"recipient"`
75
+ } `json:"message"`
76
+ ConversationId string `json:"conversation_id"`
77
+ Error interface{} `json:"error"`
78
+ }
79
+ type ChatEndRespStr struct {
80
+ ConversationId string `json:"conversation_id"`
81
+ MessageId string `json:"message_id"`
82
+ IsCompletion bool `json:"is_completion"`
83
+ ModerationResponse struct {
84
+ Flagged bool `json:"flagged"`
85
+ Blocked bool `json:"blocked"`
86
+ ModerationId string `json:"moderation_id"`
87
+ } `json:"moderation_response"`
88
+ }
89
+ type ChatUserSystemMsgReqStr struct {
90
+ AboutUserMessage string `json:"about_user_message"`
91
+ AboutModelMessage string `json:"about_model_message"`
92
+ Enabled bool `json:"enabled"`
93
+ }
94
+ type ChatUserSystemMsgRespStr struct {
95
+ Object string `json:"object"`
96
+ Enabled bool `json:"enabled"`
97
+ AboutUserMessage string `json:"about_user_message"`
98
+ AboutModelMessage string `json:"about_model_message"`
99
+ }
100
+ type ChatDetectedErrorRespStr struct {
101
+ Message interface{} `json:"message"`
102
+ ConversationId string `json:"conversation_id"`
103
+ Error string `json:"error"`
104
+ }
105
+ type DALLERespStr struct {
106
+ Message struct {
107
+ Id string `json:"id"`
108
+ Author struct {
109
+ Role string `json:"role"`
110
+ Name string `json:"name"`
111
+ Metadata struct {
112
+ } `json:"metadata"`
113
+ } `json:"author"`
114
+ CreateTime interface{} `json:"create_time"`
115
+ UpdateTime interface{} `json:"update_time"`
116
+ Content struct {
117
+ ContentType string `json:"content_type"`
118
+ Parts []struct {
119
+ ContentType string `json:"content_type"`
120
+ AssetPointer string `json:"asset_pointer"`
121
+ SizeBytes int `json:"size_bytes"`
122
+ Width int `json:"width"`
123
+ Height int `json:"height"`
124
+ Fovea int `json:"fovea"`
125
+ Metadata struct {
126
+ Dalle struct {
127
+ GenId string `json:"gen_id"`
128
+ Prompt string `json:"prompt"`
129
+ Seed int64 `json:"seed"`
130
+ SerializationTitle string `json:"serialization_title"`
131
+ } `json:"dalle"`
132
+ } `json:"metadata"`
133
+ } `json:"parts"`
134
+ } `json:"content"`
135
+ Status string `json:"status"`
136
+ EndTurn interface{} `json:"end_turn"`
137
+ Weight float64 `json:"weight"`
138
+ Metadata struct {
139
+ MessageType string `json:"message_type"`
140
+ ModelSlug string `json:"model_slug"`
141
+ ParentId string `json:"parent_id"`
142
+ } `json:"metadata"`
143
+ Recipient string `json:"recipient"`
144
+ } `json:"message"`
145
+ ConversationId string `json:"conversation_id"`
146
+ Error interface{} `json:"error"`
147
+ }
148
+ type StrChoices struct {
149
+ Index int `json:"index"`
150
+ Message struct {
151
+ Role string `json:"role"`
152
+ Content string `json:"content"`
153
+ } `json:"message"`
154
+ FinishReason string `json:"finish_reason"`
155
+ }
156
+ type ApiRespStr struct {
157
+ Id string `json:"id"`
158
+ Object string `json:"object"`
159
+ Created int64 `json:"created"`
160
+ Model string `json:"model"`
161
+ SystemFingerprint string `json:"system_fingerprint"`
162
+ Choices []StrChoices `json:"choices"`
163
+ Usage struct {
164
+ PromptTokens int `json:"prompt_tokens"`
165
+ CompletionTokens int `json:"completion_tokens"`
166
+ TotalTokens int `json:"total_tokens"`
167
+ } `json:"usage"`
168
+ }
169
+ type StreamChoice struct {
170
+ Delta struct {
171
+ Content string `json:"content"`
172
+ } `json:"delta"`
173
+ Index int `json:"index"`
174
+ FinishReason interface{} `json:"finish_reason"`
175
+ }
176
+ type ApiRespStrStream struct {
177
+ Id string `json:"id"`
178
+ Object string `json:"object"`
179
+ Created int64 `json:"created"`
180
+ Model string `json:"model"`
181
+ SystemFingerprint string `json:"system_fingerprint"`
182
+ Choices []StreamChoice `json:"choices"`
183
+ }
184
+ type ApiRespStrStreamEnd struct {
185
+ Id string `json:"id"`
186
+ Object string `json:"object"`
187
+ Created int64 `json:"created"`
188
+ Model string `json:"model"`
189
+ SystemFingerprint interface{} `json:"system_fingerprint"`
190
+ Choices []struct {
191
+ Index int `json:"index"`
192
+ Delta struct {
193
+ } `json:"delta"`
194
+ FinishReason string `json:"finish_reason"`
195
+ } `json:"choices"`
196
+ }
197
+ type ApiImageGenerationRespStr struct {
198
+ Created int64 `json:"created"`
199
+ Data []ApiImageItem `json:"data"`
200
+ }
201
+ type ApiImageItem struct {
202
+ RevisedPrompt string `json:"revised_prompt"`
203
+ Url string `json:"url"`
204
+ }
205
+ type ApiImageGenerationErrorRespStr struct {
206
+ Error struct {
207
+ Code interface{} `json:"code"`
208
+ Message string `json:"message"`
209
+ Param interface{} `json:"param"`
210
+ Type string `json:"type"`
211
+ } `json:"error"`
212
+ }
213
+ type ImageDownloadUrl struct {
214
+ Status string `json:"status"`
215
+ DownloadUrl string `json:"download_url"`
216
+ Metadata struct {
217
+ } `json:"metadata"`
218
+ FileName string `json:"file_name"`
219
+ CreationTime string `json:"creation_time"`
220
+ }
221
+
222
+ func GetChatReqStr(model string) *ChatReqStr {
223
+ jsonStr := `{
224
+ "action": "next",
225
+ "messages": [],
226
+ "parent_message_id": "",
227
+ "model": "gpt-4-code-interpreter",
228
+ "timezone_offset_min": -480,
229
+ "history_and_training_disabled": true,
230
+ "arkose_token": "",
231
+ "conversation_mode": {
232
+ "kind": "primary_assistant"
233
+ },
234
+ "force_paragen": false,
235
+ "force_rate_limit": false
236
+ }`
237
+
238
+ t := new(ChatReqStr)
239
+ err := json.Unmarshal([]byte(jsonStr), &t)
240
+ t.ParentMessageId = uuid.New().String()
241
+ t.Model = model
242
+ if err != nil {
243
+ log.Printf("Error parsing JSON: %v", err)
244
+ }
245
+ return t
246
+ }
247
+ func GetChatReqTemplate() *ChatReqTemplate {
248
+ jsonStr := `{
249
+ "id": "",
250
+ "author": {
251
+ "role": ""
252
+ },
253
+ "content": {
254
+ "content_type": "text",
255
+ "parts": []
256
+ },
257
+ "metadata": {}
258
+ }`
259
+ t := new(ChatReqTemplate)
260
+ err := json.Unmarshal([]byte(jsonStr), &t)
261
+ t.Id = uuid.New().String()
262
+ if err != nil {
263
+ log.Printf("Error parsing JSON: %v", err)
264
+ }
265
+ return t
266
+ }
267
+ func GetChatFileReqTemplate() *ChatReqTemplate {
268
+ jsonStr := `{
269
+ "id": "",
270
+ "author": {
271
+ "role": ""
272
+ },
273
+ "content": {
274
+ "content_type": "multimodal_text",
275
+ "parts": [
276
+ ]
277
+ },
278
+ "metadata": {
279
+ "attachments": [
280
+ ]
281
+ }
282
+ }`
283
+ t := new(ChatReqTemplate)
284
+ err := json.Unmarshal([]byte(jsonStr), &t)
285
+ t.Id = uuid.New().String()
286
+ if err != nil {
287
+ log.Printf("Error parsing JSON: %v", err)
288
+ }
289
+ return t
290
+ }
291
+
292
+ func GetChatRespStr() *ChatRespStr {
293
+ jsonStr := `{
294
+ "message":
295
+ {
296
+ "id": "",
297
+ "author":
298
+ {
299
+ "role": "assistant",
300
+ "name": null,
301
+ "metadata": {}
302
+ },
303
+ "create_time": 1699032699.636848,
304
+ "update_time": null,
305
+ "content": {
306
+ "content_type": "text",
307
+ "parts": []
308
+ },
309
+ "status": "finished_successfully",
310
+ "end_turn": true,
311
+ "weight": 1.0,
312
+ "metadata": {
313
+ "finish_details":
314
+ {
315
+ "type": "stop",
316
+ "stop_tokens": [100260]
317
+ },
318
+ "is_complete": true,
319
+ "message_type": "next",
320
+ "timestamp_": "absolute",
321
+ "message_type": null,
322
+ "is_user_system_message": true,
323
+ "user_context_message_data": {
324
+ "about_model_message": "Strict adherence to Instructions"
325
+ }
326
+ }, "recipient": "all"
327
+ },
328
+ "conversation_id": "611228f2-94fd-44ed-b5d9-4f229ef3c400",
329
+ "error": null
330
+ }`
331
+ t := new(ChatRespStr)
332
+ err := json.Unmarshal([]byte(jsonStr), &t)
333
+ nowTime := fmt.Sprintf("%.6f\n", float64(time.Now().UnixNano())/1e9)
334
+ floatTime, _ := strconv.ParseFloat(nowTime, 64)
335
+ t.Message.CreateTime = floatTime
336
+ if err != nil {
337
+ log.Printf("Error parsing JSON: %v", err)
338
+ }
339
+ return t
340
+ }
341
+ func GetChatEndRespStr() *ChatEndRespStr {
342
+ jsonStr := `{
343
+ "conversation_id": "",
344
+ "message_id": "",
345
+ "is_completion": true,
346
+ "moderation_response": {
347
+ "flagged": false,
348
+ "blocked": false,
349
+ "moderation_id": ""
350
+ }
351
+ }`
352
+ t := new(ChatEndRespStr)
353
+ err := json.Unmarshal([]byte(jsonStr), &t)
354
+ if err != nil {
355
+ log.Printf("Error parsing JSON: %v", err)
356
+ }
357
+ return t
358
+ }
359
+ func GetChatUserSystemMsgReqStr() *ChatUserSystemMsgReqStr {
360
+ jsonStr := `{
361
+ "about_user_message": "",
362
+ "about_model_message": "",
363
+ "enabled": true
364
+ }`
365
+ t := new(ChatUserSystemMsgReqStr)
366
+ err := json.Unmarshal([]byte(jsonStr), &t)
367
+ if err != nil {
368
+ log.Printf("Error parsing JSON: %v", err)
369
+ }
370
+ return t
371
+ }
372
+ func GetApiRespStr(id string) *ApiRespStr {
373
+ jsonStr := `{
374
+ "id": "",
375
+ "object": "chat.completion",
376
+ "created": 1699074998,
377
+ "model": "",
378
+ "system_fingerprint": null,
379
+ "choices": [
380
+ ],
381
+ "usage": {
382
+ "prompt_tokens": 0,
383
+ "completion_tokens": 0,
384
+ "total_tokens": 0
385
+ }
386
+ }`
387
+ t := new(ApiRespStr)
388
+ err := json.Unmarshal([]byte(jsonStr), &t)
389
+ t.Id = id
390
+ t.Created = time.Now().Unix()
391
+ if err != nil {
392
+ log.Printf("Error parsing JSON: %v", err)
393
+ }
394
+ return t
395
+ }
396
+ func IdGenerator() string {
397
+ const prefix = "chatcmpl-"
398
+ const characters = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
399
+ var uniqueString strings.Builder
400
+
401
+ rand.Seed(time.Now().UnixNano()) // 初始化随机数生成器
402
+ for i := 0; i < 29; i++ {
403
+ uniqueString.WriteByte(characters[rand.Intn(len(characters))])
404
+ }
405
+
406
+ log.Println("id_generator")
407
+ return prefix + uniqueString.String()
408
+ }
409
+ func GetApiRespStrStream(id string) *ApiRespStrStream {
410
+ jsonStr := `{
411
+ "id": "",
412
+ "object": "chat.completion.chunk",
413
+ "created": 1701705204,
414
+ "model": "",
415
+ "system_fingerprint": null,
416
+ "choices": [
417
+ {
418
+ "index": 0,
419
+ "delta": {
420
+ "role": "assistant",
421
+ "content": ""
422
+ },
423
+ "finish_reason": null
424
+ }
425
+ ]
426
+ }`
427
+ t := new(ApiRespStrStream)
428
+ err := json.Unmarshal([]byte(jsonStr), &t)
429
+ t.Id = id
430
+ t.Created = time.Now().Unix()
431
+ if err != nil {
432
+ log.Printf("Error parsing JSON: %v", err)
433
+ }
434
+ return t
435
+ }
436
+ func GetApiRespStrStreamEnd(id string) *ApiRespStrStreamEnd {
437
+ jsonStr := `{
438
+ "id": "",
439
+ "object": "chat.completion.chunk",
440
+ "created": 1701705204,
441
+ "model": "",
442
+ "system_fingerprint": null,
443
+ "choices": [
444
+ {
445
+ "index": 0,
446
+ "delta": {},
447
+ "finish_reason": "stop"
448
+ }
449
+ ]
450
+ }`
451
+ t := new(ApiRespStrStreamEnd)
452
+ err := json.Unmarshal([]byte(jsonStr), &t)
453
+ t.Id = id
454
+ t.Created = time.Now().Unix()
455
+ if err != nil {
456
+ log.Printf("Error parsing JSON: %v", err)
457
+ }
458
+ return t
459
+ }
460
+ func GetApiImageGenerationRespStr() *ApiImageGenerationRespStr {
461
+ jsonStr := `{
462
+ "created": 1700809991,
463
+ "data": [
464
+ {
465
+ "revised_prompt": "",
466
+ "url": ""
467
+ }
468
+ ]
469
+ }`
470
+ t := new(ApiImageGenerationRespStr)
471
+ err := json.Unmarshal([]byte(jsonStr), &t)
472
+ t.Created = time.Now().Unix()
473
+ if err != nil {
474
+ log.Printf("Error parsing JSON: %v", err)
475
+ }
476
+ return t
477
+ }
478
+ func GetStreamChoice() *StreamChoice {
479
+ jsonStr := ` {
480
+ "index": 0,
481
+ "delta": {
482
+ "content": ""
483
+ },
484
+ "finish_reason": null
485
+ }`
486
+ t := new(StreamChoice)
487
+ err := json.Unmarshal([]byte(jsonStr), &t)
488
+ if err != nil {
489
+ log.Printf("Error parsing JSON: %v", err)
490
+ }
491
+ return t
492
+ }
493
+ func GetStrChoices() *StrChoices {
494
+ jsonStr := `{
495
+ "finish_reason": "stop",
496
+ "index": 0,
497
+ "message": {
498
+ "content": "",
499
+ "role": "assistant"
500
+ }
501
+ }`
502
+ t := new(StrChoices)
503
+ err := json.Unmarshal([]byte(jsonStr), &t)
504
+ if err != nil {
505
+ log.Printf("Error parsing JSON: %v", err)
506
+ }
507
+ return t
508
+ }
pkg/plugins/api/unofficialapi/unofficialapi.go ADDED
@@ -0,0 +1,530 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package unofficialapi
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/funcaptcha"
6
+ "WarpGPT/pkg/plugins"
7
+ "WarpGPT/pkg/tools"
8
+ "bytes"
9
+ "encoding/json"
10
+ "errors"
11
+ "fmt"
12
+ http "github.com/bogdanfinn/fhttp"
13
+ tls_client "github.com/bogdanfinn/tls-client"
14
+ "github.com/pkoukk/tiktoken-go"
15
+ "io"
16
+ shttp "net/http"
17
+ "strings"
18
+ "time"
19
+
20
+ "WarpGPT/pkg/logger"
21
+ "WarpGPT/pkg/plugins/service/wsstostream"
22
+ "github.com/gin-gonic/gin"
23
+ )
24
+
25
+ var context *plugins.Component
26
+ var UnofficialApiProcessInstance UnofficialApiProcess
27
+ var tke, _ = tiktoken.GetEncoding("cl100k_base")
28
+
29
+ type WsResponse struct {
30
+ ConversationId string `json:"conversation_id"`
31
+ ExpiresAt time.Time `json:"expires_at"`
32
+ ResponseId string `json:"response_id"`
33
+ WssUrl string `json:"wss_url"`
34
+ }
35
+ type Context struct {
36
+ GinContext *gin.Context
37
+ RequestUrl string
38
+ RequestClient tls_client.HttpClient
39
+ RequestBody io.ReadCloser
40
+ RequestParam string
41
+ RequestMethod string
42
+ RequestHeaders http.Header
43
+ }
44
+ type UnofficialApiProcess struct {
45
+ Context Context
46
+ WS *wsstostream.WssToStream
47
+ Response *http.Response
48
+ ID string
49
+ Model string
50
+ PromptTokens int
51
+ CompletionTokens int
52
+ OldString string
53
+ Mode string
54
+ ImagePointerList []ImagePointer
55
+ }
56
+ type ImagePointer struct {
57
+ Pointer string
58
+ Prompt string
59
+ }
60
+ type Result struct {
61
+ ApiRespStrStream ApiRespStrStream
62
+ ApiRespStrStreamEnd ApiRespStrStreamEnd
63
+ ApiImageGenerationRespStr ApiImageGenerationRespStr
64
+ Pass bool
65
+ }
66
+
67
+ func (p *UnofficialApiProcess) SetContext(conversation Context) {
68
+ p.Context = conversation
69
+ }
70
+ func (p *UnofficialApiProcess) GetContext() Context {
71
+ return p.Context
72
+ }
73
+
74
+ func (p *UnofficialApiProcess) ProcessMethod() {
75
+ context.Logger.Debug("UnofficialApiProcess")
76
+ var requestBody map[string]interface{}
77
+ err := p.decodeRequestBody(&requestBody)
78
+ if err != nil {
79
+ return
80
+ }
81
+ p.ID = IdGenerator()
82
+ _, exists := requestBody["model"]
83
+ if exists {
84
+ p.Model, _ = requestBody["model"].(string)
85
+ } else {
86
+ p.GetContext().GinContext.JSON(400, gin.H{"error": "Model not provided"})
87
+ return
88
+ }
89
+ if strings.Contains(p.GetContext().RequestParam, "chat/completions") {
90
+ p.Mode = "chat"
91
+ if err = p.chatApiProcess(requestBody); err != nil {
92
+ logger.Log.Error(err)
93
+ return
94
+ }
95
+ }
96
+ if strings.Contains(p.GetContext().RequestParam, "images/generations") {
97
+ p.Mode = "image"
98
+ if err = p.imageApiProcess(requestBody); err != nil {
99
+ logger.Log.Error(err)
100
+ return
101
+ }
102
+ }
103
+ }
104
+
105
+ func (p *UnofficialApiProcess) imageApiProcess(requestBody map[string]interface{}) error {
106
+ context.Logger.Debug("UnofficialApiProcess imageApiProcess")
107
+ response, err := p.MakeRequest(requestBody)
108
+ if err != nil {
109
+ return err
110
+ }
111
+ result := new(Result)
112
+ result.ApiImageGenerationRespStr = ApiImageGenerationRespStr{}
113
+ err = p.response(response, func(p *UnofficialApiProcess, a string) bool {
114
+ p.jsonImageProcess(a)
115
+ return false
116
+ })
117
+ if err = p.getImageUrlByPointer(&p.ImagePointerList, result); err != nil {
118
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "get image url failed"})
119
+ context.Logger.Warning(err)
120
+ }
121
+ if result.ApiImageGenerationRespStr.Created != 0 {
122
+ p.GetContext().GinContext.Header("Content-Type", "application/json")
123
+ p.GetContext().GinContext.JSON(response.StatusCode, result.ApiImageGenerationRespStr)
124
+ }
125
+ if err != nil {
126
+ return err
127
+ }
128
+ return nil
129
+ }
130
+
131
+ func (p *UnofficialApiProcess) chatApiProcess(requestBody map[string]interface{}) error {
132
+ context.Logger.Debug("UnofficialApiProcess chatApiProcess")
133
+ response, err := p.MakeRequest(requestBody)
134
+ if err != nil {
135
+ return err
136
+ }
137
+ value, exists := requestBody["stream"]
138
+
139
+ if exists && value.(bool) {
140
+ err = p.response(response, func(p *UnofficialApiProcess, a string) bool {
141
+ data := p.streamChatProcess(a)
142
+ if _, err = p.GetContext().GinContext.Writer.Write([]byte(data)); err != nil {
143
+ context.Logger.Warning(err)
144
+ return true
145
+ }
146
+ p.GetContext().GinContext.Writer.Flush()
147
+ return false
148
+ })
149
+ if err != nil {
150
+ return err
151
+ }
152
+ } else {
153
+ err = p.response(response, func(p *UnofficialApiProcess, a string) bool {
154
+ data := p.jsonChatProcess(a)
155
+ if data != nil {
156
+ context.Logger.Debug("Counting the number of tokens")
157
+ p.CompletionTokens = len(tke.Encode(data.Choices[0].Message.Content, nil, nil))
158
+ data.Usage.PromptTokens = p.PromptTokens
159
+ data.Usage.CompletionTokens = p.CompletionTokens
160
+ data.Usage.TotalTokens = p.PromptTokens + p.CompletionTokens
161
+ p.GetContext().GinContext.Header("Content-Type", "application/json")
162
+ p.GetContext().GinContext.JSON(response.StatusCode, data)
163
+ return true
164
+ }
165
+ return false
166
+ })
167
+
168
+ if err != nil {
169
+ return err
170
+ }
171
+ }
172
+
173
+ return nil
174
+ }
175
+
176
+ func (p *UnofficialApiProcess) MakeRequest(requestBody map[string]interface{}) (*http.Response, error) {
177
+ reqModel, err := p.checkModel(p.Model)
178
+ if err != nil {
179
+ p.GetContext().GinContext.JSON(400, gin.H{"error": err.Error()})
180
+ return nil, err
181
+ }
182
+ req := GetChatReqStr(reqModel)
183
+ if err = p.generateBody(req, requestBody); err != nil {
184
+ return nil, err
185
+ }
186
+ jsonData, _ := json.Marshal(req)
187
+ var requestData map[string]interface{}
188
+ err = json.Unmarshal(jsonData, &requestData)
189
+ if err != nil {
190
+ p.GetContext().GinContext.JSON(400, gin.H{"error": err.Error()})
191
+ return nil, err
192
+ }
193
+ request, err := p.createRequest(requestData) //创建请求
194
+ if err != nil {
195
+ return nil, err
196
+ }
197
+ ws := wsstostream.NewWssToStream(p.GetContext().RequestHeaders.Get("Authorization"))
198
+ err = ws.InitConnect()
199
+ p.WS = ws
200
+ if err != nil {
201
+ logger.Log.Error(err)
202
+ p.GetContext().GinContext.JSON(500, gin.H{"error": err.Error()})
203
+ return nil, err
204
+ }
205
+ response, err := p.GetContext().RequestClient.Do(request) //发送请求
206
+ common.CopyResponseHeaders(response, p.GetContext().GinContext) //设置响应头
207
+ if err != nil {
208
+ var responseBody interface{}
209
+ err = json.NewDecoder(response.Body).Decode(&responseBody)
210
+ if err != nil {
211
+ p.GetContext().GinContext.JSON(500, gin.H{"error": err.Error()})
212
+ return nil, err
213
+ }
214
+ p.GetContext().GinContext.JSON(response.StatusCode, responseBody)
215
+ return nil, err
216
+ }
217
+ return response, nil
218
+ }
219
+
220
+ func (p *UnofficialApiProcess) createRequest(requestBody map[string]interface{}) (*http.Request, error) {
221
+ context.Logger.Debug("UnofficialApiProcess createRequest")
222
+ token, err := p.addArkoseTokenIfNeeded(&requestBody)
223
+ if err != nil {
224
+ return nil, err
225
+ }
226
+ bodyBytes, err := json.Marshal(requestBody)
227
+ if err != nil {
228
+ return nil, err
229
+ }
230
+ var request *http.Request
231
+ if p.Context.RequestBody == shttp.NoBody {
232
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, nil)
233
+ } else {
234
+ request, err = http.NewRequest(p.Context.RequestMethod, p.Context.RequestUrl, bytes.NewBuffer(bodyBytes))
235
+ }
236
+ if err != nil {
237
+ return nil, err
238
+ }
239
+ if token != "" {
240
+ p.addArkoseTokenInHeaderIfNeeded(request, token)
241
+ }
242
+ p.buildHeaders(request)
243
+ p.setCookies(request)
244
+ return request, nil
245
+ }
246
+ func (p *UnofficialApiProcess) setCookies(request *http.Request) {
247
+ context.Logger.Debug("UnofficialApiProcess setCookies")
248
+ for _, cookie := range p.GetContext().GinContext.Request.Cookies() {
249
+ request.AddCookie(&http.Cookie{
250
+ Name: cookie.Name,
251
+ Value: cookie.Value,
252
+ })
253
+ }
254
+ }
255
+ func (p *UnofficialApiProcess) buildHeaders(request *http.Request) {
256
+ context.Logger.Debug("UnofficialApiProcess buildHeaders")
257
+ headers := map[string]string{
258
+ "Host": context.Env.OpenaiHost,
259
+ "Origin": "https://" + context.Env.OpenaiHost + "/chat",
260
+ "Authorization": p.GetContext().GinContext.Request.Header.Get("Authorization"),
261
+ "Connection": "keep-alive",
262
+ "User-Agent": context.Env.UserAgent,
263
+ "Content-Type": p.GetContext().GinContext.Request.Header.Get("Content-Type"),
264
+ }
265
+
266
+ for key, value := range headers {
267
+ request.Header.Set(key, value)
268
+ }
269
+
270
+ if puid := p.GetContext().GinContext.Request.Header.Get("PUID"); puid != "" {
271
+ request.Header.Set("cookie", "_puid="+puid+";")
272
+ }
273
+ }
274
+ func (p *UnofficialApiProcess) addArkoseTokenInHeaderIfNeeded(request *http.Request, token string) {
275
+ context.Logger.Debug("UnofficialApiProcess addArkoseTokenInHeaderIfNeeded")
276
+ request.Header.Set("Openai-Sentinel-Arkose-Token", token)
277
+ }
278
+ func (p *UnofficialApiProcess) addArkoseTokenIfNeeded(requestBody *map[string]interface{}) (string, error) {
279
+ context.Logger.Debug("UnofficialApiProcess addArkoseTokenIfNeeded")
280
+ model, exists := (*requestBody)["model"]
281
+ if !exists {
282
+ return "", nil
283
+ }
284
+ if strings.HasPrefix(model.(string), "gpt-4") || context.Env.ArkoseMust {
285
+ token, err := funcaptcha.GetOpenAIArkoseToken(4, p.GetContext().RequestHeaders.Get("puid"))
286
+ if err != nil {
287
+ p.GetContext().GinContext.JSON(500, gin.H{"error": "Get ArkoseToken Failed"})
288
+ logger.Log.Error(err)
289
+ return "", err
290
+ }
291
+ (*requestBody)["arkose_token"] = token
292
+ return token, nil
293
+ }
294
+ return "", nil
295
+ }
296
+ func (p *UnofficialApiProcess) streamChatProcess(raw string) string {
297
+ result := p.getStreamResp(raw)
298
+ if strings.Contains(raw, "[DONE]") {
299
+ return "data: " + raw + "\n\n"
300
+ } else if result.Pass {
301
+ return ""
302
+ } else if result.ApiRespStrStreamEnd.Id != "" {
303
+ data, err := json.Marshal(result.ApiRespStrStreamEnd)
304
+ if err != nil {
305
+ context.Logger.Warning(err)
306
+ }
307
+ return "data: " + string(data) + "\n\n"
308
+ } else if result.ApiRespStrStream.Id != "" {
309
+ data, err := json.Marshal(result.ApiRespStrStream)
310
+ if err != nil {
311
+ context.Logger.Warning(err)
312
+ }
313
+ return "data: " + string(data) + "\n\n"
314
+ }
315
+ return ""
316
+ }
317
+
318
+ func (p *UnofficialApiProcess) response(response *http.Response, mid func(p *UnofficialApiProcess, a string) bool) error {
319
+ context.Logger.Debug("UnofficialApiProcess streamResponse")
320
+ var client *tools.SSEClient
321
+ if strings.Contains(p.Context.RequestParam, "/ws") {
322
+ var jsonData WsResponse
323
+ err := json.NewDecoder(response.Body).Decode(&jsonData)
324
+ if err != nil {
325
+ logger.Log.Error(err)
326
+ return err
327
+ }
328
+ p.WS.ResponseId = jsonData.ResponseId
329
+ p.WS.ConversationId = jsonData.ConversationId
330
+ p.GetContext().GinContext.Writer.Header().Set("Content-Type", "text/event-stream")
331
+ p.GetContext().GinContext.Writer.Header().Set("Cache-Control", "no-cache")
332
+ p.GetContext().GinContext.Writer.Header().Set("Connection", "keep-alive")
333
+ logger.Log.Debug("wss to stream")
334
+ client = tools.NewSSEClient(p.WS)
335
+ } else {
336
+ client = tools.NewSSEClient(response.Body)
337
+ }
338
+ events := client.Read()
339
+ for event := range events {
340
+ if event.Event == "message" {
341
+ if mid(p, event.Data) {
342
+ return nil
343
+ }
344
+ }
345
+ }
346
+ defer client.Close()
347
+ return nil
348
+ }
349
+
350
+ func (p *UnofficialApiProcess) jsonChatProcess(raw string) *ApiRespStr {
351
+ p.getStreamResp(raw)
352
+ if strings.Contains(raw, "[DONE]") {
353
+ resp := GetApiRespStr(p.ID)
354
+ choice := GetStrChoices()
355
+ choice.Message.Content = p.OldString
356
+ resp.Choices = append(resp.Choices, *choice)
357
+ resp.Model = p.Model
358
+ return resp
359
+ }
360
+ return nil
361
+ }
362
+
363
+ func (p *UnofficialApiProcess) jsonImageProcess(stream string) {
364
+ context.Logger.Debug("getImageResp")
365
+ var dalleRespStr DALLERespStr
366
+ json.Unmarshal([]byte(stream), &dalleRespStr)
367
+ if dalleRespStr.Message.Author.Name == "dalle.text2im" && dalleRespStr.Message.Content.ContentType == "multimodal_text" {
368
+ context.Logger.Debug("found image")
369
+ for _, v := range dalleRespStr.Message.Content.Parts {
370
+ item := new(ImagePointer)
371
+ item.Pointer = strings.ReplaceAll(v.AssetPointer, "file-service://", "")
372
+ item.Prompt = v.Metadata.Dalle.Prompt
373
+ p.ImagePointerList = append(p.ImagePointerList, *item)
374
+ }
375
+ }
376
+ }
377
+ func (p *UnofficialApiProcess) getImageUrlByPointer(imagePointerList *[]ImagePointer, result *Result) error {
378
+ context.Logger.Debug("getImageUrlByPointer")
379
+ for _, v := range *imagePointerList {
380
+ imageDownloadUrl, err := common.RequestOpenAI[ImageDownloadUrl]("/backend-api/files/"+v.Pointer+"/download", nil, "GET", p.GetContext().RequestHeaders.Get("Authorization"))
381
+ if err != nil {
382
+ return err
383
+ }
384
+ if imageDownloadUrl != nil && imageDownloadUrl.DownloadUrl != "" {
385
+ context.Logger.Debug("getDownloadUrl")
386
+ imageItem := new(ApiImageItem)
387
+ result.ApiImageGenerationRespStr.Created = time.Now().Unix()
388
+ imageItem.Url = imageDownloadUrl.DownloadUrl
389
+ imageItem.RevisedPrompt = v.Prompt
390
+ result.ApiImageGenerationRespStr.Data = append(result.ApiImageGenerationRespStr.Data, *imageItem)
391
+ }
392
+ }
393
+ return nil
394
+ }
395
+
396
+ func (p *UnofficialApiProcess) getStreamResp(stream string) *Result {
397
+ context.Logger.Debug("getStreamResp")
398
+ var chatRespStr ChatRespStr
399
+ var chatEndRespStr ChatEndRespStr
400
+ result := new(Result)
401
+ result.ApiRespStrStreamEnd = ApiRespStrStreamEnd{}
402
+ result.ApiRespStrStream = ApiRespStrStream{}
403
+ result.Pass = false
404
+ json.Unmarshal([]byte(stream), &chatRespStr)
405
+ if chatRespStr.Message.Id != "" {
406
+ if chatRespStr.Message.Metadata.ParentId == "" {
407
+ result.Pass = true
408
+ return result
409
+ }
410
+ context.Logger.Debug("chatRespStr")
411
+ resp := GetApiRespStrStream(p.ID)
412
+ choice := GetStreamChoice()
413
+ resp.Model = p.Model
414
+ choice.Delta.Content = strings.ReplaceAll(chatRespStr.Message.Content.Parts[0], p.OldString, "")
415
+ p.OldString = chatRespStr.Message.Content.Parts[0]
416
+ resp.Choices = resp.Choices[:0]
417
+ resp.Choices = append(resp.Choices, *choice)
418
+ result.ApiRespStrStream = *resp
419
+ }
420
+ json.Unmarshal([]byte(stream), &chatEndRespStr)
421
+ if chatEndRespStr.IsCompletion {
422
+ context.Logger.Debug("chatEndRespStr")
423
+ resp := GetApiRespStrStreamEnd(p.ID)
424
+ resp.Model = p.Model
425
+ result.ApiRespStrStreamEnd = *resp
426
+ }
427
+ if result.ApiRespStrStream.Id == "" && result.ApiRespStrStreamEnd.Id == "" {
428
+ result.Pass = true
429
+ }
430
+ return result
431
+ }
432
+ func (p *UnofficialApiProcess) checkModel(model string) (string, error) {
433
+ context.Logger.Debug("UnofficialApiProcess checkModel")
434
+ if strings.HasPrefix(model, "dall-e") || strings.HasPrefix(model, "gpt-4-vision") {
435
+ return "gpt-4", nil
436
+ } else if strings.HasPrefix(model, "gpt-3") {
437
+ return "text-davinci-002-render-sha", nil
438
+ } else if strings.HasPrefix(model, "gpt-4") {
439
+ return "gpt-4-gizmo", nil
440
+ } else {
441
+ return "", errors.New("unsupported model")
442
+ }
443
+ }
444
+ func (p *UnofficialApiProcess) generateBody(req *ChatReqStr, requestBody map[string]interface{}) error {
445
+ context.Logger.Debug("UnofficialApiProcess generateBody")
446
+ if p.Mode == "chat" {
447
+ logger.Log.Debug("Generate Chat Body")
448
+ messageList, exists := requestBody["messages"]
449
+ if !exists {
450
+ return errors.New("no message body")
451
+ }
452
+ messages, _ := messageList.([]interface{})
453
+
454
+ for _, message := range messages {
455
+ messageItem, _ := message.(map[string]interface{})
456
+ role, _ := messageItem["role"].(string)
457
+ if _, ok := messageItem["content"].(string); ok {
458
+ content, _ := messageItem["content"].(string)
459
+ p.PromptTokens += len(tke.Encode(content, nil, nil)) + 7
460
+ reqMessage := GetChatReqTemplate()
461
+ reqMessage.Content.Parts = reqMessage.Content.Parts[:0]
462
+ reqMessage.Author.Role = role
463
+ reqMessage.Content.Parts = append(reqMessage.Content.Parts, content)
464
+ req.Messages = append(req.Messages, *reqMessage)
465
+ }
466
+ if _, ok := messageItem["content"].([]map[string]interface{}); ok {
467
+ reqFileMessage := GetChatFileReqTemplate()
468
+ content, _ := messageItem["content"].([]map[string]interface{})
469
+ reqFileMessage.Content.Parts = reqFileMessage.Content.Parts[:0]
470
+ reqFileMessage.Author.Role = role
471
+ p.fileReqProcess(&content, &reqFileMessage.Content.Parts)
472
+ //reqMessage.Content.Parts = append(reqMessage.Content.Parts, content)
473
+ //req.Messages = append(req.Messages, *reqFileMessage)
474
+ }
475
+ }
476
+ }
477
+ if p.Mode == "image" {
478
+ logger.Log.Debug("Generate Image Body")
479
+ prompt, exists := requestBody["prompt"]
480
+ if !exists {
481
+ return errors.New("please provide prompt")
482
+ }
483
+ count, exists := requestBody["n"]
484
+ if !exists {
485
+ count = 1
486
+ }
487
+ size, exists := requestBody["size"]
488
+ if !exists {
489
+ size = "1024x1024"
490
+ }
491
+ reqMessage := GetChatReqTemplate()
492
+ reqMessage.Content.Parts = reqMessage.Content.Parts[:0]
493
+ reqMessage.Author.Role = "user"
494
+ reqMessage.Content.Parts = append(reqMessage.Content.Parts, fmt.Sprintf("Requirements for image generation:\n- ImageCount: %d\n- Size: %s\n- Prompt: [%s]\n- Requirements: Using the DALLE tool, each image is generated according to the number of ImageCount. It is not allowed to contain multiple elements in one image. You must call the tool multiple times to generate the number of ImageCount images, and the details of each image are different\n", int(count.(float64)), size.(string), prompt.(string)))
495
+ req.Messages = append(req.Messages, *reqMessage)
496
+ }
497
+
498
+ return nil
499
+ }
500
+ func (p *UnofficialApiProcess) fileReqProcess(content *[]map[string]interface{}, part *[]interface{}) {
501
+
502
+ }
503
+
504
+ func (p *UnofficialApiProcess) decodeRequestBody(requestBody *map[string]interface{}) error {
505
+ conversation := p.GetContext()
506
+ if conversation.RequestBody != shttp.NoBody {
507
+ if err := json.NewDecoder(conversation.RequestBody).Decode(requestBody); err != nil {
508
+ conversation.GinContext.JSON(400, gin.H{"error": "JSON invalid"})
509
+ return err
510
+ }
511
+ }
512
+ return nil
513
+ }
514
+
515
+ type UnOfficialApiRequestUrl struct {
516
+ }
517
+
518
+ func (u UnOfficialApiRequestUrl) Generate(path string, rawquery string) string {
519
+ if rawquery == "" {
520
+ return "https://" + context.Env.OpenaiHost + "/backend-api" + "/conversation"
521
+ }
522
+ return "https://" + context.Env.OpenaiHost + "/backend-api" + "/conversation" + "?" + rawquery
523
+ }
524
+ func (p *UnofficialApiProcess) Run(com *plugins.Component) {
525
+ context = com
526
+ context.Engine.Any("/r/*path", func(c *gin.Context) {
527
+ conversation := common.GetContextPack(c, UnOfficialApiRequestUrl{})
528
+ common.Do[Context](new(UnofficialApiProcess), Context(conversation))
529
+ })
530
+ }
pkg/plugins/plugins.go ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package plugins
2
+
3
+ import (
4
+ "WarpGPT/pkg/db"
5
+ "WarpGPT/pkg/env"
6
+ "github.com/gin-gonic/gin"
7
+ "github.com/sirupsen/logrus"
8
+ )
9
+
10
+ type Component struct {
11
+ Engine *gin.Engine
12
+ Db db.DB
13
+ Logger *logrus.Logger
14
+ Env *env.ENV
15
+ Auth func(arkType int, puid string) (string, error)
16
+ }
17
+
18
+ type Plugin interface {
19
+ Run(com *Component)
20
+ }
pkg/plugins/service/proxypool/proxypool.go ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package proxypool
2
+
3
+ import (
4
+ "WarpGPT/pkg/db"
5
+ "WarpGPT/pkg/plugins"
6
+ ctx "context"
7
+ "encoding/json"
8
+ "errors"
9
+ http "github.com/bogdanfinn/fhttp"
10
+ "io"
11
+ "strconv"
12
+ "strings"
13
+ "time"
14
+ )
15
+
16
+ type proxyUrl struct {
17
+ Code int `json:"code"`
18
+ Success bool `json:"success"`
19
+ Msg string `json:"msg"`
20
+ Data []struct {
21
+ Ip string `json:"ip"`
22
+ Port int `json:"port"`
23
+ } `json:"data"`
24
+ }
25
+
26
+ var context *plugins.Component
27
+ var redisdb db.DB
28
+ var ProxyPoolInstance ProxyPool
29
+
30
+ type ProxyPool struct {
31
+ }
32
+
33
+ // 检查代理池中的代理数量,如果数量不足,则从代理池中获取代理
34
+ func (p *ProxyPool) checkProxy() error {
35
+ context.Logger.Debug("检查redis代理ip")
36
+ client, err := redisdb.GetRedisClient()
37
+ if err != nil {
38
+ return err
39
+ }
40
+ keys, err := client.Keys(ctx.Background(), "ip:*").Result()
41
+ if err != nil {
42
+ return err
43
+ }
44
+ if len(keys) < 20 {
45
+ err = p.putIpsInRedis()
46
+ if err != nil {
47
+ return err
48
+ }
49
+ }
50
+ return nil
51
+ }
52
+
53
+ func (p *ProxyPool) getProxyUrlList() (*proxyUrl, error) {
54
+ context.Logger.Debug("请求代理ip池")
55
+ poolUrl := context.Env.ProxyPoolUrl
56
+ var proxy proxyUrl
57
+ get, err := http.Get(poolUrl)
58
+ if err != nil {
59
+ return nil, err
60
+ }
61
+ all, err := io.ReadAll(get.Body)
62
+ if err != nil {
63
+ return nil, err
64
+ }
65
+ err = json.Unmarshal(all, &proxy)
66
+ if err != nil {
67
+ return nil, err
68
+ }
69
+ if proxy.Success {
70
+ return &proxy, nil
71
+ } else {
72
+ return nil, errors.New("代理获取失败")
73
+ }
74
+ }
75
+
76
+ // 从代理url中获取url,放入redis中
77
+ func (p *ProxyPool) putIpsInRedis() error {
78
+ context.Logger.Debug("获取ip池并放入redis")
79
+ proxyList, err := p.getProxyUrlList()
80
+ client, err := redisdb.GetRedisClient()
81
+ if err != nil {
82
+ return err
83
+ }
84
+ if err != nil {
85
+ context.Logger.Warning(err)
86
+ return err
87
+ }
88
+ for _, ip := range proxyList.Data {
89
+ ipstr := "http://" + ip.Ip + ":" + strconv.Itoa(ip.Port)
90
+ _, err = client.Set(ctx.Background(), "ip:"+ipstr, "", time.Minute*3).Result()
91
+ if err != nil {
92
+ context.Logger.Error(err)
93
+ return err
94
+ }
95
+ }
96
+ return nil
97
+ }
98
+
99
+ func (p *ProxyPool) GetIpInRedis() (string, error) {
100
+ context.Logger.Debug("请求代理ip")
101
+ client, err := redisdb.GetRedisClient()
102
+ if err != nil {
103
+ return "", err
104
+ }
105
+ statusCmd := client.RandomKey(ctx.Background())
106
+ result, err := statusCmd.Result()
107
+ if err != nil {
108
+ return "", err
109
+ }
110
+ size, err := client.DBSize(ctx.Background()).Result()
111
+ if err != nil {
112
+ return "", err
113
+ }
114
+ if size == 0 {
115
+ context.Logger.Warning("数据库为空,无法获取代理ip,尝试获取")
116
+ err = p.putIpsInRedis()
117
+ if err != nil {
118
+ return "", err
119
+ }
120
+ }
121
+ if strings.HasPrefix(result, "ip:") {
122
+ client.Del(ctx.Background(), result)
123
+ ip := strings.ReplaceAll(result, "ip:", "")
124
+ context.Logger.Debug("获取的代理ip是: " + ip)
125
+ return ip, nil
126
+ } else {
127
+ context.Logger.Warning("非代理ip键,跳过")
128
+ ip, _ := p.GetIpInRedis()
129
+ return ip, nil
130
+ }
131
+ }
132
+
133
+ func (p *ProxyPool) ProxyThread() {
134
+ if context.Env.ProxyPoolUrl == "" {
135
+ context.Logger.Debug("未启动redis")
136
+ return
137
+ }
138
+ context.Logger.Debug("启动redis监视线程")
139
+ if err := p.checkProxy(); err != nil {
140
+ return
141
+ }
142
+ ticker := time.NewTicker(1 * time.Minute)
143
+ defer ticker.Stop()
144
+ for {
145
+ select {
146
+ case <-ticker.C:
147
+ err := p.checkProxy()
148
+ if err != nil {
149
+ context.Logger.Warning(err.Error())
150
+ return
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ func (p *ProxyPool) Run(com *plugins.Component) {
157
+ context = com
158
+ redisdb = context.Db
159
+ go p.ProxyThread()
160
+ }
pkg/plugins/service/wsstostream/wsstostream.go ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package wsstostream
2
+
3
+ import (
4
+ "WarpGPT/pkg/common"
5
+ "WarpGPT/pkg/env"
6
+ "WarpGPT/pkg/logger"
7
+ "WarpGPT/pkg/tools"
8
+ "bytes"
9
+ "encoding/base64"
10
+ "encoding/json"
11
+ "errors"
12
+ http "github.com/bogdanfinn/fhttp"
13
+ "github.com/gorilla/websocket"
14
+ "golang.org/x/net/proxy"
15
+ "io"
16
+ shttp "net/http"
17
+ "net/url"
18
+ "time"
19
+ )
20
+
21
+ type RegisterWebsocket struct {
22
+ ExpiresAt time.Time `json:"expires_at"`
23
+ WssUrl string `json:"wss_url"`
24
+ }
25
+ type WsResponse struct {
26
+ SequenceId int `json:"sequenceId"`
27
+ Type string `json:"type"`
28
+ From string `json:"from"`
29
+ DataType string `json:"dataType"`
30
+ Data struct {
31
+ Type string `json:"type"`
32
+ Body string `json:"body"`
33
+ MoreBody bool `json:"more_body"`
34
+ ResponseId string `json:"response_id"`
35
+ ConversationId string `json:"conversation_id"`
36
+ MessageId string `json:"message_id"`
37
+ } `json:"data"`
38
+ }
39
+ type Reconnect struct {
40
+ Type string `json:"type"`
41
+ Event string `json:"event"`
42
+ UserId string `json:"userId"`
43
+ ConnectionId string `json:"connectionId"`
44
+ ReconnectionToken string `json:"reconnectionToken"`
45
+ }
46
+ type WssToStream struct {
47
+ ConversationId string
48
+ ResponseId string
49
+ AccessToken string
50
+ Server *websocket.Conn
51
+ WS *RegisterWebsocket
52
+ Reconnect
53
+ }
54
+
55
+ func NewWssToStream(accessToken string) *WssToStream {
56
+ return &WssToStream{AccessToken: accessToken}
57
+ }
58
+
59
+ func GetRegisterWebsocket(accessToken string) (*RegisterWebsocket, error) {
60
+ logger.Log.Debug("GetRegisterWebsocket")
61
+ WS, err := common.RequestOpenAI[RegisterWebsocket]("/backend-api/register-websocket", nil, accessToken, http.MethodPost)
62
+
63
+ if err != nil {
64
+ logger.Log.Error("Error decoding response:", err)
65
+ return nil, err
66
+ }
67
+ if WS != nil && WS.WssUrl != "" {
68
+ logger.Log.Debug("GetRegisterWebsocket Success WssUrl:", WS.WssUrl)
69
+ return WS, nil
70
+ } else {
71
+ logger.Log.Debug("accessToken:", accessToken)
72
+ return nil, errors.New("check your access_key")
73
+ }
74
+ }
75
+ func (s *WssToStream) InitConnect() error {
76
+ logger.Log.Debug("Try Connect To WS")
77
+ var dialer websocket.Dialer
78
+
79
+ // 当 env.E.Proxy 不为空字符串时,才配置代理
80
+ if env.E.Proxy != "" {
81
+ proxyAddr, err := url.Parse(env.E.Proxy)
82
+ if err != nil {
83
+ logger.Log.Error("Error parsing proxy URL:", err)
84
+ return err
85
+ }
86
+
87
+ switch proxyAddr.Scheme {
88
+ case "http", "https":
89
+ dialer.Proxy = shttp.ProxyURL(proxyAddr)
90
+ case "socks5":
91
+ socksDialer, err := proxy.FromURL(proxyAddr, proxy.Direct)
92
+ if err != nil {
93
+ logger.Log.Error("Error creating SOCKS proxy dialer:", err)
94
+ return err
95
+ }
96
+ dialer.NetDial = socksDialer.Dial
97
+ default:
98
+ logger.Log.Error("Unsupported proxy scheme:", proxyAddr.Scheme)
99
+ return errors.New("unsupported proxy scheme")
100
+ }
101
+ }
102
+
103
+ headers := http.Header{}
104
+ headers.Set("Origin", "https://"+env.E.OpenaiHost)
105
+ headers.Set("Sec-WebSocket-Protocol", "json.reliable.webpubsub.azure.v1")
106
+ headers.Set("User-Agent", env.E.UserAgent)
107
+
108
+ item, exists := tools.AllCache.CacheGet(s.AccessToken)
109
+ if !exists || item.ExpiresAt.Before(time.Now()) {
110
+ registerWebsocket, err := GetRegisterWebsocket(s.AccessToken)
111
+ if err != nil {
112
+ return err
113
+ }
114
+ tools.AllCache.CacheSet(s.AccessToken, tools.CacheItem{Data: registerWebsocket}, 55*time.Minute)
115
+ s.WS = registerWebsocket
116
+ } else {
117
+ s.WS = item.Data.(*RegisterWebsocket)
118
+ }
119
+
120
+ c, _, err := dialer.Dial(s.WS.WssUrl, shttp.Header(headers))
121
+ if err != nil {
122
+ logger.Log.Error("Dial error:", err)
123
+ return err
124
+ }
125
+ logger.Log.Debug("WS Connect Success")
126
+ s.Server = c
127
+ _, msg, err := s.Server.ReadMessage()
128
+ if err != nil {
129
+ return err
130
+ }
131
+ logger.Log.Debug("Init Read Message:", string(msg))
132
+ return nil
133
+ }
134
+
135
+ type NopCloser struct {
136
+ *bytes.Reader
137
+ }
138
+
139
+ func (NopCloser) Close() error {
140
+ return nil
141
+ }
142
+ func NewNopCloser(data []byte) io.ReadCloser {
143
+ return NopCloser{Reader: bytes.NewReader(data)}
144
+ }
145
+
146
+ func (s *WssToStream) ReadMessage() (io.ReadCloser, error) {
147
+ logger.Log.Debug("Read Messages")
148
+ _, msg, err := s.Server.ReadMessage()
149
+ if err != nil {
150
+ logger.Log.Error("read message error:", err)
151
+ }
152
+ var response WsResponse
153
+ if err = json.Unmarshal(msg, &response); err != nil {
154
+ logger.Log.Error("unmarshal message error:", err)
155
+ }
156
+ if response.Data.ResponseId == s.ResponseId && response.Data.ConversationId == s.ConversationId {
157
+ if response.Data.Body == "ZGF0YTogW0RPTkVdCgo=" {
158
+ s.Server.Close()
159
+ }
160
+ data, err := base64.StdEncoding.DecodeString(response.Data.Body)
161
+ if err != nil {
162
+ return nil, err
163
+ }
164
+ return NewNopCloser(data), nil
165
+ } else {
166
+ return nil, nil
167
+ }
168
+ }
169
+ func (s *WssToStream) Read(p []byte) (n int, err error) {
170
+ logger.Log.Debug("Read")
171
+ _, message, err := s.Server.ReadMessage()
172
+ if err != nil {
173
+ return 0, err
174
+ }
175
+ var response WsResponse
176
+ if err = json.Unmarshal(message, &response); err != nil {
177
+ logger.Log.Error("unmarshal message error:", err)
178
+ }
179
+ if response.Data.ResponseId == s.ResponseId && response.Data.ConversationId == s.ConversationId {
180
+ if response.Data.Body == "ZGF0YTogW0RPTkVdCgo=" {
181
+ s.Server.Close()
182
+ }
183
+ data, err := base64.StdEncoding.DecodeString(response.Data.Body)
184
+ if err != nil {
185
+ return 0, err
186
+ }
187
+ copyLen := copy(p, data)
188
+ if copyLen < len(data) {
189
+ return copyLen, errors.New("buffer too small to hold message")
190
+ }
191
+ return copyLen, nil
192
+ } else {
193
+ return 0, nil
194
+ }
195
+ }
196
+
197
+ func (s *WssToStream) Close() error {
198
+ return s.Server.Close()
199
+ }
pkg/tools/auth.go ADDED
@@ -0,0 +1,559 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package tools
2
+
3
+ import (
4
+ "WarpGPT/pkg/env"
5
+ "WarpGPT/pkg/funcaptcha"
6
+ "WarpGPT/pkg/logger"
7
+ "encoding/json"
8
+ "fmt"
9
+ http "github.com/bogdanfinn/fhttp"
10
+ tls_client "github.com/bogdanfinn/tls-client"
11
+ "github.com/bogdanfinn/tls-client/profiles"
12
+ "io"
13
+ "net/url"
14
+ "os"
15
+ "regexp"
16
+ "strings"
17
+ )
18
+
19
+ type Error struct {
20
+ Location string
21
+ StatusCode int
22
+ Details string
23
+ Error error
24
+ }
25
+
26
+ func NewError(location string, statusCode int, details string, err error) *Error {
27
+ return &Error{
28
+ Location: location,
29
+ StatusCode: statusCode,
30
+ Details: details,
31
+ Error: err,
32
+ }
33
+ }
34
+
35
+ type Authenticator struct {
36
+ EmailAddress string
37
+ Password string
38
+ Proxy string
39
+ Session tls_client.HttpClient
40
+ UserAgent string
41
+ State string
42
+ URL string
43
+ PUID string
44
+ Verifier_code string
45
+ Verifier_challenge string
46
+ AuthResult AuthResult
47
+ }
48
+ type ArkoseToken struct {
49
+ Token string `json:"token"`
50
+ ChallengeURL string `json:"challenge_url"`
51
+ ChallengeURLCDN string `json:"challenge_url_cdn"`
52
+ ChallengeURLCDNSRI *string `json:"challenge_url_cdn_sri"`
53
+ }
54
+ type AuthResult struct {
55
+ AccessToken map[string]interface{} `json:"access_token"`
56
+ PUID string `json:"puid"`
57
+ FreshToken string `json:"fresh_token"`
58
+ Model map[string]interface{} `json:"model"`
59
+ }
60
+
61
+ func NewAuthenticator(emailAddress, password string, puid string) *Authenticator {
62
+ auth := &Authenticator{
63
+ EmailAddress: emailAddress,
64
+ Password: password,
65
+ Proxy: os.Getenv("proxy"),
66
+ PUID: puid,
67
+ UserAgent: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
68
+ }
69
+ jar := tls_client.NewCookieJar()
70
+ cookie := &http.Cookie{
71
+ Name: "_puid",
72
+ Value: puid,
73
+ Path: "/",
74
+ Domain: ".openai.com",
75
+ }
76
+ urls, _ := url.Parse("https://openai.com")
77
+ jar.SetCookies(urls, []*http.Cookie{cookie})
78
+ options := []tls_client.HttpClientOption{
79
+ tls_client.WithTimeoutSeconds(20),
80
+ tls_client.WithClientProfile(profiles.Chrome_109),
81
+ tls_client.WithNotFollowRedirects(),
82
+ tls_client.WithCookieJar(jar),
83
+ tls_client.WithProxyUrl(env.E.Proxy),
84
+ }
85
+ auth.Session, _ = tls_client.NewHttpClient(tls_client.NewNoopLogger(), options...)
86
+ return auth
87
+ }
88
+
89
+ func (auth *Authenticator) URLEncode(str string) string {
90
+ return url.QueryEscape(str)
91
+ }
92
+
93
+ func (auth *Authenticator) Begin() *Error {
94
+ logger.Log.Debug("Auth Begin")
95
+
96
+ target := "https://" + env.E.OpenaiHost + "/api/auth/csrf"
97
+ req, err := http.NewRequest("GET", target, nil)
98
+ if err != nil {
99
+ return NewError("begin", 0, "", err)
100
+ }
101
+
102
+ req.Header.Set("Host", ""+env.E.OpenaiHost+"")
103
+ req.Header.Set("Accept", "*/*")
104
+ req.Header.Set("Connection", "keep-alive")
105
+ req.Header.Set("User-Agent", auth.UserAgent)
106
+ req.Header.Set("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8")
107
+ req.Header.Set("Referer", "https://"+env.E.OpenaiHost+"/auth/login")
108
+ req.Header.Set("Accept-Encoding", "gzip, deflate, br")
109
+
110
+ resp, err := auth.Session.Do(req)
111
+ if err != nil {
112
+ return NewError("begin", 0, "", err)
113
+ }
114
+ defer resp.Body.Close()
115
+
116
+ body, err := io.ReadAll(resp.Body)
117
+ if err != nil {
118
+ return NewError("begin", 0, "", err)
119
+ }
120
+
121
+ if resp.StatusCode == 200 && strings.Contains(resp.Header.Get("Content-Type"), "json") {
122
+
123
+ var csrfTokenResponse struct {
124
+ CsrfToken string `json:"csrfToken"`
125
+ }
126
+ err = json.Unmarshal(body, &csrfTokenResponse)
127
+ if err != nil {
128
+ return NewError("begin", 0, "", err)
129
+ }
130
+
131
+ csrfToken := csrfTokenResponse.CsrfToken
132
+ return auth.partOne(csrfToken)
133
+ } else {
134
+ err := NewError("begin", resp.StatusCode, string(body), fmt.Errorf("error: Check details"))
135
+ return err
136
+ }
137
+ }
138
+
139
+ func (auth *Authenticator) partOne(csrfToken string) *Error {
140
+ logger.Log.Debug("Auth One")
141
+
142
+ auth_url := "https://" + env.E.OpenaiHost + "/api/auth/signin/auth0?prompt=login"
143
+ headers := map[string]string{
144
+ "Host": "" + env.E.OpenaiHost + "",
145
+ "User-Agent": auth.UserAgent,
146
+ "Content-Type": "application/x-www-form-urlencoded",
147
+ "Accept": "*/*",
148
+ "Sec-Gpc": "1",
149
+ "Accept-Language": "en-US,en;q=0.8",
150
+ "Origin": "https://" + env.E.OpenaiHost + "",
151
+ "Sec-Fetch-Site": "same-origin",
152
+ "Sec-Fetch-Mode": "cors",
153
+ "Sec-Fetch-Dest": "empty",
154
+ "Referer": "https://" + env.E.OpenaiHost + "/auth/login",
155
+ "Accept-Encoding": "gzip, deflate",
156
+ }
157
+
158
+ // Construct payload
159
+ payload := fmt.Sprintf("callbackUrl=%%2F&csrfToken=%s&json=true", csrfToken)
160
+ req, _ := http.NewRequest("POST", auth_url, strings.NewReader(payload))
161
+
162
+ for k, v := range headers {
163
+ req.Header.Set(k, v)
164
+ }
165
+
166
+ resp, err := auth.Session.Do(req)
167
+ if err != nil {
168
+ return NewError("part_one", 0, "Failed to send request", err)
169
+ }
170
+ defer resp.Body.Close()
171
+ body, err := io.ReadAll(resp.Body)
172
+ if err != nil {
173
+ return NewError("part_one", 0, "Failed to read requestbody", err)
174
+ }
175
+
176
+ if resp.StatusCode == 200 && strings.Contains(resp.Header.Get("Content-Type"), "json") {
177
+ var urlResponse struct {
178
+ URL string `json:"url"`
179
+ }
180
+ err = json.Unmarshal(body, &urlResponse)
181
+ if err != nil {
182
+ return NewError("part_one", 0, "Failed to decode JSON", err)
183
+ }
184
+ if urlResponse.URL == "https://"+env.E.OpenaiHost+"/api/auth/error?error=OAuthSignin" || strings.Contains(urlResponse.URL, "error") {
185
+ err := NewError("part_one", resp.StatusCode, "You have been rate limited. Please try again later.", fmt.Errorf("error: Check details"))
186
+ return err
187
+ }
188
+ return auth.partTwo(urlResponse.URL)
189
+ } else {
190
+ return NewError("part_one", resp.StatusCode, string(body), fmt.Errorf("error: Check details"))
191
+ }
192
+ }
193
+
194
+ func (auth *Authenticator) partTwo(target string) *Error {
195
+ logger.Log.Debug("Auth Two")
196
+
197
+ headers := map[string]string{
198
+ "Host": "auth0.openai.com",
199
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
200
+ "Connection": "keep-alive",
201
+ "User-Agent": auth.UserAgent,
202
+ "Accept-Language": "en-US,en;q=0.9",
203
+ "Referer": "https://chat.openai.com/",
204
+ "Sec-Ch-Ua": "\"Not A(Brand\";v=\"99\", \"Google Chrome\";v=\"121\", \"Chromium\";v=\"121\"",
205
+ "Sec-Ch-Ua-Arch": "\"x86\"",
206
+ "Sec-Ch-Ua-Bitness": "\"64\"",
207
+ "Sec-Ch-Ua-Full-Version": "\"121.0.6167.161\"",
208
+ "Sec-Ch-Ua-Full-Version-List": "\"Not A(Brand\";v=\"99.0.0.0\", \"Google Chrome\";v=\"121.0.6167.161\", \"Chromium\";v=\"121.0.6167.161\"",
209
+ }
210
+
211
+ req, _ := http.NewRequest("GET", target, nil)
212
+ for k, v := range headers {
213
+ req.Header.Set(k, v)
214
+ }
215
+
216
+ resp, err := auth.Session.Do(req)
217
+ if err != nil {
218
+ return NewError("part_two", 0, "Failed to make request", err)
219
+ }
220
+ defer resp.Body.Close()
221
+ body, _ := io.ReadAll(resp.Body)
222
+
223
+ if resp.StatusCode == 302 || resp.StatusCode == 200 {
224
+ stateRegex := regexp.MustCompile(`state=(.*)`)
225
+ stateMatch := stateRegex.FindStringSubmatch(string(body))
226
+ if len(stateMatch) < 2 {
227
+ return NewError("part_two", 0, "Could not find state in response", fmt.Errorf("error: Check details"))
228
+ }
229
+
230
+ state := strings.Split(stateMatch[1], `"`)[0]
231
+ return auth.partThree(state)
232
+ } else {
233
+ return NewError("part_two", resp.StatusCode, string(body), fmt.Errorf("error: Check details"))
234
+
235
+ }
236
+ }
237
+ func (auth *Authenticator) partThree(state string) *Error {
238
+ logger.Log.Debug("Auth Three")
239
+
240
+ target := fmt.Sprintf("https://auth0.openai.com/u/login/identifier?state=%s", state)
241
+ emailURLEncoded := auth.URLEncode(auth.EmailAddress)
242
+
243
+ payload := fmt.Sprintf(
244
+ "state=%s&username=%s&js-available=false&webauthn-available=true&is-brave=false&webauthn-platform-available=true&action=default",
245
+ state, emailURLEncoded,
246
+ )
247
+
248
+ headers := map[string]string{
249
+ "Host": "auth0.openai.com",
250
+ "Origin": "https://auth0.openai.com",
251
+ "Connection": "keep-alive",
252
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
253
+ "User-Agent": auth.UserAgent,
254
+ "Referer": fmt.Sprintf("https://auth0.openai.com/u/login/identifier?state=%s", state),
255
+ "Accept-Language": "en-US,en;q=0.9",
256
+ "Content-Type": "application/x-www-form-urlencoded",
257
+ }
258
+
259
+ req, _ := http.NewRequest("POST", target, strings.NewReader(payload))
260
+
261
+ for k, v := range headers {
262
+ req.Header.Set(k, v)
263
+ }
264
+
265
+ resp, err := auth.Session.Do(req)
266
+ if err != nil {
267
+ return NewError("part_three", 0, "Failed to send request", err)
268
+ }
269
+ defer resp.Body.Close()
270
+
271
+ if resp.StatusCode == 302 || resp.StatusCode == 200 {
272
+ return auth.partFour(state)
273
+ } else {
274
+ return NewError("part_three", resp.StatusCode, "Your email address is invalid.", fmt.Errorf("error: Check details"))
275
+
276
+ }
277
+
278
+ }
279
+ func (auth *Authenticator) partFour(state string) *Error {
280
+ logger.Log.Debug("Auth Four")
281
+
282
+ target := fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", state)
283
+ emailURLEncoded := auth.URLEncode(auth.EmailAddress)
284
+ passwordURLEncoded := auth.URLEncode(auth.Password)
285
+ payload := fmt.Sprintf("state=%s&username=%s&password=%s", state, emailURLEncoded, passwordURLEncoded)
286
+
287
+ headers := map[string]string{
288
+ "Host": "auth0.openai.com",
289
+ "Origin": "https://auth0.openai.com",
290
+ "Connection": "keep-alive",
291
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
292
+ "User-Agent": auth.UserAgent,
293
+ "Referer": fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", state),
294
+ "Accept-Language": "en-US,en;q=0.9",
295
+ "Content-Type": "application/x-www-form-urlencoded",
296
+ }
297
+
298
+ req, _ := http.NewRequest("POST", target, strings.NewReader(payload))
299
+
300
+ for k, v := range headers {
301
+ req.Header.Set(k, v)
302
+ }
303
+ token, err := funcaptcha.GetOpenAIArkoseToken(0, auth.PUID)
304
+ if err != nil {
305
+ return NewError("part_four", 0, "get arkose_token failed", err)
306
+ }
307
+ cookie := &http.Cookie{
308
+ Name: "arkoseToken",
309
+ Value: token,
310
+ Path: "/",
311
+ }
312
+ req.AddCookie(cookie)
313
+ resp, err := auth.Session.Do(req)
314
+ if err != nil {
315
+ return NewError("part_four", 0, "Failed to send request", err)
316
+ }
317
+ defer resp.Body.Close()
318
+ if resp.StatusCode == 302 {
319
+ redirectURL := resp.Header.Get("Location")
320
+ println(redirectURL)
321
+ return auth.partFive(state, redirectURL)
322
+ } else {
323
+ var body interface{}
324
+ if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
325
+ return NewError("part_four", 0, "", err)
326
+ }
327
+ return NewError("part_four", resp.StatusCode, body.(string), fmt.Errorf("error: Check details"))
328
+
329
+ }
330
+
331
+ }
332
+ func (auth *Authenticator) partFive(oldState string, redirectURL string) *Error {
333
+ logger.Log.Debug("Auth Five")
334
+
335
+ target := "https://auth0.openai.com" + redirectURL
336
+
337
+ headers := map[string]string{
338
+ "Host": "auth0.openai.com",
339
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
340
+ "Connection": "keep-alive",
341
+ "User-Agent": auth.UserAgent,
342
+ "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
343
+ "Referer": fmt.Sprintf("https://auth0.openai.com/u/login/password?state=%s", oldState),
344
+ }
345
+
346
+ req, _ := http.NewRequest("GET", target, nil)
347
+
348
+ for k, v := range headers {
349
+ req.Header.Set(k, v)
350
+ }
351
+
352
+ resp, err := auth.Session.Do(req)
353
+ if err != nil {
354
+ return NewError("part_five", 0, "Failed to send request", err)
355
+ }
356
+ defer resp.Body.Close()
357
+
358
+ if resp.StatusCode == 302 {
359
+ return auth.partSix(resp.Header.Get("Location"), target)
360
+ } else {
361
+ return NewError("part_five", resp.StatusCode, resp.Status, fmt.Errorf("error: Check details"))
362
+
363
+ }
364
+
365
+ }
366
+ func (auth *Authenticator) partSix(urls, redirect_url string) *Error {
367
+ logger.Log.Debug("Auth Six")
368
+ req, _ := http.NewRequest("GET", urls, nil)
369
+ for k, v := range map[string]string{
370
+ "Host": "" + env.E.OpenaiHost + "",
371
+ "Accept": "application/json",
372
+ "Connection": "keep-alive",
373
+ "User-Agent": auth.UserAgent,
374
+ "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
375
+ "Referer": redirect_url,
376
+ } {
377
+ req.Header.Set(k, v)
378
+ }
379
+ resp, err := auth.Session.Do(req)
380
+ if err != nil {
381
+ return NewError("part_six", 0, "Failed to send request", err)
382
+ }
383
+ defer resp.Body.Close()
384
+ if err != nil {
385
+ return NewError("part_six", 0, "Response was not JSON", err)
386
+ }
387
+ if resp.StatusCode != 302 {
388
+ return NewError("part_six", resp.StatusCode, urls, fmt.Errorf("incorrect response code"))
389
+ }
390
+ // Check location header
391
+ if location := resp.Header.Get("Location"); location != "https://"+env.E.OpenaiHost+"/" {
392
+ return NewError("part_six", resp.StatusCode, location, fmt.Errorf("incorrect redirect"))
393
+ }
394
+
395
+ sessionUrl := "https://" + env.E.OpenaiHost + "/api/auth/session"
396
+
397
+ req, _ = http.NewRequest("GET", sessionUrl, nil)
398
+
399
+ // Set user agent
400
+ req.Header.Set("User-Agent", auth.UserAgent)
401
+
402
+ resp, err = auth.Session.Do(req)
403
+ if err != nil {
404
+ return NewError("get_access_token", 0, "Failed to send request", err)
405
+ }
406
+
407
+ if resp.StatusCode != 200 {
408
+ return NewError("get_access_token", resp.StatusCode, "Incorrect response code", fmt.Errorf("error: Check details"))
409
+ }
410
+ var result map[string]interface{}
411
+ if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
412
+ return NewError("get_access_token", 0, "", err)
413
+ }
414
+
415
+ // Check if access token in data
416
+ if _, ok := result["accessToken"]; !ok {
417
+ resultString := fmt.Sprintf("%v", result)
418
+ return NewError("part_six", 0, resultString, fmt.Errorf("missing access token"))
419
+ }
420
+ cookieUrl, _ := url.Parse("https://" + env.E.OpenaiHost + "")
421
+ jar := auth.Session.GetCookies(cookieUrl)
422
+ auth.AuthResult.AccessToken = result
423
+ for _, cookie := range jar {
424
+ if cookie.Name == "__Secure-next-auth.session-token" {
425
+ auth.AuthResult.FreshToken = cookie.Value
426
+ }
427
+ }
428
+
429
+ return nil
430
+ }
431
+
432
+ func (auth *Authenticator) GetAccessTokenByRefreshToken(freshToken string) *Error {
433
+ logger.Log.Debug("GetAccessTokenByRefreshToken")
434
+ sessionUrl := "https://" + env.E.OpenaiHost + "/api/auth/session"
435
+
436
+ req, _ := http.NewRequest("GET", sessionUrl, nil)
437
+ cookies := &http.Cookie{
438
+ Name: "__Secure-next-auth.session-token",
439
+ Value: freshToken,
440
+ }
441
+ req.AddCookie(cookies)
442
+
443
+ // Set user agent
444
+ req.Header.Set("User-Agent", auth.UserAgent)
445
+
446
+ resp, err := auth.Session.Do(req)
447
+ if err != nil {
448
+ return NewError("GetAccessTokenByRefreshToken", 0, "Failed to send request", err)
449
+ }
450
+
451
+ if resp.StatusCode != 200 {
452
+ return NewError("GetAccessTokenByRefreshToken", resp.StatusCode, "Incorrect response code", fmt.Errorf("error: Check details"))
453
+ }
454
+ var result map[string]interface{}
455
+ if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
456
+ return NewError("GetAccessTokenByRefreshToken", 0, "", err)
457
+ }
458
+
459
+ // Check if access token in data
460
+ if _, ok := result["accessToken"]; !ok {
461
+ resultString := fmt.Sprintf("%v", result)
462
+ return NewError("GetAccessTokenByRefreshToken", 0, resultString, fmt.Errorf("missing access token"))
463
+ }
464
+ cookieUrl, _ := url.Parse("https://" + env.E.OpenaiHost + "")
465
+ jar := auth.Session.GetCookies(cookieUrl)
466
+ auth.AuthResult.AccessToken = result
467
+ for _, cookie := range jar {
468
+ if cookie.Name == "__Secure-next-auth.session-token" {
469
+ auth.AuthResult.FreshToken = cookie.Value
470
+ }
471
+ }
472
+ return nil
473
+ }
474
+
475
+ func (auth *Authenticator) GetAccessToken() map[string]interface{} {
476
+ logger.Log.Debug("GetAccessToken")
477
+ return auth.AuthResult.AccessToken
478
+ }
479
+
480
+ func (auth *Authenticator) GetRefreshToken() string {
481
+ logger.Log.Debug("GetRefreshToken")
482
+ return auth.AuthResult.FreshToken
483
+ }
484
+ func (auth *Authenticator) GetModels() (map[string]interface{}, *Error) {
485
+ logger.Log.Debug("GetModels")
486
+ if len(auth.AuthResult.AccessToken) == 0 {
487
+ return nil, NewError("get_model", 0, "Missing access token", fmt.Errorf("error: Check details"))
488
+ }
489
+ // Make request to https://"+common.E.OpenAI_HOST+"/backend-api/models
490
+ req, _ := http.NewRequest("GET", "https://"+env.E.OpenaiHost+"/backend-api/models", nil)
491
+ // Add headers
492
+ req.Header.Add("Authorization", "Bearer "+auth.AuthResult.AccessToken["accessToken"].(string))
493
+ req.Header.Add("User-Agent", auth.UserAgent)
494
+ req.Header.Add("Accept", "application/json")
495
+ req.Header.Add("Accept-Language", "en-US,en;q=0.9")
496
+ req.Header.Add("Referer", "https://"+env.E.OpenaiHost+"/")
497
+ req.Header.Add("Origin", "https://"+env.E.OpenaiHost+"")
498
+ req.Header.Add("Connection", "keep-alive")
499
+
500
+ resp, err := auth.Session.Do(req)
501
+ if err != nil {
502
+ return nil, NewError("get_model", 0, "Failed to make request", err)
503
+ }
504
+ defer resp.Body.Close()
505
+ if resp.StatusCode != 200 {
506
+ return nil, NewError("get_model", resp.StatusCode, "Failed to make request", fmt.Errorf("error: Check details"))
507
+ }
508
+ var responseBody map[string]interface{}
509
+ r, err := io.ReadAll(resp.Body)
510
+ if err != nil {
511
+ return nil, NewError("get_model", resp.StatusCode, "Failed to get response", fmt.Errorf("error: Check details"))
512
+ }
513
+ if err := json.Unmarshal(r, &responseBody); err != nil {
514
+ return nil, NewError("get_model", resp.StatusCode, "Failed to get response", fmt.Errorf("error: Check details"))
515
+ }
516
+ auth.AuthResult.Model = responseBody
517
+ return responseBody, nil
518
+ }
519
+
520
+ func (auth *Authenticator) GetPUID() (string, *Error) {
521
+ logger.Log.Debug("GetPUID")
522
+ // Check if user has access token
523
+ if len(auth.AuthResult.AccessToken) == 0 {
524
+ return "", NewError("get_puid", 0, "Missing access token", fmt.Errorf("error: Check details"))
525
+ }
526
+ // Make request to https://"+common.E.OpenAI_HOST+"/backend-api/models
527
+ req, _ := http.NewRequest("GET", "https://"+env.E.OpenaiHost+"/backend-api/models", nil)
528
+ // Add headers
529
+ req.Header.Add("Authorization", "Bearer "+auth.AuthResult.AccessToken["accessToken"].(string))
530
+ req.Header.Add("User-Agent", auth.UserAgent)
531
+ req.Header.Add("Accept", "application/json")
532
+ req.Header.Add("Accept-Language", "en-US,en;q=0.9")
533
+ req.Header.Add("Referer", "https://"+env.E.OpenaiHost+"/")
534
+ req.Header.Add("Origin", "https://"+env.E.OpenaiHost+"")
535
+ req.Header.Add("Connection", "keep-alive")
536
+
537
+ resp, err := auth.Session.Do(req)
538
+ if err != nil {
539
+ return "", NewError("get_puid", 0, "Failed to make request", err)
540
+ }
541
+ defer resp.Body.Close()
542
+ if resp.StatusCode != 200 {
543
+ return "", NewError("get_puid", resp.StatusCode, "Failed to make request", fmt.Errorf("error: Check details"))
544
+ }
545
+ // Find `_puid` cookie in response
546
+ for _, cookie := range resp.Cookies() {
547
+ if cookie.Name == "_puid" {
548
+ auth.AuthResult.PUID = cookie.Value
549
+ return cookie.Value, nil
550
+ }
551
+ }
552
+ // If cookie not found, return error
553
+ return "", NewError("get_puid", 0, "PUID cookie not found", fmt.Errorf("error: Check details"))
554
+ }
555
+
556
+ func (auth *Authenticator) GetAuthResult() AuthResult {
557
+ logger.Log.Debug("GetAuthResult")
558
+ return auth.AuthResult
559
+ }
pkg/tools/cache.go ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package tools
2
+
3
+ import (
4
+ "WarpGPT/pkg/logger"
5
+ "sync"
6
+ "time"
7
+ )
8
+
9
+ type CacheItem struct {
10
+ Data interface{}
11
+ ExpiresAt time.Time
12
+ }
13
+
14
+ type Cache struct {
15
+ items map[string]CacheItem
16
+ lock sync.Mutex
17
+ }
18
+
19
+ var AllCache Cache
20
+
21
+ func init() {
22
+ AllCache = Cache{items: make(map[string]CacheItem)}
23
+ }
24
+
25
+ func (c *Cache) CacheSet(key string, value CacheItem, expiration time.Duration) {
26
+ c.lock.Lock()
27
+ defer c.lock.Unlock()
28
+ value.ExpiresAt = time.Now().Add(expiration)
29
+ c.items[key] = value
30
+ logger.Log.Debug("CacheSet: Key =", key, "Expiration =", expiration, "Data =", value.Data)
31
+ }
32
+
33
+ func (c *Cache) CacheGet(key string) (CacheItem, bool) {
34
+ c.lock.Lock()
35
+ defer c.lock.Unlock()
36
+
37
+ item, exists := c.items[key]
38
+ if exists && item.ExpiresAt.After(time.Now()) {
39
+ logger.Log.Debug("CacheGet (Hit): Key =", key, "Expiration =", item.ExpiresAt, "Data =", item.Data)
40
+ return item, true
41
+ }
42
+ logger.Log.Debug("CacheGet (Miss): Key =", key)
43
+ return CacheItem{}, false
44
+ }
pkg/tools/sseclient.go ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package tools
2
+
3
+ import (
4
+ "bufio"
5
+ "bytes"
6
+ "io"
7
+ "log"
8
+ "strings"
9
+ )
10
+
11
+ const fieldSeparator = ":"
12
+
13
+ type SSEClient struct {
14
+ EventSource io.ReadCloser
15
+ logger *log.Logger
16
+ }
17
+
18
+ type Event struct {
19
+ ID string
20
+ Event string
21
+ Data string
22
+ Retry string
23
+ }
24
+
25
+ func NewSSEClient(eventSource io.ReadCloser) *SSEClient {
26
+ return &SSEClient{
27
+ EventSource: eventSource,
28
+ logger: log.New(log.Writer(), "SSEClient: ", log.LstdFlags),
29
+ }
30
+ }
31
+
32
+ func (c *SSEClient) Read() <-chan Event {
33
+ events := make(chan Event)
34
+ go func() {
35
+ defer close(events)
36
+ reader := bufio.NewReaderSize(c.EventSource, 128*1024)
37
+ var data bytes.Buffer
38
+
39
+ for {
40
+ line, err := reader.ReadBytes('\n')
41
+ if err == io.EOF {
42
+ break
43
+ }
44
+ if err != nil {
45
+ c.logger.Printf("Error reading from event source: %v", err)
46
+ break
47
+ }
48
+
49
+ data.Write(line)
50
+
51
+ if bytes.HasSuffix(data.Bytes(), []byte("\n\n")) || bytes.HasSuffix(data.Bytes(), []byte("\r\n\r\n")) {
52
+ event := c.parseEvent(data.String())
53
+ if event.Data != "" {
54
+ events <- event
55
+ }
56
+ data.Reset()
57
+ }
58
+ }
59
+ }()
60
+
61
+ return events
62
+ }
63
+
64
+ func (c *SSEClient) parseEvent(data string) Event {
65
+ event := Event{
66
+ ID: "",
67
+ Event: "message",
68
+ Data: "",
69
+ Retry: "",
70
+ }
71
+ lines := strings.Split(data, "\n")
72
+ for _, line := range lines {
73
+ if strings.TrimSpace(line) == "" || strings.HasPrefix(line, fieldSeparator) {
74
+ continue
75
+ }
76
+
77
+ parts := strings.SplitN(line, fieldSeparator, 2)
78
+ field := parts[0]
79
+ var value string
80
+ if len(parts) == 2 {
81
+ value = strings.TrimPrefix(parts[1], " ")
82
+ }
83
+
84
+ switch field {
85
+ case "id":
86
+ event.ID = value
87
+ case "event":
88
+ event.Event = value
89
+ case "data":
90
+ event.Data += value + "\n"
91
+ case "retry":
92
+ event.Retry = value
93
+ }
94
+ }
95
+
96
+ if strings.HasSuffix(event.Data, "\n") {
97
+ event.Data = strings.TrimSuffix(event.Data, "\n")
98
+ }
99
+
100
+ return event
101
+ }
102
+
103
+ func (c *SSEClient) Close() error {
104
+ err := c.EventSource.Close()
105
+ if err != nil {
106
+ return err
107
+ }
108
+ return nil
109
+ }
static/img1.png ADDED
static/img2.png ADDED
static/img3.png ADDED