Refactor OpenaiChat authentication flow; replace get_nodriver with async context manager and improve error handling

Update backend_anon_url in har_file.py for correct endpoint
Add async context manager for get_nodriver_session in requests module
Fix start-browser.sh to remove stale cookie file before launching Chrome
This commit is contained in:
hlohaus
2025-10-02 02:08:20 +02:00
parent 7d184411e2
commit 4399b432c4
4 changed files with 27 additions and 12 deletions

View File

@@ -21,7 +21,7 @@ from ..base_provider import AsyncAuthedProvider, ProviderModelMixin
from ...typing import AsyncResult, Messages, Cookies, MediaListType
from ...requests.raise_for_status import raise_for_status
from ...requests import StreamSession
from ...requests import get_nodriver
from ...requests import get_nodriver_session
from ...image import ImageRequest, to_image, to_bytes, is_accepted_format, detect_file_type
from ...errors import MissingAuthError, NoValidHarFileError, ModelNotFoundError
from ...providers.response import JsonConversation, FinishReason, SynthesizeData, AuthResult, ImageResponse, ImagePreview, ResponseType, format_link
@@ -852,8 +852,7 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
@classmethod
async def nodriver_auth(cls, proxy: str = None):
browser, stop_browser = await get_nodriver(proxy=proxy)
try:
async with get_nodriver_session(proxy=proxy) as browser:
page = await browser.get(cls.url)
def on_request(event: nodriver.cdp.network.RequestWillBeSent, page=None):
if event.request.url == start_url or event.request.url.startswith(conversation_url):
@@ -882,14 +881,21 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request)
await page.reload()
user_agent = await page.evaluate("window.navigator.userAgent", return_by_value=True)
if cls.needs_auth:
await page.select('[data-testid="accounts-profile-button"]', 300)
textarea = await page.select("#prompt-textarea", 300)
await textarea.send_keys("Hello")
await asyncio.sleep(1)
debug.log(f"OpenaiChat: User-Agent: {user_agent}")
for _ in range(3):
try:
if cls.needs_auth:
await page.select('[data-testid="accounts-profile-button"]', 300)
textarea = await page.select("#prompt-textarea", 300)
await textarea.send_keys("Hello")
await asyncio.sleep(1)
except nodriver.core.connection.ProtocolException:
continue
break
button = await page.select("[data-testid=\"send-button\"]")
if button:
await button.click()
debug.log("OpenaiChat: 'Hello' sended")
while True:
body = await page.evaluate("JSON.stringify(window.__remixContext)", return_by_value=True)
if hasattr(body, "value"):
@@ -902,17 +908,19 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
if cls._api_key is not None or not cls.needs_auth:
break
await asyncio.sleep(1)
debug.log(f"OpenaiChat: Access token: {'False' if cls._api_key is None else cls._api_key[:12]+'...'}")
while True:
if cls.request_config.proof_token:
break
await asyncio.sleep(1)
debug.log(f"OpenaiChat: Proof token: Yes")
cls.request_config.data_build = await page.evaluate("document.documentElement.getAttribute('data-build')")
cls.request_config.cookies = await page.send(get_cookies([cls.url]))
await page.close()
cls._create_request_args(cls.request_config.cookies, cls.request_config.headers, user_agent=user_agent)
cls._set_api_key(cls._api_key)
finally:
stop_browser()
debug.log(f"OpenaiChat: Sleep 10s")
await asyncio.sleep(10)
@staticmethod
def get_default_headers() -> Dict[str, str]:

View File

@@ -19,7 +19,7 @@ from ... import debug
arkose_url = "https://tcr9i.chat.openai.com/fc/gt2/public_key/35536E1E-65B4-4D96-9D97-6ADB7EFF8147"
backend_url = "https://chatgpt.com/backend-api/f/conversation"
prepare_url = "https://chatgpt.com/backend-api/f/conversation/prepare"
backend_anon_url = "https://chatgpt.com/backend-anon/conversation"
backend_anon_url = "https://chatgpt.com/backend-anon/f/conversation"
start_url = "https://chatgpt.com/"
conversation_url = "https://chatgpt.com/c/"

View File

@@ -8,6 +8,7 @@ from urllib.parse import urlparse
from typing import Iterator, AsyncIterator
from http.cookies import Morsel
from pathlib import Path
from contextlib import asynccontextmanager
import asyncio
try:
from curl_cffi.requests import Session, Response
@@ -218,6 +219,12 @@ async def get_nodriver(
BrowserConfig.stop_browser = on_stop
return browser, on_stop
@asynccontextmanager
async def get_nodriver_session(**kwargs):
browser, stop_browser = await get_nodriver(**kwargs)
yield browser
stop_browser()
async def sse_stream(iter_lines: AsyncIterator[bytes]) -> AsyncIterator[dict]:
if hasattr(iter_lines, "content"):
iter_lines = iter_lines.content

View File

@@ -2,5 +2,5 @@
while true; do
sleep 5
rm ~/.config/g4f/cookies/.nodriver_is_open
google-chrome --remote-allow-origins=* --no-first-run --no-service-autorun --no-default-browser-check --homepage=about:blank --no-pings --password-store=basic --disable-infobars --disable-breakpad --disable-dev-shm-usage --disable-session-crashed-bubble --disable-search-engine-choice-screen --user-data-dir="~/.config/g4f-nodriver" --disable-session-crashed-bubble --disable-features=IsolateOrigins,site-per-process --no-sandbox --remote-debugging-host=127.0.0.1 --remote-debugging-port=57011
google-chrome --remote-allow-origins=* --no-first-run --no-service-autorun --no-default-browser-check --homepage=about:blank --no-pings --password-store=basic --disable-infobars --disable-breakpad --disable-dev-shm-usage --disable-session-crashed-bubble --disable-search-engine-choice-screen --user-data-dir="~/.config/g4f-nodriver" --disable-session-crashed-bubble --disable-features=IsolateOrigins,site-per-process --remote-debugging-host=127.0.0.1 --remote-debugging-port=57011
done