Skip to content

Commit 54398e2

Browse files
authored
Merge pull request #244 from lanqian528/dev
Dev to Main
2 parents d65d62c + a1c01bf commit 54398e2

File tree

12 files changed

+3364
-21
lines changed

12 files changed

+3364
-21
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
🌟 无需账号即可使用免费、无限的 `GPT-3.5`
66

7-
💥 支持 AccessToken 使用账号,支持 `O1-Preview/mini``GPT-4``GPT-4o/mini` `GPTs`
7+
💥 支持 AccessToken 使用账号,支持 `O3-mini/high``O1/mini/Pro``GPT-4/4o/mini``GPTs`
88

99
🔍 回复格式与真实 API 完全一致,适配几乎所有客户端
1010

@@ -43,25 +43,28 @@
4343
> - [x] Tokens 管理,支持上传、清除
4444
> - [x] 定时使用 `RefreshToken` 刷新 `AccessToken` / 每次启动将会全部非强制刷新一次,每4天晚上3点全部强制刷新一次。
4545
> - [x] 支持文件下载,需要开启历史记录
46-
> - [x] 支持 `O1-Preview/mini` 模型推理过程输出
46+
> - [x] 支持 `O3-mini/high``O1/mini/Pro` 等模型推理过程输出
4747
4848
### 官网镜像 功能
4949
> - [x] 支持官网原生镜像
5050
> - [x] 后台账号池随机抽取,`Seed` 设置随机账号
5151
> - [x] 输入 `RefreshToken``AccessToken` 直接登录使用
52-
> - [x] 支持 O1-Preview/miniGPT-4、GPT-4o/mini
52+
> - [x] 支持 `O3-mini/high``O1/mini/Pro``GPT-4/4o/mini`
5353
> - [x] 敏感信息接口禁用、部分设置接口禁用
5454
> - [x] /login 登录页面,注销后自动跳转到登录页面
5555
> - [x] /?token=xxx 直接登录, xxx 为 `RefreshToken``AccessToken``SeedToken` (随机种子)
56+
> - [x] 支持不同 SeedToken 会话隔离
57+
> - [x] 支持 `GPTs` 商店
58+
> - [x] 支持 `DeepReaserch``Canvas` 等官网独有功能
59+
> - [x] 支持切换各国语言
5660
5761

5862
> TODO
59-
> - [ ] 镜像支持 `GPTs`
6063
> - [ ] 暂无,欢迎提 `issue`
6164
6265
## 逆向API
6366

64-
完全 `OpenAI` 格式的 API ,支持传入 `AccessToken``RefreshToken`,可用 GPT-4, GPT-4o, GPTs, O1-Preview, O1-Mini:
67+
完全 `OpenAI` 格式的 API ,支持传入 `AccessToken``RefreshToken`,可用 GPT-4, GPT-4o, GPT-4o-Mini, GPTs, O1-Pro, O1, O1-Mini, O3-Mini, O3-Mini-High
6568

