diff --git a/bot.py b/bot.py
index 0c12b0f8..c7a020b7 100644
--- a/bot.py
+++ b/bot.py
@@ -1,7 +1,6 @@
from aiogram import Bot, Dispatcher, Router
from aiogram.fsm.storage.memory import MemoryStorage
-from auth import login_with_credentials
from config import API_TOKEN
bot = Bot(token=API_TOKEN)
@@ -10,7 +9,6 @@ dp = Dispatcher(bot=bot, storage=storage)
router = Router()
from handlers import key_management, keys, notifications, pay, profile, start
-from handlers.key_management import router as key_management_router
# Регистрация обработчиков
dp.include_router(start.router)
diff --git a/handlers/key_management.py b/handlers/key_management.py
index 4a1b54fd..82d3e530 100644
--- a/handlers/key_management.py
+++ b/handlers/key_management.py
@@ -19,6 +19,7 @@ from database import (add_connection, get_balance, has_active_key, store_key,
from handlers.instructions import send_instructions
from handlers.profile import process_callback_view_profile
from handlers.start import start_command
+from handlers.notifications import send_message_to_all_clients
router = Router()
@@ -113,6 +114,10 @@ async def handle_text(message: Message, state: FSMContext):
await start_command(message)
return
+ if message.text in ["/send_to_all"]:
+ await send_message_to_all_clients(message)
+ return
+
if current_state == Form.waiting_for_key_name.state:
await handle_key_name_input(message, state)
diff --git a/handlers/notifications.py b/handlers/notifications.py
index 510886f4..ddf6e637 100644
--- a/handlers/notifications.py
+++ b/handlers/notifications.py
@@ -1,13 +1,13 @@
from datetime import datetime, timedelta
import asyncpg
-from aiogram import Bot, Router
+from aiogram import Bot, Router, types
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import ( # Импортируем необходимые классы
InlineKeyboardButton, InlineKeyboardMarkup)
from bot import bot
-from config import DATABASE_URL, ADMIN_PASSWORD, ADMIN_USERNAME
+from config import DATABASE_URL, ADMIN_PASSWORD, ADMIN_USERNAME, ADMIN_ID
from client import delete_client
from auth import login_with_credentials
@@ -41,12 +41,16 @@ async def notify_expiring_keys(bot: Bot):
# Создаем клавиатуру с выбором тарифов
keyboard = InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(text='1 месяц (100 руб.)', callback_data=f'renew_plan|1|{record["client_id"]}')],
- [InlineKeyboardButton(text='3 месяца (250 руб.)', callback_data=f'renew_plan|3|{record["client_id"]}')],
+ [InlineKeyboardButton(text='3 месяца (285 руб.)', callback_data=f'renew_plan|3|{record["client_id"]}')],
[InlineKeyboardButton(text='Пополнить баланс', callback_data='replenish_balance')]
])
- message = f"Ваш ключ {email} истечет через {hours_left} часов ({expiry_date}). Пожалуйста, продлите его."
- await bot.send_message(chat_id=tg_id, text=message, parse_mode='HTML', reply_markup=keyboard)
+ message = f"Ваш ключ {email} истечет и будет удален через {hours_left} часов ({expiry_date}). Пожалуйста, продлите его."
+
+ try:
+ await bot.send_message(chat_id=tg_id, text=message, parse_mode='HTML', reply_markup=keyboard)
+ except Exception as e:
+ print(f"Ошибка при отправке сообщения пользователю {tg_id}: {e}. Пропускаем этого пользователя.")
# Обрабатываем истекшие ключи
expired_records = await conn.fetch('''
@@ -68,16 +72,51 @@ async def notify_expiring_keys(bot: Bot):
# Удаляем клиента из панели
delete_client(session, client_id)
+ # Создаем клавиатуру с кнопкой "В профиль"
keyboard = InlineKeyboardMarkup(inline_keyboard=[
- [InlineKeyboardButton(text='1 месяц (100 руб.)', callback_data=f'renew_plan|1|{client_id}')],
- [InlineKeyboardButton(text='3 месяца (250 руб.)', callback_data=f'renew_plan|3|{client_id}')],
- [InlineKeyboardButton(text='Пополнить баланс', callback_data='replenish_balance')]
+ [InlineKeyboardButton(text='В профиль', callback_data='view_profile')]
])
- message = f"Ваш ключ {email} уже истек и был удален. Пожалуйста, продлите его."
- await bot.send_message(chat_id=tg_id, text=message, parse_mode='HTML', reply_markup=keyboard)
+ message = f"Ваш ключ {email} истек и был удален автоматически."
+
+ try:
+ await bot.send_message(chat_id=tg_id, text=message, parse_mode='HTML', reply_markup=keyboard)
+ except Exception as e:
+ print(f"Ошибка при отправке сообщения пользователю {tg_id}: {e}. Пропускаем этого пользователя.")
finally:
await conn.close()
except Exception as e:
print(f"Ошибка при отправке уведомлений: {e}")
+
+@router.message(commands=['send_to_all'])
+async def send_message_to_all_clients(message: types.Message):
+ # Проверяем, является ли отправитель администратором
+ if message.from_user.id != ADMIN_ID: # Замените ADMIN_ID на ID вашего администратора
+ await message.answer("У вас нет прав для выполнения этой команды.")
+ return
+
+ # Получаем текст сообщения
+ text = message.get_args()
+ if not text:
+ await message.answer("Пожалуйста, введите текст сообщения после команды.")
+ return
+
+ try:
+ conn = await asyncpg.connect(DATABASE_URL)
+ # Получаем все tg_id клиентов
+ tg_ids = await conn.fetch('SELECT tg_id FROM keys')
+
+ for record in tg_ids:
+ tg_id = record['tg_id']
+ try:
+ await bot.send_message(chat_id=tg_id, text=text)
+ except Exception as e:
+ print(f"Ошибка при отправке сообщения пользователю {tg_id}: {e}. Пропускаем этого пользователя.")
+
+ await message.answer("Сообщение было отправлено всем клиентам.")
+ except Exception as e:
+ print(f"Ошибка при подключении к базе данных: {e}")
+ await message.answer("Произошла ошибка при отправке сообщения.")
+ finally:
+ await conn.close()
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 79be51df..4739e13e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,26 +8,49 @@ anyio==4.4.0
async-timeout==4.0.3
asyncpg==0.29.0
attrs==24.2.0
+blinker==1.8.2
certifi==2024.8.30
charset-normalizer==3.3.2
+click==8.1.7
+Deprecated==1.2.14
+distro==1.9.0
exceptiongroup==1.2.2
frozenlist==1.4.1
greenlet==3.1.0
h11==0.14.0
+h2==4.1.0
+hpack==4.0.0
httpcore==1.0.5
httpx==0.27.2
+Hypercorn==0.17.3
+hyperframe==6.0.1
idna==3.8
isort==5.13.2
+itsdangerous==2.2.0
+Jinja2==3.1.4
magic-filter==1.0.12
+MarkupSafe==2.1.5
multidict==6.1.0
+netaddr==1.3.0
numpy==2.1.1
+
+packaging==24.1
+
+priority==2.0.0
py3xui==0.2.3
pydantic==2.5.3
pydantic_core==2.14.6
pytz==2024.2
+Quart==0.19.6
requests==2.32.3
sniffio==1.3.1
SQLAlchemy==2.0.34
+taskgroup==0.0.0a4
+tomli==2.0.1
typing_extensions==4.12.2
urllib3==2.2.3
+Werkzeug==3.0.4
+wrapt==1.16.0
+wsproto==1.2.0
yarl==1.11.1
+yookassa==3.3.0