From f82f9ef75215810f840a52d37174f3f368dec6a2 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 8 Aug 2026 06:16:09 +0500 Subject: [PATCH] feat(captcha): add periodic captcha update --- .env.example | 3 ++ config.py | 4 +++ modules/stars_bot.py | 74 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/.env.example b/.env.example index 9fdc1c2..f2a061b 100644 --- a/.env.example +++ b/.env.example @@ -35,4 +35,7 @@ BUMP_CHECK_INTERVAL=3600 # Капча будет в самом нижнем спойлере: Капча (обязательно) ENABLE_CAPTCHA=false CAPTCHA_ANSWER=40 +# Интервал проверки обновления капчи в секундах (минимум 300 секунд = 5 минут) +# Капча будет автоматически обновляться из файла storage/captcha.txt +CAPTCHA_CHECK_INTERVAL=1800 diff --git a/config.py b/config.py index 0036b0a..97f8436 100644 --- a/config.py +++ b/config.py @@ -130,6 +130,9 @@ class Config: os.getenv(key="ENABLE_CAPTCHA", default="true") ).lower() == "true" captcha_answer = os.getenv(key="CAPTCHA_ANSWER", default=None) + captcha_check_interval = max( + float(os.getenv(key="CAPTCHA_CHECK_INTERVAL", default=1800)), 300 + ) # проверка обновления капчи, минимум 300с (5 минут) # Validate captcha configuration if enable_captcha and not captcha_answer: @@ -165,6 +168,7 @@ class Config: # Captcha "enable_captcha": enable_captcha, "captcha_answer": captcha_answer, + "captcha_check_interval": captcha_check_interval, } except ConfigError: diff --git a/modules/stars_bot.py b/modules/stars_bot.py index 5dbc478..c24ffd4 100644 --- a/modules/stars_bot.py +++ b/modules/stars_bot.py @@ -141,7 +141,8 @@ class TelegramStarsBot: logger.error(f"Критическая ошибка при отправке звезд: {e}") return False - async def add_captcha(self): + async def update_captcha(self): + """Update or add captcha text in the thread spoiler block""" captcha_text = self.config._load_captcha() if ( not captcha_text @@ -167,22 +168,39 @@ class TelegramStarsBot: ) thread_text = thread["first_post"].get("post_body", "") - # Check if captcha already exists in thread - if "[spoiler=Капча" in thread_text: - logger.info( - f"Капча уже существует в теме {self.config.lolz_thread_id}, пропускаю добавление." - ) - return True + # Pattern to match the captcha spoiler block + captcha_pattern = r'\[spoiler=Капча[^\]]*\]\[CENTER\].*?\[/CENTER\]\[/spoiler\]' - captcha_wrapper = f"\n\n[spoiler=Капча (обязательно);align=center][CENTER]{captcha_text}[/CENTER][/spoiler]" - thread_text += captcha_wrapper + if re.search(captcha_pattern, thread_text, re.DOTALL): + # Replace existing captcha text + captcha_wrapper = f"[spoiler=Капча (обязательно);align=center][CENTER]{captcha_text}[/CENTER][/spoiler]" + updated_text = re.sub(captcha_pattern, captcha_wrapper, thread_text, flags=re.DOTALL) + + # Check if text actually changed + if updated_text == thread_text: + logger.info( + f"Капча в теме {self.config.lolz_thread_id} уже актуальна, изменений не требуется." + ) + return True + + thread_text = updated_text + logger.info( + f"Обновление капчи в теме {self.config.lolz_thread_id}..." + ) + else: + # Add new captcha block + captcha_wrapper = f"\n\n[spoiler=Капча (обязательно);align=center][CENTER]{captcha_text}[/CENTER][/spoiler]" + thread_text += captcha_wrapper + logger.info( + f"Добавление капчи в тему {self.config.lolz_thread_id}..." + ) await self.lolz_api.edit_thread( thread_id=self.config.lolz_thread_id, post_body=thread_text ) logger.info( - f"Тема {self.config.lolz_thread_id} отредактирована. Текст с капчей добавлен" + f"Тема {self.config.lolz_thread_id} успешно отредактирована." ) return True @@ -382,6 +400,27 @@ class TelegramStarsBot: logger.exception(f"Критическая ошибка в цикле поднятия темы: {e}") await asyncio.sleep(self.config.bump_check_interval) + async def _captcha_loop(self): + """Loop to periodically check and update captcha text""" + while True: + try: + logger.info( + f"Проверка обновления капчи для темы {self.config.lolz_thread_id}..." + ) + + await self.update_captcha() + + logger.info(f"Ожидание {self.config.captcha_check_interval} секунд до следующей проверки капчи...") + await asyncio.sleep(self.config.captcha_check_interval) + + except KeyboardInterrupt: + logger.info("Получен сигнал прерывания (Ctrl+C).") + break + + except Exception as e: + logger.exception(f"Критическая ошибка в цикле обновления капчи: {e}") + await asyncio.sleep(self.config.captcha_check_interval) + async def start(self): is_first_login = not os.path.exists(f"{self.SESSION_NAME}.session") @@ -434,14 +473,21 @@ class TelegramStarsBot: # _main_loop - Основной цикл для остлеживания темы # _bump_loop - Цикл для авто-поднятия темы + # _captcha_loop - Цикл для обновления капчи if self.config.enable_captcha: - await self.add_captcha() + await self.update_captcha() + + # Gather all enabled loops + tasks = [self._main_loop()] if self.config.enable_auto_bump: - await asyncio.gather(self._main_loop(), self._bump_loop()) - else: - await self._main_loop() + tasks.append(self._bump_loop()) + + if self.config.enable_captcha: + tasks.append(self._captcha_loop()) + + await asyncio.gather(*tasks) except Exception as e: logger.error(f"Ошибка в главном процессе бота: {e}")