import os import time import json import hmac import hashlib import datetime import requests import redis import sys # ========================================== # ๐Ÿ”ง Config (Hardcoded for Debugging) # ========================================== # Try to load from env, fallback to hardcoded (Matches volc_limit_sync.py defaults) ACCESS_KEY = os.getenv( "VOLC_ACCESS_KEY", "AKLTNGYxZmUyNzNmZjk3NGMyZmEzNjVjZmY4NGM5ZjcxMjU" ) SECRET_KEY = os.getenv( "VOLC_SECRET_KEY", "Tm1VNE5XSmlORGs1WXpGbU5EVmtabUUyT1RZeVltTTBNalkxTWpjeE1tTQ==" ) HOST = "open.volcengineapi.com" REGION = "cn-beijing" REDIS_HOST = os.getenv( "REDIS_HOST", "redis" ) # Assuming running inside container or mapped REDIS_PORT = int(os.getenv("REDIS_PORT", 6379)) REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None) print( f"๐Ÿ”ง Config: AK={ACCESS_KEY[:4]}***, SK={SECRET_KEY[:4]}***, Redis={REDIS_HOST}:{REDIS_PORT}" ) # ========================================== # ๐Ÿ”Œ Redis Connection # ========================================== try: print(f"๐Ÿ”Œ Connecting to Redis at {REDIS_HOST}:{REDIS_PORT}...") r = redis.Redis( host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, decode_responses=True ) r.ping() print("โœ… Redis Connected Successfully!") except Exception as e: print(f"โŒ Redis Connection Failed: {e}") print("โš ๏ธ Script will continue but cannot check Redis keys.") r = None # ========================================== # ๐Ÿ—๏ธ Volcengine Signing Logic # ========================================== def sign(key, msg): return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest() def get_signature_key(key, date_stamp, region_name, service_name): k_date = sign(key.encode("utf-8"), date_stamp) k_region = sign(k_date, region_name) k_service = sign(k_region, service_name) k_signing = sign(k_service, "request") return k_signing def get_signed_headers(action, version, body_dict, service="billing"): t = datetime.datetime.utcnow() amz_date = t.strftime("%Y%m%dT%H%M%SZ") date_stamp = t.strftime("%Y%m%d") request_body = json.dumps(body_dict) payload_hash = hashlib.sha256(request_body.encode("utf-8")).hexdigest() canonical_headers = f"content-type:application/json\nhost:{HOST}\nx-content-sha256:{payload_hash}\nx-date:{amz_date}\n" signed_headers = "content-type;host;x-content-sha256;x-date" canonical_request = f"POST\n/\nAction={action}&Version={version}\n{canonical_headers}\n{signed_headers}\n{payload_hash}" credential_scope = f"{date_stamp}/{REGION}/{service}/request" string_to_sign = f"HMAC-SHA256\n{amz_date}\n{credential_scope}\n{hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()}" signing_key = get_signature_key(SECRET_KEY, date_stamp, REGION, service) signature = hmac.new( signing_key, string_to_sign.encode("utf-8"), hashlib.sha256 ).hexdigest() authorization_header = f"HMAC-SHA256 Credential={ACCESS_KEY}/{credential_scope}, SignedHeaders={signed_headers}, Signature={signature}" return { "Content-Type": "application/json", "Host": HOST, "X-Date": amz_date, "X-Content-Sha256": payload_hash, "Authorization": authorization_header, }, request_body # ========================================== # ๐Ÿ“ฆ API Fetch Logic # ========================================== def fetch_all_packages(): print("\n๐Ÿš€ Fetching Volcengine Packages...") action = "ListResourcePackages" version = "2022-01-01" all_packages = [] current_token = "" page_count = 0 MAX_PAGES = 15 # ๐Ÿ›‘ Safety Limit for Debugging seen_tokens = set() while True: try: page_count += 1 if page_count > MAX_PAGES: print( f"โš ๏ธ Reached MAX_PAGES ({MAX_PAGES}). Stopping fetch to prevent infinite loop." ) break payload = { "ResourceType": "Package", "MaxResults": "20", "NextToken": current_token, } headers, body = get_signed_headers(action, version, payload) url = f"https://{HOST}/?Action={action}&Version={version}" print(f" [Page {page_count}] POST {url} (Token: {current_token[:10]}...)") response = requests.post(url, data=body, headers=headers, timeout=60) if response.status_code != 200: print(f"โŒ API Error {response.status_code}: {response.text}") break data = response.json() items = data.get("Result", {}).get("List", []) print(f" Found {len(items)} items in this page.") if items: all_packages.extend(items) next_token = data.get("Result", {}).get("NextToken", "") if not next_token: print(" โœ… No NextToken. Done.") break if next_token == current_token: print(" โš ๏ธ NextToken did not change. Stopping.") break if next_token in seen_tokens: print( f" โš ๏ธ Detected pagination cycle with token {next_token[:10]}... Stopping." ) break seen_tokens.add(next_token) current_token = next_token time.sleep(0.2) except Exception as e: print(f"โŒ Exception fetching packages: {e}") break return all_packages # ========================================== # ๐Ÿ“Š Processing Logic # ========================================== VOLC_MODEL_MAP = { "doubao-seed-1-6": ["doubao-seed-1-6-250615", "doubao-seed-1-6-251015"], "doubao-seed-1-8": "doubao-seed-1-8-251228", "doubao-seed-2-0-pro": "doubao-seed-2-0-pro-260215", "doubao-seed-2-0-lite": "doubao-seed-2-0-lite-260215", "doubao-seed-code": "doubao-seed-code-preview-251028", "doubao-seed-translation": "doubao-seed-translation-250915", "deepseek-v3": "deepseek-v3-250324", "deepseek-v3-1": "deepseek-v3-1-terminus", "deepseek-v3-2": "deepseek-v3-2-251201", "deepseek-r1": "deepseek-r1-250528", "kimi-k2": "kimi-k2-thinking-251104", "glm-4_7": "glm-4-7-251222", "glm-4-7": "glm-4-7-251222", } SUFFIXES_TO_REMOVE = [ "_data_collaboration_resource_pack", "ๅไฝœๅฅ–ๅŠฑ่ฎกๅˆ’่ต„ๆบๅŒ…", "ๅ…่ดนๅœจ็บฟๆŽจ็†่ต„ๆบๅŒ…", "ๅ…่ดนๅœจ็บฟๆŽจ็†ๅŒ…", "่ต„ๆบๅŒ…", ] def normalize_volc_name(raw_name): if not raw_name: return "unknown" clean_name = raw_name for suffix in sorted(SUFFIXES_TO_REMOVE, key=len, reverse=True): if clean_name.endswith(suffix): clean_name = clean_name.replace(suffix, "") break clean_name = clean_name.replace("_", "-").replace(".", "-") clean_name = clean_name.lower().strip() return VOLC_MODEL_MAP.get(clean_name, clean_name) def analyze_packages(packages): print("\n๐Ÿ” Analyzing Packages...") for pkg in packages: raw_name = pkg.get("ConfigurationName", "Unknown") raw_code = pkg.get("ConfigurationCode", "") spec_code = pkg.get("SpecificationCode", "") status = pkg.get("Status", "") if status == "Effective": avail = pkg.get("AvailableAmount", 0) else: avail = 0 unit = pkg.get("Unit", "token") target_raw = raw_code if raw_code else raw_name norm_name = normalize_volc_name(target_raw) print(f"๐Ÿ“ฆ Pkg: Name='{raw_name}', Code='{raw_code}', Spec='{spec_code}', Status='{status}'") print(f" -> Target='{target_raw}' -> Norm='{norm_name}'") print(f" -> Avail={avail} {unit} (Effective: {status == 'Effective'})") if r: # Check Redis Key that SHOULD be set key = f"limit:dynamic:volcengine:remaining:{norm_name}" val = r.get(key) print(f" -> Redis Key '{key}': {val}") print("-" * 40) # ========================================== # โ–ถ๏ธ Main Execution # ========================================== if __name__ == "__main__": packages = fetch_all_packages() analyze_packages(packages) print("\nโœ… Done.")