fix(telegram): /status shows auto_trade+paper_mode, adopt:dup edits message
Bug 1: /status didn't show auto_trade or paper_mode — the two most important trading states for Pro users. Added a trading block that queries the Subscription row (only when wallet-linked) and shows: Auto-Trade: ON/OFF, Mode: Paper/Live, Circuit breaker: clear/tripped. Bug 2: adopt:dup callback (tapping an 'already managed' position in the /adopt picker) answered the spinner but left the picker message stuck with no guidance. Now edits the message in place: explains the position is already managed and shows /release commands. Button no longer results in a visually broken UI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -393,6 +393,15 @@ async def _cmd_status(chat_id: int) -> None:
|
|||||||
b = (await db.execute(
|
b = (await db.execute(
|
||||||
select(TelegramBinding).where(TelegramBinding.chat_id == chat_id)
|
select(TelegramBinding).where(TelegramBinding.chat_id == chat_id)
|
||||||
)).scalar_one_or_none()
|
)).scalar_one_or_none()
|
||||||
|
# Also fetch the subscription if the binding is wallet-linked, so we
|
||||||
|
# can show auto_trade + paper_mode — the two most important trading
|
||||||
|
# states that were previously invisible in /status.
|
||||||
|
sub = None
|
||||||
|
if b and b.wallet_address:
|
||||||
|
sub = (await db.execute(
|
||||||
|
select(Subscription).where(Subscription.wallet_address == b.wallet_address)
|
||||||
|
)).scalar_one_or_none()
|
||||||
|
|
||||||
if not b:
|
if not b:
|
||||||
await send_message(chat_id,
|
await send_message(chat_id,
|
||||||
"Not subscribed yet. Send /start to begin (no wallet required).")
|
"Not subscribed yet. Send /start to begin (no wallet required).")
|
||||||
@@ -418,6 +427,23 @@ async def _cmd_status(chat_id: int) -> None:
|
|||||||
f"🟢 ON @ {b.digest_hour_utc:02d}:00 UTC"
|
f"🟢 ON @ {b.digest_hour_utc:02d}:00 UTC"
|
||||||
if b.digest_enabled else "🔴 OFF"
|
if b.digest_enabled else "🔴 OFF"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Pro-only trading state block — only shown when wallet-linked.
|
||||||
|
trading_block = ""
|
||||||
|
if sub:
|
||||||
|
auto = "🟢 ON" if sub.auto_trade else "🔴 OFF"
|
||||||
|
mode = "📝 Paper" if sub.paper_mode else "💰 Live"
|
||||||
|
cb_line = ""
|
||||||
|
if sub.circuit_breaker_tripped_at:
|
||||||
|
cb_line = f"\n🚨 Circuit breaker: tripped ({sub.circuit_breaker_reason or 'risk limit'})"
|
||||||
|
else:
|
||||||
|
cb_line = "\n✓ Circuit breaker: clear"
|
||||||
|
trading_block = (
|
||||||
|
f"\n\n<b>— Auto-Trader —</b>\n"
|
||||||
|
f"Auto-Trade: {auto}\n"
|
||||||
|
f"Mode: {mode}{cb_line}"
|
||||||
|
)
|
||||||
|
|
||||||
await send_message(
|
await send_message(
|
||||||
chat_id,
|
chat_id,
|
||||||
f"📡 <b>Status</b>\n\n"
|
f"📡 <b>Status</b>\n\n"
|
||||||
@@ -425,7 +451,8 @@ async def _cmd_status(chat_id: int) -> None:
|
|||||||
f"Alerts: {on}\n"
|
f"Alerts: {on}\n"
|
||||||
f"Sources: {src_line}\n"
|
f"Sources: {src_line}\n"
|
||||||
f"Min confidence: {b.min_confidence}{mute}\n"
|
f"Min confidence: {b.min_confidence}{mute}\n"
|
||||||
f"Daily brief: {digest_state}\n\n"
|
f"Daily brief: {digest_state}"
|
||||||
|
f"{trading_block}\n\n"
|
||||||
f"Sent: {b.total_alerts_sent} · Failed: {b.total_alerts_failed}\n\n"
|
f"Sent: {b.total_alerts_sent} · Failed: {b.total_alerts_failed}\n\n"
|
||||||
f"Toggle anything with /trump /btc /funding /kol /conf /quiet "
|
f"Toggle anything with /trump /btc /funding /kol /conf /quiet "
|
||||||
f"/digest /digest_time — send /help for the full list.",
|
f"/digest /digest_time — send /help for the full list.",
|
||||||
@@ -787,9 +814,17 @@ async def _handle_callback(cb: dict) -> None:
|
|||||||
await answer_callback(cb_id)
|
await answer_callback(cb_id)
|
||||||
return
|
return
|
||||||
if sub == "dup":
|
if sub == "dup":
|
||||||
await answer_callback(cb_id,
|
# Asset is already adopted — tell the user how to release,
|
||||||
"This position is already managed.",
|
# and also edit the picker message so the UI doesn't stay stuck.
|
||||||
show_alert=True)
|
asset_dup = parts[2] if len(parts) > 2 else "this position"
|
||||||
|
await edit_message(
|
||||||
|
chat_id, msg_id,
|
||||||
|
f"✅ <b>{asset_dup}</b> is already under bot management.\n\n"
|
||||||
|
f"To stop managing it and take back manual control:\n"
|
||||||
|
f"<code>/release</code> — pick from list\n"
|
||||||
|
f"or send <code>/release <trade_id></code> directly."
|
||||||
|
)
|
||||||
|
await answer_callback(cb_id, "Already managed — see message.", show_alert=False)
|
||||||
return
|
return
|
||||||
if sub == "pick" and len(parts) == 3:
|
if sub == "pick" and len(parts) == 3:
|
||||||
asset = parts[2]
|
asset = parts[2]
|
||||||
|
|||||||
Reference in New Issue
Block a user