issaocean commited on
Commit
5578cb5
·
verified ·
1 Parent(s): f4b735b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +498 -287
app.py CHANGED
@@ -1,71 +1,41 @@
 
1
  import gradio as gr
2
- import requests, re
3
- from api_usage import get_subscription, check_key_availability, get_orgs_me, check_key_ant_availability, check_ant_rate_limit, check_key_gemini_availability, check_key_azure_availability, get_azure_status, get_azure_deploy, check_key_mistral_availability, check_mistral_quota, check_key_replicate_availability, check_key_aws_availability, check_key_or_availability, check_key_or_limits, check_gcp_anthropic, check_groq_status, check_nai_status, check_elevenlabs_status, check_xai_status, check_stability_status, check_deepseek_status
 
4
 
5
- async def sort_key(key, rate_limit, claude_model):
6
- _key = key.strip()
7
-
8
- if re.match(re.compile("sk-or-v1-[a-z0-9]{64}"), _key):
9
- return get_key_openrouter_info(_key)
10
-
11
- if re.match(re.compile("sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or (_key.startswith("sk-ant-") and len(_key) == 93) or (len(_key) == 89 and re.match(re.compile("sk-[a-zA-Z0-9]{86}"), _key)):
12
- return await get_key_ant_info(_key, rate_limit, claude_model)
13
-
14
- if re.match(re.compile(r"sk-[a-zA-Z0-9]{48}"), _key) and len(_key) == 51 and 'T3BlbkFJ' not in _key:
15
- return get_key_stability_info(_key)
16
-
17
- if re.match(re.compile(r"sk-[a-f0-9]{32}"), _key):
18
- return get_key_deepseek_info(_key)
19
-
20
- if _key.startswith("sk-"):
21
- return get_key_oai_info(_key)
22
-
23
- if _key.startswith("AIzaSy"):
24
- return get_key_gemini_info(_key)
25
-
26
- if _key.startswith("pst-"):
27
- return get_key_nai_info(_key)
28
-
29
- if (_key.startswith("r8_") and len(_key) == 40) or (_key.islower() and len(_key) == 40):
30
- return get_key_replicate_info(_key)
31
-
32
- if _key.startswith("xai-"):
33
- return get_key_xai_info(_key)
34
-
35
- if len(_key.split(':')) == 2 and _key.split(':')[1].islower() and len(_key.split(':')[1]) == 32 and "openai.azure.com" not in _key.split(':')[1]:
36
- endpoint = f"{_key.split(':')[0]}.openai.azure.com"
37
- api_key = _key.split(':')[1]
38
- return get_key_azure_info(endpoint, api_key)
39
-
40
- if "openai.azure.com" in _key.split(';')[0]:
41
- endpoint = _key.split(';')[0]
42
- api_key = _key.split(';')[1]
43
- return get_key_azure_info(endpoint, api_key)
44
-
45
- if _key.startswith("AKIA") and len(_key.split(':')[0]) == 20 and _key.split(':')[0].isupper():
46
- return await get_key_aws_info(_key)
47
-
48
- if re.match(re.compile(r"[a-f0-9]{32}"), _key) or re.match(re.compile(r"sk_[a-f0-9]{48}"), _key):
49
- return get_key_elevenlabs_info(_key)
50
-
51
- if re.match(re.compile(r"[a-zA-Z0-9]{32}"), _key):
52
- return get_key_mistral_info(_key)
53
-
54
- if re.match(re.compile(r"gsk_[a-zA-Z0-9]{20}WGdyb3FY[a-zA-Z0-9]{24}"), _key):
55
- return get_key_groq_info(_key)
56
-
57
- if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:[\w-]+:.+"), _key): # 0: refresh token
58
- return await get_key_gcp_info(_key, 0)
59
-
60
- if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+\\n"), _key): # 1: service account
61
- return await get_key_gcp_info(_key, 1)
62
-
63
- return not_supported(_key)
64
-
65
- def get_key_oai_info(key):
66
- # Return a dictionary containing key information
67
- session = requests.Session()
68
 
 
 
 
 
 
69
  status, org_data = check_key_availability(session, key)
70
 
71
  info_dict = {
@@ -80,7 +50,7 @@ def get_key_oai_info(key):
80
  "requests_per_minute": "",
81
  "tokens_per_minute": "",
82
  "quota": "",
83
- "all_models": ""
84
  }
85
 
86
  if not status:
@@ -90,41 +60,42 @@ def get_key_oai_info(key):
90
  status_me, orgs_me = get_orgs_me(session, key)
91
  if status_me == 200:
92
  org_data = orgs_me
93
-
94
- subscription_info = get_subscription(key, session, org_data)
95
-
96
- # Update the info_dict with subscription details
97
- info_dict.update({
98
- "gpt4_availability": subscription_info["has_gpt4"],
99
- "gpt4_32k_availability": subscription_info["has_gpt4_32k"],
100
- "default_org": subscription_info["default_org"],
101
- "org_description": subscription_info["org_description"],
102
- "organization": subscription_info["organization"],
103
- "models": subscription_info["models"],
104
- "requests_per_minute": subscription_info["rpm"],
105
- "tokens_per_minute": subscription_info["tpm"],
106
- "quota": subscription_info["quota"],
107
- "all_models": subscription_info["all_models"]
108
- })
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  return info_dict
111
 
112
- async def get_key_ant_info(key, rate_limit, claude_model):
113
- # Return a dictionary containing key information
114
  key_avai = await check_key_ant_availability(key, claude_model)
115
- info_dict = {#"account_name": "",
116
- "key_type": "Anthropic Claude",
117
- "key_availability": key_avai[0],
118
- "status": "",
119
- "filter_response": "",
120
- "requests_per_minute": "",
121
- "tokens_per_minute": "",
122
- "tokens_input_per_minute": "",
123
- "tokens_output_per_minute": "",
124
- "tier": "",
125
- "concurrent_rate_limit": "",
126
- "models": ""}
127
-
 
128
  info_dict["status"] = key_avai[1]
129
  info_dict["filter_response"] = key_avai[2]
130
  info_dict["requests_per_minute"] = key_avai[3] + ("" if key_avai[3] == "" else f" ({key_avai[4]} left)")
@@ -133,251 +104,491 @@ async def get_key_ant_info(key, rate_limit, claude_model):
133
  info_dict["tokens_output_per_minute"] = key_avai[10] + ("" if key_avai[10] == "" else f" ({key_avai[11]} left)")
134
  info_dict["tier"] = key_avai[7]
135
  info_dict["models"] = key_avai[12]
136
-
137
  if rate_limit:
138
  rate = await check_ant_rate_limit(key, claude_model)
139
  info_dict["concurrent_rate_limit"] = rate
140
-
141
  return info_dict
142
 
143
- def get_key_gemini_info(key):
144
- key_avai = check_key_gemini_availability(key)
145
- info_dict = {#"account_name": "",
146
- "key_type": "Google Gemini",
147
- "key_availability": key_avai[0],
148
- "status": key_avai[1],
149
- "models": key_avai[2]}
 
 
 
150
  return info_dict
151
 
152
- def get_key_azure_info(endpoint, api_key):
 
153
  key_avai = check_key_azure_availability(endpoint, api_key)
154
- info_dict = {#"account_name": "",
155
- "key_type": "Microsoft Azure OpenAI",
156
- "key_availability": key_avai[0],
157
- "gpt35_availability": "",
158
- "gpt4_availability": "",
159
- "gpt4_32k_availability": "",
160
- "dall_e_3_availability": "",
161
- "moderation_status": "",
162
- "models": "",
163
- "deployments": ""}
164
- if key_avai[0]:
 
165
  azure_deploy = get_azure_deploy(endpoint, api_key)
166
- status = get_azure_status(endpoint, api_key, azure_deploy)
167
- info_dict["gpt35_availability"] = status[1]
168
- info_dict["gpt4_availability"] = status[2]
169
- info_dict["gpt4_32k_availability"] = status[3]
170
- info_dict["dall_e_3_availability"] = status[4]
171
- info_dict["moderation_status"] = status[0]
 
 
172
  info_dict["models"] = key_avai[1]
173
- info_dict["deployments"] = azure_deploy
174
  return info_dict
175
 
176
- def get_key_mistral_info(key):
 
177
  key_avai = check_key_mistral_availability(key)
178
- info_dict = {#"account_name": "",
179
- "key_type": "Mistral AI",
180
- "key_availability": True if key_avai else False,
181
- "has_quota": "",
182
- "limits": "",
183
- "models": ""}
 
184
  if key_avai:
185
  quota_info = check_mistral_quota(key)
186
- info_dict['has_quota'] = quota_info[0]
187
- if quota_info[1]:
188
- info_dict['limits'] = quota_info[1]
189
- info_dict['models'] = key_avai
 
190
  return info_dict
191
 
192
- def get_key_replicate_info(key):
 
193
  key_avai = check_key_replicate_availability(key)
194
- info_dict = {#"account_name": "",
195
- "key_type": "Replicate",
196
- "key_availability": key_avai[0],
197
- "account_name": "",
198
- "type": "",
199
- "has_quota": "",
200
- "hardware_available": ""}
201
- if key_avai[0]:
202
- info_dict['account_name'] = key_avai[1]['username']
203
- info_dict['type'] = key_avai[1]['type']
204
- info_dict['has_quota'] = key_avai[2]
205
- info_dict['hardware_available'] = key_avai[3]
 
206
  return info_dict
207
 
208
- async def get_key_aws_info(key):
 
209
  key_avai = await check_key_aws_availability(key)
210
- info_dict = {#"account_name": "",
211
- "key_type": "Amazon AWS Claude",
212
- "key_availability": key_avai[0],
213
- "username": "",
214
- "root": "",
215
- "admin": "",
216
- "quarantine": "",
217
- "iam_full_access": "",
218
- "iam_user_change_password": "",
219
- "aws_bedrock_full_access": "",
220
- "enabled_region": "",
221
- "models_usage": "",
222
- "cost_and_usage": key_avai[1]}
 
223
  if key_avai[0]:
224
- info_dict['username'] = key_avai[1]
225
- info_dict['root'] = key_avai[2]
226
- info_dict['admin'] = key_avai[3]
227
- info_dict['quarantine'] = key_avai[4]
228
- info_dict['iam_full_access'] = key_avai[5]
229
- info_dict['iam_user_change_password'] = key_avai[6]
230
- info_dict['aws_bedrock_full_access'] = key_avai[7]
231
- info_dict['enabled_region'] = key_avai[8]
232
- info_dict['models_usage'] = key_avai[9]
233
- info_dict['cost_and_usage'] = key_avai[10]
234
  return info_dict
235
 
236
- def get_key_openrouter_info(key):
 
237
  key_avai = check_key_or_availability(key)
238
- info_dict = {#"account_name": "",
239
- "key_type": "OpenRouter",
240
- "key_availability": key_avai[0],
241
- "is_free_tier": "",
242
- "usage": "",
243
- "balance": "",
244
- "limit": "",
245
- "limit_remaining": "",
246
- "rate_limit_per_minite": "",
247
- "4_turbo_per_request_tokens_limit": "",
248
- "sonnet_per_request_tokens_limit": "",
249
- "opus_per_request_tokens_limit": ""}
250
- if key_avai[0]:
 
251
  models_info = check_key_or_limits(key)
252
- info_dict['is_free_tier'] = key_avai[1]['is_free_tier']
253
- info_dict['limit'] = key_avai[1]['limit']
254
- info_dict['limit_remaining'] = key_avai[1]['limit_remaining']
255
- info_dict['usage'] = f"${format(key_avai[1]['usage'], '.4f')}"
256
- info_dict['balance'] = f"${format(models_info[0], '.4f')}" if models_info[0] else f"${key_avai[2]/60} (estimated)"
257
- info_dict['rate_limit_per_minite'] = key_avai[2]
258
- info_dict['4_turbo_per_request_tokens_limit'] = models_info[1]['openai/gpt-4o']
259
- info_dict['sonnet_per_request_tokens_limit'] = models_info[1]['anthropic/claude-3.5-sonnet:beta']
260
- info_dict['opus_per_request_tokens_limit'] = models_info[1]['anthropic/claude-3-opus:beta']
261
- else:
262
- info_dict['usage'] = key_avai[1]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  return info_dict
264
 
265
- async def get_key_gcp_info(key, type):
 
266
  key_avai = await check_gcp_anthropic(key, type)
267
- info_dict = {#"account_name": "",
268
- "key_type": "Vertex AI (GCP)",
269
- "key_availability": key_avai[0],
270
- "status": "",
271
- "enabled_region": ""}
 
272
  if key_avai[0]:
273
- info_dict['enabled_region'] = key_avai[2]
274
- else:
275
- info_dict['status'] = key_avai[1]
276
  return info_dict
277
 
278
- def get_key_groq_info(key):
 
279
  key_avai = check_groq_status(key)
280
- info_dict = {#"account_name": "",
281
- "key_type": "Groq",
282
- "key_availability": True if key_avai else False,
283
- "models": key_avai if key_avai else ""}
 
284
  return info_dict
285
 
286
- def get_key_nai_info(key):
 
287
  key_avai = check_nai_status(key)
288
- info_dict = {#"account_name": "",
289
- "key_type": "NovelAI",
290
- "key_availability": True if key_avai[0] else False,
291
- "user_info": key_avai[1] if key_avai[0] else ""}
 
292
  return info_dict
293
-
294
- def get_key_elevenlabs_info(key):
 
295
  key_avai = check_elevenlabs_status(key)
296
- info_dict = {#"account_name": "",
297
- "key_type": "ElevenLabs",
298
- "key_availability": key_avai[0],
299
- "user_info": key_avai[1],
300
- "voices_info": key_avai[2]}
 
301
  return info_dict
302
 
303
- def get_key_xai_info(key):
 
304
  key_avai = check_xai_status(key)
305
- info_dict = {#"account_name": "",
306
- "key_type": "xAI Grok",
307
- "key_availability": key_avai[0],
308
- "key_status": "",
309
- "models": ""}
 
310
  if key_avai[0]:
311
- info_dict['key_status'] = key_avai[1]
312
- info_dict['models'] = key_avai[2]
313
  return info_dict
314
-
315
- def get_key_stability_info(key):
 
316
  key_avai = check_stability_status(key)
317
- info_dict = {#"account_name": "",
318
- "key_type": "Stability AI",
319
- "key_availability": key_avai[0],
320
- "account_info": "",
321
- "credits": "",
322
- "models": ""}
 
323
  if key_avai[0]:
324
- info_dict['account_info'] = key_avai[1]
325
- info_dict['credits'] = key_avai[2]
326
- info_dict['models'] = key_avai[3]
327
  return info_dict
328
 
329
- def get_key_deepseek_info(key):
 
330
  key_avai = check_deepseek_status(key)
331
- info_dict = {#"account_name": "",
332
- "key_type": "deepseek",
333
- "key_availability": key_avai[0],
334
- "balance": "",
335
- "models": ""}
336
- if key_avai[0]:
337
- info_dict['models'] = key_avai[1]
338
- info_dict['balance'] = key_avai[2]
 
339
  return info_dict
340
 
341
- def not_supported(key):
342
- info_dict = {#"account_name": "",
343
- "key_type": "Not supported",
344
- "status": ""}
345
- return info_dict
346
-
347
- def clear_inputs(text):
348
- return ""
349
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  with gr.Blocks() as demo:
351
- gr.Markdown('''
352
- # OpenAI/Anthropic/Gemini/Azure/Mistral/Replicate/AWS Claude/OpenRouter/Vertex AI(GCP Anthropic)/Groq/NovelAI/ElevenLabs/xAI/Stability/Deepseek API Key Status Checker
353
-
354
- *(Based on shaocongma, CncAnon1, su, Drago, kingbased key checkers)*
355
- AWS credential's format: AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY (root might not be accurate)
356
-
357
- Azure endpoint's format: YOUR_RESOURCE_NAME:YOUR_API_KEY or (https://)YOUR_RESOURCE_NAME.openai.azure.com;YOUR_API_KEY
358
-
359
- GCP format: PROJECT_ID:CLIENT_EMAIL:PRIVATE_KEY (including \\n)
360
- | or refresh token: PROJECT_ID:CLIENT_ID:CLIENT_SECRET:REFRESH_TOKEN
361
- ''')
 
 
 
362
  claude_options = [
363
- 'claude-3-haiku-20240307',
364
- 'claude-3-sonnet-20240229',
365
- 'claude-3-opus-20240229',
366
- 'claude-3-5-sonnet-20240620',
367
- 'claude-3-5-sonnet-20241022',
368
- 'claude-3-5-haiku-20241022'
369
  ]
 
370
  with gr.Row():
371
- with gr.Column():
372
- key = gr.Textbox(lines=1, max_lines=5, label="API Key")
373
- claude_model = gr.Dropdown(claude_options, value="claude-3-haiku-20240307", label="Claude API model", info="model for filter_response and concurrent check")
374
- rate_limit = gr.Checkbox(label="Check concurrent rate limit (API Claude, experimental)")
 
 
 
 
 
 
 
 
 
 
 
 
375
  with gr.Row():
376
- clear_button = gr.Button("Clear")
377
- submit_button = gr.Button("Submit", variant="primary")
378
- with gr.Column():
379
- info = gr.JSON(label="API Key Information", open=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
 
381
- clear_button.click(fn=clear_inputs, inputs=[key], outputs=[key])
382
- submit_button.click(fn=sort_key, inputs=[key, rate_limit, claude_model], outputs=[info], api_name="sort_key")
383
  demo.launch()
 
1
+ import asyncio
2
  import gradio as gr
3
+ import requests
4
+ import re
5
+ from typing import List, Dict, Tuple, Any # 添加类型提示
6
 
7
+ # 假设api_usage模块根据用户环境存在
8
+ # 导入需要的函数(实际使用时需要此模块)
9
+ from api_usage import (
10
+ get_subscription,
11
+ check_key_availability,
12
+ get_orgs_me,
13
+ check_key_ant_availability,
14
+ check_ant_rate_limit,
15
+ check_key_gemini_availability, # 假设此函数返回(bool, str)元组
16
+ check_key_azure_availability,
17
+ get_azure_status,
18
+ get_azure_deploy,
19
+ check_key_mistral_availability,
20
+ check_mistral_quota,
21
+ check_key_replicate_availability,
22
+ check_key_aws_availability,
23
+ check_key_or_availability,
24
+ check_key_or_limits,
25
+ check_gcp_anthropic,
26
+ check_groq_status,
27
+ check_nai_status,
28
+ check_elevenlabs_status,
29
+ check_xai_status,
30
+ check_stability_status,
31
+ check_deepseek_status,
32
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
+ # ─────────────────────────────────────────
35
+ # 特定密钥的帮助函数(保持原样 - 包括Gemini)
36
+ # ─────────────────────────────────────────
37
+ def get_key_oai_info(key: str) -> Dict[str, Any]:
38
+ session = requests.Session()
39
  status, org_data = check_key_availability(session, key)
40
 
41
  info_dict = {
 
50
  "requests_per_minute": "",
51
  "tokens_per_minute": "",
52
  "quota": "",
53
+ "all_models": "",
54
  }
55
 
56
  if not status:
 
60
  status_me, orgs_me = get_orgs_me(session, key)
61
  if status_me == 200:
62
  org_data = orgs_me
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
+ subscription_info = get_subscription(key, session, org_data)
65
+ if subscription_info:
66
+ info_dict.update(
67
+ {
68
+ "gpt4_availability": subscription_info.get("has_gpt4", ""),
69
+ "gpt4_32k_availability": subscription_info.get("has_gpt4_32k", ""),
70
+ "default_org": subscription_info.get("default_org", ""),
71
+ "org_description": subscription_info.get("org_description", ""),
72
+ "organization": subscription_info.get("organization", ""),
73
+ "models": subscription_info.get("models", ""),
74
+ "requests_per_minute": subscription_info.get("rpm", ""),
75
+ "tokens_per_minute": subscription_info.get("tpm", ""),
76
+ "quota": subscription_info.get("quota", ""),
77
+ "all_models": subscription_info.get("all_models", ""),
78
+ }
79
+ )
80
  return info_dict
81
 
82
+
83
+ async def get_key_ant_info(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
84
  key_avai = await check_key_ant_availability(key, claude_model)
85
+ info_dict = {
86
+ "key_type": "Anthropic Claude",
87
+ "key_availability": key_avai[0],
88
+ "status": "",
89
+ "filter_response": "",
90
+ "requests_per_minute": "",
91
+ "tokens_per_minute": "",
92
+ "tokens_input_per_minute": "",
93
+ "tokens_output_per_minute": "",
94
+ "tier": "",
95
+ "concurrent_rate_limit": "",
96
+ "models": "",
97
+ }
98
+
99
  info_dict["status"] = key_avai[1]
100
  info_dict["filter_response"] = key_avai[2]
101
  info_dict["requests_per_minute"] = key_avai[3] + ("" if key_avai[3] == "" else f" ({key_avai[4]} left)")
 
104
  info_dict["tokens_output_per_minute"] = key_avai[10] + ("" if key_avai[10] == "" else f" ({key_avai[11]} left)")
105
  info_dict["tier"] = key_avai[7]
106
  info_dict["models"] = key_avai[12]
107
+
108
  if rate_limit:
109
  rate = await check_ant_rate_limit(key, claude_model)
110
  info_dict["concurrent_rate_limit"] = rate
111
+
112
  return info_dict
113
 
114
+
115
+ # 保持用户原始的get_key_gemini_info函数
116
+ def get_key_gemini_info(key: str) -> Dict[str, Any]:
117
+ """获取Gemini密钥信息(用户原始版本)。"""
118
+ key_avai = check_key_gemini_availability(key) # 假设返回(bool, str)元组
119
+ info_dict = {
120
+ "key": key, # 原版中有key字段
121
+ "key_availability": key_avai[0],
122
+ "status": key_avai[1],
123
+ }
124
  return info_dict
125
 
126
+
127
+ def get_key_azure_info(endpoint: str, api_key: str) -> Dict[str, Any]:
128
  key_avai = check_key_azure_availability(endpoint, api_key)
129
+ info_dict = {
130
+ "key_type": "Microsoft Azure OpenAI",
131
+ "key_availability": key_avai[0],
132
+ "gpt35_availability": "",
133
+ "gpt4_availability": "",
134
+ "gpt4_32k_availability": "",
135
+ "dall_e_3_availability": "",
136
+ "moderation_status": "",
137
+ "models": "",
138
+ "deployments": "",
139
+ }
140
+ if key_avai[0]:
141
  azure_deploy = get_azure_deploy(endpoint, api_key)
142
+ if azure_deploy:
143
+ status = get_azure_status(endpoint, api_key, azure_deploy)
144
+ if status:
145
+ info_dict["gpt35_availability"] = status[1]
146
+ info_dict["gpt4_availability"] = status[2]
147
+ info_dict["gpt4_32k_availability"] = status[3]
148
+ info_dict["dall_e_3_availability"] = status[4]
149
+ info_dict["moderation_status"] = status[0]
150
  info_dict["models"] = key_avai[1]
151
+ info_dict["deployments"] = azure_deploy if azure_deploy else "N/A"
152
  return info_dict
153
 
154
+
155
+ def get_key_mistral_info(key: str) -> Dict[str, Any]:
156
  key_avai = check_key_mistral_availability(key)
157
+ info_dict = {
158
+ "key_type": "Mistral AI",
159
+ "key_availability": True if key_avai else False,
160
+ "has_quota": "",
161
+ "limits": "",
162
+ "models": "",
163
+ }
164
  if key_avai:
165
  quota_info = check_mistral_quota(key)
166
+ if quota_info:
167
+ info_dict["has_quota"] = quota_info[0]
168
+ if quota_info[1]:
169
+ info_dict["limits"] = quota_info[1]
170
+ info_dict["models"] = key_avai
171
  return info_dict
172
 
173
+
174
+ def get_key_replicate_info(key: str) -> Dict[str, Any]:
175
  key_avai = check_key_replicate_availability(key)
176
+ info_dict = {
177
+ "key_type": "Replicate",
178
+ "key_availability": key_avai[0],
179
+ "account_name": "",
180
+ "type": "",
181
+ "has_quota": "",
182
+ "hardware_available": "",
183
+ }
184
+ if key_avai[0] and isinstance(key_avai[1], dict):
185
+ info_dict["account_name"] = key_avai[1].get("username", "")
186
+ info_dict["type"] = key_avai[1].get("type", "")
187
+ info_dict["has_quota"] = key_avai[2]
188
+ info_dict["hardware_available"] = key_avai[3]
189
  return info_dict
190
 
191
+
192
+ async def get_key_aws_info(key: str) -> Dict[str, Any]:
193
  key_avai = await check_key_aws_availability(key)
194
+ info_dict = {
195
+ "key_type": "Amazon AWS Claude",
196
+ "key_availability": key_avai[0],
197
+ "username": "",
198
+ "root": "",
199
+ "admin": "",
200
+ "quarantine": "",
201
+ "iam_full_access": "",
202
+ "iam_user_change_password": "",
203
+ "aws_bedrock_full_access": "",
204
+ "enabled_region": "",
205
+ "models_usage": "",
206
+ "cost_and_usage": key_avai[1] if not key_avai[0] else "",
207
+ }
208
  if key_avai[0]:
209
+ info_dict["username"] = key_avai[1]
210
+ info_dict["root"] = key_avai[2]
211
+ info_dict["admin"] = key_avai[3]
212
+ info_dict["quarantine"] = key_avai[4]
213
+ info_dict["iam_full_access"] = key_avai[5]
214
+ info_dict["iam_user_change_password"] = key_avai[6]
215
+ info_dict["aws_bedrock_full_access"] = key_avai[7]
216
+ info_dict["enabled_region"] = key_avai[8]
217
+ info_dict["models_usage"] = key_avai[9]
218
+ info_dict["cost_and_usage"] = key_avai[10]
219
  return info_dict
220
 
221
+
222
+ def get_key_openrouter_info(key: str) -> Dict[str, Any]:
223
  key_avai = check_key_or_availability(key)
224
+ info_dict = {
225
+ "key_type": "OpenRouter",
226
+ "key_availability": key_avai[0],
227
+ "is_free_tier": "",
228
+ "usage": "",
229
+ "balance": "",
230
+ "limit": "",
231
+ "limit_remaining": "",
232
+ "rate_limit_per_minite": "",
233
+ "4_turbo_per_request_tokens_limit": "",
234
+ "sonnet_per_request_tokens_limit": "",
235
+ "opus_per_request_tokens_limit": "",
236
+ }
237
+ if key_avai[0] and isinstance(key_avai[1], dict):
238
  models_info = check_key_or_limits(key)
239
+ info_dict["is_free_tier"] = key_avai[1].get("is_free_tier", "")
240
+ info_dict["limit"] = key_avai[1].get("limit", "")
241
+ info_dict["limit_remaining"] = key_avai[1].get("limit_remaining", "")
242
+ usage_val = key_avai[1].get("usage")
243
+ info_dict["usage"] = f"${format(usage_val, '.4f')}" if isinstance(usage_val, (int, float)) else ""
244
+
245
+ balance_val = models_info[0] if models_info else None
246
+ rate_limit_val = key_avai[2] if len(key_avai) > 2 else None
247
+
248
+ if balance_val is not None:
249
+ info_dict["balance"] = f"${format(balance_val, '.4f')}"
250
+ elif rate_limit_val is not None:
251
+ try:
252
+ estimated_balance = float(rate_limit_val) / 60
253
+ info_dict["balance"] = f"${format(estimated_balance, '.4f')} (estimated)"
254
+ except (ValueError, TypeError):
255
+ info_dict["balance"] = "$N/A (estimation failed)"
256
+ else:
257
+ info_dict["balance"] = "$N/A"
258
+
259
+ info_dict["rate_limit_per_minite"] = rate_limit_val if rate_limit_val is not None else ""
260
+
261
+ if models_info and isinstance(models_info[1], dict):
262
+ model_limits = models_info[1]
263
+ info_dict["4_turbo_per_request_tokens_limit"] = model_limits.get("openai/gpt-4o", "")
264
+ info_dict["sonnet_per_request_tokens_limit"] = model_limits.get("anthropic/claude-3.5-sonnet:beta", "")
265
+ info_dict["opus_per_request_tokens_limit"] = model_limits.get("anthropic/claude-3-opus:beta", "")
266
+ elif not key_avai[0] and len(key_avai) > 1:
267
+ info_dict["usage"] = key_avai[1]
268
  return info_dict
269
 
270
+
271
+ async def get_key_gcp_info(key: str, type: int) -> Dict[str, Any]:
272
  key_avai = await check_gcp_anthropic(key, type)
273
+ info_dict = {
274
+ "key_type": "Vertex AI (GCP)",
275
+ "key_availability": key_avai[0],
276
+ "status": "",
277
+ "enabled_region": "",
278
+ }
279
  if key_avai[0]:
280
+ info_dict["enabled_region"] = key_avai[2]
281
+ elif len(key_avai) > 1:
282
+ info_dict["status"] = key_avai[1]
283
  return info_dict
284
 
285
+
286
+ def get_key_groq_info(key: str) -> Dict[str, Any]:
287
  key_avai = check_groq_status(key)
288
+ info_dict = {
289
+ "key_type": "Groq",
290
+ "key_availability": True if key_avai else False,
291
+ "models": key_avai if key_avai else "",
292
+ }
293
  return info_dict
294
 
295
+
296
+ def get_key_nai_info(key: str) -> Dict[str, Any]:
297
  key_avai = check_nai_status(key)
298
+ info_dict = {
299
+ "key_type": "NovelAI",
300
+ "key_availability": True if key_avai[0] else False,
301
+ "user_info": key_avai[1] if key_avai[0] else "",
302
+ }
303
  return info_dict
304
+
305
+
306
+ def get_key_elevenlabs_info(key: str) -> Dict[str, Any]:
307
  key_avai = check_elevenlabs_status(key)
308
+ info_dict = {
309
+ "key_type": "ElevenLabs",
310
+ "key_availability": key_avai[0],
311
+ "user_info": key_avai[1] if len(key_avai) > 1 else "",
312
+ "voices_info": key_avai[2] if len(key_avai) > 2 else "",
313
+ }
314
  return info_dict
315
 
316
+
317
+ def get_key_xai_info(key: str) -> Dict[str, Any]:
318
  key_avai = check_xai_status(key)
319
+ info_dict = {
320
+ "key_type": "xAI Grok",
321
+ "key_availability": key_avai[0],
322
+ "key_status": "",
323
+ "models": "",
324
+ }
325
  if key_avai[0]:
326
+ info_dict["key_status"] = key_avai[1] if len(key_avai) > 1 else ""
327
+ info_dict["models"] = key_avai[2] if len(key_avai) > 2 else ""
328
  return info_dict
329
+
330
+
331
+ def get_key_stability_info(key: str) -> Dict[str, Any]:
332
  key_avai = check_stability_status(key)
333
+ info_dict = {
334
+ "key_type": "Stability AI",
335
+ "key_availability": key_avai[0],
336
+ "account_info": "",
337
+ "credits": "",
338
+ "models": "",
339
+ }
340
  if key_avai[0]:
341
+ info_dict["account_info"] = key_avai[1] if len(key_avai) > 1 else ""
342
+ info_dict["credits"] = key_avai[2] if len(key_avai) > 2 else ""
343
+ info_dict["models"] = key_avai[3] if len(key_avai) > 3 else ""
344
  return info_dict
345
 
346
+
347
+ def get_key_deepseek_info(key: str) -> Dict[str, Any]:
348
  key_avai = check_deepseek_status(key)
349
+ info_dict = {
350
+ "key_type": "DeepSeek",
351
+ "key_availability": key_avai[0],
352
+ "balance": "",
353
+ "models": "",
354
+ }
355
+ if key_avai[0]:
356
+ info_dict["models"] = key_avai[1] if len(key_avai) > 1 else ""
357
+ info_dict["balance"] = key_avai[2] if len(key_avai) > 2 else ""
358
  return info_dict
359
 
 
 
 
 
 
 
 
 
360
 
361
+ def not_supported(key: str) -> Dict[str, Any]:
362
+ return {
363
+ "key_type": "Not supported",
364
+ "key_availability": False,
365
+ "status": "Unknown key format",
366
+ }
367
+
368
+
369
+ # ─────────────────────────────────────────
370
+ # 单个密钥异步处理(已更新)
371
+ # ─────────────────────────────────────────
372
+ async def process_single_key(key: str, rate_limit: bool, claude_model: str) -> Dict[str, Any]:
373
+ """分析给定的单个密钥并返回信息字典。包含Gemini密钥的工作状态标志。"""
374
+ _key = key.strip()
375
+
376
+ if not _key:
377
+ return {"key": "", "key_type": "Empty", "key_availability": False}
378
+
379
+ # OpenRouter
380
+ if re.match(re.compile(r"sk-or-v1-[a-z0-9]{64}"), _key):
381
+ result = get_key_openrouter_info(_key)
382
+ return {"key": _key, **result} # key_type在get_key_openrouter_info中返回
383
+
384
+ # Anthropic Claude
385
+ if re.match(re.compile(r"sk-ant-api03-[a-zA-Z0-9\-_]{93}AA"), _key) or \
386
+ (_key.startswith("sk-ant-") and len(_key) == 93) or \
387
+ (len(_key) == 89 and re.match(re.compile(r"sk-[a-zA-Z0-9]{86}"), _key)):
388
+ result = await get_key_ant_info(_key, rate_limit, claude_model)
389
+ return {"key": _key, **result} # 包含key_type
390
+
391
+ # Stability
392
+ if re.match(re.compile(r"sk-[a-zA-Z0-9]{48}"), _key) and len(_key) == 51 and "T3BlbkFJ" not in _key:
393
+ result = get_key_stability_info(_key)
394
+ return {"key": _key, **result} # 包含key_type
395
+
396
+ # Deepseek
397
+ if re.match(re.compile(r"sk-[a-f0-9]{32}"), _key):
398
+ result = get_key_deepseek_info(_key)
399
+ return {"key": _key, **result} # 包含key_type
400
+
401
+ # OpenAI (应该位于其他sk-模式之后)
402
+ if _key.startswith("sk-"):
403
+ result = get_key_oai_info(_key)
404
+ return {"key": _key, **result} # 包含key_type
405
+
406
+ # Google Gemini处理(已修改)
407
+ if _key.startswith("AIzaSy"):
408
+ gemini_info = get_key_gemini_info(_key) # 调用原始函数
409
+ # 添加工作状态标志(检查status)
410
+ is_working = gemini_info.get("key_availability") and gemini_info.get("status") == "Working"
411
+ # 构建结果字典:原始信息 + key_type + 工作状态标志
412
+ # gemini_info已经包含'key'
413
+ result = {
414
+ "key_type": "Google Gemini", # 明确添加类型信息
415
+ **gemini_info,
416
+ "is_gemini_working": is_working # 工作状态标志
417
+ }
418
+ return result
419
+
420
+ # NovelAI
421
+ if _key.startswith("pst-"):
422
+ result = get_key_nai_info(_key)
423
+ return {"key": _key, **result} # 包含key_type
424
+
425
+ # Replicate
426
+ if (_key.startswith("r8_") and len(_key) == 40) or (_key.islower() and len(_key) == 40):
427
+ result = get_key_replicate_info(_key)
428
+ return {"key": _key, **result} # 包含key_type
429
+
430
+ # xAI
431
+ if _key.startswith("xai-"):
432
+ result = get_key_xai_info(_key)
433
+ return {"key": _key, **result} # 包含key_type
434
+
435
+ # Azure endpoint: "name:key"
436
+ if len(_key.split(":")) == 2:
437
+ name, potential_key = _key.split(":", 1)
438
+ if re.fullmatch(r'[a-fA-F0-9]{32}', potential_key) and "openai.azure.com" not in name:
439
+ endpoint = f"https://{name}.openai.azure.com/"
440
+ api_key = potential_key
441
+ result = get_key_azure_info(endpoint, api_key)
442
+ return {"key": _key, **result} # 包含key_type
443
+
444
+ # Azure endpoint: "https://xxx.openai.azure.com;key"
445
+ if ";" in _key and "openai.azure.com" in _key.split(";")[0]:
446
+ endpoint, api_key = _key.split(";", 1)
447
+ result = get_key_azure_info(endpoint, api_key)
448
+ return {"key": _key, **result} # 包含key_type
449
+
450
+ # AWS
451
+ if _key.startswith("AKIA") and len(_key.split(":")[0]) == 20 and _key.split(":")[0].isalnum() and _key.split(":")[0].isupper() and len(_key.split(':')) == 2:
452
+ result = await get_key_aws_info(_key)
453
+ return {"key": _key, **result} # 包含key_type
454
+
455
+ # ElevenLabs
456
+ if re.fullmatch(r"[a-f0-9]{32}", _key) or re.fullmatch(r"sk_[a-f0-9]{48}", _key):
457
+ result = get_key_elevenlabs_info(_key)
458
+ return {"key": _key, **result} # 包含key_type
459
+
460
+ # Mistral
461
+ if re.fullmatch(r"[a-zA-Z0-9]{32}", _key) and not _key.startswith('sk-'):
462
+ result = get_key_mistral_info(_key)
463
+ return {"key": _key, **result} # 包含key_type
464
+
465
+ # Groq
466
+ if re.match(re.compile(r"gsk_[a-zA-Z0-9]{20}WGdyb3FY[a-zA-Z0-9]{24}"), _key):
467
+ result = get_key_groq_info(_key)
468
+ return {"key": _key, **result} # 包含key_type
469
+
470
+ # GCP - refresh token
471
+ if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+:.+"), _key):
472
+ parts = _key.split(':')
473
+ if len(parts) >= 4:
474
+ result = await get_key_gcp_info(_key, 0)
475
+ return {"key": _key, **result} # 包含key_type
476
+
477
+ # GCP - service account
478
+ if re.match(re.compile(r"[\w\-]+:[\w\-@\.]+:.+\\n"), _key):
479
+ parts = _key.split(':')
480
+ if len(parts) >= 3:
481
+ result = await get_key_gcp_info(_key, 1)
482
+ return {"key": _key, **result} # 包含key_type
483
+
484
+ # Not supported
485
+ result = not_supported(_key) # 包含key_type, key_availability, status
486
+ # 添加密钥值并返回
487
+ return {"key": _key, **result}
488
+
489
+
490
+ # ─────────────────────────────────────────
491
+ # 多密钥异步处理函数(已更新)
492
+ # ─────────────────────────────────────────
493
+ async def sort_keys(text: str, rate_limit: bool, claude_model: str) -> Tuple[List[Dict[str, Any]], str]:
494
+ """分析文本框中输入的多个密钥(按行),并返回完整结果和有效Gemini密钥列表。"""
495
+ keys = [k.strip() for k in text.splitlines() if k.strip()]
496
+ if not keys:
497
+ return [], ""
498
+
499
+ tasks = [process_single_key(k, rate_limit, claude_model) for k in keys]
500
+ results = await asyncio.gather(*tasks)
501
+
502
+ # 仅筛选有效的Gemini密钥(使用is_gemini_working标志)
503
+ working_gemini_keys = []
504
+ for result in results:
505
+ # 检查is_gemini_working键是否存在且为True
506
+ if result.get("is_gemini_working"): # 使用get()避免键不存在时出错
507
+ # 原始get_key_gemini_info包含'key'字段,可直接使用
508
+ working_gemini_keys.append(result["key"])
509
+
510
+ # 返回JSON列表结果和Gemini密钥列表字符串
511
+ return results, "\n".join(working_gemini_keys)
512
+
513
+
514
+ # ─────────────────────────────────────────
515
+ # UI工具函数
516
+ # ─────────────────────────────────────────
517
+ def clear_inputs(): # 移除输入参数(不需要key_box值)
518
+ return "", "", "" # 重置所有输入/输出
519
+
520
+
521
+ # ─────────────────────────────────────────
522
+ # Gradio界面(已更新)
523
+ # ─────────────────────────────────────────
524
  with gr.Blocks() as demo:
525
+ gr.Markdown(
526
+ """
527
+ # 多API密钥状态检查器(Gemini增强版)
528
+ *(基于shaocongmaCncAnon1suDragokingbased密钥检查器)*
529
+ 检查各种API密钥的状态和详细信息,包括OpenAI、Anthropic、Gemini、Azure、Mistral、Replicate、AWS Claude、OpenRouter、Vertex AI(GCP Anthropic)、Groq、NovelAI、ElevenLabs、xAI、Stability AI和DeepSeek。
530
+ **密钥格式:**
531
+ * **AWS:** `AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY`(root可能不准确)
532
+ * **Azure:** `RESOURCE_NAME:API_KEY` **或** `https://RESOURCE_NAME.openai.azure.com;API_KEY`
533
+ * **GCP服务账号:** `PROJECT_ID:CLIENT_EMAIL:PRIVATE_KEY`(确保在密钥中包含`\\n`作为换行符)
534
+ * **GCP刷新令牌:** `PROJECT_ID:CLIENT_ID:CLIENT_SECRET:REFRESH_TOKEN`
535
+ * **其他密钥:** 供应商提供的标准格式。
536
+ """
537
+ )
538
+
539
  claude_options = [
540
+ "claude-3-haiku-20240307",
541
+ "claude-3-sonnet-20240229",
542
+ "claude-3-opus-20240229",
543
+ "claude-3-5-sonnet-20240620",
 
 
544
  ]
545
+
546
  with gr.Row():
547
+ with gr.Column(scale=1):
548
+ key_box = gr.Textbox(
549
+ lines=5,
550
+ max_lines=20,
551
+ label="API密钥(每行一个)",
552
+ placeholder="在此处输入API密钥,每行一个。",
553
+ )
554
+ with gr.Row():
555
+ claude_model = gr.Dropdown(
556
+ claude_options,
557
+ value="claude-3-haiku-20240307",
558
+ label="Claude模型(用于过滤/并发检查)",
559
+ scale=3
560
+ )
561
+ rate_limit = gr.Checkbox(label="检查Claude并发限制(实验性)", scale=1)
562
+
563
  with gr.Row():
564
+ clear_button = gr.Button("清除所有")
565
+ submit_button = gr.Button("检查密钥", variant="primary")
566
+
567
+ with gr.Column(scale=2):
568
+ info = gr.JSON(label="API密钥信息(所有结果)", open=True)
569
+ # 添加Gemini专用输出框
570
+ gemini_keys_output = gr.Textbox(
571
+ label="有效的Gemini密钥",
572
+ info="列出确认为'有效'的Gemini密钥。",
573
+ lines=3,
574
+ max_lines=10,
575
+ interactive=False, # 用户不可编辑
576
+ )
577
+
578
+ # 点击清除按钮时重置输入框和输出框
579
+ clear_button.click(
580
+ fn=clear_inputs, # 使用修改后的函数
581
+ inputs=None,
582
+ outputs=[key_box, info, gemini_keys_output]
583
+ )
584
+
585
+ # 点击提交按钮时调用sort_keys函数并分配结果
586
+ submit_button.click(
587
+ fn=sort_keys,
588
+ inputs=[key_box, rate_limit, claude_model],
589
+ outputs=[info, gemini_keys_output], # 将结果映射到两个输出组件
590
+ api_name="sort_keys",
591
+ )
592
 
593
+ # demo.launch(share=True) # 需要时激活共享链接
 
594
  demo.launch()