146 lines
4.7 KiB
Python
146 lines
4.7 KiB
Python
import asyncio
|
||
import logging
|
||
import os
|
||
from pathlib import Path
|
||
|
||
import pytz
|
||
from datetime import datetime
|
||
from aiogram import Bot, Dispatcher, executor, types
|
||
from aiogram.dispatcher.filters import Text
|
||
from dotenv import load_dotenv
|
||
|
||
from main import start_parser
|
||
|
||
load_dotenv()
|
||
|
||
logging.basicConfig(
|
||
level=logging.INFO,
|
||
filename="logs/bot.log",
|
||
format="%(asctime)s - %(module)s - %(levelname)s - %(funcName)s: %(lineno)d - %(message)s",
|
||
datefmt='%H:%M:%S',
|
||
)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
BOT_TOKEN = os.getenv("BOT_TOKEN")
|
||
WEBHOOK_URL = os.getenv("WEBHOOK_URL")
|
||
|
||
if not BOT_TOKEN:
|
||
raise ValueError("❌ Переменная BOT_TOKEN не задана в .env")
|
||
if not WEBHOOK_URL:
|
||
raise ValueError("❌ Переменная WEBHOOK_URL не задана в .env")
|
||
|
||
TZ = pytz.timezone('Europe/Moscow')
|
||
USER_LOG = Path("logs/users.log")
|
||
UPDATE_INTERVAL = 300
|
||
|
||
bot = Bot(token=BOT_TOKEN)
|
||
dp = Dispatcher(bot)
|
||
|
||
|
||
async def periodic_update():
|
||
while True:
|
||
logger.info("Запуск автоматического обновления данных...")
|
||
try:
|
||
start_parser()
|
||
logger.info("Автоматическое обновление завершено")
|
||
except Exception as e:
|
||
logger.error(f"Ошибка при автоматическом обновлении: {e}")
|
||
await asyncio.sleep(UPDATE_INTERVAL)
|
||
|
||
|
||
@dp.message_handler(commands='start')
|
||
async def cmd_start(message: types.Message):
|
||
buttons = ['Плановые', 'Внерегламентные', 'Аварийные', 'Информация']
|
||
keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
|
||
keyboard.add(*buttons)
|
||
await message.answer('Выберите тип отключений:', reply_markup=keyboard)
|
||
|
||
|
||
async def send_file_content(message: types.Message, file_path: Path, empty_msg: str, log_msg: str):
|
||
await message.answer("Обновляю...")
|
||
|
||
if not file_path.exists() or file_path.stat().st_size == 0:
|
||
await message.answer(empty_msg)
|
||
else:
|
||
text = file_path.read_text(encoding='utf-8')
|
||
if len(text) > 4095:
|
||
for i in range(0, len(text), 4095):
|
||
await message.answer(text[i:i + 4095])
|
||
else:
|
||
await message.answer(text)
|
||
|
||
now = datetime.now(TZ).strftime('%d/%m/%Y %H:%M')
|
||
username = message.from_user.username or f"id{message.from_user.id}"
|
||
log_entry = f"{now} t.me/{username} получил инфу по {log_msg}.\n"
|
||
USER_LOG.parent.mkdir(exist_ok=True)
|
||
with USER_LOG.open('a', encoding='utf-8') as f:
|
||
f.write(log_entry)
|
||
logger.info(f"Пользователь {username} запросил {log_msg}")
|
||
|
||
|
||
@dp.message_handler(Text(equals='Плановые'))
|
||
async def plan(message: types.Message):
|
||
await send_file_content(
|
||
message,
|
||
Path("plan.txt"),
|
||
"[Нет плановых отключений]",
|
||
"плановым отключениям"
|
||
)
|
||
|
||
|
||
@dp.message_handler(Text(equals='Внерегламентные'))
|
||
async def vnereglament(message: types.Message):
|
||
await send_file_content(
|
||
message,
|
||
Path("vnereglament.txt"),
|
||
"[Нет внерегламентных отключений]",
|
||
"внерегламентным отключениям"
|
||
)
|
||
|
||
|
||
@dp.message_handler(Text(equals='Аварийные'))
|
||
async def avar(message: types.Message):
|
||
await send_file_content(
|
||
message,
|
||
Path("avar.txt"),
|
||
"[Нет аварийных отключений]",
|
||
"аварийным отключениям"
|
||
)
|
||
|
||
|
||
@dp.message_handler(Text(equals='Информация'))
|
||
async def info(message: types.Message):
|
||
await message.answer(
|
||
"ℹ️ Информация МРСК Белгород по отключениям эл-ва (v2)\n\n"
|
||
"✅ Данные обновляются автоматически каждые 5 минут.\n"
|
||
"📩 Вопросы и предложения: @pikusQQ"
|
||
)
|
||
|
||
|
||
@dp.message_handler()
|
||
async def fallback(message: types.Message):
|
||
await message.answer("Нажмите /start для начала работы.")
|
||
|
||
|
||
async def on_startup(dp):
|
||
await bot.set_webhook(WEBHOOK_URL)
|
||
asyncio.create_task(periodic_update())
|
||
logger.info(f"Webhook установлен на {WEBHOOK_URL}. Фоновое обновление запущено.")
|
||
|
||
|
||
async def on_shutdown(dp):
|
||
await bot.delete_webhook()
|
||
logger.info("Webhook удалён")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
executor.start_webhook(
|
||
dispatcher=dp,
|
||
webhook_path='',
|
||
on_startup=on_startup,
|
||
on_shutdown=on_shutdown,
|
||
skip_updates=True,
|
||
host='0.0.0.0',
|
||
port=5000,
|
||
)
|