Compare commits

..

2 Commits

8 changed files with 22 additions and 2560 deletions

View File

@@ -3,6 +3,7 @@ from contextlib import asynccontextmanager
from aiogram import Bot from aiogram import Bot
from aiogram.client.default import DefaultBotProperties from aiogram.client.default import DefaultBotProperties
from aiogram.client.session.aiohttp import AiohttpSession
from fastapi import FastAPI from fastapi import FastAPI
from api.routes import routers from api.routes import routers
@@ -18,8 +19,9 @@ from services.user_service import UserService
@asynccontextmanager @asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator: async def lifespan(app: FastAPI) -> AsyncGenerator:
# Bot Init # Bot Init
bot_default = DefaultBotProperties(parse_mode="HTML") aiohttp_session = AiohttpSession(proxy=settings.proxy) if settings.proxy else None
bot = Bot(token=settings.bot_token, default=bot_default) default = DefaultBotProperties(parse_mode="HTML")
bot = Bot(token=settings.bot_token, default=default, session=aiohttp_session)
app.state.bot = bot app.state.bot = bot
user_repository = UserRepository() user_repository = UserRepository()

View File

@@ -176,7 +176,7 @@ async def proceed_to_checkout(
if effective_balance < amount: if effective_balance < amount:
await cb.message.edit_text( await cb.message.edit_text(
INSUFFICIENT_FUNDS.format(balance=user.balance, amount=amount), reply_markup=deposit_kb INSUFFICIENT_FUNDS.format(balance=user.balance, amount=amount, diff=abs(amount-user.balance)), reply_markup=deposit_kb
) )
return return

View File

@@ -149,7 +149,7 @@ async def sub_info(
deps.user_service.format_subscription_message( deps.user_service.format_subscription_message(
rw_user, link=user.subscription_link, autorenew=sub.autorenew rw_user, link=user.subscription_link, autorenew=sub.autorenew
), ),
reply_markup=subscription_controls(sub.autorenew), reply_markup=subscription_controls(show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew),
) )
@@ -183,5 +183,5 @@ async def toggle_autorenewal(
deps.user_service.format_subscription_message( deps.user_service.format_subscription_message(
rw_user, link=user.subscription_link, autorenew=sub.autorenew rw_user, link=user.subscription_link, autorenew=sub.autorenew
), ),
reply_markup=subscription_controls(sub.autorenew), reply_markup=subscription_controls(show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew),
) )

View File

@@ -54,18 +54,19 @@ deposit_kb: InlineKeyboardMarkup = InlineKeyboardBuilder(
).as_markup() ).as_markup()
def subscription_controls(current_autorenewal_status: bool) -> InlineKeyboardMarkup: def subscription_controls(show_autorenew: bool, current_autorenewal_status: bool = None) -> InlineKeyboardMarkup:
autorenewal_text = ( builder = InlineKeyboardBuilder()
"🟢 Включить автопродление"
if not current_autorenewal_status if show_autorenew:
else "🔴 Отключить автопродление" autorenewal_text = (
) "🟢 Включить автопродление"
return InlineKeyboardBuilder( if not current_autorenewal_status
[ else "🔴 Отключить автопродление"
[InlineKeyboardButton(text=autorenewal_text, callback_data="toggle:autorenewal")], )
[_return_to_menu_btn], builder.row(InlineKeyboardButton(text=autorenewal_text, callback_data="toggle:autorenewal"))
]
).as_markup() builder.row(_return_to_menu_btn)
return builder.as_markup()
def _return_btn(data: str = "menu:main", text: str = "⬅️ Назад") -> InlineKeyboardButton: def _return_btn(data: str = "menu:main", text: str = "⬅️ Назад") -> InlineKeyboardButton:

View File

