mirror of
https://github.com/BEDOLAGA-DEV/remnawave-bedolaga-telegram-bot.git
synced 2026-05-02 02:36:26 +00:00
Merge branch 'dev4' into main
This commit is contained in:
@@ -47,6 +47,7 @@ async def create_server_squad(
|
||||
max_users: int = None,
|
||||
is_available: bool = True,
|
||||
is_trial_eligible: bool = False,
|
||||
sort_order: int = 0,
|
||||
promo_group_ids: Optional[Iterable[int]] = None,
|
||||
) -> ServerSquad:
|
||||
|
||||
@@ -80,6 +81,7 @@ async def create_server_squad(
|
||||
max_users=max_users,
|
||||
is_available=is_available,
|
||||
is_trial_eligible=is_trial_eligible,
|
||||
sort_order=sort_order,
|
||||
allowed_promo_groups=promo_groups,
|
||||
)
|
||||
|
||||
@@ -260,8 +262,15 @@ async def update_server_squad(
|
||||
) -> Optional[ServerSquad]:
|
||||
|
||||
valid_fields = {
|
||||
'display_name', 'country_code', 'price_kopeks', 'description',
|
||||
'max_users', 'is_available', 'sort_order', 'is_trial_eligible'
|
||||
"display_name",
|
||||
"original_name",
|
||||
"country_code",
|
||||
"price_kopeks",
|
||||
"description",
|
||||
"max_users",
|
||||
"is_available",
|
||||
"sort_order",
|
||||
"is_trial_eligible",
|
||||
}
|
||||
|
||||
filtered_updates = {k: v for k, v in updates.items() if k in valid_fields}
|
||||
|
||||
@@ -5,7 +5,7 @@ from datetime import datetime, timedelta
|
||||
from typing import Optional, List, Dict
|
||||
from sqlalchemy import select, and_, or_, func, case, nullslast, text
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
from sqlalchemy.orm import selectinload, joinedload
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from app.database.models import (
|
||||
@@ -47,8 +47,18 @@ async def get_user_by_id(db: AsyncSession, user_id: int) -> Optional[User]:
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return user
|
||||
|
||||
|
||||
@@ -65,7 +75,17 @@ async def get_user_by_telegram_id(db: AsyncSession, telegram_id: int) -> Optiona
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return user
|
||||
|
||||
@@ -89,7 +109,17 @@ async def get_user_by_username(db: AsyncSession, username: str) -> Optional[User
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return user
|
||||
|
||||
@@ -97,10 +127,29 @@ async def get_user_by_username(db: AsyncSession, username: str) -> Optional[User
|
||||
async def get_user_by_referral_code(db: AsyncSession, referral_code: str) -> Optional[User]:
|
||||
result = await db.execute(
|
||||
select(User)
|
||||
.options(selectinload(User.promo_group))
|
||||
.options(
|
||||
selectinload(User.subscription),
|
||||
selectinload(User.promo_group),
|
||||
selectinload(User.referrer),
|
||||
)
|
||||
.where(User.referral_code == referral_code)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
user = result.scalar_one_or_none()
|
||||
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return user
|
||||
|
||||
|
||||
async def create_unique_referral_code(db: AsyncSession) -> str:
|
||||
@@ -570,7 +619,11 @@ async def get_users_list(
|
||||
order_by_purchase_count: bool = False
|
||||
) -> List[User]:
|
||||
|
||||
query = select(User).options(selectinload(User.subscription))
|
||||
query = select(User).options(
|
||||
selectinload(User.subscription),
|
||||
selectinload(User.promo_group),
|
||||
selectinload(User.referrer),
|
||||
)
|
||||
|
||||
if status:
|
||||
query = query.where(User.status == status.value)
|
||||
@@ -584,7 +637,14 @@ async def get_users_list(
|
||||
]
|
||||
|
||||
if search.isdigit():
|
||||
conditions.append(User.telegram_id == int(search))
|
||||
try:
|
||||
search_int = int(search)
|
||||
# Добавляем условие поиска по telegram_id, который является BigInteger
|
||||
# и может содержать большие значения, в отличие от User.id (INTEGER)
|
||||
conditions.append(User.telegram_id == search_int)
|
||||
except ValueError:
|
||||
# Если не удалось преобразовать в int, просто ищем по текстовым полям
|
||||
pass
|
||||
|
||||
query = query.where(or_(*conditions))
|
||||
|
||||
@@ -658,7 +718,24 @@ async def get_users_list(
|
||||
query = query.offset(offset).limit(limit)
|
||||
|
||||
result = await db.execute(query)
|
||||
return result.scalars().all()
|
||||
users = result.scalars().all()
|
||||
|
||||
# Загружаем дополнительные зависимости для всех пользователей
|
||||
for user in users:
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return users
|
||||
|
||||
|
||||
async def get_users_count(
|
||||
@@ -681,7 +758,14 @@ async def get_users_count(
|
||||
]
|
||||
|
||||
if search.isdigit():
|
||||
conditions.append(User.telegram_id == int(search))
|
||||
try:
|
||||
search_int = int(search)
|
||||
# Добавляем условие поиска по telegram_id, который является BigInteger
|
||||
# и может содержать большие значения, в отличие от User.id (INTEGER)
|
||||
conditions.append(User.telegram_id == search_int)
|
||||
except ValueError:
|
||||
# Если не удалось преобразовать в int, просто ищем по текстовым полям
|
||||
pass
|
||||
|
||||
query = query.where(or_(*conditions))
|
||||
|
||||
@@ -751,11 +835,29 @@ async def get_referrals(db: AsyncSession, user_id: int) -> List[User]:
|
||||
.options(
|
||||
selectinload(User.subscription),
|
||||
selectinload(User.user_promo_groups).selectinload(UserPromoGroup.promo_group),
|
||||
selectinload(User.referrer),
|
||||
)
|
||||
.where(User.referred_by_id == user_id)
|
||||
.order_by(User.created_at.desc())
|
||||
)
|
||||
return result.scalars().all()
|
||||
users = result.scalars().all()
|
||||
|
||||
# Загружаем дополнительные зависимости для всех пользователей
|
||||
for user in users:
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return users
|
||||
|
||||
|
||||
async def get_users_for_promo_segment(db: AsyncSession, segment: str) -> List[User]:
|
||||
@@ -763,7 +865,11 @@ async def get_users_for_promo_segment(db: AsyncSession, segment: str) -> List[Us
|
||||
|
||||
base_query = (
|
||||
select(User)
|
||||
.options(selectinload(User.subscription))
|
||||
.options(
|
||||
selectinload(User.subscription),
|
||||
selectinload(User.promo_group),
|
||||
selectinload(User.referrer),
|
||||
)
|
||||
.where(User.status == UserStatus.ACTIVE.value)
|
||||
)
|
||||
|
||||
@@ -808,7 +914,24 @@ async def get_users_for_promo_segment(db: AsyncSession, segment: str) -> List[Us
|
||||
return []
|
||||
|
||||
result = await db.execute(query.order_by(User.id))
|
||||
return result.scalars().unique().all()
|
||||
users = result.scalars().unique().all()
|
||||
|
||||
# Загружаем дополнительные зависимости для всех пользователей
|
||||
for user in users:
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return users
|
||||
|
||||
|
||||
async def get_inactive_users(db: AsyncSession, months: int = 3) -> List[User]:
|
||||
@@ -819,6 +942,7 @@ async def get_inactive_users(db: AsyncSession, months: int = 3) -> List[User]:
|
||||
.options(
|
||||
selectinload(User.subscription),
|
||||
selectinload(User.user_promo_groups).selectinload(UserPromoGroup.promo_group),
|
||||
selectinload(User.referrer),
|
||||
)
|
||||
.where(
|
||||
and_(
|
||||
@@ -827,7 +951,24 @@ async def get_inactive_users(db: AsyncSession, months: int = 3) -> List[User]:
|
||||
)
|
||||
)
|
||||
)
|
||||
return result.scalars().all()
|
||||
users = result.scalars().all()
|
||||
|
||||
# Загружаем дополнительные зависимости для всех пользователей
|
||||
for user in users:
|
||||
if user and user.subscription:
|
||||
# Загружаем дополнительные зависимости для subscription
|
||||
_ = user.subscription.is_active
|
||||
|
||||
if user and user.promo_group:
|
||||
# Убедимся, что все атрибуты promo_group доступны
|
||||
_ = user.promo_group.name
|
||||
_ = user.promo_group.server_discount_percent
|
||||
_ = user.promo_group.traffic_discount_percent
|
||||
_ = user.promo_group.device_discount_percent
|
||||
_ = user.promo_group.period_discounts
|
||||
_ = user.promo_group.is_default
|
||||
|
||||
return users
|
||||
|
||||
|
||||
async def delete_user(db: AsyncSession, user: User) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user