Enhance schedule formatting and error handling in DTEK notification bot

v2
This commit is contained in:
2025-11-12 18:23:53 +01:00
parent c820aac02c
commit 7ca26b77a7
+121 -103
View File
@@ -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"]
# Проверяем статус отключения
first_off = first["status"] == "off"
second_off = second["status"] == "off"
if first_off or second_off:
start_time = f"{block['hour']:02d}:00" if first_off else f"{block['hour']:02d}:30"
# Ищем конец периода отключения
j = i
while j < len(day_blocks):
b = day_blocks[j]
f = b["first_half"]
s = b["second_half"]
# Если обе половины не отключены, прерываем
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"
else:
end_time = f"{prev_block['hour']:02d}:30"
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
current_time = None
current_status = None
current_confirmed = None
current_queue = None
start_time = None
# Выводим сгруппированные отключения
if disconnections:
for d in disconnections:
queue_info = f" Ч{d['queue']}" if d['queue'] else ""
message += f"{d['icon']} {d['time']}{queue_info}\n"
disconnection_periods = []
for i, block in enumerate(day_blocks):
hour = block["hour"]
# Проверяем обе половины часа
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 half["status"] == "off":
if current_status != "off":
# Начало нового периода отключения
start_time = time_str
current_confirmed = half["confirmed"]
current_queue = half["queue"]
current_status = "off"
else:
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:
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>"
# Создаем почасовой график одной строкой
hourly = []
for block in day_blocks:
first = block["first_half"]
second = block["second_half"]
# Создаем визуальную шкалу времени
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
first = block["first_half"]
second = block["second_half"]
def get_icon(half_data):
if half_data["status"] == "off":
return "🔴" if half_data["confirmed"] is True else "🟠"
elif half_data["status"] == "on":
return "🟢"
return ""
first_icon = "" if first["status"] == "off" else "·"
second_icon = "" if second["status"] == "off" else "·"
line += f"<code>{h:02d}|{first_icon}{second_icon}</code> "
def get_short_icon(half_data):
if half_data["status"] == "off":
return "" if half_data["confirmed"] is True else ""
elif half_data["status"] == "on":
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}")
message += line + "\n"
# Выводим по 6 часов в строке
for i in range(0, len(hourly), 6):
chunk = hourly[i:i+6]
message += " ".join(chunk) + "\n"
message += "\n<i>● = відключено, · = світло</i>\n\n"
message += "\n<i>● підтв • ○ можл • · світло</i>\n\n"
# Детальний список відключень
message += "📋 <b>Детально:</b>\n\n"
# Добавляем список отключений
disconnections = []
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():