mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
Refactor Cloudflare and LMArena providers to enhance authentication handling and improve WebSocket communication
This commit is contained in:
parent
63315df501
commit
da6c00e2a2
6 changed files with 58 additions and 74 deletions
57
.gitignore
vendored
57
.gitignore
vendored
|
|
@ -1,48 +1,11 @@
|
||||||
# Default ignored files
|
bin
|
||||||
/shelf/
|
dist
|
||||||
/workspace.xml
|
__pycache__
|
||||||
# Editor-based HTTP Client requests
|
generated_media
|
||||||
/httpRequests/
|
site-packages
|
||||||
# Datasource local storage ignored files
|
projects
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
|
|
||||||
# Ignore local python virtual environment
|
|
||||||
venv/
|
|
||||||
|
|
||||||
# Ignore streamlit_chat_app.py conversations pickle
|
|
||||||
conversations.pkl
|
|
||||||
*.pkl
|
|
||||||
.idea/
|
|
||||||
**/__pycache__/
|
|
||||||
__pycache__/
|
|
||||||
|
|
||||||
*.log
|
|
||||||
*.pyc
|
|
||||||
*.egg-info/
|
|
||||||
*.egg
|
|
||||||
*.egg-info
|
|
||||||
.DS_Store
|
|
||||||
*~
|
|
||||||
*.gguf
|
|
||||||
.buildozer
|
|
||||||
har_and_cookies
|
|
||||||
node_modules
|
node_modules
|
||||||
models
|
g4f.egg-info
|
||||||
projects/windows/g4f
|
models/models.json
|
||||||
generated_images/
|
pyvenv.cfg
|
||||||
generated_media/
|
lib64
|
||||||
projects/windows/
|
|
||||||
|
|
||||||
*.bak
|
|
||||||
*.backup
|
|
||||||
.env
|
|
||||||
g4f.dev/
|
|
||||||
|
|
||||||
# Build artifacts
|
|
||||||
build/
|
|
||||||
dist/
|
|
||||||
*.spec
|
|
||||||
pyproject.toml.bak
|
|
||||||
debian/
|
|
||||||
winget/
|
|
||||||
|
|
|
||||||
|
|
@ -568,15 +568,22 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
|
||||||
pass
|
pass
|
||||||
elif has_nodriver or cls.share_url is None:
|
elif has_nodriver or cls.share_url is None:
|
||||||
async def callback(page):
|
async def callback(page):
|
||||||
element = await page.select('[style="display: grid;"]')
|
|
||||||
if element:
|
|
||||||
await click_trunstile(page, 'document.querySelector(\'[style="display: grid;"]\')')
|
|
||||||
await page.find("Ask anything…", 120)
|
|
||||||
button = await page.find("Accept Cookies")
|
button = await page.find("Accept Cookies")
|
||||||
if button:
|
if button:
|
||||||
await button.click()
|
await button.click()
|
||||||
else:
|
else:
|
||||||
debug.log("No 'Accept Cookies' button found, skipping.")
|
debug.log("No 'Accept Cookies' button found, skipping.")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
textarea = await page.find("Ask anything…")
|
||||||
|
if textarea:
|
||||||
|
await textarea.send_keys("Hello")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
button = await page.select('[type="submit"]:has([data-sentry-element="ArrowUp"])')
|
||||||
|
if button:
|
||||||
|
await button.click()
|
||||||
|
element = await page.select('[style="display: grid;"]')
|
||||||
|
if element:
|
||||||
|
await click_trunstile(page, 'document.querySelector(\'[style="display: grid;"]\')')
|
||||||
if not await page.evaluate('document.cookie.indexOf("arena-auth-prod-v1") >= 0'):
|
if not await page.evaluate('document.cookie.indexOf("arena-auth-prod-v1") >= 0'):
|
||||||
debug.log("No authentication cookie found, trying to authenticate.")
|
debug.log("No authentication cookie found, trying to authenticate.")
|
||||||
await page.select('#cf-turnstile', 300)
|
await page.select('#cf-turnstile', 300)
|
||||||
|
|
@ -628,7 +635,7 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
|
||||||
elif model in cls.image_models:
|
elif model in cls.image_models:
|
||||||
model_id = cls.image_models[model]
|
model_id = cls.image_models[model]
|
||||||
else:
|
else:
|
||||||
raise ModelNotFoundError(f"Model '{model}' is not supported by LMArena Beta.")
|
raise ModelNotFoundError(f"Model '{model}' is not supported by LMArena provider.")
|
||||||
|
|
||||||
userMessageId = str(uuid.uuid7())
|
userMessageId = str(uuid.uuid7())
|
||||||
modelAMessageId = str(uuid.uuid7())
|
modelAMessageId = str(uuid.uuid7())
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from aiohttp import ClientSession, ClientTimeout
|
from aiohttp import ClientSession, ClientTimeout
|
||||||
|
|
@ -10,13 +11,13 @@ from aiohttp import ClientSession
|
||||||
try:
|
try:
|
||||||
import nodriver
|
import nodriver
|
||||||
from nodriver.core.connection import ProtocolException
|
from nodriver.core.connection import ProtocolException
|
||||||
|
has_nodriver = True
|
||||||
except:
|
except:
|
||||||
pass
|
has_nodriver = False
|
||||||
|
|
||||||
from ...typing import Messages, AsyncResult
|
from ...typing import Messages, AsyncResult
|
||||||
from ...providers.response import VideoResponse, Reasoning, ContinueResponse, ProviderInfo
|
from ...providers.response import VideoResponse, Reasoning, ContinueResponse, ProviderInfo
|
||||||
from ...requests import get_nodriver
|
from ...requests import get_nodriver
|
||||||
from ...errors import MissingRequirementsError
|
|
||||||
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
|
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
|
||||||
from ..helper import format_media_prompt
|
from ..helper import format_media_prompt
|
||||||
from ... import debug
|
from ... import debug
|
||||||
|
|
@ -53,7 +54,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
"sora": "https://sora.chatgpt.com/explore",
|
"sora": "https://sora.chatgpt.com/explore",
|
||||||
#"veo": "https://aistudio.google.com/generate-video"
|
#"veo": "https://aistudio.google.com/generate-video"
|
||||||
}
|
}
|
||||||
api_url = f"{PUBLIC_URL}/backend-api/v2/create?provider=Video&cache=true&prompt="
|
api_path = f"?provider=Video&cache=true&prompt="
|
||||||
drive_url = "https://www.googleapis.com/drive/v3/"
|
drive_url = "https://www.googleapis.com/drive/v3/"
|
||||||
|
|
||||||
active_by_default = True
|
active_by_default = True
|
||||||
|
|
@ -62,10 +63,11 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
video_models = models
|
video_models = models
|
||||||
|
|
||||||
needs_auth = True
|
needs_auth = True
|
||||||
working = True
|
working = has_nodriver
|
||||||
|
|
||||||
browser = None
|
browser = None
|
||||||
stop_browser = None
|
stop_browser = None
|
||||||
|
share_url: Optional[str] = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def create_async_generator(
|
async def create_async_generator(
|
||||||
|
|
@ -77,6 +79,8 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
aspect_ratio: str = None,
|
aspect_ratio: str = None,
|
||||||
**kwargs
|
**kwargs
|
||||||
) -> AsyncResult:
|
) -> AsyncResult:
|
||||||
|
if cls.share_url is None:
|
||||||
|
cls.share_url = os.getenv("G4F_SHARE_URL")
|
||||||
if not model:
|
if not model:
|
||||||
model = cls.default_model
|
model = cls.default_model
|
||||||
if model not in cls.video_models:
|
if model not in cls.video_models:
|
||||||
|
|
@ -94,10 +98,12 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
yield Reasoning(label="Open browser")
|
yield Reasoning(label="Open browser")
|
||||||
browser, stop_browser = await get_nodriver(proxy=proxy)
|
browser, stop_browser = await get_nodriver(proxy=proxy)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if cls.share_url is None:
|
||||||
|
raise
|
||||||
debug.error(f"Error getting nodriver:", e)
|
debug.error(f"Error getting nodriver:", e)
|
||||||
async with ClientSession() as session:
|
async with ClientSession() as session:
|
||||||
yield Reasoning(label="Generating")
|
yield Reasoning(label="Generating")
|
||||||
async with session.get(cls.api_url + quote(prompt)) as response:
|
async with session.get(f"{cls.share_url}{cls.api_path + quote(prompt)}") as response:
|
||||||
if not response.ok:
|
if not response.ok:
|
||||||
debug.error(f"Failed to generate Video: {response.status}")
|
debug.error(f"Failed to generate Video: {response.status}")
|
||||||
else:
|
else:
|
||||||
|
|
@ -108,7 +114,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
return
|
return
|
||||||
yield VideoResponse(str(response.url), prompt)
|
yield VideoResponse(str(response.url), prompt)
|
||||||
return
|
return
|
||||||
raise MissingRequirementsError("Video provider requires a browser to be installed.")
|
raise
|
||||||
page = None
|
page = None
|
||||||
try:
|
try:
|
||||||
yield ContinueResponse("Timeout waiting for Video URL")
|
yield ContinueResponse("Timeout waiting for Video URL")
|
||||||
|
|
@ -123,7 +129,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
RequestConfig.headers = {}
|
RequestConfig.headers = {}
|
||||||
for key, value in event.request.headers.items():
|
for key, value in event.request.headers.items():
|
||||||
RequestConfig.headers[key.lower()] = value
|
RequestConfig.headers[key.lower()] = value
|
||||||
for _, urls in RequestConfig.urls.items():
|
for urls in RequestConfig.urls.values():
|
||||||
if event.request.url in urls:
|
if event.request.url in urls:
|
||||||
return
|
return
|
||||||
debug.log(f"Adding URL: {event.request.url}")
|
debug.log(f"Adding URL: {event.request.url}")
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ class QwenCode(OpenaiTemplate):
|
||||||
needs_auth = True
|
needs_auth = True
|
||||||
active_by_default = True
|
active_by_default = True
|
||||||
default_model = "qwen3-coder-plus"
|
default_model = "qwen3-coder-plus"
|
||||||
default_vision_model = "qwen-vl-max-latest"
|
models = [default_model]
|
||||||
models = [default_model, default_vision_model]
|
|
||||||
vision_models = [default_vision_model]
|
|
||||||
client = QwenContentGenerator(QwenOAuth2Client())
|
client = QwenContentGenerator(QwenOAuth2Client())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
@ -48,9 +46,12 @@ class QwenCode(OpenaiTemplate):
|
||||||
api_base=creds.get("endpoint", api_base),
|
api_base=creds.get("endpoint", api_base),
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
if chunk != last_chunk:
|
if isinstance(chunk, str):
|
||||||
|
if chunk != last_chunk:
|
||||||
|
yield chunk
|
||||||
|
last_chunk = chunk
|
||||||
|
else:
|
||||||
yield chunk
|
yield chunk
|
||||||
last_chunk = chunk
|
|
||||||
except TokenManagerError:
|
except TokenManagerError:
|
||||||
await cls.client.shared_manager.getValidCredentials(cls.client.qwen_client, True)
|
await cls.client.shared_manager.getValidCredentials(cls.client.qwen_client, True)
|
||||||
creds = await cls.client.get_valid_token()
|
creds = await cls.client.get_valid_token()
|
||||||
|
|
@ -62,8 +63,11 @@ class QwenCode(OpenaiTemplate):
|
||||||
api_base=creds.get("endpoint"),
|
api_base=creds.get("endpoint"),
|
||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
if chunk != last_chunk:
|
if isinstance(chunk, str):
|
||||||
|
if chunk != last_chunk:
|
||||||
|
yield chunk
|
||||||
|
last_chunk = chunk
|
||||||
|
else:
|
||||||
yield chunk
|
yield chunk
|
||||||
last_chunk = chunk
|
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
|
|
@ -239,8 +239,7 @@ class Api:
|
||||||
user_g4f_api_key = await self.get_g4f_api_key(request)
|
user_g4f_api_key = await self.get_g4f_api_key(request)
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
user_g4f_api_key = await self.security(request)
|
user_g4f_api_key = await self.security(request)
|
||||||
if hasattr(user_g4f_api_key, "credentials"):
|
user_g4f_api_key = getattr(user_g4f_api_key, "credentials", user_g4f_api_key)
|
||||||
user_g4f_api_key = user_g4f_api_key.credentials
|
|
||||||
if AppConfig.demo and user is None:
|
if AppConfig.demo and user is None:
|
||||||
ip = request.headers.get("X-Forwarded-For", "")[:4].strip(":.")
|
ip = request.headers.get("X-Forwarded-For", "")[:4].strip(":.")
|
||||||
country = request.headers.get("Cf-Ipcountry", "")
|
country = request.headers.get("Cf-Ipcountry", "")
|
||||||
|
|
@ -265,14 +264,14 @@ class Api:
|
||||||
debug.log(f"User: '{user}' G4F API key expires in {hours}h {minutes}m {seconds}s")
|
debug.log(f"User: '{user}' G4F API key expires in {hours}h {minutes}m {seconds}s")
|
||||||
if expires < 0:
|
if expires < 0:
|
||||||
return ErrorResponse.from_message("G4F API key expired", HTTP_401_UNAUTHORIZED)
|
return ErrorResponse.from_message("G4F API key expired", HTTP_401_UNAUTHORIZED)
|
||||||
|
count = 0
|
||||||
|
for char in user:
|
||||||
|
if char.isupper():
|
||||||
|
count += 1
|
||||||
|
if count > 4:
|
||||||
|
return ErrorResponse.from_message("Invalid user name (screaming)", HTTP_401_UNAUTHORIZED)
|
||||||
else:
|
else:
|
||||||
user = "admin"
|
user = "admin"
|
||||||
count = 0
|
|
||||||
for char in string:
|
|
||||||
if char.isupper():
|
|
||||||
count += 1
|
|
||||||
if count > 4:
|
|
||||||
return ErrorResponse.from_message("Invalid user name", HTTP_401_UNAUTHORIZED)
|
|
||||||
path = request.url.path
|
path = request.url.path
|
||||||
if path.startswith("/v1") or path.startswith("/api/") or (AppConfig.demo and path == '/backend-api/v2/upload_cookies'):
|
if path.startswith("/v1") or path.startswith("/api/") or (AppConfig.demo and path == '/backend-api/v2/upload_cookies'):
|
||||||
if request.method != "OPTIONS" and not path.endswith("/models"):
|
if request.method != "OPTIONS" and not path.endswith("/models"):
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,11 @@ def is_data_an_media(data, filename: str = None) -> str:
|
||||||
return content_type
|
return content_type
|
||||||
if isinstance(data, bytes):
|
if isinstance(data, bytes):
|
||||||
return is_accepted_format(data)
|
return is_accepted_format(data)
|
||||||
|
if isinstance(data, str) and data.startswith("http"):
|
||||||
|
path = urlparse(data).path
|
||||||
|
extension = get_extension(path)
|
||||||
|
if extension is not None:
|
||||||
|
return EXTENSIONS_MAP[extension]
|
||||||
return is_data_uri_an_image(data)
|
return is_data_uri_an_image(data)
|
||||||
|
|
||||||
def is_valid_media(data: ImageType = None, filename: str = None) -> str:
|
def is_valid_media(data: ImageType = None, filename: str = None) -> str:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue