Align with Twelve Data API docs and add Telegram command menu
data_provider: - Switch to Authorization header (recommended over apikey query param) - Enforce 800 credits/day daily limit with warning at 80% - Fall back to synthetic data when daily limit is reached - Fix null OHLC field handling (API can return null for any field) telegram_bot: - Register commands with set_my_commands so Telegram shows / menu - Add /credits command to show daily API credit usage and limits Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+41
-1
@@ -27,7 +27,7 @@ from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime, timezone
|
||||
from typing import Dict, Optional
|
||||
|
||||
from telegram import Update
|
||||
from telegram import BotCommand, Update
|
||||
from telegram.constants import ParseMode
|
||||
from telegram.ext import Application, CallbackContext, CommandHandler, ContextTypes
|
||||
|
||||
@@ -514,6 +514,29 @@ class ForexTelegramBot:
|
||||
job.schedule_removal()
|
||||
await update.message.reply_text("❌ Watch alerts disabled.")
|
||||
|
||||
async def cmd_credits(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
"""Show API credit usage against the free-tier daily limit."""
|
||||
from data_provider import ForexDataProvider
|
||||
config = self._build_config(self._state(update.effective_chat.id))
|
||||
provider = ForexDataProvider(config)
|
||||
used = provider._daily_credits
|
||||
limit = provider.DAILY_LIMIT
|
||||
remaining = limit - used
|
||||
pct = (used / limit) * 100 if limit else 0
|
||||
bar_filled = int(pct / 5)
|
||||
bar = "█" * bar_filled + "░" * (20 - bar_filled)
|
||||
status = "🟢" if pct < 60 else ("🟡" if pct < 80 else "🔴")
|
||||
text = (
|
||||
"<b>📊 API Credit Usage</b>\n\n"
|
||||
f"<code>{bar}</code> {status}\n"
|
||||
f"<b>Used:</b> {used} / {limit} credits\n"
|
||||
f"<b>Remaining:</b> {remaining} credits\n\n"
|
||||
"<i>Free tier: 8 credits/min, 800 credits/day\n"
|
||||
"Each full scan uses ~21 credits (7 pairs × 3 timeframes)\n"
|
||||
"≈ 38 scans available per day</i>"
|
||||
)
|
||||
await update.message.reply_text(text, parse_mode=ParseMode.HTML)
|
||||
|
||||
# ── Watch job ──────────────────────────────────────────────────
|
||||
|
||||
async def _watch_job(self, context: CallbackContext):
|
||||
@@ -548,9 +571,25 @@ class ForexTelegramBot:
|
||||
" export TELEGRAM_BOT_TOKEN='your_token_here'"
|
||||
)
|
||||
|
||||
async def _register_commands(app: Application) -> None:
|
||||
"""Register commands with Telegram so they appear in the / menu."""
|
||||
await app.bot.set_my_commands([
|
||||
BotCommand("scan", "Scan all major pairs"),
|
||||
BotCommand("signals", "Actionable signals only (grade B+)"),
|
||||
BotCommand("pair", "Detailed pair analysis — /pair EURUSD"),
|
||||
BotCommand("all", "Scan major + cross pairs"),
|
||||
BotCommand("tf", "Set timeframe — /tf H4"),
|
||||
BotCommand("watch", "Enable periodic alerts"),
|
||||
BotCommand("unwatch", "Disable alerts"),
|
||||
BotCommand("credits", "View API credit usage"),
|
||||
BotCommand("status", "View current settings"),
|
||||
BotCommand("help", "Full command reference"),
|
||||
])
|
||||
|
||||
app = (
|
||||
Application.builder()
|
||||
.token(token)
|
||||
.post_init(_register_commands)
|
||||
.build()
|
||||
)
|
||||
|
||||
@@ -564,6 +603,7 @@ class ForexTelegramBot:
|
||||
app.add_handler(CommandHandler("all", self.cmd_all))
|
||||
app.add_handler(CommandHandler("watch", self.cmd_watch))
|
||||
app.add_handler(CommandHandler("unwatch", self.cmd_unwatch))
|
||||
app.add_handler(CommandHandler("credits", self.cmd_credits))
|
||||
|
||||
return app
|
||||
|
||||
|
||||
Reference in New Issue
Block a user