From ab21d7661d95133eec66da74a4058c262cb6d4fd Mon Sep 17 00:00:00 2001 From: based Date: Fri, 11 Apr 2025 02:28:53 +1000 Subject: [PATCH] xai checker + non standard oai model detection --- APIKey.py | 7 +++ OpenAI.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++------- README.md | 1 + XAI.py | 30 +++++++++++++ main.py | 30 +++++++++++-- 5 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 XAI.py diff --git a/APIKey.py b/APIKey.py index fde6ec2..3dc31c9 100644 --- a/APIKey.py +++ b/APIKey.py @@ -16,6 +16,8 @@ class APIKey: self.has_special_models = False self.real_32k = False self.the_one = False + self.extra_models = False + self.extra_model_list = [] elif provider == Provider.ANTHROPIC: self.pozzed = False @@ -78,6 +80,10 @@ class APIKey: self.available = False self.rate_limited = False + elif provider == Provider.XAI: + self.blocked = True + self.subbed = False + def clone(self): cloned_key = APIKey(self.provider, self.api_key) cloned_key.__dict__ = self.__dict__.copy() @@ -96,3 +102,4 @@ class Provider(Enum): OPENROUTER = 9 ELEVENLABS = 10 DEEPSEEK = 11 + XAI = 12 diff --git a/OpenAI.py b/OpenAI.py index cbfc753..48a2d80 100644 --- a/OpenAI.py +++ b/OpenAI.py @@ -4,6 +4,82 @@ import asyncio oai_api_url = "https://api.openai.com/v1" oai_tiers = {40000: 'Free', 200000: 'Tier1', 2000000: 'Tier2', 4000000: 'Tier3', 10000000: 'Tier4', 150000000: 'Tier5'} +standard_model_ids = { + "omni-moderation-2024-09-26", + "gpt-4o-mini-audio-preview-2024-12-17", + "dall-e-3", + "dall-e-2", + "gpt-4o-audio-preview-2024-10-01", + "o1", + "gpt-4o-audio-preview", + "gpt-4o-mini-realtime-preview-2024-12-17", + "o1-2024-12-17", + "gpt-4-0314", + "gpt-4o-mini-realtime-preview", + "o1-mini-2024-09-12", + "o1-preview-2024-09-12", + "o1-mini", + "o1-preview", + "gpt-4o-mini-audio-preview", + "whisper-1", + "gpt-4-turbo", + "gpt-4-32k-0314", + "gpt-4o-realtime-preview-2024-10-01", + "gpt-4", + "babbage-002", + "gpt-4-turbo-preview", + "tts-1-hd-1106", + "gpt-4-0125-preview", + "gpt-4o-audio-preview-2024-12-17", + "tts-1-hd", + "gpt-4o-mini-2024-07-18", + "gpt-4o-2024-08-06", + "gpt-4o", + "tts-1", + "tts-1-1106", + "gpt-4-turbo-2024-04-09", + "davinci-002", + "gpt-3.5-turbo-1106", + "gpt-4o-mini", + "gpt-4o-2024-05-13", + "gpt-3.5-turbo-instruct", + "chatgpt-4o-latest", + "gpt-3.5-turbo-instruct-0914", + "gpt-3.5-turbo-0125", + "gpt-4o-realtime-preview-2024-12-17", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k-0613", + "gpt-4o-realtime-preview", + "gpt-3.5-turbo-16k", + "text-embedding-3-small", + "gpt-4o-2024-11-20", + "gpt-4-1106-preview", + "text-embedding-ada-002", + "text-embedding-3-large", + "o3-mini-2025-01-31", + "gpt-4-0613", + "gpt-4-32k-0613", + "o3-mini", + "omni-moderation-latest", + "gpt-4-base", + "gpt-4-32k", + "o1-pro", + "o1-pro-2025-03-19", + "gpt-4o-transcribe", + "computer-use-preview", + "computer-use-preview-2025-03-11", + "gpt-4o-search-preview", + "gpt-4o-search-preview-2025-03-11", + "gpt-4o-mini-search-preview", + "gpt-4o-mini-search-preview-2025-03-11", + "gpt-4o-mini-transcribe", + "gpt-4o-mini-tts", + "gpt-4.5-preview", + "gpt-4.5-preview-2025-02-27", + "o3", + "o4-mini", +} + async def get_oai_model(key: APIKey, session, retries, org=None): for _ in range(retries): @@ -13,23 +89,36 @@ async def get_oai_model(key: APIKey, session, retries, org=None): async with session.get(f'{oai_api_url}/models', headers=headers) as response: if response.status == 200: data = await response.json() - models = sorted(data["data"], key=lambda m: len(m["id"])) - top_model = "gpt-4o-mini" - for model in models: - if "ft:" in model["id"]: + + model_priority = ["gpt-4-32k-0314", "gpt-4o", "gpt-4o-mini"] + available_priority_models = set() + + for model in data["data"]: + model_id = model["id"] + + if "ft:" in model_id: key.has_special_models = True - if model["id"] == "gpt-4-base": + elif model_id not in standard_model_ids and ":ft-" not in model_id: + key.extra_models = True + key.extra_model_list.append(model_id) + + if model_id == "gpt-4-base": key.the_one = True - if model["id"] == "gpt-4-32k": + if model_id == "gpt-4-32k" or model_id == "gpt-4-32k-0613": key.real_32k = True - if model["id"] == "gpt-4-32k-0314": - top_model = model["id"] - elif model["id"] == "gpt-4o": - top_model = model["id"] - key.model = top_model + + if model_id in model_priority: + available_priority_models.add(model_id) + + key.model = "gpt-4o-mini" + for priority_model in model_priority: + if priority_model in available_priority_models: + key.model = priority_model + break + return True elif response.status == 403: - key.model = "gpt-4o" + key.model = "gpt-4o-mini" return True elif response.status != 502: return @@ -177,13 +266,15 @@ def pretty_print_oai_keys(keys, cloned_keys): + (f" | default org - {key.default_org}" if key.default_org else "") + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + f" | {key.rpm} RPM" + (f" - {key.tier}" if key.tier else "") - + (" (RPM increased via request)" if check_manual_increase(key) else "")) + + (" (RPM increased via request)" if check_manual_increase(key) else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "")) print(f'\nValidated {len(key_groups["gpt-4o-mini"]["no_quota"])} gpt-4o-mini keys with no quota:') for key in key_groups["gpt-4o-mini"]["no_quota"]: print(f"{key.api_key}" + (f" | default org - {key.default_org}" if key.default_org else "") - + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "")) + + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "")) print(f'\nValidated {len(key_groups["gpt-4o"]["has_quota"])} gpt-4o keys with quota:') for key in key_groups["gpt-4o"]["has_quota"]: @@ -192,14 +283,16 @@ def pretty_print_oai_keys(keys, cloned_keys): + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + f" | {key.rpm} RPM" + (f" - {key.tier}" if key.tier else "") + (" (RPM increased via request)" if check_manual_increase(key) else "") - + (f" | key has finetuned models" if key.has_special_models else "")) + + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "")) print(f'\nValidated {len(key_groups["gpt-4o"]["no_quota"])} gpt-4o keys with no quota:') for key in key_groups["gpt-4o"]["no_quota"]: print(f"{key.api_key}" + (f" | default org - {key.default_org}" if key.default_org else "") + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") - + (f" | key has finetuned models" if key.has_special_models else "")) + + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "")) print(f'\nValidated {len(key_groups["gpt-4-32k-0314"]["has_quota"])} gpt-4-32k keys with quota:') for key in key_groups["gpt-4-32k-0314"]["has_quota"]: @@ -209,6 +302,7 @@ def pretty_print_oai_keys(keys, cloned_keys): + f" | {key.rpm} RPM" + (f" - {key.tier}" if key.tier else "") + (" (RPM increased via request)" if check_manual_increase(key) else "") + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "") + (f" | real 32k key (pre deprecation)" if key.real_32k else "") + (f" | !!!god key!!!" if key.the_one else "")) @@ -218,6 +312,7 @@ def pretty_print_oai_keys(keys, cloned_keys): + (f" | default org - {key.default_org}" if key.default_org else "") + (f" | other orgs - {key.organizations}" if len(key.organizations) > 1 else "") + (f" | key has finetuned models" if key.has_special_models else "") + + (f" | key has access to non-standard models: {', '.join(key.extra_model_list)}" if key.extra_models else "") + (f" | real 32k key (pre deprecation)" if key.real_32k else "") + (f" | !!!god key!!!" if key.the_one else "")) diff --git a/README.md b/README.md index bc4a10d..e0b72db 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ Currently supports and validates keys for the services below, and checks for the - OpenRouter - (Estimated balance, usage in $, credit limit, RPM, has purchased any credits) - ElevenLabs - (Key tier, remaining characters in plan, detect uncapped char quota, pro voice cloning limit, invoice details on pay as you go plans) - DeepSeek - (Account balance) +- xAI - (Subscription status) # Usage: `pip install -r requirements.txt` diff --git a/XAI.py b/XAI.py new file mode 100644 index 0000000..7a52c4a --- /dev/null +++ b/XAI.py @@ -0,0 +1,30 @@ +import APIKey + +async def check_xai(key: APIKey, session): + async with session.get(f'https://api.x.ai/v1/api-key', headers={'Authorization': f'Bearer {key.api_key}'}) as response: + if response.status != 200: + return + data = await response.json() + key.blocked = data.get('team_blocked', True) or data.get('api_key_blocked', True) or data.get('api_key_disabled', True) + if not key.blocked: + key.subbed = await test_xai_prompt(key, session) + return True + + +async def test_xai_prompt(key: APIKey, session): + data = {"messages": [], "model": "grok-3-mini-latest", "frequency_penalty": -3.0} + async with session.post(f'https://api.x.ai/v1/chat/completions', headers={'Authorization': f'Bearer {key.api_key}'}, json=data) as response: + if response.status == 400 or response.status == 200: + return True + return False + +def pretty_print_xai_keys(keys): + keys = sorted(keys, key=lambda x: x.subbed, reverse=True) + print('-' * 90) + subbed = 0 + print(f'Validated {len(keys)} xAI keys:') + for key in keys: + if key.subbed: + subbed += 1 + print(f'{key.api_key}' + (' | has sub active' if key.subbed else '')) + print(f'\n--- Total Valid xAI Keys: {len(keys)} ({subbed} with an active subscription) ---\n') \ No newline at end of file diff --git a/main.py b/main.py index 0197d2a..909e332 100644 --- a/main.py +++ b/main.py @@ -10,6 +10,7 @@ from VertexAI import check_vertexai, pretty_print_vertexai_keys from Mistral import check_mistral, pretty_print_mistral_keys from OpenRouter import check_openrouter, pretty_print_openrouter_keys from ElevenLabs import check_elevenlabs, pretty_print_elevenlabs_keys +from XAI import check_xai, pretty_print_xai_keys from APIKey import APIKey, Provider from concurrent.futures import ThreadPoolExecutor, as_completed @@ -144,6 +145,16 @@ async def validate_elevenlabs(key: APIKey, sem): api_keys.add(key) +async def validate_xai(key: APIKey, sem): + async with sem, aiohttp.ClientSession() as session: + IO.conditional_print(f"Checking xAI key: {key.api_key}", args.verbose) + if await check_xai(key, session) is None: + IO.conditional_print(f"Invalid xAI key: {key.api_key}", args.verbose) + return + IO.conditional_print(f"xAI key '{key.api_key}' is valid", args.verbose) + api_keys.add(key) + + def validate_aws(key: APIKey): IO.conditional_print(f"Checking AWS key: {key.api_key}", args.verbose) if check_aws(key) is None: @@ -235,6 +246,7 @@ aws_regex = re.compile(r'^(AKIA[0-9A-Z]{16}):([A-Za-z0-9+/]{40})$') azure_regex = re.compile(r'^(.+):([a-z0-9]{32})$') openrouter_regex = re.compile(r'sk-or-v1-[a-z0-9]{64}') deepseek_regex = re.compile(r'sk-[a-f0-9]{32}') +xai_regex = re.compile(r'xai-[A-Za-z0-9]{80}') # vertex_regex = re.compile(r'^(.+):(ya29.[A-Za-z0-9\-_]{469})$') regex for the oauth tokens, useless since they expire hourly executor = ThreadPoolExecutor(max_workers=100) concurrent_connections = asyncio.Semaphore(1500) @@ -263,6 +275,12 @@ async def validate_keys(): continue key_obj = APIKey(Provider.MAKERSUITE, key) tasks.append(execute_with_retries(validate_makersuite, key_obj, makersuite_semaphore, 5)) + elif "xai-" in key[:4]: + match = xai_regex.match(key) + if not match: + continue + key_obj = APIKey(Provider.XAI, key) + tasks.append(execute_with_retries(validate_xai, key_obj, concurrent_connections, 5)) elif "sk-or-v1-" in key: match = openrouter_regex.match(key) if not match: @@ -321,7 +339,7 @@ async def validate_keys(): futures.clear() -def get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, valid_makersuite_keys, valid_aws_keys, valid_azure_keys, valid_vertexai_keys, valid_mistral_keys, valid_openrouter_keys, valid_elevenlabs_keys, valid_deepseek_keys): +def get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, valid_makersuite_keys, valid_aws_keys, valid_azure_keys, valid_vertexai_keys, valid_mistral_keys, valid_openrouter_keys, valid_elevenlabs_keys, valid_deepseek_keys, valid_xai_keys): valid_oai_keys_set = set([key.api_key for key in valid_oai_keys]) valid_anthropic_keys_set = set([key.api_key for key in valid_anthropic_keys]) valid_ai21_keys_set = set([key.api_key for key in valid_ai21_keys]) @@ -333,8 +351,9 @@ def get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, vali valid_openrouter_keys_set = set([key.api_key for key in valid_openrouter_keys]) valid_elevenlabs_set = set([key.api_key for key in valid_elevenlabs_keys]) valid_deepseek_set = set([key.api_key for key in valid_deepseek_keys]) + valid_xai_set = set([key.api_key for key in valid_xai_keys]) - invalid_keys = inputted_keys - valid_oai_keys_set - valid_anthropic_keys_set - valid_ai21_keys_set - valid_makersuite_keys_set - valid_aws_keys_set - valid_azure_keys_set - valid_vertexai_keys_set - valid_mistral_keys_set - valid_openrouter_keys_set - valid_elevenlabs_set - valid_deepseek_set + invalid_keys = inputted_keys - valid_oai_keys_set - valid_anthropic_keys_set - valid_ai21_keys_set - valid_makersuite_keys_set - valid_aws_keys_set - valid_azure_keys_set - valid_vertexai_keys_set - valid_mistral_keys_set - valid_openrouter_keys_set - valid_elevenlabs_set - valid_deepseek_set - valid_xai_set invalid_keys_len = len(invalid_keys) + len(cloned_keys) if cloned_keys else len(invalid_keys) if invalid_keys_len < 1: return @@ -357,6 +376,7 @@ def output_keys(): valid_openrouter_keys = [] valid_elevenlabs_keys = [] valid_deepseek_keys = [] + valid_xai_keys = [] for key in api_keys: if key.provider == Provider.OPENAI: @@ -381,6 +401,8 @@ def output_keys(): valid_elevenlabs_keys.append(key) elif key.provider == Provider.DEEPSEEK: valid_deepseek_keys.append(key) + elif key.provider == Provider.XAI: + valid_xai_keys.append(key) if should_write: output_filename = "key_snapshots.txt" @@ -392,7 +414,7 @@ def output_keys(): print(f"Key snapshot from {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("#" * 90) print(f'\n--- Checked {len(inputted_keys)} keys | {invalid_keys} were invalid ---') - get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, valid_makersuite_keys, valid_aws_keys, valid_azure_keys, valid_vertexai_keys, valid_mistral_keys, valid_openrouter_keys, valid_elevenlabs_keys, valid_deepseek_keys) + get_invalid_keys(valid_oai_keys, valid_anthropic_keys, valid_ai21_keys, valid_makersuite_keys, valid_aws_keys, valid_azure_keys, valid_vertexai_keys, valid_mistral_keys, valid_openrouter_keys, valid_elevenlabs_keys, valid_deepseek_keys, valid_xai_keys) print() if valid_oai_keys: pretty_print_oai_keys(valid_oai_keys, cloned_keys) @@ -416,6 +438,8 @@ def output_keys(): pretty_print_elevenlabs_keys(valid_elevenlabs_keys) if valid_deepseek_keys: pretty_print_deepseek_keys(valid_deepseek_keys) + if valid_xai_keys: + pretty_print_xai_keys(valid_xai_keys) else: print("OPENAI_KEY=" + ','.join(key.api_key for key in valid_oai_keys if key.has_quota)) print("ANTHROPIC_KEY=" + ','.join(key.api_key for key in valid_anthropic_keys if key.has_quota))