Merge remote-tracking branch 'origin/master'

This commit is contained in:
Andrey Sazonov 2025-10-05 21:48:06 +03:00
commit 5aaeeae78e
2 changed files with 22 additions and 4 deletions

11
bot.py
View File

@ -36,6 +36,7 @@ UPDATE_INTERVAL = 300 # 5 минут
bot = Bot(token=BOT_TOKEN) bot = Bot(token=BOT_TOKEN)
dp = Dispatcher(bot) dp = Dispatcher(bot)
async def periodic_update(): async def periodic_update():
while True: while True:
logger.info("Запуск автоматического обновления данных...") logger.info("Запуск автоматического обновления данных...")
@ -46,6 +47,7 @@ async def periodic_update():
logger.error(f"Ошибка при автоматическом обновлении: {e}") logger.error(f"Ошибка при автоматическом обновлении: {e}")
await asyncio.sleep(UPDATE_INTERVAL) await asyncio.sleep(UPDATE_INTERVAL)
@dp.message_handler(commands='start') @dp.message_handler(commands='start')
async def cmd_start(message: types.Message): async def cmd_start(message: types.Message):
buttons = ['Плановые', 'Внерегламентные', 'Аварийные', 'Информация'] buttons = ['Плановые', 'Внерегламентные', 'Аварийные', 'Информация']
@ -53,6 +55,7 @@ async def cmd_start(message: types.Message):
keyboard.add(*buttons) keyboard.add(*buttons)
await message.answer('Выберите тип отключений:', reply_markup=keyboard) await message.answer('Выберите тип отключений:', reply_markup=keyboard)
async def send_file_content(message: types.Message, file_path: Path, empty_msg: str, log_msg: str): async def send_file_content(message: types.Message, file_path: Path, empty_msg: str, log_msg: str):
await message.answer("Обновляю...") await message.answer("Обновляю...")
@ -74,6 +77,7 @@ async def send_file_content(message: types.Message, file_path: Path, empty_msg:
f.write(log_entry) f.write(log_entry)
logger.info(f"Пользователь {username} запросил {log_msg}") logger.info(f"Пользователь {username} запросил {log_msg}")
@dp.message_handler(Text(equals='Плановые')) @dp.message_handler(Text(equals='Плановые'))
async def plan(message: types.Message): async def plan(message: types.Message):
await send_file_content( await send_file_content(
@ -83,6 +87,7 @@ async def plan(message: types.Message):
"плановым отключениям" "плановым отключениям"
) )
@dp.message_handler(Text(equals='Внерегламентные')) @dp.message_handler(Text(equals='Внерегламентные'))
async def vnereglament(message: types.Message): async def vnereglament(message: types.Message):
await send_file_content( await send_file_content(
@ -92,6 +97,7 @@ async def vnereglament(message: types.Message):
"внерегламентным отключениям" "внерегламентным отключениям"
) )
@dp.message_handler(Text(equals='Аварийные')) @dp.message_handler(Text(equals='Аварийные'))
async def avar(message: types.Message): async def avar(message: types.Message):
await send_file_content( await send_file_content(
@ -101,6 +107,7 @@ async def avar(message: types.Message):
"аварийным отключениям" "аварийным отключениям"
) )
@dp.message_handler(Text(equals='Информация')) @dp.message_handler(Text(equals='Информация'))
async def info(message: types.Message): async def info(message: types.Message):
await message.answer( await message.answer(
@ -109,19 +116,23 @@ async def info(message: types.Message):
"📩 Вопросы и предложения: @pikusQQ" "📩 Вопросы и предложения: @pikusQQ"
) )
@dp.message_handler() @dp.message_handler()
async def fallback(message: types.Message): async def fallback(message: types.Message):
await message.answer("Нажмите /start для начала работы.") await message.answer("Нажмите /start для начала работы.")
async def on_startup(dp): async def on_startup(dp):
await bot.set_webhook(WEBHOOK_URL) await bot.set_webhook(WEBHOOK_URL)
asyncio.create_task(periodic_update()) asyncio.create_task(periodic_update())
logger.info(f"Webhook установлен на {WEBHOOK_URL}. Фоновое обновление запущено.") logger.info(f"Webhook установлен на {WEBHOOK_URL}. Фоновое обновление запущено.")
async def on_shutdown(dp): async def on_shutdown(dp):
await bot.delete_webhook() await bot.delete_webhook()
logger.info("Webhook удалён") logger.info("Webhook удалён")
if __name__ == '__main__': if __name__ == '__main__':
executor.start_webhook( executor.start_webhook(
dispatcher=dp, dispatcher=dp,

11
main.py
View File

@ -45,6 +45,7 @@ PLAN_FILE = Path("plan.txt")
VN_FILE = Path("vnereglament.txt") VN_FILE = Path("vnereglament.txt")
AVAR_FILE = Path("avar.txt") AVAR_FILE = Path("avar.txt")
def clean_street(street: str) -> str: def clean_street(street: str) -> str:
if not street: if not street:
return "" return ""
@ -81,13 +82,15 @@ def clean_street(street: str) -> str:
return '\n'.join(formatted) if formatted else "[Нет данных]" return '\n'.join(formatted) if formatted else "[Нет данных]"
def format_time(dt_str: str) -> str: def format_time(dt_str: str) -> str:
try: try:
dt = datetime.fromisoformat(dt_str.replace('Z', '+00:00')) dt = datetime.fromisoformat(dt_str.replace('Z', '+00:00'))
return dt.strftime('%d.%m.%Y %H:%M') return dt.strftime('%d.%m.%Y %H:%M')
except: except Exception:
return dt_str.replace('T', ' ') return dt_str.replace('T', ' ')
def parse_and_save(data, file_path: Path, mode: str): def parse_and_save(data, file_path: Path, mode: str):
if not data or data == 0: if not data or data == 0:
file_path.write_text("[Нет отключений]", encoding='utf-8') file_path.write_text("[Нет отключений]", encoding='utf-8')
@ -101,7 +104,7 @@ def parse_and_save(data, file_path: Path, mode: str):
street = clean_street(item.get("DisconnectionObject", "")) street = clean_street(item.get("DisconnectionObject", ""))
time_down = format_time(item.get("DisconnectionDateTime", "")) time_down = format_time(item.get("DisconnectionDateTime", ""))
time_up = format_time(item.get("EnergyOnPlanningDateTime", "")) time_up = format_time(item.get("EnergyOnPlanningDateTime", ""))
lines.append(f"{street}\nОтключение: {time_down}{time_up}\n{'' * 30}") lines.append(f"{street}\nВремя: с {time_down} по {time_up}\n{'-' * 30}")
elif mode == 'avar': elif mode == 'avar':
street = clean_street(item.get("StreetHome", "")) street = clean_street(item.get("StreetHome", ""))
time_up = format_time(item.get("ScheduledTimeRemoval", "")) time_up = format_time(item.get("ScheduledTimeRemoval", ""))
@ -109,6 +112,7 @@ def parse_and_save(data, file_path: Path, mode: str):
file_path.write_text('\n'.join(lines), encoding='utf-8') file_path.write_text('\n'.join(lines), encoding='utf-8')
def get_plan(): def get_plan():
try: try:
r = requests.get(URL_PLAN, headers=HEADERS, verify=False, timeout=15) r = requests.get(URL_PLAN, headers=HEADERS, verify=False, timeout=15)
@ -123,6 +127,7 @@ def get_plan():
logger.error(f"Ответ: {r.text[:500]}") logger.error(f"Ответ: {r.text[:500]}")
PLAN_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8') PLAN_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8')
def get_vnereglament(): def get_vnereglament():
try: try:
r = requests.get(URL_VNEREGLAMENT, headers=HEADERS, verify=False, timeout=15) r = requests.get(URL_VNEREGLAMENT, headers=HEADERS, verify=False, timeout=15)
@ -137,6 +142,7 @@ def get_vnereglament():
logger.error(f"Ответ: {r.text[:500]}") logger.error(f"Ответ: {r.text[:500]}")
VN_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8') VN_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8')
def get_avar(): def get_avar():
try: try:
r = requests.get(URL_AVAR, headers=HEADERS, verify=False, timeout=15) r = requests.get(URL_AVAR, headers=HEADERS, verify=False, timeout=15)
@ -151,6 +157,7 @@ def get_avar():
logger.error(f"Ответ: {r.text[:500]}") logger.error(f"Ответ: {r.text[:500]}")
AVAR_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8') AVAR_FILE.write_text("[Ошибка загрузки данных]", encoding='utf-8')
def start_parser(): def start_parser():
get_plan() get_plan()
get_vnereglament() get_vnereglament()