from __future__ import annotations import os import asyncio import requests import json try: import nodriver except ImportError: pass from ..typing import AsyncResult, Messages from ..config import DEFAULT_MODEL from ..requests import get_args_from_nodriver, raise_for_status from ..providers.base_provider import AuthFileMixin from .template import OpenaiTemplate from .helper import get_last_user_message from .. import debug class EasyChat(OpenaiTemplate, AuthFileMixin): url = "https://chat3.eqing.tech" api_base = f"{url}/api/openai/v1" api_endpoint = f"{api_base}/chat/completions" working = False active_by_default = True use_model_names = True default_model = DEFAULT_MODEL.split("/")[-1] model_aliases = { DEFAULT_MODEL: f"{default_model}-free", } captchaToken: str = None share_url: str = None looked: bool = False guestId: str = None @classmethod def get_models(cls, **kwargs) -> list[str]: if not cls.models: models = super().get_models(**kwargs) models = {m.replace("-free", ""): m for m in models if m.endswith("-free")} cls.model_aliases.update(models) cls.models = list(models) return cls.models @classmethod async def create_async_generator( cls, model: str, messages: Messages, stream: bool = True, proxy: str = None, extra_body: dict = None, **kwargs ) -> AsyncResult: cls.share_url = os.getenv("G4F_SHARE_URL") model = cls.get_model(model.replace("-free", "")) args = None cache_file = cls.get_cache_file() async def callback(page): cls.captchaToken = None def on_request(event: nodriver.cdp.network.RequestWillBeSent, page=None): if event.request.url != cls.api_endpoint: return if not event.request.post_data: return cls.captchaToken = json.loads(event.request.post_data).get("captchaToken") await page.send(nodriver.cdp.network.enable()) page.add_handler(nodriver.cdp.network.RequestWillBeSent, on_request) button = await page.find("我已知晓") if button: await button.click() else: debug.error("No 'Agree' button found.") for _ in range(3): await asyncio.sleep(1) for _ in range(300): modal = await page.find("Verifying...") if not modal: break debug.log("EasyChat: Waiting for captcha verification...") await asyncio.sleep(1) if cls.captchaToken: debug.log("EasyChat: Captcha token found, proceeding.") break textarea = await page.select("[contenteditable=\"true\"]", 180) if textarea is not None: await textarea.send_keys("Hello") await asyncio.sleep(1) button = await page.select("button[class*='chat_chat-input-send']") if button: await button.click() for _ in range(300): await asyncio.sleep(1) if cls.captchaToken: break cls.guestId = await page.evaluate('"" + JSON.parse(localStorage.getItem("user-info") || "{}")?.state?.guestId') await asyncio.sleep(3) if cache_file.exists(): with cache_file.open("r") as f: args = json.load(f) cls.captchaToken = args.pop("captchaToken") cls.guestId = args.pop("guestId", None) if cls.captchaToken: debug.log("EasyChat: Using cached captchaToken.") elif not cls.looked and cls.share_url: cls.looked = True try: debug.log("No cache file found, trying to fetch from share URL.") response = requests.get(cls.share_url, params={ "prompt": get_last_user_message(messages), "model": model, "provider": cls.__name__ }) raise_for_status(response) text, *sub = response.text.split("\n" * 10 + "