113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
import asyncio
|
|
from datetime import datetime, timedelta
|
|
from random import randint
|
|
from aiogram import Bot
|
|
from models.state import BotState
|
|
from config import Config
|
|
from services.schedule_service import ScheduleService
|
|
from logging import getLogger
|
|
|
|
|
|
logger = getLogger(__name__)
|
|
|
|
|
|
class WatcherService:
|
|
def __init__(self, state: BotState, bot: Bot):
|
|
self.state = state
|
|
self.bot = bot
|
|
self.schedule_service = ScheduleService()
|
|
|
|
async def start(self):
|
|
"""Запуск слежки"""
|
|
if self.state.watcher_work:
|
|
return
|
|
|
|
self.state.watcher_work = True
|
|
self.state.watcher_task = asyncio.create_task(self._watcher_loop())
|
|
logger.info("Watcher запущен")
|
|
|
|
async def stop(self):
|
|
"""Остановка слежки"""
|
|
if not self.state.watcher_work:
|
|
return
|
|
|
|
self.state.watcher_work = False
|
|
if self.state.watcher_task:
|
|
self.state.watcher_task.cancel()
|
|
try:
|
|
await self.state.watcher_task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
logger.info("Watcher остановлен")
|
|
|
|
async def _watcher_loop(self):
|
|
"""Основной цикл слежки"""
|
|
while self.state.watcher_work:
|
|
try:
|
|
find = await self._check_all_groups()
|
|
if find:
|
|
# ничего не нашли → ждём
|
|
delay = randint(
|
|
Config.WATCHER_BASE_DELAY, Config.WATCHER_BASE_DELAY + 100
|
|
)
|
|
logger.info(f"Следующая проверка через {delay}")
|
|
await asyncio.sleep(delay)
|
|
else:
|
|
# нашли → останавливаемся
|
|
logger.info("Расписание найдено, останавливаем watcher")
|
|
self.state.watcher_work = False
|
|
break
|
|
except asyncio.CancelledError:
|
|
break
|
|
except Exception as e:
|
|
logger.error(f"Ошибка в watcher_loop: {e}")
|
|
await asyncio.sleep(60)
|
|
|
|
@staticmethod
|
|
def _get_target_day() -> datetime:
|
|
"""Получение целевого дня"""
|
|
now = datetime.now()
|
|
target = now + timedelta(days=1)
|
|
if target.weekday() == 6:
|
|
target += timedelta(days=1)
|
|
return target
|
|
|
|
async def _check_all_groups(self) -> bool:
|
|
"""
|
|
Возвращает True, если НИ в одной группе не найдено расписание.
|
|
Возвращает False, если хотя бы в одной группе найдено расписание.
|
|
"""
|
|
day = self._get_target_day()
|
|
found_any = False
|
|
|
|
for group, chat_id in Config.GROUP_CHATS.items():
|
|
logger.info(
|
|
f"Проверяем расписание для {group} на {day.strftime('%d.%m.%Y')}"
|
|
)
|
|
found = await self._check_group_schedule(group, chat_id, day.day)
|
|
if found:
|
|
found_any = True
|
|
|
|
return not found_any # <-- вот так правильно
|
|
|
|
async def _check_group_schedule(self, group: str, chat_id: int, day: int) -> bool:
|
|
text, url, data_day, data_month = await self.schedule_service.get_schedule(
|
|
group, day
|
|
)
|
|
if text and "не найдено" not in text.lower():
|
|
msg = await self.bot.send_message(
|
|
chat_id,
|
|
f"Авто-расписание для {group} на {data_day:02d}.{data_month:02d}\n\n{text}",
|
|
parse_mode="Markdown",
|
|
)
|
|
await self.bot.pin_chat_message(
|
|
chat_id, msg.message_id, disable_notification=False
|
|
)
|
|
return True
|
|
return False
|
|
|
|
# clip_hash = hashlib.md5(clip_png).hexdigest()
|
|
|
|
# Логика проверки изменений и отправки сообщений
|
|
# ... (ваша существующая логика)
|