Ручная проверка в админке (monitoring.py):
- Новая кнопка "📊 Проверка трафика" в меню мониторинга
- Проверяет всех юзеров с активной подпиской
- Показывает результат: сколько проверено, сколько превышений
- Отправляет уведомления админам при превышении
Изменения в traffic_monitoring_service.py:
1. Добавлен импорт get_db — для получения сессии БД внутри цикла
2. Добавлен set_bot() — для установки бота
3. Изменён start_monitoring() — не требует db и bot как параметры
4. Добавлен кэш уведомлений — защита от спама (1 уведомление в 24ч на юзера)
5. Добавлена очистка кэша — удаляет записи старше 48ч
Изменения в main.py:
1. Импорт traffic_monitoring_scheduler
2. Переменная traffic_monitoring_task
3. set_bot() при старте
4. Stage "Мониторинг трафика" с логированием интервала и порога
5. Секция "Активные фоновые сервисы" — добавлен статус
6. Перезапуск при ошибке в основном цикле
7. Остановка в блоке finally
---
Как включить
В .env на сервере:
TRAFFIC_MONITORING_ENABLED=true
TRAFFIC_THRESHOLD_GB_PER_DAY=10.0
TRAFFIC_MONITORING_INTERVAL_HOURS=1
SUSPICIOUS_NOTIFICATIONS_TOPIC_ID=14
После перезагрузки бота увидишь в логах:
📊 Мониторинг трафика
├ Интервал проверки: 1 ч
├ Порог трафика: 10.0 ГБ/сутки
└ ✅ Мониторинг трафика запущен
Add configuration options for personal cabinet:
- CABINET_ENABLED, JWT settings, CORS origins
- Email verification settings
- SMTP configuration for email sending
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Ошибка: код итерировал по строке "14,30,60,90,180,360" посимвольно,
что приводило к ValueError: invalid literal for int() with base 10: ','
Заменено на settings.get_available_subscription_periods() который
корректно парсит строку в список [14, 30, 60, 90, 180, 360].
1. app/keyboards/inline.py
- Добавлен параметр callback_data: str = "back_to_menu" в get_back_keyboard()
- Позволяет использовать кнопку "Назад" с разными callback'ами
2. app/services/admin_notification_service.py
- Добавлен тип "modem" в update_types с заголовком "📡 ИЗМЕНЕНИЕ МОД
ПРОБЛЕМА:
При таймауте после успешной авторизации чек мог быть создан на сервере
nalog.ru, но ответ не возвращался. Бот добавлял чек в очередь повторной
отправки → создавался дубликат.
РЕШЕНИЕ:
1. Разделена обработка ошибок на два этапа:
- Аутентификация не прошла → чек точно не создан → в очередь
- Таймаут при создании → чек МОГ быть создан → НЕ в очередь
2. Новая очередь `nalogo:pending_verification` для чеков требующих
ручной проверки (когда таймаут после успешной авторизации)
3. Кнопка в админке: Мониторинг → Статистика → "⚠️ Проверить (N)"
- Показывает список чеков с суммой, датой, payment_id
- "✅ Создан" — чек найден в налоговой, убираем из очереди
- "🔄 Отправить" — чек НЕ найден, отправляем повторно
- "🗑 Очистить всё" — после полной сверки с lknpd.nalog.ru
4. Таймаут увеличен с 10 до 30 секунд (NALOGO_TIMEOUT)
5. Атомарная защита от race condition через cache.setnx()
Изменённые файлы:
- app/utils/cache.py — добавлен метод setnx()
- app/services/nalogo_service.py — разделение ошибок, pending_verification
- app/services/nalogo_queue_service.py — статус pending в get_status()
- app/handlers/admin/monitoring.py — UI для ручной проверки
Исправленные файлы:
1. app/services/traffic_monitoring_service.py — удалены неиспользуемые импорты Decimal, aiohttp
2. app/services/blacklist_service.py — удалён неиспользуемый импорт re
3. app/database/crud/user.py:998 — создана отсутствующая функция get_users_with_active_subscriptions:
async def get_users_with_active_subscriptions(db: AsyncSession) -> List[User]:
3. Функция:
- Возвращает пользователей с активными подписками
- Фильтрует по remnawave_uuid IS NOT NULL (нужен для API Remnawave)
- Проверяет end_date > now и status == ACTIVE
app/database/crud/subscription.py:
Добавлен await db.flush() в create_subscription_no_commit для консистентности с create_user_no_commit:
db.add(subscription)
# Выполняем flush, чтобы получить присвоенный первичный ключ
await db.flush()
# Не коммитим сразу, оставляем для пакетной обработки
1. app/database/crud/subscription.py
Объединены функции create_pending_subscription и create_pending_trial_subscription:
- Добавлен параметр is_trial: bool = False в create_pending_subscription
- create_pending_trial_subscription теперь просто вызывает create_pending_subscription(is_trial=True)
- Сокращено ~75 строк дублированного кода
Удалён лишний импорт:
# Было внутри activate_pending_subscription:
from sqlalchemy import and_ # Удалено — уже импортирован на уровне модуля
2. app/handlers/subscription/purchase.py
Устранено дублирование функций:
- Удалены определения _calculate_simple_subscription_price() и _get_simple_subscription_payment_keyboard() (~75 строк)
- Добавлен импорт из app.handlers.simple_subscription
from app.handlers.simple_subscription import (
_calculate_simple_subscription_price,
_get_simple_subscription_payment_keyboard,
)
Итого сокращено: ~150 строк дублированного кода