mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-09-26 20:31:14 +08:00

- In `g4f/__init__.py`, changed logger setup to use fixed "g4f" name and refactored `ChatCompletion.create` and `create_async` to share `_prepare_request` logic for preprocessing arguments - In `g4f/config.py`, added `__future__.annotations`, `lru_cache` import, wrapped `get_config_dir` with `@lru_cache`, and simplified platform branch logic - In `g4f/cookies.py`, added typing imports, renamed `browsers` to `BROWSERS`, reformatted `DOMAINS`, updated docstrings, improved loop logic in `load_cookies_from_browsers` with additional exception handling, split HAR/JSON parsing into `_parse_har_file` and `_parse_json_cookie_file`, and enhanced `read_cookie_files` with optional filters and `.env` loading - In `g4f/debug.py`, added enable/disable logging functions, updated log handler typing, appended messages to `logs` in `log()`, and improved `error()` formatting - In `g4f/errors.py`, introduced base `G4FError` and updated all exception classes to inherit from it or relevant subclasses, with descriptive docstrings for each - In `g4f/files.py`, added `max_length` parameter to `secure_filename`, adjusted regex formatting, and added docstring; updated `get_bucket_dir` to sanitize parts inline with docstring - In `g4f/typing.py`, added `__future__.annotations`, reorganized imports, restricted PIL import to type-checking, defined `ContentPart` and `Message` TypedDicts, updated type aliases and `__all__` to include new types - In `g4f/version.py`, added `lru_cache` and request timeout constant, applied caching to `get_pypi_version` and `get_github_version`, added response validation and explicit exceptions, refactored `VersionUtils.current_version` with clearer sources and error on miss, changed `check_version` to return a boolean with optional silent mode, and improved error handling outputs
34 lines
907 B
Python
34 lines
907 B
Python
from __future__ import annotations
|
|
|
|
import re
|
|
import os
|
|
from urllib.parse import unquote
|
|
|
|
from .cookies import get_cookies_dir
|
|
|
|
|
|
def secure_filename(filename: str, max_length: int = 100) -> str:
|
|
"""Sanitize a filename for safe filesystem storage."""
|
|
if filename is None:
|
|
return None
|
|
|
|
# Keep letters, numbers, basic punctuation, underscores
|
|
filename = re.sub(
|
|
r"[^\w.,_+\-]+",
|
|
"_",
|
|
unquote(filename).strip(),
|
|
flags=re.UNICODE
|
|
)
|
|
encoding = "utf-8"
|
|
encoded = filename.encode(encoding)[:max_length]
|
|
decoded = encoded.decode(encoding, "ignore")
|
|
return decoded.strip(".,_+-")
|
|
|
|
|
|
def get_bucket_dir(*parts: str) -> str:
|
|
"""Return a path under the cookies 'buckets' directory with sanitized parts."""
|
|
return os.path.join(
|
|
get_cookies_dir(),
|
|
"buckets",
|
|
*[secure_filename(part) for part in parts if part]
|
|
) |