From 29a3f629e2d8ff233a0fb9aac648f12caf223ff4 Mon Sep 17 00:00:00 2001 From: Aron Date: Fri, 2 Jan 2026 13:41:21 +0100 Subject: [PATCH] add start stop --- BOTFATHER_COMMANDS.txt | 19 +++++++++++++++++++ main.py | 7 +++++++ state_manager.py | 13 ++++++++++++- telegram_bot.py | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/BOTFATHER_COMMANDS.txt b/BOTFATHER_COMMANDS.txt index 5ffec20..3fabcc7 100644 --- a/BOTFATHER_COMMANDS.txt +++ b/BOTFATHER_COMMANDS.txt @@ -1,8 +1,27 @@ Autopilot bot command list for @BotFather +=== BOT DESCRIPTION (for @BotFather /setdescription) === + +🏠 Monitors 6 Berlin housing companies (HOWOGE, Gewobag, Degewo, Gesobau, Stadt und Land, WBM) + WG-Company for new apartments. + +βœ… Instant Telegram notifications +πŸ€– Autopilot: auto-fill & submit applications +πŸ“Š Weekly listing patterns & error tracking +πŸ”„ Retry failed applications with one command +⏸️ Pause/resume monitoring anytime + +Perfect for Berlin apartment hunters who want to apply first! + +=== BOT ABOUT (for @BotFather /setabouttext) === + +Automated Berlin apartment monitoring bot with auto-apply functionality for inberlinwohnen.de and wgcompany.de listings. + +=== COMMANDS (for @BotFather /setcommands) === Use @BotFather -> setcommands and paste the following lines exactly (one per line): +start - Resume monitoring for new listings +stop - Pause monitoring (bot stays running, commands still work) autopilot - Enable or disable automatic applications. Usage: autopilot on or autopilot off status - Show current status and statistics (autopilot state, application counts by company) plot - Show weekly listing patterns (image) diff --git a/main.py b/main.py index 942f063..21d2e28 100644 --- a/main.py +++ b/main.py @@ -139,6 +139,13 @@ async def main() -> None: last_clean = now try: + # Check if monitoring is enabled before fetching listings + if not state_manager.is_monitoring_enabled(): + logger.debug("Monitoring is paused, skipping listing check") + await asyncio.sleep(CHECK_INTERVAL) + _flush_rotating_file_handlers() + continue + current_listings = await app_handler.fetch_listings() except Exception as e: logger.error(f"πŸ’₯ Browser crash: {e}") diff --git a/state_manager.py b/state_manager.py index 30c8bfe..15337a5 100644 --- a/state_manager.py +++ b/state_manager.py @@ -25,7 +25,7 @@ class StateManager: if self.state_file.exists(): with open(self.state_file, "r") as f: return json.load(f) - return {"autopilot": False} + return {"autopilot": False, "monitoring_enabled": True} def save_state(self, state: dict) -> None: """Save persistent state""" @@ -43,6 +43,17 @@ class StateManager: """Check if autopilot mode is enabled""" return self.load_state().get("autopilot", False) + def set_monitoring_enabled(self, enabled: bool) -> None: + """Enable or disable monitoring""" + state = self.load_state() + state["monitoring_enabled"] = enabled + self.save_state(state) + logger.info(f"Monitoring {'enabled' if enabled else 'disabled'}") + + def is_monitoring_enabled(self) -> bool: + """Check if monitoring is enabled""" + return self.load_state().get("monitoring_enabled", True) + def set_logged_in(self, status: bool) -> None: """Set the logged_in status""" self.logged_in = status diff --git a/telegram_bot.py b/telegram_bot.py index 6830dc2..8843a3a 100644 --- a/telegram_bot.py +++ b/telegram_bot.py @@ -20,6 +20,8 @@ class TelegramBot: """Send a help message with available commands.""" help_text = ( "Available commands:\n" + "/start - Resume monitoring\n" + "/stop - Pause monitoring\n" "/autopilot on|off - Enable/disable autopilot\n" "/status - Show current status\n" "/plot - Show weekly listing pattern plot\n" @@ -38,6 +40,25 @@ class TelegramBot: ) await self._send_message(msg) + async def _handle_start_command(self) -> None: + """Resume monitoring for new listings.""" + self.monitor.state_manager.set_monitoring_enabled(True) + await self._send_message( + "▢️ Monitoring RESUMED\n\n" + "Bot will now check for new listings and notify you." + ) + logger.info("Monitoring resumed via /start command") + + async def _handle_stop_command(self) -> None: + """Pause monitoring without stopping the bot.""" + self.monitor.state_manager.set_monitoring_enabled(False) + await self._send_message( + "⏸️ Monitoring PAUSED\n\n" + "Bot will not check for new listings until you send /start.\n" + "Commands like /status, /plot, and /retryfailed still work." + ) + logger.info("Monitoring paused via /stop command") + async def _handle_reset_listings_command(self) -> None: """Move listings.json to data/old/ with a timestamp, preserving statistics and application history.""" import shutil @@ -133,7 +154,11 @@ class TelegramBot: return logger.info(f"Received Telegram command: {text}") loop = self.event_loop - if text.startswith("/autopilot"): + if text == "/start": + asyncio.run_coroutine_threadsafe(self._handle_start_command(), loop) + elif text == "/stop": + asyncio.run_coroutine_threadsafe(self._handle_stop_command(), loop) + elif text.startswith("/autopilot"): asyncio.run_coroutine_threadsafe(self._handle_autopilot_command(text), loop) elif text == "/status": asyncio.run_coroutine_threadsafe(self._handle_status_command(), loop) @@ -230,9 +255,13 @@ class TelegramBot: async def _handle_status_command(self) -> None: state = self.app_handler.load_state() autopilot = state.get("autopilot", False) + monitoring = state.get("monitoring_enabled", True) applications = self.app_handler.load_applications() - status = "Autopilot: " + ("ON" if autopilot else "OFF") + + status = "Monitoring: " + ("▢️ RUNNING" if monitoring else "⏸️ PAUSED") + status += "\nAutopilot: " + ("βœ… ON" if autopilot else "πŸ›‘ OFF") status += f"\nπŸ“ Applications sent: {len(applications)}" + by_company: dict[str, int] = {} for app in applications.values(): company = app.get("company", "unknown")