From 6477afd00f0e284c3a6fc0380af56e20f24a4579 Mon Sep 17 00:00:00 2001 From: Vladless Date: Sun, 1 Feb 2026 09:58:58 +0300 Subject: [PATCH] Docker/ API 0.5.0: Partner Statistics/Coupons for New Customers and More --- .gitignore | 6 +- Dockerfile | 23 ++ api/main.py | 6 +- api/routes/base_crud.py | 49 ++- api/routes/keys.py | 24 +- api/routes/partners.py | 325 ++++++++++++++++++ database/coupons.py | 10 +- database/models.py | 1 + database/servers.py | 17 +- database/users.py | 4 +- docker-compose.yml | 10 + handlers/admin/clusters/cluster_manage.py | 8 +- handlers/admin/clusters/cluster_sync.py | 5 +- handlers/admin/clusters/cluster_tariffs.py | 77 ++--- handlers/admin/clusters/keyboard.py | 9 +- handlers/admin/coupons/coupons_handler.py | 92 ++++- handlers/admin/users/keyboard.py | 4 +- handlers/admin/users/users_gifts.py | 12 +- handlers/admin/users/users_keys.py | 7 +- handlers/admin/users/users_manage.py | 4 +- handlers/admin/users/users_tariffs.py | 24 +- handlers/coupons.py | 18 +- handlers/keys/key_view.py | 6 +- handlers/keys/operations/creation.py | 4 +- handlers/keys/operations/renewal.py | 12 +- handlers/keys/operations/update.py | 16 +- .../notifications/general_notifications.py | 216 ++++++------ handlers/notifications/notify_utils.py | 1 + .../notifications/special_notifications.py | 20 +- handlers/payments/constants.py | 2 +- handlers/payments/currency_flow.py | 2 +- handlers/payments/fast_payment_flow.py | 12 +- .../gift.cpython-312-x86_64-linux-gnu.so | Bin 1093928 -> 1159496 bytes handlers/payments/heleket/handlers.py | 33 +- handlers/payments/heleket/service.py | 43 +-- handlers/payments/heleket/webhook.py | 51 +-- handlers/payments/kassai/handlers.py | 50 +-- handlers/payments/kassai/service.py | 39 ++- handlers/payments/kassai/webhook.py | 29 +- handlers/payments/keyboards.py | 4 +- handlers/payments/pay.py | 4 +- handlers/tariffs/addons/key_addons_pack.py | 4 +- handlers/tariffs/subgroup_migration.py | 4 +- img/store.png | Bin 0 -> 146419 bytes main.py | 5 +- middlewares/user.py | 23 +- 46 files changed, 820 insertions(+), 495 deletions(-) create mode 100644 Dockerfile create mode 100644 api/routes/partners.py create mode 100644 docker-compose.yml create mode 100644 img/store.png diff --git a/.gitignore b/.gitignore index ab7d7aca..cb26abc2 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,6 @@ database.db bot_old.py bot_old_2.py backup_pg.sh -docker-compose.yml config copy.py handlers/texts.py @@ -53,11 +52,12 @@ Thumbs.db nginx.conf scripts -Dockerfile .csv /logs setup.py .ruff_cache .github/workflows/ modules/ -storage/ \ No newline at end of file +storage/ + +.license_state \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..92a17fee --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV PIP_NO_CACHE_DIR=1 + +WORKDIR /app + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + tzdata \ + git \ + && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt . +COPY . . + +RUN rm -rf /app/venv \ + && python -m venv /app/venv \ + && /app/venv/bin/pip install --upgrade pip \ + && /app/venv/bin/pip install -r requirements.txt + +CMD ["/app/venv/bin/python", "main.py"] diff --git a/api/main.py b/api/main.py index 9c722deb..82d8b3f1 100644 --- a/api/main.py +++ b/api/main.py @@ -1,9 +1,9 @@ from fastapi import FastAPI -from api.routes import coupons, gifts, keys, misc, referrals, servers, settings, tariffs, users +from api.routes import users, keys, coupons, servers, tariffs, gifts, referrals, misc, partners app = FastAPI( title="SoloBot API (Alpha)", - version="0.4.0", + version="0.5.0", docs_url="/api/docs", redoc_url="/api/redoc", openapi_url="/api/openapi.json", @@ -16,7 +16,7 @@ app.include_router(servers.router, prefix="/api/servers", tags=["Servers"]) app.include_router(tariffs.router, prefix="/api/tariffs", tags=["Tariffs"]) app.include_router(gifts.router, prefix="/api/gifts", tags=["Gifts"]) app.include_router(referrals.router, prefix="/api/referrals", tags=["Referrals"]) -app.include_router(settings.router, prefix="/api/settings", tags=["Settings"]) +app.include_router(partners.router, prefix="/api/partners", tags=["Partners"]) app.include_router(misc.router, prefix="/api") diff --git a/api/routes/base_crud.py b/api/routes/base_crud.py index ed6d7b08..52535ff8 100644 --- a/api/routes/base_crud.py +++ b/api/routes/base_crud.py @@ -1,3 +1,5 @@ +from typing import Any + from fastapi import APIRouter, Depends, HTTPException, Path, Query from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession @@ -7,13 +9,23 @@ from api.depends import get_session, verify_admin_token from database.models import Admin -def _cast_identifier_type(field: InstrumentedAttribute, value: int | str): +def cast_identifier_type(field: InstrumentedAttribute, value: int | str): column_type = type(field.property.columns[0].type).__name__ if column_type in ("Integer", "BigInteger"): return int(value) return value +def normalize_outgoing_object(obj: object) -> None: + if hasattr(obj, "vless") and getattr(obj, "vless") is None: + setattr(obj, "vless", False) + + +def to_schema(schema_response: type, obj: object): + normalize_outgoing_object(obj) + return schema_response.model_validate(obj, from_attributes=True) + + def generate_crud_router( *, model: type, @@ -35,7 +47,10 @@ def generate_crud_router( session: AsyncSession = Depends(get_session), ): result = await session.execute(select(model)) - return result.scalars().all() + items = result.scalars().all() + for item in items: + normalize_outgoing_object(item) + return [schema_response.model_validate(item, from_attributes=True) for item in items] if "get_by_email" in enabled_methods and extra_get_by_email: @@ -49,7 +64,7 @@ def generate_crud_router( obj = result.scalar_one_or_none() if not obj: raise HTTPException(status_code=404, detail="Not found by email") - return obj + return to_schema(schema_response, obj) if "get_one" in enabled_methods: @@ -60,12 +75,12 @@ def generate_crud_router( session: AsyncSession = Depends(get_session), ): field = getattr(model, identifier_field) - casted = _cast_identifier_type(field, value) + casted = cast_identifier_type(field, value) result = await session.execute(select(model).where(field == casted)) obj = result.scalar_one_or_none() if not obj: raise HTTPException(status_code=404, detail=f"{model.__name__} not found") - return obj + return to_schema(schema_response, obj) if "get_all_by_field" in enabled_methods: @@ -76,52 +91,56 @@ def generate_crud_router( session: AsyncSession = Depends(get_session), ): field = getattr(model, identifier_field) - casted = _cast_identifier_type(field, value) + casted = cast_identifier_type(field, value) result = await session.execute(select(model).where(field == casted)) objs = result.scalars().all() if not objs: raise HTTPException(status_code=404, detail=f"{model.__name__} not found") - return objs + for obj in objs: + normalize_outgoing_object(obj) + return [schema_response.model_validate(obj, from_attributes=True) for obj in objs] if "create" in enabled_methods: @router.post("/", response_model=schema_response) async def create( - payload: schema_create, # type: ignore + payload: Any, admin: Admin = Depends(verify_admin_token), session: AsyncSession = Depends(get_session), ): - data = payload.dict(exclude_unset=True) + validated = schema_create.model_validate(payload) + data = validated.model_dump(exclude_unset=True) if "days" in data and data["days"] == 0: data["days"] = None obj = model(**data) session.add(obj) await session.commit() await session.refresh(obj) - return obj + return to_schema(schema_response, obj) if "update" in enabled_methods: @router.patch(f"/{{{parameter_name}}}", response_model=schema_response) async def update( - payload: schema_update, # type: ignore + payload: Any, value: int | str = Path(..., alias=parameter_name), admin: Admin = Depends(verify_admin_token), session: AsyncSession = Depends(get_session), ): field = getattr(model, identifier_field) - casted = _cast_identifier_type(field, value) + casted = cast_identifier_type(field, value) result = await session.execute(select(model).where(field == casted)) obj = result.scalar_one_or_none() if not obj: raise HTTPException(status_code=404, detail=f"{model.__name__} not found") - for k, v in payload.dict(exclude_unset=True).items(): + validated = schema_update.model_validate(payload) + for k, v in validated.model_dump(exclude_unset=True).items(): setattr(obj, k, v) await session.commit() await session.refresh(obj) - return obj + return to_schema(schema_response, obj) if "delete" in enabled_methods: @@ -132,7 +151,7 @@ def generate_crud_router( session: AsyncSession = Depends(get_session), ): field = getattr(model, identifier_field) - casted = _cast_identifier_type(field, value) + casted = cast_identifier_type(field, value) result = await session.execute(select(model).where(field == casted)) obj = result.scalar_one_or_none() if not obj: diff --git a/api/routes/keys.py b/api/routes/keys.py index 2d7daaab..54614714 100644 --- a/api/routes/keys.py +++ b/api/routes/keys.py @@ -93,31 +93,15 @@ async def edit_key_by_email( setattr(db_key, field, value) try: - tariff = None - if db_key.tariff_id is not None: - tariff_result = await session.execute(select(Tariff).where(Tariff.id == db_key.tariff_id)) - tariff = tariff_result.scalar_one_or_none() - - total_gb = db_key.current_traffic_limit - if total_gb is None: - total_gb = db_key.selected_traffic_limit - if total_gb is None and tariff is not None: - total_gb = tariff.traffic_limit - - hwid_device_limit = db_key.current_device_limit - if hwid_device_limit is None: - hwid_device_limit = db_key.selected_device_limit - if hwid_device_limit is None and tariff is not None: - hwid_device_limit = tariff.device_limit - + new_expiry_time = db_key.expiry_time await renew_key_in_cluster( cluster_id=db_key.server_id, email=db_key.email, client_id=db_key.client_id, - new_expiry_time=db_key.expiry_time, - total_gb=total_gb, + new_expiry_time=new_expiry_time, + total_gb=getattr(db_key, "traffic_limit", None), session=session, - hwid_device_limit=hwid_device_limit, + hwid_device_limit=getattr(db_key, "device_limit", None), reset_traffic=True, ) await session.commit() diff --git a/api/routes/partners.py b/api/routes/partners.py new file mode 100644 index 00000000..63ef40c7 --- /dev/null +++ b/api/routes/partners.py @@ -0,0 +1,325 @@ +from datetime import datetime + +from fastapi import APIRouter, Depends, Path, Query +from fastapi.responses import JSONResponse +from sqlalchemy import text +from sqlalchemy.ext.asyncio import AsyncSession + +from api.depends import get_session, verify_admin_token + + +router = APIRouter() + + +@router.get("/all") +async def get_all_partners( + limit: int = Query(1000, ge=1, le=10000, description="Лимит результатов"), + offset: int = Query(0, ge=0, description="Смещение"), + admin=Depends(verify_admin_token), + session: AsyncSession = Depends(get_session), +): + """Возвращает список всех партнёров со статистикой. + + Структура ответа: + { + "total": int, + "items": [ + { + "tg_id": int, + "balance": float, + "percent": float, + "code": str | None, + "method": str | None, + "referred_count": int + } + ] + } + """ + + partners_sql = text( + """ + SELECT + p.partner_tg_id AS tg_id, + COALESCE(u.partner_balance, 0) AS partner_balance, + COALESCE(u.partner_percent, 0) AS partner_percent, + u.partner_code, + u.payout_method, + COUNT(p.joined_tg_id) as joined_count + FROM partners p + LEFT JOIN users u ON u.tg_id = p.partner_tg_id + WHERE p.partner_tg_id IS NOT NULL + GROUP BY p.partner_tg_id, u.partner_balance, u.partner_percent, u.partner_code, u.payout_method + ORDER BY partner_balance DESC + LIMIT :limit OFFSET :offset + """ + ) + + count_sql = text( + """ + SELECT COUNT(DISTINCT partner_tg_id) FROM partners + WHERE partner_tg_id IS NOT NULL + """ + ) + + result = await session.execute(partners_sql, {"limit": limit, "offset": offset}) + partners = result.fetchall() + + count_result = await session.execute(count_sql) + total = count_result.scalar() or 0 + + partners_list = [ + { + "tg_id": int(partner[0]), + "balance": float(partner[1] or 0), + "percent": float(partner[2] or 0), + "code": partner[3] or None, + "method": partner[4] or None, + "referred_count": int(partner[5] or 0), + } + for partner in partners + ] + + return JSONResponse(content={"total": total, "items": partners_list}) + + +@router.get("/stats/all") +async def get_partners_stats( + admin=Depends(verify_admin_token), + session: AsyncSession = Depends(get_session), +): + """Возвращает общую статистику партнёрской программы. + + Структура ответа: + { + "total_partners": int, + "total_referred": int, + "total_balance": float, + "top_partner_tg_id": int, + "top_partner_refs": int + } + """ + + stats_sql = text( + """ + WITH partner_refs AS ( + SELECT partner_tg_id, COUNT(DISTINCT joined_tg_id) AS ref_count + FROM partners + WHERE partner_tg_id IS NOT NULL + GROUP BY partner_tg_id + ) + SELECT + (SELECT COUNT(*) FROM partner_refs) AS total_partners, + (SELECT COUNT(DISTINCT joined_tg_id) FROM partners WHERE partner_tg_id IS NOT NULL) AS total_referred, + ( + SELECT COALESCE(SUM(u.partner_balance), 0.0) + FROM users u + WHERE u.tg_id IN (SELECT partner_tg_id FROM partner_refs) + ) AS total_balance, + (SELECT partner_tg_id FROM partner_refs ORDER BY ref_count DESC LIMIT 1) AS top_partner_tg_id, + (SELECT ref_count FROM partner_refs ORDER BY ref_count DESC LIMIT 1) AS top_partner_refs + """ + ) + + stats_result = await session.execute(stats_sql) + stats_row = stats_result.fetchone() + + if stats_row: + stats = { + "total_partners": int(stats_row[0] or 0), + "total_referred": int(stats_row[1] or 0), + "total_balance": float(stats_row[2] or 0.0), + "top_partner_tg_id": int(stats_row[3] or 0), + "top_partner_refs": int(stats_row[4] or 0), + } + else: + stats = { + "total_partners": 0, + "total_referred": 0, + "total_balance": 0.0, + "top_partner_tg_id": 0, + "top_partner_refs": 0, + } + + return JSONResponse(content=stats) + + +@router.patch("/{tg_id}") +async def update_partner( + tg_id: int = Path(..., description="Telegram ID партнёра"), + balance: float = Query(..., description="Новый баланс партнёра"), + percent: float = Query(..., description="Новый процент партнёра"), + admin=Depends(verify_admin_token), + session: AsyncSession = Depends(get_session), +): + """Обновляет данные партнёра (баланс и процент). + + Структура ответа: + { + "success": bool, + "message": str + } + """ + + try: + stmt = text( + """ + UPDATE users + SET partner_balance = :balance, partner_percent = :percent + WHERE tg_id = :tg_id + """ + ) + + result = await session.execute(stmt, {"tg_id": tg_id, "balance": balance, "percent": percent}) + await session.commit() + + if result.rowcount > 0: + return JSONResponse( + content={"success": True, "message": f"Партнёр {tg_id} успешно обновлён"}, + status_code=200, + ) + else: + return JSONResponse( + content={"success": False, "message": "Партнёр не найден"}, + status_code=404, + ) + except Exception as e: + await session.rollback() + return JSONResponse( + content={"success": False, "message": str(e)}, + status_code=500, + ) + + +@router.get("/{tg_id}") +async def get_partner_data( + tg_id: int = Path(..., description="Telegram ID партнёра"), + admin=Depends(verify_admin_token), + session: AsyncSession = Depends(get_session), +): + """Возвращает партнёрские данные для указанного `tg_id`. + + Структура ответа: + { + "tg_id": int, + "partner_balance": float, + "partner_percent": float, + "partner_code": str | None, + "payout_method": str | None, + "invited": [ + { "tg_id": int, "joined_at": str | None, "balance": float, "subs_count": int, "payments_count": int } + ] + } + """ + + meta_sql = text( + """ + SELECT + COALESCE(u.partner_balance, 0) AS partner_balance, + COALESCE(u.partner_percent, 0) AS partner_percent, + u.partner_code, + u.payout_method + FROM users u + WHERE u.tg_id = :tg_id + """ + ) + + invited_sql = text( + """ + SELECT + pr.joined_tg_id, + pr.created_at, + COALESCE(u.balance, 0) AS user_balance, + ( + SELECT COUNT(*) FROM keys k + WHERE k.tg_id = pr.joined_tg_id + ) AS subs_count, + ( + SELECT COUNT(*) FROM payments pay + WHERE pay.tg_id = pr.joined_tg_id + AND lower(pay.status) = 'success' + ) AS payments_count + FROM partners pr + LEFT JOIN users u ON u.tg_id = pr.joined_tg_id + WHERE pr.partner_tg_id = :tg_id + ORDER BY pr.created_at DESC + """ + ) + + meta_res = await session.execute(meta_sql, {"tg_id": tg_id}) + meta_row = meta_res.fetchone() + + invited_res = await session.execute(invited_sql, {"tg_id": tg_id}) + invited_rows = invited_res.fetchall() + + response = { + "tg_id": tg_id, + "partner_balance": float(meta_row[0] or 0) if meta_row else 0.0, + "partner_percent": float(meta_row[1] or 0) if meta_row else 0.0, + "partner_code": meta_row[2] if meta_row else None, + "payout_method": meta_row[3] if meta_row else None, + "invited": [ + { + "tg_id": row[0], + "joined_at": row[1].isoformat() if isinstance(row[1], datetime) else None, + "balance": float(row[2] or 0), + "subs_count": int(row[3] or 0), + "payments_count": int(row[4] or 0), + } + for row in invited_rows + ], + } + + return JSONResponse(content=response) + + +@router.get("/{tg_id}/invited") +async def get_partner_invited( + tg_id: int = Path(..., description="Telegram ID партнёра"), + admin=Depends(verify_admin_token), + session: AsyncSession = Depends(get_session), +): + """Возвращает список приглашённых пользователей конкретного партнёра. + + Структура ответа: + [ + { "tg_id": int, "joined_at": str | None, "balance": float, "subs_count": int, "payments_count": int } + ] + """ + + invited_sql = text( + """ + SELECT + pr.joined_tg_id, + pr.created_at, + COALESCE(u.balance, 0) AS user_balance, + ( + SELECT COUNT(*) FROM keys k + WHERE k.tg_id = pr.joined_tg_id + ) AS subs_count, + ( + SELECT COUNT(*) FROM payments pay + WHERE pay.tg_id = pr.joined_tg_id + AND lower(pay.status) = 'success' + ) AS payments_count + FROM partners pr + LEFT JOIN users u ON u.tg_id = pr.joined_tg_id + WHERE pr.partner_tg_id = :tg_id + ORDER BY pr.created_at DESC + """ + ) + + invited_res = await session.execute(invited_sql, {"tg_id": tg_id}) + invited_rows = invited_res.fetchall() + + invited_list = [ + { + "tg_id": row[0], + "joined_at": row[1].isoformat() if isinstance(row[1], datetime) else None, + "balance": float(row[2] or 0), + "subs_count": int(row[3] or 0), + "payments_count": int(row[4] or 0), + } + for row in invited_rows + ] + + return JSONResponse(content=invited_list) diff --git a/database/coupons.py b/database/coupons.py index 5fa0693b..323b68e5 100644 --- a/database/coupons.py +++ b/database/coupons.py @@ -8,7 +8,14 @@ from database.models import Coupon, CouponUsage from logger import logger -async def create_coupon(session: AsyncSession, code: str, amount: int, usage_limit: int, days: int = None) -> bool: +async def create_coupon( + session: AsyncSession, + code: str, + amount: int, + usage_limit: int, + days: int = None, + new_users_only: bool = False, +) -> bool: try: exists = await session.scalar(select(Coupon.id).where(Coupon.code == code)) if exists: @@ -23,6 +30,7 @@ async def create_coupon(session: AsyncSession, code: str, amount: int, usage_lim usage_count=0, is_used=False, days=days, + new_users_only=new_users_only, ) ) await session.commit() diff --git a/database/models.py b/database/models.py index 52f251a8..97896ed8 100644 --- a/database/models.py +++ b/database/models.py @@ -183,6 +183,7 @@ class Coupon(DictLikeMixin, Base): usage_count = Column(Integer, default=0) is_used = Column(Boolean, default=False) days = Column(Integer, nullable=True) + new_users_only = Column(Boolean, default=False, nullable=False) class CouponUsage(DictLikeMixin, Base): diff --git a/database/servers.py b/database/servers.py index 09301a74..bb5090b7 100644 --- a/database/servers.py +++ b/database/servers.py @@ -278,9 +278,9 @@ async def resolve_device_limit_from_group(session: AsyncSession, server_id: str) async def filter_cluster_by_subgroup( - session: AsyncSession, - cluster: list, - target_subgroup: str, + session: AsyncSession, + cluster: list, + target_subgroup: str, cluster_id: str, tariff_id: int | None = None, ) -> list: @@ -320,7 +320,7 @@ async def filter_cluster_by_subgroup( check_values = [target_subgroup] if tariff_id: check_values.append(str(tariff_id)) - + total_bindings = await session.scalar( select(func.count()).select_from(ServerSubgroup).where(ServerSubgroup.subgroup_title.in_(check_values)) ) @@ -345,9 +345,7 @@ async def filter_cluster_by_subgroup( return cluster -async def filter_cluster_by_tariff( - session: AsyncSession, cluster: list, tariff_id: int, cluster_id: str -) -> list: +async def filter_cluster_by_tariff(session: AsyncSession, cluster: list, tariff_id: int, cluster_id: str) -> list: names = [s.get("server_name") for s in cluster if s.get("server_name")] if not names: return [] @@ -394,10 +392,9 @@ async def filter_cluster_by_tariff( async def has_legacy_subgroup_bindings(session: AsyncSession, server_ids: list[int]) -> bool: if not server_ids: return False - + result = await session.execute( - select(ServerSubgroup.subgroup_title) - .where(ServerSubgroup.server_id.in_(server_ids)) + select(ServerSubgroup.subgroup_title).where(ServerSubgroup.server_id.in_(server_ids)) ) for (title,) in result.all(): if title and not title.isdigit(): diff --git a/database/users.py b/database/users.py index 3425dfeb..31a49dfe 100644 --- a/database/users.py +++ b/database/users.py @@ -225,9 +225,7 @@ async def mark_trial_extended(tg_id: int, session: AsyncSession): async def get_user_snapshot(session: AsyncSession, tg_id: int) -> tuple[int, int] | None: keys_count_sq = select(func.count(Key.client_id)).where(Key.tg_id == tg_id).scalar_subquery() - res = await session.execute( - select(func.coalesce(User.trial, 0), keys_count_sq).where(User.tg_id == tg_id) - ) + res = await session.execute(select(func.coalesce(User.trial, 0), keys_count_sq).where(User.tg_id == tg_id)) row = res.first() if row is None: return None diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..4c1e3a48 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,10 @@ +services: + bot: + container_name: solobot + build: . + restart: unless-stopped + network_mode: host + volumes: + - /etc/machine-id:/etc/machine-id:ro + - /var/lib/dbus/machine-id:/var/lib/dbus/machine-id:ro + diff --git a/handlers/admin/clusters/cluster_manage.py b/handlers/admin/clusters/cluster_manage.py index 89ee3c74..7eccd54e 100644 --- a/handlers/admin/clusters/cluster_manage.py +++ b/handlers/admin/clusters/cluster_manage.py @@ -149,16 +149,13 @@ async def handle_days_input(message: Message, state: FSMContext, session: AsyncS servers = await get_servers(session=session) cluster_servers = servers.get(cluster_name, []) - + if not cluster_servers: await message.answer("❌ Не найдены серверы в кластере.") await state.clear() return - is_full_remnawave = all( - str(s.get("panel_type", "")).lower() == "remnawave" - for s in cluster_servers - ) + is_full_remnawave = all(str(s.get("panel_type", "")).lower() == "remnawave" for s in cluster_servers) if is_full_remnawave: uuids = [key.client_id for key in keys if key.client_id] @@ -175,6 +172,7 @@ async def handle_days_input(message: Message, state: FSMContext, session: AsyncS return from panels.remnawave import RemnawaveAPI + remna = RemnawaveAPI(api_url) try: diff --git a/handlers/admin/clusters/cluster_sync.py b/handlers/admin/clusters/cluster_sync.py index 5bd747fc..53e18cdf 100644 --- a/handlers/admin/clusters/cluster_sync.py +++ b/handlers/admin/clusters/cluster_sync.py @@ -293,7 +293,7 @@ async def handle_sync_server( has_new_binding = tid and tid in (server_info.get("tariff_ids") or []) has_old_binding = subgroup and subgroup in (server_info.get("tariff_subgroups") or []) has_any_binding = bool(server_info.get("tariff_ids") or server_info.get("tariff_subgroups")) - + if has_any_binding and subgroup and not has_new_binding and not has_old_binding: continue @@ -565,7 +565,8 @@ async def handle_sync_cluster( if subgroup_title or (tariff and tariff.get("id")): tid = tariff.get("id") if tariff else None filtered_servers = [ - s for s in cluster_servers + s + for s in cluster_servers if (tid and tid in (s.get("tariff_ids") or [])) or (subgroup_title and subgroup_title in (s.get("tariff_subgroups") or [])) ] diff --git a/handlers/admin/clusters/cluster_tariffs.py b/handlers/admin/clusters/cluster_tariffs.py index c7de23e5..020441e4 100644 --- a/handlers/admin/clusters/cluster_tariffs.py +++ b/handlers/admin/clusters/cluster_tariffs.py @@ -96,12 +96,11 @@ async def show_servers_for_tariffs( reply_markup=build_legacy_reset_kb(cluster_name), ) return - + data = await state.get_data() selected = set(data.get(f"subgrp_sel:{cluster_name}", [])) await callback.message.edit_text( - f"📋 Выберите серверы для привязки тарифов\n" - f"Кластер: {cluster_name}", + f"📋 Выберите серверы для привязки тарифов\nКластер: {cluster_name}", reply_markup=build_select_subgroup_servers_kb(cluster_name, cluster_servers, selected), ) @@ -135,8 +134,7 @@ async def toggle_server_for_tariffs( selected.add(server_name) await state.update_data({key: list(selected)}) await callback.message.edit_text( - f"📋 Выберите серверы для привязки тарифов\n" - f"Кластер: {cluster_name}", + f"📋 Выберите серверы для привязки тарифов\nКластер: {cluster_name}", reply_markup=build_select_subgroup_servers_kb(cluster_name, cluster_servers, selected), ) @@ -153,8 +151,7 @@ async def reset_tariff_selection( f"tariff_sel:{cluster_name}": [], }) await callback.message.edit_text( - f"📋 Выберите серверы для привязки тарифов\n" - f"Кластер: {cluster_name}", + f"📋 Выберите серверы для привязки тарифов\nКластер: {cluster_name}", reply_markup=build_select_subgroup_servers_kb(cluster_name, cluster_servers, set()), ) @@ -185,7 +182,7 @@ async def choose_tariffs( .order_by(Tariff.subgroup_title.nulls_last(), Tariff.sort_order, Tariff.id) ) tariffs = result.scalars().all() - + if not tariffs: await callback.message.edit_text("❌ Для этой группы нет доступных тарифов.") return @@ -193,8 +190,7 @@ async def choose_tariffs( selected_tariffs = set(data.get(f"tariff_sel:{cluster_name}", [])) await callback.message.edit_text( - f"📋 Выберите тарифы для {len(selected_servers)} сервер(а/ов)\n" - f"Кластер: {cluster_name}", + f"📋 Выберите тарифы для {len(selected_servers)} сервер(а/ов)\nКластер: {cluster_name}", reply_markup=build_tariff_selection_kb(cluster_name, tariffs, selected_tariffs), ) @@ -205,35 +201,34 @@ async def toggle_tariff_selection( ): cluster_name, tariff_id_str = callback_data.data.split("|", 1) tariff_id = int(tariff_id_str) - + key = f"tariff_sel:{cluster_name}" data = await state.get_data() selected_tariffs = set(data.get(key, [])) - + if tariff_id in selected_tariffs: selected_tariffs.remove(tariff_id) else: selected_tariffs.add(tariff_id) - + await state.update_data({key: list(selected_tariffs)}) res = await session.execute(select(Server.tariff_group).where(Server.cluster_name == cluster_name).distinct()) group_codes = [r[0] for r in res.fetchall() if r[0]] if not group_codes: return - + result = await session.execute( select(Tariff) .where(Tariff.group_code == group_codes[0], Tariff.is_active.is_(True)) .order_by(Tariff.subgroup_title.nulls_last(), Tariff.sort_order, Tariff.id) ) tariffs = result.scalars().all() - + selected_servers = set(data.get(f"subgrp_sel:{cluster_name}", [])) - + await callback.message.edit_text( - f"📋 Выберите тарифы для {len(selected_servers)} сервер(а/ов)\n" - f"Кластер: {cluster_name}", + f"📋 Выберите тарифы для {len(selected_servers)} сервер(а/ов)\nКластер: {cluster_name}", reply_markup=build_tariff_selection_kb(cluster_name, tariffs, selected_tariffs), ) @@ -245,42 +240,41 @@ async def apply_tariffs( try: cluster_name = callback_data.data data = await state.get_data() - + selected_servers = set(data.get(f"subgrp_sel:{cluster_name}", [])) selected_tariffs = set(data.get(f"tariff_sel:{cluster_name}", [])) - + if not selected_servers: await callback.answer("Не выбраны серверы", show_alert=True) return - + if not selected_tariffs: await callback.answer("Не выбраны тарифы", show_alert=True) return servers_q = await session.execute( - select(Server.id, Server.server_name, Server.tariff_group) - .where(Server.server_name.in_(selected_servers)) + select(Server.id, Server.server_name, Server.tariff_group).where(Server.server_name.in_(selected_servers)) ) servers_data = servers_q.fetchall() server_ids = [row[0] for row in servers_data] group_code = servers_data[0][2] if servers_data else "standard" - + if not server_ids: await callback.answer("Серверы не найдены", show_alert=True) return selected_tariff_strs = {str(tid) for tid in selected_tariffs} - + await session.execute( delete(ServerSubgroup) .where(ServerSubgroup.server_id.in_(server_ids)) - .where(ServerSubgroup.subgroup_title.regexp_match(r'^\d+$')) + .where(ServerSubgroup.subgroup_title.regexp_match(r"^\d+$")) .where(ServerSubgroup.subgroup_title.notin_(selected_tariff_strs)) ) for tariff_id in selected_tariffs: tariff_id_str = str(tariff_id) - + existing_q = await session.execute( select(ServerSubgroup.server_id) .where(ServerSubgroup.server_id.in_(server_ids)) @@ -288,13 +282,13 @@ async def apply_tariffs( ) already = {r[0] for r in existing_q.fetchall()} to_insert = [sid for sid in server_ids if sid not in already] - + if to_insert: session.add_all([ - ServerSubgroup(server_id=sid, group_code=group_code, subgroup_title=tariff_id_str) + ServerSubgroup(server_id=sid, group_code=group_code, subgroup_title=tariff_id_str) for sid in to_insert ]) - + await session.commit() await state.update_data({ @@ -308,7 +302,7 @@ async def apply_tariffs( all_tariff_ids = set() for s in cluster_servers: all_tariff_ids.update(s.get("tariff_ids") or []) - + tariffs_cache = {} if all_tariff_ids: result = await session.execute(select(Tariff).where(Tariff.id.in_(all_tariff_ids))) @@ -319,7 +313,7 @@ async def apply_tariffs( "subgroup_title": t.subgroup_title, "group_code": t.group_code, } - + text = render_attach_tariff_menu_text(cluster_name, cluster_servers, tariffs_cache) await callback.message.edit_text( text=text, @@ -359,14 +353,11 @@ async def reset_cluster_subgroups(callback: CallbackQuery, callback_data: AdminC def render_attach_tariff_menu_text( - cluster_name: str, - cluster_servers: list[dict], - tariffs_cache: dict[int, dict] | None = None + cluster_name: str, cluster_servers: list[dict], tariffs_cache: dict[int, dict] | None = None ) -> str: - tariff_map: dict[int, list[str]] = {} legacy_map: dict[str, list[str]] = {} - + for s in cluster_servers: server_name = s["server_name"] @@ -393,10 +384,10 @@ def render_attach_tariff_menu_text( subgroup = tariff.get("subgroup_title") name = tariff.get("name", f"ID:{tid}") grouped.setdefault(subgroup, []).append((tid, name, servers)) - + tariff_lines = [] subgroups_sorted = sorted(grouped.keys(), key=lambda x: (x is None, x or "")) - + for subgroup in subgroups_sorted: tariffs_list = grouped[subgroup] if subgroup: @@ -408,7 +399,7 @@ def render_attach_tariff_menu_text( for tid, name, servers in sorted(tariffs_list, key=lambda x: x[1]): servers_str = ", ".join(sorted(set(servers))) tariff_lines.append(f"• {name}: {servers_str}") - + lines.append("
" + "\n".join(tariff_lines) + "
") elif tariff_map: tariff_lines = [] @@ -453,12 +444,10 @@ async def handle_attach_tariff_menu(callback: CallbackQuery, session: AsyncSessi all_tariff_ids = set() for s in cluster_servers: all_tariff_ids.update(s.get("tariff_ids") or []) - + tariffs_cache = {} if all_tariff_ids: - result = await session.execute( - select(Tariff).where(Tariff.id.in_(all_tariff_ids)) - ) + result = await session.execute(select(Tariff).where(Tariff.id.in_(all_tariff_ids))) for t in result.scalars().all(): tariffs_cache[t.id] = { "id": t.id, diff --git a/handlers/admin/clusters/keyboard.py b/handlers/admin/clusters/keyboard.py index ec88063c..734af93d 100644 --- a/handlers/admin/clusters/keyboard.py +++ b/handlers/admin/clusters/keyboard.py @@ -191,7 +191,7 @@ def build_tariff_selection_kb(cluster_name: str, tariffs: list, selected: set[in grouped.setdefault(subgroup, []).append(t) subgroups_sorted = sorted(grouped.keys(), key=lambda x: (x is None, x or "")) - + for subgroup in subgroups_sorted: tariffs_list = grouped[subgroup] @@ -208,10 +208,7 @@ def build_tariff_selection_kb(cluster_name: str, tariffs: list, selected: set[in builder.row( InlineKeyboardButton( text=f"{mark} {t.name}", - callback_data=AdminClusterCallback( - action="toggle_tariff", - data=f"{cluster_name}|{t.id}" - ).pack(), + callback_data=AdminClusterCallback(action="toggle_tariff", data=f"{cluster_name}|{t.id}").pack(), ) ) @@ -227,7 +224,7 @@ def build_tariff_selection_kb(cluster_name: str, tariffs: list, selected: set[in callback_data=AdminClusterCallback(action="set_subgroup", data=cluster_name).pack(), ) ) - + return builder.as_markup() diff --git a/handlers/admin/coupons/coupons_handler.py b/handlers/admin/coupons/coupons_handler.py index 2c9aba64..adc607f4 100644 --- a/handlers/admin/coupons/coupons_handler.py +++ b/handlers/admin/coupons/coupons_handler.py @@ -34,6 +34,7 @@ router = Router() class AdminCouponsState(StatesGroup): waiting_for_coupon_type = State() + waiting_for_coupon_audience = State() waiting_for_balance_data = State() waiting_for_days_data = State() @@ -62,30 +63,59 @@ async def handle_coupons_create(callback_query: CallbackQuery, state: FSMContext await state.set_state(AdminCouponsState.waiting_for_coupon_type) -@router.callback_query(F.data == "coupon_type_balance") -async def handle_balance_coupon_selection(callback_query: CallbackQuery, state: FSMContext): - text = ( - "🎫 Введите данные для создания купона в формате:\n\n" - "📝 код 💰 сумма 🔢 лимит\n\n" - "Пример: 'COUPON1 50 5' 👈\n\n" - ) +async def show_coupon_audience_step(callback_query: CallbackQuery, state: FSMContext, coupon_type: str): + await state.update_data(coupon_type=coupon_type) + + text = "🎯 Кому доступен купон?" kb = InlineKeyboardBuilder() + kb.button(text="👤 Всем", callback_data="coupon_audience_all") + kb.button(text="🆕 Только новым", callback_data="coupon_audience_new") kb.button(text=BACK, callback_data=AdminPanelCallback(action="coupons").pack()) + kb.adjust(1) await callback_query.message.edit_text(text=text, reply_markup=kb.as_markup()) - await state.set_state(AdminCouponsState.waiting_for_balance_data) + await state.set_state(AdminCouponsState.waiting_for_coupon_audience) -@router.callback_query(F.data == "coupon_type_days") +@router.callback_query(F.data == "coupon_type_balance", IsAdminFilter()) +async def handle_balance_coupon_selection(callback_query: CallbackQuery, state: FSMContext): + await show_coupon_audience_step(callback_query, state, "balance") + + +@router.callback_query(F.data == "coupon_type_days", IsAdminFilter()) async def handle_days_coupon_selection(callback_query: CallbackQuery, state: FSMContext): + await show_coupon_audience_step(callback_query, state, "days") + + +@router.callback_query(F.data.in_(("coupon_audience_all", "coupon_audience_new")), IsAdminFilter()) +async def handle_coupon_audience(callback_query: CallbackQuery, state: FSMContext): + data = await state.get_data() + coupon_type = data.get("coupon_type") + if coupon_type not in ("balance", "days"): + await callback_query.answer("Ошибка: тип купона не найден", show_alert=True) + return + + await state.update_data(new_users_only=callback_query.data == "coupon_audience_new") + + kb = InlineKeyboardBuilder() + kb.button(text=BACK, callback_data=AdminPanelCallback(action="coupons").pack()) + kb.adjust(1) + + if coupon_type == "balance": + text = ( + "🎫 Введите данные для создания купона в формате:\n\n" + "📝 код 💰 сумма 🔢 лимит\n\n" + "Пример: 'COUPON1 50 5' 👈\n\n" + ) + await callback_query.message.edit_text(text=text, reply_markup=kb.as_markup()) + await state.set_state(AdminCouponsState.waiting_for_balance_data) + return + text = ( "🎫 Введите данные для создания купона в формате:\n\n" "📝 коддни 🔢 лимит\n\n" "Пример: 'DAYS10 10 50' 👈\n\n" ) - kb = InlineKeyboardBuilder() - kb.button(text=BACK, callback_data=AdminPanelCallback(action="coupons").pack()) - await callback_query.message.edit_text(text=text, reply_markup=kb.as_markup()) await state.set_state(AdminCouponsState.waiting_for_days_data) @@ -97,6 +127,7 @@ async def handle_balance_coupon_input(message: Message, state: FSMContext, sessi kb = InlineKeyboardBuilder() kb.button(text=BACK, callback_data=AdminPanelCallback(action="coupons").pack()) + kb.adjust(1) if len(parts) != 3: text = ( @@ -119,13 +150,29 @@ async def handle_balance_coupon_input(message: Message, state: FSMContext, sessi return try: - await create_coupon(session, coupon_code, coupon_amount, usage_limit, days=None) + data = await state.get_data() + new_users_only = bool(data.get("new_users_only")) + + ok = await create_coupon( + session, + coupon_code, + coupon_amount, + usage_limit, + days=None, + new_users_only=new_users_only, + ) + if not ok: + await message.answer("❌ Купон с таким кодом уже существует.", reply_markup=kb.as_markup()) + return coupon_link = f"https://t.me/{USERNAME_BOT}?start=coupons_{coupon_code}" + audience_txt = "🆕 Только новым" if new_users_only else "👤 Всем" + text = ( f"✅ Купон с кодом {coupon_code} успешно создан!\n" f"💰 Сумма: {coupon_amount} рублей\n" f"🔢 Лимит использования: {usage_limit} раз\n" + f"🎯 Доступ: {audience_txt}\n" f"🔗 Ссылка: {coupon_link}\n" ) @@ -150,6 +197,7 @@ async def handle_days_coupon_input(message: Message, state: FSMContext, session: kb = InlineKeyboardBuilder() kb.button(text=BACK, callback_data=AdminPanelCallback(action="coupons").pack()) + kb.adjust(1) if len(parts) != 3: text = ( @@ -172,13 +220,29 @@ async def handle_days_coupon_input(message: Message, state: FSMContext, session: return try: - await create_coupon(session, coupon_code, 0, usage_limit, days=days) + data = await state.get_data() + new_users_only = bool(data.get("new_users_only")) + + ok = await create_coupon( + session, + coupon_code, + 0, + usage_limit, + days=days, + new_users_only=new_users_only, + ) + if not ok: + await message.answer("❌ Купон с таким кодом уже существует.", reply_markup=kb.as_markup()) + return coupon_link = f"https://t.me/{USERNAME_BOT}?start=coupons_{coupon_code}" + audience_txt = "🆕 Только новым" if new_users_only else "👤 Всем" + text = ( f"✅ Купон с кодом {coupon_code} успешно создан!\n" f"⏳ {format_days(days)}\n" f"🔢 Лимит использования: {usage_limit} раз\n" + f"🎯 Доступ: {audience_txt}\n" f"🔗 Ссылка: {coupon_link}\n" ) diff --git a/handlers/admin/users/keyboard.py b/handlers/admin/users/keyboard.py index 642afbd7..bfad1b01 100644 --- a/handlers/admin/users/keyboard.py +++ b/handlers/admin/users/keyboard.py @@ -481,9 +481,7 @@ def build_user_gifts_kb(tg_id: int, gifts: list, page: int = 0) -> InlineKeyboar callback_data=f"user_gift_page|{tg_id}|{page - 1}", ) ) - nav_buttons.append( - InlineKeyboardButton(text=f"{page + 1}/{total_pages}", callback_data="noop") - ) + nav_buttons.append(InlineKeyboardButton(text=f"{page + 1}/{total_pages}", callback_data="noop")) if page < total_pages - 1: nav_buttons.append( InlineKeyboardButton( diff --git a/handlers/admin/users/users_gifts.py b/handlers/admin/users/users_gifts.py index 9d94cecf..24e65c64 100644 --- a/handlers/admin/users/users_gifts.py +++ b/handlers/admin/users/users_gifts.py @@ -29,10 +29,7 @@ async def show_gifts_list(message: types.Message, session: AsyncSession, tg_id: gifts = await get_user_gifts(session, tg_id) if not gifts: - text = ( - f"🎁 Подарки пользователя {tg_id}\n\n" - f"У пользователя нет созданных подарков." - ) + text = f"🎁 Подарки пользователя {tg_id}\n\nУ пользователя нет созданных подарков." await message.edit_text( text=text, reply_markup=build_user_gifts_kb(tg_id, [], page), @@ -40,6 +37,7 @@ async def show_gifts_list(message: types.Message, session: AsyncSession, tg_id: return from .keyboard import GIFTS_PER_PAGE + start_idx = page * GIFTS_PER_PAGE end_idx = start_idx + GIFTS_PER_PAGE page_gifts = gifts[start_idx:end_idx] @@ -61,11 +59,7 @@ async def show_gifts_list(message: types.Message, session: AsyncSession, tg_id: created_str = gift.created_at.replace(tzinfo=pytz.UTC).astimezone(MOSCOW_TZ).strftime("%d.%m.%Y %H:%M") - lines.append( - f"\n{i}.🎁 {gift.selected_months} мес.\n" - f" 📅 Создан: {created_str}\n" - f" {status}" - ) + lines.append(f"\n{i}.🎁 {gift.selected_months} мес.\n 📅 Создан: {created_str}\n {status}") lines.append("\n\nНажмите кнопку для удаления:") diff --git a/handlers/admin/users/users_keys.py b/handlers/admin/users/users_keys.py index 2990f4c9..4a5b9ce0 100644 --- a/handlers/admin/users/users_keys.py +++ b/handlers/admin/users/users_keys.py @@ -110,7 +110,12 @@ async def handle_key_edit( if key_obj.tariff_id: result = await session.execute( select( - Tariff.name, Tariff.subgroup_title, Tariff.group_code, Tariff.device_limit, Tariff.traffic_limit, Tariff.configurable + Tariff.name, + Tariff.subgroup_title, + Tariff.group_code, + Tariff.device_limit, + Tariff.traffic_limit, + Tariff.configurable, ).where(Tariff.id == key_obj.tariff_id) ) row = result.first() diff --git a/handlers/admin/users/users_manage.py b/handlers/admin/users/users_manage.py index a53a4065..3f6f507e 100644 --- a/handlers/admin/users/users_manage.py +++ b/handlers/admin/users/users_manage.py @@ -342,7 +342,9 @@ async def process_user_search( ) -> None: await state.clear() - stmt_user = select(User.username, User.balance, User.created_at, User.updated_at, User.trial).where(User.tg_id == tg_id) + stmt_user = select(User.username, User.balance, User.created_at, User.updated_at, User.trial).where( + User.tg_id == tg_id + ) result_user = await session.execute(stmt_user) user_data = result_user.first() diff --git a/handlers/admin/users/users_tariffs.py b/handlers/admin/users/users_tariffs.py index db1a58b5..b735ec26 100644 --- a/handlers/admin/users/users_tariffs.py +++ b/handlers/admin/users/users_tariffs.py @@ -207,10 +207,14 @@ async def handle_user_renew_confirm( base_traffic_gb = int(base_traffic_gb) if base_traffic_gb is not None else None selected_devices = ( - base_device_limit if base_device_limit is not None else (device_int_options[0] if device_int_options else None) + base_device_limit + if base_device_limit is not None + else (device_int_options[0] if device_int_options else None) ) selected_traffic_gb = ( - base_traffic_gb if base_traffic_gb is not None else (traffic_int_options[0] if traffic_int_options else None) + base_traffic_gb + if base_traffic_gb is not None + else (traffic_int_options[0] if traffic_int_options else None) ) await state.update_data( @@ -343,7 +347,9 @@ async def handle_user_renew_confirm( plan=tariff_id, ) except Exception as e: - logger.error(f"[AdminRenew] renew_key_in_cluster failed: tg_id={tg_id} email={email} tariff_id={tariff_id}: {e}") + logger.error( + f"[AdminRenew] renew_key_in_cluster failed: tg_id={tg_id} email={email} tariff_id={tariff_id}: {e}" + ) ok = False await state.clear() @@ -353,7 +359,9 @@ async def handle_user_renew_confirm( callback_data_back = AdminUserEditorCallback(action="users_key_edit", data=email, tg_id=tg_id) - await handle_key_edit(callback_query=callback_query, callback_data=callback_data_back, session=session, update=False) + await handle_key_edit( + callback_query=callback_query, callback_data=callback_data_back, session=session, update=False + ) @router.callback_query(F.data.startswith("cfg_renew_devices|"), IsAdminFilter()) @@ -662,7 +670,9 @@ async def handle_cfg_renew_apply(callback_query: CallbackQuery, session: AsyncSe plan=tariff_id, ) except Exception as e: - logger.error(f"[AdminRenewCfg] renew_key_in_cluster failed: tg_id={tg_id} email={email} tariff_id={tariff_id}: {e}") + logger.error( + f"[AdminRenewCfg] renew_key_in_cluster failed: tg_id={tg_id} email={email} tariff_id={tariff_id}: {e}" + ) ok = False await state.clear() @@ -672,7 +682,9 @@ async def handle_cfg_renew_apply(callback_query: CallbackQuery, session: AsyncSe callback_data_back = AdminUserEditorCallback(action="users_key_edit", data=email, tg_id=int(tg_id)) - await handle_key_edit(callback_query=callback_query, callback_data=callback_data_back, session=session, update=False) + await handle_key_edit( + callback_query=callback_query, callback_data=callback_data_back, session=session, update=False + ) @router.callback_query(F.data == "back:group", IsAdminFilter()) diff --git a/handlers/coupons.py b/handlers/coupons.py index 9e7df522..1187be51 100644 --- a/handlers/coupons.py +++ b/handlers/coupons.py @@ -107,6 +107,15 @@ async def activate_coupon( await state.clear() return + from database.models import User + + if getattr(coupon, "new_users_only", False): + exists = await session.scalar(select(User.tg_id).where(User.tg_id == user_id)) + if exists is not None: + await message.answer("❌ Этот купон доступен только для новых пользователей.") + await state.clear() + return + if isinstance(user, dict): await add_user(session=session, **user) else: @@ -184,7 +193,7 @@ async def handle_key_extension( session: AsyncSession, admin: bool = False, ): - from database.models import Coupon, Key + from database.models import Coupon, Key, User parts = callback_query.data.split("|") client_id = parts[1] @@ -205,6 +214,13 @@ async def handle_key_extension( await state.clear() return + if getattr(coupon, "new_users_only", False): + exists = await session.scalar(select(User.tg_id).where(User.tg_id == tg_id)) + if exists is not None: + await callback_query.message.edit_text("❌ Этот купон доступен только для новых пользователей.") + await state.clear() + return + result = await session.execute(select(Key).where(Key.tg_id == tg_id, Key.client_id == client_id)) key = result.scalar_one_or_none() if not key or key.is_frozen: diff --git a/handlers/keys/key_view.py b/handlers/keys/key_view.py index 075b39c2..1435cac2 100644 --- a/handlers/keys/key_view.py +++ b/handlers/keys/key_view.py @@ -340,12 +340,14 @@ async def build_key_view_payload(session: AsyncSession, key_name: str): remna_server = None for cluster_name, cluster_servers in servers.items(): for srv in cluster_servers: - if (srv.get("server_name") == server_name or cluster_name == server_name) and srv.get("panel_type") == "remnawave": + if (srv.get("server_name") == server_name or cluster_name == server_name) and srv.get( + "panel_type" + ) == "remnawave": remna_server = srv break if remna_server: break - + if remna_server: api = RemnawaveAPI(remna_server["api_url"]) if await api.login(REMNAWAVE_LOGIN, REMNAWAVE_PASSWORD): diff --git a/handlers/keys/operations/creation.py b/handlers/keys/operations/creation.py index b846e677..412c9b61 100644 --- a/handlers/keys/operations/creation.py +++ b/handlers/keys/operations/creation.py @@ -97,9 +97,7 @@ async def create_key_on_cluster( device_limit_value = int(hwid_limit or 0) if plan is not None: - filtered = await filter_cluster_by_tariff( - session, enabled_servers, plan, cluster_id - ) + filtered = await filter_cluster_by_tariff(session, enabled_servers, plan, cluster_id) if filtered is not enabled_servers: enabled_servers = filtered elif subgroup_title: diff --git a/handlers/keys/operations/renewal.py b/handlers/keys/operations/renewal.py index 71c3bcff..889f533c 100644 --- a/handlers/keys/operations/renewal.py +++ b/handlers/keys/operations/renewal.py @@ -78,7 +78,9 @@ async def renew_on_remnawave( if old_device_limit is not None and hwid_device_limit < old_device_limit: try: await remna.clear_all_hwid_devices(client_id) - logger.info(f"{PANEL_REMNA} HWID устройства сброшены для {client_id} (лимит {old_device_limit} → {hwid_device_limit})") + logger.info( + f"{PANEL_REMNA} HWID устройства сброшены для {client_id} (лимит {old_device_limit} → {hwid_device_limit})" + ) except Exception as e: logger.warning(f"{PANEL_REMNA} Ошибка сброса HWID: {e}") @@ -298,9 +300,7 @@ async def renew_key_in_cluster( cluster_scope = [single_server] else: if plan is not None: - filtered = await filter_cluster_by_tariff( - session, cluster, plan, cluster_id - ) + filtered = await filter_cluster_by_tariff(session, cluster, plan, cluster_id) if filtered is not cluster: cluster_scope = filtered elif target_subgroup: @@ -310,9 +310,7 @@ async def renew_key_in_cluster( else: cluster_scope = cluster elif target_subgroup: - target = await filter_cluster_by_subgroup( - session, cluster, target_subgroup, cluster_id, tariff_id=plan - ) + target = await filter_cluster_by_subgroup(session, cluster, target_subgroup, cluster_id, tariff_id=plan) cluster_scope = target if target else cluster else: cluster_scope = cluster diff --git a/handlers/keys/operations/update.py b/handlers/keys/operations/update.py index b81c054d..432985f4 100644 --- a/handlers/keys/operations/update.py +++ b/handlers/keys/operations/update.py @@ -53,9 +53,7 @@ async def update_key_on_cluster( raise ValueError(f"Кластер или сервер с ID/именем {cluster_id} не найден.") if tariff_id is not None: - filtered = await filter_cluster_by_tariff( - session, cluster, tariff_id, cluster_id - ) + filtered = await filter_cluster_by_tariff(session, cluster, tariff_id, cluster_id) if filtered is not cluster: cluster = filtered elif subgroup_code: @@ -63,9 +61,7 @@ async def update_key_on_cluster( session, cluster, subgroup_code, cluster_id, tariff_id=tariff_id ) elif subgroup_code: - cluster = await filter_cluster_by_subgroup( - session, cluster, subgroup_code, cluster_id, tariff_id=tariff_id - ) + cluster = await filter_cluster_by_subgroup(session, cluster, subgroup_code, cluster_id, tariff_id=tariff_id) if not cluster: logger.warning(f"[Update] Нет серверов после фильтрации по привязкам в кластере {cluster_id}") @@ -276,9 +272,7 @@ async def update_subscription( cluster_servers = [] if tariff_id is not None: - filtered = await filter_cluster_by_tariff( - session, cluster_servers, tariff_id, new_cluster_id - ) + filtered = await filter_cluster_by_tariff(session, cluster_servers, tariff_id, new_cluster_id) if filtered is not cluster_servers: cluster_servers = filtered elif subgroup_code: @@ -291,9 +285,7 @@ async def update_subscription( ) if not cluster_servers: - logger.warning( - f"[Update] Пересоздание пропущено: нет серверов после фильтрации в {new_cluster_id}." - ) + logger.warning(f"[Update] Пересоздание пропущено: нет серверов после фильтрации в {new_cluster_id}.") return if tariff: diff --git a/handlers/notifications/general_notifications.py b/handlers/notifications/general_notifications.py index 74aaf96c..1906ee33 100644 --- a/handlers/notifications/general_notifications.py +++ b/handlers/notifications/general_notifications.py @@ -78,12 +78,12 @@ class NotificationContext: current_time: int preload_data: Optional[dict] = None bulk_updates: Optional[dict] = None - + def get_balance(self, tg_id: int) -> float: if self.preload_data and tg_id in self.preload_data.get("balances_cache", {}): return self.preload_data["balances_cache"][tg_id] return 0.0 - + def get_tariff(self, tariff_id: int) -> Optional[dict]: if self.preload_data and tariff_id in self.preload_data.get("tariffs_cache", {}): return self.preload_data["tariffs_cache"][tariff_id] @@ -139,26 +139,18 @@ async def execute_bulk_updates(session: AsyncSession, bulk_updates: dict[str, An for tg_id, balance_change in bulk_updates["balance_changes"].items(): await session.execute( text("UPDATE users SET balance = balance + :change WHERE tg_id = :tg_id"), - {"change": balance_change, "tg_id": tg_id} + {"change": balance_change, "tg_id": tg_id}, ) logger.info(f"Bulk: обновлено {len(bulk_updates['balance_changes'])} балансов") if bulk_updates["key_expiry_updates"]: for client_id, new_expiry in bulk_updates["key_expiry_updates"]: - await session.execute( - update(Key) - .where(Key.client_id == client_id) - .values(expiry_time=new_expiry) - ) + await session.execute(update(Key).where(Key.client_id == client_id).values(expiry_time=new_expiry)) logger.info(f"Bulk: обновлено {len(bulk_updates['key_expiry_updates'])} сроков действия ключей") if bulk_updates["key_tariff_updates"]: for client_id, new_tariff_id in bulk_updates["key_tariff_updates"]: - await session.execute( - update(Key) - .where(Key.client_id == client_id) - .values(tariff_id=new_tariff_id) - ) + await session.execute(update(Key).where(Key.client_id == client_id).values(tariff_id=new_tariff_id)) logger.info(f"Bulk: обновлено {len(bulk_updates['key_tariff_updates'])} тарифов ключей") for tg_id, notification_type in bulk_updates["notifications_to_add"]: @@ -184,9 +176,9 @@ async def execute_bulk_updates(session: AsyncSession, bulk_updates: dict[str, An async def send_expiry_warning(ctx: NotificationContext, key, hours_left: int, photo: str) -> bool: tg_id = key.tg_id email = key.email or "" - + expiry_data = await prepare_key_expiry_data(key, ctx.session, ctx.current_time) - + message_text = KEY_EXPIRY.format( email=email, hours_left_formatted=expiry_data["hours_left_formatted"], @@ -194,7 +186,7 @@ async def send_expiry_warning(ctx: NotificationContext, key, hours_left: int, ph tariff_name=expiry_data["tariff_name"], tariff_details=expiry_data["tariff_details"], ) - + keyboard = build_notification_kb(email) return await send_notification(ctx.bot, tg_id, photo, message_text, keyboard) @@ -202,9 +194,9 @@ async def send_expiry_warning(ctx: NotificationContext, key, hours_left: int, ph async def send_cannot_renew(ctx: NotificationContext, key, photo: str) -> bool: tg_id = key.tg_id email = key.email or "" - + expiry_data = await prepare_key_expiry_data(key, ctx.session, ctx.current_time) - + message_text = KEY_CANNOT_RENEW_CURRENT.format( email=email, hours_left_formatted=expiry_data["hours_left_formatted"], @@ -212,7 +204,7 @@ async def send_cannot_renew(ctx: NotificationContext, key, photo: str) -> bool: tariff_name=expiry_data["tariff_name"], tariff_details=expiry_data["tariff_details"], ) - + keyboard = build_change_tariff_kb(email) return await send_notification(ctx.bot, tg_id, photo, message_text, keyboard) @@ -220,7 +212,7 @@ async def send_cannot_renew(ctx: NotificationContext, key, photo: str) -> bool: async def send_expired_notification(ctx: NotificationContext, key, delay_minutes: int) -> bool: tg_id = key.tg_id email = key.email or "" - + if delay_minutes > 0: hours = delay_minutes // 60 minutes = delay_minutes % 60 @@ -233,7 +225,7 @@ async def send_expired_notification(ctx: NotificationContext, key, delay_minutes message_text = KEY_EXPIRED_DELAY_MSG.format(email=email, time_formatted=time_formatted) else: message_text = KEY_EXPIRED_NO_DELAY_MSG.format(email=email) - + keyboard = build_notification_kb(email) return await send_notification(ctx.bot, tg_id, "notify_expired.jpg", message_text, keyboard) @@ -241,7 +233,7 @@ async def send_expired_notification(ctx: NotificationContext, key, delay_minutes async def send_deleted_notification(ctx: NotificationContext, key) -> bool: tg_id = key.tg_id email = key.email or "" - + message_text = KEY_DELETED_MSG.format(email=email) keyboard = build_notification_expired_kb() return await send_notification(ctx.bot, tg_id, "notify_expired.jpg", message_text, keyboard) @@ -250,11 +242,11 @@ async def send_deleted_notification(ctx: NotificationContext, key) -> bool: async def send_renewed_notification(ctx: NotificationContext, key, tariff: dict, new_expiry_time: int) -> bool: tg_id = key.tg_id email = key.email or "" - + selected_device_limit = getattr(key, "selected_device_limit", None) selected_traffic_limit = getattr(key, "selected_traffic_limit", None) selected_traffic_gb = int(selected_traffic_limit) if selected_traffic_limit is not None else None - + device_limit_effective, traffic_limit_bytes_effective = await get_effective_limits_for_key( session=ctx.session, tariff_id=int(tariff["id"]), @@ -262,13 +254,13 @@ async def send_renewed_notification(ctx: NotificationContext, key, tariff: dict, selected_traffic_gb=selected_traffic_gb, ) traffic_limit_gb = int(traffic_limit_bytes_effective / GB) if traffic_limit_bytes_effective else 0 - + formatted_expiry_date = datetime.fromtimestamp(new_expiry_time / 1000, tz=moscow_tz).strftime("%d %B %Y, %H:%M") formatted_expiry_date = formatted_expiry_date.replace( datetime.fromtimestamp(new_expiry_time / 1000, tz=moscow_tz).strftime("%B"), get_russian_month(datetime.fromtimestamp(new_expiry_time / 1000, tz=moscow_tz)), ) - + message_text = get_renewal_message( tariff_name=tariff["name"], traffic_limit=traffic_limit_gb, @@ -276,15 +268,15 @@ async def send_renewed_notification(ctx: NotificationContext, key, tariff: dict, expiry_date=formatted_expiry_date, subgroup_title=tariff.get("subgroup_title", ""), ) - + keyboard = build_notification_expired_kb() result = await send_notification(ctx.bot, tg_id, "notify_expired.jpg", message_text, keyboard) - + if result: logger.info(f"✅ Уведомление о продлении подписки {email} отправлено пользователю {tg_id}.") else: logger.warning(f"📢 Не удалось отправить уведомление о продлении подписки {email} пользователю {tg_id}.") - + return result @@ -292,34 +284,34 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ tg_id = key.tg_id email = key.email or "" renew_notification_id = f"{email}_renew" - + can_renew = await check_notification_time(ctx.session, tg_id, renew_notification_id, hours=24) if not can_renew: logger.debug(f"⏳ Подписка {email} уже продлевалась в течение последних 24 часов.") return False, None, None - + if ctx.preload_data and tg_id in ctx.preload_data.get("balances_cache", {}): balance = ctx.preload_data["balances_cache"][tg_id] else: balance = await get_balance(ctx.session, tg_id) - + server_id = key.server_id tariff_id = key.tariff_id - + tariffs = await get_tariffs_for_cluster(ctx.session, server_id) if not tariffs: logger.warning(f"⛔ Нет доступных тарифов для продления подписки {email}") return False, None, None - + current_tariff = None if tariff_id: current_tariff = ctx.get_tariff(tariff_id) if not current_tariff and await check_tariff_exists(ctx.session, tariff_id): current_tariff = await get_tariff_by_id(ctx.session, tariff_id) - + if not current_tariff: return False, None, None - + forbidden_groups = ["discounts", "discounts_max", "gifts", "trial"] try: hook_results = await run_hooks("renewal_forbidden_groups", chat_id=tg_id, admin=False, session=ctx.session) @@ -328,10 +320,10 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ forbidden_groups.extend(additional_groups) except Exception as error: logger.warning(f"[AUTO_RENEW] Ошибка при получении дополнительных групп: {error}") - + if current_tariff["group_code"] in forbidden_groups: return False, None, None - + renewal_cost = await resolve_price_to_charge( ctx.session, { @@ -341,18 +333,18 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ "selected_price_rub": getattr(key, "selected_price_rub", None), }, ) - + if renewal_cost is None or balance < renewal_cost: return False, None, None - + client_id = key.client_id current_expiry = key.expiry_time duration_days = current_tariff["duration_days"] - + selected_device_limit = getattr(key, "selected_device_limit", None) selected_traffic_limit = getattr(key, "selected_traffic_limit", None) selected_traffic_gb = int(selected_traffic_limit) if selected_traffic_limit is not None else None - + device_limit_effective, traffic_limit_bytes_effective = await get_effective_limits_for_key( session=ctx.session, tariff_id=int(current_tariff["id"]), @@ -360,20 +352,20 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ selected_traffic_gb=selected_traffic_gb, ) traffic_limit_gb = int(traffic_limit_bytes_effective / GB) if traffic_limit_bytes_effective else 0 - + new_expiry_time = ( current_expiry if current_expiry > datetime.utcnow().timestamp() * 1000 else datetime.utcnow().timestamp() * 1000 ) + duration_days * 24 * 60 * 60 * 1000 - + logger.info( f"Продление подписки {email} на {duration_days} дней для пользователя {tg_id}. " f"Баланс: {balance}, списываем: {renewal_cost}" ) - + key_subgroup = current_tariff.get("subgroup_title") - + await renew_key_in_cluster( cluster_id=server_id, email=email, @@ -386,13 +378,13 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ old_subgroup=key_subgroup, plan=current_tariff["id"], ) - + if ctx.bulk_updates is not None: if tg_id in ctx.bulk_updates["balance_changes"]: ctx.bulk_updates["balance_changes"][tg_id] -= renewal_cost else: ctx.bulk_updates["balance_changes"][tg_id] = -renewal_cost - + ctx.bulk_updates["key_expiry_updates"].append((client_id, int(new_expiry_time))) ctx.bulk_updates["key_tariff_updates"].append((client_id, current_tariff["id"])) ctx.bulk_updates["notifications_to_add"].append((tg_id, renew_notification_id)) @@ -401,7 +393,7 @@ async def try_auto_renew(ctx: NotificationContext, key) -> tuple[bool, Optional[ await update_key_expiry(ctx.session, client_id, int(new_expiry_time)) await update_key_tariff(ctx.session, client_id, current_tariff["id"]) await add_notification(ctx.session, tg_id, renew_notification_id) - + return True, current_tariff, int(new_expiry_time) @@ -418,47 +410,47 @@ async def notify_expiring_keys( logger.info(f"Начало проверки подписок, истекающих через {min_hours}-{max_hours} часов.") else: logger.info(f"Начало проверки подписок, истекающих через {max_hours} часов.") - + min_threshold = int((datetime.now(moscow_tz) + timedelta(hours=min_hours)).timestamp() * 1000) max_threshold = int((datetime.now(moscow_tz) + timedelta(hours=max_hours)).timestamp() * 1000) expiring_keys = [key for key in keys if key.expiry_time and min_threshold < key.expiry_time <= max_threshold] - + if min_hours > 0: logger.info(f"Найдено {len(expiring_keys)} подписок, истекающих через {min_hours}-{max_hours} часов.") else: logger.info(f"Найдено {len(expiring_keys)} подписок, истекающих через {max_hours} часов.") - + tg_ids = [key.tg_id for key in expiring_keys] emails = [key.email or "" for key in expiring_keys] allowed = await check_notifications_bulk(ctx.session, notify_type, max_hours, tg_ids=tg_ids, emails=emails) allowed_set = {(user["tg_id"], user["email"]) for user in allowed} - + messages = [] - + for key in expiring_keys: tg_id = key.tg_id email = key.email or "" - + if (tg_id, email) not in allowed_set: continue - + notification_id = f"{email}_{notify_type}" - + can_notify = await check_notification_time(ctx.session, tg_id, notification_id, hours=max_hours) if not can_notify: continue - + if notify_renew_enabled: try: renewed, tariff, new_expiry = await try_auto_renew(ctx, key) - + if renewed and tariff and new_expiry: await send_renewed_notification(ctx, key, tariff, new_expiry) await add_notification(ctx.session, tg_id, notification_id) else: await send_cannot_renew(ctx, key, photo) await add_notification(ctx.session, tg_id, notification_id) - + except Exception as error: logger.error(f"Ошибка авто-продления/уведомления для пользователя {tg_id}: {error}") else: @@ -479,7 +471,7 @@ async def notify_expiring_keys( "notification_id": notification_id, "email": email, }) - + if messages: results = await send_messages_with_limit(ctx.bot, messages, session=ctx.session) sent_count = 0 @@ -487,41 +479,43 @@ async def notify_expiring_keys( await add_notification(ctx.session, msg["tg_id"], msg["notification_id"]) if result: sent_count += 1 - logger.info(f"Отправлено уведомление об истекающей подписке {msg['email']} пользователю {msg['tg_id']}.") + logger.info( + f"Отправлено уведомление об истекающей подписке {msg['email']} пользователю {msg['tg_id']}." + ) logger.info(f"Отправлено {sent_count} уведомлений типа {notify_type}.") - + logger.info(f"Обработка уведомлений {notify_type} завершена.") await asyncio.sleep(1) async def handle_expired_keys(ctx: NotificationContext, keys: list): logger.info("Начало обработки истекших ключей.") - + expired_keys = [key for key in keys if key.expiry_time and key.expiry_time < ctx.current_time] logger.info(f"Найдено {len(expired_keys)} истекших ключей.") - + tg_ids = [key.tg_id for key in expired_keys] emails = [key.email or "" for key in expired_keys] users = await check_notifications_bulk(ctx.session, "key_expired", 0, tg_ids=tg_ids, emails=emails) users_set = {(user["tg_id"], user["email"]) for user in users} - + notify_renew_expired_enabled = bool(NOTIFICATIONS_CONFIG.get("RENEW_EXPIRED_ENABLED", NOTIFY_RENEW_EXPIRED)) notify_delete_key_enabled = bool(NOTIFICATIONS_CONFIG.get("DELETE_KEY_ENABLED", NOTIFY_DELETE_KEY)) delete_key_delay_minutes = int(NOTIFICATIONS_CONFIG.get("DELETE_KEY_DELAY_MINUTES", NOTIFY_DELETE_DELAY)) - + for key in expired_keys: tg_id = key.tg_id email = key.email or "" client_id = key.client_id server_id = key.server_id notification_id = f"{email}_key_expired" - + last_notification_time = await get_last_notification_time(ctx.session, tg_id, notification_id) - + if notify_renew_expired_enabled: try: renewed, tariff, new_expiry = await try_auto_renew(ctx, key) - + if renewed and tariff and new_expiry: await send_renewed_notification(ctx, key, tariff, new_expiry) if ctx.bulk_updates: @@ -529,36 +523,36 @@ async def handle_expired_keys(ctx: NotificationContext, keys: list): else: await delete_notification(ctx.session, tg_id, notification_id) continue - + except Exception as error: logger.error(f"Ошибка авто-продления для пользователя {tg_id}: {error}") continue - + if notify_delete_key_enabled: should_delete = False - + if delete_key_delay_minutes == 0: should_delete = True elif last_notification_time is not None: minutes_passed = (ctx.current_time - last_notification_time) / (1000 * 60) should_delete = minutes_passed >= delete_key_delay_minutes logger.info(f"Прошло минут={minutes_passed:.2f} DELETE_KEY_DELAY_MINUTES={delete_key_delay_minutes}") - + if should_delete: try: await delete_key_from_cluster(server_id, email, client_id, ctx.session) await delete_key(ctx.session, client_id) logger.info(f"🗑 Ключ {client_id} для пользователя {tg_id} успешно удалён.") - + await send_deleted_notification(ctx, key) except Exception as error: logger.error(f"Ошибка удаления ключа {client_id} для пользователя {tg_id}: {error}") continue - + if last_notification_time is None and (tg_id, email) in users_set: await send_expired_notification(ctx, key, delete_key_delay_minutes) await add_notification(ctx.session, tg_id, notification_id) - + logger.info("Обработка истекших ключей завершена.") await asyncio.sleep(1) @@ -566,20 +560,20 @@ async def handle_expired_keys(ctx: NotificationContext, keys: list): async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): while True: notification_interval = int(NOTIFICATIONS_CONFIG.get("BASE_NOTIFICATION_MINUTE", NOTIFICATION_TIME)) - + if notification_lock.locked(): logger.warning("Уведомления уже выполняются. Пропуск...") await asyncio.sleep(notification_interval) continue - + async with notification_lock: try: async with sessionmaker() as session: logger.info("Запуск обработки уведомлений") - + current_time = int(datetime.now(moscow_tz).timestamp() * 1000) start_time = datetime.now() - + try: preload_data = await preload_notification_data(session) keys_data = preload_data["keys_data"] @@ -589,7 +583,7 @@ async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): f"Предзагружено данных: {len(keys)} ключей, " f"{len(preload_data['tariffs_cache'])} тарифов за {preload_time:.2f}s" ) - + bulk_updates = { "balance_changes": {}, "key_expiry_updates": [], @@ -597,7 +591,7 @@ async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): "notifications_to_add": [], "notifications_to_delete": [], } - + except Exception as error: logger.error(f"Ошибка при предварительной загрузке данных: {error}") try: @@ -612,7 +606,7 @@ async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): keys = [] preload_data = None bulk_updates = None - + ctx = NotificationContext( bot=bot, session=session, @@ -620,85 +614,93 @@ async def periodic_notifications(bot: Bot, *, sessionmaker: async_sessionmaker): preload_data=preload_data, bulk_updates=bulk_updates, ) - + trial_time_disable = bool(MODES_CONFIG.get("TRIAL_TIME_DISABLED", TRIAL_TIME_DISABLE)) if not trial_time_disable: try: await notify_inactive_trial_users(bot, session) except Exception as error: logger.error(f"Ошибка в notify_inactive_trial_users: {error}") - + notify_24_enabled = bool(NOTIFICATIONS_CONFIG.get("EXPIRY_24H_ENABLED", NOTIFY_24H_ENABLED)) notify_24_hours = int(NOTIFICATIONS_CONFIG.get("EXPIRY_24H_BEFORE_HOURS", NOTIFY_24H_HOURS)) notify_10_enabled = bool(NOTIFICATIONS_CONFIG.get("EXPIRY_10H_ENABLED", NOTIFY_10H_ENABLED)) notify_10_hours = int(NOTIFICATIONS_CONFIG.get("EXPIRY_10H_BEFORE_HOURS", NOTIFY_10H_HOURS)) notify_renew_enabled = bool(NOTIFICATIONS_CONFIG.get("RENEW_ENABLED", NOTIFY_RENEW)) - inactive_traffic_enabled = bool(NOTIFICATIONS_CONFIG.get("INACTIVE_TRAFFIC_ENABLED", NOTIFY_INACTIVE_TRAFFIC)) + inactive_traffic_enabled = bool( + NOTIFICATIONS_CONFIG.get("INACTIVE_TRAFFIC_ENABLED", NOTIFY_INACTIVE_TRAFFIC) + ) notify_hot_leads_enabled = bool(NOTIFICATIONS_CONFIG.get("HOT_LEADS_ENABLED", NOTIFY_HOT_LEADS)) - + if notify_24_enabled: try: await notify_expiring_keys( - ctx, keys, + ctx, + keys, min_hours=notify_10_hours if notify_10_enabled else 0, max_hours=notify_24_hours, - notify_type="key_24h", - photo="notify_24h.jpg", - notify_renew_enabled=notify_renew_enabled + notify_type="key_24h", + photo="notify_24h.jpg", + notify_renew_enabled=notify_renew_enabled, ) except Exception as error: logger.error(f"Ошибка в notify_expiring_keys (24h): {error}") - + if notify_10_enabled: try: await notify_expiring_keys( - ctx, keys, + ctx, + keys, min_hours=0, max_hours=notify_10_hours, - notify_type="key_10h", - photo="notify_10h.jpg", - notify_renew_enabled=notify_renew_enabled + notify_type="key_10h", + photo="notify_10h.jpg", + notify_renew_enabled=notify_renew_enabled, ) except Exception as error: logger.error(f"Ошибка в notify_expiring_keys (10h): {error}") - + try: await handle_expired_keys(ctx, keys) except Exception as error: logger.error(f"Ошибка в handle_expired_keys: {error}") - + if inactive_traffic_enabled: try: await notify_users_no_traffic(bot, session, current_time, keys) except Exception as error: logger.error(f"Ошибка в notify_users_no_traffic: {error}") - + try: await run_hooks("periodic_notifications", bot=bot, session=session, keys=keys) except Exception as error: logger.error(f"Ошибка в хуках periodic_notifications: {error}") - + if notify_hot_leads_enabled: try: await notify_hot_leads(bot, session) except Exception as error: logger.error(f"Ошибка в notify_hot_leads: {error}") - + if bulk_updates: bulk_start = datetime.now() await execute_bulk_updates(session, bulk_updates) bulk_time = (datetime.now() - bulk_start).total_seconds() total_renewals = len(bulk_updates["balance_changes"]) - total_key_updates = len(bulk_updates["key_expiry_updates"]) + len(bulk_updates["key_tariff_updates"]) - total_notification_updates = len(bulk_updates["notifications_to_add"]) + len(bulk_updates["notifications_to_delete"]) + total_key_updates = len(bulk_updates["key_expiry_updates"]) + len( + bulk_updates["key_tariff_updates"] + ) + total_notification_updates = len(bulk_updates["notifications_to_add"]) + len( + bulk_updates["notifications_to_delete"] + ) logger.info( f"Bulk-операции выполнены за {bulk_time:.2f}s. Обработано: {total_renewals} продлений, {total_key_updates} ключей, {total_notification_updates} уведомлений" ) - + total_time = (datetime.now() - start_time).total_seconds() logger.info(f"Уведомления завершены за {total_time:.2f}s") - + except Exception as error: logger.error(f"Ошибка в periodic_notifications: {error}") - + await asyncio.sleep(notification_interval) diff --git a/handlers/notifications/notify_utils.py b/handlers/notifications/notify_utils.py index 4e59ae71..58fb07f9 100644 --- a/handlers/notifications/notify_utils.py +++ b/handlers/notifications/notify_utils.py @@ -152,6 +152,7 @@ class FastNotificationSender: try: from sqlalchemy.dialects.postgresql import insert from database.models import BlockedUser + values = [{"tg_id": tg_id} for tg_id in self.blocked_users] stmt = insert(BlockedUser).values(values).on_conflict_do_nothing(index_elements=[BlockedUser.tg_id]) await self.session.execute(stmt) diff --git a/handlers/notifications/special_notifications.py b/handlers/notifications/special_notifications.py index 1d08542e..e0d48b0b 100644 --- a/handlers/notifications/special_notifications.py +++ b/handlers/notifications/special_notifications.py @@ -49,7 +49,7 @@ async def notify_inactive_trial_users(bot: Bot, session: AsyncSession): users = await check_notifications_bulk(session, "inactive_trial", inactive_hours) logger.info(f"Найдено {len(users)} неактивных пользователей для уведомления.") - + if not users: logger.info("Проверка пользователей с неактивным пробным периодом завершена.") return @@ -106,22 +106,20 @@ async def notify_inactive_trial_users(bot: Bot, session: AsyncSession): source_file="special_notifications", messages_per_second=25, ) - + sent_tg_ids = [] for msg, result in zip(messages, results, strict=False): if result: sent_tg_ids.append(msg["tg_id"]) - + if sent_tg_ids: for tg_id in sent_tg_ids: await add_notification(session, tg_id, "inactive_trial") logger.info(f"Отправлено {len(sent_tg_ids)} уведомлений неактивным пользователям.") - + extend_ids = [tg_id for tg_id in users_to_extend if tg_id in sent_tg_ids] if extend_ids: - await session.execute( - update(User).where(User.tg_id.in_(extend_ids)).values(trial=-1) - ) + await session.execute(update(User).where(User.tg_id.in_(extend_ids)).values(trial=-1)) await session.commit() logger.info(f"Bulk: отмечено {len(extend_ids)} пользователей с расширенным триалом") @@ -139,12 +137,12 @@ async def notify_users_no_traffic(bot: Bot, session: AsyncSession, current_time: trial_tariffs = await get_tariffs(session, group_code="trial") trial_tariff_ids = {t["id"] for t in trial_tariffs} if trial_tariffs else set() - + if not trial_tariff_ids: return remnawave_webapp_enabled = bool(MODES_CONFIG.get("REMNAWAVE_WEBAPP_ENABLED", REMNAWAVE_WEBAPP)) - + messages = [] keys_to_mark_notified = [] @@ -232,9 +230,7 @@ async def notify_users_no_traffic(bot: Bot, session: AsyncSession, current_time: if keys_to_mark_notified: try: - await session.execute( - update(Key).where(Key.client_id.in_(keys_to_mark_notified)).values(notified=True) - ) + await session.execute(update(Key).where(Key.client_id.in_(keys_to_mark_notified)).values(notified=True)) await session.commit() logger.info(f"Bulk: отмечено {len(keys_to_mark_notified)} ключей как notified") except Exception as error: diff --git a/handlers/payments/constants.py b/handlers/payments/constants.py index ea30cdd4..a8e31802 100644 --- a/handlers/payments/constants.py +++ b/handlers/payments/constants.py @@ -3,4 +3,4 @@ ALLOWED_TEMP_PAYMENT_STATES = { "waiting_for_renewal_payment", "waiting_for_gift_payment", "waiting_for_addons_payment", -} \ No newline at end of file +} diff --git a/handlers/payments/currency_flow.py b/handlers/payments/currency_flow.py index 97e5e96d..9f3f9ff3 100644 --- a/handlers/payments/currency_flow.py +++ b/handlers/payments/currency_flow.py @@ -18,7 +18,7 @@ def build_currency_choice_kb( kb.row(InlineKeyboardButton(text=RUB_CURRENCY, callback_data=f"{prefix}|RUB")) kb.row(InlineKeyboardButton(text=USD_CURRENCY, callback_data=f"{prefix}|USD")) trib = (TRIBUTE_LINK or "").strip() - trib_enabled = (bool(trib) if show_tribute is None else bool(show_tribute) and bool(trib)) + trib_enabled = bool(trib) if show_tribute is None else bool(show_tribute) and bool(trib) if show_stars: row = [InlineKeyboardButton(text=STARS, callback_data=f"{prefix}|STARS")] diff --git a/handlers/payments/fast_payment_flow.py b/handlers/payments/fast_payment_flow.py index e8c021b1..561909f2 100644 --- a/handlers/payments/fast_payment_flow.py +++ b/handlers/payments/fast_payment_flow.py @@ -119,18 +119,10 @@ async def try_fast_payment_flow( tribute_cfg = providers_map.get("TRIBUTE") or {} tribute_link = (TRIBUTE_LINK or "").strip() - tribute_enabled = ( - "TRIBUTE" in configured_set - and tribute_cfg.get("enabled", True) - and bool(tribute_link) - ) + tribute_enabled = "TRIBUTE" in configured_set and tribute_cfg.get("enabled", True) and bool(tribute_link) stars_cfg = providers_map.get("STARS") or {} - stars_enabled_for_fast = ( - "STARS" in configured_set - and stars_cfg.get("fast") - and stars_cfg.get("enabled", True) - ) + stars_enabled_for_fast = "STARS" in configured_set and stars_cfg.get("fast") and stars_cfg.get("enabled", True) if multicurrency_mode and not one_screen: show_stars = stars_enabled_for_fast diff --git a/handlers/payments/gift.cpython-312-x86_64-linux-gnu.so b/handlers/payments/gift.cpython-312-x86_64-linux-gnu.so index 26e68c53098800470afe76cbb61ef1f259c29253..f2dd0e9c0562974b8ac77dad9ba060ed426f007f 100644 GIT binary patch delta 512258 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 z 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

H@@K0~( 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 z�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 z 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