mirror of
https://github.com/lanqian528/chat2api.git
synced 2026-06-13 21:02:46 +08:00
Merge pull request #201 from lanqian528/dev
Some checks failed
Build Docker Image / main (push) Has been cancelled
Some checks failed
Build Docker Image / main (push) Has been cancelled
Dev to Main
This commit is contained in:
commit
f7b3952b50
@ -8,6 +8,9 @@
|
||||
|
||||
🔍 回复格式与真实 API 完全一致,适配几乎所有客户端
|
||||
|
||||
👮 配套用户管理端[Chat-Share](https://github.com/h88782481/Chat-Share)使用前需提前配置好环境变量(ENABLE_GATEWAY设置为True,AUTO_SEED设置为False)
|
||||
|
||||
|
||||
## 交流群
|
||||
|
||||
[https://t.me/chat2api](https://t.me/chat2api)
|
||||
|
||||
@ -8,9 +8,10 @@ from starlette.concurrency import run_in_threadpool
|
||||
|
||||
from api.files import get_image_size, get_file_extension, determine_file_use_case
|
||||
from api.models import model_proxy
|
||||
from chatgpt.authorization import get_req_token, verify_token, get_fp
|
||||
from chatgpt.authorization import get_req_token, verify_token
|
||||
from chatgpt.chatFormat import api_messages_to_chat, stream_response, format_not_stream_response, head_process_response
|
||||
from chatgpt.chatLimit import check_is_limit, handle_request_limit
|
||||
from chatgpt.fp import get_fp
|
||||
from chatgpt.proofofWork import get_config, get_dpl, get_answer_token, get_requirements_token
|
||||
|
||||
from utils.Client import Client
|
||||
@ -52,10 +53,10 @@ class ChatService:
|
||||
self.access_token = None
|
||||
self.account_id = None
|
||||
|
||||
self.fp = get_fp(self.req_token)
|
||||
self.proxy_url = self.fp.get("proxy_url")
|
||||
self.fp = get_fp(self.req_token).copy()
|
||||
self.proxy_url = self.fp.pop("proxy_url", None)
|
||||
self.impersonate = self.fp.pop("impersonate", "safari15_3")
|
||||
self.user_agent = self.fp.get("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0")
|
||||
self.impersonate = self.fp.get("impersonate", "safari15_3")
|
||||
logger.info(f"Request token: {self.req_token}")
|
||||
logger.info(f"Request proxy: {self.proxy_url}")
|
||||
logger.info(f"Request UA: {self.user_agent}")
|
||||
@ -86,7 +87,6 @@ class ChatService:
|
||||
|
||||
self.s = Client(proxy=self.proxy_url, impersonate=self.impersonate)
|
||||
|
||||
self.oai_device_id = str(uuid.uuid4())
|
||||
self.persona = None
|
||||
self.ark0se_token = None
|
||||
self.proof_token = None
|
||||
@ -100,19 +100,16 @@ class ChatService:
|
||||
'accept-encoding': 'gzip, deflate, br, zstd',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'content-type': 'application/json',
|
||||
'oai-device-id': self.oai_device_id,
|
||||
'oai-language': oai_language,
|
||||
'origin': self.host_url,
|
||||
'priority': 'u=1, i',
|
||||
'referer': f'{self.host_url}/',
|
||||
'sec-ch-ua': self.fp.get("sec-ch-ua", '"Chromium";v="124", "Microsoft Edge";v="124", "Not-A.Brand";v="99"'),
|
||||
'sec-ch-ua-mobile': self.fp.get("sec-ch-ua-mobile", "?0"),
|
||||
'sec-ch-ua-platform': self.fp.get("sec-ch-ua-platform", '"Windows"'),
|
||||
'sec-fetch-dest': 'empty',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-site': 'same-origin',
|
||||
'user-agent': self.user_agent
|
||||
'sec-fetch-site': 'same-origin'
|
||||
}
|
||||
self.base_headers.update(self.fp)
|
||||
|
||||
if self.access_token:
|
||||
self.base_url = self.host_url + "/backend-api"
|
||||
self.base_headers['authorization'] = f'Bearer {self.access_token}'
|
||||
@ -225,7 +222,7 @@ class ChatService:
|
||||
if not self.ark0se_token_url:
|
||||
raise HTTPException(status_code=403, detail="Ark0se service required")
|
||||
ark0se_dx = ark0se.get("dx")
|
||||
ark0se_client = Client(impersonate=self.fp.get("impersonate", "safari15_3"))
|
||||
ark0se_client = Client(impersonate=self.impersonate)
|
||||
try:
|
||||
r2 = await ark0se_client.post(
|
||||
url=self.ark0se_token_url, json={"blob": ark0se_dx, "method": ark0se_method}, timeout=15
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
import asyncio
|
||||
import json
|
||||
import random
|
||||
import uuid
|
||||
|
||||
import ua_generator
|
||||
from ua_generator.options import Options
|
||||
from ua_generator.data.version import VersionRange
|
||||
from fastapi import HTTPException
|
||||
|
||||
import utils.configs as configs
|
||||
@ -47,51 +43,6 @@ def get_req_token(req_token, seed=None):
|
||||
return globals.seed_map[seed]["token"]
|
||||
|
||||
|
||||
def get_fp(req_token):
|
||||
fp = globals.fp_map.get(req_token, {})
|
||||
if fp and fp.get("user-agent") and fp.get("impersonate"):
|
||||
if "proxy_url" in fp.keys() and fp["proxy_url"] is None and fp["proxy_url"] not in configs.proxy_url_list:
|
||||
fp["proxy_url"] = random.choice(configs.proxy_url_list) if configs.proxy_url_list else None
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
if globals.impersonate_list and "impersonate" in fp.keys() and fp["impersonate"] not in globals.impersonate_list:
|
||||
fp["impersonate"] = random.choice(globals.impersonate_list)
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
if configs.user_agents_list and "user-agent" in fp.keys() and fp["user-agent"] not in configs.user_agents_list:
|
||||
fp["user-agent"] = random.choice(configs.user_agents_list)
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
fp = {k.lower(): v for k, v in fp.items()}
|
||||
return fp
|
||||
else:
|
||||
options = Options(version_ranges={
|
||||
'chrome': VersionRange(min_version=124),
|
||||
'edge': VersionRange(min_version=124),
|
||||
})
|
||||
ua = ua_generator.generate(device='desktop', browser=('chrome', 'edge', 'firefox', 'safari'),
|
||||
platform=('windows', 'macos'), options=options)
|
||||
fp = {
|
||||
"user-agent": ua.text if not configs.user_agents_list else random.choice(configs.user_agents_list),
|
||||
"sec-ch-ua-platform": ua.ch.platform,
|
||||
"sec-ch-ua": ua.ch.brands,
|
||||
"sec-ch-ua-mobile": ua.ch.mobile,
|
||||
"impersonate": random.choice(globals.impersonate_list),
|
||||
"proxy_url": random.choice(configs.proxy_url_list) if configs.proxy_url_list else None,
|
||||
"oai-device-id": str(uuid.uuid4())
|
||||
}
|
||||
if not req_token:
|
||||
return fp
|
||||
else:
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
return fp
|
||||
|
||||
|
||||
async def verify_token(req_token):
|
||||
if not req_token:
|
||||
if configs.authorization_list:
|
||||
|
||||
61
chatgpt/fp.py
Normal file
61
chatgpt/fp.py
Normal file
@ -0,0 +1,61 @@
|
||||
import json
|
||||
import random
|
||||
import uuid
|
||||
|
||||
import ua_generator
|
||||
from ua_generator.data.version import VersionRange
|
||||
from ua_generator.options import Options
|
||||
|
||||
import utils.globals as globals
|
||||
from utils import configs
|
||||
|
||||
|
||||
def get_fp(req_token):
|
||||
fp = globals.fp_map.get(req_token, {})
|
||||
if fp and fp.get("user-agent") and fp.get("impersonate"):
|
||||
if "proxy_url" in fp.keys() and (fp["proxy_url"] is None or fp["proxy_url"] not in configs.proxy_url_list):
|
||||
fp["proxy_url"] = random.choice(configs.proxy_url_list) if configs.proxy_url_list else None
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
if globals.impersonate_list and "impersonate" in fp.keys() and fp["impersonate"] not in globals.impersonate_list:
|
||||
fp["impersonate"] = random.choice(globals.impersonate_list)
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
if configs.user_agents_list and "user-agent" in fp.keys() and fp["user-agent"] not in configs.user_agents_list:
|
||||
fp["user-agent"] = random.choice(configs.user_agents_list)
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
fp = {k.lower(): v for k, v in fp.items()}
|
||||
return fp
|
||||
else:
|
||||
options = Options(version_ranges={
|
||||
'chrome': VersionRange(min_version=124),
|
||||
'edge': VersionRange(min_version=124),
|
||||
})
|
||||
ua = ua_generator.generate(
|
||||
device=configs.device_tuple if configs.device_tuple else ('desktop'),
|
||||
browser=configs.browser_tuple if configs.browser_tuple else ('chrome', 'edge', 'firefox', 'safari'),
|
||||
platform=configs.platform_tuple if configs.platform_tuple else ('windows', 'macos'),
|
||||
options=options
|
||||
)
|
||||
fp = {
|
||||
"user-agent": ua.text if not configs.user_agents_list else random.choice(configs.user_agents_list),
|
||||
"impersonate": random.choice(globals.impersonate_list),
|
||||
"proxy_url": random.choice(configs.proxy_url_list) if configs.proxy_url_list else None,
|
||||
"oai-device-id": str(uuid.uuid4())
|
||||
}
|
||||
if ua.device == "desktop" and ua.browser in ("chrome", "edge"):
|
||||
fp["sec-ch-ua-platform"] = ua.ch.platform
|
||||
fp["sec-ch-ua"] = ua.ch.brands
|
||||
fp["sec-ch-ua-mobile"] = ua.ch.mobile
|
||||
|
||||
if not req_token:
|
||||
return fp
|
||||
else:
|
||||
globals.fp_map[req_token] = fp
|
||||
with open(globals.FP_FILE, "w", encoding="utf-8") as f:
|
||||
json.dump(globals.fp_map, f, indent=4)
|
||||
return fp
|
||||
@ -11,7 +11,8 @@ from starlette.concurrency import run_in_threadpool
|
||||
|
||||
import utils.globals as globals
|
||||
from app import app
|
||||
from chatgpt.authorization import verify_token, get_fp
|
||||
from chatgpt.authorization import verify_token
|
||||
from chatgpt.fp import get_fp
|
||||
from chatgpt.proofofWork import get_answer_token, get_config, get_requirements_token
|
||||
from gateway.chatgpt import chatgpt_html
|
||||
from gateway.reverseProxy import chatgpt_reverse_proxy, content_generator, get_real_req_token, headers_reject_list
|
||||
@ -252,11 +253,10 @@ if no_sentinel:
|
||||
token = request.headers.get("Authorization", "").replace("Bearer ", "")
|
||||
req_token = await get_real_req_token(token)
|
||||
access_token = await verify_token(req_token)
|
||||
fp = get_fp(req_token)
|
||||
fp = get_fp(req_token).copy()
|
||||
proxy_url = fp.pop("proxy_url", None)
|
||||
impersonate = fp.pop("impersonate", "safari15_3")
|
||||
user_agent = fp.get("user-agent",
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0")
|
||||
user_agent = fp.get("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0")
|
||||
|
||||
host_url = random.choice(chatgpt_base_url_list) if chatgpt_base_url_list else "https://chatgpt.com"
|
||||
proof_token = None
|
||||
@ -264,14 +264,10 @@ if no_sentinel:
|
||||
|
||||
headers = {
|
||||
key: value for key, value in request.headers.items()
|
||||
if (key.lower() not in ["host", "origin", "referer", "priority",
|
||||
"oai-device-id"] and key.lower() not in headers_reject_list)
|
||||
if (key.lower() not in ["host", "origin", "referer", "priority", "sec-ch-ua-platform", "sec-ch-ua", "sec-ch-ua-mobile", "oai-device-id"] and key.lower() not in headers_reject_list)
|
||||
}
|
||||
headers.update(fp)
|
||||
headers.update({
|
||||
"authorization": f"Bearer {access_token}",
|
||||
"oai-device-id": fp.get("oai-device-id", str(uuid.uuid4()))
|
||||
})
|
||||
headers.update({"authorization": f"Bearer {access_token}"})
|
||||
|
||||
client = Client(proxy=proxy_url, impersonate=impersonate)
|
||||
|
||||
|
||||
@ -9,7 +9,8 @@ from fastapi.responses import StreamingResponse, Response
|
||||
from starlette.background import BackgroundTask
|
||||
|
||||
import utils.globals as globals
|
||||
from chatgpt.authorization import verify_token, get_req_token, get_fp
|
||||
from chatgpt.authorization import verify_token, get_req_token
|
||||
from chatgpt.fp import get_fp
|
||||
from utils.Client import Client
|
||||
from utils.Logger import logger
|
||||
from utils.configs import chatgpt_base_url_list
|
||||
@ -173,7 +174,7 @@ async def chatgpt_reverse_proxy(request: Request, path: str):
|
||||
|
||||
token = request.cookies.get("token", "")
|
||||
req_token = await get_real_req_token(token)
|
||||
fp = get_fp(req_token)
|
||||
fp = get_fp(req_token).copy()
|
||||
proxy_url = fp.pop("proxy_url", None)
|
||||
impersonate = fp.pop("impersonate", "safari15_3")
|
||||
user_agent = fp.get("user-agent")
|
||||
|
||||
@ -9,7 +9,8 @@ from fastapi.security import HTTPAuthorizationCredentials
|
||||
|
||||
import utils.globals as globals
|
||||
from app import app, security_scheme
|
||||
from chatgpt.authorization import get_fp, verify_token
|
||||
from chatgpt.authorization import verify_token
|
||||
from chatgpt.fp import get_fp
|
||||
from gateway.reverseProxy import get_real_req_token
|
||||
from utils.Client import Client
|
||||
from utils.Logger import logger
|
||||
@ -127,13 +128,13 @@ async def chatgpt_account_check(access_token):
|
||||
host_url = random.choice(chatgpt_base_url_list) if chatgpt_base_url_list else "https://chatgpt.com"
|
||||
req_token = await get_real_req_token(access_token)
|
||||
access_token = await verify_token(req_token)
|
||||
fp = get_fp(req_token)
|
||||
fp = get_fp(req_token).copy()
|
||||
proxy_url = fp.pop("proxy_url", None)
|
||||
impersonate = fp.pop("impersonate", "safari15_3")
|
||||
|
||||
headers = base_headers.copy()
|
||||
headers.update({"authorization": f"Bearer {access_token}"})
|
||||
headers.update(fp)
|
||||
headers.update({"authorization": f"Bearer {access_token}"})
|
||||
|
||||
client = Client(proxy=proxy_url, impersonate=impersonate)
|
||||
r = await client.get(f"{host_url}/backend-api/models?history_and_training_disabled=false", headers=headers,
|
||||
|
||||
@ -32,6 +32,9 @@ proxy_url = os.getenv('PROXY_URL', '').replace(' ', '')
|
||||
export_proxy_url = os.getenv('EXPORT_PROXY_URL', None)
|
||||
impersonate_list_str = os.getenv('IMPERSONATE', '[]')
|
||||
user_agents_list_str = os.getenv('USER_AGENTS', '[]')
|
||||
device_tuple_str = os.getenv('DEVICE_TUPLE', '()')
|
||||
browser_tuple_str = os.getenv('BROWSER_TUPLE', '()')
|
||||
platform_tuple_str = os.getenv('PLATFORM_TUPLE', '()')
|
||||
|
||||
cf_file_url = os.getenv('CF_FILE_URL', None)
|
||||
turnstile_solver_url = os.getenv('TURNSTILE_SOLVER_URL', None)
|
||||
@ -53,6 +56,9 @@ ark0se_token_url_list = ark0se_token_url.split(',') if ark0se_token_url else []
|
||||
proxy_url_list = proxy_url.split(',') if proxy_url else []
|
||||
impersonate_list = ast.literal_eval(impersonate_list_str)
|
||||
user_agents_list = ast.literal_eval(user_agents_list_str)
|
||||
device_tuple = ast.literal_eval(device_tuple_str)
|
||||
browser_tuple = ast.literal_eval(browser_tuple_str)
|
||||
platform_tuple = ast.literal_eval(platform_tuple_str)
|
||||
|
||||
enable_gateway = is_true(os.getenv('ENABLE_GATEWAY', False))
|
||||
auto_seed = is_true(os.getenv('AUTO_SEED', True))
|
||||
|
||||
@ -1 +1 @@
|
||||
1.7.2
|
||||
v1.7.3-beta1
|
||||
Loading…
Reference in New Issue
Block a user