返回提交历史
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+48
-33
Modified
g4f/Provider/openai/har_file.py
+4
-3
Modified
g4f/Provider/openai/proofofwork.py
+9
-20
Modified
g4f/Provider/you/har_file.py
+1
-1
XFEstudio/gpt4free
Fix OpenaiChat provider, improve proofofwork
96e378e9
代码差异
4 个文件
+62
-57
@@ -330,6 +330,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
330
330
image: ImageType = None,
331
331
image_name: str = None,
332
332
return_conversation: bool = False,
333
max_retries: int = 3,
333
334
**kwargs
334
335
) -> AsyncResult:
335
336
"""
@@ -409,36 +410,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
409
410
raise error
410
411
cls.default_model = cls.get_model(await cls.get_default_model(session, cls._headers))
411
412
412
async with session.post(
413
f"{cls.url}/backend-anon/sentinel/chat-requirements"
414
if cls._api_key is None else
415
f"{cls.url}/backend-api/sentinel/chat-requirements",
416
json={"conversation_mode_kind": "primary_assistant"},
417
#json={"p": generate_proof_token(True, user_agent=cls._headers["user-agent"], proofTokens=proofTokens)},
418
headers=cls._headers
419
) as response:
420
cls._update_request_args(session)
421
await raise_for_status(response)
422
data = await response.json()
423
need_arkose = data.get("arkose", {}).get("required")
424
chat_token = data["token"]
425
proofofwork = ""
426
if "proofofwork" in data:
427
proofofwork = generate_proof_token(**data["proofofwork"], user_agent=cls._headers["user-agent"], proofTokens=proofTokens)
428
429
if need_arkose and arkose_token is None:
430
arkose_token, api_key, cookies, headers = await getArkoseAndAccessToken(proxy)
431
cls._create_request_args(cookies, headers)
432
cls._set_api_key(api_key)
433
if arkose_token is None:
434
raise MissingAuthError("No arkose token found in .har file")
435
436
if debug.logging:
437
print(
438
'Arkose:', False if not need_arkose else arkose_token[:12]+"...",
439
'Proofofwork:', False if proofofwork is None else proofofwork[:12]+"...",
440
)
441
442
413
try:
443
414
image_request = await cls.upload_image(session, cls._headers, image, image_name) if image else None
444
415
except Exception as e:
@@ -457,6 +428,43 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
457
428
auto_continue = False
458
429
conversation.finish_reason = None
459
430
while conversation.finish_reason is None:
431
async with session.post(
432
f"{cls.url}/backend-anon/sentinel/chat-requirements"
433
if cls._api_key is None else
434
f"{cls.url}/backend-api/sentinel/chat-requirements",
435
json={"p": generate_proof_token(True, user_agent=cls._headers["user-agent"], proofTokens=proofTokens)},
436
headers=cls._headers
437
) as response:
438
cls._update_request_args(session)
439
await raise_for_status(response)
440
requirements = await response.json()
441
need_arkose = requirements.get("arkose", {}).get("required")
442
chat_token = requirements["token"]
443
444
if need_arkose and arkose_token is None:
445
arkose_token, api_key, cookies, headers, proofTokens = await getArkoseAndAccessToken(proxy)
446
cls._create_request_args(cookies, headers)
447
cls._set_api_key(api_key)
448
if arkose_token is None:
449
raise MissingAuthError("No arkose token found in .har file")
450
451
if "proofofwork" in requirements:
452
proofofwork = generate_proof_token(
453
**requirements["proofofwork"],
454
user_agent=cls._headers["user-agent"],
455
proofTokens=proofTokens
456
)
457
if debug.logging:
458
print(
459
'Arkose:', False if not need_arkose else arkose_token[:12]+"...",
460
'Proofofwork:', False if proofofwork is None else proofofwork[:12]+"...",
461
)
462
ws = None
463
if need_arkose:
464
async with session.post("https://chatgpt.com/backend-api/register-websocket", headers=cls._headers) as response:
465
wss_url = (await response.json()).get("wss_url")
466
if wss_url:
467
ws = await session.ws_connect(wss_url)
460
468
websocket_request_id = str(uuid.uuid4())
461
469
data = {
462
470
"action": action,
@@ -488,8 +496,14 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
488
496
headers=headers
489
497
) as response:
490
498
cls._update_request_args(session)
499
if response.status == 403 and max_retries > 0:
500
max_retries -= 1
501
if debug.logging:
502
print(f"Retry: Error {response.status}: {await response.text()}")
503
await asyncio.sleep(5)
504
continue
491
505
await raise_for_status(response)
492
async for chunk in cls.iter_messages_chunk(response.iter_lines(), session, conversation):
506
async for chunk in cls.iter_messages_chunk(response.iter_lines(), session, conversation, ws):
493
507
if return_conversation:
494
508
history_disabled = False
495
509
return_conversation = False
@@ -519,13 +533,14 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
519
533
cls,
520
534
messages: AsyncIterator,
521
535
session: StreamSession,
522
fields: Conversation
536
fields: Conversation,
537
ws = None
523
538
) -> AsyncIterator:
524
539
last_message: int = 0
525
540
async for message in messages:
526
541
if message.startswith(b'{"wss_url":'):
527
542
message = json.loads(message)
528
ws = await session.ws_connect(message["wss_url"])
543
ws = await session.ws_connect(message["wss_url"]) if ws is None else ws
529
544
try:
530
545
async for chunk in cls.iter_messages_chunk(
531
546
cls.iter_messages_ws(ws, message["conversation_id"], hasattr(ws, "recv")),
@@ -35,6 +35,7 @@ headers: dict = None
35
35
proofTokens: list = []
36
36
37
37
def readHAR():
38
global proofTokens
38
39
dirPath = "./"
39
40
harPath = []
40
41
chatArks = []
@@ -77,8 +78,8 @@ def readHAR():
77
78
if not accessToken:
78
79
raise NoValidHarFileError("No accessToken found in .har files")
79
80
if not chatArks:
80
return None, accessToken, cookies, headers, proofTokens
81
return chatArks.pop(), accessToken, cookies, headers, proofTokens
81
return None, accessToken, cookies, headers
82
return chatArks.pop(), accessToken, cookies, headers
82
83
83
84
def get_headers(entry) -> dict:
84
85
return {h['name'].lower(): h['value'] for h in entry['request']['headers'] if h['name'].lower() not in ['content-length', 'cookie'] and not h['name'].startswith(':')}
@@ -145,7 +146,7 @@ def getN() -> str:
145
146
async def getArkoseAndAccessToken(proxy: str) -> tuple[str, str, dict, dict]:
146
147
global chatArk, accessToken, cookies, headers, proofTokens
147
148
if chatArk is None or accessToken is None:
148
chatArk, accessToken, cookies, headers, proofTokens = readHAR()
149
chatArk, accessToken, cookies, headers = readHAR()
149
150
if chatArk is None:
150
151
return None, accessToken, cookies, headers, proofTokens
151
152
newReq = genArkReq(chatArk)
@@ -4,22 +4,18 @@ import json
4
4
import base64
5
5
from datetime import datetime, timezone
6
6
7
proof_token_cache: dict = {}
8
7
9
def generate_proof_token(required: bool, seed: str = None, difficulty: str = None, user_agent: str = None, proofTokens: list = None):
8
def generate_proof_token(required: bool, seed: str = "", difficulty: str = "", user_agent: str = None, proofTokens: list = None):
10
9
if not required:
11
10
return
12
if seed is not None and seed in proof_token_cache:
13
return proof_token_cache[seed]
14
15
# Get current UTC time
16
now_utc = datetime.now(timezone.utc)
17
parse_time = now_utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
18
11
19
12
if proofTokens:
20
config = random.choice(proofTokens)
13
config = proofTokens[-1]
21
14
else:
22
15
screen = random.choice([3008, 4010, 6000]) * random.choice([1, 2, 4])
16
# Get current UTC time
17
now_utc = datetime.now(timezone.utc)
18
parse_time = now_utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
23
19
config = [
24
20
screen, parse_time,
25
21
None, 0, user_agent,
@@ -31,22 +27,15 @@ def generate_proof_token(required: bool, seed: str = None, difficulty: str = Non
31
27
random.choice(["alert", "ontransitionend", "onprogress"])
32
28
]
33
29
34
config[1] = parse_time
35
config[4] = user_agent
36
config[7] = random.randint(101, 2100)
37
38
diff_len = None if difficulty is None else len(difficulty)
30
diff_len = len(difficulty)
39
31
for i in range(100000):
40
32
config[3] = i
41
33
json_data = json.dumps(config)
42
34
base = base64.b64encode(json_data.encode()).decode()
43
hash_value = hashlib.sha3_512((seed or "" + base).encode()).digest()
35
hash_value = hashlib.sha3_512((seed + base).encode()).digest()
44
36
45
if difficulty is None or hash_value.hex()[:diff_len] <= difficulty:
46
if seed is None:
47
return "gAAAAAC" + base
48
proof_token_cache[seed] = "gAAAAAB" + base
49
return proof_token_cache[seed]
37
if hash_value.hex()[:diff_len] <= difficulty:
38
return "gAAAAAB" + base
50
39
51
40
fallback_base = base64.b64encode(f'"{seed}"'.encode()).decode()
52
41
return "gAAAAABwQ8Lk5FbGpA2NcR9dShT6gYjU7VxZ4D" + fallback_base
@@ -115,7 +115,7 @@ async def get_telemetry_ids(proxy: str = None) -> list:
115
115
if page is not None:
116
116
await page.close()
117
117
if browser is not None:
118
await browser.close()
118
await browser.stop()
119
119
except Exception as e:
120
120
if debug.logging:
121
121
logging.error(e)