mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
Move raise_for_status, Create FormData wrapper
This commit is contained in:
parent
8cc6000ffb
commit
b7eee50930
7 changed files with 118 additions and 50 deletions
|
|
@ -5,7 +5,7 @@ import json
|
||||||
import base64
|
import base64
|
||||||
import uuid
|
import uuid
|
||||||
try:
|
try:
|
||||||
from curl_cffi import CurlMime
|
from ..requests.curl_cffi import FormData
|
||||||
has_curl_cffi = True
|
has_curl_cffi = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_curl_cffi = False
|
has_curl_cffi = False
|
||||||
|
|
@ -123,13 +123,11 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
|
||||||
) as response:
|
) as response:
|
||||||
await raise_for_status(response)
|
await raise_for_status(response)
|
||||||
upload_nonce = await response.text()
|
upload_nonce = await response.text()
|
||||||
#data = FormData()
|
data = FormData()
|
||||||
#data.add_field('file', file, filename=filename)
|
data.add_field('file', file, filename=filename)
|
||||||
multipart = CurlMime()
|
|
||||||
multipart.addpart(name="file", filename=filename, data=file)
|
|
||||||
async with client.post(
|
async with client.post(
|
||||||
f"{cls.url}/api/upload",
|
f"{cls.url}/api/upload",
|
||||||
multipart=multipart,
|
data=data,
|
||||||
headers={
|
headers={
|
||||||
"X-Upload-Nonce": upload_nonce,
|
"X-Upload-Nonce": upload_nonce,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,39 @@
|
||||||
import webview
|
import webview
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from platformdirs import user_config_dir
|
try:
|
||||||
|
from platformdirs import user_config_dir
|
||||||
|
has_platformdirs = True
|
||||||
|
except ImportError:
|
||||||
|
has_platformdirs = False
|
||||||
|
|
||||||
from g4f.gui import run_gui
|
from g4f.gui import run_gui
|
||||||
from g4f.gui.run import gui_parser
|
from g4f.gui.run import gui_parser
|
||||||
import g4f.version
|
import g4f.version
|
||||||
import g4f.debug
|
import g4f.debug
|
||||||
|
|
||||||
def run_webview(host: str = "0.0.0.0", port: int = 8080, debug: bool = True):
|
def run_webview(
|
||||||
webview.create_window(f"g4f - {g4f.version.utils.current_version}", f"http://{host}:{port}/")
|
host: str = "0.0.0.0",
|
||||||
if debug:
|
port: int = 8080,
|
||||||
g4f.debug.logging = True
|
debug: bool = False,
|
||||||
|
storage_path: str = None
|
||||||
|
):
|
||||||
|
webview.create_window(
|
||||||
|
f"g4f - {g4f.version.utils.current_version}",
|
||||||
|
f"http://{host}:{port}/",
|
||||||
|
text_select=True
|
||||||
|
)
|
||||||
|
if has_platformdirs and storage_path is None:
|
||||||
|
storage_path = user_config_dir("g4f-webview")
|
||||||
webview.start(
|
webview.start(
|
||||||
partial(run_gui, host, port),
|
partial(run_gui, host, port),
|
||||||
private_mode=False,
|
private_mode=False,
|
||||||
storage_path=user_config_dir("g4f-webview"),
|
storage_path=storage_path,
|
||||||
debug=debug
|
debug=debug
|
||||||
)
|
)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = gui_parser()
|
parser = gui_parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
if args.debug:
|
||||||
|
g4f.debug.logging = True
|
||||||
run_webview(args.host, args.port, args.debug)
|
run_webview(args.host, args.port, args.debug)
|
||||||
45
g4f/gui/webview.spec
Normal file
45
g4f/gui/webview.spec
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(
|
||||||
|
['webview.py'],
|
||||||
|
pathex=[],
|
||||||
|
binaries=[],
|
||||||
|
datas=[],
|
||||||
|
hiddenimports=[],
|
||||||
|
hookspath=[],
|
||||||
|
hooksconfig={},
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher,
|
||||||
|
noarchive=False,
|
||||||
|
)
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||||
|
|
||||||
|
exe = EXE(
|
||||||
|
pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
Tree('client', prefix='client'),
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='webview',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
upx_exclude=[],
|
||||||
|
runtime_tmpdir=None,
|
||||||
|
console=False,
|
||||||
|
disable_windowed_traceback=False,
|
||||||
|
argv_emulation=False,
|
||||||
|
target_arch=None,
|
||||||
|
codesign_identity=None,
|
||||||
|
entitlements_file=None,
|
||||||
|
)
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Union
|
|
||||||
from aiohttp import ClientResponse
|
|
||||||
from requests import Response as RequestsResponse
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from curl_cffi.requests import Session, Response
|
from curl_cffi.requests import Session, Response
|
||||||
from .curl_cffi import StreamResponse, StreamSession
|
from .curl_cffi import StreamResponse, StreamSession, FormData
|
||||||
has_curl_cffi = True
|
has_curl_cffi = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from typing import Type as Session, Type as Response
|
from typing import Type as Session, Type as Response
|
||||||
from .aiohttp import StreamResponse, StreamSession
|
from .aiohttp import StreamResponse, StreamSession, FormData
|
||||||
has_curl_cffi = False
|
has_curl_cffi = False
|
||||||
try:
|
try:
|
||||||
import webview
|
import webview
|
||||||
|
|
@ -19,12 +15,13 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
has_webview = False
|
has_webview = False
|
||||||
|
|
||||||
|
from .raise_for_status import raise_for_status
|
||||||
from ..webdriver import WebDriver, WebDriverSession
|
from ..webdriver import WebDriver, WebDriverSession
|
||||||
from ..webdriver import bypass_cloudflare, get_driver_cookies
|
from ..webdriver import bypass_cloudflare, get_driver_cookies
|
||||||
from ..errors import MissingRequirementsError, RateLimitError, ResponseStatusError
|
from ..errors import MissingRequirementsError
|
||||||
from .defaults import DEFAULT_HEADERS, WEBVIEW_HAEDERS
|
from .defaults import DEFAULT_HEADERS, WEBVIEW_HAEDERS
|
||||||
|
|
||||||
async def get_args_from_webview(url: str):
|
async def get_args_from_webview(url: str) -> dict:
|
||||||
if not has_webview:
|
if not has_webview:
|
||||||
raise MissingRequirementsError('Install "webview" package')
|
raise MissingRequirementsError('Install "webview" package')
|
||||||
window = webview.create_window("", url, hidden=True)
|
window = webview.create_window("", url, hidden=True)
|
||||||
|
|
@ -109,26 +106,3 @@ def get_session_from_browser(url: str, webdriver: WebDriver = None, proxy: str =
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
impersonate="chrome"
|
impersonate="chrome"
|
||||||
)
|
)
|
||||||
|
|
||||||
def is_cloudflare(text: str):
|
|
||||||
return '<div id="cf-please-wait">' in text or "<title>Just a moment...</title>" in text
|
|
||||||
|
|
||||||
async def raise_for_status_async(response: Union[StreamResponse, ClientResponse], message: str = None):
|
|
||||||
if response.status in (429, 402):
|
|
||||||
raise RateLimitError(f"Response {response.status}: Rate limit reached")
|
|
||||||
message = await response.text() if not response.ok and message is None else message
|
|
||||||
if response.status == 403 and is_cloudflare(message):
|
|
||||||
raise ResponseStatusError(f"Response {response.status}: Cloudflare detected")
|
|
||||||
elif not response.ok:
|
|
||||||
raise ResponseStatusError(f"Response {response.status}: {message}")
|
|
||||||
|
|
||||||
def raise_for_status(response: Union[StreamResponse, ClientResponse, Response, RequestsResponse], message: str = None):
|
|
||||||
if hasattr(response, "status"):
|
|
||||||
return raise_for_status_async(response, message)
|
|
||||||
|
|
||||||
if response.status_code in (429, 402):
|
|
||||||
raise RateLimitError(f"Response {response.status_code}: Rate limit reached")
|
|
||||||
elif response.status_code == 403 and is_cloudflare(response.text):
|
|
||||||
raise ResponseStatusError(f"Response {response.status_code}: Cloudflare detected")
|
|
||||||
elif not response.ok:
|
|
||||||
raise ResponseStatusError(f"Response {response.status_code}: {response.text if message is None else message}")
|
|
||||||
|
|
@ -44,7 +44,3 @@ def get_connector(connector: BaseConnector = None, proxy: str = None, rdns: bool
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise MissingRequirementsError('Install "aiohttp_socks" package for proxy support')
|
raise MissingRequirementsError('Install "aiohttp_socks" package for proxy support')
|
||||||
return connector
|
return connector
|
||||||
|
|
||||||
class CurlMime(FormData):
|
|
||||||
def addpart(self, name: str, content_type: str = None, filename: str = None, data: bytes = None):
|
|
||||||
self.add_field(name, data, content_type=content_type, filename=filename)
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from curl_cffi.requests import AsyncSession, Response
|
from curl_cffi.requests import AsyncSession, Response, CurlMime
|
||||||
from typing import AsyncGenerator, Any
|
from typing import AsyncGenerator, Any
|
||||||
from functools import partialmethod
|
from functools import partialmethod
|
||||||
import json
|
import json
|
||||||
|
|
@ -65,6 +65,8 @@ class StreamSession(AsyncSession):
|
||||||
def request(
|
def request(
|
||||||
self, method: str, url: str, **kwargs
|
self, method: str, url: str, **kwargs
|
||||||
) -> StreamResponse:
|
) -> StreamResponse:
|
||||||
|
if isinstance(kwargs.get("data"), CurlMime):
|
||||||
|
kwargs["multipart"] = kwargs.pop("data")
|
||||||
"""Create and return a StreamResponse object for the given HTTP request."""
|
"""Create and return a StreamResponse object for the given HTTP request."""
|
||||||
return StreamResponse(super().request(method, url, stream=True, **kwargs))
|
return StreamResponse(super().request(method, url, stream=True, **kwargs))
|
||||||
|
|
||||||
|
|
@ -75,3 +77,7 @@ class StreamSession(AsyncSession):
|
||||||
put = partialmethod(request, "PUT")
|
put = partialmethod(request, "PUT")
|
||||||
patch = partialmethod(request, "PATCH")
|
patch = partialmethod(request, "PATCH")
|
||||||
delete = partialmethod(request, "DELETE")
|
delete = partialmethod(request, "DELETE")
|
||||||
|
|
||||||
|
class FormData(CurlMime):
|
||||||
|
def add_field(self, name, data=None, content_type: str = None, filename: str = None) -> None:
|
||||||
|
self.addpart(name, content_type=content_type, filename=filename, data=data)
|
||||||
34
g4f/requests/raise_for_status.py
Normal file
34
g4f/requests/raise_for_status.py
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Union
|
||||||
|
from aiohttp import ClientResponse
|
||||||
|
from requests import Response as RequestsResponse
|
||||||
|
|
||||||
|
from ..errors import ResponseStatusError, RateLimitError
|
||||||
|
from . import Response, StreamResponse
|
||||||
|
|
||||||
|
class CloudflareError(ResponseStatusError):
|
||||||
|
...
|
||||||
|
|
||||||
|
def is_cloudflare(text: str) -> bool:
|
||||||
|
return '<div id="cf-please-wait">' in text or "<title>Just a moment...</title>" in text
|
||||||
|
|
||||||
|
async def raise_for_status_async(response: Union[StreamResponse, ClientResponse], message: str = None):
|
||||||
|
if response.status in (429, 402):
|
||||||
|
raise RateLimitError(f"Response {response.status}: Rate limit reached")
|
||||||
|
message = await response.text() if not response.ok and message is None else message
|
||||||
|
if response.status == 403 and is_cloudflare(message):
|
||||||
|
raise CloudflareError(f"Response {response.status}: Cloudflare detected")
|
||||||
|
elif not response.ok:
|
||||||
|
raise ResponseStatusError(f"Response {response.status}: {message}")
|
||||||
|
|
||||||
|
def raise_for_status(response: Union[Response, StreamResponse, ClientResponse, RequestsResponse], message: str = None):
|
||||||
|
if hasattr(response, "status"):
|
||||||
|
return raise_for_status_async(response, message)
|
||||||
|
|
||||||
|
if response.status_code in (429, 402):
|
||||||
|
raise RateLimitError(f"Response {response.status_code}: Rate limit reached")
|
||||||
|
elif response.status_code == 403 and is_cloudflare(response.text):
|
||||||
|
raise CloudflareError(f"Response {response.status_code}: Cloudflare detected")
|
||||||
|
elif not response.ok:
|
||||||
|
raise ResponseStatusError(f"Response {response.status_code}: {response.text if message is None else message}")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue