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

XFEstudio/gpt4free

Refactor Cloudflare and LMArena providers to enhance authentication handling and improve WebSocket communication

da6c00e2
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

6 个文件 +58 -74
Modified .gitignore +10 -47
@@ -1,48 +1,11 @@
1 # Default ignored files
2 /shelf/
3 /workspace.xml
4 # Editor-based HTTP Client requests
5 /httpRequests/
6 # Datasource local storage ignored files
7 /dataSources/
8 /dataSources.local.xml
9
10 # Ignore local python virtual environment
11 venv/
12
13 # Ignore streamlit_chat_app.py conversations pickle
14 conversations.pkl
15 *.pkl
16 .idea/
17 **/__pycache__/
18 __pycache__/
19
20 *.log
21 *.pyc
22 *.egg-info/
23 *.egg
24 *.egg-info
25 .DS_Store
26 *~
27 *.gguf
28 .buildozer
29 har_and_cookies
1 bin
2 dist
3 __pycache__
4 generated_media
5 site-packages
6 projects
30 7 node_modules
31 models
32 projects/windows/g4f
33 generated_images/
34 generated_media/
35 projects/windows/
36
37 *.bak
38 *.backup
39 .env
40 g4f.dev/
41
42 # Build artifacts
43 build/
44 dist/
45 *.spec
46 pyproject.toml.bak
47 debian/
48 winget/
8 g4f.egg-info
9 models/models.json
10 pyvenv.cfg
11 lib64
Modified g4f/Provider/needs_auth/LMArena.py +12 -5
@@ -568,15 +568,22 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
568 568 pass
569 569 elif has_nodriver or cls.share_url is None:
570 570 async def callback(page):
571 element = await page.select('[style="display: grid;"]')
572 if element:
573 await click_trunstile(page, 'document.querySelector(\'[style="display: grid;"]\')')
574 await page.find("Ask anything…", 120)
575 571 button = await page.find("Accept Cookies")
576 572 if button:
577 573 await button.click()
578 574 else:
579 575 debug.log("No 'Accept Cookies' button found, skipping.")
576 await asyncio.sleep(1)
577 textarea = await page.find("Ask anything…")
578 if textarea:
579 await textarea.send_keys("Hello")
580 await asyncio.sleep(1)
581 button = await page.select('[type="submit"]:has([data-sentry-element="ArrowUp"])')
582 if button:
583 await button.click()
584 element = await page.select('[style="display: grid;"]')
585 if element:
586 await click_trunstile(page, 'document.querySelector(\'[style="display: grid;"]\')')
580 587 if not await page.evaluate('document.cookie.indexOf("arena-auth-prod-v1") >= 0'):
581 588 debug.log("No authentication cookie found, trying to authenticate.")
582 589 await page.select('#cf-turnstile', 300)
@@ -628,7 +635,7 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
628 635 elif model in cls.image_models:
629 636 model_id = cls.image_models[model]
630 637 else:
631 raise ModelNotFoundError(f"Model '{model}' is not supported by LMArena Beta.")
638 raise ModelNotFoundError(f"Model '{model}' is not supported by LMArena provider.")
632 639
633 640 userMessageId = str(uuid.uuid7())
634 641 modelAMessageId = str(uuid.uuid7())
Modified g4f/Provider/needs_auth/Video.py +13 -7
@@ -1,5 +1,6 @@
1 1 from __future__ import annotations
2 2
3 import os
3 4 import asyncio
4 5 from typing import Optional
5 6 from aiohttp import ClientSession, ClientTimeout
@@ -10,13 +11,13 @@ from aiohttp import ClientSession
10 11 try:
11 12 import nodriver
12 13 from nodriver.core.connection import ProtocolException
14 has_nodriver = True
13 15 except:
14 pass
16 has_nodriver = False
15 17
16 18 from ...typing import Messages, AsyncResult
17 19 from ...providers.response import VideoResponse, Reasoning, ContinueResponse, ProviderInfo
18 20 from ...requests import get_nodriver
19 from ...errors import MissingRequirementsError
20 21 from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
21 22 from ..helper import format_media_prompt
22 23 from ... import debug
@@ -53,7 +54,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
53 54 "sora": "https://sora.chatgpt.com/explore",
54 55 #"veo": "https://aistudio.google.com/generate-video"
55 56 }
56 api_url = f"{PUBLIC_URL}/backend-api/v2/create?provider=Video&cache=true&prompt="
57 api_path = f"?provider=Video&cache=true&prompt="
57 58 drive_url = "https://www.googleapis.com/drive/v3/"
58 59
59 60 active_by_default = True
@@ -62,10 +63,11 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
62 63 video_models = models
63 64
64 65 needs_auth = True
65 working = True
66 working = has_nodriver
66 67
67 68 browser = None
68 69 stop_browser = None
70 share_url: Optional[str] = None
69 71
70 72 @classmethod
71 73 async def create_async_generator(
@@ -77,6 +79,8 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
77 79 aspect_ratio: str = None,
78 80 **kwargs
79 81 ) -> AsyncResult:
82 if cls.share_url is None:
83 cls.share_url = os.getenv("G4F_SHARE_URL")
80 84 if not model:
81 85 model = cls.default_model
82 86 if model not in cls.video_models:
@@ -94,10 +98,12 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
94 98 yield Reasoning(label="Open browser")
95 99 browser, stop_browser = await get_nodriver(proxy=proxy)
96 100 except Exception as e:
101 if cls.share_url is None:
102 raise
97 103 debug.error(f"Error getting nodriver:", e)
98 104 async with ClientSession() as session:
99 105 yield Reasoning(label="Generating")
100 async with session.get(cls.api_url + quote(prompt)) as response:
106 async with session.get(f"{cls.share_url}{cls.api_path + quote(prompt)}") as response:
101 107 if not response.ok:
102 108 debug.error(f"Failed to generate Video: {response.status}")
103 109 else:
@@ -108,7 +114,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
108 114 return
109 115 yield VideoResponse(str(response.url), prompt)
110 116 return
111 raise MissingRequirementsError("Video provider requires a browser to be installed.")
117 raise
112 118 page = None
113 119 try:
114 120 yield ContinueResponse("Timeout waiting for Video URL")
@@ -123,7 +129,7 @@ class Video(AsyncGeneratorProvider, ProviderModelMixin):
123 129 RequestConfig.headers = {}
124 130 for key, value in event.request.headers.items():
125 131 RequestConfig.headers[key.lower()] = value
126 for _, urls in RequestConfig.urls.items():
132 for urls in RequestConfig.urls.values():
127 133 if event.request.url in urls:
128 134 return
129 135 debug.log(f"Adding URL: {event.request.url}")
Modified g4f/Provider/qwen/QwenCode.py +11 -7
@@ -14,9 +14,7 @@ class QwenCode(OpenaiTemplate):
14 14 needs_auth = True
15 15 active_by_default = True
16 16 default_model = "qwen3-coder-plus"
17 default_vision_model = "qwen-vl-max-latest"
18 models = [default_model, default_vision_model]
19 vision_models = [default_vision_model]
17 models = [default_model]
20 18 client = QwenContentGenerator(QwenOAuth2Client())
21 19
22 20 @classmethod
@@ -48,9 +46,12 @@ class QwenCode(OpenaiTemplate):
48 46 api_base=creds.get("endpoint", api_base),
49 47 **kwargs
50 48 ):
51 if chunk != last_chunk:
49 if isinstance(chunk, str):
50 if chunk != last_chunk:
51 yield chunk
52 last_chunk = chunk
53 else:
52 54 yield chunk
53 last_chunk = chunk
54 55 except TokenManagerError:
55 56 await cls.client.shared_manager.getValidCredentials(cls.client.qwen_client, True)
56 57 creds = await cls.client.get_valid_token()
@@ -62,8 +63,11 @@ class QwenCode(OpenaiTemplate):
62 63 api_base=creds.get("endpoint"),
63 64 **kwargs
64 65 ):
65 if chunk != last_chunk:
66 if isinstance(chunk, str):
67 if chunk != last_chunk:
68 yield chunk
69 last_chunk = chunk
70 else:
66 71 yield chunk
67 last_chunk = chunk
68 72 except:
69 73 raise
Modified g4f/api/__init__.py +7 -8
@@ -239,8 +239,7 @@ class Api:
239 239 user_g4f_api_key = await self.get_g4f_api_key(request)
240 240 except HTTPException:
241 241 user_g4f_api_key = await self.security(request)
242 if hasattr(user_g4f_api_key, "credentials"):
243 user_g4f_api_key = user_g4f_api_key.credentials
242 user_g4f_api_key = getattr(user_g4f_api_key, "credentials", user_g4f_api_key)
244 243 if AppConfig.demo and user is None:
245 244 ip = request.headers.get("X-Forwarded-For", "")[:4].strip(":.")
246 245 country = request.headers.get("Cf-Ipcountry", "")
@@ -265,14 +264,14 @@ class Api:
265 264 debug.log(f"User: '{user}' G4F API key expires in {hours}h {minutes}m {seconds}s")
266 265 if expires < 0:
267 266 return ErrorResponse.from_message("G4F API key expired", HTTP_401_UNAUTHORIZED)
267 count = 0
268 for char in user:
269 if char.isupper():
270 count += 1
271 if count > 4:
272 return ErrorResponse.from_message("Invalid user name (screaming)", HTTP_401_UNAUTHORIZED)
268 273 else:
269 274 user = "admin"
270 count = 0
271 for char in string:
272 if char.isupper():
273 count += 1
274 if count > 4:
275 return ErrorResponse.from_message("Invalid user name", HTTP_401_UNAUTHORIZED)
276 275 path = request.url.path
277 276 if path.startswith("/v1") or path.startswith("/api/") or (AppConfig.demo and path == '/backend-api/v2/upload_cookies'):
278 277 if request.method != "OPTIONS" and not path.endswith("/models"):
Modified g4f/image/__init__.py +5 -0
@@ -107,6 +107,11 @@ def is_data_an_media(data, filename: str = None) -> str:
107 107 return content_type
108 108 if isinstance(data, bytes):
109 109 return is_accepted_format(data)
110 if isinstance(data, str) and data.startswith("http"):
111 path = urlparse(data).path
112 extension = get_extension(path)
113 if extension is not None:
114 return EXTENSIONS_MAP[extension]
110 115 return is_data_uri_an_image(data)
111 116
112 117 def is_valid_media(data: ImageType = None, filename: str = None) -> str: