feat: add admin commands to manage whitelist, extended webinar reporting

This commit is contained in:
2025-11-26 22:25:47 +01:00
parent d4e0e7f37a
commit 8fae8bf75d
+69 -5
View File
@@ -98,11 +98,59 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
"/help - Show this message\n" "/help - Show this message\n"
) )
if update.effective_user.id == ADMIN_ID: if update.effective_user.id == ADMIN_ID:
msg += "\n<b>Admin Commands:</b>\nUse the panel below to manage settings." msg += (
"\n<b>Admin Commands:</b>\n"
"/adduser [user_id] - Add user to whitelist\n"
"/removeuser [user_id] - Remove user from whitelist\n"
"Or use the panel below to manage settings."
)
await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard()) await update.message.reply_text(msg, parse_mode='HTML', reply_markup=get_admin_keyboard())
else: else:
await update.message.reply_text(msg, parse_mode='HTML') await update.message.reply_text(msg, parse_mode='HTML')
async def add_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Add user to whitelist (admin only)."""
if update.effective_user.id != ADMIN_ID:
await update.message.reply_text("⛔ Admin only!")
return
if not context.args:
await update.message.reply_text("Usage: /adduser [user_id]")
return
try:
user_id = int(context.args[0])
redis_client.sadd(KEY_WHITELIST, str(user_id))
await update.message.reply_text(f"✅ User {user_id} added to whitelist")
logger.info(f"Admin added user {user_id} to whitelist")
except ValueError:
await update.message.reply_text("❌ Invalid user ID. Must be a number.")
async def remove_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Remove user from whitelist (admin only)."""
if update.effective_user.id != ADMIN_ID:
await update.message.reply_text("⛔ Admin only!")
return
if not context.args:
await update.message.reply_text("Usage: /removeuser [user_id]")
return
try:
user_id = int(context.args[0])
if str(user_id) == str(ADMIN_ID):
await update.message.reply_text("❌ Cannot remove admin from whitelist")
return
removed = redis_client.srem(KEY_WHITELIST, str(user_id))
if removed:
await update.message.reply_text(f"✅ User {user_id} removed from whitelist")
logger.info(f"Admin removed user {user_id} from whitelist")
else:
await update.message.reply_text(f"⚠️ User {user_id} was not in whitelist")
except ValueError:
await update.message.reply_text("❌ Invalid user ID. Must be a number.")
# --- Admin Callbacks --- # --- Admin Callbacks ---
async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE): async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -137,18 +185,29 @@ async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
elif data == "force_check": elif data == "force_check":
await query.message.reply_text("🔄 Running immediate check...") await query.message.reply_text("🔄 Running immediate check...")
await check_webinars_job(context) result = await check_webinars_job(context)
if result is None:
await query.message.reply_text("❌ Check failed. See logs for details.")
elif result == 0:
await query.message.reply_text("✅ Check completed. No webinars found.")
else:
await query.message.reply_text(f"✅ Check completed. Found {result} webinar(s)!")
# --- Webinar Checking Job --- # --- Webinar Checking Job ---
async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE): async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
"""Background job to check for webinars using Async Playwright.""" """Background job to check for webinars using Async Playwright.
Returns:
int: Number of webinars found, or None if check failed
"""
logger.info("Running webinar check...") logger.info("Running webinar check...")
phpsessid = redis_client.get(KEY_PHPSESSID) phpsessid = redis_client.get(KEY_PHPSESSID)
if not phpsessid: if not phpsessid:
logger.warning("PHPSESSID missing. Skipping check.") logger.warning("PHPSESSID missing. Skipping check.")
return return None
webinar_details = [] webinar_details = []
@@ -199,6 +258,7 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
except Exception as e: except Exception as e:
logger.error(f"Error checking page: {e}") logger.error(f"Error checking page: {e}")
return None
finally: finally:
await page.close() await page.close()
await context_browser.close() await context_browser.close()
@@ -208,7 +268,7 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
except Exception as e: except Exception as e:
logger.error(f"Playwright error: {e}") logger.error(f"Playwright error: {e}")
return return None
# Notify subscribers if webinars found # Notify subscribers if webinars found
if webinar_details: if webinar_details:
@@ -221,6 +281,8 @@ async def check_webinars_job(context: ContextTypes.DEFAULT_TYPE):
logger.info(f"Notification sent to {sub_id}") logger.info(f"Notification sent to {sub_id}")
except Exception as e: except Exception as e:
logger.error(f"Failed to send to {sub_id}: {e}") logger.error(f"Failed to send to {sub_id}: {e}")
return len(webinar_details)
# --- Main --- # --- Main ---
@@ -242,6 +304,8 @@ def main():
# Handlers # Handlers
app.add_handler(CommandHandler("start", start)) app.add_handler(CommandHandler("start", start))
app.add_handler(CommandHandler("help", help_command)) app.add_handler(CommandHandler("help", help_command))
app.add_handler(CommandHandler("adduser", add_user))
app.add_handler(CommandHandler("removeuser", remove_user))
app.add_handler(CallbackQueryHandler(admin_callback)) app.add_handler(CallbackQueryHandler(admin_callback))
# Job Queue # Job Queue