diff --git a/.env.example b/.env.example index d8d5d99..660e7d9 100644 --- a/.env.example +++ b/.env.example @@ -27,3 +27,4 @@ MAX_RETRIES=3 ENABLE_REPLY=true SKIP_COMMENTED=true +BUMP_CHECK_INTERVAL=3600 diff --git a/config.py b/config.py index 20157ef..470ce1d 100644 --- a/config.py +++ b/config.py @@ -88,6 +88,10 @@ class Config: os.getenv(key="SKIP_COMMENTED", default="true") ).lower() == "true" + bump_check_interval = max( + float(os.getenv(key="BUMP_CHECK_INTERVAL", default=3600)), 3600 + ) # 1 поднятие/3600с (1ч) = минимум + return { # Pyrogram "api_id": api_id, @@ -101,14 +105,17 @@ class Config: "lolz_thread_id": lolz_thread_id, # Stars "stars_count": stars_count, - # Misc - "default_choice": default_choice, + # Posts "start_page": start_page, + "enable_reply": enable_reply, "check_interval": check_interval, + "skip_commented": skip_commented, + # Misc "api_delay": api_delay, "max_retries": max_retries, - "enable_reply": enable_reply, - "skip_commented": skip_commented, + "default_choice": default_choice, + # Bump + "bump_check_interval": bump_check_interval, } except: diff --git a/modules/lolz.py b/modules/lolz.py index e815ac5..27993a8 100644 --- a/modules/lolz.py +++ b/modules/lolz.py @@ -1,3 +1,4 @@ +from concurrent.futures import thread import logging import asyncio @@ -11,11 +12,46 @@ class Lolz: def __init__(self, token: str): try: self.client = Forum(token=token, timeout=15) + + # ! Не рекомендуется включить этот логгер, + # ! ибо логи занимают очень много места в экране при этом логгере # self.client.settings.logger.enable() except: raise + async def get_thread(self, thread_id: Union[str, int]) -> Dict[str, Any]: + logger.debug(f"Запрашиваю данные темы {thread_id}...") + response = await self.client.threads.get(thread_id=thread_id) + thread = (response.json()).get("thread", {}) + + if thread == {}: + logger.warning(f"Тема {thread_id} не найдена или вернула пустой ответ.") + + return thread + + async def can_bump( + self, thread_id: Optional[int] = None, thread: Dict[str, Any] = None + ) -> bool: + if not thread: + if not thread_id: + thread = {} + else: + thread = await self.get_thread(thread_id=thread_id) + + return thread["permissions"]["bump"]["can"] + + async def bump_thread(self, thread_id: Union[str, int]) -> bool: + logger.debug(f"Поднимаю тему {thread_id}...") + response = await self.client.threads.bump(thread_id=thread_id) + + if response.status_code == 200: + logger.info(f"Тема {thread_id} успешно поднята.") + return True + else: + logger.error(f"Не удалось поднять тему {thread_id}.") + return False + async def get_post(self, post_id: Union[str, int]) -> Dict[str, Any]: logger.debug(f"Запрашиваю данные поста {post_id}...") response = await self.client.posts.get(post_id=post_id) diff --git a/modules/stars_bot.py b/modules/stars_bot.py index 33a3edd..5066a86 100644 --- a/modules/stars_bot.py +++ b/modules/stars_bot.py @@ -291,6 +291,42 @@ class TelegramStarsBot: logger.exception(f"Критическая ошибка в главном цикле: {e}") await asyncio.sleep(self.config.check_interval) + async def _bump_loop(self): + while True: + try: + logger.info( + f"Проверка статуса поднятия для темы {self.config.lolz_thread_id}..." + ) + + thread = await self.lolz_api.get_thread( + thread_id=self.config.lolz_thread_id + ) + can_bump = await self.lolz_api.can_bump(thread=thread) + + if can_bump: + try: + await self.lolz_api.bump_thread( + thread_id=self.config.lolz_thread_id + ) + + except Exception as e: + logger.error( + f"Ошибка поднятия темы {self.config.lolz_thread_id}, пропускаю: {e}" + ) + else: + logger.info("Тему нельзя поднять.") + + logger.info(f"Ожидание {self.config.check_interval} секунд...") + await asyncio.sleep(self.config.bump_check_interval) + + except KeyboardInterrupt: + logger.info("Получен сигнал прерывания (Ctrl+C).") + break + + except Exception as e: + logger.exception(f"Критическая ошибка в цикле поднятия темы: {e}") + await asyncio.sleep(self.config.check_interval) + async def start(self): is_first_login = not os.path.exists(f"{self.SESSION_NAME}.session") @@ -334,7 +370,10 @@ class TelegramStarsBot: logger.info(f"Проверка начинается со страницы: {self.start_page}") logger.info("Бот в работе. Для остановки нажмите Ctrl+C.") - await self._main_loop() + + # _main_loop - Основной цикл для остлеживания темы + # _bump_look - Цикл для авто-поднятия темы + await asyncio.gather(await self._main_loop(), await self._bump_loop()) finally: if self.client and self.client.is_connected: