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

XFEstudio/gpt4free

feat: Add get_quota method and refactor login methods in multiple providers

49d0cfe2
hlohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

4 个文件 +63 -59
Modified g4f/Provider/needs_auth/Gemini.py +14 -2
@@ -105,7 +105,7 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
105 105 rotate_tasks = {}
106 106
107 107 @classmethod
108 async def nodriver_login(cls, proxy: str = None) -> AsyncIterator[str]:
108 async def login(cls, proxy: str = None) -> AsyncIterator[str]:
109 109 if not has_nodriver:
110 110 debug.log("Skip nodriver login in Gemini provider")
111 111 return
@@ -146,6 +146,18 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
146 146 cls._cookies["__Secure-1PSIDTS"] = new_1psidts
147 147 await asyncio.sleep(cls.refresh_interval)
148 148
149 @classmethod
150 async def get_quota(cls, **kwargs):
151 if not cls._cookies:
152 cls._cookies = get_cookies(GOOGLE_COOKIE_DOMAIN, False, True)
153 if not cls._cookies:
154 raise MissingAuthError('Missing or invalid "__Secure-1PSID" cookie')
155 async with ClientSession(
156 headers=REQUEST_HEADERS
157 ) as session:
158 await cls.fetch_snlm0e(session, cls._cookies)
159 return cls._snlm0e
160
149 161 @classmethod
150 162 async def create_async_generator(
151 163 cls,
@@ -188,7 +200,7 @@ class Gemini(AsyncGeneratorProvider, ProviderModelMixin):
188 200 await cls.fetch_snlm0e(session, cls._cookies) if cls._cookies else None
189 201 if not cls._snlm0e:
190 202 try:
191 async for chunk in cls.nodriver_login(proxy):
203 async for chunk in cls.login(proxy):
192 204 yield chunk
193 205 except Exception as e:
194 206 raise MissingAuthError('Missing or invalid "__Secure-1PSID" cookie', e)
Modified g4f/Provider/needs_auth/LMArena.py +26 -46
@@ -442,22 +442,8 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
442 442 return files
443 443
444 444 @classmethod
445 async def create_async_generator(
446 cls,
447 model: str,
448 messages: Messages,
449 conversation: JsonConversation = None,
450 media: MediaListType = None,
451 proxy: str = None,
452 timeout: int = None,
453 **kwargs
454 ) -> AsyncResult:
455 if cls.share_url is None:
456 cls.share_url = os.getenv("G4F_SHARE_URL")
457 prompt = get_last_user_message(messages)
445 def read_args(cls, args: dict = {}):
458 446 cache_file = cls.get_cache_file()
459 args = kwargs.get("lmarena_args", {})
460 grecaptcha = kwargs.pop("grecaptcha", "")
461 447 if not args and cache_file.exists():
462 448 try:
463 449 with cache_file.open("r") as f:
@@ -466,35 +452,35 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
466 452 debug.log(f"Cache file {cache_file} is corrupted, removing it.")
467 453 cache_file.unlink()
468 454 args = None
469 force = False
455 return args
456
457 @classmethod
458 async def get_quota(cls, **kwargs):
459 args = cls.read_args()
460 if not args:
461 raise MissingAuthError("No authentication arguments found.")
462 return {key: len(value) if value else 0 for key, value in args.items()}
463
464 @classmethod
465 async def create_async_generator(
466 cls,
467 model: str,
468 messages: Messages,
469 conversation: JsonConversation = None,
470 media: MediaListType = None,
471 proxy: str = None,
472 timeout: int = None,
473 **kwargs
474 ) -> AsyncResult:
475 prompt = get_last_user_message(messages)
476 cache_file = cls.get_cache_file()
477 args = cls.read_args(kwargs.get("lmarena_args", {}))
478 grecaptcha = kwargs.pop("grecaptcha", "")
470 479 for _ in range(2):
471 480 if args:
472 481 pass
473 elif has_nodriver or cls.share_url is None:
482 elif has_nodriver:
474 483 args, grecaptcha = await cls.get_args_from_nodriver(proxy)
475
476 elif not cls.looked:
477 cls.looked = True
478 try:
479 debug.log("No cache file found, trying to fetch from share URL.")
480 response = requests.get(cls.share_url, params={
481 "prompt": prompt,
482 "model": model,
483 "provider": cls.__name__
484 })
485 raise_for_status(response)
486 if response.headers.get("Content-Type", "").startswith("image/"):
487 yield ImageResponse(str(response.url), prompt)
488 else:
489 text, *args = response.text.split("\n" * 10 + "<!--", 1)
490 if args:
491 debug.log("Save args to cache file:", str(cache_file))
492 with cache_file.open("w") as f:
493 f.write(args[0].strip())
494 yield text
495 finally:
496 cls.looked = False
497 return
498 484 else:
499 485 raise MissingRequirementsError("No auth file found and nodriver is not available.")
500 486
@@ -587,21 +573,15 @@ class LMArena(AsyncGeneratorProvider, ProviderModelMixin, AuthFileMixin):
587 573 continue
588 574 except (RateLimitError) as error:
589 575 args = None
590 force = True
591 576 debug.error(error)
592 577 continue
593 578 except:
594 579 raise
595 if args and os.getenv("G4F_SHARE_AUTH") and not kwargs.get("action"):
596 yield "\n" * 10
597 yield "<!--"
598 yield json.dumps(args)
599 580 if args:
600 581 debug.log("Save args to cache file:", str(cache_file))
601 582 with cache_file.open("w") as f:
602 583 f.write(json.dumps(args))
603 584
604
605 585 def get_content_type(url: str) -> str:
606 586 if url.endswith(".webp"):
607 587 return "image/webp"
Modified g4f/Provider/needs_auth/OpenaiChat.py +17 -9
@@ -130,9 +130,17 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
130 130 user = await response.json()
131 131 return {"id": user.get("id"), "name": user.get("name")}
132 132
133 @classmethod
134 async def login(cls, **kwargs):
135 cache_file = cls.get_cache_file()
136 async for chunk in cls.on_auth_async(**kwargs):
137 if isinstance(chunk, AuthResult):
138 cls.write_cache_file(cache_file, chunk)
139 return
140
133 141 @classmethod
134 142 async def on_auth_async(cls, proxy: str = None, **kwargs) -> AsyncIterator:
135 async for chunk in cls.login(proxy=proxy):
143 async for chunk in cls.login_generator(proxy=proxy):
136 144 yield chunk
137 145 yield AuthResult(
138 146 api_key=cls._api_key,
@@ -1037,14 +1045,14 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
1037 1045 yield chunk
1038 1046
1039 1047 @classmethod
1040 async def login(
1041 cls,
1042 proxy: str = None,
1043 api_key: str = None,
1044 proof_token: str = None,
1045 cookies: Cookies = None,
1046 headers: dict = None,
1047 **kwargs
1048 async def login_generator(
1049 cls,
1050 proxy: str = None,
1051 api_key: str = None,
1052 proof_token: str = None,
1053 cookies: Cookies = None,
1054 headers: dict = None,
1055 **kwargs
1048 1056 ) -> AsyncIterator:
1049 1057 if cls._expires is not None and (cls._expires - 60 * 10) < time.time():
1050 1058 cls._headers = cls._api_key = None
Modified g4f/Provider/template/OpenaiTemplate.py +6 -2
@@ -32,6 +32,7 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
32 32 add_user = True
33 33 use_image_size = False
34 34 max_tokens: int = None
35 _checked_api_keys: dict = {}
35 36
36 37 @classmethod
37 38 async def get_quota(cls, api_key: Optional[str] = None, **kwargs) -> dict:
@@ -49,8 +50,9 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
49 50 return await cls.test_api_key(api_key)
50 51
51 52 @classmethod
52 @lru_cache(maxsize=24)
53 53 async def test_api_key(cls, api_key: str):
54 if api_key in cls._checked_api_keys:
55 return cls._checked_api_keys[api_key]
54 56 url = f"{cls.base_url}/chat/completions"
55 57 headers = {
56 58 "authorization": f"Bearer {api_key}"
@@ -63,7 +65,9 @@ class OpenaiTemplate(AsyncGeneratorProvider, ProviderModelMixin, RaiseErrorMixin
63 65 async with StreamSession() as session:
64 66 async with session.post(url, headers=headers, json=json_data) as response:
65 67 await raise_for_status(response)
66 return await response.json()
68 result = await response.json()
69 cls._checked_api_keys[api_key] = result
70 return result
67 71
68 72 @classmethod
69 73 def is_provider_api_key(cls, api_key: str) -> bool: