mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
Add random cookie generation and enhance authentication flow in Copilot
This commit is contained in:
parent
77afb46c50
commit
cf4ab392b6
1 changed files with 66 additions and 14 deletions
|
|
@ -4,6 +4,9 @@ import os
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import urllib.parse
|
||||||
from typing import AsyncIterator
|
from typing import AsyncIterator
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
|
@ -25,7 +28,7 @@ from ..typing import AsyncResult, Messages, MediaListType
|
||||||
from ..errors import MissingRequirementsError, NoValidHarFileError, MissingAuthError
|
from ..errors import MissingRequirementsError, NoValidHarFileError, MissingAuthError
|
||||||
from ..providers.response import *
|
from ..providers.response import *
|
||||||
from ..tools.media import merge_media
|
from ..tools.media import merge_media
|
||||||
from ..requests import get_nodriver
|
from ..requests import get_nodriver, DEFAULT_HEADERS
|
||||||
from ..image import to_bytes, is_accepted_format
|
from ..image import to_bytes, is_accepted_format
|
||||||
from .helper import get_last_user_message
|
from .helper import get_last_user_message
|
||||||
from ..files import get_bucket_dir
|
from ..files import get_bucket_dir
|
||||||
|
|
@ -52,6 +55,24 @@ def extract_bucket_items(messages: Messages) -> list[dict]:
|
||||||
bucket_items = []
|
bucket_items = []
|
||||||
return bucket_items
|
return bucket_items
|
||||||
|
|
||||||
|
def random_hex(length):
|
||||||
|
return ''.join(random.choices('0123456789ABCDEF', k=length))
|
||||||
|
|
||||||
|
def random_base64(length):
|
||||||
|
chars = string.ascii_letters + string.digits + '+/='
|
||||||
|
return ''.join(random.choices(chars, k=length))
|
||||||
|
|
||||||
|
def get_fake_cookie():
|
||||||
|
return {
|
||||||
|
"_C_ETH": "1",
|
||||||
|
"_C_Auth": "",
|
||||||
|
"MUID": random_hex(32),
|
||||||
|
"MUIDB": random_hex(32),
|
||||||
|
"_EDGE_S": f"F=1&SID={random_hex(32)}",
|
||||||
|
"_EDGE_V": "1",
|
||||||
|
"ak_bmsc": f"{random_hex(32)}~{'0'*48}~{urllib.parse.quote(random_base64(300))}"
|
||||||
|
}
|
||||||
|
|
||||||
class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
||||||
label = "Microsoft Copilot"
|
label = "Microsoft Copilot"
|
||||||
url = "https://copilot.microsoft.com"
|
url = "https://copilot.microsoft.com"
|
||||||
|
|
@ -76,12 +97,8 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
||||||
conversation_url = f"{url}/c/api/conversations"
|
conversation_url = f"{url}/c/api/conversations"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def on_auth_async(cls, cookies: dict = None, api_key: str = None, proxy: str = None, **kwargs) -> AsyncIterator:
|
async def on_auth_async(cls, cookies: dict = None, proxy: str = None, **kwargs) -> AsyncIterator:
|
||||||
if api_key:
|
if cookies is None:
|
||||||
if not cookies:
|
|
||||||
cookies = {}
|
|
||||||
cookies[cls.anon_cookie_name] = api_key
|
|
||||||
elif cookies is None:
|
|
||||||
cookies = get_cookies(cls.cookie_domain, False, cache_result=False)
|
cookies = get_cookies(cls.cookie_domain, False, cache_result=False)
|
||||||
access_token = None
|
access_token = None
|
||||||
useridentitytype = None
|
useridentitytype = None
|
||||||
|
|
@ -119,10 +136,12 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
||||||
raise MissingRequirementsError('Install or update "curl_cffi" package | pip install -U curl_cffi')
|
raise MissingRequirementsError('Install or update "curl_cffi" package | pip install -U curl_cffi')
|
||||||
model = cls.get_model(model)
|
model = cls.get_model(model)
|
||||||
websocket_url = cls.websocket_url
|
websocket_url = cls.websocket_url
|
||||||
headers = None
|
headers = DEFAULT_HEADERS.copy()
|
||||||
|
headers["origin"] = cls.url
|
||||||
|
headers["referer"] = cls.url + "/"
|
||||||
if getattr(auth_result, "access_token", None):
|
if getattr(auth_result, "access_token", None):
|
||||||
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 "")
|
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 "")
|
||||||
headers = {"authorization": f"Bearer {auth_result.access_token}"}
|
headers["authorization"] = f"Bearer {auth_result.access_token}"
|
||||||
|
|
||||||
async with AsyncSession(
|
async with AsyncSession(
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
|
|
@ -170,12 +189,14 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
||||||
if response.status_code == 401:
|
if response.status_code == 401:
|
||||||
raise MissingAuthError("Status 401: Invalid session")
|
raise MissingAuthError("Status 401: Invalid session")
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
debug.log(f"Copilot: Update cookies: [{', '.join(key for key in response.cookies)}]")
|
||||||
|
auth_result.cookies.update({key: value for key, value in response.cookies.items()})
|
||||||
|
if not cls.needs_auth and cls.anon_cookie_name not in auth_result.cookies:
|
||||||
|
raise MissingAuthError(f"Missing cookie: {cls.anon_cookie_name}")
|
||||||
conversation = Conversation(response.json().get("currentConversationId"))
|
conversation = Conversation(response.json().get("currentConversationId"))
|
||||||
debug.log(f"Copilot: Created conversation: {conversation.conversation_id}")
|
debug.log(f"Copilot: Created conversation: {conversation.conversation_id}")
|
||||||
else:
|
else:
|
||||||
debug.log(f"Copilot: Use conversation: {conversation.conversation_id}")
|
debug.log(f"Copilot: Use conversation: {conversation.conversation_id}")
|
||||||
if return_conversation:
|
|
||||||
yield conversation
|
|
||||||
|
|
||||||
# response = await session.get("https://copilot.microsoft.com/c/api/user?api-version=4", headers={"x-useridentitytype": useridentitytype} if cls._access_token else {})
|
# response = await session.get("https://copilot.microsoft.com/c/api/user?api-version=4", headers={"x-useridentitytype": useridentitytype} if cls._access_token else {})
|
||||||
# if response.status_code == 401:
|
# if response.status_code == 401:
|
||||||
|
|
@ -298,6 +319,8 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
|
||||||
debug.log(f"Copilot Message: {msg_txt[:100]}...")
|
debug.log(f"Copilot Message: {msg_txt[:100]}...")
|
||||||
if not done:
|
if not done:
|
||||||
raise MissingAuthError(f"Invalid response: {last_msg}")
|
raise MissingAuthError(f"Invalid response: {last_msg}")
|
||||||
|
if return_conversation:
|
||||||
|
yield conversation
|
||||||
if sources:
|
if sources:
|
||||||
yield Sources(sources.values())
|
yield Sources(sources.values())
|
||||||
if not wss.closed:
|
if not wss.closed:
|
||||||
|
|
@ -338,6 +361,19 @@ async def get_access_token_and_cookies(url: str, proxy: str = None, needs_auth:
|
||||||
break
|
break
|
||||||
if not needs_auth:
|
if not needs_auth:
|
||||||
break
|
break
|
||||||
|
if not needs_auth:
|
||||||
|
textarea = await page.select("textarea")
|
||||||
|
if textarea is not None:
|
||||||
|
await textarea.send_keys("Hello")
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
button = await page.select("[data-testid=\"submit-button\"]")
|
||||||
|
if button:
|
||||||
|
await button.click()
|
||||||
|
turnstile = await page.select('#cf-turnstile', 300)
|
||||||
|
if turnstile:
|
||||||
|
debug.log("Found Element: 'cf-turnstile'")
|
||||||
|
await asyncio.sleep(3)
|
||||||
|
await click_trunstile(page)
|
||||||
cookies = {}
|
cookies = {}
|
||||||
while Copilot.anon_cookie_name not in cookies:
|
while Copilot.anon_cookie_name not in cookies:
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|
@ -369,7 +405,23 @@ def readHAR(url: str):
|
||||||
useridentitytype = v_headers["x-useridentitytype"]
|
useridentitytype = v_headers["x-useridentitytype"]
|
||||||
if v['request']['cookies']:
|
if v['request']['cookies']:
|
||||||
cookies = {c['name']: c['value'] for c in v['request']['cookies']}
|
cookies = {c['name']: c['value'] for c in v['request']['cookies']}
|
||||||
if api_key is None:
|
if not cookies:
|
||||||
raise NoValidHarFileError("No access token found in .har files")
|
raise NoValidHarFileError("No session found in .har files")
|
||||||
|
|
||||||
return api_key, useridentitytype, cookies
|
return api_key, useridentitytype, cookies
|
||||||
|
|
||||||
|
if has_nodriver:
|
||||||
|
async def click_trunstile(page: nodriver.Tab, element='document.getElementById("cf-turnstile")'):
|
||||||
|
for _ in range(3):
|
||||||
|
size = None
|
||||||
|
for idx in range(15):
|
||||||
|
size = await page.js_dumps(f'{element}?.getBoundingClientRect()||{{}}')
|
||||||
|
debug.log(f"Found size: {size.get('x'), size.get('y')}")
|
||||||
|
if "x" not in size:
|
||||||
|
break
|
||||||
|
await page.flash_point(size.get("x") + idx * 3, size.get("y") + idx * 3)
|
||||||
|
await page.mouse_click(size.get("x") + idx * 3, size.get("y") + idx * 3)
|
||||||
|
await asyncio.sleep(2)
|
||||||
|
if "x" not in size:
|
||||||
|
break
|
||||||
|
debug.log("Finished clicking trunstile.")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue