fix: skip notifications during baseline load, add /interval command with /list display
This commit is contained in:
+79
-2
@@ -79,6 +79,7 @@ def register_handlers(app: Application) -> None:
|
||||
app.add_handler(CommandHandler("add", add_handler))
|
||||
app.add_handler(CommandHandler("list", list_handler))
|
||||
app.add_handler(CommandHandler("delete", delete_handler))
|
||||
app.add_handler(CommandHandler("interval", interval_handler))
|
||||
app.add_handler(CommandHandler("stats", stats_handler))
|
||||
app.add_handler(CommandHandler("adduser", adduser_handler))
|
||||
app.add_handler(CommandHandler("removeuser", removeuser_handler))
|
||||
@@ -99,6 +100,7 @@ async def start_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N
|
||||
"/add <keyword> — Subscribe to a keyword (shared across users)\n"
|
||||
"/list — List your subscriptions\n"
|
||||
"/delete <keyword_id> — Unsubscribe from a keyword\n"
|
||||
"/interval <keyword_id> <minutes> — Change scrape interval\n"
|
||||
"/stats — View your tracking statistics",
|
||||
)
|
||||
|
||||
@@ -127,7 +129,7 @@ async def add_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Non
|
||||
if not existing:
|
||||
kw_id = str(uuid.uuid4())
|
||||
await pool.execute(
|
||||
"INSERT INTO keywords (id, keyword, interval_minutes, is_active) VALUES ($1, $2, 60, true)",
|
||||
"INSERT INTO keywords (id, keyword, interval_minutes, is_active) VALUES ($1, $2, 5, true)",
|
||||
kw_id,
|
||||
keyword,
|
||||
)
|
||||
@@ -171,7 +173,7 @@ async def list_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
|
||||
pool = await get_pool()
|
||||
subscriptions = await pool.fetch(
|
||||
"SELECT kw.id, kw.keyword, kw.is_active, kw.last_scraped_at, COUNT(ks2.user_id) AS subs "
|
||||
"SELECT kw.id, kw.keyword, kw.is_active, kw.interval_minutes, kw.last_scraped_at, COUNT(ks2.user_id) AS subs "
|
||||
"FROM keyword_subscriptions ks "
|
||||
"JOIN keywords kw ON kw.id = ks.keyword_id "
|
||||
"LEFT JOIN keyword_subscriptions ks2 ON ks2.keyword_id = ks.keyword_id "
|
||||
@@ -194,12 +196,87 @@ async def list_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
f"{i}. \"{s['keyword']}\"\n"
|
||||
f" ID: {s['id']}\n"
|
||||
f" Status: {status}{subs}\n"
|
||||
f" Interval: {s['interval_minutes']} min\n"
|
||||
f" Last scraped: {last}"
|
||||
)
|
||||
|
||||
await update.message.reply_text("\n\n".join(lines)) # type: ignore[union-attr]
|
||||
|
||||
|
||||
# -- /interval ------------------------------------------------------------
|
||||
|
||||
async def interval_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
row = await _require_user(update)
|
||||
if not row:
|
||||
return
|
||||
|
||||
text = (update.message or update.callback_query).text or "" # type: ignore[union-attr]
|
||||
parts = text.split()
|
||||
if len(parts) < 3:
|
||||
await update.message.reply_text("Usage: /interval <keyword_id> <minutes>") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
keyword_id = parts[1].strip()
|
||||
try:
|
||||
uuid.UUID(keyword_id)
|
||||
except ValueError:
|
||||
await update.message.reply_text("Invalid keyword ID format.") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
try:
|
||||
minutes = int(parts[2])
|
||||
except ValueError:
|
||||
await update.message.reply_text("Interval must be a number (minutes).") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
if minutes < 1 or minutes > 1440:
|
||||
await update.message.reply_text("Interval must be between 1 and 1440 minutes.") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
pool = await get_pool()
|
||||
|
||||
sub_check = await pool.fetchrow(
|
||||
"SELECT 1 FROM keyword_subscriptions WHERE keyword_id = $1 AND user_id = $2",
|
||||
keyword_id,
|
||||
row["id"],
|
||||
)
|
||||
if not sub_check:
|
||||
await update.message.reply_text("You are not subscribed to this keyword.") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
kw_row = await pool.fetchrow(
|
||||
"SELECT id, interval_minutes FROM keywords WHERE id = $1",
|
||||
keyword_id,
|
||||
)
|
||||
if not kw_row:
|
||||
await update.message.reply_text("Keyword not found.") # type: ignore[union-attr]
|
||||
return
|
||||
|
||||
old_interval = kw_row["interval_minutes"]
|
||||
await pool.execute(
|
||||
"UPDATE keywords SET interval_minutes = $1 WHERE id = $2",
|
||||
minutes,
|
||||
keyword_id,
|
||||
)
|
||||
|
||||
sub_count = await pool.fetchval(
|
||||
"SELECT COUNT(*) FROM keyword_subscriptions WHERE keyword_id = $1",
|
||||
keyword_id,
|
||||
)
|
||||
|
||||
if sub_count > 1:
|
||||
await update.message.reply_text( # type: ignore[union-attr]
|
||||
f"Interval updated: {old_interval} min → {minutes} min\n"
|
||||
f"(affects all {sub_count} subscriber(s))",
|
||||
)
|
||||
else:
|
||||
await update.message.reply_text( # type: ignore[union-attr]
|
||||
f"Interval updated: {old_interval} min → {minutes} min",
|
||||
)
|
||||
|
||||
logger.info("User %s changed interval for keyword '%s' to %d min", update.effective_user.id, keyword_id, minutes)
|
||||
|
||||
|
||||
# -- /delete --------------------------------------------------------------
|
||||
|
||||
async def delete_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ async def scheduler_task(pool: object, bot: ExtBot) -> None:
|
||||
fields.get("main_image_url"), fields.get("postcode"), ad_uuid,
|
||||
)
|
||||
|
||||
if not initial_loaded:
|
||||
if initial_loaded:
|
||||
notify_fields = {**fields, "keyword": keyword}
|
||||
for tg_id in telegram_ids:
|
||||
await notify_new_ad(bot, tg_id, notify_fields)
|
||||
|
||||
Reference in New Issue
Block a user