6669
```bash
6770
curl --location 'http://127.0.0.1:5005/v1/chat/completions' \

chatgpt/ChatService.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import hashlib
23
import json
34
import random
45
import uuid
@@ -86,9 +87,12 @@ async def set_dynamic_data(self, data):
8687
self.host_url = random.choice(chatgpt_base_url_list) if chatgpt_base_url_list else "https://chatgpt.com"
8788
self.ark0se_token_url = random.choice(ark0se_token_url_list) if ark0se_token_url_list else None
8889

89-
self.s = Client(proxy=self.proxy_url, impersonate=self.impersonate)
90+
session_id = hashlib.md5(self.req_token.encode()).hexdigest()
91+
proxy_url = self.proxy_url.replace("{}", session_id) if self.proxy_url else None
92+
self.s = Client(proxy=proxy_url, impersonate=self.impersonate)
9093
if sentinel_proxy_url_list:
91-
self.ss = Client(proxy=random.choice(sentinel_proxy_url_list), impersonate=self.impersonate)
94+
sentinel_proxy_url = (random.choice(sentinel_proxy_url_list)).replace("{}", session_id) if sentinel_proxy_url_list else None
95+
self.ss = Client(proxy=sentinel_proxy_url, impersonate=self.impersonate)
9296
else:
9397
self.ss = self.s
9498

chatgpt/refreshToken.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import json
23
import random
34
import time
@@ -34,7 +35,9 @@ async def chat_refresh(refresh_token):
3435
"redirect_uri": "com.openai.chat://auth0.openai.com/ios/com.openai.chat/callback",
3536
"refresh_token": refresh_token
3637
}
37-
client = Client(proxy=random.choice(proxy_url_list) if proxy_url_list else None)
38+
session_id = hashlib.md5(refresh_token.encode()).hexdigest()
39+
proxy_url = random.choice(proxy_url_list).replace("{}", session_id) if proxy_url_list else None
40+
client = Client(proxy=proxy_url)
3841
try:
3942
r = await client.post("https://auth0.openai.com/oauth/token", json=data, timeout=15)
4043
if r.status_code == 200:

gateway/backend.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import json
23
import random
34
import re
@@ -295,9 +296,12 @@ async def sentinel_chat_conversations(request: Request):
295296
}
296297
headers.update(fp)
297298
headers.update({"authorization": f"Bearer {access_token}"})
299+
session_id = hashlib.md5(req_token.encode()).hexdigest()
300+
proxy_url = proxy_url.replace("{}", session_id) if proxy_url else None
298301
client = Client(proxy=proxy_url, impersonate=impersonate)
299302
if sentinel_proxy_url_list:
300-
clients = Client(proxy=random.choice(sentinel_proxy_url_list), impersonate=impersonate)
303+
sentinel_proxy_url = random.choice(sentinel_proxy_url_list).replace("{}", session_id) if sentinel_proxy_url_list else None
304+
clients = Client(proxy=sentinel_proxy_url, impersonate=impersonate)
301305
else:
302306
clients = client
303307

@@ -390,9 +394,12 @@ async def chat_conversations(request: Request):
390394
headers.update({"authorization": f"Bearer {access_token}"})
391395

392396
try:
397+
session_id = hashlib.md5(req_token.encode()).hexdigest()
398+
proxy_url = proxy_url.replace("{}", session_id) if proxy_url else None
393399
client = Client(proxy=proxy_url, impersonate=impersonate)
394400
if sentinel_proxy_url_list:
395-
clients = Client(proxy=random.choice(sentinel_proxy_url_list), impersonate=impersonate)
401+
sentinel_proxy_url = random.choice(sentinel_proxy_url_list).replace("{}", session_id) if sentinel_proxy_url_list else None
402+
clients = Client(proxy=sentinel_proxy_url, impersonate=impersonate)
396403
else:
397404
clients = client
398405

gateway/chatgpt.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,29 @@ async def chatgpt_html(request: Request):
3232
set_value_for_key_list(user_chatgpt_context_1, "accessToken", token)
3333
if request.cookies.get("oai-locale"):
3434
set_value_for_key_list(user_chatgpt_context_1, "locale", request.cookies.get("oai-locale"))
35+
else:
36+
accept_language = request.headers.get("accept-language")
37+
if accept_language:
38+
set_value_for_key_list(user_chatgpt_context_1, "locale", accept_language.split(",")[0])
3539

3640
user_chatgpt_context_1 = json.dumps(user_chatgpt_context_1, separators=(',', ':'), ensure_ascii=False)
3741
user_chatgpt_context_2 = json.dumps(user_chatgpt_context_2, separators=(',', ':'), ensure_ascii=False)
3842

39-
escaped_context_1 = user_chatgpt_context_1.replace("\\", "\\\\")
40-
escaped_context_2 = user_chatgpt_context_2.replace("\\", "\\\\")
43+
escaped_context_1 = user_chatgpt_context_1.replace("\\", "\\\\").replace('"', '\\"')
44+
escaped_context_2 = user_chatgpt_context_2.replace("\\", "\\\\").replace('"', '\\"')
4145

42-
escaped_context_1 = escaped_context_1.replace('"', '\\"')
43-
escaped_context_2 = escaped_context_2.replace('"', '\\"')
46+
clear_localstorage_script = """
47+
<script>
48+
localStorage.clear();
49+
</script>
50+
"""
4451

4552
response = templates.TemplateResponse("chatgpt.html", {
46-
"request": request,
53+
"request": request,
4754
"react_chatgpt_context_1": escaped_context_1,
48-
"react_chatgpt_context_2": escaped_context_2
55+
"react_chatgpt_context_2": escaped_context_2,
56+
"clear_localstorage_script": clear_localstorage_script
4957
})
5058
response.set_cookie("token", value=token, expires="Thu, 01 Jan 2099 00:00:00 GMT")
5159
return response
60+

gateway/reverseProxy.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import json
23
import random
34
import time
@@ -211,6 +212,8 @@ async def chatgpt_reverse_proxy(request: Request, path: str):
211212
req_token = await get_real_req_token(cookie_token)
212213
fp = get_fp(req_token).copy()
213214

215+
session_id = hashlib.md5(req_token.encode()).hexdigest()
216+
214217
proxy_url = fp.pop("proxy_url", None)
215218
impersonate = fp.pop("impersonate", "safari15_3")
216219
user_agent = fp.get("user-agent")
@@ -248,9 +251,11 @@ async def chatgpt_reverse_proxy(request: Request, path: str):
248251
data = json.dumps(req_json).encode("utf-8")
249252

250253

251-
if sentinel_proxy_url_list and "backend-api/sentinel/chat-requirements" in path:
252-
client = Client(proxy=random.choice(sentinel_proxy_url_list))
254+
if "backend-api/sentinel/chat-requirements" in path and sentinel_proxy_url_list:
255+
sentinel_proxy_url = random.choice(sentinel_proxy_url_list).replace("{}", session_id) if sentinel_proxy_url_list else None
256+
client = Client(proxy=sentinel_proxy_url)
253257
else:
258+
proxy_url = proxy_url.replace("{}", session_id) if proxy_url else None
254259
client = Client(proxy=proxy_url, impersonate=impersonate)
255260
try:
256261
background = BackgroundTask(client.close)

gateway/share.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import json
23
import random
34
import time
@@ -136,6 +137,8 @@ async def chatgpt_account_check(access_token):
136137
headers.update(fp)
137138
headers.update({"authorization": f"Bearer {access_token}"})
138139

140+
session_id = hashlib.md5(access_token.encode()).hexdigest()
141+
proxy_url = random.choice(proxy_url_list).replace("{}", session_id) if proxy_url_list else None
139142
client = Client(proxy=proxy_url, impersonate=impersonate)
140143
r = await client.get(f"{host_url}/backend-api/models?history_and_training_disabled=false", headers=headers,
141144
timeout=10)
@@ -182,7 +185,9 @@ async def chatgpt_account_check(access_token):
182185

183186

184187
async def chatgpt_refresh(refresh_token):
185-
client = Client(proxy=random.choice(proxy_url_list) if proxy_url_list else None)
188+
session_id = hashlib.md5(refresh_token.encode()).hexdigest()
189+
proxy_url = random.choice(proxy_url_list).replace("{}", session_id) if proxy_url_list else None
190+
client = Client(proxy=proxy_url)
186191
try:
187192
data = {
188193
"client_id": "pdlLIX2Y72MIl2rhLhTE9VV9bN905kBh",

gateway/v1.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
from gateway.reverseProxy import chatgpt_reverse_proxy
88
from utils.kv_utils import set_value_for_key_dict
99

10+
with open("templates/initialize.json", "r") as f:
11+
initialize_json = json.load(f)
12+
1013

1114
@app.post("/v1/initialize")
1215
async def initialize(request: Request):

templates/chatgpt.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
} catch {}
8383
}();
8484
</script>
85+
{{ clear_localstorage_script | safe }}
8586
</head>
8687
<body class="">
8788
<script>

templates/chatgpt_context_1.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
"userCountry",
129129
"US",
130130
"locale",
131-
"zh-CN",
131+
"",
132132
"statsig",
133133
{
134134
"_65": 66

0 commit comments

Comments
 (0)