XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

No arkose token and .har files

95bab66d
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

5 个文件 +48 -47
Modified g4f/Provider/bing/conversation.py +3 -2
@@ -3,8 +3,9 @@ from __future__ import annotations
3 3 from aiohttp import ClientSession
4 4 from ...requests import raise_for_status
5 5 from ...errors import RateLimitError
6 from ...providers.conversation import BaseConversation
6 7
7 class Conversation:
8 class Conversation(BaseConversation):
8 9 """
9 10 Represents a conversation with specific attributes.
10 11 """
@@ -32,7 +33,7 @@ async def create_conversation(session: ClientSession, headers: dict, tone: str)
32 33 Returns:
33 34 Conversation: An instance representing the created conversation.
34 35 """
35 if tone == "copilot":
36 if tone == "Copilot":
36 37 url = "https://copilot.microsoft.com/turing/conversation/create?bundleVersion=1.1634.3-nodesign2"
37 38 else:
38 39 url = "https://www.bing.com/turing/conversation/create?bundleVersion=1.1626.1"
Modified g4f/Provider/needs_auth/OpenaiChat.py +20 -28
@@ -3,10 +3,10 @@ from __future__ import annotations
3 3 import asyncio
4 4 import uuid
5 5 import json
6 import os
7 6 import base64
8 7 import time
9 8 from aiohttp import ClientWebSocketResponse
9 from copy import copy
10 10
11 11 try:
12 12 import webview
@@ -22,13 +22,13 @@ except ImportError:
22 22 pass
23 23
24 24 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
25 from ..helper import get_cookies
26 25 from ...webdriver import get_browser
27 26 from ...typing import AsyncResult, Messages, Cookies, ImageType, Union, AsyncIterator
28 27 from ...requests import get_args_from_browser, raise_for_status
29 28 from ...requests.aiohttp import StreamSession
30 29 from ...image import to_image, to_bytes, ImageResponse, ImageRequest
31 from ...errors import MissingRequirementsError, MissingAuthError, ProviderNotWorkingError
30 from ...errors import MissingAuthError
31 from ...providers.conversation import BaseConversation
32 32 from ..openai.har_file import getArkoseAndAccessToken
33 33 from ... import debug
34 34
@@ -56,11 +56,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
56 56 prompt: str = None,
57 57 model: str = "",
58 58 messages: Messages = [],
59 history_disabled: bool = False,
60 action: str = "next",
61 conversation_id: str = None,
62 parent_id: str = None,
63 image: ImageType = None,
64 59 **kwargs
65 60 ) -> Response:
66 61 """
@@ -89,12 +84,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
89 84 generator = cls.create_async_generator(
90 85 model,
91 86 messages,
92 history_disabled=history_disabled,
93 action=action,
94 conversation_id=conversation_id,
95 parent_id=parent_id,
96 image=image,
97 response_fields=True,
87 return_conversation=True,
98 88 **kwargs
99 89 )
100 90 return Response(
@@ -209,7 +199,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
209 199 } for message in messages]
210 200
211 201 # Check if there is an image response
212 if image_request:
202 if image_request is not None:
213 203 # Change content in last user message
214 204 messages[-1]["content"] = {
215 205 "content_type": "multimodal_text",
@@ -308,10 +298,11 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
308 298 history_disabled: bool = True,
309 299 action: str = "next",
310 300 conversation_id: str = None,
301 conversation: Conversation = None,
311 302 parent_id: str = None,
312 303 image: ImageType = None,
313 304 image_name: str = None,
314 response_fields: bool = False,
305 return_conversation: bool = False,
315 306 **kwargs
316 307 ) -> AsyncResult:
317 308 """
@@ -330,7 +321,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
330 321 conversation_id (str): ID of the conversation.
331 322 parent_id (str): ID of the parent message.
332 323 image (ImageType): Image to include in the conversation.
333 response_fields (bool): Flag to include response fields in the output.
324 return_conversation (bool): Flag to include response fields in the output.
334 325 **kwargs: Additional keyword arguments.
335 326
336 327 Yields:
@@ -387,6 +378,8 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
387 378 arkose_token, api_key, cookies = await getArkoseAndAccessToken(proxy)
388 379 cls._create_request_args(cookies)
389 380 cls._set_api_key(api_key)
381 if arkose_token is None:
382 raise MissingAuthError("No arkose token found in .har file")
390 383
391 384 try:
392 385 image_request = await cls.upload_image(session, cls._headers, image, image_name) if image else None
@@ -396,7 +389,8 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
396 389 print(f"{e.__class__.__name__}: {e}")
397 390
398 391 model = cls.get_model(model).replace("gpt-3.5-turbo", "text-davinci-002-render-sha")
399 fields = ResponseFields()
392 fields = Conversation() if conversation is None else copy(conversation)
393 fields.finish_reason = None
400 394 while fields.finish_reason is None:
401 395 conversation_id = conversation_id if fields.conversation_id is None else fields.conversation_id
402 396 parent_id = parent_id if fields.message_id is None else fields.message_id
@@ -422,8 +416,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
422 416 }
423 417 if need_arkose:
424 418 headers["OpenAI-Sentinel-Arkose-Token"] = arkose_token
425 headers["OpenAI-Sentinel-Chat-Requirements-Token"] = chat_token
426
427 419 async with session.post(
428 420 f"{cls.url}/backend-api/conversation",
429 421 json=data,
@@ -432,15 +424,15 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
432 424 cls._update_request_args(session)
433 425 await raise_for_status(response)
434 426 async for chunk in cls.iter_messages_chunk(response.iter_lines(), session, fields):
435 if response_fields:
436 response_fields = False
427 if return_conversation:
428 return_conversation = False
437 429 yield fields
438 430 yield chunk
439 431 if not auto_continue:
440 432 break
441 433 action = "continue"
442 434 await asyncio.sleep(5)
443 if history_disabled and auto_continue:
435 if history_disabled and auto_continue and not return_conversation:
444 436 await cls.delete_conversation(session, cls._headers, fields.conversation_id)
445 437
446 438 @staticmethod
@@ -458,7 +450,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
458 450 cls,
459 451 messages: AsyncIterator,
460 452 session: StreamSession,
461 fields: ResponseFields
453 fields: Conversation
462 454 ) -> AsyncIterator:
463 455 last_message: int = 0
464 456 async for message in messages:
@@ -487,7 +479,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
487 479 break
488 480
489 481 @classmethod
490 async def iter_messages_line(cls, session: StreamSession, line: bytes, fields: ResponseFields) -> AsyncIterator:
482 async def iter_messages_line(cls, session: StreamSession, line: bytes, fields: Conversation) -> AsyncIterator:
491 483 if not line.startswith(b"data: "):
492 484 return
493 485 elif line.startswith(b"data: [DONE]"):
@@ -618,7 +610,7 @@ this.fetch = async (url, options) => {
618 610 @classmethod
619 611 def _update_request_args(cls, session: StreamSession):
620 612 for c in session.cookie_jar if hasattr(session, "cookie_jar") else session.cookies.jar:
621 cls._cookies[c.name if hasattr(c, "name") else c.key] = c.value
613 cls._cookies[c.key if hasattr(c, "key") else c.name] = c.value
622 614 cls._update_cookie_header()
623 615
624 616 @classmethod
@@ -631,7 +623,7 @@ this.fetch = async (url, options) => {
631 623 def _update_cookie_header(cls):
632 624 cls._headers["Cookie"] = cls._format_cookies(cls._cookies)
633 625
634 class ResponseFields:
626 class Conversation(BaseConversation):
635 627 """
636 628 Class to encapsulate response fields.
637 629 """
@@ -664,7 +656,7 @@ class Response():
664 656 self._generator = None
665 657 chunks = []
666 658 async for chunk in self._generator:
667 if isinstance(chunk, ResponseFields):
659 if isinstance(chunk, Conversation):
668 660 self._fields = chunk
669 661 else:
670 662 yield chunk
Modified g4f/Provider/openai/har_file.py +19 -13
@@ -11,11 +11,6 @@ from copy import deepcopy
11 11 from .crypt import decrypt, encrypt
12 12 from ...requests import StreamSession
13 13
14 arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
15 sessionUrl = "https://chat.openai.com/api/auth/session"
16 chatArk = None
17 accessToken = None
18
19 14 class arkReq:
20 15 def __init__(self, arkURL, arkBx, arkHeader, arkBody, arkCookies, userAgent):
21 16 self.arkURL = arkURL
@@ -25,15 +20,24 @@ class arkReq:
25 20 self.arkCookies = arkCookies
26 21 self.userAgent = userAgent
27 22
23 arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
24 sessionUrl = "https://chat.openai.com/api/auth/session"
25 chatArk: arkReq = None
26 accessToken: str = None
27 cookies: dict = None
28
28 29 def readHAR():
29 30 dirPath = "./"
30 31 harPath = []
31 32 chatArks = []
32 33 accessToken = None
34 cookies = {}
33 35 for root, dirs, files in os.walk(dirPath):
34 36 for file in files:
35 37 if file.endswith(".har"):
36 38 harPath.append(os.path.join(root, file))
39 if harPath:
40 break
37 41 if not harPath:
38 42 raise RuntimeError("No .har file found")
39 43 for path in harPath:
@@ -48,11 +52,12 @@ def readHAR():
48 52 chatArks.append(parseHAREntry(v))
49 53 elif v['request']['url'] == sessionUrl:
50 54 accessToken = json.loads(v["response"]["content"]["text"]).get("accessToken")
51 if not chatArks:
52 RuntimeError("No arkose requests found in .har files")
55 cookies = {c['name']: c['value'] for c in v['request']['cookies']}
53 56 if not accessToken:
54 57 RuntimeError("No accessToken found in .har files")
55 return chatArks.pop(), accessToken
58 if not chatArks:
59 return None, accessToken, cookies
60 return chatArks.pop(), accessToken, cookies
56 61
57 62 def parseHAREntry(entry) -> arkReq:
58 63 tmpArk = arkReq(
@@ -60,7 +65,7 @@ def parseHAREntry(entry) -> arkReq:
60 65 arkBx="",
61 66 arkHeader={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(':')},
62 67 arkBody={p['name']: unquote(p['value']) for p in entry['request']['postData']['params'] if p['name'] not in ['rnd']},
63 arkCookies=[{'name': c['name'], 'value': c['value'], 'expires': c['expires']} for c in entry['request']['cookies']],
68 arkCookies={c['name']: c['value'] for c in entry['request']['cookies']},
64 69 userAgent=""
65 70 )
66 71 tmpArk.userAgent = tmpArk.arkHeader.get('user-agent', '')
@@ -81,7 +86,6 @@ def genArkReq(chatArk: arkReq) -> arkReq:
81 86 tmpArk.arkBody['bda'] = base64.b64encode(bda.encode()).decode()
82 87 tmpArk.arkBody['rnd'] = str(random.random())
83 88 tmpArk.arkHeader['x-ark-esync-value'] = bw
84 tmpArk.arkCookies = {cookie['name']: cookie['value'] for cookie in tmpArk.arkCookies}
85 89 return tmpArk
86 90
87 91 async def sendRequest(tmpArk: arkReq, proxy: str = None):
@@ -117,8 +121,10 @@ def getN() -> str:
117 121 return base64.b64encode(timestamp.encode()).decode()
118 122
119 123 async def getArkoseAndAccessToken(proxy: str):
120 global chatArk, accessToken
124 global chatArk, accessToken, cookies
121 125 if chatArk is None or accessToken is None:
122 chatArk, accessToken = readHAR()
126 chatArk, accessToken, cookies = readHAR()
127 if chatArk is None:
128 return None, accessToken, cookies
123 129 newReq = genArkReq(chatArk)
124 return await sendRequest(newReq, proxy), accessToken, newReq.arkCookies
130 return await sendRequest(newReq, proxy), accessToken, cookies
Modified g4f/gui/server/api.py +4 -4
@@ -39,9 +39,9 @@ from g4f.errors import VersionNotFoundError
39 39 from g4f.Provider import ProviderType, __providers__, __map__
40 40 from g4f.providers.base_provider import ProviderModelMixin
41 41 from g4f.Provider.bing.create_images import patch_provider
42 from g4f.Provider.Bing import Conversation
42 from g4f.providers.conversation import BaseConversation
43 43
44 conversations: dict[str, Conversation] = {}
44 conversations: dict[str, BaseConversation] = {}
45 45
46 46 class Api():
47 47
@@ -230,14 +230,14 @@ class Api():
230 230 if first:
231 231 first = False
232 232 yield self._format_json("provider", get_last_provider(True))
233 if isinstance(chunk, Conversation):
233 if isinstance(chunk, BaseConversation):
234 234 conversations[conversation_id] = chunk
235 235 yield self._format_json("conversation", conversation_id)
236 236 elif isinstance(chunk, Exception):
237 237 logging.exception(chunk)
238 238 yield self._format_json("message", get_error_message(chunk))
239 239 else:
240 yield self._format_json("content", chunk)
240 yield self._format_json("content", str(chunk))
241 241 except Exception as e:
242 242 logging.exception(e)
243 243 yield self._format_json('error', get_error_message(e))
Added g4f/providers/conversation.py +2 -0
@@ -0,0 +1,2 @@
1 class BaseConversation:
2 ...