|
|
from fastapi import APIRouter, Query
|
|
|
from typing import Optional, Dict, Any
|
|
|
from backend.services.telegram_notification_service import TelegramNotificationService
|
|
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
|
|
|
telegram_service = TelegramNotificationService()
|
|
|
|
|
|
|
|
|
@router.get("/api/settings/telegram")
|
|
|
async def get_telegram_settings():
|
|
|
"""
|
|
|
Get Telegram settings with masked token.
|
|
|
|
|
|
Returns:
|
|
|
- enabled: bool
|
|
|
- mask_token: str (only last 4 chars visible)
|
|
|
- chat_id: str
|
|
|
- thresholds: dict
|
|
|
- toggles: dict
|
|
|
- last_test_at: ISO datetime or None
|
|
|
- last_delivery_at: ISO datetime or None
|
|
|
"""
|
|
|
return telegram_service.get_masked_settings()
|
|
|
|
|
|
|
|
|
@router.post("/api/settings/telegram")
|
|
|
async def save_telegram_settings(settings: Dict[str, Any]):
|
|
|
"""
|
|
|
Save Telegram settings securely.
|
|
|
|
|
|
Body:
|
|
|
{
|
|
|
"token": "bot_token",
|
|
|
"chat_id": "chat_id",
|
|
|
"enabled": true/false,
|
|
|
"thresholds": {
|
|
|
"signal_score": 0.7,
|
|
|
"whale_amount_usd": 250000
|
|
|
},
|
|
|
"toggles": {
|
|
|
"trading_signal": true,
|
|
|
"whale_transfer": true,
|
|
|
"provider_offline": true,
|
|
|
"news_negative": true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Returns:
|
|
|
{ "ok": true/false }
|
|
|
"""
|
|
|
|
|
|
if 'token' not in settings or 'chat_id' not in settings:
|
|
|
return {'ok': False, 'detail': 'Missing token or chat_id'}
|
|
|
|
|
|
|
|
|
current = telegram_service.load_settings()
|
|
|
|
|
|
|
|
|
updated_settings = {
|
|
|
'token': settings.get('token'),
|
|
|
'chat_id': settings.get('chat_id'),
|
|
|
'enabled': settings.get('enabled', True),
|
|
|
'thresholds': settings.get('thresholds', {
|
|
|
'signal_score': 0.7,
|
|
|
'whale_amount_usd': 250000
|
|
|
}),
|
|
|
'toggles': settings.get('toggles', {
|
|
|
'trading_signal': True,
|
|
|
'whale_transfer': True,
|
|
|
'provider_offline': True,
|
|
|
'news_negative': True
|
|
|
}),
|
|
|
'last_test_at': current.get('last_test_at'),
|
|
|
'last_delivery_at': current.get('last_delivery_at')
|
|
|
}
|
|
|
|
|
|
|
|
|
success = telegram_service.save_settings(updated_settings)
|
|
|
|
|
|
return {'ok': success}
|
|
|
|
|
|
|
|
|
@router.post("/api/settings/telegram/test")
|
|
|
async def test_telegram_notification():
|
|
|
"""
|
|
|
Send a test message to verify Telegram configuration.
|
|
|
|
|
|
Returns:
|
|
|
{
|
|
|
"ok": true/false,
|
|
|
"detail": "success or error message"
|
|
|
}
|
|
|
"""
|
|
|
result = telegram_service.send_test_message()
|
|
|
return result
|
|
|
|
|
|
|
|
|
@router.get("/api/logs/recent")
|
|
|
async def get_recent_logs(limit: int = Query(default=50, ge=1, le=500)):
|
|
|
"""
|
|
|
Get recent log events from events.jsonl
|
|
|
|
|
|
Args:
|
|
|
limit: Number of recent events to return
|
|
|
|
|
|
Returns:
|
|
|
List of log event objects
|
|
|
"""
|
|
|
events = telegram_service.get_recent_logs(limit)
|
|
|
return {
|
|
|
'count': len(events),
|
|
|
'events': events
|
|
|
}
|
|
|
|
|
|
|
|
|
@router.post("/api/notifications/signal")
|
|
|
async def send_signal_notification(signal: Dict[str, Any]):
|
|
|
"""
|
|
|
Send trading signal notification.
|
|
|
|
|
|
Body example:
|
|
|
{
|
|
|
"symbol": "BTC",
|
|
|
"score": 0.85,
|
|
|
"timeframe": "1h",
|
|
|
"entry_price": 87500,
|
|
|
"stop_loss": 86000,
|
|
|
"take_profit": 90000
|
|
|
}
|
|
|
"""
|
|
|
success = telegram_service.notify_trading_signal(signal)
|
|
|
return {'ok': success}
|
|
|
|
|
|
|
|
|
@router.post("/api/notifications/whale")
|
|
|
async def send_whale_notification(transfer: Dict[str, Any]):
|
|
|
"""
|
|
|
Send whale transfer notification.
|
|
|
|
|
|
Body example:
|
|
|
{
|
|
|
"token_symbol": "ETH",
|
|
|
"amount_usd": 5000000,
|
|
|
"from_address": "0xabc...",
|
|
|
"to_address": "0xdef...",
|
|
|
"txid": "0x123..."
|
|
|
}
|
|
|
"""
|
|
|
success = telegram_service.notify_whale_transfer(transfer)
|
|
|
return {'ok': success}
|
|
|
|
|
|
|
|
|
@router.post("/api/notifications/provider")
|
|
|
async def send_provider_notification(data: Dict[str, Any]):
|
|
|
"""
|
|
|
Send provider offline notification.
|
|
|
|
|
|
Body example:
|
|
|
{
|
|
|
"provider": "binance",
|
|
|
"last_good": "2025-11-26T10:30:00Z"
|
|
|
}
|
|
|
"""
|
|
|
provider = data.get('provider', 'unknown')
|
|
|
last_good = data.get('last_good', 'unknown')
|
|
|
success = telegram_service.notify_provider_offline(provider, last_good)
|
|
|
return {'ok': success}
|
|
|
|
|
|
|
|
|
@router.post("/api/notifications/news")
|
|
|
async def send_news_notification(news: Dict[str, Any]):
|
|
|
"""
|
|
|
Send negative news notification.
|
|
|
|
|
|
Body example:
|
|
|
{
|
|
|
"title": "Bitcoin crashes",
|
|
|
"summary": "Market sees significant downturn...",
|
|
|
"url": "https://...",
|
|
|
"published_at": "2025-11-26T10:00:00Z",
|
|
|
"sentiment_label": "negative"
|
|
|
}
|
|
|
"""
|
|
|
success = telegram_service.notify_news_negative(news)
|
|
|
return {'ok': success}
|
|
|
|