返回提交历史
Modified
g4f/Provider/Copilot.py
+29
-46
Modified
g4f/Provider/needs_auth/CopilotAccount.py
+2
-24
Modified
g4f/Provider/needs_auth/OpenaiChat.py
+1
-1
XFEstudio/gpt4free
Refactor Copilot authentication handling; streamline cookie management and access token retrieval
cd42fa6d
代码差异
3 个文件
+32
-71
@@ -75,18 +75,30 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
75
75
websocket_url = "wss://copilot.microsoft.com/c/api/chat?api-version=2"
76
76
conversation_url = f"{url}/c/api/conversations"
77
77
78
_access_token: str = None
79
_useridentitytype: str = None
80
_cookies: dict = {}
81
82
78
@classmethod
83
async def on_auth_async(cls, api_key: str = None, **kwargs) -> AsyncIterator:
84
cookies = cls.cookies_to_dict()
79
async def on_auth_async(cls, cookies: dict = None, api_key: str = None, proxy: str = None, **kwargs) -> AsyncIterator:
85
80
if api_key:
81
if not cookies:
82
cookies = {}
86
83
cookies[cls.anon_cookie_name] = api_key
84
elif cookies is None:
85
cookies = get_cookies(cls.cookie_domain, False, cache_result=False)
86
access_token = None
87
useridentitytype = None
88
if cls.needs_auth or cls.anon_cookie_name not in cookies:
89
try:
90
access_token, useridentitytype, cookies = readHAR(cls.url)
91
except NoValidHarFileError as h:
92
debug.log(f"Copilot: {h}")
93
if has_nodriver:
94
yield RequestLogin(cls.label, os.environ.get("G4F_LOGIN_URL", ""))
95
access_token, useridentitytype, cookies = await get_access_token_and_cookies(cls.url, proxy)
96
else:
97
raise h
87
98
yield AuthResult(
88
access_token=cls._access_token,
89
cookies=cls.cookies_to_dict() or get_cookies(cls.cookie_domain, False)
99
access_token=access_token,
100
useridentitytype=useridentitytype,
101
cookies=cookies
90
102
)
91
103
92
104
@classmethod
@@ -95,23 +107,6 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
95
107
model: str,
96
108
messages: Messages,
97
109
auth_result: AuthResult,
98
**kwargs
99
) -> AsyncResult:
100
cls._access_token = getattr(auth_result, "access_token", None)
101
cls._cookies = getattr(auth_result, "cookies")
102
async for chunk in cls.create(model, messages, **kwargs):
103
yield chunk
104
auth_result.cookies = cls.cookies_to_dict()
105
106
@classmethod
107
def cookies_to_dict(cls):
108
return cls._cookies if isinstance(cls._cookies, dict) else {c.name: c.value for c in cls._cookies}
109
110
@classmethod
111
async def create(
112
cls,
113
model: str,
114
messages: Messages,
115
110
proxy: str = None,
116
111
timeout: int = 30,
117
112
prompt: str = None,
@@ -125,29 +120,17 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
125
120
model = cls.get_model(model)
126
121
websocket_url = cls.websocket_url
127
122
headers = None
128
if cls._access_token or cls.needs_auth:
129
if cls._access_token is None:
130
try:
131
cls._access_token, cls._useridentitytype, cls._cookies = readHAR(cls.url)
132
except NoValidHarFileError as h:
133
debug.log(f"Copilot: {h}")
134
if has_nodriver:
135
yield RequestLogin(cls.label, os.environ.get("G4F_LOGIN_URL", ""))
136
cls._access_token, cls._useridentitytype, cls._cookies = await get_access_token_and_cookies(cls.url, proxy)
137
else:
138
raise h
139
websocket_url = f"{websocket_url}&accessToken={quote(cls._access_token)}" + (f"&X-UserIdentityType={quote(cls._useridentitytype)}" if cls._useridentitytype else "")
140
headers = {"authorization": f"Bearer {cls._access_token}"}
141
123
if auth_result.access_token:
124
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}"}
142
126
143
127
async with AsyncSession(
144
128
timeout=timeout,
145
129
proxy=proxy,
146
130
impersonate="chrome",
147
131
headers=headers,
148
cookies=cls._cookies,
132
cookies=auth_result.cookies
149
133
) as session:
150
cls._cookies = session.cookies.jar if hasattr(session.cookies, "jar") else session.cookies
151
134
if conversation is None:
152
135
# har_file = os.path.join(os.path.dirname(__file__), "copilot", "copilot.microsoft.com.har")
153
136
# with open(har_file, "r") as f:
@@ -179,7 +162,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
179
162
"https://copilot.microsoft.com/c/api/start",
180
163
headers={
181
164
"content-type": "application/json",
182
**({"x-useridentitytype": cls._useridentitytype} if cls._useridentitytype else {}),
165
**({"x-useridentitytype": auth_result.useridentitytype} if getattr(auth_result, "useridentitytype", None) else {}),
183
166
**(headers or {})
184
167
},
185
168
json=data
@@ -206,7 +189,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
206
189
# debug.log(f"Copilot: User: {user}")
207
190
208
191
uploaded_attachments = []
209
if cls._access_token is not None:
192
if auth_result.access_token:
210
193
# Upload regular media (images)
211
194
for media, _ in merge_media(media, messages):
212
195
if not isinstance(media, str):
@@ -216,7 +199,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
216
199
headers={
217
200
"content-type": is_accepted_format(data),
218
201
"content-length": str(len(data)),
219
**({"x-useridentitytype": cls._useridentitytype} if cls._useridentitytype else {})
202
**({"x-useridentitytype": auth_result.useridentitytype} if getattr(auth_result, "useridentitytype", None) else {})
220
203
},
221
204
data=data
222
205
)
@@ -239,7 +222,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
239
222
response = await session.post(
240
223
"https://copilot.microsoft.com/c/api/attachments",
241
224
multipart=data,
242
headers={"x-useridentitytype": cls._useridentitytype} if cls._useridentitytype else {}
225
headers={"x-useridentitytype": auth_result.useridentitytype} if getattr(auth_result, "useridentitytype", None) else {}
243
226
)
244
227
response.raise_for_status()
245
228
data = response.json()
@@ -312,7 +295,7 @@ class Copilot(AsyncAuthedProvider, ProviderModelMixin):
312
295
elif msg.get("event") not in ["received", "startMessage", "partCompleted", "connected"]:
313
296
debug.log(f"Copilot Message: {msg_txt[:100]}...")
314
297
if not done:
315
raise RuntimeError(f"Invalid response: {last_msg}")
298
raise MissingAuthError(f"Invalid response: {last_msg}")
316
299
if sources:
317
300
yield Sources(sources.values())
318
301
if not wss.closed:
@@ -1,12 +1,6 @@
1
1
from __future__ import annotations
2
2
3
import os
4
from typing import AsyncIterator
5
6
from ..Copilot import Copilot, readHAR, has_nodriver, get_access_token_and_cookies
7
from ...providers.response import AuthResult, RequestLogin
8
from ...errors import NoValidHarFileError
9
from ... import debug
3
from ..Copilot import Copilot
10
4
11
5
class CopilotAccount(Copilot):
12
6
needs_auth = True
@@ -19,20 +13,4 @@ class CopilotAccount(Copilot):
19
13
"gpt-4o": default_model,
20
14
"o1": "Think Deeper",
21
15
"dall-e-3": default_model
22
}
23
24
@classmethod
25
async def on_auth_async(cls, proxy: str = None, **kwargs) -> AsyncIterator:
26
try:
27
cls._access_token, cls._cookies = readHAR(cls.url)
28
except NoValidHarFileError as h:
29
debug.log(f"Copilot: {h}")
30
if has_nodriver:
31
yield RequestLogin(cls.label, os.environ.get("G4F_LOGIN_URL", ""))
32
cls._access_token, cls._useridentitytype, cls._cookies = await get_access_token_and_cookies(cls.url, proxy)
33
else:
34
raise h
35
yield AuthResult(
36
api_key=cls._access_token,
37
cookies=cls.cookies_to_dict()
38
)
16
}
@@ -531,7 +531,7 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
531
531
headers=headers
532
532
) as response:
533
533
cls._update_request_args(auth_result, session)
534
if response.status in (401, 403, 429):
534
if response.status in (401, 403, 429, 500):
535
535
raise MissingAuthError("Access token is not valid")
536
536
elif response.status == 422:
537
537
raise RuntimeError((await response.json()), data)