Compare commits

..

3 Commits

8 changed files with 57 additions and 25 deletions

2
.gitignore vendored
View File

@@ -175,3 +175,5 @@ cython_debug/
# PyPI configuration file
.pypirc
plans

View File

@@ -233,7 +233,7 @@ async def proceed_to_checkout(
balance_before=deducted_user.balance + amount,
balance_after=deducted_user.balance,
devices=ctx.devices,
duration_days=convert_duration_to_int(ctx.duration),
duration_days=convert_duration_to_int(ctx.duration) * 30,
whitelists=ctx.whitelists,
credit=credit,
)

View File

@@ -4,12 +4,13 @@ from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message
from sqlalchemy.ext.asyncio import AsyncSession
from bot.keyboards.client import close_kb, main_menu, subscription_controls
from bot.keyboards.client import close_kb, construct_devices_list, main_menu, subscription_controls
from bot.keyboards.common import return_to_menu
from bot.texts import (
CALLBACK_FALLBACK,
FAQ_TEXT,
GENERAL_PROCESSING,
NO_CONNECTIONS,
NO_SUBSCRIPTION,
)
from db.models.users import User
@@ -17,7 +18,7 @@ from misc import utils
from misc.utils import build_main_menu_text, format_subscription_link
from schemas.di import DependenciesDTO
from schemas.subscriptions import InternalSquads, SubscriptionPlan
from services.rw import get_user_by_telegram_id
from services.rw import get_hwid_list, get_user_by_telegram_id
router = Router()
@@ -34,7 +35,7 @@ async def fetch_referal(
data = command.args.split("_")
if not data:
await standard_start(msg, command, state)
await standard_start(msg, state, session, deps)
return
referal = int(data[1])
@@ -126,7 +127,7 @@ async def sub_info(
return
if not user:
await cb.answer("1" + CALLBACK_FALLBACK)
await cb.answer(CALLBACK_FALLBACK)
return
if rw_user and not sub:
@@ -146,7 +147,7 @@ async def sub_info(
plan_price_paid=utils.calculate_price(dto),
)
except Exception:
await cb.answer("2" + CALLBACK_FALLBACK)
await cb.answer(CALLBACK_FALLBACK)
return
await cb.message.edit_text(
@@ -158,6 +159,25 @@ async def sub_info(
),
)
@router.callback_query(F.data == "hwid_control")
async def hwid_control(cb: CallbackQuery, state: FSMContext, deps: DependenciesDTO):
await state.clear()
await cb.message.edit_text(GENERAL_PROCESSING, reply_markup=close_kb)
rw_user = await get_user_by_telegram_id(deps.rw_sdk, cb.from_user.id)
if not rw_user:
await cb.message.edit_text(NO_SUBSCRIPTION, reply_markup=return_to_menu)
return
devices = await get_hwid_list(deps.rw_sdk, rw_user.uuid)
if not devices:
await cb.message.edit_text(NO_CONNECTIONS, reply_markup=return_to_menu)
return
await cb.message.edit_text(text="pepe", reply_markup=construct_devices_list(devices))
@router.callback_query(F.data == "toggle:autorenewal")
async def toggle_autorenewal(
@@ -191,19 +211,3 @@ async def toggle_autorenewal(
show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew
),
)
rw_user = await get_user_by_telegram_id(deps.rw_sdk, cb.from_user.id)
user: User | None = await deps.user_service.update_user_link(
session, cb.from_user.id, deps.rw_sdk
)
status_text = "включено" if new_autorenew else "отключено"
await cb.answer(f"Автопродление {status_text}")
await cb.message.edit_text(
deps.user_service.format_subscription_message(
rw_user, link=user.subscription_link, autorenew=sub.autorenew
),
reply_markup=subscription_controls(
show_autorenew=bool(rw_user), current_autorenewal_status=sub.autorenew
),
)

View File

@@ -1,5 +1,6 @@
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.utils.keyboard import InlineKeyboardBuilder
from remnawave.models.hwid import HwidDeviceDto
from config import settings
from misc.utils import convert_duration_to_int
@@ -63,6 +64,7 @@ def subscription_controls(
)
builder.row(InlineKeyboardButton(text=autorenewal_text, callback_data="toggle:autorenewal"))
builder.row(InlineKeyboardButton(text="Управление устройствами", callback_data="hwid_control"))
builder.row(_return_to_menu_btn)
return builder.as_markup()
@@ -143,3 +145,11 @@ def pay_url(url: str) -> InlineKeyboardMarkup:
[InlineKeyboardButton(text="", callback_data="menu:main")],
]
).as_markup()
def construct_devices_list(devices: list[HwidDeviceDto]) -> InlineKeyboardMarkup:
builder = InlineKeyboardBuilder()
for device in devices:
builder.row(InlineKeyboardButton(text=f"{device.platform} | {device.device_model} | {device.user_agent.split('/')[0]}", callback_data=f"hwid:{device.hwid}"))
builder.row(_return_btn(data="sub_info"))
return builder.as_markup()

View File

@@ -155,6 +155,7 @@ SUBSCRIPTION_INFORMATION = (
NO_SUBSCRIPTION = f"{MALENIA_WARN} <b>Подписка не найдена.</b>"
NO_CONNECTIONS = f"{MALENIA_SHIELD} <b>Вы ещё не подключались по своей ссылке.</b>"
# ============================================================
# РЕФЕРАЛЬНАЯ СИСТЕМА

View File

@@ -1,10 +1,12 @@
import logging
from dataclasses import dataclass
from datetime import UTC, datetime, timedelta
from typing import List
from uuid import UUID
from remnawave import RemnawaveSDK
from remnawave.models import CreateUserRequestDto, UpdateUserRequestDto
from remnawave.models.hwid import HwidDeviceDto
logger = logging.getLogger(__name__)
@@ -349,3 +351,15 @@ async def create_user(
except Exception as exc:
logger.warning("Failed to create user username=%s: %s", username, exc)
return None
async def get_hwid_list(
sdk: RemnawaveSDK,
user_uuid: str
) -> List[HwidDeviceDto] | None:
try:
resp = await sdk.hwid.get_hwid_user(user_uuid)
return resp.devices
except Exception as exc:
logger.exception("failed to fetch hwid list for user=%s", user_uuid)
return

View File

@@ -2,8 +2,9 @@ import datetime
import logging
import math
from aiogram.types import Message, User as TelegramUser
from aiogram.types import InlineKeyboardMarkup, Message, User as TelegramUser
from remnawave import RemnawaveSDK
from remnawave.models.hwid import HwidDeviceDto
from sqlalchemy.ext.asyncio import AsyncSession
from bot.texts import NO_SUBSCRIPTION, NOTHING_PLACEHOLDER, SUBSCRIPTION_INFORMATION

View File

@@ -66,7 +66,7 @@ def main():
gross_amount = args.amount * (1 + commission_rate)
commission = gross_amount - args.amount
print(f"customer pays fee:")
print("customer pays fee:")
print(f" Сумма заказа: {args.amount} RUB")
print(f" Комиссия: {commission:.2f} RUB")
print(f" Итого к оплате: {gross_amount:.2f} RUB")