XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Add random cookie generation and enhance authentication flow in Copilot

cf4ab392
hlohaus <983577+hlohaus@users.noreply.github.com>
提交于

代码差异

1 个文件 +66 -14
Modified g4f/Provider/Copilot.py +66 -14
@@ -4,6 +4,9 @@ import os
4 4 import json
5 5 import asyncio
6 6 import base64
7 import random
8 import string
9 import urllib.parse
7 10 from typing import AsyncIterator
8 11 from urllib.parse import quote
9 12
@@ -25,7 +28,7 @@ from ..typing import AsyncResult, Messages, MediaListType
25 28 from ..errors import MissingRequirementsError, NoValidHarFileError, MissingAuthError
26 29 from ..providers.response import *
27 30 from ..tools.media import merge_media
28 from ..requests import get_nodriver
31 from ..requests import get_nodriver, DEFAULT_HEADERS
29 32 from ..image import to_bytes, is_accepted_format
30 33 from .helper import get_last_user_message
31 34 from ..files import get_bucket_dir
@@ -52,6 +55,24 @@ def extract_bucket_items(messages: Messages) -> list[dict]:
52 55 bucket_items = []
53 56 return bucket_items
54 57
58 def random_hex(length):
59 return ''.join(random.choices('0123456789ABCDEF', k=length))
60
61 def random_base64(length):
62 chars = string.ascii_letters + string.digits + '+/='
63 return ''.join(random.choices(chars, k=length))
64
65 def get_fake_cookie():
66 return {
67 "_C_ETH": "1",
68 "_C_Auth": "",
69 "MUID": random_hex(32),
70 "MUIDB": random_hex(32),
71 "_EDGE_S": f"F=1&SID={random_hex(32)}",
72 "_EDGE_V": "1",
73 "ak_bmsc": f"{random_hex(32)}~{'0'*48}~{urllib.parse.quote(random_base64(300))}"
74 }
75
55 76 class Copilot(AsyncAuthedProvider, ProviderModelMixin):
56 77 label = "Microsoft Copilot"
57 78 url = "https://copilot.microsoft.com"
@@ -76,12 +97,8 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
76 97 conversation_url = f"{url}/c/api/conversations"
77 98
78 99 @classmethod
79 async def on_auth_async(cls, cookies: dict = None, api_key: str = None, proxy: str = None, **kwargs) -> AsyncIterator:
80 if api_key:
81 if not cookies:
82 cookies = {}
83 cookies[cls.anon_cookie_name] = api_key
84 elif cookies is None:
100 async def on_auth_async(cls, cookies: dict = None, proxy: str = None, **kwargs) -> AsyncIterator:
101 if cookies is None:
85 102 cookies = get_cookies(cls.cookie_domain, False, cache_result=False)
86 103 access_token = None
87 104 useridentitytype = None
@@ -119,10 +136,12 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
119 136 raise MissingRequirementsError('Install or update "curl_cffi" package | pip install -U curl_cffi')
120 137 model = cls.get_model(model)
121 138 websocket_url = cls.websocket_url
122 headers = None
139 headers = DEFAULT_HEADERS.copy()
140 headers["origin"] = cls.url
141 headers["referer"] = cls.url + "/"
123 142 if getattr(auth_result, "access_token", None):
124 143 websocket_url = f"{websocket_url}&accessToken={quote(auth_result.access_token)}" + (f"&X-UserIdentityType={quote(auth_result.useridentitytype)}" if getattr(auth_result, "useridentitytype", None) else "")
125 headers = {"authorization": f"Bearer {auth_result.access_token}"}
144 headers["authorization"] = f"Bearer {auth_result.access_token}"
126 145
127 146 async with AsyncSession(
128 147 timeout=timeout,
@@ -170,12 +189,14 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
170 189 if response.status_code == 401:
171 190 raise MissingAuthError("Status 401: Invalid session")
172 191 response.raise_for_status()
192 debug.log(f"Copilot: Update cookies: [{', '.join(key for key in response.cookies)}]")
193 auth_result.cookies.update({key: value for key, value in response.cookies.items()})
194 if not cls.needs_auth and cls.anon_cookie_name not in auth_result.cookies:
195 raise MissingAuthError(f"Missing cookie: {cls.anon_cookie_name}")
173 196 conversation = Conversation(response.json().get("currentConversationId"))
174 197 debug.log(f"Copilot: Created conversation: {conversation.conversation_id}")
175 198 else:
176 199 debug.log(f"Copilot: Use conversation: {conversation.conversation_id}")
177 if return_conversation:
178 yield conversation
179 200
180 201 # response = await session.get("https://copilot.microsoft.com/c/api/user?api-version=4", headers={"x-useridentitytype": useridentitytype} if cls._access_token else {})
181 202 # if response.status_code == 401:
@@ -298,6 +319,8 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
298 319 debug.log(f"Copilot Message: {msg_txt[:100]}...")
299 320 if not done:
300 321 raise MissingAuthError(f"Invalid response: {last_msg}")
322 if return_conversation:
323 yield conversation
301 324 if sources:
302 325 yield Sources(sources.values())
303 326 if not wss.closed:
@@ -338,6 +361,19 @@ async def get_access_token_and_cookies(url: str, proxy: str = None, needs_auth:
338 361 break
339 362 if not needs_auth:
340 363 break
364 if not needs_auth:
365 textarea = await page.select("textarea")
366 if textarea is not None:
367 await textarea.send_keys("Hello")
368 await asyncio.sleep(1)
369 button = await page.select("[data-testid=\"submit-button\"]")
370 if button:
371 await button.click()
372 turnstile = await page.select('#cf-turnstile', 300)
373 if turnstile:
374 debug.log("Found Element: 'cf-turnstile'")
375 await asyncio.sleep(3)
376 await click_trunstile(page)
341 377 cookies = {}
342 378 while Copilot.anon_cookie_name not in cookies:
343 379 await asyncio.sleep(2)
@@ -369,7 +405,23 @@ def readHAR(url: str):
369 405 useridentitytype = v_headers["x-useridentitytype"]
370 406 if v['request']['cookies']:
371 407 cookies = {c['name']: c['value'] for c in v['request']['cookies']}
372 if api_key is None:
373 raise NoValidHarFileError("No access token found in .har files")
408 if not cookies:
409 raise NoValidHarFileError("No session found in .har files")
410
411 return api_key, useridentitytype, cookies
374 412
375 return api_key, useridentitytype, cookies
413 if has_nodriver:
414 async def click_trunstile(page: nodriver.Tab, element='document.getElementById("cf-turnstile")'):
415 for _ in range(3):
416 size = None
417 for idx in range(15):
418 size = await page.js_dumps(f'{element}?.getBoundingClientRect()||{{}}')
419 debug.log(f"Found size: {size.get('x'), size.get('y')}")
420 if "x" not in size:
421 break
422 await page.flash_point(size.get("x") + idx * 3, size.get("y") + idx * 3)
423 await page.mouse_click(size.get("x") + idx * 3, size.get("y") + idx * 3)
424 await asyncio.sleep(2)
425 if "x" not in size:
426 break
427 debug.log("Finished clicking trunstile.")