Move raise_for_status, Create FormData wrapper

This commit is contained in:
Heiner Lohaus 2024-03-15 14:55:53 +01:00
parent 8cc6000ffb
commit b7eee50930
7 changed files with 118 additions and 50 deletions

View File

@ -5,7 +5,7 @@ import json
import base64
import uuid
try:
from curl_cffi import CurlMime
from ..requests.curl_cffi import FormData
has_curl_cffi = True
except ImportError:
has_curl_cffi = False
@ -123,13 +123,11 @@ class You(AsyncGeneratorProvider, ProviderModelMixin):
) as response:
await raise_for_status(response)
upload_nonce = await response.text()
#data = FormData()
#data.add_field('file', file, filename=filename)
multipart = CurlMime()
multipart.addpart(name="file", filename=filename, data=file)
data = FormData()
data.add_field('file', file, filename=filename)
async with client.post(
f"{cls.url}/api/upload",
multipart=multipart,
data=data,
headers={
"X-Upload-Nonce": upload_nonce,
},

View File

@ -1,24 +1,39 @@
import webview
from functools import partial
try:
from platformdirs import user_config_dir
has_platformdirs = True
except ImportError:
has_platformdirs = False
from g4f.gui import run_gui
from g4f.gui.run import gui_parser
import g4f.version
import g4f.debug
def run_webview(host: str = "0.0.0.0", port: int = 8080, debug: bool = True):
webview.create_window(f"g4f - {g4f.version.utils.current_version}", f"http://{host}:{port}/")
if debug:
g4f.debug.logging = True
def run_webview(
host: str = "0.0.0.0",
port: int = 8080,
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(
partial(run_gui, host, port),
private_mode=False,
storage_path=user_config_dir("g4f-webview"),
storage_path=storage_path,
debug=debug
)
if __name__ == "__main__":
parser = gui_parser()
args = parser.parse_args()
if args.debug:
g4f.debug.logging = True
run_webview(args.host, args.port, args.debug)

45
g4f/gui/webview.spec Normal file
View 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,
)

View File

@ -1,16 +1,12 @@
from __future__ import annotations
from typing import Union
from aiohttp import ClientResponse
from requests import Response as RequestsResponse
try:
from curl_cffi.requests import Session, Response
from .curl_cffi import StreamResponse, StreamSession
from .curl_cffi import StreamResponse, StreamSession, FormData
has_curl_cffi = True
except ImportError:
from typing import Type as Session, Type as Response
from .aiohttp import StreamResponse, StreamSession
from .aiohttp import StreamResponse, StreamSession, FormData
has_curl_cffi = False
try:
import webview
@ -19,12 +15,13 @@ try:
except ImportError:
has_webview = False
from .raise_for_status import raise_for_status
from ..webdriver import WebDriver, WebDriverSession
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
async def get_args_from_webview(url: str):
async def get_args_from_webview(url: str) -> dict:
if not has_webview:
raise MissingRequirementsError('Install "webview" package')
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,
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}")

View File

@ -44,7 +44,3 @@ def get_connector(connector: BaseConnector = None, proxy: str = None, rdns: bool
except ImportError:
raise MissingRequirementsError('Install "aiohttp_socks" package for proxy support')
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)

View File

@ -1,6 +1,6 @@
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 functools import partialmethod
import json
@ -65,6 +65,8 @@ class StreamSession(AsyncSession):
def request(
self, method: str, url: str, **kwargs
) -> StreamResponse:
if isinstance(kwargs.get("data"), CurlMime):
kwargs["multipart"] = kwargs.pop("data")
"""Create and return a StreamResponse object for the given HTTP request."""
return StreamResponse(super().request(method, url, stream=True, **kwargs))
@ -75,3 +77,7 @@ class StreamSession(AsyncSession):
put = partialmethod(request, "PUT")
patch = partialmethod(request, "PATCH")
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)

View 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}")