From 67b85478aaf091ccb733f2f7096b49e1cdcf5c22 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 2 Oct 2024 04:16:04 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BE=D1=81=D1=82=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=81=D0=BE=D0=BE=D0=B1=D1=89=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F,=20=D0=BF=D0=BE=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20requirements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.py | 2 -- handlers/key_management.py | 5 ++++ handlers/notifications.py | 59 +++++++++++++++++++++++++++++++------- requirements.txt | 23 +++++++++++++++ 4 files changed, 77 insertions(+), 12 deletions(-) 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