mirror of
https://github.com/xtekky/gpt4free.git
synced 2024-12-25 04:01:52 +03:00
Update docker tags in workfloe for slim images,
Update read har file in OpenaiChat provider Remove webdriver in OpenaiChat provider Add supported_encodings and supported_encodings in OpenaiChat
This commit is contained in:
parent
ea1448001d
commit
b7a8e03220
4
.github/workflows/publish-workflow.yaml
vendored
4
.github/workflows/publish-workflow.yaml
vendored
@ -55,8 +55,8 @@ jobs:
|
|||||||
file: docker/Dockerfile-slim
|
file: docker/Dockerfile-slim
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
hlohaus789/g4f=slim
|
hlohaus789/g4f:slim-latest
|
||||||
hlohaus789/g4f=${{ github.ref_name }}-slim
|
hlohaus789/g4f:${{ github.ref_name }}-slim
|
||||||
labels: ${{ steps.metadata.outputs.labels }}
|
labels: ${{ steps.metadata.outputs.labels }}
|
||||||
build-args: |
|
build-args: |
|
||||||
G4F_VERSION=${{ github.ref_name }}
|
G4F_VERSION=${{ github.ref_name }}
|
@ -9,22 +9,19 @@ from aiohttp import ClientWebSocketResponse
|
|||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import webview
|
import nodriver
|
||||||
has_webview = True
|
has_nodriver = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_webview = False
|
has_nodriver = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from selenium.webdriver.common.by import By
|
from platformdirs import user_config_dir
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
has_platformdirs = True
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
has_platformdirs = False
|
||||||
|
|
||||||
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
|
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
|
||||||
from ...webdriver import get_browser
|
|
||||||
from ...typing import AsyncResult, Messages, Cookies, ImageType, AsyncIterator
|
from ...typing import AsyncResult, Messages, Cookies, ImageType, AsyncIterator
|
||||||
from ...requests import get_args_from_browser, raise_for_status
|
from ...requests.raise_for_status import raise_for_status
|
||||||
from ...requests.aiohttp import StreamSession
|
from ...requests.aiohttp import StreamSession
|
||||||
from ...image import ImageResponse, ImageRequest, to_image, to_bytes, is_accepted_format
|
from ...image import ImageResponse, ImageRequest, to_image, to_bytes, is_accepted_format
|
||||||
from ...errors import MissingAuthError, ResponseError
|
from ...errors import MissingAuthError, ResponseError
|
||||||
@ -63,11 +60,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
default_vision_model = "gpt-4o"
|
default_vision_model = "gpt-4o"
|
||||||
models = [ "auto", "gpt-4o-mini", "gpt-4o", "gpt-4", "gpt-4-gizmo"]
|
models = [ "auto", "gpt-4o-mini", "gpt-4o", "gpt-4", "gpt-4-gizmo"]
|
||||||
|
|
||||||
model_aliases = {
|
|
||||||
#"gpt-4-turbo": "gpt-4",
|
|
||||||
#"gpt-4": "gpt-4-gizmo",
|
|
||||||
#"dalle": "gpt-4",
|
|
||||||
}
|
|
||||||
_api_key: str = None
|
_api_key: str = None
|
||||||
_headers: dict = None
|
_headers: dict = None
|
||||||
_cookies: Cookies = None
|
_cookies: Cookies = None
|
||||||
@ -219,9 +211,12 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
"""
|
"""
|
||||||
# Create a message object with the user role and the content
|
# Create a message object with the user role and the content
|
||||||
messages = [{
|
messages = [{
|
||||||
"id": str(uuid.uuid4()),
|
|
||||||
"author": {"role": message["role"]},
|
"author": {"role": message["role"]},
|
||||||
"content": {"content_type": "text", "parts": [message["content"]]},
|
"content": {"content_type": "text", "parts": [message["content"]]},
|
||||||
|
"id": str(uuid.uuid4()),
|
||||||
|
"create_time": int(time.time()),
|
||||||
|
"id": str(uuid.uuid4()),
|
||||||
|
"metadata": {"serialization_metadata": {"custom_symbol_offsets": []}}
|
||||||
} for message in messages]
|
} for message in messages]
|
||||||
|
|
||||||
# Check if there is an image response
|
# Check if there is an image response
|
||||||
@ -250,7 +245,7 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
return messages
|
return messages
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def get_generated_image(cls, session: StreamSession, headers: dict, line: dict) -> ImageResponse:
|
async def get_generated_image(cls, session: StreamSession, headers: dict, element: dict) -> ImageResponse:
|
||||||
"""
|
"""
|
||||||
Retrieves the image response based on the message content.
|
Retrieves the image response based on the message content.
|
||||||
|
|
||||||
@ -269,15 +264,8 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If there'san error in downloading the image, including issues with the HTTP request or response.
|
RuntimeError: If there'san error in downloading the image, including issues with the HTTP request or response.
|
||||||
"""
|
"""
|
||||||
if "parts" not in line["message"]["content"]:
|
prompt = element["metadata"]["dalle"]["prompt"]
|
||||||
return
|
file_id = element["asset_pointer"].split("file-service://", 1)[1]
|
||||||
first_part = line["message"]["content"]["parts"][0]
|
|
||||||
if "asset_pointer" not in first_part or "metadata" not in first_part:
|
|
||||||
return
|
|
||||||
if first_part["metadata"] is None or first_part["metadata"]["dalle"] is None:
|
|
||||||
return
|
|
||||||
prompt = first_part["metadata"]["dalle"]["prompt"]
|
|
||||||
file_id = first_part["asset_pointer"].split("file-service://", 1)[1]
|
|
||||||
try:
|
try:
|
||||||
async with session.get(f"{cls.url}/backend-api/files/{file_id}/download", headers=headers) as response:
|
async with session.get(f"{cls.url}/backend-api/files/{file_id}/download", headers=headers) as response:
|
||||||
cls._update_request_args(session)
|
cls._update_request_args(session)
|
||||||
@ -365,9 +353,10 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
if cls._expires is not None and cls._expires < time.time():
|
if cls._expires is not None and cls._expires < time.time():
|
||||||
cls._headers = cls._api_key = None
|
cls._headers = cls._api_key = None
|
||||||
arkose_token = None
|
arkose_token = None
|
||||||
proofTokens = None
|
proofToken = None
|
||||||
|
turnstileToken = None
|
||||||
try:
|
try:
|
||||||
arkose_token, api_key, cookies, headers, proofTokens = await getArkoseAndAccessToken(proxy)
|
arkose_token, api_key, cookies, headers, proofToken, turnstileToken = await getArkoseAndAccessToken(proxy)
|
||||||
cls._create_request_args(cookies, headers)
|
cls._create_request_args(cookies, headers)
|
||||||
cls._set_api_key(api_key)
|
cls._set_api_key(api_key)
|
||||||
except NoValidHarFileError as e:
|
except NoValidHarFileError as e:
|
||||||
@ -400,32 +389,28 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
f"{cls.url}/backend-anon/sentinel/chat-requirements"
|
f"{cls.url}/backend-anon/sentinel/chat-requirements"
|
||||||
if cls._api_key is None else
|
if cls._api_key is None else
|
||||||
f"{cls.url}/backend-api/sentinel/chat-requirements",
|
f"{cls.url}/backend-api/sentinel/chat-requirements",
|
||||||
json={"p": generate_proof_token(True, user_agent=cls._headers["user-agent"], proofTokens=proofTokens)},
|
json={"p": generate_proof_token(True, user_agent=cls._headers["user-agent"], proofToken=proofToken)},
|
||||||
headers=cls._headers
|
headers=cls._headers
|
||||||
) as response:
|
) as response:
|
||||||
cls._update_request_args(session)
|
cls._update_request_args(session)
|
||||||
await raise_for_status(response)
|
await raise_for_status(response)
|
||||||
requirements = await response.json()
|
chat_requirements = await response.json()
|
||||||
text_data = json.loads(requirements.get("text", "{}"))
|
need_turnstile = chat_requirements.get("turnstile", {}).get("required", False)
|
||||||
need_arkose = text_data.get("turnstile", {}).get("required", False)
|
need_arkose = chat_requirements.get("arkose", {}).get("required", False)
|
||||||
if need_arkose:
|
chat_token = chat_requirements.get("token")
|
||||||
arkose_token = text_data.get("turnstile", {}).get("dx")
|
|
||||||
else:
|
|
||||||
need_arkose = requirements.get("arkose", {}).get("required", False)
|
|
||||||
chat_token = requirements["token"]
|
|
||||||
|
|
||||||
if need_arkose and arkose_token is None:
|
if need_arkose and arkose_token is None:
|
||||||
arkose_token, api_key, cookies, headers, proofTokens = await getArkoseAndAccessToken(proxy)
|
arkose_token, api_key, cookies, headers, proofToken, turnstileToken = await getArkoseAndAccessToken(proxy)
|
||||||
cls._create_request_args(cookies, headers)
|
cls._create_request_args(cookies, headers)
|
||||||
cls._set_api_key(api_key)
|
cls._set_api_key(api_key)
|
||||||
if arkose_token is None:
|
if arkose_token is None:
|
||||||
raise MissingAuthError("No arkose token found in .har file")
|
raise MissingAuthError("No arkose token found in .har file")
|
||||||
|
|
||||||
if "proofofwork" in requirements:
|
if "proofofwork" in chat_requirements:
|
||||||
proofofwork = generate_proof_token(
|
proofofwork = generate_proof_token(
|
||||||
**requirements["proofofwork"],
|
**chat_requirements["proofofwork"],
|
||||||
user_agent=cls._headers["user-agent"],
|
user_agent=cls._headers["user-agent"],
|
||||||
proofTokens=proofTokens
|
proofToken=proofToken
|
||||||
)
|
)
|
||||||
if debug.logging:
|
if debug.logging:
|
||||||
print(
|
print(
|
||||||
@ -441,15 +426,18 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
websocket_request_id = str(uuid.uuid4())
|
websocket_request_id = str(uuid.uuid4())
|
||||||
data = {
|
data = {
|
||||||
"action": action,
|
"action": action,
|
||||||
"conversation_mode": {"kind": "primary_assistant"},
|
"messages": None,
|
||||||
"force_paragen": False,
|
|
||||||
"force_rate_limit": False,
|
|
||||||
"conversation_id": conversation.conversation_id,
|
|
||||||
"parent_message_id": conversation.message_id,
|
"parent_message_id": conversation.message_id,
|
||||||
"model": model,
|
"model": model,
|
||||||
|
"paragen_cot_summary_display_override": "allow",
|
||||||
"history_and_training_disabled": history_disabled and not auto_continue and not return_conversation,
|
"history_and_training_disabled": history_disabled and not auto_continue and not return_conversation,
|
||||||
"websocket_request_id": websocket_request_id
|
"conversation_mode": {"kind":"primary_assistant"},
|
||||||
|
"websocket_request_id": websocket_request_id,
|
||||||
|
"supported_encodings": ["v1"],
|
||||||
|
"supports_buffering": True
|
||||||
}
|
}
|
||||||
|
if conversation.conversation_id is not None:
|
||||||
|
data["conversation_id"] = conversation.conversation_id
|
||||||
if action != "continue":
|
if action != "continue":
|
||||||
messages = messages if conversation_id is None else [messages[-1]]
|
messages = messages if conversation_id is None else [messages[-1]]
|
||||||
data["messages"] = cls.create_messages(messages, image_request)
|
data["messages"] = cls.create_messages(messages, image_request)
|
||||||
@ -458,10 +446,12 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
"Openai-Sentinel-Chat-Requirements-Token": chat_token,
|
"Openai-Sentinel-Chat-Requirements-Token": chat_token,
|
||||||
**cls._headers
|
**cls._headers
|
||||||
}
|
}
|
||||||
if need_arkose:
|
if arkose_token:
|
||||||
headers["Openai-Sentinel-Arkose-Token"] = arkose_token
|
headers["Openai-Sentinel-Arkose-Token"] = arkose_token
|
||||||
if proofofwork is not None:
|
if proofofwork is not None:
|
||||||
headers["Openai-Sentinel-Proof-Token"] = proofofwork
|
headers["Openai-Sentinel-Proof-Token"] = proofofwork
|
||||||
|
if need_turnstile and turnstileToken is not None:
|
||||||
|
headers['openai-sentinel-turnstile-token'] = turnstileToken
|
||||||
async with session.post(
|
async with session.post(
|
||||||
f"{cls.url}/backend-anon/conversation"
|
f"{cls.url}/backend-anon/conversation"
|
||||||
if cls._api_key is None else
|
if cls._api_key is None else
|
||||||
@ -510,7 +500,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
fields: Conversation,
|
fields: Conversation,
|
||||||
ws = None
|
ws = None
|
||||||
) -> AsyncIterator:
|
) -> AsyncIterator:
|
||||||
last_message: int = 0
|
|
||||||
async for message in messages:
|
async for message in messages:
|
||||||
if message.startswith(b'{"wss_url":'):
|
if message.startswith(b'{"wss_url":'):
|
||||||
message = json.loads(message)
|
message = json.loads(message)
|
||||||
@ -527,10 +516,6 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
async for chunk in cls.iter_messages_line(session, message, fields):
|
async for chunk in cls.iter_messages_line(session, message, fields):
|
||||||
if fields.finish_reason is not None:
|
if fields.finish_reason is not None:
|
||||||
break
|
break
|
||||||
elif isinstance(chunk, str):
|
|
||||||
if len(chunk) > last_message:
|
|
||||||
yield chunk[last_message:]
|
|
||||||
last_message = len(chunk)
|
|
||||||
else:
|
else:
|
||||||
yield chunk
|
yield chunk
|
||||||
if fields.finish_reason is not None:
|
if fields.finish_reason is not None:
|
||||||
@ -548,82 +533,50 @@ class OpenaiChat(AsyncGeneratorProvider, ProviderModelMixin):
|
|||||||
line = json.loads(line[6:])
|
line = json.loads(line[6:])
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
if "message" not in line:
|
if isinstance(line, dict) and "v" in line:
|
||||||
return
|
v = line.get("v")
|
||||||
if "error" in line and line["error"]:
|
r = ""
|
||||||
raise RuntimeError(line["error"])
|
if isinstance(v, str):
|
||||||
if "message_type" not in line["message"]["metadata"]:
|
yield v
|
||||||
return
|
elif isinstance(v, list):
|
||||||
image_response = await cls.get_generated_image(session, cls._headers, line)
|
for m in v:
|
||||||
if image_response is not None:
|
if m.get("p") == "/message/content/parts/0":
|
||||||
yield image_response
|
yield m.get("v")
|
||||||
if line["message"]["author"]["role"] != "assistant":
|
elif m.get("p") == "/message/metadata":
|
||||||
return
|
fields.finish_reason = m.get("v", {}).get("finish_details", {}).get("type")
|
||||||
if line["message"]["content"]["content_type"] != "text":
|
break
|
||||||
return
|
elif isinstance(v, dict):
|
||||||
if line["message"]["metadata"]["message_type"] not in ("next", "continue", "variant"):
|
|
||||||
return
|
|
||||||
if line["message"]["recipient"] != "all":
|
|
||||||
return
|
|
||||||
if fields.conversation_id is None:
|
if fields.conversation_id is None:
|
||||||
fields.conversation_id = line["conversation_id"]
|
fields.conversation_id = v.get("conversation_id")
|
||||||
fields.message_id = line["message"]["id"]
|
fields.message_id = v.get("message", {}).get("id")
|
||||||
if "parts" in line["message"]["content"]:
|
c = v.get("message", {}).get("content", {})
|
||||||
yield line["message"]["content"]["parts"][0]
|
if c.get("content_type") == "multimodal_text":
|
||||||
if "finish_details" in line["message"]["metadata"]:
|
generated_images = []
|
||||||
fields.finish_reason = line["message"]["metadata"]["finish_details"]["type"]
|
for element in c.get("parts"):
|
||||||
|
if element.get("content_type") == "image_asset_pointer":
|
||||||
@classmethod
|
generated_images.append(
|
||||||
async def webview_access_token(cls) -> str:
|
cls.get_generated_image(session, cls._headers, element)
|
||||||
window = webview.create_window("OpenAI Chat", cls.url)
|
)
|
||||||
await asyncio.sleep(3)
|
elif element.get("content_type") == "text":
|
||||||
prompt_input = None
|
for part in element.get("parts", []):
|
||||||
while not prompt_input:
|
yield part
|
||||||
try:
|
for image_response in await asyncio.gather(*generated_images):
|
||||||
await asyncio.sleep(1)
|
yield image_response
|
||||||
prompt_input = window.dom.get_element("#prompt-textarea")
|
return
|
||||||
except:
|
if "error" in line and line.get("error"):
|
||||||
...
|
raise RuntimeError(line.get("error"))
|
||||||
window.evaluate_js("""
|
|
||||||
this._fetch = this.fetch;
|
|
||||||
this.fetch = async (url, options) => {
|
|
||||||
const response = await this._fetch(url, options);
|
|
||||||
if (url == "https://chatgpt.com/backend-api/conversation") {
|
|
||||||
this._headers = options.headers;
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
};
|
|
||||||
""")
|
|
||||||
window.evaluate_js("""
|
|
||||||
document.querySelector('.from-token-main-surface-secondary').click();
|
|
||||||
""")
|
|
||||||
headers = None
|
|
||||||
while headers is None:
|
|
||||||
headers = window.evaluate_js("this._headers")
|
|
||||||
await asyncio.sleep(1)
|
|
||||||
headers["User-Agent"] = window.evaluate_js("this.navigator.userAgent")
|
|
||||||
cookies = [list(*cookie.items()) for cookie in window.get_cookies()]
|
|
||||||
window.destroy()
|
|
||||||
cls._cookies = dict([(name, cookie.value) for name, cookie in cookies])
|
|
||||||
cls._headers = headers
|
|
||||||
cls._expires = int(time.time()) + 60 * 60 * 4
|
|
||||||
cls._update_cookie_header()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def nodriver_access_token(cls, proxy: str = None):
|
async def nodriver_access_token(cls, proxy: str = None):
|
||||||
try:
|
if not has_nodriver:
|
||||||
import nodriver as uc
|
|
||||||
except ImportError:
|
|
||||||
return
|
return
|
||||||
try:
|
if has_platformdirs:
|
||||||
from platformdirs import user_config_dir
|
|
||||||
user_data_dir = user_config_dir("g4f-nodriver")
|
user_data_dir = user_config_dir("g4f-nodriver")
|
||||||
except:
|
else:
|
||||||
user_data_dir = None
|
user_data_dir = None
|
||||||
if debug.logging:
|
if debug.logging:
|
||||||
print(f"Open nodriver with user_dir: {user_data_dir}")
|
print(f"Open nodriver with user_dir: {user_data_dir}")
|
||||||
browser = await uc.start(
|
browser = await nodriver.start(
|
||||||
user_data_dir=user_data_dir,
|
user_data_dir=user_data_dir,
|
||||||
browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
|
browser_args=None if proxy is None else [f"--proxy-server={proxy}"],
|
||||||
)
|
)
|
||||||
@ -649,48 +602,6 @@ this.fetch = async (url, options) => {
|
|||||||
cls._create_request_args(cookies, user_agent=user_agent)
|
cls._create_request_args(cookies, user_agent=user_agent)
|
||||||
cls._set_api_key(api_key)
|
cls._set_api_key(api_key)
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def browse_access_token(cls, proxy: str = None, timeout: int = 1200) -> None:
|
|
||||||
"""
|
|
||||||
Browse to obtain an access token.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
proxy (str): Proxy to use for browsing.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
tuple[str, dict]: A tuple containing the access token and cookies.
|
|
||||||
"""
|
|
||||||
driver = get_browser(proxy=proxy)
|
|
||||||
try:
|
|
||||||
driver.get(f"{cls.url}/")
|
|
||||||
WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.ID, "prompt-textarea")))
|
|
||||||
access_token = driver.execute_script(
|
|
||||||
"let session = await fetch('/api/auth/session');"
|
|
||||||
"let data = await session.json();"
|
|
||||||
"let accessToken = data['accessToken'];"
|
|
||||||
"let expires = new Date(); expires.setTime(expires.getTime() + 60 * 60 * 4 * 1000);"
|
|
||||||
"document.cookie = 'access_token=' + accessToken + ';expires=' + expires.toUTCString() + ';path=/';"
|
|
||||||
"return accessToken;"
|
|
||||||
)
|
|
||||||
args = get_args_from_browser(f"{cls.url}/", driver, do_bypass_cloudflare=False)
|
|
||||||
cls._headers = args["headers"]
|
|
||||||
cls._cookies = args["cookies"]
|
|
||||||
cls._update_cookie_header()
|
|
||||||
cls._set_api_key(access_token)
|
|
||||||
finally:
|
|
||||||
driver.close()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
async def fetch_access_token(cls, session: StreamSession, headers: dict):
|
|
||||||
async with session.get(
|
|
||||||
f"{cls.url}/api/auth/session",
|
|
||||||
headers=headers
|
|
||||||
) as response:
|
|
||||||
if response.ok:
|
|
||||||
data = await response.json()
|
|
||||||
if "accessToken" in data:
|
|
||||||
return data["accessToken"]
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_default_headers() -> dict:
|
def get_default_headers() -> dict:
|
||||||
return {
|
return {
|
||||||
|
@ -27,16 +27,18 @@ class arkReq:
|
|||||||
self.arkCookies = arkCookies
|
self.arkCookies = arkCookies
|
||||||
self.userAgent = userAgent
|
self.userAgent = userAgent
|
||||||
|
|
||||||
arkPreURL = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
|
arkoseURL = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
|
||||||
sessionUrl = "https://chatgpt.com/"
|
startUrl = "https://chatgpt.com/"
|
||||||
chatArk: arkReq = None
|
conversationUrl = "https://chatgpt.com/c/"
|
||||||
|
arkoseRequest: arkReq = None
|
||||||
accessToken: str = None
|
accessToken: str = None
|
||||||
cookies: dict = None
|
cookies: dict = None
|
||||||
headers: dict = None
|
headers: dict = None
|
||||||
proofTokens: list = []
|
proofToken: list = []
|
||||||
|
turnstileToken: str = None
|
||||||
|
|
||||||
def readHAR():
|
def readHAR():
|
||||||
global proofTokens
|
global arkoseRequest, accessToken, proofToken, turnstileToken
|
||||||
harPath = []
|
harPath = []
|
||||||
chatArks = []
|
chatArks = []
|
||||||
accessToken = None
|
accessToken = None
|
||||||
@ -58,15 +60,17 @@ def readHAR():
|
|||||||
v_headers = get_headers(v)
|
v_headers = get_headers(v)
|
||||||
try:
|
try:
|
||||||
if "openai-sentinel-proof-token" in v_headers:
|
if "openai-sentinel-proof-token" in v_headers:
|
||||||
proofTokens.append(json.loads(base64.b64decode(
|
proofToken = json.loads(base64.b64decode(
|
||||||
v_headers["openai-sentinel-proof-token"].split("gAAAAAB", 1)[-1].encode()
|
v_headers["openai-sentinel-proof-token"].split("gAAAAAB", 1)[-1].encode()
|
||||||
).decode()))
|
).decode())
|
||||||
|
if "openai-sentinel-turnstile-token" in v_headers:
|
||||||
|
turnstileToken = v_headers["openai-sentinel-turnstile-token"]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if debug.logging:
|
if debug.logging:
|
||||||
print(f"Read proof token: {e}")
|
print(f"Read proof token: {e}")
|
||||||
if arkPreURL in v['request']['url']:
|
if arkoseURL in v['request']['url']:
|
||||||
chatArks.append(parseHAREntry(v))
|
arkoseRequest = parseHAREntry(v)
|
||||||
elif v['request']['url'] == sessionUrl:
|
elif v['request']['url'] == startUrl or v['request']['url'].startswith(conversationUrl):
|
||||||
try:
|
try:
|
||||||
match = re.search(r'"accessToken":"(.*?)"', v["response"]["content"]["text"])
|
match = re.search(r'"accessToken":"(.*?)"', v["response"]["content"]["text"])
|
||||||
if match:
|
if match:
|
||||||
@ -78,8 +82,8 @@ def readHAR():
|
|||||||
if not accessToken:
|
if not accessToken:
|
||||||
raise NoValidHarFileError("No accessToken found in .har files")
|
raise NoValidHarFileError("No accessToken found in .har files")
|
||||||
if not chatArks:
|
if not chatArks:
|
||||||
return None, accessToken, cookies, headers
|
return cookies, headers
|
||||||
return chatArks.pop(), accessToken, cookies, headers
|
return cookies, headers
|
||||||
|
|
||||||
def get_headers(entry) -> dict:
|
def get_headers(entry) -> dict:
|
||||||
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(':')}
|
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(':')}
|
||||||
@ -110,7 +114,7 @@ def genArkReq(chatArk: arkReq) -> arkReq:
|
|||||||
tmpArk.arkHeader['x-ark-esync-value'] = bw
|
tmpArk.arkHeader['x-ark-esync-value'] = bw
|
||||||
return tmpArk
|
return tmpArk
|
||||||
|
|
||||||
async def sendRequest(tmpArk: arkReq, proxy: str = None):
|
async def sendRequest(tmpArk: arkReq, proxy: str = None) -> str:
|
||||||
async with StreamSession(headers=tmpArk.arkHeader, cookies=tmpArk.arkCookies, proxies={"https": proxy}) as session:
|
async with StreamSession(headers=tmpArk.arkHeader, cookies=tmpArk.arkCookies, proxies={"https": proxy}) as session:
|
||||||
async with session.post(tmpArk.arkURL, data=tmpArk.arkBody) as response:
|
async with session.post(tmpArk.arkURL, data=tmpArk.arkBody) as response:
|
||||||
data = await response.json()
|
data = await response.json()
|
||||||
@ -144,10 +148,10 @@ def getN() -> str:
|
|||||||
return base64.b64encode(timestamp.encode()).decode()
|
return base64.b64encode(timestamp.encode()).decode()
|
||||||
|
|
||||||
async def getArkoseAndAccessToken(proxy: str) -> tuple[str, str, dict, dict]:
|
async def getArkoseAndAccessToken(proxy: str) -> tuple[str, str, dict, dict]:
|
||||||
global chatArk, accessToken, cookies, headers, proofTokens
|
global arkoseRequest, accessToken, cookies, headers, proofToken, turnstileToken
|
||||||
if chatArk is None or accessToken is None:
|
if arkoseRequest is None or accessToken is None:
|
||||||
chatArk, accessToken, cookies, headers = readHAR()
|
cookies, headers = readHAR()
|
||||||
if chatArk is None:
|
if arkoseRequest is None:
|
||||||
return None, accessToken, cookies, headers, proofTokens
|
return None, accessToken, cookies, headers, proofToken, turnstileToken
|
||||||
newReq = genArkReq(chatArk)
|
newReq = genArkReq(arkoseRequest)
|
||||||
return await sendRequest(newReq, proxy), accessToken, cookies, headers, proofTokens
|
return await sendRequest(newReq, proxy), accessToken, cookies, headers, proofToken, turnstileToken
|
||||||
|
@ -4,18 +4,16 @@ import json
|
|||||||
import base64
|
import base64
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
def generate_proof_token(required: bool, seed: str = "", difficulty: str = "", user_agent: str = None, proofTokens: list = None):
|
def generate_proof_token(required: bool, seed: str = "", difficulty: str = "", user_agent: str = None, proofToken: str = None):
|
||||||
if not required:
|
if not required:
|
||||||
return
|
return
|
||||||
|
|
||||||
if proofTokens:
|
if proofToken is None:
|
||||||
config = proofTokens[-1]
|
|
||||||
else:
|
|
||||||
screen = random.choice([3008, 4010, 6000]) * random.choice([1, 2, 4])
|
screen = random.choice([3008, 4010, 6000]) * random.choice([1, 2, 4])
|
||||||
# Get current UTC time
|
# Get current UTC time
|
||||||
now_utc = datetime.now(timezone.utc)
|
now_utc = datetime.now(timezone.utc)
|
||||||
parse_time = now_utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
parse_time = now_utc.strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||||
config = [
|
proofToken = [
|
||||||
screen, parse_time,
|
screen, parse_time,
|
||||||
None, 0, user_agent,
|
None, 0, user_agent,
|
||||||
"https://tcr9i.chat.openai.com/v2/35536E1E-65B4-4D96-9D97-6ADB7EFF8147/api.js",
|
"https://tcr9i.chat.openai.com/v2/35536E1E-65B4-4D96-9D97-6ADB7EFF8147/api.js",
|
||||||
@ -28,8 +26,8 @@ def generate_proof_token(required: bool, seed: str = "", difficulty: str = "", u
|
|||||||
|
|
||||||
diff_len = len(difficulty)
|
diff_len = len(difficulty)
|
||||||
for i in range(100000):
|
for i in range(100000):
|
||||||
config[3] = i
|
proofToken[3] = i
|
||||||
json_data = json.dumps(config)
|
json_data = json.dumps(proofToken)
|
||||||
base = base64.b64encode(json_data.encode()).decode()
|
base = base64.b64encode(json_data.encode()).decode()
|
||||||
hash_value = hashlib.sha3_512((seed + base).encode()).digest()
|
hash_value = hashlib.sha3_512((seed + base).encode()).digest()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user