Files
Solo_bot/handlers/notifications/engine.py
T

165 lines
6.4 KiB
Python

from __future__ import annotations
import asyncio
from datetime import datetime
import pytz
from aiogram import Bot
from sqlalchemy.ext.asyncio import async_sessionmaker
from config import (
NOTIFICATION_TIME,
NOTIFY_10H_ENABLED,
NOTIFY_10H_HOURS,
NOTIFY_24H_ENABLED,
NOTIFY_24H_HOURS,
NOTIFY_DELETE_DELAY,
NOTIFY_DELETE_KEY,
NOTIFY_HOT_LEADS,
NOTIFY_INACTIVE_TRAFFIC,
NOTIFY_RENEW,
NOTIFY_RENEW_EXPIRED,
TRIAL_TIME_DISABLE,
)
from core.bootstrap import MODES_CONFIG, NOTIFICATIONS_CONFIG
from handlers.notifications.bulk import create_bulk_updates, execute_bulk_updates
from handlers.notifications.context import NotificationContext
from handlers.notifications.preload import preload_with_fallback
from handlers.notifications.processors.expired import process_expired_keys
from handlers.notifications.processors.expiring import process_expiring_keys
from handlers.notifications.processors.hot_leads import process_hot_leads
from handlers.notifications.processors.inactive_trial import process_inactive_trial
from handlers.notifications.processors.zero_traffic import process_zero_traffic
from hooks.hooks import run_hooks
from logger import logger
from middlewares.session import wrap_session
moscow_tz = pytz.timezone("Europe/Moscow")
notification_lock = asyncio.Lock()
async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker):
while True:
interval = int(NOTIFICATIONS_CONFIG.get("BASE_NOTIFICATION_MINUTE", NOTIFICATION_TIME))
if notification_lock.locked():
logger.warning("Уведомления уже выполняются. Пропуск...")
await asyncio.sleep(interval)
continue
async with notification_lock:
try:
await _run_cycle(bot, sessionmaker)
except Exception as error:
logger.error(f"Ошибка в periodic_notifications: {error}")
await asyncio.sleep(interval)
async def _run_cycle(bot: Bot, sessionmaker: async_sessionmaker):
start_time = datetime.now()
current_time = int(datetime.now(moscow_tz).timestamp() * 1000)
async with sessionmaker() as preload_session:
keys, preload_data = await preload_with_fallback(preload_session)
if not keys and not preload_data:
logger.info("Нет данных для обработки")
return
bulk_updates = create_bulk_updates()
async with sessionmaker() as session:
session = wrap_session(session, sessionmaker)
ctx = NotificationContext(
bot=bot,
session=session,
current_time=current_time,
preload_data=preload_data,
bulk_updates=bulk_updates,
)
trial_disabled = bool(MODES_CONFIG.get("TRIAL_TIME_DISABLED", TRIAL_TIME_DISABLE))
notify_24_enabled = bool(NOTIFICATIONS_CONFIG.get("EXPIRY_24H_ENABLED", NOTIFY_24H_ENABLED))
notify_24_hours = int(NOTIFICATIONS_CONFIG.get("EXPIRY_24H_BEFORE_HOURS", NOTIFY_24H_HOURS))
notify_10_enabled = bool(NOTIFICATIONS_CONFIG.get("EXPIRY_10H_ENABLED", NOTIFY_10H_ENABLED))
notify_10_hours = int(NOTIFICATIONS_CONFIG.get("EXPIRY_10H_BEFORE_HOURS", NOTIFY_10H_HOURS))
renew_enabled = bool(NOTIFICATIONS_CONFIG.get("RENEW_ENABLED", NOTIFY_RENEW))
renew_expired_enabled = bool(NOTIFICATIONS_CONFIG.get("RENEW_EXPIRED_ENABLED", NOTIFY_RENEW_EXPIRED))
delete_key_enabled = bool(NOTIFICATIONS_CONFIG.get("DELETE_KEY_ENABLED", NOTIFY_DELETE_KEY))
delete_delay = int(NOTIFICATIONS_CONFIG.get("DELETE_KEY_DELAY_MINUTES", NOTIFY_DELETE_DELAY))
inactive_traffic = bool(NOTIFICATIONS_CONFIG.get("INACTIVE_TRAFFIC_ENABLED", NOTIFY_INACTIVE_TRAFFIC))
hot_leads_enabled = bool(NOTIFICATIONS_CONFIG.get("HOT_LEADS_ENABLED", NOTIFY_HOT_LEADS))
if not trial_disabled:
try:
await process_inactive_trial(bot, session, sessionmaker=sessionmaker)
except Exception as e:
logger.error(f"Ошибка inactive_trial: {e}")
if notify_24_enabled:
try:
await process_expiring_keys(
ctx, keys,
min_hours=notify_10_hours if notify_10_enabled else 0,
max_hours=notify_24_hours,
notify_type="key_24h",
photo="notify_24h.jpg",
notify_renew_enabled=renew_enabled,
sessionmaker=sessionmaker,
)
except Exception as e:
logger.error(f"Ошибка expiring 24h: {e}")
if notify_10_enabled:
try:
await process_expiring_keys(
ctx, keys,
min_hours=0,
max_hours=notify_10_hours,
notify_type="key_10h",
photo="notify_10h.jpg",
notify_renew_enabled=renew_enabled,
sessionmaker=sessionmaker,
)
except Exception as e:
logger.error(f"Ошибка expiring 10h: {e}")
try:
await process_expired_keys(
ctx, keys,
notify_renew_expired=renew_expired_enabled,
notify_delete_key=delete_key_enabled,
delete_delay_minutes=delete_delay,
)
except Exception as e:
logger.error(f"Ошибка expired: {e}")
if inactive_traffic:
try:
await process_zero_traffic(bot, session, current_time, keys)
except Exception as e:
logger.error(f"Ошибка zero_traffic: {e}")
try:
await run_hooks("periodic_notifications", bot=bot, session=session, keys=keys)
except Exception as e:
logger.error(f"Ошибка хуков: {e}")
if hot_leads_enabled:
try:
await process_hot_leads(bot, session)
except Exception as e:
logger.error(f"Ошибка hot_leads: {e}")
if bulk_updates:
bulk_start = datetime.now()
await execute_bulk_updates(session, bulk_updates)
bulk_time = (datetime.now() - bulk_start).total_seconds()
logger.info(f"Bulk за {bulk_time:.2f}s")
total_time = (datetime.now() - start_time).total_seconds()
logger.info(f"Уведомления завершены за {total_time:.2f}s")