Renamed dtek-bot's dockercompose for easy access
Updated parser logic for updated site version
This commit is contained in:
+64
-51
@@ -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")
|
||||
# Визначаємо статус та підтвердження для всієї години
|
||||
confirmed = None
|
||||
if 'confirm_1' in cell_classes:
|
||||
confirmed = True
|
||||
elif 'confirm_0' in cell_classes:
|
||||
confirmed = False
|
||||
|
||||
def parse_half(half, force_off: bool = False) -> Dict:
|
||||
if not half:
|
||||
return {"status": "unknown", "queue": None, "confirmed": None}
|
||||
# Шукаємо часткові відключення через div.fill
|
||||
fill_divs = hour_block.select(".fill")
|
||||
|
||||
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"
|
||||
first_half_data = {"status": "on", "queue": None, "confirmed": None}
|
||||
second_half_data = {"status": "on", "queue": None, "confirmed": None}
|
||||
|
||||
queue = None
|
||||
confirmed = None
|
||||
disconnection_div = half.select_one(".disconnection")
|
||||
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', [])
|
||||
|
||||
if disconnection_div and disconnection_div.has_attr("title"):
|
||||
title = disconnection_div["title"]
|
||||
if "Номер черги" in title:
|
||||
try:
|
||||
queue = title.split(":")[-1].strip()
|
||||
except:
|
||||
pass
|
||||
# Визначаємо підтвердження
|
||||
fill_confirmed = None
|
||||
if 'confirmed' in fill_classes:
|
||||
fill_confirmed = True
|
||||
elif 'possible' in fill_classes:
|
||||
fill_confirmed = False
|
||||
|
||||
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)
|
||||
# Парсимо стиль для визначення часу
|
||||
# --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"❌ <b>Помилка:</b> {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 = "✅ <b>Знайдено зміни!</b>\n\n" if schedules_differ(last_schedule, new_schedule) else "✓ <b>Графік без змін</b>\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 == "🔄 Оновити":
|
||||
|
||||
Reference in New Issue
Block a user