diff --git a/dtek_notif/dtek-docker-compose.yaml b/dtek_notif/docker-compose.yaml similarity index 100% rename from dtek_notif/dtek-docker-compose.yaml rename to dtek_notif/docker-compose.yaml diff --git a/dtek_notif/main.py b/dtek_notif/main.py index 67c3735..6637257 100644 --- a/dtek_notif/main.py +++ b/dtek_notif/main.py @@ -1,3 +1,10 @@ +# Раздел "ТВАРИ, ЧИТАТЕ ВНИМАТЕЛЬНО!" + +# Когда обновят сайт -- расскоментровать 641-646 и закоментировать 647. +# Поменять комменты 671 и 672 местами. + + + import requests import json import asyncio @@ -82,7 +89,7 @@ def get_day_statistics(day_blocks: List[Dict]) -> Dict[str, int]: # ============================================================================ def parse_html(html: str) -> List[Dict]: - """Парсит HTML с графиком отключений""" + """Парсит HTML с графиком отключений (нова логіка)""" soup = BeautifulSoup(html, "html.parser") cells = soup.select(".disconnection-detailed-table-cell.cell") @@ -95,61 +102,63 @@ def parse_html(html: str) -> List[Dict]: continue cell_classes = cell.get('class', []) + + # Перевіряємо чи вся година вимкнена full_hour_off = 'has_disconnection' in cell_classes and 'full_hour' in cell_classes + no_disconnection = 'no_disconnection' in cell_classes hour_block = cell.select_one(".hour_block") if not hour_block: continue - left = hour_block.select_one(".half.left") - right = hour_block.select_one(".half.right") - - def parse_half(half, force_off: bool = False) -> Dict: - if not half: - return {"status": "unknown", "queue": None, "confirmed": None} - - status = "off" if force_off else "unknown" - if not force_off: - classes = half.get("class", []) - if "has_disconnection" in classes: - status = "off" - elif "no_disconnection" in classes: - status = "on" - - queue = None - confirmed = None - disconnection_div = half.select_one(".disconnection") - - if disconnection_div and disconnection_div.has_attr("title"): - title = disconnection_div["title"] - if "Номер черги" in title: - try: - queue = title.split(":")[-1].strip() - except: - pass + # Визначаємо статус та підтвердження для всієї години + confirmed = None + if 'confirm_1' in cell_classes: + confirmed = True + elif 'confirm_0' in cell_classes: + confirmed = False + + # Шукаємо часткові відключення через div.fill + fill_divs = hour_block.select(".fill") + + first_half_data = {"status": "on", "queue": None, "confirmed": None} + second_half_data = {"status": "on", "queue": None, "confirmed": None} + + if full_hour_off: + # Вся година вимкнена + first_half_data = {"status": "off", "queue": None, "confirmed": confirmed} + second_half_data = {"status": "off", "queue": None, "confirmed": confirmed} + elif no_disconnection and not fill_divs: + # Вся година ввімкнена + first_half_data = {"status": "on", "queue": None, "confirmed": None} + second_half_data = {"status": "on", "queue": None, "confirmed": None} + else: + # Перевіряємо часткові відключення + for fill_div in fill_divs: + title = fill_div.get('title', '') + style = fill_div.get('style', '') + fill_classes = fill_div.get('class', []) - disconnection_classes = disconnection_div.get("class", []) - if "disconnection_confirm_1" in disconnection_classes: - confirmed = True - elif "disconnection_confirm_0" in disconnection_classes: - confirmed = False - - if force_off and confirmed is None: - if 'confirm_1' in cell_classes: - confirmed = True - elif 'confirm_0' in cell_classes: - confirmed = False - - return {"status": status, "queue": queue, "confirmed": confirmed} - - left_data = parse_half(left, force_off=full_hour_off) - right_data = parse_half(right, force_off=full_hour_off) + # Визначаємо підтвердження + fill_confirmed = None + if 'confirmed' in fill_classes: + fill_confirmed = True + elif 'possible' in fill_classes: + fill_confirmed = False + + # Парсимо стиль для визначення часу + # --start:0;--size:50 означає 0-30 хвилин (перша половина) + # --start:50;--size:50 означає 30-60 хвилин (друга половина) + if '--start:0' in style or title.endswith(':00—' + f'{current_hour:02d}:30'): + first_half_data = {"status": "off", "queue": None, "confirmed": fill_confirmed} + elif '--start:50' in style or (f'{current_hour:02d}:30' in title and title.endswith(':00')): + second_half_data = {"status": "off", "queue": None, "confirmed": fill_confirmed} schedule.append({ "hour": current_hour, "day": current_day, - "first_half": left_data, - "second_half": right_data, + "first_half": first_half_data, + "second_half": second_half_data, }) current_hour += 1 @@ -159,7 +168,6 @@ def parse_html(html: str) -> List[Dict]: return schedule - def get_voe_html(city_id: int, street_id: int, house_id: int) -> str: """Получает HTML с сайта VOE""" url = "https://www.voe.com.ua/disconnection/detailed?ajax_form=1&_wrapper_format=drupal_ajax" @@ -637,17 +645,21 @@ async def cmd_tomorrow(message: Message): return try: - await message.answer("⏳ Завантаження графіку завтра...") - html = get_voe_html(VOE_CITY_ID, VOE_STREET_ID, VOE_HOUSE_ID) - schedule = parse_html(html) - text = format_single_day_schedule(schedule, 1) - await message.answer(text, parse_mode="HTML", reply_markup=get_main_keyboard()) + # """Закоментировал до лучших времен""" + # await message.answer("⏳ Завантаження графіку завтра...") + # html = get_voe_html(VOE_CITY_ID, VOE_STREET_ID, VOE_HOUSE_ID) + # schedule = parse_html(html) + # text = format_single_day_schedule(schedule, 1) + # await message.answer(text, parse_mode="HTML", reply_markup=get_main_keyboard()) + await message.answer("❌ Функція тимчасово недоступна. Чекаємо на оновлення сайту", parse_mode="HTML", reply_markup=get_main_keyboard()) except Exception as e: await message.answer( f"❌ Помилка: {str(e)}", parse_mode="HTML", reply_markup=get_main_keyboard() ) +# Когда обновят сайт -- расскоментровать 641-646 и закоментировать 647. +# Поменять комменты 671 и 672 местами. @dp.message(Command("check")) @@ -663,7 +675,8 @@ async def cmd_check(message: Message): new_schedule = parse_html(html) prefix = "✅ Знайдено зміни!\n\n" if schedules_differ(last_schedule, new_schedule) else "✓ Графік без змін\n\n" - result = prefix + format_schedule_message(new_schedule, days_to_show=2) + # result = prefix + format_schedule_message(new_schedule, days_to_show=2) + result = prefix + format_schedule_message(new_schedule, days_to_show=1) await message.answer(result, parse_mode="HTML", reply_markup=get_main_keyboard()) except Exception as e: @@ -690,9 +703,9 @@ async def handle_text(message: Message): elif text == "📅 Сьогодні": await cmd_today(message) - # Кнопка "Завтра" - elif text == "📅 Завтра": - await cmd_tomorrow(message) + # # Кнопка "Завтра" + # elif text == "📅 Завтра": + # await cmd_tomorrow(message) # Кнопка "Оновити" elif text == "🔄 Оновити":