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

View File

@@ -176,7 +176,7 @@ async def proceed_to_checkout(
if effective_balance < amount:
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

View File

@@ -149,7 +149,7 @@ async def sub_info(
deps.user_service.format_subscription_message(
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(
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()
def subscription_controls(current_autorenewal_status: bool) -> InlineKeyboardMarkup:
autorenewal_text = (
"🟢 Включить автопродление"
if not current_autorenewal_status
else "🔴 Отключить автопродление"
)
return InlineKeyboardBuilder(
[
[InlineKeyboardButton(text=autorenewal_text, callback_data="toggle:autorenewal")],
[_return_to_menu_btn],
]
).as_markup()
def subscription_controls(show_autorenew: bool, current_autorenewal_status: bool = None) -> InlineKeyboardMarkup:
builder = InlineKeyboardBuilder()
if show_autorenew:
autorenewal_text = (
"🟢 Включить автопродление"
if not current_autorenewal_status
else "🔴 Отключить автопродление"
)
builder.row(InlineKeyboardButton(text=autorenewal_text, callback_data="toggle:autorenewal"))
builder.row(_return_to_menu_btn)
return builder.as_markup()
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
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 = (
"<b>💚 Ваша подписка успешно оплачена!</b> Ссылка на добавления доступна в главном меню."
)
@@ -205,58 +205,3 @@ SUPPORT_INIT = "<b>🎧 Тех. Поддержка Malenia</b> — не здес
SUPPORT_MSG_SENT = "⏳ Приняли ваше сообщение. Мы постараемся ответить на него в ближайшее время.\n<i>Вернуться в меню: /cancel</i>"
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)
if not rw_user:
return user
link = utils.get_subscription_link(rw_user.short_uuid)
link = utils.get_subscription_link(rw_user.short_uuid) if rw_user else None
user = await self.user_repository.update_user_link(session, user_id, link)
return user