Enhance schedule formatting and error handling in DTEK notification bot
v2
This commit is contained in:
+112
-94
@@ -143,9 +143,9 @@ def get_main_keyboard():
|
||||
|
||||
|
||||
def format_schedule_message(schedule, days_to_show=2):
|
||||
"""Форматирует расписание для отправки в Telegram (компактная версия)"""
|
||||
message = f"⚡️ <b>Графік відключень</b>\n"
|
||||
message += f"🕐 {datetime.now().strftime('%d.%m.%Y %H:%M')}\n\n"
|
||||
"""Форматирует расписание для отправки в Telegram"""
|
||||
message = f"⚡️ <b>Графік відключень світла</b>\n"
|
||||
message += f"🕐 Оновлено: {datetime.now().strftime('%d.%m.%Y %H:%M')}\n\n"
|
||||
|
||||
start_date = datetime.now()
|
||||
|
||||
@@ -155,138 +155,142 @@ def format_schedule_message(schedule, days_to_show=2):
|
||||
continue
|
||||
|
||||
date_str = (start_date + timedelta(days=day)).strftime('%d.%m')
|
||||
day_name = "Сьогодні" if day == 0 else "Завтра"
|
||||
day_name = "🌅 Сьогодні" if day == 0 else "🌄 Завтра"
|
||||
|
||||
message += f"{'─' * 32}\n"
|
||||
message += f"📅 <b>{day_name} ({date_str})</b>\n"
|
||||
message += f"{'─' * 32}\n\n"
|
||||
|
||||
# Группируем последовательные отключения
|
||||
disconnections = []
|
||||
i = 0
|
||||
while i < len(day_blocks):
|
||||
block = day_blocks[i]
|
||||
first = block["first_half"]
|
||||
second = block["second_half"]
|
||||
current_time = None
|
||||
current_status = None
|
||||
current_confirmed = None
|
||||
current_queue = None
|
||||
start_time = None
|
||||
|
||||
# Проверяем статус отключения
|
||||
first_off = first["status"] == "off"
|
||||
second_off = second["status"] == "off"
|
||||
disconnection_periods = []
|
||||
|
||||
if first_off or second_off:
|
||||
start_time = f"{block['hour']:02d}:00" if first_off else f"{block['hour']:02d}:30"
|
||||
for i, block in enumerate(day_blocks):
|
||||
hour = block["hour"]
|
||||
|
||||
# Ищем конец периода отключения
|
||||
j = i
|
||||
while j < len(day_blocks):
|
||||
b = day_blocks[j]
|
||||
f = b["first_half"]
|
||||
s = b["second_half"]
|
||||
# Проверяем обе половины часа
|
||||
for half_idx, half in enumerate([block["first_half"], block["second_half"]]):
|
||||
time_str = f"{hour:02d}:00" if half_idx == 0 else f"{hour:02d}:30"
|
||||
|
||||
# Если обе половины не отключены, прерываем
|
||||
if f["status"] != "off" and s["status"] != "off":
|
||||
break
|
||||
|
||||
j += 1
|
||||
|
||||
# Определяем конечное время
|
||||
if j > 0:
|
||||
prev_block = day_blocks[j-1]
|
||||
if prev_block["second_half"]["status"] == "off":
|
||||
end_time = f"{prev_block['hour']+1:02d}:00"
|
||||
if half["status"] == "off":
|
||||
if current_status != "off":
|
||||
# Начало нового периода отключения
|
||||
start_time = time_str
|
||||
current_confirmed = half["confirmed"]
|
||||
current_queue = half["queue"]
|
||||
current_status = "off"
|
||||
else:
|
||||
end_time = f"{prev_block['hour']:02d}:30"
|
||||
if current_status == "off":
|
||||
# Конец периода отключения
|
||||
icon = "🔴" if current_confirmed is True else "🟠"
|
||||
queue_text = f" • Черга {current_queue}" if current_queue else ""
|
||||
disconnection_periods.append(f"{icon} <code>{start_time} - {time_str}</code>{queue_text}")
|
||||
current_status = half["status"]
|
||||
|
||||
# Если день закончился на отключении
|
||||
if current_status == "off":
|
||||
icon = "🔴" if current_confirmed is True else "🟠"
|
||||
queue_text = f" • Черга {current_queue}" if current_queue else ""
|
||||
next_hour = (day_blocks[-1]["hour"] + 1) % 24
|
||||
end_time = f"{next_hour:02d}:00"
|
||||
disconnection_periods.append(f"{icon} <code>{start_time} - {end_time}</code>{queue_text}")
|
||||
|
||||
# Выводим результат
|
||||
if disconnection_periods:
|
||||
for period in disconnection_periods:
|
||||
message += period + "\n"
|
||||
else:
|
||||
end_time = f"{block['hour']+1:02d}:00"
|
||||
|
||||
# Получаем информацию о черге и подтверждении
|
||||
queue = first["queue"] or second["queue"]
|
||||
confirmed = first["confirmed"] if first_off else second["confirmed"]
|
||||
|
||||
icon = "🔴" if confirmed is True else "🟠" if confirmed is False else "🔴"
|
||||
|
||||
disconnections.append({
|
||||
"time": f"{start_time}-{end_time}",
|
||||
"icon": icon,
|
||||
"queue": queue
|
||||
})
|
||||
|
||||
i = j if j > i else i + 1
|
||||
else:
|
||||
i += 1
|
||||
|
||||
# Выводим сгруппированные отключения
|
||||
if disconnections:
|
||||
for d in disconnections:
|
||||
queue_info = f" Ч{d['queue']}" if d['queue'] else ""
|
||||
message += f"{d['icon']} {d['time']}{queue_info}\n"
|
||||
else:
|
||||
message += "🟢 Відключень немає\n"
|
||||
message += "🟢 <b>Відключень немає!</b>\n"
|
||||
|
||||
message += "\n"
|
||||
|
||||
message += "<i>🔴 підтверджено • 🟠 можливо</i>"
|
||||
message += f"{'─' * 32}\n"
|
||||
message += "💡 <i>Легенда:</i>\n"
|
||||
message += "🔴 — Підтверджено\n"
|
||||
message += "🟠 — Можливо\n"
|
||||
message += "🟢 — Світло є\n"
|
||||
|
||||
return message
|
||||
|
||||
|
||||
def format_single_day_schedule(schedule, day_num):
|
||||
"""Форматирует расписание для одного дня (еще более компактно)"""
|
||||
"""Форматирует расписание для одного дня"""
|
||||
start_date = datetime.now()
|
||||
date_str = (start_date + timedelta(days=day_num)).strftime('%d.%m')
|
||||
day_name = "Сьогодні" if day_num == 0 else "Завтра"
|
||||
day_name = "🌅 Сьогодні" if day_num == 0 else "🌄 Завтра"
|
||||
|
||||
message = f"⚡️ <b>{day_name} ({date_str})</b>\n\n"
|
||||
message = f"{'─' * 32}\n"
|
||||
message += f"📅 <b>{day_name} ({date_str})</b>\n"
|
||||
message += f"{'─' * 32}\n\n"
|
||||
|
||||
day_blocks = [b for b in schedule if b["day"] == day_num]
|
||||
if not day_blocks:
|
||||
return message + "❓ Немає даних"
|
||||
return message + "❓ <i>Немає даних</i>"
|
||||
|
||||
# Создаем визуальную шкалу времени
|
||||
message += "⏰ <b>Часова шкала:</b>\n\n"
|
||||
|
||||
# Выводим по 4 часа в строке для читаемости
|
||||
for start_hour in range(0, 24, 4):
|
||||
line = ""
|
||||
for h in range(start_hour, min(start_hour + 4, 24)):
|
||||
block = day_blocks[h] if h < len(day_blocks) else None
|
||||
if not block:
|
||||
line += f"{h:02d}|❓❓ "
|
||||
continue
|
||||
|
||||
# Создаем почасовой график одной строкой
|
||||
hourly = []
|
||||
for block in day_blocks:
|
||||
first = block["first_half"]
|
||||
second = block["second_half"]
|
||||
|
||||
def get_short_icon(half_data):
|
||||
def get_icon(half_data):
|
||||
if half_data["status"] == "off":
|
||||
return "●" if half_data["confirmed"] is True else "○"
|
||||
return "🔴" if half_data["confirmed"] is True else "🟠"
|
||||
elif half_data["status"] == "on":
|
||||
return "·"
|
||||
return "?"
|
||||
return "🟢"
|
||||
return "❓"
|
||||
|
||||
hour_str = f"{block['hour']:02d}"
|
||||
first_icon = get_short_icon(first)
|
||||
second_icon = get_short_icon(second)
|
||||
hourly.append(f"{hour_str}|{first_icon}{second_icon}")
|
||||
first_icon = "●" if first["status"] == "off" else "·"
|
||||
second_icon = "●" if second["status"] == "off" else "·"
|
||||
|
||||
# Выводим по 6 часов в строке
|
||||
for i in range(0, len(hourly), 6):
|
||||
chunk = hourly[i:i+6]
|
||||
message += " ".join(chunk) + "\n"
|
||||
line += f"<code>{h:02d}|{first_icon}{second_icon}</code> "
|
||||
|
||||
message += "\n<i>● підтв • ○ можл • · світло</i>\n\n"
|
||||
message += line + "\n"
|
||||
|
||||
# Добавляем список отключений
|
||||
disconnections = []
|
||||
message += "\n<i>● = відключено, · = світло</i>\n\n"
|
||||
|
||||
# Детальний список відключень
|
||||
message += "📋 <b>Детально:</b>\n\n"
|
||||
|
||||
has_disconnections = False
|
||||
for block in day_blocks:
|
||||
hour = block["hour"]
|
||||
first = block["first_half"]
|
||||
second = block["second_half"]
|
||||
|
||||
if first["status"] == "off":
|
||||
has_disconnections = True
|
||||
icon = "🔴" if first["confirmed"] is True else "🟠"
|
||||
time = f"{block['hour']:02d}:00-30"
|
||||
queue = f" Ч{first['queue']}" if first['queue'] else ""
|
||||
disconnections.append(f"{icon} {time}{queue}")
|
||||
status = "підтв." if first["confirmed"] is True else "можл."
|
||||
queue = f"Ч{first['queue']}" if first['queue'] else "—"
|
||||
message += f"{icon} <code>{hour:02d}:00-{hour:02d}:30</code> • {status} • {queue}\n"
|
||||
|
||||
if second["status"] == "off":
|
||||
has_disconnections = True
|
||||
icon = "🔴" if second["confirmed"] is True else "🟠"
|
||||
time = f"{block['hour']:02d}:30-{block['hour']+1:02d}:00"
|
||||
queue = f" Ч{second['queue']}" if second['queue'] else ""
|
||||
disconnections.append(f"{icon} {time}{queue}")
|
||||
status = "підтв." if second["confirmed"] is True else "можл."
|
||||
queue = f"Ч{second['queue']}" if second['queue'] else "—"
|
||||
message += f"{icon} <code>{hour:02d}:30-{hour+1:02d}:00</code> • {status} • {queue}\n"
|
||||
|
||||
if disconnections:
|
||||
message += "<b>Відключення:</b>\n" + "\n".join(disconnections)
|
||||
else:
|
||||
message += "🟢 <b>Відключень немає</b>"
|
||||
if not has_disconnections:
|
||||
message += "🟢 <b>Відключень немає!</b>\n"
|
||||
|
||||
message += f"\n{'─' * 32}\n"
|
||||
message += "<i>🔴 підтв. • 🟠 можл. • 🟢 світло</i>"
|
||||
|
||||
return message
|
||||
|
||||
@@ -335,8 +339,7 @@ async def check_schedule():
|
||||
message = format_schedule_message(new_schedule, days_to_show=2)
|
||||
|
||||
if last_schedule is None:
|
||||
# Первый запуск
|
||||
await send_to_all_users(f"✨ <b>Бот запущено!</b>\n\n{message}")
|
||||
pass # Ничего не делать, если изменений нет
|
||||
else:
|
||||
# Изменения в графике
|
||||
await send_to_all_users(f"🔄 <b>Графік оновлено!</b>\n\n{message}")
|
||||
@@ -530,7 +533,22 @@ async def cmd_check(message: Message):
|
||||
return
|
||||
|
||||
await message.answer("🔄 Перевіряю графік...", reply_markup=get_main_keyboard())
|
||||
await check_schedule()
|
||||
|
||||
# Выполняем проверку и отправляем результат
|
||||
try:
|
||||
html = get_voe_html(VOE_CITY_ID, VOE_STREET_ID, VOE_HOUSE_ID)
|
||||
new_schedule = parse_html(html)
|
||||
|
||||
if schedules_differ(last_schedule, new_schedule):
|
||||
result_message = "✅ <b>Знайдено зміни в графіку!</b>\n\n"
|
||||
result_message += format_schedule_message(new_schedule, days_to_show=2)
|
||||
await message.answer(result_message, parse_mode="HTML", reply_markup=get_main_keyboard())
|
||||
else:
|
||||
result_message = "✅ <b>Графік без змін</b>\n\n"
|
||||
result_message += format_schedule_message(new_schedule, days_to_show=2)
|
||||
await message.answer(result_message, parse_mode="HTML", reply_markup=get_main_keyboard())
|
||||
except Exception as e:
|
||||
await message.answer(f"❌ Помилка при перевірці: {str(e)}", reply_markup=get_main_keyboard())
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
Reference in New Issue
Block a user