Files
myfirstprogram/addons/x_days_to/handlers.py
T

124 lines
5.0 KiB
Python

import asyncio
import aiosqlite
from datetime import datetime
from logging import getLogger
from aiogram import Dispatcher, Bot
from config import Config
from models.state import BotState
from utils.antispam import save_message
logger = getLogger(__name__)
def register_handlers(dp: Dispatcher, state: BotState, bot: Bot) -> int:
async def init_db():
if Config.DISABLE_STORAGE:
return
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
await db.execute("""
CREATE TABLE IF NOT EXISTS days_to_new_year (
user_id INTEGER PRIMARY KEY,
days INTEGER NOT NULL,
timestamp TEXT NOT NULL
)
""")
await db.commit()
logger.info("База данных инициализирована")
async def save_days_to_db(user_id: int, days: int):
if Config.DISABLE_STORAGE:
return
logger.debug(f"Сохраняем user_id={user_id}, days={days}")
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
await db.execute("""
INSERT OR REPLACE INTO days_to_new_year (user_id, days, timestamp)
VALUES (?, ?, ?)
""", (int(user_id), int(days), datetime.now().strftime("%Y-%m-%d %H:%M:%S")))
await db.commit()
logger.info(f"Запись сохранена: user_id={user_id}, days={days}")
async def get_last_days(user_id: int) -> int | None:
if Config.DISABLE_STORAGE:
return None
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
async with db.execute(
"SELECT days FROM days_to_new_year WHERE user_id = ?", (int(user_id),)
) as cursor:
row = await cursor.fetchone()
return row[0] if row else None
async def days_to_new_years() -> int:
now = datetime.now()
new_year = datetime(now.year + 1, 1, 1)
delta = (new_year - now).days
logger.debug(f"До Нового года осталось {delta} дней")
return delta
async def days_to_summer() -> int:
"""Считает дни до 1 июня текущего года (или следующего, если уже лето прошло)."""
now = datetime.now()
summer = datetime(now.year, 6, 1)
if now >= summer:
summer = datetime(now.year + 1, 6, 1)
delta = (summer - now).days
logger.debug(f"До лета осталось {delta} дней")
return delta
async def days_to_session() -> int:
"""Считает дни до 1 июня текущего года (или следующего, если уже лето прошло)."""
now = datetime.now()
summer = datetime(2026, 7, 6)
if now >= summer:
logger.warning("days_to_session")
delta = (summer - now).days
logger.debug(f"До Сессии осталось {delta} дней")
return delta
async def send_days_to_new_years(user_id: int):
days_ny = await days_to_new_years()
days_summer = await days_to_summer()
days_session = await days_to_session()
last_days = await get_last_days(user_id)
if last_days == days_ny:
logger.info(f"user_id={user_id}: запись уже есть ({days_ny} дней), пропускаем")
return
await save_days_to_db(user_id, days_ny)
events = [
("🌞 До лета", days_summer),
("📚 До конца сессии", days_session),
("🎄 До Нового года", days_ny),
]
# сортировка по числу дней (от меньшего к большему)
events_sorted = sorted(events, key=lambda x: x[1])
message_text = "\n".join([f"{emoji} осталось {days} дней!" for emoji, days in events_sorted])
for chat_id in Config.CHAT_IDS:
try:
logger.info(f"Отправляем сообщение в чат {chat_id} для user_id={user_id}")
await bot.send_message(chat_id, message_text)
except Exception as e:
logger.error(f"Ошибка при отправке в чат {chat_id}: {e}")
async def periodic_task():
await init_db()
while True:
logger.info("Запуск цикла periodic_task")
for uid in Config.CHAT_IDS:
try:
msg = await send_days_to_new_years(int(uid))
if msg:
save_message(msg.chat.id, msg.message_id)
except Exception as e:
logger.exception(f"Ошибка при обработке uid={uid}: {e}")
logger.info("Завершён цикл periodic_task, спим 24 часов")
await asyncio.sleep(86400) # каждые 24 часов
asyncio.create_task(periodic_task())
return 0