diff options
-rw-r--r-- | g4f/Provider/Copilot.py | 78 | ||||
-rw-r--r-- | g4f/Provider/needs_auth/CopilotAccount.py | 8 | ||||
-rw-r--r-- | g4f/Provider/needs_auth/__init__.py | 4 |
3 files changed, 82 insertions, 8 deletions
diff --git a/g4f/Provider/Copilot.py b/g4f/Provider/Copilot.py index ddfed4a8..0d8b612b 100644 --- a/g4f/Provider/Copilot.py +++ b/g4f/Provider/Copilot.py @@ -1,12 +1,25 @@ from __future__ import annotations import json +import asyncio from http.cookiejar import CookieJar +from urllib.parse import quote + try: from curl_cffi.requests import Session, CurlWsFlag has_curl_cffi = True except ImportError: has_curl_cffi = False +try: + import nodriver + has_nodriver = True +except ImportError: + has_nodriver = False +try: + from platformdirs import user_config_dir + has_platformdirs = True +except ImportError: + has_platformdirs = False from .base_provider import AbstractProvider, BaseConversation from .helper import format_prompt @@ -18,10 +31,12 @@ from .. import debug class Conversation(BaseConversation): conversation_id: str cookie_jar: CookieJar + access_token: str - def __init__(self, conversation_id: str, cookie_jar: CookieJar): + def __init__(self, conversation_id: str, cookie_jar: CookieJar, access_token: str = None): self.conversation_id = conversation_id self.cookie_jar = cookie_jar + self.access_token = access_token class Copilot(AbstractProvider): label = "Microsoft Copilot" @@ -45,10 +60,26 @@ class Copilot(AbstractProvider): **kwargs ) -> CreateResult: if not has_curl_cffi: - raise MissingRequirementsError('Install or update "curl_cffi" package | pip install -U nodriver') + raise MissingRequirementsError('Install or update "curl_cffi" package | pip install -U curl_cffi') + websocket_url = cls.websocket_url + access_token = None cookies = conversation.cookie_jar if conversation is not None else None - with Session(timeout=timeout, proxy=proxy, impersonate="chrome", cookies=cookies) as session: + if cls.needs_auth: + if conversation is None or conversation.access_token is None: + access_token, cookies = asyncio.run(cls.get_access_token_and_cookies(proxy)) + else: + access_token = conversation.access_token + websocket_url = f"{websocket_url}&acessToken={quote(access_token)}" + headers = {"Authorization": f"Bearer {access_token}"} + + with Session( + timeout=timeout, + proxy=proxy, + impersonate="chrome", + headers=headers, + cookies=cookies + ) as session: response = session.get(f"{cls.url}/") raise_for_status(response) if conversation is None: @@ -56,7 +87,7 @@ class Copilot(AbstractProvider): raise_for_status(response) conversation_id = response.json().get("id") if return_conversation: - yield Conversation(conversation_id, session.cookies.jar) + yield Conversation(conversation_id, session.cookies.jar, access_token) prompt = format_prompt(messages) if debug.logging: print(f"Copilot: Created conversation: {conversation_id}") @@ -84,4 +115,41 @@ class Copilot(AbstractProvider): if msg.get("event") == "appendText": yield msg.get("text") elif msg.get("event") in ["done", "partCompleted"]: - break
\ No newline at end of file + break + + @classmethod + async def get_access_token_and_cookies(cls, proxy: str = None): + if not has_nodriver: + raise MissingRequirementsError('Install "nodriver" package | pip install -U nodriver') + if has_platformdirs: + user_data_dir = user_config_dir("g4f-nodriver") + else: + user_data_dir = None + if debug.logging: + print(f"Copilot: Open nodriver with user_dir: {user_data_dir}") + browser = await nodriver.start( + user_data_dir=user_data_dir, + browser_args=None if proxy is None else [f"--proxy-server={proxy}"], + ) + page = await browser.get(cls.url) + while True: + access_token = await page.evaluate(""" + (() => { + for (var i = 0; i < localStorage.length; i++) { + try { + item = JSON.parse(localStorage.getItem(localStorage.key(i))); + if (item.credentialType == "AccessToken") { + return item.secret; + } + } catch(e) {} + } + })() + """) + if access_token: + break + asyncio.sleep(1) + cookies = {} + for c in await page.send(nodriver.cdp.network.get_cookies([cls.url])): + cookies[c.name] = c.value + await page.close() + return access_token, cookies
\ No newline at end of file diff --git a/g4f/Provider/needs_auth/CopilotAccount.py b/g4f/Provider/needs_auth/CopilotAccount.py new file mode 100644 index 00000000..fa43867e --- /dev/null +++ b/g4f/Provider/needs_auth/CopilotAccount.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +from ..Copilot import Copilot + +class CopilotAccount(Copilot): + needs_auth = True + parent = "Copilot" + default_model = ""
\ No newline at end of file diff --git a/g4f/Provider/needs_auth/__init__.py b/g4f/Provider/needs_auth/__init__.py index ace53876..0f430ab5 100644 --- a/g4f/Provider/needs_auth/__init__.py +++ b/g4f/Provider/needs_auth/__init__.py @@ -1,9 +1,7 @@ from .gigachat import * -#from .MetaAIAccount import MetaAIAccount -#from .OpenaiAccount import OpenaiAccount - from .BingCreateImages import BingCreateImages +from .CopilotAccount import CopilotAccount from .DeepInfra import DeepInfra from .DeepInfraImage import DeepInfraImage from .Gemini import Gemini |