|
|
|
|
|
""" |
|
|
Restricted APIs Configuration |
|
|
تنظیمات APIهایی که نیاز به Proxy/DNS دارن |
|
|
|
|
|
فقط APIهایی که واقعاً فیلتر شدن یا محدودیت دارن |
|
|
""" |
|
|
|
|
|
from typing import Dict, List |
|
|
from enum import Enum |
|
|
|
|
|
|
|
|
class AccessLevel(Enum): |
|
|
"""سطح دسترسی""" |
|
|
DIRECT = "direct" |
|
|
SMART = "smart" |
|
|
FORCE_PROXY = "force_proxy" |
|
|
FORCE_DNS = "force_dns" |
|
|
|
|
|
|
|
|
|
|
|
RESTRICTED_APIS = { |
|
|
|
|
|
|
|
|
|
|
|
"kucoin": { |
|
|
"domains": [ |
|
|
"api.kucoin.com", |
|
|
"api-futures.kucoin.com", |
|
|
"openapi-v2.kucoin.com" |
|
|
], |
|
|
"access_level": AccessLevel.SMART, |
|
|
"priority": 1, |
|
|
"reason": "Critical exchange - always use smart access with rotating DNS/Proxy", |
|
|
"fallback_order": ["direct", "dns_cloudflare", "dns_google", "proxy", "dns_proxy"], |
|
|
"rotate_dns": True, |
|
|
"rotate_proxy": True, |
|
|
"always_secure": True |
|
|
}, |
|
|
|
|
|
"binance": { |
|
|
"domains": [ |
|
|
"api.binance.com", |
|
|
"api1.binance.com", |
|
|
"api2.binance.com", |
|
|
"api3.binance.com", |
|
|
"fapi.binance.com" |
|
|
], |
|
|
"access_level": AccessLevel.SMART, |
|
|
"priority": 1, |
|
|
"reason": "Critical exchange - always use smart access with rotating DNS/Proxy", |
|
|
"fallback_order": ["direct", "dns_cloudflare", "dns_google", "proxy", "dns_proxy"], |
|
|
"rotate_dns": True, |
|
|
"rotate_proxy": True, |
|
|
"always_secure": True |
|
|
}, |
|
|
|
|
|
"bybit": { |
|
|
"domains": [ |
|
|
"api.bybit.com", |
|
|
"api-testnet.bybit.com" |
|
|
], |
|
|
"access_level": AccessLevel.SMART, |
|
|
"priority": 2, |
|
|
"reason": "May have regional restrictions", |
|
|
"fallback_order": ["direct", "dns_cloudflare", "proxy"] |
|
|
}, |
|
|
|
|
|
"okx": { |
|
|
"domains": [ |
|
|
"www.okx.com", |
|
|
"aws.okx.com" |
|
|
], |
|
|
"access_level": AccessLevel.SMART, |
|
|
"priority": 2, |
|
|
"reason": "Geo-restrictions in some regions", |
|
|
"fallback_order": ["direct", "dns_google", "proxy"] |
|
|
}, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"coinmarketcap_pro": { |
|
|
"domains": [ |
|
|
"pro-api.coinmarketcap.com" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"priority": 3, |
|
|
"reason": "Usually works directly with API key", |
|
|
"fallback_order": ["direct", "dns_cloudflare"] |
|
|
}, |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
UNRESTRICTED_APIS = { |
|
|
"coingecko": { |
|
|
"domains": [ |
|
|
"api.coingecko.com", |
|
|
"pro-api.coingecko.com" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Works globally without restrictions" |
|
|
}, |
|
|
|
|
|
"coinpaprika": { |
|
|
"domains": [ |
|
|
"api.coinpaprika.com" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Free API, no restrictions" |
|
|
}, |
|
|
|
|
|
"coincap": { |
|
|
"domains": [ |
|
|
"api.coincap.io" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Free API, globally accessible" |
|
|
}, |
|
|
|
|
|
"coinlore": { |
|
|
"domains": [ |
|
|
"api.coinlore.net" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Free API, no geo-restrictions" |
|
|
}, |
|
|
|
|
|
"cryptopanic": { |
|
|
"domains": [ |
|
|
"cryptopanic.com" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "News API, works globally" |
|
|
}, |
|
|
|
|
|
"alternative_me": { |
|
|
"domains": [ |
|
|
"api.alternative.me" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Fear & Greed index, no restrictions" |
|
|
}, |
|
|
|
|
|
"blockchain_info": { |
|
|
"domains": [ |
|
|
"blockchain.info" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Public blockchain explorer" |
|
|
}, |
|
|
|
|
|
"etherscan": { |
|
|
"domains": [ |
|
|
"api.etherscan.io" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Public API with key" |
|
|
}, |
|
|
|
|
|
"bscscan": { |
|
|
"domains": [ |
|
|
"api.bscscan.com" |
|
|
], |
|
|
"access_level": AccessLevel.DIRECT, |
|
|
"reason": "Public API with key" |
|
|
}, |
|
|
} |
|
|
|
|
|
|
|
|
def get_access_config(domain: str) -> Dict: |
|
|
""" |
|
|
دریافت تنظیمات دسترسی برای یک domain |
|
|
|
|
|
Returns: |
|
|
{ |
|
|
"access_level": AccessLevel, |
|
|
"use_smart_access": bool, |
|
|
"fallback_order": List[str] |
|
|
} |
|
|
""" |
|
|
|
|
|
for api_name, config in RESTRICTED_APIS.items(): |
|
|
if domain in config["domains"]: |
|
|
return { |
|
|
"api_name": api_name, |
|
|
"access_level": config["access_level"], |
|
|
"use_smart_access": config["access_level"] != AccessLevel.DIRECT, |
|
|
"fallback_order": config.get("fallback_order", ["direct"]), |
|
|
"priority": config.get("priority", 99), |
|
|
"reason": config.get("reason", "") |
|
|
} |
|
|
|
|
|
|
|
|
for api_name, config in UNRESTRICTED_APIS.items(): |
|
|
if domain in config["domains"]: |
|
|
return { |
|
|
"api_name": api_name, |
|
|
"access_level": config["access_level"], |
|
|
"use_smart_access": False, |
|
|
"fallback_order": ["direct"], |
|
|
"priority": 99, |
|
|
"reason": config.get("reason", "") |
|
|
} |
|
|
|
|
|
|
|
|
return { |
|
|
"api_name": "unknown", |
|
|
"access_level": AccessLevel.SMART, |
|
|
"use_smart_access": True, |
|
|
"fallback_order": ["direct", "dns_cloudflare", "proxy"], |
|
|
"priority": 50, |
|
|
"reason": "Unknown API, using smart access" |
|
|
} |
|
|
|
|
|
|
|
|
def should_use_smart_access(url: str) -> bool: |
|
|
""" |
|
|
آیا این URL نیاز به Smart Access داره؟ |
|
|
""" |
|
|
|
|
|
if "://" in url: |
|
|
domain = url.split("://")[1].split("/")[0] |
|
|
else: |
|
|
domain = url.split("/")[0] |
|
|
|
|
|
config = get_access_config(domain) |
|
|
return config["use_smart_access"] |
|
|
|
|
|
|
|
|
def get_restricted_apis_list() -> List[str]: |
|
|
"""لیست APIهایی که نیاز به Proxy/DNS دارن""" |
|
|
return list(RESTRICTED_APIS.keys()) |
|
|
|
|
|
|
|
|
def get_unrestricted_apis_list() -> List[str]: |
|
|
"""لیست APIهایی که مستقیم کار میکنن""" |
|
|
return list(UNRESTRICTED_APIS.keys()) |
|
|
|
|
|
|
|
|
def get_all_monitored_domains() -> List[str]: |
|
|
"""همه domainهایی که تحت نظارت هستن""" |
|
|
domains = [] |
|
|
|
|
|
for config in RESTRICTED_APIS.values(): |
|
|
domains.extend(config["domains"]) |
|
|
|
|
|
for config in UNRESTRICTED_APIS.values(): |
|
|
domains.extend(config["domains"]) |
|
|
|
|
|
return domains |
|
|
|
|
|
|
|
|
def print_config_summary(): |
|
|
"""چاپ خلاصه تنظیمات""" |
|
|
print("=" * 60) |
|
|
print("📋 RESTRICTED APIS CONFIGURATION") |
|
|
print("=" * 60) |
|
|
|
|
|
print("\n🔴 APIs that need Proxy/DNS:") |
|
|
for api_name, config in RESTRICTED_APIS.items(): |
|
|
print(f"\n {api_name.upper()}:") |
|
|
print(f" Domains: {', '.join(config['domains'])}") |
|
|
print(f" Access: {config['access_level'].value}") |
|
|
print(f" Priority: {config['priority']}") |
|
|
print(f" Reason: {config['reason']}") |
|
|
|
|
|
print("\n\n✅ APIs that work DIRECT:") |
|
|
for api_name, config in UNRESTRICTED_APIS.items(): |
|
|
print(f" • {api_name}: {config['domains'][0]}") |
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print(f"Total Restricted: {len(RESTRICTED_APIS)}") |
|
|
print(f"Total Unrestricted: {len(UNRESTRICTED_APIS)}") |
|
|
print("=" * 60) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
print_config_summary() |
|
|
|
|
|
|