@@ -185,7 +185,7 @@ BILL_CREATION = _BILL_TEMPLATE + _DIVIDER + GENERAL_PROCESSING
BILL_CREATED = _BILL_TEMPLATE + _DIVIDER + _BILL_LINK BILL_CREATED = _BILL_TEMPLATE + _DIVIDER + _BILL_LINK
INSUFFICIENT_FUNDS = "<b>⚠️ Недостаточно средств для проведения операции.</b>\n\n💰 Текущий баланс: {balance}\n💸 Требуется: {amount}" INSUFFICIENT_FUNDS = "<b>⚠️ Недостаточно средств для проведения операции.</b>\n\n<b>💰 Текущий баланс:</b> <code>{balance}</code>\n<b>💸 Требуется:</b> <code>{amount}</code>\n\n<i>❗ Пополните баланс на <code>{diff}₽</code></i>"
SUCCESSFULLY_CREATED_SUBSCRIPTION = ( SUCCESSFULLY_CREATED_SUBSCRIPTION = (
"<b>💚 Ваша подписка успешно оплачена!</b> Ссылка на добавления доступна в главном меню." "<b>💚 Ваша подписка успешно оплачена!</b> Ссылка на добавления доступна в главном меню."
) )
@@ -205,58 +205,3 @@ SUPPORT_INIT = "<b>🎧 Тех. Поддержка Malenia</b> — не здес
SUPPORT_MSG_SENT = "⏳ Приняли ваше сообщение. Мы постараемся ответить на него в ближайшее время.\n<i>Вернуться в меню: /cancel</i>" SUPPORT_MSG_SENT = "⏳ Приняли ваше сообщение. Мы постараемся ответить на него в ближайшее время.\n<i>Вернуться в меню: /cancel</i>"
SUPPORT_SIGNATURE = "<b>📡 Ответ от Malenia:</b>" SUPPORT_SIGNATURE = "<b>📡 Ответ от Malenia:</b>"
# ============================================================
# ШАБЛОНЫ — ЗАЯВКИ И ТИКЕТЫ
# ============================================================
SUPPORT_SUBSCRIPTION = (
"<b>🎫 ВХОДЯЩИЙ ЗАПРОС:</b>\n\n"
+ _SUPPORT_USER_DESCRIPTION
+ "\n"
+ _DIVIDER
+ "🗓️ Срок: <b>{duration} мес.</b>\n"
+ "📱 Устройства: <b>{devices}</b>\n"
+ "🏳️ Whitelists: <b>{whitelist_description}</b>\n\n"
+ "💰 К оплате: <b>{price}₽</b>"
)
ADMIN_TICKET_WITH_RW = (
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
+ _SUPPORT_USER_DESCRIPTION
+ "\n"
+ _DIVIDER
+ "📊 <b>ТЕХ. ДАННЫЕ (Remnawave)</b>\n\n"
+ "{status_icon} <b>Статус:</b> {status}\n"
+ "📅 <b>Deadline:</b> {expire_date}\n"
+ "⏳ <b>Остаток:</b> {days_left}\n"
+ "📊 <b>Трафик:</b> {used_traffic}\n"
+ "📱 <b>HWID:</b> {hwid_limit}\n"
+ "🎯 <b>Squads:</b> {squads}\n\n"
+ _DIVIDER
+ "🔑 <b>UUID:</b> <code>{remnawave_uuid}</code>"
)
ADMIN_TICKET_WITHOUT_RW = (
"🎫 <b>ТИКЕТ T-{ticket_number:04d}</b>\n\n"
+ _SUPPORT_USER_DESCRIPTION
+ "\n"
+ _DIVIDER
+ NO_SUBSCRIPTION
)
ADMIN_STANDARD_FALLBACK = "<b>❌ Ошибка выполнения.</b> Проверь логи, что-то пошло не по чертежу."
# ============================================================
# АДМИНСКАЯ ХУЙНЯ
# ============================================================
ADMIN_PROMOTION_INIT = "👥 Введите текст рассылки"
ADMIN_PROMOTION_CONFIRMATION = "❓ Отправить сообщение всем пользователям бота?"
SUCCESSFULLY_SENT_PROMOTION = "Успешно разосланно {user_count} пользователям."
SPECIFY_REFERAL_PAYMENT_AMOUNT = "Укажите количество средств для перевода рефералу пользователя."
USER_NO_REFERAL = "У пользователя нет реферала."
INVALID_ARGUMENT_REFPAY = "❌ Укажите в аргументах количество средств, которые необходимо перевести рефералу пользователя."
SUCCESSFUL_REFPAY = "<b>💸 Баланс реферала ({referal_id}) пополнен на {amount}₽</b>"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -80,11 +80,7 @@ class UserService:
user = await self.user_repository.get_user_by_id(session, user_id) user = await self.user_repository.get_user_by_id(session, user_id)
if not rw_user: link = utils.get_subscription_link(rw_user.short_uuid) if rw_user else None
return user
link = utils.get_subscription_link(rw_user.short_uuid)
user = await self.user_repository.update_user_link(session, user_id, link) user = await self.user_repository.update_user_link(session, user_id, link)
return user return user