From 287b1b154f523b6c95ac74a9358e5acab91ca4ec Mon Sep 17 00:00:00 2001 From: Aron Date: Fri, 2 Jan 2026 11:23:35 +0100 Subject: [PATCH] fix emojis --- application_handler.py | 18 +++++++++--------- handlers/wbm_handler.py | 2 ++ handlers/wgcompany_notifier.py | 6 +++--- main.py | 23 +++++++++++------------ telegram_bot.py | 22 ++++++++++++++-------- 5 files changed, 39 insertions(+), 32 deletions(-) diff --git a/application_handler.py b/application_handler.py index eaf4240..f94c2c6 100644 --- a/application_handler.py +++ b/application_handler.py @@ -85,7 +85,7 @@ class ApplicationHandler: company_label = company.capitalize() if company != "unknown" else "Wohnung" message = ( - f"๐Ÿ  [{company_label}] Neue Wohnung!\n\n" + f"[{company_label}] Neue Wohnung!\n\n" f"๐Ÿšช {listing['rooms']}\n" f"๐Ÿ“ {listing['size']}\n" f"๐Ÿ’ฐ {listing['price']}\n" @@ -136,7 +136,7 @@ class ApplicationHandler: result = await self.apply(listing) results[listing["id"]] = result self.save_application(result) - status = "โœ…" if result["success"] else "โŒ" + status = "[SUCCESS]" if result["success"] else "[FAILED]" logger.info(f"{status} {listing['address'][:30]}... | {result['message'][:50]}") await asyncio.sleep(2) return results @@ -409,7 +409,7 @@ class ApplicationHandler: else: stats_text = "๐ŸŽฏ Peak time: N/A" - stats_text = f"""๐Ÿ“Š Summary Statistics + stats_text = f"""Summary Statistics Total listings tracked: {total_listings} @@ -632,15 +632,15 @@ Total listings tracked: {total_listings} try: listings = await self._fetch_listings_attempt() if attempt > 0: - logger.info(f"โœ… Fetch succeeded (attempt {attempt + 1})") + logger.info(f"Fetch succeeded (attempt {attempt + 1})") return listings except Exception as e: if attempt < max_retries - 1: wait_time = retry_delay * (2 ** attempt) # Exponential backoff - logger.warning(f"โš ๏ธ Fetch failed (attempt {attempt + 1}/{max_retries}): {str(e)[:50]}... Retrying in {wait_time}s") + logger.warning(f"Fetch failed (attempt {attempt + 1}/{max_retries}): {str(e)[:50]}... Retrying in {wait_time}s") await asyncio.sleep(wait_time) else: - logger.error(f"โŒ Fetch failed after {max_retries} attempts") + logger.error(f"Fetch failed after {max_retries} attempts") return [] return [] @@ -782,14 +782,14 @@ Total listings tracked: {total_listings} listings = unique_listings if not listings: - logger.warning("โš ๏ธ No listings parsed") + logger.warning("No listings parsed") await page.close() - logger.info(f"๐Ÿ“Š Fetched {len(listings)} listings") + logger.info(f"Fetched {len(listings)} listings") return listings except Exception as e: - logger.error(f"โŒ Fetch error: {str(e)[:100]}") + logger.error(f"Fetch error: {str(e)[:100]}") return [] diff --git a/handlers/wbm_handler.py b/handlers/wbm_handler.py index 9daa2da..7370dcd 100644 --- a/handlers/wbm_handler.py +++ b/handlers/wbm_handler.py @@ -92,6 +92,8 @@ class WBMHandler(BaseHandler): # Look for application button on detail page logger.info("[WBM] Looking for application button on detail page...") selectors = [ + 'button:has-text("Anfrage absenden")', + 'a:has-text("Anfrage absenden")', 'a[href*="expose-anfordern"]', 'a[href*="bewerben"]', 'a:has-text("Anfragen")', diff --git a/handlers/wgcompany_notifier.py b/handlers/wgcompany_notifier.py index e3b8d7a..6022f09 100644 --- a/handlers/wgcompany_notifier.py +++ b/handlers/wgcompany_notifier.py @@ -151,7 +151,7 @@ class WGCompanyNotifier: if listing['id'] not in previous: new.append(listing) if new: - logger.info(f"[WG] ๐Ÿ  {len(new)} new listing{'s' if len(new) > 1 else ''} detected") + logger.info(f"[WG] {len(new)} new listing{'s' if len(new) > 1 else ''} detected") return new def log_listing_times(self, new_listings): @@ -185,7 +185,7 @@ class WGCompanyNotifier: for idx, listing in enumerate(new_listings, start=1): try: message = ( - f"๐Ÿ  [WG-Company] Neues WG-Zimmer!\n\n" + f"[WG-Company] Neues WG-Zimmer!\n\n" f"๐Ÿšช {listing['rooms']}\n" f"๐Ÿ“ {listing['size']}\n" f"๐Ÿ’ฐ {listing['price']}\n" @@ -196,7 +196,7 @@ class WGCompanyNotifier: asyncio.run_coroutine_threadsafe(self.telegram_bot._send_message(message), loop) await asyncio.sleep(0.5) except Exception as e: - logger.error(f"[WG] โŒ Telegram failed for listing {idx}: {str(e)[:50]}") + logger.error(f"[WG] Telegram failed for listing {idx}: {str(e)[:50]}") async def run(self): await self.init_browser() diff --git a/main.py b/main.py index 530de62..942f063 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,3 @@ - import asyncio from playwright.async_api import async_playwright from application_handler import ApplicationHandler @@ -22,13 +21,13 @@ logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)-5s] %(name)-20s | %(message)s", handlers=[ - RotatingFileHandler("data/monitor.log", maxBytes=1 * 1024 * 1024, backupCount=3), # 1 MB per file, 3 backups + RotatingFileHandler("data/monitor.log", maxBytes=1 * 1024 * 1024, backupCount=3), logging.StreamHandler() ], force=True # Enforce for all modules, Python 3.8+ ) logger = logging.getLogger(__name__) # Use named logger -logger.info("๐Ÿš€ Bot starting | Logs: data/monitor.log + console") +logger.info("Bot starting | Logs: data/monitor.log + console") # Interval (seconds) between checks for new listings CHECK_INTERVAL = int(os.getenv("CHECK_INTERVAL", 300)) # Default: 300 seconds @@ -96,7 +95,7 @@ async def init_browser_context() -> tuple: return playwright, browser, browser_context async def main() -> None: - logger.info("๐Ÿค– Initializing wohn-bot...") + logger.info("Initializing wohn-bot...") # Validate configuration before starting if not validate_config(): @@ -106,7 +105,7 @@ async def main() -> None: state_manager = StateManager(Path("data/state.json")) # --- Playwright browser/context setup with recovery --- - logger.info("๐ŸŒ Initializing browser...") + logger.info("Initializing browser...") playwright, browser, browser_context = await init_browser_context() # Application handler manages browser/context @@ -134,16 +133,16 @@ async def main() -> None: try: deleted = autoclean_debug_material() if deleted: - logger.info(f"๐Ÿงน Cleaned {len(deleted)} debug files (48h)") + logger.info(f"Cleaned {len(deleted)} debug files (48h)") except Exception as e: - logger.warning(f"โš ๏ธ Autoclean failed: {e}") + logger.warning(f"Autoclean failed: {e}") last_clean = now try: current_listings = await app_handler.fetch_listings() except Exception as e: logger.error(f"๐Ÿ’ฅ Browser crash: {e}") - logger.info("๐Ÿ”„ Recovering...") + logger.info("Recovering...") try: await browser.close() await playwright.stop() @@ -154,7 +153,7 @@ async def main() -> None: try: playwright, browser, browser_context = await init_browser_context() app_handler.context = browser_context - logger.info("โœ… Browser recovered") + logger.info("Browser recovered") await asyncio.sleep(5) continue except Exception as recovery_error: @@ -163,7 +162,7 @@ async def main() -> None: continue if not current_listings: - logger.warning("โš ๏ธ No listings fetched") + logger.warning("No listings fetched") await asyncio.sleep(CHECK_INTERVAL) _flush_rotating_file_handlers() continue @@ -192,10 +191,10 @@ async def main() -> None: new_listings = app_handler.find_new_listings(current_listings, previous_listings) application_results = {} if new_listings: - logger.info(f"\ud83c\udfe0 {len(new_listings)} new listing{'s' if len(new_listings) > 1 else ''} detected") + logger.info(f"{len(new_listings)} new listing{'s' if len(new_listings) > 1 else ''} detected") app_handler.log_listing_times(new_listings) if app_handler.is_autopilot_enabled(): - logger.info("\ud83e\udd16 Autopilot active - applying...") + logger.info("Autopilot active - applying...") application_results = await app_handler.apply_to_listings(new_listings) app_handler.notify_new_listings(new_listings, application_results) app_handler.save_listings(current_listings) diff --git a/telegram_bot.py b/telegram_bot.py index ae5e572..6830dc2 100644 --- a/telegram_bot.py +++ b/telegram_bot.py @@ -62,7 +62,7 @@ class TelegramBot: await self._send_message(msg) except Exception as e: logger.error(f"Error resetting listings: {e}") - await self._send_message(f"โŒ Error resetting listings: {str(e)}") + await self._send_message(f"[ERROR] Error resetting listings: {str(e)}") def __init__(self, monitor, bot_token: str | None = None, chat_id: str | None = None, event_loop=None) -> None: self.monitor = monitor @@ -174,9 +174,9 @@ class TelegramBot: and app.get("retries", 0) < max_retries and not app.get("deactivated", False) ] - await self._send_message(f"๐Ÿ”„ Retrying {len(failed)} failed applications (max retries: {max_retries})...") + await self._send_message(f"[RETRY] Retrying {len(failed)} failed applications (max retries: {max_retries})...") if not failed: - await self._send_message("โœ… No failed applications to retry (or all reached max retries).") + await self._send_message("[INFO] No failed applications to retry (or all reached max retries).") return results = {} details = [] @@ -197,7 +197,7 @@ class TelegramBot: result["timestamp"] = app.get("timestamp", result["timestamp"]) self.app_handler.save_application(result) results[listing["id"]] = result - status_emoji = "โœ…" if result["success"] else "โŒ" + status_emoji = "[SUCCESS]" if result["success"] else "[FAILED]" details.append( f"{status_emoji} {result.get('address', '')} ({result.get('company', '')})\n" f"{result.get('link', '')}\n" @@ -205,7 +205,7 @@ class TelegramBot: ) n_success = sum(1 for r in results.values() if r["success"]) n_fail = sum(1 for r in results.values() if not r["success"]) - summary = f"๐Ÿ”„ Retried {len(results)} failed applications.\nโœ… Success: {n_success}\nโŒ Still failed: {n_fail}" + summary = f"[RETRY] Retried {len(results)} failed applications.\n[SUCCESS]: {n_success}\n[FAILED]: {n_fail}" if details: summary += "\n\nDetails:\n" + "\n".join(details) await self._send_message(summary) @@ -220,7 +220,7 @@ class TelegramBot: if action == "on": logger.info("Enabling autopilot mode") self.monitor.set_autopilot(True) - await self._send_message("๐Ÿค– Autopilot ENABLED\n\nI will automatically apply to new listings!") + await self._send_message("Autopilot ENABLED\n\nI will automatically apply to new listings!") elif action == "off": self.monitor.set_autopilot(False) await self._send_message("๐Ÿ›‘ Autopilot DISABLED\n\nI will only notify you of new listings.") @@ -231,7 +231,7 @@ class TelegramBot: state = self.app_handler.load_state() autopilot = state.get("autopilot", False) applications = self.app_handler.load_applications() - status = "๐Ÿค– Autopilot: " + ("ON โœ…" if autopilot else "OFF โŒ") + status = "Autopilot: " + ("ON" if autopilot else "OFF") status += f"\n๐Ÿ“ Applications sent: {len(applications)}" by_company: dict[str, int] = {} for app in applications.values(): @@ -264,7 +264,7 @@ class TelegramBot: logger.error(f"Error generating errorrate plot: {e}") import traceback logger.error(traceback.format_exc()) - await self._send_message(f"โŒ Error generating errorrate plot: {str(e)}") + await self._send_message(f"[ERROR] Error generating errorrate plot: {str(e)}") async def _send_message(self, text: str) -> None: @@ -274,6 +274,9 @@ class TelegramBot: logger.warning("Telegram bot token or chat ID not configured, cannot send message") return + # Clean text: remove invalid unicode surrogates + text = text.encode('utf-8', errors='ignore').decode('utf-8') + url = f"https://api.telegram.org/bot{self.bot_token}/sendMessage" # Split message into chunks if too long @@ -340,6 +343,9 @@ class TelegramBot: logger.warning("Telegram bot token or chat ID not configured, cannot send photo") return + # Clean caption: remove invalid unicode surrogates + caption = caption.encode('utf-8', errors='ignore').decode('utf-8') + url = f"https://api.telegram.org/bot{self.bot_token}/sendPhoto" max_retries = 3 retry_delay = 1 # Initial delay in seconds