summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g4f/Provider/You.py10
-rw-r--r--g4f/gui/webview.py27
-rw-r--r--g4f/gui/webview.spec45
-rw-r--r--g4f/requests/__init__.py38
-rw-r--r--g4f/requests/aiohttp.py6
-rw-r--r--g4f/requests/curl_cffi.py8
-rw-r--r--g4f/requests/raise_for_status.py34
7 files changed, 118 insertions, 50 deletions
diff --git a/g4f/Provider/You.py b/g4f/Provider/You.py
index 8adc8b19..9b040367 100644
--- a/g4f/Provider/You.py
+++ b/g4f/Provider/You.py
@@ -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,
},
diff --git a/g4f/gui/webview.py b/g4f/gui/webview.py
index 5a4263dc..16f143c4 100644
--- a/g4f/gui/webview.py
+++ b/g4f/gui/webview.py
@@ -1,24 +1,39 @@
import webview
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.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) \ No newline at end of file
diff --git a/g4f/gui/webview.spec b/g4f/gui/webview.spec
new file mode 100644
index 00000000..360e264e
--- /dev/null
+++ b/g4f/gui/webview.spec
@@ -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,
+)
diff --git a/g4f/requests/__init__.py b/g4f/requests/__init__.py
index cfc6af42..e65de99a 100644
--- a/g4f/requests/__init__.py
+++ b/g4f/requests/__init__.py
@@ -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)
@@ -108,27 +105,4 @@ def get_session_from_browser(url: str, webdriver: WebDriver = None, proxy: str =
proxies={"https": proxy, "http": proxy},
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}") \ No newline at end of file
+ ) \ No newline at end of file
diff --git a/g4f/requests/aiohttp.py b/g4f/requests/aiohttp.py
index 505086a1..16b052eb 100644
--- a/g4f/requests/aiohttp.py
+++ b/g4f/requests/aiohttp.py
@@ -43,8 +43,4 @@ def get_connector(connector: BaseConnector = None, proxy: str = None, rdns: bool
connector = ProxyConnector.from_url(proxy, rdns=rdns)
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) \ No newline at end of file
+ return connector \ No newline at end of file
diff --git a/g4f/requests/curl_cffi.py b/g4f/requests/curl_cffi.py
index cfcdd63b..91142365 100644
--- a/g4f/requests/curl_cffi.py
+++ b/g4f/requests/curl_cffi.py
@@ -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) \ No newline at end of file
diff --git a/g4f/requests/raise_for_status.py b/g4f/requests/raise_for_status.py
new file mode 100644
index 00000000..9e8e141c
--- /dev/null
+++ b/g4f/requests/raise_for_status.py
@@ -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}") \ No newline at end of file