号商用来挣钱的1脚本
Gmi.pyimport datetime
import json
import random
import string
import time
import httpx
from graph import EmailFetcher
def generate_random_string(length: int = 8) -> str:
"""Generate a random string of specified length using lowercase letters and numbers.
Args:
length: Length of the string to generate. Defaults to 8.
Returns:
str: Random string of specified length
"""
characters = string.ascii_lowercase + string.digits
return "".join(random.choice(characters) for _ in range(length))
def load_proxies():
"""Load and parse proxies from the proxies.txt file.
Returns:
list: List of proxy strings in format host:port:username:password
"""
proxies = []
try:
with open("proxies.txt", "r") as f:
for line in f:
line = line.strip()
if line:# Skip empty lines
proxies.append(line)
return proxies
except Exception as e:
print(f"Error loading proxies: {e}")
return []
def get_random_proxy(proxies):
"""Get a random proxy from the list.
Args:
proxies: List of proxy strings
Returns:
str: A random proxy string or None if list is empty
"""
if not proxies:
return None
return random.choice(proxies)
class RequestyClient:
"""Class for managing Requesty.ai account operations."""
BASE_API_URL = "https://inference-engine.gmicloud.ai/api/v1"
def __init__(
self, email: str, password: str, client_id: str, refresh_token: str, proxy=None
):
self.email = email
self.password = password
self.email_fetcher = EmailFetcher(client_id, refresh_token)
self.client_id = client_id
self.refresh_token = refresh_token
self.proxy = proxy
self.request_client_id = generate_random_string()# 生成唯一的客户端ID
# Setup client with or without proxy
if proxy:
# Format: host:port:username:password
proxy_host, proxy_port, proxy_user, proxy_pass = proxy.split(":")
# Construct the proxy URL in the correct format for httpx
proxy_url = f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
self.client = httpx.Client(proxy=proxy_url)
else:
self.client = httpx.Client()
# 设置默认请求头
self.client.headers.update({"ce-clientid": self.request_client_id})
self.code = None
self.emailVerificationToken = None
self.authToken = None
self.accessToken = None
self.refreshToken = None
self.organization_id = None
self.balance = None
self.apikey = None
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.client.close()
def register_account(self) -> bool:
try:
print(f"\nUsing client ID: {self.request_client_id}")
response = self.client.post(
f"{self.BASE_API_URL}/users",
json={
"email": self.email,
"password": self.password,
"firstName": self.email.split("@"),
"organization": {"name": self.email.split("@")},
},
)
if response.status_code != 201:
print(f"Failed to get emailVerificationToken: {response.status_code}")
print(response.text)
return False
response_json = response.json()
self.emailVerificationToken = response_json["emailVerificationToken"]
print(json.dumps(response_json, indent=4))
return True
except Exception as e:
print(f"\nError during account registration: {e}")
return False
def retrieve_verification_code(
self, subject="Confirm your email address", max_attempts=10
) -> bool:
verification_code_pattern = r"\b(\d{6})\b"
self.code = None
for i in range(max_attempts):
print(f"\nWaiting for email code... ({i + 1}/{max_attempts})")
try:
emails = self.email_fetcher.fetch_emails(
top=5, sender_filter="cluster-engine@gmicloud.ai"
)
if emails:
latest_email = emails
print(
f"Body Preview: {latest_email.get('bodyPreview', '').strip()}..."
)
if latest_email.get("subject") == subject:
self.code = self.email_fetcher.extract_verification_code(
latest_email, verification_code_pattern
)
if self.code:
print(f"\nVerification code: {self.code}")
return True
time.sleep(3)# Wait before checking again
except Exception as e:
print(f"\nError during email retrieval: {e}")
continue
print("Failed to retrieve verification code.")
return False
def verify_email(self) -> bool:
"""Verify email with the retrieved code.
Returns:
bool: True if verification successful, False otherwise
"""
try:
response = self.client.post(
f"{self.BASE_API_URL}/users/email-verification",
json={
"otpCode": self.code,
},
headers={
"Authorization": f"Bearer {self.emailVerificationToken}",
},
).json()
print(json.dumps(response, indent=4))
# Get session ID
if "id" in response:
self.session_id = response["id"]
print(f"\nSession ID: {self.session_id}")
return True
else:
print(f"\nError during email verification: {response}")
return False
except Exception as e:
print(f"\nError during email verification: {e}")
return False
def login(self) -> bool:
self.authToken = None
try:
response = self.client.post(
f"{self.BASE_API_URL}/me/auth-tokens",
json={
"email": self.email,
"password": self.password,
},
).json()
print(json.dumps(response, indent=4))
# Get organization ID
self.authToken = response["authToken"]
print(f"\nAuth Token: {self.authToken}")
return True
except Exception as e:
print(f"\nError during organization creation: {e}")
return False
def get_access_token(self) -> bool:
try:
response = self.client.post(
f"{self.BASE_API_URL}/me/sessions",
json={
"authToken": self.authToken,
"otpCode": self.code,
"type": "native",
},
).json()
print(json.dumps(response, indent=4))
self.accessToken = response["accessToken"]
self.refreshToken = response["refreshToken"]
print(f"\nAccess Token: {self.accessToken}")
print(f"\nRefresh Token: {self.refreshToken}")
return True
except Exception as e:
print(f"\nError during email verification: {e}")
return False
def get_organization(self) -> bool:
try:
response = self.client.get(
f"{self.BASE_API_URL}/me/profile",
headers={
"Authorization": f"Bearer {self.accessToken}",
},
).json()
print(json.dumps(response, indent=4))
self.organization_id = response["organization"]["id"]
print(f"\nOrganization ID: {self.organization_id}")
return True
except Exception as e:
print(f"\nError during email verification: {e}")
return False
def redeem_promotion(self) -> bool:
try:
response = self.client.post(
f"{self.BASE_API_URL}/billing/credit_coupons/INFERENCE/use",
headers={
"Authorization": f"Bearer {self.accessToken}",
},
).json()
print(json.dumps(response, indent=4))
valid = response["valid"]
if valid:
print(f"\nPromotion redeemed successfully: {valid}")
return True
else:
print(f"\nError during promotion redemption: {response}")
return False
except Exception as e:
print(f"\nError during promotion redemption: {e}")
return False
def get_balance(self) -> bool:
try:
response = self.client.get(
f"{self.BASE_API_URL}/billing/balance",
headers={
"Authorization": f"Bearer {self.accessToken}",
},
).json()
print(json.dumps(response, indent=4))
self.balance = response["balanceAmount"]
print(f"\nBalance: {self.balance}")
return True
except Exception as e:
print(f"\nError during balance retrieval: {e}")
return False
def create_api_key(self) -> bool:
try:
response = self.client.post(
f"{self.BASE_API_URL}/organizations/{self.organization_id}/api-keys",
headers={
"Authorization": f"Bearer {self.accessToken}",
},
json={"name": self.email.split("@"), "type": "ie_model"},
).json()
print(json.dumps(response, indent=4))
self.apikey = response["key"]
print(f"\nAPI Key: {self.apikey}")
return True
except Exception as e:
print(f"\nError during API key creation: {e}")
return False
def save_account_data(account_data: dict) -> None:
"""Save account data to a JSONL file.
Args:
account_data: Dictionary containing account information
"""
try:
# Add timestamp
account_data["created_at"] = datetime.datetime.now().isoformat()
# Append to JSONL file
with open("gmi_accounts.jsonl", "a", encoding="utf-8") as f:
f.write(json.dumps(account_data, ensure_ascii=False) + "\n")
except Exception as e:
print(f"\nError saving account data: {e}")
def process_account(
email: str,
password: str,
client_id: str,
refresh_token: str,
proxy=None,
) -> bool:
print(f"\nProcessing {email}...")
if proxy:
print(f"Using proxy: {proxy}")
with RequestyClient(email, password, client_id, refresh_token, proxy) as client:
# Step 2: Register account
if not client.register_account():
return False
# Step 4: Retrieve verification code
if not client.retrieve_verification_code():
return False
# Step 5: Verify email
if not client.verify_email():
return False
# Step 6: Create organization
if not client.login():
return False
# Step 4: Retrieve verification code
if not client.retrieve_verification_code(
subject="Two-Factor Authentication verification code"
):
return False
# Step 7: Get JWT token
if not client.get_access_token():
return False
if not client.get_organization():
return False
if not client.redeem_promotion():
return False
# Step 8: Get account balance
if not client.get_balance():
return False
# Step 9: Create API key
if not client.create_api_key():
return False
# Save account data
account_data = {
"email": email,
"password": password,
"client_id": client_id,
"refresh_token": refresh_token,
"proxy": proxy,
"api_key": client.apikey,
"balance": client.balance,
"organization_id": client.organization_id,
"gmi_access_token": client.accessToken,
"gmi_refresh_token": client.refreshToken,
}
save_account_data(account_data)
return True
def main():
# Load proxies
proxies = load_proxies()
# Process accounts from file
with open("accounts.txt", "r") as f:
for line in f:
try:
email, password, client_id, refresh_token = line.strip().split("----")
proxy = get_random_proxy(proxies)
process_account(email, password, client_id, refresh_token, proxy)
except Exception as e:
print(f"\nError processing account: {e}")
if __name__ == "__main__":
main()
Graph.py
import httpx
import re
import time
import random
# --- Custom Exceptions ---
class EmailFetcherError(Exception):
"""Base exception for EmailFetcher errors."""
pass
class TokenError(EmailFetcherError):
"""Raised when there's an error obtaining the access token."""
pass
class GraphApiError(EmailFetcherError):
"""Raised when there's an error during a Microsoft Graph API call."""
pass
class InvalidRegexError(EmailFetcherError):
"""Raised when the provided regex pattern is invalid."""
pass
# --- End Custom Exceptions ---
class EmailFetcher:
BASE_URL = "https://graph.microsoft.com/v1.0"
TOKEN_URL = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"
MAX_RETRIES = 3# Maximum number of retry attempts
BASE_RETRY_DELAY = 2# Base delay in seconds
def __init__(self, client_id, refresh_token):
self.client_id = client_id
self.refresh_token = refresh_token
self.access_token = None
def _get_access_token(self):
"""Retrieves or refreshes the access token. Raises TokenError on failure."""
data = {
"client_id": self.client_id,
"grant_type": "refresh_token",
"refresh_token": self.refresh_token,
"scope": "https://graph.microsoft.com/.default",
}
retries = 0
while retries <= self.MAX_RETRIES:
try:
response = httpx.post(self.TOKEN_URL, data=data)
# Handle 429 Too Many Requests specifically
if response.status_code == 429:
if retries == self.MAX_RETRIES:
error_msg = f"Token request failed after {self.MAX_RETRIES} retries due to rate limiting (429)"
print(error_msg)
raise TokenError(error_msg)
# Get retry-after header if available, otherwise use exponential backoff
retry_after = response.headers.get('Retry-After')
if retry_after and retry_after.isdigit():
delay = int(retry_after)
else:
# Exponential backoff with jitter
delay = self.BASE_RETRY_DELAY * (2 ** retries) + random.uniform(0, 1)
print(f"Rate limited (429). Retrying in {delay:.2f} seconds... (Attempt {retries+1}/{self.MAX_RETRIES})")
time.sleep(delay)
retries += 1
continue
response.raise_for_status()# Raise an exception for other bad status codes
result = response.json()
if "error" in result:
error_msg = f"Access token error: {result.get('error')}, Description: {result.get('error_description')}"
print(error_msg)# Also print for immediate feedback
raise TokenError(error_msg)
self.access_token = result.get("access_token")
if not self.access_token:
raise TokenError("No access token found in the response.")
return self.access_token
except httpx.HTTPStatusError as e:
# For other HTTP errors that aren't 429
if e.response.status_code != 429:
error_msg = f"Token request failed with status {e.response.status_code}: {e.response.text}"
print(error_msg)
raise TokenError(error_msg) from e
# 429 errors are handled in the code above
except httpx.RequestError as e:
error_msg = f"Token request network error: {e}"
print(error_msg)
raise TokenError(error_msg) from e
except Exception as e:
if isinstance(e, TokenError):
raise# Re-raise TokenError without wrapping
error_msg = f"An unexpected error occurred during token request: {e}"
print(error_msg)
raise TokenError(error_msg) from e
def fetch_emails(self, top=50, sender_filter=None):
"""
Fetches emails and performs client-side filtering.
Raises TokenError or GraphApiError on failure.
Args:
top: Maximum number of emails to fetch
sender_filter: Optional email address to filter by (client-side filtering)
Returns:
List of filtered email objects
"""
try:
if not self.access_token:
# Attempt to get token, will raise TokenError if it fails
self._get_access_token()
except TokenError as e:
# Re-raise token errors so the caller knows token fetch failed
raise GraphApiError(
"Failed to obtain access token before fetching emails."
) from e
# Construct the base URL
url = f"{self.BASE_URL}/me/messages"
# Prepare query parameters - only use ordering and top, no server-side filtering
params = {"$orderby": "receivedDateTime desc", "$top": top}
headers = {"Authorization": f"Bearer {self.access_token}"}
retries = 0
while retries <= self.MAX_RETRIES:
try:
response = httpx.get(url, headers=headers, params=params)
# Handle 429 Too Many Requests specifically
if response.status_code == 429:
if retries == self.MAX_RETRIES:
error_msg = f"Graph API request failed after {self.MAX_RETRIES} retries due to rate limiting (429)"
print(error_msg)
raise GraphApiError(error_msg)
# Get retry-after header if available, otherwise use exponential backoff
retry_after = response.headers.get('Retry-After')
if retry_after and retry_after.isdigit():
delay = int(retry_after)
else:
# Exponential backoff with jitter
delay = self.BASE_RETRY_DELAY * (2 ** retries) + random.uniform(0, 1)
print(f"Rate limited (429). Retrying in {delay:.2f} seconds... (Attempt {retries+1}/{self.MAX_RETRIES})")
time.sleep(delay)
retries += 1
continue
response.raise_for_status()# Check for other HTTP errors
all_emails = response.json().get("value", [])
# Perform client-side filtering if a sender filter is specified
if sender_filter and all_emails:
filtered_emails = []
for email in all_emails:
sender_address = (
email.get("from", {}).get("emailAddress", {}).get("address", "")
)
if (
sender_address
and sender_filter.lower() in sender_address.lower()
):
filtered_emails.append(email)
return filtered_emails
# Return all emails if no filter is specified
return all_emails
except httpx.HTTPStatusError as e:
# For other HTTP errors that aren't 429
if e.response.status_code != 429:
error_msg = f"Graph API request failed with status {e.response.status_code}: {e.response.text}"
print(error_msg)
# Handle specific errors like token expiry if needed
if e.response.status_code == 401:# Unauthorized - token might have expired
print(
"Access token might be invalid or expired. Clearing token for retry."
)
self.access_token = None# Clear token
raise GraphApiError(error_msg) from e
# 429 errors are handled in the code above
except httpx.RequestError as e:
error_msg = f"Graph API request network error: {e}"
print(error_msg)
raise GraphApiError(error_msg) from e
except Exception as e:
error_msg = f"An unexpected error occurred during Graph API request: {e}"
print(error_msg)
raise GraphApiError(error_msg) from e
def extract_verification_code(self, email, pattern):
"""Extracts code using regex. Raises InvalidRegexError or returns None."""
if not email or not isinstance(email, dict):
return None
subject = email.get("subject", "")
body_preview = email.get("bodyPreview", "")
body_content = email.get("body", {}).get("content", "")
try:
regex = re.compile(pattern)
except re.error as e:
error_msg = f"Invalid regex pattern '{pattern}': {e}"
print(error_msg)
raise InvalidRegexError(error_msg) from e
# Search order: subject, body preview, full body
for text_source in :
if text_source:# Ensure source is not None or empty
match = regex.search(text_source)
if match:
# Assuming the code is in the first capture group
# If pattern has no groups, match.group(0) is the whole match
return match.group(1) if regex.groups >= 1 else match.group(0)
return None# No code found
页:
[1]