fix: summary message, stats back, admin cancel/back buttons, keyword added confirmation, notifications logging
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Agent Instructions
|
||||
|
||||
## Standard Practice
|
||||
- **Always use subagents** (`Task` tool) to implement code changes unless explicitly told otherwise by the user. This optimizes token usage and enables parallel work.
|
||||
- Each subagent should handle a single, well-scoped task with clear acceptance criteria.
|
||||
- After subagents complete, verify syntax, commit, and deploy.
|
||||
|
||||
## Deployment Pattern
|
||||
```bash
|
||||
ssh tizona "cd /mnt/user/appdata/willhaben-tracker && docker compose down worker && git pull origin main && docker compose build worker --no-cache && docker compose up -d"
|
||||
```
|
||||
|
||||
## Key Context
|
||||
- Bot token: `8653489932:AAG_Ins2_z3sNHX8ZlGI4mhyzmUhWAWCZlg` (in `.env`)
|
||||
- Admin TG ID: `298181113`
|
||||
- PTB v21, asyncpg with Postgres 15
|
||||
+46
-11
@@ -180,7 +180,6 @@ def _admin_menu_keyboard() -> InlineKeyboardMarkup:
|
||||
[InlineKeyboardButton("➕ Add User", callback_data="admin_add"),
|
||||
InlineKeyboardButton("👥 List Users", callback_data="admin_list")],
|
||||
[InlineKeyboardButton("🗑 Remove User", callback_data="admin_remove")],
|
||||
[InlineKeyboardButton("↩ Back", callback_data="menu:")],
|
||||
])
|
||||
|
||||
|
||||
@@ -384,6 +383,8 @@ async def text_input_handler(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
||||
|
||||
context.user_data.clear()
|
||||
logger.info("Admin added user %d", tg_id)
|
||||
await update.message.reply_text( # type: ignore[union-attr]
|
||||
"<b>⚙️ Admin Panel</b>", parse_mode="HTML", reply_markup=_admin_menu_keyboard())
|
||||
|
||||
# ── admin: awaiting TG ID to remove user ──────────────────────────
|
||||
elif state == "admin_awaiting_tg_id_remove":
|
||||
@@ -428,6 +429,8 @@ async def text_input_handler(update: Update, context: ContextTypes.DEFAULT_TYPE)
|
||||
|
||||
context.user_data.clear()
|
||||
logger.info("Admin removed user %d", tg_id)
|
||||
await update.message.reply_text( # type: ignore[union-attr]
|
||||
"<b>⚙️ Admin Panel</b>", parse_mode="HTML", reply_markup=_admin_menu_keyboard())
|
||||
|
||||
|
||||
# ── callback router (handles ALL inline button clicks) ────────────────────
|
||||
@@ -507,12 +510,16 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
)
|
||||
|
||||
name = user["first_name"] or "there"
|
||||
await context.bot.send_message(
|
||||
chat_id=chat_id,
|
||||
text=f"<b>That was all your listings, {name}!</b>\n\nAnything else I can help with?",
|
||||
parse_mode="HTML",
|
||||
reply_markup=_main_menu_keyboard(),
|
||||
)
|
||||
summary_chat_id = update.effective_chat.id # type: ignore[union-attr]
|
||||
try:
|
||||
await context.bot.send_message(
|
||||
chat_id=summary_chat_id,
|
||||
text=f"<b>That was all your listings, {name}!</b>\n\nAnything else I can help with?",
|
||||
parse_mode="HTML",
|
||||
reply_markup=_main_menu_keyboard(),
|
||||
)
|
||||
except Exception:
|
||||
logger.exception("Failed to send summary message for user %s", user["id"])
|
||||
|
||||
elif sub == "stats":
|
||||
total_kw = await pool.fetchval(
|
||||
@@ -529,7 +536,12 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
f"Ads indexed: <code>{total_ads}</code>\n"
|
||||
f"Notifications sent: <code>{total_notifs}</code>"
|
||||
)
|
||||
await query.edit_message_text(text=text, parse_mode="HTML")
|
||||
await query.edit_message_text(
|
||||
text=text, parse_mode="HTML",
|
||||
reply_markup=InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("↩ Back", callback_data="back:admin")],
|
||||
]),
|
||||
)
|
||||
|
||||
else:
|
||||
# Empty payload — "Back" button from sub-menus, show main menu
|
||||
@@ -601,7 +613,10 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
|
||||
await _edit_or_send(
|
||||
context.bot, chat_id, msg_id, # type: ignore[arg-type]
|
||||
f'<b>✅ Keyword added!</b>\n\n<blockquote>"{keyword_text}"</blockquote>{extra}',
|
||||
f'<b>✅ Keyword added!</b>\n\n"{keyword_text}"{extra}',
|
||||
reply_markup=InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("↩ Back", callback_data="menu:")],
|
||||
]),
|
||||
)
|
||||
logger.info("User %s subscribed to '%s'", update.effective_user.id, keyword_text)
|
||||
|
||||
@@ -789,13 +804,28 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
# ADMIN FLOWS
|
||||
# ════════════════════════════════════════════════════════════════════
|
||||
|
||||
elif action == "back":
|
||||
if payload == "admin":
|
||||
context.user_data.clear()
|
||||
try:
|
||||
await query.edit_message_text(
|
||||
"<b>⚙️ Admin Panel</b>", parse_mode="HTML",
|
||||
reply_markup=_admin_menu_keyboard())
|
||||
except Exception:
|
||||
await query.answer(show_alert=True)
|
||||
|
||||
elif action == "admin_add":
|
||||
admin_row = await _require_admin(update)
|
||||
if not admin_row:
|
||||
return
|
||||
context.user_data["state"] = "admin_awaiting_tg_id_add"
|
||||
context.user_data["admin_action_msg_id"] = msg_id
|
||||
await query.edit_message_text("Enter the Telegram user ID to add:", parse_mode="HTML")
|
||||
await query.edit_message_text(
|
||||
"Enter the Telegram user ID to add:", parse_mode="HTML",
|
||||
reply_markup=InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("❌ Cancel", callback_data="back:admin")],
|
||||
]),
|
||||
)
|
||||
|
||||
elif action == "admin_list":
|
||||
admin_row = await _require_admin(update)
|
||||
@@ -831,4 +861,9 @@ async def _handle_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
return
|
||||
context.user_data["state"] = "admin_awaiting_tg_id_remove"
|
||||
context.user_data["admin_action_msg_id"] = msg_id
|
||||
await query.edit_message_text("Enter the Telegram user ID to remove:", parse_mode="HTML")
|
||||
await query.edit_message_text(
|
||||
"Enter the Telegram user ID to remove:", parse_mode="HTML",
|
||||
reply_markup=InlineKeyboardMarkup([
|
||||
[InlineKeyboardButton("❌ Cancel", callback_data="back:admin")],
|
||||
]),
|
||||
)
|
||||
+8
-1
@@ -79,7 +79,14 @@ async def scheduler_task(pool: object, bot: ExtBot) -> None:
|
||||
if initial_loaded:
|
||||
notify_fields = {**fields, "keyword": keyword}
|
||||
for tg_id in telegram_ids:
|
||||
await notify_new_ad(bot, tg_id, notify_fields)
|
||||
msg_id_val = await notify_new_ad(bot, tg_id, notify_fields)
|
||||
if msg_id_val:
|
||||
user_row = await pool.fetchrow("SELECT id FROM users WHERE telegram_id = $1", tg_id)
|
||||
if user_row:
|
||||
try:
|
||||
await log_notification(pool, str(user_row["id"]), ad_uuid, msg_id_val)
|
||||
except Exception:
|
||||
logger.exception("Failed to log new ad notification")
|
||||
new_count += 1
|
||||
else:
|
||||
ad_uuid = str(existing["id"])
|
||||
|
||||
Reference in New Issue
Block a user