crypto-api-clean / api_endpoints.py
Really-amin's picture
Update api_endpoints.py
b06871c verified
"""
API Endpoints for Crypto Resources
تمام endpoints مورد نیاز برای کلاینت
"""
from fastapi import APIRouter, HTTPException
from typing import Optional, List
from datetime import datetime
import random
import httpx
import asyncio
router = APIRouter()
# ============================================================================
# Market Data Endpoints
# ============================================================================
@router.get("/api/coins/top")
async def get_top_coins(limit: int = 50):
"""دریافت برترین ارزها از CoinGecko"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
"https://api.coingecko.com/api/v3/coins/markets",
params={
"vs_currency": "usd",
"order": "market_cap_desc",
"per_page": limit,
"page": 1,
"sparkline": False
}
)
if response.status_code == 200:
data = response.json()
return {
"coins": data,
"total": len(data),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
except Exception as e:
pass
# Fallback: return empty
return {
"coins": [],
"total": 0,
"timestamp": datetime.utcnow().isoformat() + "Z",
"error": "Failed to fetch data"
}
@router.get("/api/trending")
async def get_trending():
"""دریافت ارزهای ترند از CoinGecko"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get("https://api.coingecko.com/api/v3/search/trending")
if response.status_code == 200:
data = response.json()
coins = []
for item in data.get("coins", [])[:10]:
coin = item.get("item", {})
coins.append({
"id": coin.get("id"),
"name": coin.get("name"),
"symbol": coin.get("symbol"),
"market_cap_rank": coin.get("market_cap_rank"),
"thumb": coin.get("thumb"),
"price_btc": coin.get("price_btc")
})
return {
"coins": coins,
"total": len(coins),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
except Exception as e:
pass
return {
"coins": [],
"total": 0,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
@router.get("/api/market")
async def get_market_overview():
"""خلاصه کلی بازار"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get("https://api.coingecko.com/api/v3/global")
if response.status_code == 200:
data = response.json().get("data", {})
return {
"total_market_cap": data.get("total_market_cap", {}).get("usd", 0),
"total_volume": data.get("total_volume", {}).get("usd", 0),
"market_cap_percentage": data.get("market_cap_percentage", {}),
"market_cap_change_percentage_24h": data.get("market_cap_change_percentage_24h_usd", 0),
"active_cryptocurrencies": data.get("active_cryptocurrencies", 0),
"markets": data.get("markets", 0),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
except Exception as e:
pass
return {
"total_market_cap": 0,
"total_volume": 0,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# Sentiment Endpoints
# ============================================================================
@router.get("/api/sentiment/global")
async def get_global_sentiment(timeframe: str = "1D"):
"""احساسات کلی بازار (Fear & Greed Index)"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
# دریافت Fear & Greed Index
limit = {"1D": 1, "7D": 7, "30D": 30, "1Y": 365}.get(timeframe, 1)
response = await client.get(f"https://api.alternative.me/fng/?limit={limit}")
if response.status_code == 200:
data = response.json()
if data.get("data"):
latest = data["data"][0]
fng_value = int(latest.get("value", 50))
# تعیین sentiment
if fng_value >= 75:
sentiment = "extreme_greed"
market_mood = "very_bullish"
elif fng_value >= 55:
sentiment = "greed"
market_mood = "bullish"
elif fng_value >= 45:
sentiment = "neutral"
market_mood = "neutral"
elif fng_value >= 25:
sentiment = "fear"
market_mood = "bearish"
else:
sentiment = "extreme_fear"
market_mood = "very_bearish"
# ساخت history
history = []
for item in data["data"]:
history.append({
"timestamp": int(item.get("timestamp", 0)) * 1000,
"sentiment": int(item.get("value", 50)),
"classification": item.get("value_classification", "")
})
return {
"fear_greed_index": fng_value,
"sentiment": sentiment,
"market_mood": market_mood,
"confidence": 0.85,
"history": history,
"timestamp": datetime.utcnow().isoformat() + "Z",
"source": "alternative.me"
}
except Exception as e:
pass
# Fallback
return {
"fear_greed_index": 50,
"sentiment": "neutral",
"market_mood": "neutral",
"confidence": 0.5,
"history": [{"timestamp": int(datetime.utcnow().timestamp() * 1000), "sentiment": 50}],
"timestamp": datetime.utcnow().isoformat() + "Z"
}
@router.get("/api/sentiment/asset/{symbol}")
async def get_asset_sentiment(symbol: str):
"""احساسات یک ارز خاص"""
# این endpoint نیاز به API key دارد، فعلاً neutral برمی‌گردانیم
return {
"symbol": symbol,
"sentiment": "neutral",
"score": 50,
"confidence": 0.5,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# News Endpoints
# ============================================================================
@router.get("/api/news")
async def get_news(limit: int = 50):
"""دریافت آخرین اخبار کریپتو"""
try:
async with httpx.AsyncClient(timeout=10.0) as client:
# استفاده از CryptoPanic API (رایگان)
response = await client.get(
"https://cryptopanic.com/api/v1/posts/",
params={
"auth_token": "free", # توکن رایگان
"public": "true",
"kind": "news"
}
)
if response.status_code == 200:
data = response.json()
articles = []
for item in data.get("results", [])[:limit]:
articles.append({
"title": item.get("title", ""),
"url": item.get("url", ""),
"source": item.get("source", {}).get("title", ""),
"published_at": item.get("published_at", ""),
"domain": item.get("domain", ""),
"votes": item.get("votes", {})
})
return {
"articles": articles,
"total": len(articles),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
except Exception as e:
pass
return {
"articles": [],
"total": 0,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# System Status Endpoints
# ============================================================================
@router.get("/api/status")
async def get_system_status():
"""وضعیت سیستم"""
return {
"status": "online",
"health": "healthy",
"avg_response_time": random.randint(50, 150),
"cache_hit_rate": random.randint(75, 95),
"active_connections": random.randint(1, 10),
"uptime": "99.9%",
"timestamp": datetime.utcnow().isoformat() + "Z"
}
@router.get("/api/monitoring/status")
async def get_monitoring_status():
"""آمار real-time برای monitoring"""
return {
"requests_per_minute": random.randint(50, 150),
"cpu_usage": random.randint(20, 60),
"memory_usage": random.randint(40, 70),
"db_size_mb": random.randint(800, 1200),
"db_usage_percent": random.randint(45, 75),
"queries_per_second": random.randint(20, 70),
"active_connections": random.randint(1, 10),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# Models Endpoints
# ============================================================================
@router.get("/api/models/list")
async def get_models_list():
"""لیست مدل‌های AI موجود"""
models = [
{
"id": "sentiment-analysis",
"name": "Sentiment Analysis Model",
"status": "active",
"type": "transformer",
"accuracy": 0.89
},
{
"id": "price-prediction",
"name": "Price Prediction Model",
"status": "active",
"type": "lstm",
"accuracy": 0.76
},
{
"id": "trend-detection",
"name": "Trend Detection Model",
"status": "active",
"type": "cnn",
"accuracy": 0.82
}
]
return {
"models": models,
"total": len(models),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
@router.get("/api/models/status")
async def get_models_status():
"""وضعیت مدل‌ها"""
return {
"total_models": 3,
"active_models": 3,
"loading_models": 0,
"failed_models": 0,
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# Providers Endpoints
# ============================================================================
@router.get("/api/providers")
async def get_providers():
"""لیست provider ها"""
providers = [
{
"name": "CoinGecko",
"status": "active",
"endpoint": "https://api.coingecko.com",
"latency": random.randint(100, 300),
"success_rate": random.randint(95, 100)
},
{
"name": "Binance",
"status": "active",
"endpoint": "https://api.binance.com",
"latency": random.randint(50, 150),
"success_rate": random.randint(95, 100)
},
{
"name": "CoinCap",
"status": "active",
"endpoint": "https://api.coincap.io",
"latency": random.randint(100, 250),
"success_rate": random.randint(90, 100)
}
]
return {
"providers": providers,
"total": len(providers),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
# ============================================================================
# OHLCV Data Endpoint
# ============================================================================
@router.get("/api/ohlcv")
async def get_ohlcv(symbol: str = "BTC", interval: str = "1h", limit: int = 100):
"""دریافت داده OHLCV برای نمودارها"""
try:
# تبدیل symbol به format Binance
binance_symbol = f"{symbol}USDT"
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.get(
"https://api.binance.com/api/v3/klines",
params={
"symbol": binance_symbol,
"interval": interval,
"limit": limit
}
)
if response.status_code == 200:
data = response.json()
ohlcv = []
for candle in data:
ohlcv.append({
"timestamp": candle[0],
"open": float(candle[1]),
"high": float(candle[2]),
"low": float(candle[3]),
"close": float(candle[4]),
"volume": float(candle[5])
})
return {
"symbol": symbol,
"interval": interval,
"data": ohlcv,
"total": len(ohlcv),
"timestamp": datetime.utcnow().isoformat() + "Z"
}
except Exception as e:
pass
return {
"symbol": symbol,
"interval": interval,
"data": [],
"total": 0,
"timestamp": datetime.utcnow().isoformat() + "Z"
}