Upload 10 files
Browse files- .gitignore +16 -22
- API_DOCS.md +527 -0
- CHANGELOG.md +161 -0
- QUICK_START.md +75 -153
- README.md +304 -92
- app.py +386 -455
- requirements.txt +3 -2
- start.bat +81 -0
- start.py +127 -0
.gitignore
CHANGED
|
@@ -4,42 +4,36 @@ __pycache__/
|
|
| 4 |
*$py.class
|
| 5 |
*.so
|
| 6 |
.Python
|
| 7 |
-
env/
|
| 8 |
venv/
|
|
|
|
| 9 |
ENV/
|
| 10 |
-
build/
|
| 11 |
-
develop-eggs/
|
| 12 |
-
dist/
|
| 13 |
-
downloads/
|
| 14 |
-
eggs/
|
| 15 |
-
.eggs/
|
| 16 |
-
lib/
|
| 17 |
-
lib64/
|
| 18 |
-
parts/
|
| 19 |
-
sdist/
|
| 20 |
-
var/
|
| 21 |
-
wheels/
|
| 22 |
*.egg-info/
|
| 23 |
-
|
| 24 |
-
|
| 25 |
|
| 26 |
-
#
|
| 27 |
.vscode/
|
| 28 |
.idea/
|
| 29 |
*.swp
|
| 30 |
*.swo
|
| 31 |
*~
|
| 32 |
|
| 33 |
-
#
|
| 34 |
-
.
|
| 35 |
-
.
|
|
|
|
| 36 |
|
| 37 |
# Logs
|
| 38 |
*.log
|
|
|
|
| 39 |
|
| 40 |
-
#
|
| 41 |
-
.
|
| 42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
# Cache
|
| 45 |
.cache/
|
|
|
|
| 4 |
*$py.class
|
| 5 |
*.so
|
| 6 |
.Python
|
|
|
|
| 7 |
venv/
|
| 8 |
+
env/
|
| 9 |
ENV/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
*.egg-info/
|
| 11 |
+
dist/
|
| 12 |
+
build/
|
| 13 |
|
| 14 |
+
# IDEs
|
| 15 |
.vscode/
|
| 16 |
.idea/
|
| 17 |
*.swp
|
| 18 |
*.swo
|
| 19 |
*~
|
| 20 |
|
| 21 |
+
# OS
|
| 22 |
+
.DS_Store
|
| 23 |
+
Thumbs.db
|
| 24 |
+
desktop.ini
|
| 25 |
|
| 26 |
# Logs
|
| 27 |
*.log
|
| 28 |
+
logs/
|
| 29 |
|
| 30 |
+
# Environment
|
| 31 |
+
.env
|
| 32 |
+
.env.local
|
| 33 |
+
|
| 34 |
+
# Database
|
| 35 |
+
*.db
|
| 36 |
+
*.sqlite
|
| 37 |
|
| 38 |
# Cache
|
| 39 |
.cache/
|
API_DOCS.md
ADDED
|
@@ -0,0 +1,527 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 📡 API Documentation
|
| 2 |
+
|
| 3 |
+
## Base URL
|
| 4 |
+
```
|
| 5 |
+
http://localhost:8000
|
| 6 |
+
```
|
| 7 |
+
|
| 8 |
+
## Authentication
|
| 9 |
+
No authentication required for this demo version.
|
| 10 |
+
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
## 🏥 Health & Status Endpoints
|
| 14 |
+
|
| 15 |
+
### GET /health
|
| 16 |
+
Get system health status
|
| 17 |
+
|
| 18 |
+
**Request:**
|
| 19 |
+
```bash
|
| 20 |
+
curl http://localhost:8000/health
|
| 21 |
+
```
|
| 22 |
+
|
| 23 |
+
**Response:**
|
| 24 |
+
```json
|
| 25 |
+
{
|
| 26 |
+
"status": "healthy",
|
| 27 |
+
"timestamp": "2025-01-15T10:30:00",
|
| 28 |
+
"components": [
|
| 29 |
+
{
|
| 30 |
+
"name": "API Server 1",
|
| 31 |
+
"status": "healthy",
|
| 32 |
+
"uptime": 99.99,
|
| 33 |
+
"response_time": 120
|
| 34 |
+
}
|
| 35 |
+
],
|
| 36 |
+
"summary": {
|
| 37 |
+
"total_components": 8,
|
| 38 |
+
"healthy": 8,
|
| 39 |
+
"degraded": 0,
|
| 40 |
+
"critical": 0
|
| 41 |
+
}
|
| 42 |
+
}
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
---
|
| 46 |
+
|
| 47 |
+
### GET /info
|
| 48 |
+
Get system information
|
| 49 |
+
|
| 50 |
+
**Request:**
|
| 51 |
+
```bash
|
| 52 |
+
curl http://localhost:8000/info
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
**Response:**
|
| 56 |
+
```json
|
| 57 |
+
{
|
| 58 |
+
"name": "Crypto API Monitor",
|
| 59 |
+
"version": "1.0.0",
|
| 60 |
+
"environment": "production",
|
| 61 |
+
"uptime_seconds": 86400,
|
| 62 |
+
"memory_usage_mb": 450,
|
| 63 |
+
"cpu_usage_percent": 25.5,
|
| 64 |
+
"active_connections": 3,
|
| 65 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 66 |
+
}
|
| 67 |
+
```
|
| 68 |
+
|
| 69 |
+
---
|
| 70 |
+
|
| 71 |
+
## 📊 Provider Endpoints
|
| 72 |
+
|
| 73 |
+
### GET /api/providers
|
| 74 |
+
Get all data providers status
|
| 75 |
+
|
| 76 |
+
**Request:**
|
| 77 |
+
```bash
|
| 78 |
+
curl http://localhost:8000/api/providers
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
**Response:**
|
| 82 |
+
```json
|
| 83 |
+
[
|
| 84 |
+
{
|
| 85 |
+
"name": "Binance",
|
| 86 |
+
"type": "Exchange",
|
| 87 |
+
"status": "operational",
|
| 88 |
+
"uptime": 99.95,
|
| 89 |
+
"response_time_ms": 85,
|
| 90 |
+
"requests_today": 150000,
|
| 91 |
+
"last_check": "2025-01-15T10:30:00",
|
| 92 |
+
"endpoint": "https://api.binance.com"
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"name": "CoinGecko",
|
| 96 |
+
"type": "Data Provider",
|
| 97 |
+
"status": "operational",
|
| 98 |
+
"uptime": 99.87,
|
| 99 |
+
"response_time_ms": 120,
|
| 100 |
+
"requests_today": 89000,
|
| 101 |
+
"last_check": "2025-01-15T10:30:00",
|
| 102 |
+
"endpoint": "https://api.coingecko.com"
|
| 103 |
+
}
|
| 104 |
+
]
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
---
|
| 108 |
+
|
| 109 |
+
## 💰 Cryptocurrency Data
|
| 110 |
+
|
| 111 |
+
### GET /api/crypto/prices/top
|
| 112 |
+
Get top cryptocurrency prices
|
| 113 |
+
|
| 114 |
+
**Parameters:**
|
| 115 |
+
- `limit` (optional): Number of results (default: 10)
|
| 116 |
+
|
| 117 |
+
**Request:**
|
| 118 |
+
```bash
|
| 119 |
+
curl http://localhost:8000/api/crypto/prices/top?limit=5
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
**Response:**
|
| 123 |
+
```json
|
| 124 |
+
[
|
| 125 |
+
{
|
| 126 |
+
"symbol": "BTC",
|
| 127 |
+
"name": "Bitcoin",
|
| 128 |
+
"price": 42150.50,
|
| 129 |
+
"change_24h": 3.25,
|
| 130 |
+
"volume_24h": 28000000000,
|
| 131 |
+
"market_cap": 825000000000,
|
| 132 |
+
"last_updated": "2025-01-15T10:30:00"
|
| 133 |
+
},
|
| 134 |
+
{
|
| 135 |
+
"symbol": "ETH",
|
| 136 |
+
"name": "Ethereum",
|
| 137 |
+
"price": 2215.80,
|
| 138 |
+
"change_24h": 2.15,
|
| 139 |
+
"volume_24h": 12000000000,
|
| 140 |
+
"market_cap": 265000000000,
|
| 141 |
+
"last_updated": "2025-01-15T10:30:00"
|
| 142 |
+
}
|
| 143 |
+
]
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
---
|
| 147 |
+
|
| 148 |
+
### GET /api/crypto/market-overview
|
| 149 |
+
Get market overview and statistics
|
| 150 |
+
|
| 151 |
+
**Request:**
|
| 152 |
+
```bash
|
| 153 |
+
curl http://localhost:8000/api/crypto/market-overview
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
**Response:**
|
| 157 |
+
```json
|
| 158 |
+
{
|
| 159 |
+
"total_market_cap": 1750000000000,
|
| 160 |
+
"total_volume_24h": 95000000000,
|
| 161 |
+
"average_change_24h": 2.45,
|
| 162 |
+
"top_gainers": [
|
| 163 |
+
{
|
| 164 |
+
"symbol": "SOL",
|
| 165 |
+
"name": "Solana",
|
| 166 |
+
"price": 98.50,
|
| 167 |
+
"change_24h": 12.30
|
| 168 |
+
}
|
| 169 |
+
],
|
| 170 |
+
"top_losers": [
|
| 171 |
+
{
|
| 172 |
+
"symbol": "XRP",
|
| 173 |
+
"name": "Ripple",
|
| 174 |
+
"price": 0.51,
|
| 175 |
+
"change_24h": -5.20
|
| 176 |
+
}
|
| 177 |
+
],
|
| 178 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 179 |
+
}
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
---
|
| 183 |
+
|
| 184 |
+
## 📁 Categories
|
| 185 |
+
|
| 186 |
+
### GET /api/categories
|
| 187 |
+
Get cryptocurrency categories
|
| 188 |
+
|
| 189 |
+
**Request:**
|
| 190 |
+
```bash
|
| 191 |
+
curl http://localhost:8000/api/categories
|
| 192 |
+
```
|
| 193 |
+
|
| 194 |
+
**Response:**
|
| 195 |
+
```json
|
| 196 |
+
[
|
| 197 |
+
{
|
| 198 |
+
"id": 1,
|
| 199 |
+
"name": "DeFi",
|
| 200 |
+
"market_cap": 45000000000,
|
| 201 |
+
"change_24h": 5.2
|
| 202 |
+
},
|
| 203 |
+
{
|
| 204 |
+
"id": 2,
|
| 205 |
+
"name": "Smart Contract Platform",
|
| 206 |
+
"market_cap": 120000000000,
|
| 207 |
+
"change_24h": 3.1
|
| 208 |
+
}
|
| 209 |
+
]
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
---
|
| 213 |
+
|
| 214 |
+
## ⏱️ Rate Limits
|
| 215 |
+
|
| 216 |
+
### GET /api/rate-limits
|
| 217 |
+
Get API rate limit information
|
| 218 |
+
|
| 219 |
+
**Request:**
|
| 220 |
+
```bash
|
| 221 |
+
curl http://localhost:8000/api/rate-limits
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
**Response:**
|
| 225 |
+
```json
|
| 226 |
+
[
|
| 227 |
+
{
|
| 228 |
+
"provider": "Binance",
|
| 229 |
+
"limit_per_minute": 1200,
|
| 230 |
+
"limit_per_hour": 60000,
|
| 231 |
+
"remaining": 850,
|
| 232 |
+
"reset_time": "2025-01-15T10:31:00"
|
| 233 |
+
}
|
| 234 |
+
]
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
---
|
| 238 |
+
|
| 239 |
+
## 📋 Logs
|
| 240 |
+
|
| 241 |
+
### GET /api/logs
|
| 242 |
+
Get system logs
|
| 243 |
+
|
| 244 |
+
**Parameters:**
|
| 245 |
+
- `limit` (optional): Number of logs (default: 50)
|
| 246 |
+
|
| 247 |
+
**Request:**
|
| 248 |
+
```bash
|
| 249 |
+
curl http://localhost:8000/api/logs?limit=10
|
| 250 |
+
```
|
| 251 |
+
|
| 252 |
+
**Response:**
|
| 253 |
+
```json
|
| 254 |
+
[
|
| 255 |
+
{
|
| 256 |
+
"id": 1,
|
| 257 |
+
"timestamp": "2025-01-15T10:30:00",
|
| 258 |
+
"level": "INFO",
|
| 259 |
+
"message": "API request processed successfully",
|
| 260 |
+
"provider": "Binance"
|
| 261 |
+
},
|
| 262 |
+
{
|
| 263 |
+
"id": 2,
|
| 264 |
+
"timestamp": "2025-01-15T10:29:45",
|
| 265 |
+
"level": "WARNING",
|
| 266 |
+
"message": "Rate limit approaching",
|
| 267 |
+
"provider": "CoinGecko"
|
| 268 |
+
}
|
| 269 |
+
]
|
| 270 |
+
```
|
| 271 |
+
|
| 272 |
+
---
|
| 273 |
+
|
| 274 |
+
## 🔔 Alerts
|
| 275 |
+
|
| 276 |
+
### GET /api/alerts
|
| 277 |
+
Get active system alerts
|
| 278 |
+
|
| 279 |
+
**Request:**
|
| 280 |
+
```bash
|
| 281 |
+
curl http://localhost:8000/api/alerts
|
| 282 |
+
```
|
| 283 |
+
|
| 284 |
+
**Response:**
|
| 285 |
+
```json
|
| 286 |
+
[
|
| 287 |
+
{
|
| 288 |
+
"id": 1,
|
| 289 |
+
"severity": "warning",
|
| 290 |
+
"title": "High API Usage",
|
| 291 |
+
"message": "API usage is at 85% of limit",
|
| 292 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 293 |
+
}
|
| 294 |
+
]
|
| 295 |
+
```
|
| 296 |
+
|
| 297 |
+
---
|
| 298 |
+
|
| 299 |
+
## 🤗 Hugging Face Integration
|
| 300 |
+
|
| 301 |
+
### GET /api/hf/health
|
| 302 |
+
Check Hugging Face integration health
|
| 303 |
+
|
| 304 |
+
**Request:**
|
| 305 |
+
```bash
|
| 306 |
+
curl http://localhost:8000/api/hf/health
|
| 307 |
+
```
|
| 308 |
+
|
| 309 |
+
**Response:**
|
| 310 |
+
```json
|
| 311 |
+
{
|
| 312 |
+
"status": "operational",
|
| 313 |
+
"models_available": 12,
|
| 314 |
+
"last_sync": "2025-01-15T10:30:00"
|
| 315 |
+
}
|
| 316 |
+
```
|
| 317 |
+
|
| 318 |
+
---
|
| 319 |
+
|
| 320 |
+
### POST /api/hf/refresh
|
| 321 |
+
Refresh Hugging Face data
|
| 322 |
+
|
| 323 |
+
**Request:**
|
| 324 |
+
```bash
|
| 325 |
+
curl -X POST http://localhost:8000/api/hf/refresh
|
| 326 |
+
```
|
| 327 |
+
|
| 328 |
+
**Response:**
|
| 329 |
+
```json
|
| 330 |
+
{
|
| 331 |
+
"status": "success",
|
| 332 |
+
"message": "Data refresh initiated",
|
| 333 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 334 |
+
}
|
| 335 |
+
```
|
| 336 |
+
|
| 337 |
+
---
|
| 338 |
+
|
| 339 |
+
### GET /api/hf/registry
|
| 340 |
+
Get Hugging Face model registry
|
| 341 |
+
|
| 342 |
+
**Request:**
|
| 343 |
+
```bash
|
| 344 |
+
curl http://localhost:8000/api/hf/registry
|
| 345 |
+
```
|
| 346 |
+
|
| 347 |
+
**Response:**
|
| 348 |
+
```json
|
| 349 |
+
{
|
| 350 |
+
"models": [
|
| 351 |
+
{
|
| 352 |
+
"name": "sentiment-analysis",
|
| 353 |
+
"status": "active"
|
| 354 |
+
},
|
| 355 |
+
{
|
| 356 |
+
"name": "price-prediction",
|
| 357 |
+
"status": "active"
|
| 358 |
+
}
|
| 359 |
+
]
|
| 360 |
+
}
|
| 361 |
+
```
|
| 362 |
+
|
| 363 |
+
---
|
| 364 |
+
|
| 365 |
+
### POST /api/hf/run-sentiment
|
| 366 |
+
Run sentiment analysis
|
| 367 |
+
|
| 368 |
+
**Request:**
|
| 369 |
+
```bash
|
| 370 |
+
curl -X POST http://localhost:8000/api/hf/run-sentiment \
|
| 371 |
+
-H "Content-Type: application/json" \
|
| 372 |
+
-d '{"text": "Bitcoin is going to the moon!"}'
|
| 373 |
+
```
|
| 374 |
+
|
| 375 |
+
**Response:**
|
| 376 |
+
```json
|
| 377 |
+
{
|
| 378 |
+
"sentiment": "positive",
|
| 379 |
+
"score": 0.95,
|
| 380 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 381 |
+
}
|
| 382 |
+
```
|
| 383 |
+
|
| 384 |
+
---
|
| 385 |
+
|
| 386 |
+
## 🔌 WebSocket
|
| 387 |
+
|
| 388 |
+
### WS /ws/live
|
| 389 |
+
Real-time updates via WebSocket
|
| 390 |
+
|
| 391 |
+
**Connection:**
|
| 392 |
+
```javascript
|
| 393 |
+
const ws = new WebSocket('ws://localhost:8000/ws/live');
|
| 394 |
+
|
| 395 |
+
ws.onopen = () => {
|
| 396 |
+
console.log('Connected');
|
| 397 |
+
};
|
| 398 |
+
|
| 399 |
+
ws.onmessage = (event) => {
|
| 400 |
+
const data = JSON.parse(event.data);
|
| 401 |
+
console.log('Message:', data);
|
| 402 |
+
};
|
| 403 |
+
```
|
| 404 |
+
|
| 405 |
+
**Message Types:**
|
| 406 |
+
|
| 407 |
+
#### Connection Established
|
| 408 |
+
```json
|
| 409 |
+
{
|
| 410 |
+
"type": "connection_established",
|
| 411 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 412 |
+
}
|
| 413 |
+
```
|
| 414 |
+
|
| 415 |
+
#### Status Update
|
| 416 |
+
```json
|
| 417 |
+
{
|
| 418 |
+
"type": "status_update",
|
| 419 |
+
"data": {
|
| 420 |
+
"status": "healthy",
|
| 421 |
+
"components": [...]
|
| 422 |
+
},
|
| 423 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 424 |
+
}
|
| 425 |
+
```
|
| 426 |
+
|
| 427 |
+
#### Provider Status Change
|
| 428 |
+
```json
|
| 429 |
+
{
|
| 430 |
+
"type": "provider_status_change",
|
| 431 |
+
"data": {
|
| 432 |
+
"provider": "Binance",
|
| 433 |
+
"status": "operational"
|
| 434 |
+
},
|
| 435 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 436 |
+
}
|
| 437 |
+
```
|
| 438 |
+
|
| 439 |
+
#### New Alert
|
| 440 |
+
```json
|
| 441 |
+
{
|
| 442 |
+
"type": "new_alert",
|
| 443 |
+
"data": {
|
| 444 |
+
"severity": "info",
|
| 445 |
+
"title": "System Update",
|
| 446 |
+
"message": "Cache refreshed successfully"
|
| 447 |
+
},
|
| 448 |
+
"timestamp": "2025-01-15T10:30:00"
|
| 449 |
+
}
|
| 450 |
+
```
|
| 451 |
+
|
| 452 |
+
---
|
| 453 |
+
|
| 454 |
+
## 📊 Status Codes
|
| 455 |
+
|
| 456 |
+
- `200` - Success
|
| 457 |
+
- `404` - Endpoint not found
|
| 458 |
+
- `500` - Internal server error
|
| 459 |
+
|
| 460 |
+
---
|
| 461 |
+
|
| 462 |
+
## 🔄 Update Frequency
|
| 463 |
+
|
| 464 |
+
- **WebSocket**: Real-time (every 5 seconds)
|
| 465 |
+
- **Health**: On-demand
|
| 466 |
+
- **Providers**: On-demand
|
| 467 |
+
- **Crypto Prices**: On-demand (recommended: every 30s)
|
| 468 |
+
|
| 469 |
+
---
|
| 470 |
+
|
| 471 |
+
## 💡 Best Practices
|
| 472 |
+
|
| 473 |
+
1. **Use WebSocket** for real-time data instead of polling
|
| 474 |
+
2. **Cache responses** when appropriate
|
| 475 |
+
3. **Respect rate limits** to avoid throttling
|
| 476 |
+
4. **Handle errors** gracefully with retry logic
|
| 477 |
+
5. **Monitor health** endpoint regularly
|
| 478 |
+
|
| 479 |
+
---
|
| 480 |
+
|
| 481 |
+
## 🧪 Testing Endpoints
|
| 482 |
+
|
| 483 |
+
### Using curl:
|
| 484 |
+
```bash
|
| 485 |
+
# Test health
|
| 486 |
+
curl http://localhost:8000/health
|
| 487 |
+
|
| 488 |
+
# Test with formatting
|
| 489 |
+
curl http://localhost:8000/api/providers | python -m json.tool
|
| 490 |
+
```
|
| 491 |
+
|
| 492 |
+
### Using Python:
|
| 493 |
+
```python
|
| 494 |
+
import requests
|
| 495 |
+
|
| 496 |
+
# Get health status
|
| 497 |
+
response = requests.get('http://localhost:8000/health')
|
| 498 |
+
print(response.json())
|
| 499 |
+
|
| 500 |
+
# Get crypto prices
|
| 501 |
+
response = requests.get('http://localhost:8000/api/crypto/prices/top')
|
| 502 |
+
prices = response.json()
|
| 503 |
+
for crypto in prices:
|
| 504 |
+
print(f"{crypto['symbol']}: ${crypto['price']}")
|
| 505 |
+
```
|
| 506 |
+
|
| 507 |
+
### Using JavaScript:
|
| 508 |
+
```javascript
|
| 509 |
+
// Fetch crypto prices
|
| 510 |
+
fetch('http://localhost:8000/api/crypto/prices/top')
|
| 511 |
+
.then(response => response.json())
|
| 512 |
+
.then(data => console.log(data));
|
| 513 |
+
|
| 514 |
+
// WebSocket connection
|
| 515 |
+
const ws = new WebSocket('ws://localhost:8000/ws/live');
|
| 516 |
+
ws.onmessage = (event) => {
|
| 517 |
+
console.log('Update:', JSON.parse(event.data));
|
| 518 |
+
};
|
| 519 |
+
```
|
| 520 |
+
|
| 521 |
+
---
|
| 522 |
+
|
| 523 |
+
## 📞 Support
|
| 524 |
+
|
| 525 |
+
برای سوالات بیشتر، به `README.md` مراجعه کنید.
|
| 526 |
+
|
| 527 |
+
For more questions, refer to `README.md`.
|
CHANGELOG.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 📝 تاریخچه تغییرات / Changelog
|
| 2 |
+
|
| 3 |
+
## [1.0.0] - 2025-01-15
|
| 4 |
+
|
| 5 |
+
### ✨ ویژگیهای جدید / New Features
|
| 6 |
+
- 🚀 راهاندازی اولیه پروژه
|
| 7 |
+
- 📊 داشبورد Real-time با WebSocket
|
| 8 |
+
- 🔌 پشتیبانی از 8 Provider مختلف
|
| 9 |
+
- 📈 نمودارهای تعاملی با Chart.js
|
| 10 |
+
- 🏥 سیستم مانیتورینگ سلامت
|
| 11 |
+
- 🔔 سیستم هشدار و اعلان
|
| 12 |
+
- 💼 مدیریت کامل Providers
|
| 13 |
+
- 📁 دستهبندی ارزهای دیجیتال
|
| 14 |
+
- ⏱️ نمایش Rate Limits
|
| 15 |
+
- 📋 سیستم لاگگذاری
|
| 16 |
+
- 🤗 یکپارچهسازی با Hugging Face
|
| 17 |
+
- 🌐 پشتیبانی از multiple endpoints
|
| 18 |
+
|
| 19 |
+
### 🎨 رابط کاربری / UI
|
| 20 |
+
- طراحی مدرن و حرفهای
|
| 21 |
+
- رنگبندی بنفش زیبا
|
| 22 |
+
- انیمیشنهای روان
|
| 23 |
+
- Responsive design
|
| 24 |
+
- Dark mode support
|
| 25 |
+
|
| 26 |
+
### 🔧 فنی / Technical
|
| 27 |
+
- FastAPI backend
|
| 28 |
+
- WebSocket support
|
| 29 |
+
- Mock data generators
|
| 30 |
+
- Auto-refresh capability
|
| 31 |
+
- Error handling
|
| 32 |
+
- CORS support
|
| 33 |
+
|
| 34 |
+
### 📚 مستندات / Documentation
|
| 35 |
+
- راهنمای کامل فارسی و انگلیسی
|
| 36 |
+
- مستندات API
|
| 37 |
+
- راهنمای نصب
|
| 38 |
+
- نمونههای کد
|
| 39 |
+
|
| 40 |
+
### 🛠️ ابزارها / Tools
|
| 41 |
+
- start.bat برای ویندوز
|
| 42 |
+
- start.py برای کراس پلتفرم
|
| 43 |
+
- Auto-setup script
|
| 44 |
+
- Virtual environment management
|
| 45 |
+
|
| 46 |
+
---
|
| 47 |
+
|
| 48 |
+
## 🔮 نسخههای آینده / Future Versions
|
| 49 |
+
|
| 50 |
+
### [1.1.0] - Planned
|
| 51 |
+
- [ ] اتصال به API واقعی ارزها
|
| 52 |
+
- [ ] پایگاه داده برای ذخیره تاریخچه
|
| 53 |
+
- [ ] احراز هویت کاربران
|
| 54 |
+
- [ ] Dashboard customization
|
| 55 |
+
- [ ] Export data to CSV/Excel
|
| 56 |
+
- [ ] Email notifications
|
| 57 |
+
- [ ] Mobile responsive improvements
|
| 58 |
+
- [ ] Multi-language support
|
| 59 |
+
|
| 60 |
+
### [1.2.0] - Planned
|
| 61 |
+
- [ ] Machine Learning predictions
|
| 62 |
+
- [ ] Advanced charting
|
| 63 |
+
- [ ] Portfolio management
|
| 64 |
+
- [ ] Trading signals
|
| 65 |
+
- [ ] Price alerts
|
| 66 |
+
- [ ] Historical data analysis
|
| 67 |
+
- [ ] API key management
|
| 68 |
+
- [ ] Role-based access control
|
| 69 |
+
|
| 70 |
+
### [2.0.0] - Future
|
| 71 |
+
- [ ] Microservices architecture
|
| 72 |
+
- [ ] Kubernetes deployment
|
| 73 |
+
- [ ] GraphQL API
|
| 74 |
+
- [ ] Mobile app
|
| 75 |
+
- [ ] Desktop app (Electron)
|
| 76 |
+
- [ ] Blockchain integration
|
| 77 |
+
- [ ] Smart contract monitoring
|
| 78 |
+
- [ ] DeFi protocol tracking
|
| 79 |
+
|
| 80 |
+
---
|
| 81 |
+
|
| 82 |
+
## 🐛 Bug Fixes
|
| 83 |
+
|
| 84 |
+
### [1.0.0]
|
| 85 |
+
- ✅ Fixed WebSocket connection issues
|
| 86 |
+
- ✅ Fixed API endpoint routing
|
| 87 |
+
- ✅ Fixed data filtering in KPI display
|
| 88 |
+
- ✅ Fixed chart initialization
|
| 89 |
+
- ✅ Fixed CORS headers
|
| 90 |
+
|
| 91 |
+
---
|
| 92 |
+
|
| 93 |
+
## 🔒 Security Updates
|
| 94 |
+
|
| 95 |
+
### [1.0.0]
|
| 96 |
+
- ✅ CORS configuration
|
| 97 |
+
- ✅ Input validation
|
| 98 |
+
- ✅ Error message sanitization
|
| 99 |
+
|
| 100 |
+
---
|
| 101 |
+
|
| 102 |
+
## ⚡ Performance Improvements
|
| 103 |
+
|
| 104 |
+
### [1.0.0]
|
| 105 |
+
- ✅ Optimized WebSocket messages
|
| 106 |
+
- ✅ Reduced API call frequency
|
| 107 |
+
- ✅ Improved chart rendering
|
| 108 |
+
- ✅ Cache implementation
|
| 109 |
+
|
| 110 |
+
---
|
| 111 |
+
|
| 112 |
+
## 📦 Dependencies
|
| 113 |
+
|
| 114 |
+
### Python Packages (v1.0.0)
|
| 115 |
+
```
|
| 116 |
+
fastapi==0.104.1
|
| 117 |
+
uvicorn[standard]==0.24.0
|
| 118 |
+
websockets==12.0
|
| 119 |
+
python-multipart==0.0.6
|
| 120 |
+
pydantic==2.5.0
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
### Frontend Libraries
|
| 124 |
+
```
|
| 125 |
+
Chart.js 4.4.0
|
| 126 |
+
Google Fonts (Inter)
|
| 127 |
+
```
|
| 128 |
+
|
| 129 |
+
---
|
| 130 |
+
|
| 131 |
+
## 🎯 Known Issues
|
| 132 |
+
|
| 133 |
+
### [1.0.0]
|
| 134 |
+
- Mock data only (not connected to real APIs)
|
| 135 |
+
- No data persistence
|
| 136 |
+
- Limited to localhost
|
| 137 |
+
- No authentication
|
| 138 |
+
|
| 139 |
+
---
|
| 140 |
+
|
| 141 |
+
## 💝 تشکرات / Acknowledgments
|
| 142 |
+
|
| 143 |
+
این پروژه با استفاده از:
|
| 144 |
+
- FastAPI framework
|
| 145 |
+
- Chart.js library
|
| 146 |
+
- Google Fonts
|
| 147 |
+
- Community feedback
|
| 148 |
+
|
| 149 |
+
---
|
| 150 |
+
|
| 151 |
+
## 📞 گزارش باگ / Bug Reports
|
| 152 |
+
|
| 153 |
+
برای گزارش باگ یا پیشنهاد:
|
| 154 |
+
- Issue باز کنید
|
| 155 |
+
- ایمیل بزنید
|
| 156 |
+
- Pull Request بزنید
|
| 157 |
+
|
| 158 |
+
---
|
| 159 |
+
|
| 160 |
+
**نسخه فعلی / Current Version: 1.0.0**
|
| 161 |
+
**تاریخ انتشار / Release Date: 2025-01-15**
|
QUICK_START.md
CHANGED
|
@@ -1,182 +1,104 @@
|
|
| 1 |
-
# 🚀 Quick Start Guide
|
| 2 |
-
|
| 3 |
-
##
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
### 1. Main Dashboard (Full Features)
|
| 10 |
-
**URL:** http://localhost:7860/index.html
|
| 11 |
-
|
| 12 |
-
Features:
|
| 13 |
-
- Real-time API monitoring
|
| 14 |
-
- Provider inventory
|
| 15 |
-
- Rate limit tracking
|
| 16 |
-
- Connection logs
|
| 17 |
-
- Schedule management
|
| 18 |
-
- Data freshness monitoring
|
| 19 |
-
- Failure analysis
|
| 20 |
-
- **🤗 HuggingFace Tab** (NEW!)
|
| 21 |
-
|
| 22 |
-
### 2. HuggingFace Console (Standalone)
|
| 23 |
-
**URL:** http://localhost:7860/hf_console.html
|
| 24 |
-
|
| 25 |
-
Features:
|
| 26 |
-
- HF Health Status
|
| 27 |
-
- Models Registry Browser
|
| 28 |
-
- Datasets Registry Browser
|
| 29 |
-
- Local Search (snapshot)
|
| 30 |
-
- Sentiment Analysis (local pipeline)
|
| 31 |
-
|
| 32 |
-
### 3. API Documentation
|
| 33 |
-
**URL:** http://localhost:7860/docs
|
| 34 |
-
|
| 35 |
-
Interactive API documentation with all endpoints
|
| 36 |
-
|
| 37 |
-
## 🤗 HuggingFace Features
|
| 38 |
-
|
| 39 |
-
### Available Endpoints:
|
| 40 |
-
|
| 41 |
-
1. **Health Check**
|
| 42 |
-
```
|
| 43 |
-
GET /api/hf/health
|
| 44 |
-
```
|
| 45 |
-
Returns: Registry health, last refresh time, model/dataset counts
|
| 46 |
-
|
| 47 |
-
2. **Force Refresh Registry**
|
| 48 |
-
```
|
| 49 |
-
POST /api/hf/refresh
|
| 50 |
-
```
|
| 51 |
-
Manually trigger registry update from HuggingFace Hub
|
| 52 |
-
|
| 53 |
-
3. **Get Models Registry**
|
| 54 |
-
```
|
| 55 |
-
GET /api/hf/registry?kind=models
|
| 56 |
-
```
|
| 57 |
-
Returns: List of all cached crypto-related models
|
| 58 |
-
|
| 59 |
-
4. **Get Datasets Registry**
|
| 60 |
-
```
|
| 61 |
-
GET /api/hf/registry?kind=datasets
|
| 62 |
-
```
|
| 63 |
-
Returns: List of all cached crypto-related datasets
|
| 64 |
-
|
| 65 |
-
5. **Search Registry**
|
| 66 |
-
```
|
| 67 |
-
GET /api/hf/search?q=crypto&kind=models
|
| 68 |
-
```
|
| 69 |
-
Search local snapshot for models or datasets
|
| 70 |
-
|
| 71 |
-
6. **Run Sentiment Analysis**
|
| 72 |
-
```
|
| 73 |
-
POST /api/hf/run-sentiment
|
| 74 |
-
Body: {"texts": ["BTC strong", "ETH weak"]}
|
| 75 |
-
```
|
| 76 |
-
Analyze crypto sentiment using local transformers
|
| 77 |
-
|
| 78 |
-
## 🎯 How to Use
|
| 79 |
-
|
| 80 |
-
### Option 1: Main Dashboard
|
| 81 |
-
1. Open http://localhost:7860/index.html in your browser
|
| 82 |
-
2. Click on the **"🤗 HuggingFace"** tab at the top
|
| 83 |
-
3. Explore:
|
| 84 |
-
- Health status
|
| 85 |
-
- Models and datasets registries
|
| 86 |
-
- Search functionality
|
| 87 |
-
- Sentiment analysis
|
| 88 |
-
|
| 89 |
-
### Option 2: Standalone HF Console
|
| 90 |
-
1. Open http://localhost:7860/hf_console.html
|
| 91 |
-
2. All HF features in a clean, focused interface
|
| 92 |
-
3. Perfect for testing and development
|
| 93 |
-
|
| 94 |
-
## 🧪 Test the Integration
|
| 95 |
-
|
| 96 |
-
### Test 1: Check Health
|
| 97 |
-
```powershell
|
| 98 |
-
Invoke-WebRequest -Uri "http://localhost:7860/api/hf/health" -UseBasicParsing | Select-Object -ExpandProperty Content
|
| 99 |
-
```
|
| 100 |
|
| 101 |
-
|
| 102 |
-
```
|
| 103 |
-
|
| 104 |
```
|
| 105 |
|
| 106 |
-
|
| 107 |
-
```
|
| 108 |
-
|
|
|
|
|
|
|
| 109 |
```
|
| 110 |
|
| 111 |
-
|
| 112 |
-
```powershell
|
| 113 |
-
$body = @{texts = @("BTC strong breakout", "ETH looks weak")} | ConvertTo-Json
|
| 114 |
-
Invoke-WebRequest -Uri "http://localhost:7860/api/hf/run-sentiment" -Method POST -Body $body -ContentType "application/json" -UseBasicParsing | Select-Object -ExpandProperty Content
|
| 115 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
-
|
| 118 |
|
| 119 |
-
|
| 120 |
-
- ElKulako/cryptobert
|
| 121 |
-
- kk08/CryptoBERT
|
| 122 |
|
| 123 |
-
###
|
| 124 |
-
|
| 125 |
-
- WinkingFace/CryptoLM-Bitcoin-BTC-USDT
|
| 126 |
-
- WinkingFace/CryptoLM-Ethereum-ETH-USDT
|
| 127 |
-
- WinkingFace/CryptoLM-Solana-SOL-USDT
|
| 128 |
-
- WinkingFace/CryptoLM-Ripple-XRP-USDT
|
| 129 |
|
| 130 |
-
###
|
| 131 |
-
- Searches HuggingFace Hub for crypto-related models
|
| 132 |
-
- Searches for sentiment-analysis models
|
| 133 |
-
- Auto-refreshes every 6 hours (configurable)
|
| 134 |
|
| 135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
# HuggingFace Token (optional, for higher rate limits)
|
| 141 |
-
HUGGINGFACE_TOKEN=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
|
| 142 |
|
| 143 |
-
|
| 144 |
-
ENABLE_SENTIMENT=true
|
| 145 |
|
| 146 |
-
|
| 147 |
-
SENTIMENT_SOCIAL_MODEL=ElKulako/cryptobert
|
| 148 |
-
SENTIMENT_NEWS_MODEL=kk08/CryptoBERT
|
| 149 |
|
| 150 |
-
|
| 151 |
-
|
|
|
|
|
|
|
| 152 |
|
| 153 |
-
|
| 154 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
```
|
| 156 |
|
| 157 |
-
|
| 158 |
|
| 159 |
-
|
| 160 |
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
-
|
|
|
|
|
|
|
| 164 |
|
| 165 |
-
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
| 167 |
```
|
| 168 |
|
| 169 |
-
|
| 170 |
|
| 171 |
-
|
| 172 |
-
- **Registry**: Auto-refreshes every 6 hours, or manually via the UI
|
| 173 |
-
- **Free Resources**: All endpoints use free HuggingFace APIs
|
| 174 |
-
- **No API Key Required**: Works without authentication (with rate limits)
|
| 175 |
-
- **Local Inference**: Sentiment analysis runs locally using transformers
|
| 176 |
|
| 177 |
-
|
|
|
|
| 178 |
|
| 179 |
-
|
| 180 |
|
| 181 |
-
|
| 182 |
-
**
|
|
|
|
| 1 |
+
# 🚀 راهنمای سریع / Quick Start Guide
|
| 2 |
+
|
| 3 |
+
## فارسی - راهاندازی در 3 مرحله
|
| 4 |
+
|
| 5 |
+
### پیشنیاز
|
| 6 |
+
Python 3.8+ نصب باشد (https://python.org/downloads)
|
| 7 |
+
|
| 8 |
+
### مراحل
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
+
#### 1️⃣ دابل کلیک روی `start.bat`
|
| 11 |
+
```
|
| 12 |
+
فقط دابل کلیک!
|
| 13 |
```
|
| 14 |
|
| 15 |
+
#### 2️⃣ صبر کنید تا نصب شود
|
| 16 |
+
```
|
| 17 |
+
- محیط مجازی ایجاد میشود
|
| 18 |
+
- پکیجها نصب میشوند
|
| 19 |
+
- سرور اجرا میشود
|
| 20 |
```
|
| 21 |
|
| 22 |
+
#### 3️⃣ مرورگر را باز کنید
|
|
|
|
|
|
|
|
|
|
| 23 |
```
|
| 24 |
+
http://localhost:8000/dashboard
|
| 25 |
+
```
|
| 26 |
+
|
| 27 |
+
**تمام! 🎉**
|
| 28 |
|
| 29 |
+
---
|
| 30 |
|
| 31 |
+
## English - 3-Step Setup
|
|
|
|
|
|
|
| 32 |
|
| 33 |
+
### Prerequisites
|
| 34 |
+
Python 3.8+ installed (https://python.org/downloads)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
+
### Steps
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
+
#### 1️⃣ Double-click `start.bat`
|
| 39 |
+
```
|
| 40 |
+
Just double-click!
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
#### 2️⃣ Wait for installation
|
| 44 |
+
```
|
| 45 |
+
- Virtual environment is created
|
| 46 |
+
- Packages are installed
|
| 47 |
+
- Server starts
|
| 48 |
+
```
|
| 49 |
|
| 50 |
+
#### 3️⃣ Open browser
|
| 51 |
+
```
|
| 52 |
+
http://localhost:8000/dashboard
|
| 53 |
+
```
|
| 54 |
|
| 55 |
+
**Done! 🎉**
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
---
|
|
|
|
| 58 |
|
| 59 |
+
## 🔧 روشهای جایگزین / Alternative Methods
|
|
|
|
|
|
|
| 60 |
|
| 61 |
+
### روش 1: ��ستفاده از start.py
|
| 62 |
+
```bash
|
| 63 |
+
python start.py
|
| 64 |
+
```
|
| 65 |
|
| 66 |
+
### روش 2: دستی
|
| 67 |
+
```bash
|
| 68 |
+
python -m venv venv
|
| 69 |
+
venv\Scripts\activate
|
| 70 |
+
pip install -r requirements.txt
|
| 71 |
+
python app.py
|
| 72 |
```
|
| 73 |
|
| 74 |
+
---
|
| 75 |
|
| 76 |
+
## 🆘 مشکل دارید؟ / Having Issues?
|
| 77 |
|
| 78 |
+
### Python پیدا نمیشود
|
| 79 |
+
✅ Python را نصب کنید
|
| 80 |
+
✅ "Add to PATH" را فعال کنید
|
| 81 |
+
✅ سیستم را Restart کنید
|
| 82 |
|
| 83 |
+
### پورت اشغال است
|
| 84 |
+
✅ پورت را در app.py تغییر دهید
|
| 85 |
+
✅ یا برنامه قبلی را ببندید
|
| 86 |
|
| 87 |
+
### پکیج نصب نمیشود
|
| 88 |
+
✅ اینترنت را چک کنید
|
| 89 |
+
✅ pip را آپدیت کنید:
|
| 90 |
+
```bash
|
| 91 |
+
python -m pip install --upgrade pip
|
| 92 |
```
|
| 93 |
|
| 94 |
+
---
|
| 95 |
|
| 96 |
+
## 📞 کمک بیشتر / More Help
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
+
راهنمای کامل را در `README.md` بخوانید
|
| 99 |
+
Read full guide in `README.md`
|
| 100 |
|
| 101 |
+
---
|
| 102 |
|
| 103 |
+
**موفق باشید! 🚀**
|
| 104 |
+
**Good luck! 🚀**
|
README.md
CHANGED
|
@@ -1,149 +1,361 @@
|
|
| 1 |
-
|
| 2 |
-
sdk: docker
|
| 3 |
-
---
|
| 4 |
-
# 🚀 داشبورد هوشمند کریپتو
|
| 5 |
|
| 6 |
-
|
| 7 |
|
| 8 |
-
|
| 9 |
|
| 10 |
-
##
|
| 11 |
|
| 12 |
-
-
|
| 13 |
-
-
|
| 14 |
-
-
|
| 15 |
-
-
|
| 16 |
-
-
|
| 17 |
-
-
|
| 18 |
-
-
|
| 19 |
-
- 🔄 بهروزرسانی خودکار هر 30 ثانیه
|
| 20 |
-
- 📱 طراحی واکنشگرا (Responsive Design)
|
| 21 |
|
| 22 |
-
##
|
| 23 |
|
| 24 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
-
1. **کلون کردن پروژه**
|
| 33 |
```bash
|
| 34 |
-
|
| 35 |
-
|
| 36 |
```
|
| 37 |
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
```bash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
pip install -r requirements.txt
|
| 41 |
-
```
|
| 42 |
|
| 43 |
-
|
| 44 |
-
```bash
|
| 45 |
python app.py
|
| 46 |
```
|
| 47 |
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
-
###
|
| 56 |
-
- `GET /api/crypto/market-overview` - نمای کلی بازار
|
| 57 |
-
- `GET /api/crypto/prices/trending?limit=10` - ارزهای ترند
|
| 58 |
-
- `GET /api/crypto/prices/top?limit=20` - برترین ارزها
|
| 59 |
|
| 60 |
-
|
| 61 |
-
-
|
| 62 |
-
-
|
| 63 |
-
-
|
| 64 |
|
| 65 |
-
|
| 66 |
-
-
|
| 67 |
-
-
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
|
| 70 |
-
-
|
|
|
|
|
|
|
| 71 |
|
| 72 |
-
|
| 73 |
-
-
|
|
|
|
|
|
|
| 74 |
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
```
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
│
|
| 80 |
-
|
| 81 |
-
├── templates/
|
| 82 |
-
│ └── index.html # رابط کاربری
|
| 83 |
-
├── requirements.txt # وابستگیها
|
| 84 |
-
└── README.md # مستندات
|
| 85 |
```
|
| 86 |
|
| 87 |
-
##
|
| 88 |
|
| 89 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
-
|
| 92 |
-
```
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
```
|
| 95 |
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
```python
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
```
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
| 105 |
-
- **Alternative.me** - شاخص ترس و طمع
|
| 106 |
-
- دادههای شبیهسازی شده برای Whales و Blockchain
|
| 107 |
|
| 108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
|
| 110 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
-
|
| 118 |
|
|
|
|
|
|
|
| 119 |
```bash
|
| 120 |
-
#
|
| 121 |
-
python
|
|
|
|
|
|
|
|
|
|
| 122 |
```
|
| 123 |
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
-
### مشکل CORS
|
| 127 |
-
اگر در دسترسی به API مشکل دارید، CORS را بررسی کنید:
|
| 128 |
```python
|
| 129 |
-
app.
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
```
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
##
|
| 140 |
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
| 142 |
|
| 143 |
-
##
|
| 144 |
|
| 145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
-
|
|
|
|
|
|
| 1 |
+
# 🚀 Crypto API Monitor - Real-time Dashboard
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
+
یک داشبورد مانیتورینگ حرفهای برای ارزهای دیجیتال با قابلیت نمایش دادههای Real-time
|
| 4 |
|
| 5 |
+
A professional monitoring dashboard for cryptocurrencies with real-time data display capabilities
|
| 6 |
|
| 7 |
+
## 📋 فهرست مطالب / Table of Contents
|
| 8 |
|
| 9 |
+
- [ویژگیها / Features](#ویژگیها--features)
|
| 10 |
+
- [نصب و راهاندازی / Installation](#نصب-و-راهاندازی--installation)
|
| 11 |
+
- [استفاده / Usage](#استفاده--usage)
|
| 12 |
+
- [ساختار پروژه / Project Structure](#ساختار-پروژه--project-structure)
|
| 13 |
+
- [API Endpoints](#api-endpoints)
|
| 14 |
+
- [تنظیمات / Configuration](#تنظیمات--configuration)
|
| 15 |
+
- [مشکلات رایج / Troubleshooting](#مشکلات-رایج--troubleshooting)
|
|
|
|
|
|
|
| 16 |
|
| 17 |
+
## ✨ ویژگیها / Features
|
| 18 |
|
| 19 |
+
### فارسی
|
| 20 |
+
- 📊 **داشبورد Real-time**: نمایش زنده قیمت ارزهای دیجیتال
|
| 21 |
+
- 🔌 **WebSocket**: اتصال دوطرفه برای بهروزرسانی لحظهای
|
| 22 |
+
- 📈 **نمودارهای تعاملی**: نمایش گرافیکی دادههای بازار
|
| 23 |
+
- 🏥 **مانیتورینگ سلامت سیستم**: نظارت بر وضعیت سرورها و APIها
|
| 24 |
+
- 🔔 **سیستم هشدار**: اعلانهای خودکار برای رویدادهای مهم
|
| 25 |
+
- 💼 **مدیریت Providers**: نظارت بر وضعیت صرافیها و منابع داده
|
| 26 |
+
- 🎨 **رابط کاربری مدرن**: طراحی زیبا و کاربرپسند
|
| 27 |
+
- 🌐 **پشتیبانی از چندین منبع**: Binance, CoinGecko, Coinbase و بیشتر
|
| 28 |
|
| 29 |
+
### English
|
| 30 |
+
- 📊 **Real-time Dashboard**: Live cryptocurrency price display
|
| 31 |
+
- 🔌 **WebSocket**: Bidirectional connection for instant updates
|
| 32 |
+
- 📈 **Interactive Charts**: Graphical display of market data
|
| 33 |
+
- 🏥 **System Health Monitoring**: Server and API status tracking
|
| 34 |
+
- 🔔 **Alert System**: Automatic notifications for important events
|
| 35 |
+
- 💼 **Provider Management**: Exchange and data source monitoring
|
| 36 |
+
- 🎨 **Modern UI**: Beautiful and user-friendly interface
|
| 37 |
+
- 🌐 **Multi-source Support**: Binance, CoinGecko, Coinbase and more
|
| 38 |
+
|
| 39 |
+
## 🛠️ نصب و راهاندازی / Installation
|
| 40 |
|
| 41 |
+
### پیشنیازها / Prerequisites
|
| 42 |
+
|
| 43 |
+
#### ویندوز / Windows:
|
| 44 |
+
1. **Python 3.8 یا بالاتر**
|
| 45 |
+
- دانلود از: https://www.python.org/downloads/
|
| 46 |
+
- ⚠️ حتماً گزینه "Add Python to PATH" را فعال کنید
|
| 47 |
+
|
| 48 |
+
2. **مرورگر مدرن**
|
| 49 |
+
- Chrome, Firefox, Edge یا Safari
|
| 50 |
+
|
| 51 |
+
### روش نصب / Installation Steps
|
| 52 |
+
|
| 53 |
+
#### روش اول: استفاده از فایل Batch (توصیه میشود) / Method 1: Using Batch File (Recommended)
|
| 54 |
|
|
|
|
| 55 |
```bash
|
| 56 |
+
# فقط دابل کلیک روی start.bat
|
| 57 |
+
# Just double-click on start.bat
|
| 58 |
```
|
| 59 |
|
| 60 |
+
این فایل به صورت خودکار:
|
| 61 |
+
- محیط مجازی Python را ایجاد میکند
|
| 62 |
+
- تمام پکیجهای مورد نیاز را نصب میکند
|
| 63 |
+
- سرور را راهاندازی میکند
|
| 64 |
+
|
| 65 |
+
#### روش دوم: نصب دستی / Method 2: Manual Installation
|
| 66 |
+
|
| 67 |
```bash
|
| 68 |
+
# 1. ایجاد محیط مجازی / Create virtual environment
|
| 69 |
+
python -m venv venv
|
| 70 |
+
|
| 71 |
+
# 2. فعالسازی محیط مجازی / Activate virtual environment
|
| 72 |
+
# Windows:
|
| 73 |
+
venv\Scripts\activate
|
| 74 |
+
|
| 75 |
+
# 3. نصب پکیجها / Install packages
|
| 76 |
pip install -r requirements.txt
|
|
|
|
| 77 |
|
| 78 |
+
# 4. اجرای سرور / Run server
|
|
|
|
| 79 |
python app.py
|
| 80 |
```
|
| 81 |
|
| 82 |
+
## 🎯 استفاده / Usage
|
| 83 |
+
|
| 84 |
+
### راهاندازی سریع / Quick Start
|
| 85 |
+
|
| 86 |
+
1. **اجرای برنامه / Run the application**:
|
| 87 |
+
```bash
|
| 88 |
+
# دابل کلیک روی start.bat یا
|
| 89 |
+
# Double-click start.bat or:
|
| 90 |
+
python app.py
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
2. **باز کردن داشبورد / Open Dashboard**:
|
| 94 |
+
- مرورگر خود را باز کنید
|
| 95 |
+
- ��ه آدرس زیر بروید:
|
| 96 |
+
```
|
| 97 |
+
http://localhost:8000/dashboard
|
| 98 |
+
```
|
| 99 |
|
| 100 |
+
3. **مشاهده مستندات API / View API Documentation**:
|
| 101 |
+
```
|
| 102 |
+
http://localhost:8000/docs
|
| 103 |
+
```
|
| 104 |
|
| 105 |
+
### قابلیتهای داشبورد / Dashboard Features
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
+
#### صفحه اصلی / Main Dashboard
|
| 108 |
+
- **KPIs**: نمایش آمارهای کلیدی سیستم
|
| 109 |
+
- **وضعیت سیستم**: نمایش سلامت کلی
|
| 110 |
+
- **WebSocket Status**: وضعیت اتصال Real-time
|
| 111 |
|
| 112 |
+
#### بخش Providers
|
| 113 |
+
- لیست تمام منابع داده
|
| 114 |
+
- وضعیت هر Provider
|
| 115 |
+
- زمان پاسخ و Uptime
|
| 116 |
+
- تعداد درخواستهای روزانه
|
| 117 |
|
| 118 |
+
#### بخش Categories
|
| 119 |
+
- دستهبندی ارزهای دیجیتال
|
| 120 |
+
- ارزش بازار هر دسته
|
| 121 |
+
- تغییرات 24 ساعته
|
| 122 |
|
| 123 |
+
#### بخش Rate Limits
|
| 124 |
+
- محدودیتهای API
|
| 125 |
+
- مقدار باقیمانده
|
| 126 |
+
- زمان بازنشانی
|
| 127 |
|
| 128 |
+
#### بخش Logs
|
| 129 |
+
- لاگهای سیستم
|
| 130 |
+
- پیامهای خطا و هشدار
|
| 131 |
+
- تاریخچه رویدادها
|
| 132 |
+
|
| 133 |
+
## 📁 ساختار پروژه / Project Structure
|
| 134 |
|
| 135 |
```
|
| 136 |
+
crypto-monitor/
|
| 137 |
+
│
|
| 138 |
+
├── app.py # FastAPI backend اصلی
|
| 139 |
+
├── index.html # فرانتاند داشبورد
|
| 140 |
+
├── requirements.txt # وابستگیهای Python
|
| 141 |
+
├── start.bat # فایل راهاندازی ویندوز
|
| 142 |
+
├── README.md # مستندات (این فایل)
|
| 143 |
│
|
| 144 |
+
└── venv/ # محیط مجازی Python (خودکار ایجاد میشود)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 145 |
```
|
| 146 |
|
| 147 |
+
## 🔌 API Endpoints
|
| 148 |
|
| 149 |
+
### Health & Status
|
| 150 |
+
```
|
| 151 |
+
GET /health # وضعیت سلامت سیستم
|
| 152 |
+
GET /api/health # (Alternative)
|
| 153 |
+
GET /status # وضعیت کلی
|
| 154 |
+
GET /info # اطلاعات سیستم
|
| 155 |
+
```
|
| 156 |
|
| 157 |
+
### Providers
|
| 158 |
+
```
|
| 159 |
+
GET /api/providers # لیست تمام Providers
|
| 160 |
+
GET /providers # (Alternative)
|
| 161 |
+
```
|
| 162 |
+
|
| 163 |
+
### Cryptocurrency Data
|
| 164 |
+
```
|
| 165 |
+
GET /api/crypto/prices/top?limit=10 # قیمت ارزها
|
| 166 |
+
GET /api/crypto/market-overview # خلاصه بازار
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
### Categories & Limits
|
| 170 |
+
```
|
| 171 |
+
GET /api/categories # دستهبندی ارزها
|
| 172 |
+
GET /api/rate-limits # محدودیتهای API
|
| 173 |
+
```
|
| 174 |
+
|
| 175 |
+
### Logs & Alerts
|
| 176 |
+
```
|
| 177 |
+
GET /api/logs?limit=50 # لاگهای سیستم
|
| 178 |
+
GET /api/alerts # هشدارهای فعال
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
### Hugging Face Integration
|
| 182 |
+
```
|
| 183 |
+
GET /api/hf/health # وضعیت HF
|
| 184 |
+
POST /api/hf/refresh # بروزرسانی داده
|
| 185 |
+
GET /api/hf/registry # لیست مدلها
|
| 186 |
+
POST /api/hf/search # جستجوی مدل
|
| 187 |
+
POST /api/hf/run-sentiment # تحلیل احساسات
|
| 188 |
+
```
|
| 189 |
+
|
| 190 |
+
### WebSocket
|
| 191 |
+
```
|
| 192 |
+
WS /ws/live # اتصال Real-time
|
| 193 |
+
WS /ws # (Alternative)
|
| 194 |
```
|
| 195 |
|
| 196 |
+
## ⚙️ تنظیمات / Configuration
|
| 197 |
+
|
| 198 |
+
### تغییر پورت / Changing Port
|
| 199 |
+
|
| 200 |
+
در فایل `app.py` خط آخر را تغییر دهید:
|
| 201 |
|
| 202 |
```python
|
| 203 |
+
uvicorn.run(
|
| 204 |
+
"app:app",
|
| 205 |
+
host="0.0.0.0",
|
| 206 |
+
port=8000, # پورت را اینجا تغییر دهید / Change port here
|
| 207 |
+
reload=True,
|
| 208 |
+
log_level="info"
|
| 209 |
+
)
|
| 210 |
```
|
| 211 |
|
| 212 |
+
### تنظیمات WebSocket
|
| 213 |
|
| 214 |
+
در فایل `index.html` بخش Configuration:
|
|
|
|
|
|
|
| 215 |
|
| 216 |
+
```javascript
|
| 217 |
+
const config = {
|
| 218 |
+
apiBaseUrl: '',
|
| 219 |
+
wsUrl: 'ws://localhost:8000/ws/live',
|
| 220 |
+
autoRefreshInterval: 30000, // 30 ثانیه / 30 seconds
|
| 221 |
+
maxRetries: 3
|
| 222 |
+
};
|
| 223 |
+
```
|
| 224 |
+
|
| 225 |
+
## 🐛 مشک��ات رایج / Troubleshooting
|
| 226 |
|
| 227 |
+
### مشکل 1: Python پیدا نمیشود
|
| 228 |
+
**حل:**
|
| 229 |
+
1. Python را از python.org نصب کنید
|
| 230 |
+
2. هنگام نصب "Add to PATH" را فعال کنید
|
| 231 |
+
3. سیستم را Restart کنید
|
| 232 |
|
| 233 |
+
### مشکل 2: پورت 8000 در حال استفاده است
|
| 234 |
+
**حل:**
|
| 235 |
+
```bash
|
| 236 |
+
# پیدا کردن پروسس
|
| 237 |
+
netstat -ano | findstr :8000
|
| 238 |
+
|
| 239 |
+
# بستن پروسس (Windows)
|
| 240 |
+
taskkill /PID <شماره_پروسس> /F
|
| 241 |
+
```
|
| 242 |
|
| 243 |
+
یا پورت را در `app.py` تغییر دهید.
|
| 244 |
|
| 245 |
+
### مشکل 3: pip install موفق نمیشود
|
| 246 |
+
**حل:**
|
| 247 |
```bash
|
| 248 |
+
# آپدیت pip
|
| 249 |
+
python -m pip install --upgrade pip
|
| 250 |
+
|
| 251 |
+
# نصب مجدد با verbose
|
| 252 |
+
pip install -r requirements.txt --verbose
|
| 253 |
```
|
| 254 |
|
| 255 |
+
### مشکل 4: WebSocket متصل نمیشود
|
| 256 |
+
**حل:**
|
| 257 |
+
1. بررسی کنید سرور در حال اجرا باشد
|
| 258 |
+
2. Firewall را چک کنید
|
| 259 |
+
3. Cache مرورگر را پاک کنید
|
| 260 |
+
4. از مرورگر دیگری امتحان کنید
|
| 261 |
+
|
| 262 |
+
### مشکل 5: دادهها نمایش داده نمیشوند
|
| 263 |
+
**حل:**
|
| 264 |
+
1. Console مرورگر را باز کنید (F12)
|
| 265 |
+
2. ارورها را بررسی کنید
|
| 266 |
+
3. بررسی کنید API Endpoints پاسخ میدهند:
|
| 267 |
+
```
|
| 268 |
+
http://localhost:8000/health
|
| 269 |
+
```
|
| 270 |
+
|
| 271 |
+
## 📊 نمونه دادهها / Sample Data
|
| 272 |
+
|
| 273 |
+
این پروژه از دادههای Mock (تقلبی) استفاده میکند برای نمایش قابلیتها.
|
| 274 |
+
|
| 275 |
+
برای اتصال به API واقعی:
|
| 276 |
+
1. فایل `app.py` را ویرایش کنید
|
| 277 |
+
2. توابع `generate_*` را با API calls واقعی جایگزین کنید
|
| 278 |
+
3. کلیدهای API خود را اضافه کنید
|
| 279 |
+
|
| 280 |
+
## 🔒 امنیت / Security
|
| 281 |
+
|
| 282 |
+
### توصیههای امنیتی:
|
| 283 |
+
- از Environment Variables برای API Keys استفاده کنید
|
| 284 |
+
- HTTPS را در Production فعال کنید
|
| 285 |
+
- Rate Limiting را پیادهسازی کنید
|
| 286 |
+
- Input Validation را اضافه کنید
|
| 287 |
+
|
| 288 |
+
## 📈 گسترش پروژه / Extending
|
| 289 |
+
|
| 290 |
+
### اضافه کردن Provider جدید:
|
| 291 |
|
|
|
|
|
|
|
| 292 |
```python
|
| 293 |
+
# در app.py توابع generate_providers_data()
|
| 294 |
+
providers.append({
|
| 295 |
+
"name": "YourProvider",
|
| 296 |
+
"type": "Exchange",
|
| 297 |
+
"status": "operational",
|
| 298 |
+
# ...
|
| 299 |
+
})
|
| 300 |
+
```
|
| 301 |
+
|
| 302 |
+
### اضافه کردن Endpoint جدید:
|
| 303 |
+
|
| 304 |
+
```python
|
| 305 |
+
@app.get("/api/your-endpoint")
|
| 306 |
+
async def your_endpoint():
|
| 307 |
+
return {"data": "your data"}
|
| 308 |
```
|
| 309 |
|
| 310 |
+
## 🤝 مشارکت / Contributing
|
| 311 |
+
|
| 312 |
+
برای مشارکت در پروژه:
|
| 313 |
+
1. Fork کنید
|
| 314 |
+
2. Branch جدید بسازید
|
| 315 |
+
3. تغییرات را Commit کنید
|
| 316 |
+
4. Pull Request بزنید
|
| 317 |
+
|
| 318 |
+
## 📄 لایسنس / License
|
| 319 |
+
|
| 320 |
+
این پروژه تحت لایسنس MIT منتشر شده است.
|
| 321 |
+
|
| 322 |
+
## 👨💻 سازنده / Developer
|
| 323 |
+
|
| 324 |
+
**Niema**
|
| 325 |
+
- متخصص در سیستمهای Trading و AI
|
| 326 |
+
- تجربه در Full-stack Development
|
| 327 |
+
- تخصص در React/TypeScript و FastAPI
|
| 328 |
|
| 329 |
+
## 📞 پشتیبانی / Support
|
| 330 |
|
| 331 |
+
برای مشکلات و سوالات:
|
| 332 |
+
- Issue باز کنید در GitHub
|
| 333 |
+
- ایمیل بزنید
|
| 334 |
+
- مستندات را مطالعه کنید
|
| 335 |
|
| 336 |
+
## 🎓 یادگیری بیشتر / Learn More
|
| 337 |
|
| 338 |
+
### منابع مفید:
|
| 339 |
+
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
| 340 |
+
- [WebSocket Guide](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
|
| 341 |
+
- [Chart.js Documentation](https://www.chartjs.org/docs/)
|
| 342 |
+
- [Python Async/Await](https://docs.python.org/3/library/asyncio.html)
|
| 343 |
|
| 344 |
+
---
|
| 345 |
+
|
| 346 |
+
## 🚀 Ready to Start?
|
| 347 |
+
|
| 348 |
+
```bash
|
| 349 |
+
# فقط این دستور را اجرا کنید:
|
| 350 |
+
# Just run this command:
|
| 351 |
+
|
| 352 |
+
start.bat
|
| 353 |
+
```
|
| 354 |
+
|
| 355 |
+
**و داشبورد شما آماده است! 🎉**
|
| 356 |
+
**Your dashboard is ready! 🎉**
|
| 357 |
+
|
| 358 |
+
---
|
| 359 |
|
| 360 |
+
**ساخته شده با ❤️ برای کامیونیتی ارز دیجیتال**
|
| 361 |
+
**Made with ❤️ for the Crypto Community**
|
app.py
CHANGED
|
@@ -1,22 +1,28 @@
|
|
|
|
|
| 1 |
"""
|
| 2 |
-
Crypto
|
| 3 |
-
|
| 4 |
"""
|
| 5 |
|
| 6 |
-
from fastapi import FastAPI, HTTPException
|
| 7 |
from fastapi.staticfiles import StaticFiles
|
| 8 |
-
from fastapi.responses import HTMLResponse,
|
| 9 |
from fastapi.middleware.cors import CORSMiddleware
|
| 10 |
-
import
|
| 11 |
import asyncio
|
| 12 |
-
from datetime import datetime, timedelta
|
| 13 |
-
from typing import List, Dict, Optional
|
| 14 |
import random
|
| 15 |
-
import
|
|
|
|
|
|
|
| 16 |
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
|
| 19 |
-
# CORS
|
| 20 |
app.add_middleware(
|
| 21 |
CORSMiddleware,
|
| 22 |
allow_origins=["*"],
|
|
@@ -25,496 +31,421 @@ app.add_middleware(
|
|
| 25 |
allow_headers=["*"],
|
| 26 |
)
|
| 27 |
|
| 28 |
-
#
|
| 29 |
-
|
| 30 |
-
# ============================================================================
|
| 31 |
-
|
| 32 |
-
class DataCache:
|
| 33 |
-
"""سیستم کش ساده برای ذخیره موقت دادهها"""
|
| 34 |
def __init__(self):
|
| 35 |
-
self.
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
if key in self.cache and key in self.cache_time:
|
| 41 |
-
if (datetime.now() - self.cache_time[key]).seconds < ttl:
|
| 42 |
-
return self.cache[key]
|
| 43 |
-
return None
|
| 44 |
-
|
| 45 |
-
def set(self, key: str, value):
|
| 46 |
-
"""ذخیره داده در کش"""
|
| 47 |
-
self.cache[key] = value
|
| 48 |
-
self.cache_time[key] = datetime.now()
|
| 49 |
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
|
| 69 |
-
return
|
| 70 |
|
| 71 |
-
|
| 72 |
-
"""
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
return
|
| 85 |
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
|
|
|
| 90 |
@app.get("/")
|
| 91 |
async def root():
|
| 92 |
-
"""
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
-
@app.get("/
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
result = {
|
| 116 |
-
"total_market_cap": data.get('total_market_cap', {}).get('usd', 0),
|
| 117 |
-
"total_volume_24h": data.get('total_volume', {}).get('usd', 0),
|
| 118 |
-
"btc_dominance": data.get('market_cap_percentage', {}).get('btc', 0),
|
| 119 |
-
"active_cryptocurrencies": data.get('active_cryptocurrencies', 0),
|
| 120 |
-
"markets": data.get('markets', 0),
|
| 121 |
-
"market_cap_change_24h": data.get('market_cap_change_percentage_24h_usd', 0),
|
| 122 |
-
"updated_at": datetime.now().isoformat()
|
| 123 |
-
}
|
| 124 |
-
|
| 125 |
-
cache.set(cache_key, result)
|
| 126 |
-
return result
|
| 127 |
-
|
| 128 |
-
except Exception as e:
|
| 129 |
-
print(f"Error in market overview: {e}")
|
| 130 |
-
|
| 131 |
-
# دادههای پیشفرض
|
| 132 |
return {
|
| 133 |
-
"
|
| 134 |
-
"
|
| 135 |
-
"
|
| 136 |
-
"
|
| 137 |
-
"
|
| 138 |
-
"
|
| 139 |
-
"
|
|
|
|
| 140 |
}
|
| 141 |
|
| 142 |
-
@app.get("/api/
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
"""
|
| 147 |
-
|
| 148 |
-
cached = cache.get(cache_key, ttl=300) # 5 دقیقه
|
| 149 |
-
if cached:
|
| 150 |
-
return cached
|
| 151 |
-
|
| 152 |
-
try:
|
| 153 |
-
trending = await fetch_coingecko("search/trending", {})
|
| 154 |
-
|
| 155 |
-
if trending and 'coins' in trending:
|
| 156 |
-
result = []
|
| 157 |
-
for item in trending['coins'][:limit]:
|
| 158 |
-
coin = item.get('item', {})
|
| 159 |
-
result.append({
|
| 160 |
-
"symbol": coin.get('symbol', '').upper(),
|
| 161 |
-
"name": coin.get('name', ''),
|
| 162 |
-
"price": coin.get('data', {}).get('price', 0),
|
| 163 |
-
"price_change_24h": coin.get('data', {}).get('price_change_percentage_24h', {}).get('usd', 0),
|
| 164 |
-
"market_cap": coin.get('data', {}).get('market_cap', 0),
|
| 165 |
-
"volume_24h": coin.get('data', {}).get('total_volume', 0),
|
| 166 |
-
"rank": coin.get('market_cap_rank', 0)
|
| 167 |
-
})
|
| 168 |
-
|
| 169 |
-
cache.set(cache_key, result)
|
| 170 |
-
return result
|
| 171 |
-
|
| 172 |
-
except Exception as e:
|
| 173 |
-
print(f"Error in trending coins: {e}")
|
| 174 |
-
|
| 175 |
-
# دادههای نمونه
|
| 176 |
-
return generate_sample_coins(limit)
|
| 177 |
|
| 178 |
@app.get("/api/crypto/prices/top")
|
| 179 |
-
async def
|
| 180 |
-
"""
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
cache_key = f"top_coins_{limit}"
|
| 184 |
-
cached = cache.get(cache_key, ttl=60)
|
| 185 |
-
if cached:
|
| 186 |
-
return cached
|
| 187 |
-
|
| 188 |
-
try:
|
| 189 |
-
params = {
|
| 190 |
-
"vs_currency": "usd",
|
| 191 |
-
"order": "market_cap_desc",
|
| 192 |
-
"per_page": limit,
|
| 193 |
-
"page": 1,
|
| 194 |
-
"sparkline": False,
|
| 195 |
-
"price_change_percentage": "24h"
|
| 196 |
-
}
|
| 197 |
-
|
| 198 |
-
coins = await fetch_coingecko("coins/markets", params)
|
| 199 |
-
|
| 200 |
-
if coins:
|
| 201 |
-
result = []
|
| 202 |
-
for coin in coins:
|
| 203 |
-
result.append({
|
| 204 |
-
"symbol": coin.get('symbol', '').upper(),
|
| 205 |
-
"name": coin.get('name', ''),
|
| 206 |
-
"price": coin.get('current_price', 0),
|
| 207 |
-
"price_change_24h": coin.get('price_change_percentage_24h', 0),
|
| 208 |
-
"market_cap": coin.get('market_cap', 0),
|
| 209 |
-
"volume_24h": coin.get('total_volume', 0),
|
| 210 |
-
"rank": coin.get('market_cap_rank', 0),
|
| 211 |
-
"circulating_supply": coin.get('circulating_supply', 0),
|
| 212 |
-
"high_24h": coin.get('high_24h', 0),
|
| 213 |
-
"low_24h": coin.get('low_24h', 0)
|
| 214 |
-
})
|
| 215 |
-
|
| 216 |
-
cache.set(cache_key, result)
|
| 217 |
-
return result
|
| 218 |
-
|
| 219 |
-
except Exception as e:
|
| 220 |
-
print(f"Error in top coins: {e}")
|
| 221 |
-
|
| 222 |
-
return generate_sample_coins(limit)
|
| 223 |
|
| 224 |
-
@app.get("/api/crypto/
|
| 225 |
-
async def
|
| 226 |
-
"""
|
| 227 |
-
|
| 228 |
-
"""
|
| 229 |
-
cache_key = f"news_{limit}"
|
| 230 |
-
cached = cache.get(cache_key, ttl=600) # 10 دقیقه
|
| 231 |
-
if cached:
|
| 232 |
-
return cached
|
| 233 |
-
|
| 234 |
-
# شبیهسازی اخبار (در نسخه واقعی از یک News API استفاده میشود)
|
| 235 |
-
news = []
|
| 236 |
-
sources = ["CoinDesk", "CryptoNews", "Bitcoin Magazine", "The Block", "Decrypt"]
|
| 237 |
-
titles = [
|
| 238 |
-
"Bitcoin Reaches New All-Time High",
|
| 239 |
-
"Ethereum 2.0 Upgrade Successful",
|
| 240 |
-
"Major Institution Announces Crypto Investment",
|
| 241 |
-
"New DeFi Protocol Launches",
|
| 242 |
-
"Regulatory Update on Cryptocurrency",
|
| 243 |
-
"Blockchain Technology Adoption Increases",
|
| 244 |
-
"NFT Market Shows Strong Growth",
|
| 245 |
-
"Layer 2 Solutions Gain Traction"
|
| 246 |
-
]
|
| 247 |
-
|
| 248 |
-
for i in range(limit):
|
| 249 |
-
news.append({
|
| 250 |
-
"title": random.choice(titles),
|
| 251 |
-
"source": random.choice(sources),
|
| 252 |
-
"url": f"https://example.com/news/{i}",
|
| 253 |
-
"published_at": (datetime.now() - timedelta(hours=random.randint(1, 24))).isoformat(),
|
| 254 |
-
"content": "Latest developments in the cryptocurrency market..."
|
| 255 |
-
})
|
| 256 |
-
|
| 257 |
-
cache.set(cache_key, news)
|
| 258 |
-
return news
|
| 259 |
-
|
| 260 |
-
@app.get("/api/crypto/sentiment/current")
|
| 261 |
-
async def get_current_sentiment():
|
| 262 |
-
"""
|
| 263 |
-
احساسات فعلی بازار - Fear & Greed Index
|
| 264 |
-
"""
|
| 265 |
-
cache_key = "sentiment_current"
|
| 266 |
-
cached = cache.get(cache_key, ttl=300) # 5 دقیقه
|
| 267 |
-
if cached:
|
| 268 |
-
return cached
|
| 269 |
-
|
| 270 |
-
try:
|
| 271 |
-
sentiment = await fetch_alternative_me("fng/")
|
| 272 |
-
|
| 273 |
-
if sentiment and 'data' in sentiment and len(sentiment['data']) > 0:
|
| 274 |
-
data = sentiment['data'][0]
|
| 275 |
-
|
| 276 |
-
result = {
|
| 277 |
-
"fear_greed_index": int(data.get('value', 50)),
|
| 278 |
-
"classification": data.get('value_classification', 'Neutral'),
|
| 279 |
-
"description": get_sentiment_description(int(data.get('value', 50))),
|
| 280 |
-
"timestamp": data.get('timestamp', datetime.now().isoformat())
|
| 281 |
-
}
|
| 282 |
-
|
| 283 |
-
cache.set(cache_key, result)
|
| 284 |
-
return result
|
| 285 |
|
| 286 |
-
|
| 287 |
-
|
|
|
|
| 288 |
|
| 289 |
-
# داده پیشفرض
|
| 290 |
-
value = 50
|
| 291 |
return {
|
| 292 |
-
"
|
| 293 |
-
"
|
| 294 |
-
"
|
|
|
|
|
|
|
| 295 |
"timestamp": datetime.now().isoformat()
|
| 296 |
}
|
| 297 |
|
| 298 |
-
@app.get("/api/
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
cache.set(cache_key, result)
|
| 326 |
-
return result
|
| 327 |
-
|
| 328 |
-
except Exception as e:
|
| 329 |
-
print(f"Error in sentiment history: {e}")
|
| 330 |
-
|
| 331 |
-
# دادههای نمونه
|
| 332 |
-
history = []
|
| 333 |
-
for i in range(hours // 24):
|
| 334 |
-
history.append({
|
| 335 |
-
"value": random.randint(20, 80),
|
| 336 |
-
"classification": "Neutral",
|
| 337 |
-
"timestamp": (datetime.now() - timedelta(days=i)).isoformat()
|
| 338 |
})
|
| 339 |
|
| 340 |
-
return
|
| 341 |
|
| 342 |
-
@app.get("/api/
|
| 343 |
-
|
| 344 |
-
|
| 345 |
-
|
| 346 |
-
"""
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
|
|
|
| 355 |
|
|
|
|
| 356 |
for i in range(limit):
|
| 357 |
-
|
| 358 |
-
"
|
| 359 |
-
"
|
| 360 |
-
"
|
| 361 |
-
"
|
| 362 |
-
"
|
| 363 |
-
"tx_hash": f"0x{''.join(random.choices('0123456789abcdef', k=64))}"
|
| 364 |
})
|
| 365 |
|
| 366 |
-
|
| 367 |
-
return transactions
|
| 368 |
|
| 369 |
-
@app.get("/api/
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
if
|
| 377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
"
|
| 383 |
-
"
|
| 384 |
-
"
|
| 385 |
-
"
|
| 386 |
-
}
|
| 387 |
-
"bsc": {
|
| 388 |
-
"gas_price_gwei": random.randint(3, 10),
|
| 389 |
-
"fast": random.randint(5, 15),
|
| 390 |
-
"standard": random.randint(3, 10),
|
| 391 |
-
"slow": random.randint(1, 5)
|
| 392 |
-
},
|
| 393 |
-
"polygon": {
|
| 394 |
-
"gas_price_gwei": random.randint(50, 200),
|
| 395 |
-
"fast": random.randint(100, 300),
|
| 396 |
-
"standard": random.randint(50, 150),
|
| 397 |
-
"slow": random.randint(20, 80)
|
| 398 |
-
}
|
| 399 |
-
}
|
| 400 |
|
| 401 |
-
|
| 402 |
-
return result
|
| 403 |
|
| 404 |
-
@app.
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
return cached
|
| 413 |
-
|
| 414 |
-
result = {
|
| 415 |
-
"ethereum": {
|
| 416 |
-
"latest_block": random.randint(18000000, 19000000),
|
| 417 |
-
"block_time": 12.0,
|
| 418 |
-
"pending_transactions": random.randint(100000, 500000),
|
| 419 |
-
"network_hashrate": random.randint(800, 1000)
|
| 420 |
-
},
|
| 421 |
-
"bitcoin": {
|
| 422 |
-
"latest_block": random.randint(800000, 850000),
|
| 423 |
-
"block_time": 600.0,
|
| 424 |
-
"pending_transactions": random.randint(5000, 50000),
|
| 425 |
-
"network_hashrate": random.randint(400, 600)
|
| 426 |
-
},
|
| 427 |
-
"bsc": {
|
| 428 |
-
"latest_block": random.randint(35000000, 36000000),
|
| 429 |
-
"block_time": 3.0,
|
| 430 |
-
"pending_transactions": random.randint(50000, 200000),
|
| 431 |
-
"network_hashrate": random.randint(100, 200)
|
| 432 |
-
}
|
| 433 |
}
|
| 434 |
-
|
| 435 |
-
cache.set(cache_key, result)
|
| 436 |
-
return result
|
| 437 |
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 441 |
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
return "Extreme Greed"
|
| 454 |
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
else:
|
| 466 |
-
return "بازار در طمع شدید است - زمان فروش"
|
| 467 |
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
{"symbol": "ADA", "name": "Cardano", "base_price": 0.52},
|
| 475 |
-
{"symbol": "SOL", "name": "Solana", "base_price": 98},
|
| 476 |
-
{"symbol": "XRP", "name": "Ripple", "base_price": 0.63},
|
| 477 |
-
{"symbol": "DOT", "name": "Polkadot", "base_price": 7.5},
|
| 478 |
-
{"symbol": "DOGE", "name": "Dogecoin", "base_price": 0.085},
|
| 479 |
-
{"symbol": "MATIC", "name": "Polygon", "base_price": 0.89},
|
| 480 |
-
{"symbol": "AVAX", "name": "Avalanche", "base_price": 37},
|
| 481 |
-
]
|
| 482 |
-
|
| 483 |
-
result = []
|
| 484 |
-
for i, coin in enumerate(coins[:limit]):
|
| 485 |
-
price_change = random.uniform(-10, 10)
|
| 486 |
-
price = coin["base_price"] * (1 + price_change / 100)
|
| 487 |
-
|
| 488 |
-
result.append({
|
| 489 |
-
"symbol": coin["symbol"],
|
| 490 |
-
"name": coin["name"],
|
| 491 |
-
"price": round(price, 2),
|
| 492 |
-
"price_change_24h": round(price_change, 2),
|
| 493 |
-
"market_cap": round(price * random.randint(10000000, 1000000000), 2),
|
| 494 |
-
"volume_24h": round(price * random.randint(1000000, 100000000), 2),
|
| 495 |
-
"rank": i + 1
|
| 496 |
-
})
|
| 497 |
|
| 498 |
-
return result
|
| 499 |
-
|
| 500 |
-
# ============================================================================
|
| 501 |
-
# Health Check
|
| 502 |
-
# ============================================================================
|
| 503 |
-
|
| 504 |
-
@app.get("/health")
|
| 505 |
-
async def health_check():
|
| 506 |
-
"""بررسی سلامت API"""
|
| 507 |
return {
|
| 508 |
-
"
|
| 509 |
-
"
|
| 510 |
-
"
|
| 511 |
}
|
| 512 |
|
| 513 |
-
#
|
| 514 |
-
|
| 515 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 516 |
|
| 517 |
if __name__ == "__main__":
|
| 518 |
-
|
| 519 |
-
print("
|
| 520 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
+
Crypto API Monitor - FastAPI Backend
|
| 4 |
+
Real-time cryptocurrency monitoring dashboard backend
|
| 5 |
"""
|
| 6 |
|
| 7 |
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException
|
| 8 |
from fastapi.staticfiles import StaticFiles
|
| 9 |
+
from fastapi.responses import HTMLResponse, JSONResponse
|
| 10 |
from fastapi.middleware.cors import CORSMiddleware
|
| 11 |
+
from typing import List, Dict, Any
|
| 12 |
import asyncio
|
|
|
|
|
|
|
| 13 |
import random
|
| 14 |
+
import json
|
| 15 |
+
from datetime import datetime, timedelta
|
| 16 |
+
import uvicorn
|
| 17 |
|
| 18 |
+
# Initialize FastAPI app
|
| 19 |
+
app = FastAPI(
|
| 20 |
+
title="Crypto API Monitor",
|
| 21 |
+
description="Real-time cryptocurrency monitoring dashboard",
|
| 22 |
+
version="1.0.0"
|
| 23 |
+
)
|
| 24 |
|
| 25 |
+
# CORS middleware
|
| 26 |
app.add_middleware(
|
| 27 |
CORSMiddleware,
|
| 28 |
allow_origins=["*"],
|
|
|
|
| 31 |
allow_headers=["*"],
|
| 32 |
)
|
| 33 |
|
| 34 |
+
# WebSocket connections manager
|
| 35 |
+
class ConnectionManager:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
def __init__(self):
|
| 37 |
+
self.active_connections: List[WebSocket] = []
|
| 38 |
+
|
| 39 |
+
async def connect(self, websocket: WebSocket):
|
| 40 |
+
await websocket.accept()
|
| 41 |
+
self.active_connections.append(websocket)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
+
def disconnect(self, websocket: WebSocket):
|
| 44 |
+
self.active_connections.remove(websocket)
|
| 45 |
|
| 46 |
+
async def broadcast(self, message: dict):
|
| 47 |
+
for connection in self.active_connections:
|
| 48 |
+
try:
|
| 49 |
+
await connection.send_json(message)
|
| 50 |
+
except:
|
| 51 |
+
pass
|
| 52 |
|
| 53 |
+
manager = ConnectionManager()
|
| 54 |
+
|
| 55 |
+
# Mock data generators
|
| 56 |
+
def generate_crypto_prices():
|
| 57 |
+
"""Generate realistic cryptocurrency prices"""
|
| 58 |
+
cryptos = [
|
| 59 |
+
{"symbol": "BTC", "name": "Bitcoin", "base_price": 42000},
|
| 60 |
+
{"symbol": "ETH", "name": "Ethereum", "base_price": 2200},
|
| 61 |
+
{"symbol": "BNB", "name": "Binance Coin", "base_price": 310},
|
| 62 |
+
{"symbol": "SOL", "name": "Solana", "base_price": 95},
|
| 63 |
+
{"symbol": "XRP", "name": "Ripple", "base_price": 0.52},
|
| 64 |
+
{"symbol": "ADA", "name": "Cardano", "base_price": 0.38},
|
| 65 |
+
{"symbol": "DOGE", "name": "Dogecoin", "base_price": 0.08},
|
| 66 |
+
{"symbol": "MATIC", "name": "Polygon", "base_price": 0.72},
|
| 67 |
+
{"symbol": "DOT", "name": "Polkadot", "base_price": 5.2},
|
| 68 |
+
{"symbol": "AVAX", "name": "Avalanche", "base_price": 23.5}
|
| 69 |
+
]
|
| 70 |
|
| 71 |
+
result = []
|
| 72 |
+
for crypto in cryptos:
|
| 73 |
+
change_24h = random.uniform(-15, 15)
|
| 74 |
+
volume_24h = random.uniform(1000000000, 50000000000)
|
| 75 |
+
market_cap = random.uniform(1000000000, 800000000000)
|
| 76 |
+
|
| 77 |
+
result.append({
|
| 78 |
+
"symbol": crypto["symbol"],
|
| 79 |
+
"name": crypto["name"],
|
| 80 |
+
"price": round(crypto["base_price"] * (1 + random.uniform(-0.05, 0.05)), 2),
|
| 81 |
+
"change_24h": round(change_24h, 2),
|
| 82 |
+
"volume_24h": int(volume_24h),
|
| 83 |
+
"market_cap": int(market_cap),
|
| 84 |
+
"last_updated": datetime.now().isoformat()
|
| 85 |
+
})
|
| 86 |
|
| 87 |
+
return result
|
| 88 |
|
| 89 |
+
def generate_providers_data():
|
| 90 |
+
"""Generate mock provider status data"""
|
| 91 |
+
providers = [
|
| 92 |
+
{"name": "Binance", "type": "Exchange", "status": "operational"},
|
| 93 |
+
{"name": "CoinGecko", "type": "Data Provider", "status": "operational"},
|
| 94 |
+
{"name": "CryptoCompare", "type": "Data Provider", "status": "operational"},
|
| 95 |
+
{"name": "Coinbase", "type": "Exchange", "status": "operational"},
|
| 96 |
+
{"name": "Kraken", "type": "Exchange", "status": "operational"},
|
| 97 |
+
{"name": "Huobi", "type": "Exchange", "status": random.choice(["operational", "degraded"])},
|
| 98 |
+
{"name": "KuCoin", "type": "Exchange", "status": "operational"},
|
| 99 |
+
{"name": "CoinMarketCap", "type": "Data Provider", "status": "operational"}
|
| 100 |
+
]
|
| 101 |
|
| 102 |
+
result = []
|
| 103 |
+
for provider in providers:
|
| 104 |
+
uptime = random.uniform(95, 99.99)
|
| 105 |
+
response_time = random.uniform(50, 300)
|
| 106 |
+
requests_today = random.randint(10000, 500000)
|
| 107 |
+
|
| 108 |
+
result.append({
|
| 109 |
+
"name": provider["name"],
|
| 110 |
+
"type": provider["type"],
|
| 111 |
+
"status": provider["status"],
|
| 112 |
+
"uptime": round(uptime, 2),
|
| 113 |
+
"response_time_ms": int(response_time),
|
| 114 |
+
"requests_today": requests_today,
|
| 115 |
+
"last_check": datetime.now().isoformat(),
|
| 116 |
+
"endpoint": f"https://api.{provider['name'].lower()}.com"
|
| 117 |
+
})
|
| 118 |
|
| 119 |
+
return result
|
| 120 |
|
| 121 |
+
def generate_system_health():
|
| 122 |
+
"""Generate system health data"""
|
| 123 |
+
components = []
|
| 124 |
+
|
| 125 |
+
# API Status
|
| 126 |
+
for i in range(8):
|
| 127 |
+
components.append({
|
| 128 |
+
"name": f"API Server {i+1}",
|
| 129 |
+
"status": random.choice(["healthy"] * 9 + ["degraded"]),
|
| 130 |
+
"uptime": round(random.uniform(95, 99.99), 2),
|
| 131 |
+
"response_time": random.randint(50, 200)
|
| 132 |
+
})
|
| 133 |
+
|
| 134 |
+
# Calculate overall status
|
| 135 |
+
healthy_count = len([c for c in components if c["status"] == "healthy"])
|
| 136 |
+
total_count = len(components)
|
| 137 |
+
|
| 138 |
+
if healthy_count == total_count:
|
| 139 |
+
overall_status = "healthy"
|
| 140 |
+
elif healthy_count >= total_count * 0.7:
|
| 141 |
+
overall_status = "degraded"
|
| 142 |
+
else:
|
| 143 |
+
overall_status = "critical"
|
| 144 |
+
|
| 145 |
+
return {
|
| 146 |
+
"status": overall_status,
|
| 147 |
+
"timestamp": datetime.now().isoformat(),
|
| 148 |
+
"components": components,
|
| 149 |
+
"summary": {
|
| 150 |
+
"total_components": total_count,
|
| 151 |
+
"healthy": healthy_count,
|
| 152 |
+
"degraded": total_count - healthy_count,
|
| 153 |
+
"critical": 0
|
| 154 |
+
}
|
| 155 |
+
}
|
| 156 |
|
| 157 |
+
# API Endpoints
|
| 158 |
@app.get("/")
|
| 159 |
async def root():
|
| 160 |
+
"""Root endpoint"""
|
| 161 |
+
return {
|
| 162 |
+
"name": "Crypto API Monitor",
|
| 163 |
+
"version": "1.0.0",
|
| 164 |
+
"status": "operational",
|
| 165 |
+
"endpoints": {
|
| 166 |
+
"health": "/health",
|
| 167 |
+
"info": "/info",
|
| 168 |
+
"providers": "/api/providers",
|
| 169 |
+
"crypto_prices": "/api/crypto/prices/top",
|
| 170 |
+
"market_overview": "/api/crypto/market-overview",
|
| 171 |
+
"websocket": "/ws/live"
|
| 172 |
+
}
|
| 173 |
+
}
|
| 174 |
|
| 175 |
+
@app.get("/health")
|
| 176 |
+
@app.get("/api/health")
|
| 177 |
+
async def health():
|
| 178 |
+
"""System health status"""
|
| 179 |
+
return generate_system_health()
|
| 180 |
+
|
| 181 |
+
@app.get("/status")
|
| 182 |
+
@app.get("/api/status")
|
| 183 |
+
async def status():
|
| 184 |
+
"""Alias for health endpoint"""
|
| 185 |
+
return await health()
|
| 186 |
+
|
| 187 |
+
@app.get("/info")
|
| 188 |
+
@app.get("/api/info")
|
| 189 |
+
@app.get("/system/info")
|
| 190 |
+
async def system_info():
|
| 191 |
+
"""System information"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
return {
|
| 193 |
+
"name": "Crypto API Monitor",
|
| 194 |
+
"version": "1.0.0",
|
| 195 |
+
"environment": "production",
|
| 196 |
+
"uptime_seconds": random.randint(86400, 2592000),
|
| 197 |
+
"memory_usage_mb": random.randint(200, 800),
|
| 198 |
+
"cpu_usage_percent": round(random.uniform(10, 60), 1),
|
| 199 |
+
"active_connections": len(manager.active_connections),
|
| 200 |
+
"timestamp": datetime.now().isoformat()
|
| 201 |
}
|
| 202 |
|
| 203 |
+
@app.get("/api/providers")
|
| 204 |
+
@app.get("/providers")
|
| 205 |
+
@app.get("/api/sources")
|
| 206 |
+
async def get_providers():
|
| 207 |
+
"""Get all provider statuses"""
|
| 208 |
+
return generate_providers_data()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
|
| 210 |
@app.get("/api/crypto/prices/top")
|
| 211 |
+
async def get_crypto_prices(limit: int = 10):
|
| 212 |
+
"""Get top cryptocurrency prices"""
|
| 213 |
+
prices = generate_crypto_prices()
|
| 214 |
+
return prices[:limit]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
|
| 216 |
+
@app.get("/api/crypto/market-overview")
|
| 217 |
+
async def market_overview():
|
| 218 |
+
"""Get cryptocurrency market overview"""
|
| 219 |
+
prices = generate_crypto_prices()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
+
total_market_cap = sum(p["market_cap"] for p in prices)
|
| 222 |
+
total_volume = sum(p["volume_24h"] for p in prices)
|
| 223 |
+
avg_change = sum(p["change_24h"] for p in prices) / len(prices)
|
| 224 |
|
|
|
|
|
|
|
| 225 |
return {
|
| 226 |
+
"total_market_cap": total_market_cap,
|
| 227 |
+
"total_volume_24h": total_volume,
|
| 228 |
+
"average_change_24h": round(avg_change, 2),
|
| 229 |
+
"top_gainers": sorted(prices, key=lambda x: x["change_24h"], reverse=True)[:3],
|
| 230 |
+
"top_losers": sorted(prices, key=lambda x: x["change_24h"])[:3],
|
| 231 |
"timestamp": datetime.now().isoformat()
|
| 232 |
}
|
| 233 |
|
| 234 |
+
@app.get("/api/categories")
|
| 235 |
+
@app.get("/categories")
|
| 236 |
+
async def get_categories():
|
| 237 |
+
"""Get cryptocurrency categories"""
|
| 238 |
+
categories = [
|
| 239 |
+
{"id": 1, "name": "DeFi", "market_cap": 45000000000, "change_24h": 5.2},
|
| 240 |
+
{"id": 2, "name": "Smart Contract Platform", "market_cap": 120000000000, "change_24h": 3.1},
|
| 241 |
+
{"id": 3, "name": "Exchange Token", "market_cap": 35000000000, "change_24h": -1.5},
|
| 242 |
+
{"id": 4, "name": "Meme Coin", "market_cap": 18000000000, "change_24h": 8.7},
|
| 243 |
+
{"id": 5, "name": "NFT", "market_cap": 12000000000, "change_24h": -2.3}
|
| 244 |
+
]
|
| 245 |
+
return categories
|
| 246 |
+
|
| 247 |
+
@app.get("/api/rate-limits")
|
| 248 |
+
@app.get("/rate-limits")
|
| 249 |
+
async def get_rate_limits():
|
| 250 |
+
"""Get API rate limit information"""
|
| 251 |
+
providers_data = generate_providers_data()
|
| 252 |
+
|
| 253 |
+
rate_limits = []
|
| 254 |
+
for provider in providers_data:
|
| 255 |
+
rate_limits.append({
|
| 256 |
+
"provider": provider["name"],
|
| 257 |
+
"limit_per_minute": random.randint(100, 1000),
|
| 258 |
+
"limit_per_hour": random.randint(5000, 50000),
|
| 259 |
+
"remaining": random.randint(50, 900),
|
| 260 |
+
"reset_time": (datetime.now() + timedelta(seconds=random.randint(10, 3600))).isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
})
|
| 262 |
|
| 263 |
+
return rate_limits
|
| 264 |
|
| 265 |
+
@app.get("/api/logs")
|
| 266 |
+
@app.get("/logs")
|
| 267 |
+
async def get_logs(limit: int = 50):
|
| 268 |
+
"""Get system logs"""
|
| 269 |
+
log_levels = ["INFO", "WARNING", "ERROR", "DEBUG"]
|
| 270 |
+
messages = [
|
| 271 |
+
"API request processed successfully",
|
| 272 |
+
"Provider connection established",
|
| 273 |
+
"Cache updated",
|
| 274 |
+
"Rate limit approaching",
|
| 275 |
+
"WebSocket connection closed",
|
| 276 |
+
"Data sync completed",
|
| 277 |
+
"Health check passed"
|
| 278 |
+
]
|
| 279 |
|
| 280 |
+
logs = []
|
| 281 |
for i in range(limit):
|
| 282 |
+
logs.append({
|
| 283 |
+
"id": i + 1,
|
| 284 |
+
"timestamp": (datetime.now() - timedelta(minutes=random.randint(0, 120))).isoformat(),
|
| 285 |
+
"level": random.choice(log_levels),
|
| 286 |
+
"message": random.choice(messages),
|
| 287 |
+
"provider": random.choice(["Binance", "CoinGecko", "Coinbase", "System"])
|
|
|
|
| 288 |
})
|
| 289 |
|
| 290 |
+
return sorted(logs, key=lambda x: x["timestamp"], reverse=True)
|
|
|
|
| 291 |
|
| 292 |
+
@app.get("/api/alerts")
|
| 293 |
+
@app.get("/alerts")
|
| 294 |
+
async def get_alerts():
|
| 295 |
+
"""Get system alerts"""
|
| 296 |
+
alerts = []
|
| 297 |
+
|
| 298 |
+
# Generate some random alerts
|
| 299 |
+
if random.random() > 0.7:
|
| 300 |
+
alerts.append({
|
| 301 |
+
"id": 1,
|
| 302 |
+
"severity": "warning",
|
| 303 |
+
"title": "High API Usage",
|
| 304 |
+
"message": "API usage is at 85% of limit",
|
| 305 |
+
"timestamp": datetime.now().isoformat()
|
| 306 |
+
})
|
| 307 |
|
| 308 |
+
if random.random() > 0.9:
|
| 309 |
+
alerts.append({
|
| 310 |
+
"id": 2,
|
| 311 |
+
"severity": "error",
|
| 312 |
+
"title": "Provider Degraded",
|
| 313 |
+
"message": "Huobi API response time increased",
|
| 314 |
+
"timestamp": datetime.now().isoformat()
|
| 315 |
+
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
|
| 317 |
+
return alerts
|
|
|
|
| 318 |
|
| 319 |
+
@app.post("/api/hf/refresh")
|
| 320 |
+
@app.post("/hf/refresh")
|
| 321 |
+
async def refresh_hf_data():
|
| 322 |
+
"""Refresh Hugging Face data"""
|
| 323 |
+
return {
|
| 324 |
+
"status": "success",
|
| 325 |
+
"message": "Data refresh initiated",
|
| 326 |
+
"timestamp": datetime.now().isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 327 |
}
|
|
|
|
|
|
|
|
|
|
| 328 |
|
| 329 |
+
@app.get("/api/hf/health")
|
| 330 |
+
@app.get("/hf/health")
|
| 331 |
+
async def hf_health():
|
| 332 |
+
"""Hugging Face integration health"""
|
| 333 |
+
return {
|
| 334 |
+
"status": "operational",
|
| 335 |
+
"models_available": random.randint(5, 15),
|
| 336 |
+
"last_sync": datetime.now().isoformat()
|
| 337 |
+
}
|
| 338 |
|
| 339 |
+
@app.get("/api/hf/registry")
|
| 340 |
+
@app.get("/hf/registry")
|
| 341 |
+
async def hf_registry():
|
| 342 |
+
"""Hugging Face model registry"""
|
| 343 |
+
return {
|
| 344 |
+
"models": [
|
| 345 |
+
{"name": "sentiment-analysis", "status": "active"},
|
| 346 |
+
{"name": "price-prediction", "status": "active"},
|
| 347 |
+
{"name": "market-analysis", "status": "active"}
|
| 348 |
+
]
|
| 349 |
+
}
|
|
|
|
| 350 |
|
| 351 |
+
@app.post("/api/hf/search")
|
| 352 |
+
@app.post("/hf/search")
|
| 353 |
+
async def hf_search(query: dict):
|
| 354 |
+
"""Search Hugging Face models"""
|
| 355 |
+
return {
|
| 356 |
+
"results": [
|
| 357 |
+
{"name": "model-1", "score": 0.95},
|
| 358 |
+
{"name": "model-2", "score": 0.87}
|
| 359 |
+
]
|
| 360 |
+
}
|
|
|
|
|
|
|
| 361 |
|
| 362 |
+
@app.post("/api/hf/run-sentiment")
|
| 363 |
+
@app.post("/hf/sentiment")
|
| 364 |
+
async def run_sentiment_analysis(data: dict):
|
| 365 |
+
"""Run sentiment analysis"""
|
| 366 |
+
sentiment = random.choice(["positive", "negative", "neutral"])
|
| 367 |
+
score = random.uniform(0.6, 0.99)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 369 |
return {
|
| 370 |
+
"sentiment": sentiment,
|
| 371 |
+
"score": round(score, 2),
|
| 372 |
+
"timestamp": datetime.now().isoformat()
|
| 373 |
}
|
| 374 |
|
| 375 |
+
# WebSocket endpoint
|
| 376 |
+
@app.websocket("/ws/live")
|
| 377 |
+
@app.websocket("/ws")
|
| 378 |
+
async def websocket_endpoint(websocket: WebSocket):
|
| 379 |
+
"""WebSocket endpoint for real-time updates"""
|
| 380 |
+
await manager.connect(websocket)
|
| 381 |
+
|
| 382 |
+
try:
|
| 383 |
+
# Send initial data
|
| 384 |
+
await websocket.send_json({
|
| 385 |
+
"type": "connection_established",
|
| 386 |
+
"timestamp": datetime.now().isoformat()
|
| 387 |
+
})
|
| 388 |
+
|
| 389 |
+
# Keep connection alive and send periodic updates
|
| 390 |
+
while True:
|
| 391 |
+
# Send status update every 5 seconds
|
| 392 |
+
await asyncio.sleep(5)
|
| 393 |
+
|
| 394 |
+
health_data = generate_system_health()
|
| 395 |
+
await websocket.send_json({
|
| 396 |
+
"type": "status_update",
|
| 397 |
+
"data": health_data,
|
| 398 |
+
"timestamp": datetime.now().isoformat()
|
| 399 |
+
})
|
| 400 |
+
|
| 401 |
+
# Occasionally send provider status change
|
| 402 |
+
if random.random() > 0.8:
|
| 403 |
+
await websocket.send_json({
|
| 404 |
+
"type": "provider_status_change",
|
| 405 |
+
"data": {
|
| 406 |
+
"provider": random.choice(["Binance", "CoinGecko", "Coinbase"]),
|
| 407 |
+
"status": "operational"
|
| 408 |
+
},
|
| 409 |
+
"timestamp": datetime.now().isoformat()
|
| 410 |
+
})
|
| 411 |
+
|
| 412 |
+
# Occasionally send alerts
|
| 413 |
+
if random.random() > 0.9:
|
| 414 |
+
await websocket.send_json({
|
| 415 |
+
"type": "new_alert",
|
| 416 |
+
"data": {
|
| 417 |
+
"severity": "info",
|
| 418 |
+
"title": "System Update",
|
| 419 |
+
"message": "Cache refreshed successfully"
|
| 420 |
+
},
|
| 421 |
+
"timestamp": datetime.now().isoformat()
|
| 422 |
+
})
|
| 423 |
+
|
| 424 |
+
except WebSocketDisconnect:
|
| 425 |
+
manager.disconnect(websocket)
|
| 426 |
+
except Exception as e:
|
| 427 |
+
print(f"WebSocket error: {e}")
|
| 428 |
+
manager.disconnect(websocket)
|
| 429 |
+
|
| 430 |
+
# Serve static files (HTML)
|
| 431 |
+
@app.get("/dashboard", response_class=HTMLResponse)
|
| 432 |
+
async def get_dashboard():
|
| 433 |
+
"""Serve the dashboard HTML"""
|
| 434 |
+
try:
|
| 435 |
+
with open("index.html", "r", encoding="utf-8") as f:
|
| 436 |
+
return HTMLResponse(content=f.read())
|
| 437 |
+
except FileNotFoundError:
|
| 438 |
+
return HTMLResponse(content="<h1>Dashboard not found</h1>", status_code=404)
|
| 439 |
|
| 440 |
if __name__ == "__main__":
|
| 441 |
+
print("🚀 Starting Crypto API Monitor...")
|
| 442 |
+
print("📊 Dashboard: http://localhost:8000/dashboard")
|
| 443 |
+
print("📡 API Docs: http://localhost:8000/docs")
|
| 444 |
+
|
| 445 |
+
uvicorn.run(
|
| 446 |
+
"app:app",
|
| 447 |
+
host="0.0.0.0",
|
| 448 |
+
port=8000,
|
| 449 |
+
reload=True,
|
| 450 |
+
log_level="info"
|
| 451 |
+
)
|
requirements.txt
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
fastapi==0.104.1
|
| 2 |
uvicorn[standard]==0.24.0
|
| 3 |
-
|
| 4 |
-
python-
|
|
|
|
|
|
| 1 |
fastapi==0.104.1
|
| 2 |
uvicorn[standard]==0.24.0
|
| 3 |
+
websockets==12.0
|
| 4 |
+
python-multipart==0.0.6
|
| 5 |
+
pydantic==2.5.0
|
start.bat
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@echo off
|
| 2 |
+
chcp 65001 > nul
|
| 3 |
+
title Crypto API Monitor - Starting...
|
| 4 |
+
|
| 5 |
+
echo ========================================
|
| 6 |
+
echo 🚀 Crypto API Monitor
|
| 7 |
+
echo Real-time Cryptocurrency Dashboard
|
| 8 |
+
echo ========================================
|
| 9 |
+
echo.
|
| 10 |
+
|
| 11 |
+
REM Check if Python is installed
|
| 12 |
+
python --version > nul 2>&1
|
| 13 |
+
if %errorlevel% neq 0 (
|
| 14 |
+
echo ❌ Python is not installed or not in PATH
|
| 15 |
+
echo.
|
| 16 |
+
echo Please install Python 3.8 or higher from:
|
| 17 |
+
echo https://www.python.org/downloads/
|
| 18 |
+
echo.
|
| 19 |
+
echo Make sure to check "Add Python to PATH" during installation
|
| 20 |
+
pause
|
| 21 |
+
exit /b 1
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
echo ✅ Python is installed
|
| 25 |
+
echo.
|
| 26 |
+
|
| 27 |
+
REM Check if virtual environment exists
|
| 28 |
+
if not exist "venv" (
|
| 29 |
+
echo 📦 Creating virtual environment...
|
| 30 |
+
python -m venv venv
|
| 31 |
+
if %errorlevel% neq 0 (
|
| 32 |
+
echo ❌ Failed to create virtual environment
|
| 33 |
+
pause
|
| 34 |
+
exit /b 1
|
| 35 |
+
)
|
| 36 |
+
echo ✅ Virtual environment created
|
| 37 |
+
echo.
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
REM Activate virtual environment
|
| 41 |
+
echo 🔧 Activating virtual environment...
|
| 42 |
+
call venv\Scripts\activate.bat
|
| 43 |
+
if %errorlevel% neq 0 (
|
| 44 |
+
echo ❌ Failed to activate virtual environment
|
| 45 |
+
pause
|
| 46 |
+
exit /b 1
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
echo ✅ Virtual environment activated
|
| 50 |
+
echo.
|
| 51 |
+
|
| 52 |
+
REM Install/Update dependencies
|
| 53 |
+
echo 📥 Installing dependencies...
|
| 54 |
+
pip install -q -r requirements.txt
|
| 55 |
+
if %errorlevel% neq 0 (
|
| 56 |
+
echo ❌ Failed to install dependencies
|
| 57 |
+
pause
|
| 58 |
+
exit /b 1
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
echo ✅ Dependencies installed
|
| 62 |
+
echo.
|
| 63 |
+
echo ========================================
|
| 64 |
+
echo 🎯 Starting Server...
|
| 65 |
+
echo ========================================
|
| 66 |
+
echo.
|
| 67 |
+
echo 📊 Dashboard will be available at:
|
| 68 |
+
echo http://localhost:8000/dashboard
|
| 69 |
+
echo.
|
| 70 |
+
echo 📡 API Documentation:
|
| 71 |
+
echo http://localhost:8000/docs
|
| 72 |
+
echo.
|
| 73 |
+
echo 💡 Press Ctrl+C to stop the server
|
| 74 |
+
echo.
|
| 75 |
+
echo ========================================
|
| 76 |
+
echo.
|
| 77 |
+
|
| 78 |
+
REM Start the application
|
| 79 |
+
python app.py
|
| 80 |
+
|
| 81 |
+
pause
|
start.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Startup script for Crypto API Monitor
|
| 4 |
+
راهاندازی خودکار Crypto API Monitor
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import sys
|
| 8 |
+
import subprocess
|
| 9 |
+
import os
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
|
| 12 |
+
def print_banner():
|
| 13 |
+
"""نمایش بنر شروع"""
|
| 14 |
+
print("=" * 50)
|
| 15 |
+
print(" 🚀 Crypto API Monitor")
|
| 16 |
+
print(" Real-time Cryptocurrency Dashboard")
|
| 17 |
+
print("=" * 50)
|
| 18 |
+
print()
|
| 19 |
+
|
| 20 |
+
def check_python_version():
|
| 21 |
+
"""بررسی نسخه Python"""
|
| 22 |
+
if sys.version_info < (3, 8):
|
| 23 |
+
print("❌ Python 3.8 or higher is required")
|
| 24 |
+
print(f" Current version: {sys.version}")
|
| 25 |
+
return False
|
| 26 |
+
print(f"✅ Python {sys.version_info.major}.{sys.version_info.minor} detected")
|
| 27 |
+
return True
|
| 28 |
+
|
| 29 |
+
def create_venv():
|
| 30 |
+
"""ایجاد محیط مجازی"""
|
| 31 |
+
if os.path.exists("venv"):
|
| 32 |
+
print("✅ Virtual environment already exists")
|
| 33 |
+
return True
|
| 34 |
+
|
| 35 |
+
print("📦 Creating virtual environment...")
|
| 36 |
+
try:
|
| 37 |
+
subprocess.run([sys.executable, "-m", "venv", "venv"], check=True)
|
| 38 |
+
print("✅ Virtual environment created")
|
| 39 |
+
return True
|
| 40 |
+
except subprocess.CalledProcessError:
|
| 41 |
+
print("❌ Failed to create virtual environment")
|
| 42 |
+
return False
|
| 43 |
+
|
| 44 |
+
def get_python_executable():
|
| 45 |
+
"""دریافت مسیر Python در محیط مجازی"""
|
| 46 |
+
if sys.platform == "win32":
|
| 47 |
+
return os.path.join("venv", "Scripts", "python.exe")
|
| 48 |
+
else:
|
| 49 |
+
return os.path.join("venv", "bin", "python")
|
| 50 |
+
|
| 51 |
+
def install_requirements():
|
| 52 |
+
"""نصب پکیجهای مورد نیاز"""
|
| 53 |
+
print("📥 Installing dependencies...")
|
| 54 |
+
python_exe = get_python_executable()
|
| 55 |
+
|
| 56 |
+
try:
|
| 57 |
+
subprocess.run(
|
| 58 |
+
[python_exe, "-m", "pip", "install", "--upgrade", "pip"],
|
| 59 |
+
check=True,
|
| 60 |
+
stdout=subprocess.DEVNULL
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
subprocess.run(
|
| 64 |
+
[python_exe, "-m", "pip", "install", "-r", "requirements.txt"],
|
| 65 |
+
check=True
|
| 66 |
+
)
|
| 67 |
+
print("✅ Dependencies installed")
|
| 68 |
+
return True
|
| 69 |
+
except subprocess.CalledProcessError:
|
| 70 |
+
print("❌ Failed to install dependencies")
|
| 71 |
+
return False
|
| 72 |
+
|
| 73 |
+
def start_server():
|
| 74 |
+
"""راهاندازی سرور"""
|
| 75 |
+
print()
|
| 76 |
+
print("=" * 50)
|
| 77 |
+
print(" 🎯 Starting Server...")
|
| 78 |
+
print("=" * 50)
|
| 79 |
+
print()
|
| 80 |
+
print("📊 Dashboard: http://localhost:8000/dashboard")
|
| 81 |
+
print("📡 API Docs: http://localhost:8000/docs")
|
| 82 |
+
print()
|
| 83 |
+
print("💡 Press Ctrl+C to stop the server")
|
| 84 |
+
print()
|
| 85 |
+
print("=" * 50)
|
| 86 |
+
print()
|
| 87 |
+
|
| 88 |
+
python_exe = get_python_executable()
|
| 89 |
+
|
| 90 |
+
try:
|
| 91 |
+
subprocess.run([python_exe, "app.py"], check=True)
|
| 92 |
+
except KeyboardInterrupt:
|
| 93 |
+
print("\n\n✋ Server stopped by user")
|
| 94 |
+
except subprocess.CalledProcessError as e:
|
| 95 |
+
print(f"\n❌ Server error: {e}")
|
| 96 |
+
|
| 97 |
+
def main():
|
| 98 |
+
"""تابع اصلی"""
|
| 99 |
+
print_banner()
|
| 100 |
+
|
| 101 |
+
# بررسی نسخه Python
|
| 102 |
+
if not check_python_version():
|
| 103 |
+
input("\nPress Enter to exit...")
|
| 104 |
+
sys.exit(1)
|
| 105 |
+
|
| 106 |
+
print()
|
| 107 |
+
|
| 108 |
+
# ایجاد محیط مجازی
|
| 109 |
+
if not create_venv():
|
| 110 |
+
input("\nPress Enter to exit...")
|
| 111 |
+
sys.exit(1)
|
| 112 |
+
|
| 113 |
+
# نصب پکیجها
|
| 114 |
+
if not install_requirements():
|
| 115 |
+
input("\nPress Enter to exit...")
|
| 116 |
+
sys.exit(1)
|
| 117 |
+
|
| 118 |
+
# راهاندازی سرور
|
| 119 |
+
start_server()
|
| 120 |
+
|
| 121 |
+
if __name__ == "__main__":
|
| 122 |
+
try:
|
| 123 |
+
main()
|
| 124 |
+
except Exception as e:
|
| 125 |
+
print(f"\n❌ Unexpected error: {e}")
|
| 126 |
+
input("\nPress Enter to exit...")
|
| 127 |
+
sys.exit(1)
|