Spaces:
Running
Running
Download auth.py from ItsXyron/hyperlookup-api: direct link, hf CLI and curl.
- Browser
- Download file 9.59 kB
-
https://huggingface.co/spaces/ItsXyron/hyperlookup-api/resolve/main/auth.py
- Command line
-
hf download hf://spaces/ItsXyron/hyperlookup-api/auth.py
-
curl -L -o auth.py https://huggingface.co/spaces/ItsXyron/hyperlookup-api/resolve/main/auth.py
9.59 kB
| import os | |
| import json | |
| import time | |
| import secrets | |
| import threading | |
| from typing import Optional, Dict, Any, List, Tuple | |
| KEYS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "api_keys.json") | |
| ADMIN_MASTER_KEY = os.environ.get("ADMIN_MASTER_KEY", "secretz_master_admin_2026") | |
| INTERNAL_BOT_KEY = os.environ.get("INTERNAL_BOT_KEY", "sk_internal_telebot_secretz_9921") | |
| DAILY_FREE_LIMIT = int(os.environ.get("DAILY_FREE_LIMIT", "5")) | |
| _lock = threading.Lock() | |
| # Rate limiting sliding windows | |
| # {api_key: [timestamp1, timestamp2, ...]} | |
| _rate_limits: Dict[str, List[float]] = {} | |
| # Public IP Anti-DDoS sliding windows | |
| # {ip: [timestamp1, timestamp2, ...]} | |
| _public_ip_burst: Dict[str, List[float]] = {} | |
| # Public IP Daily usage: {ip: {"date": "YYYY-MM-DD", "count": int}} | |
| _public_ip_daily: Dict[str, Dict[str, Any]] = {} | |
| def load_keys() -> Dict[str, Dict[str, Any]]: | |
| if os.path.exists(KEYS_FILE): | |
| try: | |
| with open(KEYS_FILE, "r", encoding="utf-8") as f: | |
| data = json.load(f) | |
| # Ensure all keys have both 'key' and 'api_key' fields | |
| for k, v in data.items(): | |
| if "key" not in v: | |
| v["key"] = k | |
| if "api_key" not in v: | |
| v["api_key"] = k | |
| return data | |
| except Exception: | |
| return {} | |
| return {} | |
| def save_keys(keys_data: Dict[str, Dict[str, Any]]): | |
| try: | |
| with open(KEYS_FILE, "w", encoding="utf-8") as f: | |
| json.dump(keys_data, f, indent=2) | |
| except Exception as e: | |
| print(f"Error saving api_keys.json: {e}") | |
| class KeyManager: | |
| def create_key( | |
| name: str, | |
| days_valid: Optional[int] = 30, | |
| rate_limit_per_min: int = 60, | |
| total_credits: int = 1000 | |
| ) -> Dict[str, Any]: | |
| """Creates a new API key with expiration and credit limits.""" | |
| api_key = f"sk_live_{secrets.token_hex(16)}" | |
| now = time.time() | |
| expires_at = now + (days_valid * 86400) if (days_valid and days_valid > 0) else None | |
| key_info = { | |
| "key": api_key, | |
| "api_key": api_key, | |
| "name": name, | |
| "created_at": now, | |
| "expires_at": expires_at, | |
| "rate_limit_per_min": rate_limit_per_min, | |
| "total_credits": total_credits, | |
| "used_credits": 0, | |
| "status": "active" | |
| } | |
| with _lock: | |
| keys = load_keys() | |
| keys[api_key] = key_info | |
| save_keys(keys) | |
| return key_info | |
| def list_keys() -> List[Dict[str, Any]]: | |
| with _lock: | |
| keys = load_keys() | |
| result = [] | |
| for k, v in keys.items(): | |
| item = dict(v) | |
| item["key"] = k | |
| item["api_key"] = k | |
| result.append(item) | |
| return result | |
| def revoke_key(api_key: str) -> bool: | |
| with _lock: | |
| keys = load_keys() | |
| if api_key in keys: | |
| keys[api_key]["status"] = "revoked" | |
| save_keys(keys) | |
| return True | |
| return False | |
| def delete_key(api_key: str) -> bool: | |
| with _lock: | |
| keys = load_keys() | |
| if api_key in keys: | |
| del keys[api_key] | |
| save_keys(keys) | |
| return True | |
| return False | |
| def validate_request(api_key: Optional[str], client_ip: str) -> Tuple[bool, int, str, Dict[str, Any]]: | |
| """ | |
| Validates an incoming request either by API Key or Public Free Tier (IP-based). | |
| Returns: (is_valid: bool, error_code: int, error_message: str, meta: dict) | |
| """ | |
| now = time.time() | |
| # ======================================================== | |
| # Case 1: Master Admin or Internal Bot Key | |
| # ======================================================== | |
| if api_key in (ADMIN_MASTER_KEY, INTERNAL_BOT_KEY): | |
| return True, 200, "OK", {"tier": "admin", "remaining": -1} | |
| # ======================================================== | |
| # Case 2: User provided a custom API Key | |
| # ======================================================== | |
| if api_key: | |
| with _lock: | |
| keys = load_keys() | |
| if api_key not in keys: | |
| return False, 401, "Invalid API Key. Please verify your credentials.", {} | |
| info = keys[api_key] | |
| # Status check | |
| if info.get("status") != "active": | |
| return False, 403, "API Key has been revoked or deactivated.", {} | |
| # Expiry check | |
| expires_at = info.get("expires_at") | |
| if expires_at and now > expires_at: | |
| info["status"] = "expired" | |
| save_keys(keys) | |
| return False, 403, "API Key has expired.", {} | |
| # Credits check | |
| total_credits = info.get("total_credits", -1) | |
| used_credits = info.get("used_credits", 0) | |
| if total_credits != -1 and used_credits >= total_credits: | |
| return False, 403, "API Key search credits exhausted.", {} | |
| # Rate limit (sliding window 60s) | |
| rate_limit = info.get("rate_limit_per_min", 60) | |
| if api_key not in _rate_limits: | |
| _rate_limits[api_key] = [] | |
| cutoff = now - 60.0 | |
| _rate_limits[api_key] = [t for t in _rate_limits[api_key] if t > cutoff] | |
| if len(_rate_limits[api_key]) >= rate_limit: | |
| retry_after = round(60.0 - (now - _rate_limits[api_key][0]), 1) | |
| return False, 429, f"Rate limit exceeded ({rate_limit} req/min). Retry after {retry_after}s.", {} | |
| # Deduct credit | |
| _rate_limits[api_key].append(now) | |
| info["used_credits"] = used_credits + 1 | |
| save_keys(keys) | |
| remaining = (total_credits - info["used_credits"]) if total_credits != -1 else -1 | |
| return True, 200, "OK", {"tier": "custom", "remaining": remaining} | |
| # ======================================================== | |
| # Case 3: Public / Anonymous User (Bina Key ke - Daily Free Limit & Anti-DDoS) | |
| # ======================================================== | |
| with _lock: | |
| # 1. Anti-DDoS / Rapid Burst Check (Max 1 request per 2 seconds, max 6 per minute) | |
| if client_ip not in _public_ip_burst: | |
| _public_ip_burst[client_ip] = [] | |
| cutoff = now - 60.0 | |
| _public_ip_burst[client_ip] = [t for t in _public_ip_burst[client_ip] if t > cutoff] | |
| if _public_ip_burst[client_ip] and (now - _public_ip_burst[client_ip][-1] < 1.5): | |
| return False, 429, "Anti-DDoS: Rapid requests detected. Please wait 2 seconds between queries.", {} | |
| if len(_public_ip_burst[client_ip]) >= 6: | |
| return False, 429, "Public rate limit exceeded (max 6 req/min). Please slow down.", {} | |
| # 2. Daily Free Search Limit (Reset at 00:00 UTC) | |
| today = time.strftime("%Y-%m-%d", time.gmtime()) | |
| if client_ip not in _public_ip_daily or _public_ip_daily[client_ip].get("date") != today: | |
| _public_ip_daily[client_ip] = {"date": today, "count": 0} | |
| used_today = _public_ip_daily[client_ip]["count"] | |
| if used_today >= DAILY_FREE_LIMIT: | |
| return ( | |
| False, | |
| 429, | |
| f"Daily free limit reached ({DAILY_FREE_LIMIT}/{DAILY_FREE_LIMIT} used today). Resets at midnight UTC, or enter an Access Key for unlimited searches.", | |
| {"tier": "free", "remaining": 0} | |
| ) | |
| # Record usage | |
| _public_ip_burst[client_ip].append(now) | |
| _public_ip_daily[client_ip]["count"] = used_today + 1 | |
| remaining = max(0, DAILY_FREE_LIMIT - _public_ip_daily[client_ip]["count"]) | |
| return True, 200, "OK", {"tier": "free", "remaining": remaining} | |
| def get_public_quota(client_ip: str) -> Dict[str, Any]: | |
| """Returns current daily quota status for an IP without consuming credit.""" | |
| today = time.strftime("%Y-%m-%d", time.gmtime()) | |
| with _lock: | |
| record = _public_ip_daily.get(client_ip, {}) | |
| if record.get("date") != today: | |
| used = 0 | |
| else: | |
| used = record.get("count", 0) | |
| return { | |
| "tier": "free", | |
| "daily_limit": DAILY_FREE_LIMIT, | |
| "used_today": used, | |
| "remaining_today": max(0, DAILY_FREE_LIMIT - used) | |
| } | |
| def get_key_status(api_key: str) -> Optional[Dict[str, Any]]: | |
| if api_key == ADMIN_MASTER_KEY: | |
| return {"name": "Master Admin", "status": "active", "total_credits": -1, "used_credits": 0, "expires_at": None} | |
| if api_key == INTERNAL_BOT_KEY: | |
| return {"name": "Telegram Bot Internal", "status": "active", "total_credits": -1, "used_credits": 0, "expires_at": None} | |
| with _lock: | |
| keys = load_keys() | |
| info = keys.get(api_key) | |
| if info: | |
| res = dict(info) | |
| res["key"] = api_key | |
| res["api_key"] = api_key | |
| return res | |
| return None | |