Update bot_manager.py
Этот коммит содержится в:
+252
-43
@@ -22,7 +22,7 @@ from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
from apscheduler.triggers.interval import IntervalTrigger
|
from apscheduler.triggers.interval import IntervalTrigger
|
||||||
from yoomoney import Client, Quickpay # Добавляем YooMoney
|
from yoomoney import Client, Quickpay
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -35,28 +35,30 @@ moderator_ids = setting.get('moderator_ids', [])
|
|||||||
wg_config_file = setting.get('wg_config_file')
|
wg_config_file = setting.get('wg_config_file')
|
||||||
docker_container = setting.get('docker_container')
|
docker_container = setting.get('docker_container')
|
||||||
endpoint = setting.get('endpoint')
|
endpoint = setting.get('endpoint')
|
||||||
yoomoney_token = setting.get('yoomoney_token') # Токен YooMoney
|
yoomoney_token = setting.get('yoomoney_token')
|
||||||
yoomoney_wallet = setting.get('yoomoney_wallet') # Номер кошелька YooMoney
|
yoomoney_wallet = setting.get('yoomoney_wallet')
|
||||||
|
pricing = setting.get('pricing', {
|
||||||
|
'1_month': 1000.0,
|
||||||
|
'3_months': 2500.0,
|
||||||
|
'6_months': 4500.0,
|
||||||
|
'12_months': 8000.0
|
||||||
|
})
|
||||||
|
|
||||||
if not all([bot_token, admin_ids, wg_config_file, docker_container, endpoint, yoomoney_token, yoomoney_walletseverity=ERROR]):
|
if not all([bot_token, admin_ids, wg_config_file, docker_container, endpoint]):
|
||||||
logger.error("Некоторые обязательные настройки отсутствуют.")
|
logger.error("Некоторые обязательные настройки отсутствуют.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not all([yoomoney_token, yoomoney_wallet]):
|
||||||
|
logger.warning("Настройки YooMoney отсутствуют. Установите их через бот.")
|
||||||
|
|
||||||
admins = [int(admin_id) for admin_id in admin_ids]
|
admins = [int(admin_id) for admin_id in admin_ids]
|
||||||
moderators = [int(mod_id) for mod_id in moderator_ids]
|
moderators = [int(mod_id) for mod_id in moderator_ids]
|
||||||
bot = Bot(bot_token)
|
bot = Bot(bot_token)
|
||||||
WG_CONFIG_FILE = wg_config_file
|
WG_CONFIG_FILE = wg_config_file
|
||||||
DOCKER_CONTAINER = docker_container
|
DOCKER_CONTAINER = docker_container
|
||||||
ENDPOINT = endpoint
|
ENDPOINT = endpoint
|
||||||
yoomoney_client = Client(yoomoney_token) # Инициализация YooMoney
|
yoomoney_client = Client(yoomoney_token) if yoomoney_token else None
|
||||||
|
PRICING = pricing
|
||||||
# Цены за периоды (в рублях для YooMoney)
|
|
||||||
PRICING = {
|
|
||||||
'1_month': 1000.0, # Изменено на рубли
|
|
||||||
'3_months': 2500.0,
|
|
||||||
'6_months': 4500.0,
|
|
||||||
'12_months': 8000.0
|
|
||||||
}
|
|
||||||
|
|
||||||
class AdminMessageDeletionMiddleware(BaseMiddleware):
|
class AdminMessageDeletionMiddleware(BaseMiddleware):
|
||||||
async def on_process_message(self, message: types.Message, data: dict):
|
async def on_process_message(self, message: types.Message, data: dict):
|
||||||
@@ -68,7 +70,7 @@ scheduler = AsyncIOScheduler(timezone=pytz.UTC)
|
|||||||
scheduler.start()
|
scheduler.start()
|
||||||
dp.middleware.setup(AdminMessageDeletionMiddleware())
|
dp.middleware.setup(AdminMessageDeletionMiddleware())
|
||||||
|
|
||||||
# Главное меню (удалены "Список админов", "Добавить админа", "Создать бэкап")
|
# Главное меню
|
||||||
def get_main_menu_markup(user_id):
|
def get_main_menu_markup(user_id):
|
||||||
markup = InlineKeyboardMarkup(row_width=2)
|
markup = InlineKeyboardMarkup(row_width=2)
|
||||||
if user_id in admins:
|
if user_id in admins:
|
||||||
@@ -101,7 +103,7 @@ def get_main_menu_markup(user_id):
|
|||||||
)
|
)
|
||||||
return markup
|
return markup
|
||||||
|
|
||||||
# Меню настроек (добавлены админы и бэкап)
|
# Меню настроек
|
||||||
def get_settings_menu():
|
def get_settings_menu():
|
||||||
markup = InlineKeyboardMarkup(row_width=2)
|
markup = InlineKeyboardMarkup(row_width=2)
|
||||||
markup.add(
|
markup.add(
|
||||||
@@ -116,9 +118,40 @@ def get_settings_menu():
|
|||||||
InlineKeyboardButton("👥 Список админов", callback_data="list_admins"),
|
InlineKeyboardButton("👥 Список админов", callback_data="list_admins"),
|
||||||
InlineKeyboardButton("👤 Добавить админа", callback_data="add_admin")
|
InlineKeyboardButton("👤 Добавить админа", callback_data="add_admin")
|
||||||
)
|
)
|
||||||
|
markup.add(
|
||||||
|
InlineKeyboardButton("💸 Настройки YooMoney", callback_data="yoomoney_settings"),
|
||||||
|
InlineKeyboardButton("💰 Настройки цен", callback_data="pricing_settings")
|
||||||
|
)
|
||||||
markup.add(InlineKeyboardButton("⬅️ Назад", callback_data="home"))
|
markup.add(InlineKeyboardButton("⬅️ Назад", callback_data="home"))
|
||||||
return markup
|
return markup
|
||||||
|
|
||||||
|
# Меню настроек YooMoney
|
||||||
|
def get_yoomoney_settings_menu():
|
||||||
|
markup = InlineKeyboardMarkup(row_width=2)
|
||||||
|
markup.add(
|
||||||
|
InlineKeyboardButton("🔑 Установить токен", callback_data="set_yoomoney_token"),
|
||||||
|
InlineKeyboardButton("💼 Установить кошелёк", callback_data="set_yoomoney_wallet")
|
||||||
|
)
|
||||||
|
markup.add(InlineKeyboardButton("⬅️ Назад", callback_data="settings"))
|
||||||
|
return markup
|
||||||
|
|
||||||
|
# Меню настроек цен
|
||||||
|
def get_pricing_settings_menu():
|
||||||
|
markup = InlineKeyboardMarkup(row_width=2)
|
||||||
|
periods = [
|
||||||
|
("1 месяц", "1_month"),
|
||||||
|
("3 месяца", "3_months"),
|
||||||
|
("6 месяцев", "6_months"),
|
||||||
|
("12 месяцев", "12_months")
|
||||||
|
]
|
||||||
|
for period_name, period_key in periods:
|
||||||
|
markup.add(InlineKeyboardButton(
|
||||||
|
f"{period_name} - ₽{PRICING.get(period_key, 0):.2f}",
|
||||||
|
callback_data=f"set_price_{period_key}"
|
||||||
|
))
|
||||||
|
markup.add(InlineKeyboardButton("⬅️ Назад", callback_data="settings"))
|
||||||
|
return markup
|
||||||
|
|
||||||
# Клавиатура для выбора периода продления
|
# Клавиатура для выбора периода продления
|
||||||
def get_renewal_period_keyboard(username):
|
def get_renewal_period_keyboard(username):
|
||||||
markup = InlineKeyboardMarkup(row_width=2)
|
markup = InlineKeyboardMarkup(row_width=2)
|
||||||
@@ -150,7 +183,7 @@ def get_clear_keys_date_keyboard():
|
|||||||
user_main_messages = {}
|
user_main_messages = {}
|
||||||
isp_cache = {}
|
isp_cache = {}
|
||||||
ISP_CACHE_FILE = 'files/isp_cache.json'
|
ISP_CACHE_FILE = 'files/isp_cache.json'
|
||||||
CACHE_TTL = 24 * 3600 # 24 часа в секундах
|
CACHE_TTL = 24 * 3600
|
||||||
|
|
||||||
def get_interface_name():
|
def get_interface_name():
|
||||||
return os.path.basename(WG_CONFIG_FILE).split('.')[0]
|
return os.path.basename(WG_CONFIG_FILE).split('.')[0]
|
||||||
@@ -228,7 +261,6 @@ def parse_transfer(transfer_str: str) -> tuple:
|
|||||||
return 0, 0
|
return 0, 0
|
||||||
|
|
||||||
async def generate_vpn_key(conf_path: str) -> str:
|
async def generate_vpn_key(conf_path: str) -> str:
|
||||||
"""Преобразует .conf в формат vpn:// с помощью awg-decode.py."""
|
|
||||||
process = await asyncio.create_subprocess_exec(
|
process = await asyncio.create_subprocess_exec(
|
||||||
'python3.11', '/root/amnezia-bot/awg/awg-decode.py', '--encode', conf_path,
|
'python3.11', '/root/amnezia-bot/awg/awg-decode.py', '--encode', conf_path,
|
||||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
||||||
@@ -241,7 +273,6 @@ async def generate_vpn_key(conf_path: str) -> str:
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
async def issue_vpn_key(user_id: int, period: str) -> bool:
|
async def issue_vpn_key(user_id: int, period: str) -> bool:
|
||||||
"""Выдача VPN-ключа пользователю."""
|
|
||||||
username = f"user_{user_id}_{uuid.uuid4().hex[:8]}"
|
username = f"user_{user_id}_{uuid.uuid4().hex[:8]}"
|
||||||
success = db.root_add(username, ipv6=False)
|
success = db.root_add(username, ipv6=False)
|
||||||
if success:
|
if success:
|
||||||
@@ -251,7 +282,7 @@ async def issue_vpn_key(user_id: int, period: str) -> bool:
|
|||||||
db.set_user_telegram_id(username, user_id)
|
db.set_user_telegram_id(username, user_id)
|
||||||
conf_path = os.path.join('users', username, f'{username}.conf')
|
conf_path = os.path.join('users', username, f'{username}.conf')
|
||||||
if os.path.exists(conf_path):
|
if os.path.exists(conf_path):
|
||||||
vpn_key = await generate_vpn various_key(conf_path)
|
vpn_key = await generate_vpn_key(conf_path)
|
||||||
caption = f"Ваш VPN ключ ({period.replace('_', ' ')}):\nAmneziaVPN:\n[Google Play](https://play.google.com/store/apps/details?id=org.amnezia.vpn&hl=ru)\n[GitHub](https://github.com/amnezia-vpn/amnezia-client)\n```\n{vpn_key}\n```"
|
caption = f"Ваш VPN ключ ({period.replace('_', ' ')}):\nAmneziaVPN:\n[Google Play](https://play.google.com/store/apps/details?id=org.amnezia.vpn&hl=ru)\n[GitHub](https://github.com/amnezia-vpn/amnezia-client)\n```\n{vpn_key}\n```"
|
||||||
with open(conf_path, 'rb') as config:
|
with open(conf_path, 'rb') as config:
|
||||||
config_message = await bot.send_document(user_id, config, caption=caption, parse_mode="Markdown")
|
config_message = await bot.send_document(user_id, config, caption=caption, parse_mode="Markdown")
|
||||||
@@ -339,13 +370,13 @@ async def handle_messages(message: types.Message):
|
|||||||
if promocode_data:
|
if promocode_data:
|
||||||
discount = promocode_data.get('discount', 0)
|
discount = promocode_data.get('discount', 0)
|
||||||
subscription_period = promocode_data.get('subscription_period')
|
subscription_period = promocode_data.get('subscription_period')
|
||||||
if subscription_period: # Промокод для выдачи ключа
|
if subscription_period:
|
||||||
success = await issue_vpn_key(user_id, subscription_period)
|
success = await issue_vpn_key(user_id, subscription_period)
|
||||||
if success:
|
if success:
|
||||||
await message.reply(f"Промокод активирован! VPN ключ на {subscription_period.replace('_', ' ')} выдан.")
|
await message.reply(f"Промокод активирован! VPN ключ на {subscription_period.replace('_', ' ')} выдан.")
|
||||||
else:
|
else:
|
||||||
await message.reply("Ошибка при выдаче ключа. Обратитесь к администратору.")
|
await message.reply("Ошибка при выдаче ключа. Обратитесь к администратору.")
|
||||||
else: # Промокод на скидку
|
else:
|
||||||
user_main_messages[user_id]['promocode_discount'] = discount
|
user_main_messages[user_id]['promocode_discount'] = discount
|
||||||
await message.reply(f"Промокод активирован! Скидка: {discount}%")
|
await message.reply(f"Промокод активирован! Скидка: {discount}%")
|
||||||
else:
|
else:
|
||||||
@@ -386,6 +417,53 @@ async def handle_messages(message: types.Message):
|
|||||||
'message_id': sent_message.message_id,
|
'message_id': sent_message.message_id,
|
||||||
'state': None
|
'state': None
|
||||||
}
|
}
|
||||||
|
elif user_state == 'waiting_for_yoomoney_token' and user_id in admins:
|
||||||
|
token = message.text.strip()
|
||||||
|
db.set_yoomoney_config(token=token)
|
||||||
|
global yoomoney_client, yoomoney_token
|
||||||
|
yoomoney_token = token
|
||||||
|
yoomoney_client = Client(yoomoney_token)
|
||||||
|
await message.reply("Токен YooMoney успешно обновлён.")
|
||||||
|
sent_message = await message.answer("Настройки YooMoney:", reply_markup=get_yoomoney_settings_menu())
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': None
|
||||||
|
}
|
||||||
|
elif user_state == 'waiting_for_yoomoney_wallet' and user_id in admins:
|
||||||
|
wallet = message.text.strip()
|
||||||
|
if not re.match(r'^\d{15,18}$', wallet):
|
||||||
|
await message.reply("Введите корректный номер кошелька YooMoney (15-18 цифр).")
|
||||||
|
return
|
||||||
|
db.set_yoomoney_config(wallet=wallet)
|
||||||
|
global yoomoney_wallet
|
||||||
|
yoomoney_wallet = wallet
|
||||||
|
await message.reply("Номер кошелька YooMoney успешно обновлён.")
|
||||||
|
sent_message = await message.answer("Настройки YooMoney:", reply_markup=get_yoomoney_settings_menu())
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': None
|
||||||
|
}
|
||||||
|
elif user_state.startswith('waiting_for_price_') and user_id in admins:
|
||||||
|
period = user_state.split('waiting_for_price_')[1]
|
||||||
|
try:
|
||||||
|
price = float(message.text.strip())
|
||||||
|
if price <= 0:
|
||||||
|
raise ValueError("Цена должна быть положительной.")
|
||||||
|
db.set_pricing(period, price)
|
||||||
|
global PRICING
|
||||||
|
PRICING[period] = price
|
||||||
|
await message.reply(f"Цена для {period.replace('_', ' ')} обновлена: ₽{price:.2f}")
|
||||||
|
except:
|
||||||
|
await message.reply("Введите корректное число (например, 1000.00).")
|
||||||
|
return
|
||||||
|
sent_message = await message.answer("Настройки цен:", reply_markup=get_pricing_settings_menu())
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': None
|
||||||
|
}
|
||||||
|
|
||||||
@dp.callback_query_handler(lambda c: c.data == "settings")
|
@dp.callback_query_handler(lambda c: c.data == "settings")
|
||||||
async def settings_menu_callback(callback_query: types.CallbackQuery):
|
async def settings_menu_callback(callback_query: types.CallbackQuery):
|
||||||
@@ -412,6 +490,132 @@ async def settings_menu_callback(callback_query: types.CallbackQuery):
|
|||||||
}
|
}
|
||||||
await callback_query.answer()
|
await callback_query.answer()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == "yoomoney_settings")
|
||||||
|
async def yoomoney_settings_callback(callback_query: types.CallbackQuery):
|
||||||
|
user_id = callback_query.from_user.id
|
||||||
|
if user_id not in admins:
|
||||||
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
message_id=callback_query.message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
text="Настройки YooMoney:",
|
||||||
|
reply_markup=get_yoomoney_settings_menu()
|
||||||
|
)
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': None
|
||||||
|
}
|
||||||
|
await callback_query.answer()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == "set_yoomoney_token")
|
||||||
|
async def set_yoomoney_token_callback(callback_query: types.CallbackQuery):
|
||||||
|
user_id = callback_query.from_user.id
|
||||||
|
if user_id not in admins:
|
||||||
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
message_id=callback_query.message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
text="Введите токен YooMoney:",
|
||||||
|
reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton("⬅️ Назад", callback_data="yoomoney_settings"))
|
||||||
|
)
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': 'waiting_for_yoomoney_token'
|
||||||
|
}
|
||||||
|
await callback_query.answer()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == "set_yoomoney_wallet")
|
||||||
|
async def set_yoomoney_wallet_callback(callback_query: types.CallbackQuery):
|
||||||
|
user_id = callback_query.from_user.id
|
||||||
|
if user_id not in admins:
|
||||||
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
message_id=callback_query.message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
text="Введите номер кошелька YooMoney (15-18 цифр):",
|
||||||
|
reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton("⬅️ Назад", callback_data="yoomoney_settings"))
|
||||||
|
)
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': 'waiting_for_yoomoney_wallet'
|
||||||
|
}
|
||||||
|
await callback_query.answer()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data == "pricing_settings")
|
||||||
|
async def pricing_settings_callback(callback_query: types.CallbackQuery):
|
||||||
|
user_id = callback_query.from_user.id
|
||||||
|
if user_id not in admins:
|
||||||
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
message_id=callback_query.message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
text="Настройки цен:",
|
||||||
|
reply_markup=get_pricing_settings_menu()
|
||||||
|
)
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': None
|
||||||
|
}
|
||||||
|
await callback_query.answer()
|
||||||
|
|
||||||
|
@dp.callback_query_handler(lambda c: c.data.startswith('set_price_'))
|
||||||
|
async def set_price_callback(callback_query: types.CallbackQuery):
|
||||||
|
user_id = callback_query.from_user.id
|
||||||
|
if user_id not in admins:
|
||||||
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
|
return
|
||||||
|
period = callback_query.data.split('set_price_')[1]
|
||||||
|
try:
|
||||||
|
await bot.delete_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
message_id=callback_query.message.message_id
|
||||||
|
)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sent_message = await bot.send_message(
|
||||||
|
chat_id=callback_query.message.chat.id,
|
||||||
|
text=f"Введите новую цену для {period.replace('_', ' ')} в рублях (например, 1000.00):",
|
||||||
|
reply_markup=InlineKeyboardMarkup().add(InlineKeyboardButton("⬅️ Назад", callback_data="pricing_settings"))
|
||||||
|
)
|
||||||
|
user_main_messages[user_id] = {
|
||||||
|
'chat_id': sent_message.chat.id,
|
||||||
|
'message_id': sent_message.message_id,
|
||||||
|
'state': f'waiting_for_price_{period}'
|
||||||
|
}
|
||||||
|
await callback_query.answer()
|
||||||
|
|
||||||
@dp.callback_query_handler(lambda c: c.data == "clear_old_keys")
|
@dp.callback_query_handler(lambda c: c.data == "clear_old_keys")
|
||||||
async def clear_old_keys_callback(callback_query: types.CallbackQuery):
|
async def clear_old_keys_callback(callback_query: types.CallbackQuery):
|
||||||
user_id = callback_query.from_user.id
|
user_id = callback_query.from_user.id
|
||||||
@@ -1150,13 +1354,13 @@ async def pc_instructions(callback_query: types.CallbackQuery):
|
|||||||
@dp.callback_query_handler(lambda c: c.data == "buy_key")
|
@dp.callback_query_handler(lambda c: c.data == "buy_key")
|
||||||
async def buy_key_callback(callback_query: types.CallbackQuery):
|
async def buy_key_callback(callback_query: types.CallbackQuery):
|
||||||
user_id = callback_query.from_user.id
|
user_id = callback_query.from_user.id
|
||||||
keyboard = InlineKeyboardMarkup(row_width=2).add(
|
keyboard = InlineKeyboardMarkup(row_width=2)
|
||||||
InlineKeyboardButton("1 месяц - ₽1000", callback_data="select_period_1_month"),
|
for period, price in PRICING.items():
|
||||||
InlineKeyboardButton("3 месяца - ₽2500", callback_data="select_period_3_months"),
|
keyboard.add(InlineKeyboardButton(
|
||||||
InlineKeyboardButton("6 месяцев - ₽4500", callback_data="select_period_6_months"),
|
f"{period.replace('_', ' ')} - ₽{price:.2f}",
|
||||||
InlineKeyboardButton("12 месяцев - ₽8000", callback_data="select_period_12_months"),
|
callback_data=f"select_period_{period}"
|
||||||
InlineKeyboardButton("🏠 Домой", callback_data="home")
|
))
|
||||||
)
|
keyboard.add(InlineKeyboardButton("🏠 Домой", callback_data="home"))
|
||||||
try:
|
try:
|
||||||
await bot.delete_message(
|
await bot.delete_message(
|
||||||
chat_id=callback_query.message.chat.id,
|
chat_id=callback_query.message.chat.id,
|
||||||
@@ -1184,6 +1388,10 @@ async def select_period_callback(callback_query: types.CallbackQuery):
|
|||||||
discount = user_main_messages.get(user_id, {}).get('promocode_discount', 0)
|
discount = user_main_messages.get(user_id, {}).get('promocode_discount', 0)
|
||||||
final_price = price * (1 - discount / 100)
|
final_price = price * (1 - discount / 100)
|
||||||
|
|
||||||
|
if not yoomoney_client or not yoomoney_wallet:
|
||||||
|
await callback_query.answer("Платежи недоступны. Обратитесь к администратору.", show_alert=True)
|
||||||
|
return
|
||||||
|
|
||||||
payment_id = str(uuid.uuid4())
|
payment_id = str(uuid.uuid4())
|
||||||
db.add_payment(user_id, payment_id, final_price, 'pending')
|
db.add_payment(user_id, payment_id, final_price, 'pending')
|
||||||
|
|
||||||
@@ -1250,7 +1458,7 @@ async def use_promocode_callback(callback_query: types.CallbackQuery):
|
|||||||
|
|
||||||
@dp.callback_query_handler(lambda c: c.data == "manage_promocodes")
|
@dp.callback_query_handler(lambda c: c.data == "manage_promocodes")
|
||||||
async def manage_promocodes_callback(callback_query: types.CallbackQuery):
|
async def manage_promocodes_callback(callback_query: types.CallbackQuery):
|
||||||
user_id = callback(nameof): callback_query.from_user.id
|
user_id = callback_query.from_user.id
|
||||||
if user_id not in admins:
|
if user_id not in admins:
|
||||||
await callback_query.answer("Нет прав.", show_alert=True)
|
await callback_query.answer("Нет прав.", show_alert=True)
|
||||||
return
|
return
|
||||||
@@ -1429,20 +1637,21 @@ async def check_payment_status():
|
|||||||
payments = db.get_pending_payments()
|
payments = db.get_pending_payments()
|
||||||
for user_id, payment_id, amount, _ in payments:
|
for user_id, payment_id, amount, _ in payments:
|
||||||
try:
|
try:
|
||||||
operation = yoomoney_client.operation_history(label=payment_id)
|
if yoomoney_client:
|
||||||
for op in operation.operations:
|
operation = yoomoney_client.operation_history(label=payment_id)
|
||||||
if op.label == payment_id and op.status == "success":
|
for op in operation.operations:
|
||||||
db.update_payment_status(payment_id, 'completed')
|
if op.label == payment_id and op.status == "success":
|
||||||
pending_payment = user_main_messages.get(user_id, {}).get('pending_payment', {})
|
db.update_payment_status(payment_id, 'completed')
|
||||||
if pending_payment and pending_payment['payment_id'] == payment_id:
|
pending_payment = user_main_messages.get(user_id, {}).get('pending_payment', {})
|
||||||
period = pending_payment['period']
|
if pending_payment and pending_payment['payment_id'] == payment_id:
|
||||||
success = await issue_vpn_key(user_id, period)
|
period = pending_payment['period']
|
||||||
if success:
|
success = await issue_vpn_key(user_id, period)
|
||||||
await bot.send_message(user_id, "Оплата подтверждена! Ваш VPN ключ отправлен.")
|
if success:
|
||||||
else:
|
await bot.send_message(user_id, "Оплата подтверждена! Ваш VPN ключ отправлен.")
|
||||||
await bot.send_message(user_id, "Ошибка при создании пользователя. Обратитесь к администратору.")
|
else:
|
||||||
user_main_messages[user_id].pop('pending_payment', None)
|
await bot.send_message(user_id, "Ошибка при создании пользователя. Обратитесь к администратору.")
|
||||||
break
|
user_main_messages[user_id].pop('pending_payment', None)
|
||||||
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка проверки платежа {payment_id}: {str(e)}")
|
logger.error(f"Ошибка проверки платежа {payment_id}: {str(e)}")
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user