diff --git a/worker/src/bot.py b/worker/src/bot.py
index e65f1ef..9d9b6fa 100644
--- a/worker/src/bot.py
+++ b/worker/src/bot.py
@@ -33,9 +33,9 @@ def _vienna_time(dt: datetime | None, fmt: str = "%d.%m.%Y %H:%M") -> str:
return dt.astimezone(VIENNA_TZ).strftime(fmt)
-def _safe_id(kw_id: str) -> str:
+def _safe_id(kw_id: Any) -> str:
"""Return a short, safe version of the UUID for Telegram callback_data."""
- return kw_id[:28] # well within 64-char limit with prefixes
+ return str(kw_id)[:28] # handles asyncpg.UUID objects
def _b64(text: str) -> str:
@@ -472,7 +472,12 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
if sub == "add":
context.user_data["state"] = "awaiting_keyword"
await query.edit_message_text(
- "Send me a search keyword (e.g. rtx 3090)", parse_mode="HTML")
+ "Send me a search keyword (e.g. rtx 3090)",
+ parse_mode="HTML",
+ reply_markup=InlineKeyboardMarkup([
+ [InlineKeyboardButton("❌ Cancel", callback_data="cancel:menu")],
+ ]),
+ )
elif sub == "list":
subs = await pool.fetch(
@@ -519,6 +524,18 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
)
await query.edit_message_text(text=text, parse_mode="HTML")
+ # ════════════════════════════════════════════════════════════════════
+ # CANCEL / BACK
+ # ════════════════════════════════════════════════════════════════════
+
+ elif action == "cancel":
+ context.user_data.clear()
+ kb = _main_menu_keyboard()
+ try:
+ await query.edit_message_text("Cancelled.", reply_markup=kb, parse_mode="HTML")
+ except Exception:
+ await context.bot.send_message(chat_id=chat_id or user["telegram_id"], text="Cancelled.", reply_markup=kb)
+
# ════════════════════════════════════════════════════════════════════
# ADD KEYWORD FLOW
# ════════════════════════════════════════════════════════════════════