From 9fed81082fdcadb0cabfebd86fbfb0c97856e113 Mon Sep 17 00:00:00 2001 From: sasheg Date: Sat, 25 Jul 2026 13:37:39 +0000 Subject: [PATCH] Fix hot-path endpoints: proper async DB sessions and awaited calls Convert all money-flow endpoints (api_open_case, api_submit_contract, api_execute_upgrade, api_sell_item, api_sell_bulk_items, api_open_multiple_cases, api_open_slot_case, api_open_case_animated, api_crash_bet, api_crash_cashout, api_get_inventory, api_item_detail, api_rpu_info) to use AsyncSession + await throughout. Critical bugfix: rpu.py and achievements.py functions (all async def) were being called without 'await' and with sync Session objects, which returned coroutine objects instead of actual data. This made RPU weight adjustment, achievement tracking, and stat updates non-functional. Also added AsyncSession to imports. --- frontend.py | 318 ++++++++++++++++++++++++++++------------------------ 1 file changed, 173 insertions(+), 145 deletions(-) diff --git a/frontend.py b/frontend.py index 4deeca9..715a06b 100644 --- a/frontend.py +++ b/frontend.py @@ -29,7 +29,7 @@ from pathlib import Path import json from pathlib import Path -from database import get_db, get_db_executor, get_async_db, AsyncSessionLocal, SessionLocal, User, InventoryItem, CaseOpening, Contract, Upgrade, UpgradeRPU, PromoCode +from database import get_db, get_db_executor, get_async_db, AsyncSessionLocal, SessionLocal, AsyncSession, User, InventoryItem, CaseOpening, Contract, Upgrade, UpgradeRPU, PromoCode from websocket_manager import manager, crash_game from sqlalchemy import select, func as sa_func, desc from achievements import ( @@ -890,7 +890,7 @@ def open_case_with_rpu(case_name: str, adjusted_weights: dict = None) -> dict: async def api_open_case( case_name: str = Form(...), count: int = Form(1), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Открытие кейса с проверкой баланса и учетом РПУ""" @@ -916,7 +916,7 @@ async def api_open_case( _rpu_mod._BATCH_MODE = True try: # Один раз считаем RPU на всю пачку (кэшируется внутри) - adjusted_weights = get_adjusted_weights(db, user.id) + adjusted_weights = await get_adjusted_weights(db, user.id) results = [] for _ in range(count): result = open_case_with_rpu(case_name, adjusted_weights) @@ -975,34 +975,35 @@ async def api_open_case( # Определяем был ли редкий дроп had_rare = any(r.get("rarity") in ("Covert", "Rare Special Item", "Extraordinary") for r in results) - update_rpu_stats(db, user.id, total_price, count, total_received, - rarity=results[0]["rarity"] if results else None, is_rare=had_rare) + await update_rpu_stats(db, user.id, total_price, count, total_received, + rarity=results[0]["rarity"] if results else None, is_rare=had_rare) # Проверка достижений unlocked_ach = [] - open_count = db.query(CaseOpening).filter(CaseOpening.user_id == user.id).count() - unlocked_ach += check_open_cases_achievements(db, user.id) - user_rpu = get_user_rpu(db, user.id) + open_count_result = await db.execute(select(sa_func.count(CaseOpening.id)).filter(CaseOpening.user_id == user.id)) + open_count = open_count_result.scalar() + unlocked_ach += await check_open_cases_achievements(db, user.id) + user_rpu = await get_user_rpu(db, user.id) total_spent = user_rpu.total_spent - unlocked_ach += check_spent_achievements(db, user.id, total_spent) + unlocked_ach += await check_spent_achievements(db, user.id, total_spent) for r in results: - unlocked_ach += check_rare_item_achievement(db, user.id, r.get("rarity", "")) + unlocked_ach += await check_rare_item_achievement(db, user.id, r.get("rarity", "")) item_data = get_item(r.get("id", 0)) if item_data: - unlocked_ach += check_knife_achievement(db, user.id, item_data) + unlocked_ach += await check_knife_achievement(db, user.id, item_data) - unlocked_ach += check_inventory_achievements(db, user.id) - unlocked_ach += check_dildo_achievements(db, user.id) - unlocked_ach += check_items_unboxed_achievements(db, user.id) - unlocked_ach += check_rare_item_count_achievements(db, user.id) - unlocked_ach += check_knife_count_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) - unlocked_ach += check_midnight_case_achievement(db, user.id) - unlocked_ach += check_exact_cases_achievement(db, user.id, open_count) + unlocked_ach += await check_inventory_achievements(db, user.id) + unlocked_ach += await check_dildo_achievements(db, user.id) + unlocked_ach += await check_items_unboxed_achievements(db, user.id) + unlocked_ach += await check_rare_item_count_achievements(db, user.id) + unlocked_ach += await check_knife_count_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) + unlocked_ach += await check_midnight_case_achievement(db, user.id) + unlocked_ach += await check_exact_cases_achievement(db, user.id, open_count) profit = user.balance + total_spent - unlocked_ach += check_total_profit_achievements(db, user.id, profit) + unlocked_ach += await check_total_profit_achievements(db, user.id, profit) # Запись активности — используем ту же db-сессию for r in results: @@ -1029,7 +1030,7 @@ async def api_open_case( _rpu_mod._batch_cache_clear() # Один большой commit вместо 40+ мелких - db.commit() + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -1163,17 +1164,17 @@ async def api_promo_list( @app.get("/web/api/rpu-info") async def api_rpu_info( - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): from rpu import get_rpu_v2_info - return get_rpu_v2_info(db, user.id) + return await get_rpu_v2_info(db, user.id) @app.post("/web/api/contracts/submit") async def api_submit_contract( inventory_ids: str = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): try: @@ -1189,10 +1190,13 @@ async def api_submit_contract( all_knives = True for inv_id in ids: - inv_item = db.query(InventoryItem).filter( - InventoryItem.id == inv_id, - InventoryItem.user_id == user.id - ).first() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id == inv_id, + InventoryItem.user_id == user.id + ) + ) + inv_item = result.scalar_one_or_none() if not inv_item: return JSONResponse(status_code=400, content={"error": f"Item {inv_id} not found"}) @@ -1221,8 +1225,8 @@ async def api_submit_contract( # Крафт дилдоков из ножей if all_knives and len(inventory_items) == 10: for inv_item in inventory_items: - db.delete(inv_item) - db.commit() + await db.delete(inv_item) + await db.commit() dildo_items = get_dildo_items() if not dildo_items: @@ -1285,7 +1289,7 @@ async def api_submit_contract( result.probability = 0.01 for inv_item in inventory_items: - db.delete(inv_item) + await db.delete(inv_item) received_item_data = get_item(result.received_item.id) @@ -1313,15 +1317,15 @@ async def api_submit_contract( ) db.add(contract) - db.commit() + await db.commit() - unlocked_ach = check_contracts_achievements(db, user.id) - unlocked_ach += check_inventory_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_dildo_achievements(db, user.id) - unlocked_ach += check_dildo_contract_achievement(db, user.id) - unlocked_ach += check_collection_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach = await check_contracts_achievements(db, user.id) + unlocked_ach += await check_inventory_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_dildo_achievements(db, user.id) + unlocked_ach += await check_dildo_contract_achievement(db, user.id) + unlocked_ach += await check_collection_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) act = record_activity_own_session(user.id, user.username, "contract", f"🔄 выполнил(а) контракт и получил(а) {result.received_item.market_hash_name}", @@ -1352,14 +1356,17 @@ async def api_submit_contract( @app.get("/web/api/inventory/items") async def api_get_inventory( - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Получение предметов инвентаря""" - items = db.query(InventoryItem).filter( - InventoryItem.user_id == user.id - ).order_by(desc(InventoryItem.obtained_at)).all() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.user_id == user.id + ).order_by(desc(InventoryItem.obtained_at)) + ) + items = result.scalars().all() result = [] for item in items: @@ -1409,19 +1416,25 @@ async def get_item_image( @app.get("/web/api/inventory/item-detail/{inventory_id}") async def api_item_detail( inventory_id: int, - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Детальная информация о предмете с коллекцией""" - inv_item = db.query(InventoryItem).filter( - InventoryItem.id == inventory_id, - InventoryItem.user_id == user.id - ).first() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id == inventory_id, + InventoryItem.user_id == user.id + ) + ) + inv_item = result.scalar_one_or_none() if not inv_item: # Also allow viewing if item exists (public profiles) - inv_item = db.query(InventoryItem).filter( - InventoryItem.id == inventory_id - ).first() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id == inventory_id + ) + ) + inv_item = result.scalar_one_or_none() if not inv_item: return JSONResponse(status_code=404, content={"error": "Предмет не найден"}) @@ -1471,10 +1484,12 @@ async def api_item_detail( seen_base[base] = citem # Все предметы пользователя — для проверки владения - user_items = db.query(InventoryItem.item_id).filter( - InventoryItem.user_id == user.id - ).all() - user_item_ids = {iid for (iid,) in user_items} + user_items_result = await db.execute( + select(InventoryItem.item_id).filter( + InventoryItem.user_id == user.id + ) + ) + user_item_ids = {row[0] for row in user_items_result.all()} # Сортируем по редкости (низшая → высшая) sorted_bases = sorted(seen_base.values(), key=lambda x: RARITY_ORDER.get(x.get("rarity", "Unknown"), -1)) @@ -1707,7 +1722,7 @@ async def get_user_balance( @app.post("/web/api/cases/open/animated") async def api_open_case_animated( case_name: str = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Открытие кейса с анимацией (возвращает результат)""" @@ -1720,7 +1735,7 @@ async def api_open_case_animated( "error": f"Недостаточно средств. Нужно {price_per_case:.2f} ₽, у вас {user.balance:.2f} ₽" }) - adjusted_weights = get_adjusted_weights(db, user.id) + adjusted_weights = await get_adjusted_weights(db, user.id) result = open_case_with_rpu(case_name, adjusted_weights) if not result: @@ -1761,29 +1776,29 @@ async def api_open_case_animated( user.balance -= price_per_case # Обновляем РПУ - from rpu import update_rpu_stats - update_rpu_stats(db, user.id, price_per_case, 1, - item_data.get("price_rub", 0), - rarity=item_data.get("rarity"), - is_rare=item_data.get("rarity") in ("Covert", "Rare Special Item", "Extraordinary")) + await update_rpu_stats(db, user.id, price_per_case, 1, + item_data.get("price_rub", 0), + rarity=item_data.get("rarity"), + is_rare=item_data.get("rarity") in ("Covert", "Rare Special Item", "Extraordinary")) - db.commit() + await db.commit() # Проверка достижений unlocked_ach = [] - unlocked_ach += check_open_cases_achievements(db, user.id) - unlocked_ach += check_spent_achievements(db, user.id, get_user_rpu(db, user.id).total_spent) - unlocked_ach += check_rare_item_achievement(db, user.id, item_data.get("rarity", "")) + unlocked_ach += await check_open_cases_achievements(db, user.id) + user_rpu = await get_user_rpu(db, user.id) + unlocked_ach += await check_spent_achievements(db, user.id, user_rpu.total_spent) + unlocked_ach += await check_rare_item_achievement(db, user.id, item_data.get("rarity", "")) item_full = get_item(result["id"]) if item_full: - unlocked_ach += check_knife_achievement(db, user.id, item_full) - unlocked_ach += check_inventory_achievements(db, user.id) - unlocked_ach += check_dildo_achievements(db, user.id) - unlocked_ach += check_items_unboxed_achievements(db, user.id) - unlocked_ach += check_rare_item_count_achievements(db, user.id) - unlocked_ach += check_knife_count_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach += await check_knife_achievement(db, user.id, item_full) + unlocked_ach += await check_inventory_achievements(db, user.id) + unlocked_ach += await check_dildo_achievements(db, user.id) + unlocked_ach += await check_items_unboxed_achievements(db, user.id) + unlocked_ach += await check_rare_item_count_achievements(db, user.id) + unlocked_ach += await check_knife_count_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -2010,7 +2025,7 @@ def pick_slot_reel(grouped_items: list, adjusted_weights: dict, exclude_groups: async def api_open_slot_case( case_name: str = Form(...), free_spin: str = Form(""), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Слот-машина: 3 барабана, совпадение = приз""" @@ -2029,7 +2044,7 @@ async def api_open_slot_case( if not grouped_items or len(grouped_items) < 2: return JSONResponse(status_code=400, content={"error": "В кейсе недостаточно предметов"}) - adjusted_weights = get_adjusted_weights(db, user.id) + adjusted_weights = await get_adjusted_weights(db, user.id) # Буст для слотов: чаще выпадают активки SLOT_RARITY_BOOST = { @@ -2276,18 +2291,18 @@ async def api_open_slot_case( if not is_free: user.balance -= price_per_case - update_rpu_stats(db, user.id, price_per_case, 1) + await update_rpu_stats(db, user.id, price_per_case, 1) # Проверка достижений для слота unlocked_ach = [] if match: - unlocked_ach += check_slot_match_achievements(db, user.id) - unlocked_ach += check_slot_plays_achievements(db, user.id) - unlocked_ach += check_slot_match_count_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach += await check_slot_match_achievements(db, user.id) + unlocked_ach += await check_slot_plays_achievements(db, user.id) + unlocked_ach += await check_slot_match_count_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) - db.commit() + await db.commit() return JSONResponse({ "success": True, @@ -2309,7 +2324,7 @@ async def api_open_slot_case( async def api_open_multiple_cases( case_name: str = Form(...), count: int = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Открытие нескольких кейсов с группировкой и РПУ""" @@ -2354,7 +2369,7 @@ async def api_open_multiple_cases( _rpu_mod._BATCH_MODE = True try: # Один раз считаем RPU на всю пачку (кэшируется внутри) - adjusted_weights = get_adjusted_weights(db, user.id) + adjusted_weights = await get_adjusted_weights(db, user.id) results = [] for _ in range(count): result = open_case_with_variants_rpu(case_name, adjusted_weights) @@ -2423,10 +2438,10 @@ async def api_open_multiple_cases( # Обновляем статистику РПУ total_received = sum(r.get("price", 0) for r in results) had_rare = any(r.get("rarity") in ("Covert", "Rare Special Item", "Extraordinary") for r in results) - update_rpu_stats(db, user.id, total_price, count, total_received, - rarity=results[0]["rarity"] if results else None, is_rare=had_rare) + await update_rpu_stats(db, user.id, total_price, count, total_received, + rarity=results[0]["rarity"] if results else None, is_rare=had_rare) - db.commit() + await db.commit() finally: _rpu_mod._BATCH_MODE = False _rpu_mod._batch_cache_clear() @@ -2454,21 +2469,22 @@ async def api_open_multiple_cases( # Проверка достижений unlocked_ach = [] - unlocked_ach += check_open_cases_achievements(db, user.id) - unlocked_ach += check_spent_achievements(db, user.id, get_user_rpu(db, user.id).total_spent) - unlocked_ach += check_inventory_achievements(db, user.id) - unlocked_ach += check_dildo_achievements(db, user.id) - unlocked_ach += check_items_unboxed_achievements(db, user.id) - unlocked_ach += check_rare_item_count_achievements(db, user.id) - unlocked_ach += check_knife_count_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach += await check_open_cases_achievements(db, user.id) + user_rpu = await get_user_rpu(db, user.id) + unlocked_ach += await check_spent_achievements(db, user.id, user_rpu.total_spent) + unlocked_ach += await check_inventory_achievements(db, user.id) + unlocked_ach += await check_dildo_achievements(db, user.id) + unlocked_ach += await check_items_unboxed_achievements(db, user.id) + unlocked_ach += await check_rare_item_count_achievements(db, user.id) + unlocked_ach += await check_knife_count_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) for r in results: - unlocked_ach += check_rare_item_achievement(db, user.id, r.get("rarity", "")) + unlocked_ach += await check_rare_item_achievement(db, user.id, r.get("rarity", "")) item_full = get_item(r.get("id", 0)) if item_full: - unlocked_ach += check_knife_achievement(db, user.id, item_full) + unlocked_ach += await check_knife_achievement(db, user.id, item_full) asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -2487,15 +2503,18 @@ async def api_open_multiple_cases( @app.post("/web/api/inventory/sell") async def api_sell_item( inventory_id: int = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Продажа предмета из инвентаря""" - inv_item = db.query(InventoryItem).filter( - InventoryItem.id == inventory_id, - InventoryItem.user_id == user.id - ).first() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id == inventory_id, + InventoryItem.user_id == user.id + ) + ) + inv_item = result.scalar_one_or_none() if not inv_item: return JSONResponse(status_code=400, content={"error": "Предмет не найден"}) @@ -2513,8 +2532,8 @@ async def api_sell_item( user.balance += price # Удаляем предмет - db.delete(inv_item) - db.commit() + await db.delete(inv_item) + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -2531,7 +2550,7 @@ async def api_sell_item( @app.post("/web/api/inventory/sell/bulk") async def api_sell_bulk_items( inventory_ids: str = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): """Массовая продажа предметов из инвентаря""" @@ -2545,10 +2564,13 @@ async def api_sell_bulk_items( return JSONResponse(status_code=400, content={"error": "Не выбрано ни одного предмета"}) # Получаем предметы - items_to_sell = db.query(InventoryItem).filter( - InventoryItem.id.in_(ids), - InventoryItem.user_id == user.id - ).all() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id.in_(ids), + InventoryItem.user_id == user.id + ) + ) + items_to_sell = result.scalars().all() if not items_to_sell: return JSONResponse(status_code=400, content={"error": "Предметы не найдены"}) @@ -2569,11 +2591,11 @@ async def api_sell_bulk_items( sold_count += 1 # Удаляем предмет - db.delete(inv_item) + await db.delete(inv_item) # Начисляем деньги user.balance += total_received - db.commit() + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -2764,13 +2786,16 @@ async def api_execute_upgrade( input_inventory_id: int = Form(...), target_item_id: int = Form(...), quick_mode: bool = Form(False), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): - input_item = db.query(InventoryItem).filter( - InventoryItem.id == input_inventory_id, - InventoryItem.user_id == user.id - ).first() + result = await db.execute( + select(InventoryItem).filter( + InventoryItem.id == input_inventory_id, + InventoryItem.user_id == user.id + ) + ) + input_item = result.scalar_one_or_none() if not input_item: return JSONResponse(status_code=400, content={"error": "Предмет не найден"}) @@ -2790,7 +2815,7 @@ async def api_execute_upgrade( }) base_probability = calculate_upgrade_probability(input_price, target_price) - adjusted_probability = get_adjusted_upgrade_probability(db, user.id, base_probability) + adjusted_probability = await get_adjusted_upgrade_probability_async(db, user.id, base_probability) # Бан: колесо падает аккурат на 1-15° после зелёной зоны (как будто был шанс) if user.is_banned: @@ -2808,7 +2833,7 @@ async def api_execute_upgrade( # Сохраняем поля до удаления saved_input_name = input_item.market_hash_name saved_input_item_id = input_item.item_id - db.delete(input_item) + await db.delete(input_item) if success: item_float = target_data.get("mid_float_used") or generate_item_float(target_data.get("rarity", "Unknown")) @@ -2845,16 +2870,16 @@ async def api_execute_upgrade( import rpu as _rpu_mod _rpu_mod._BATCH_MODE = True try: - update_upgrade_stats(db, user.id, success, input_price) + await update_upgrade_stats_async(db, user.id, success, input_price) - unlocked_ach = check_upgrade_achievements(db, user.id) - unlocked_ach += check_upgrade_risk_achievements(db, user.id, input_price) - unlocked_ach += check_upgrade_result_achievements(db, user.id, success, base_probability, input_price) - unlocked_ach += check_inventory_achievements(db, user.id) - unlocked_ach += check_dildo_achievements(db, user.id) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_collection_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach = await check_upgrade_achievements(db, user.id) + unlocked_ach += await check_upgrade_risk_achievements(db, user.id, input_price) + unlocked_ach += await check_upgrade_result_achievements(db, user.id, success, base_probability, input_price) + unlocked_ach += await check_inventory_achievements(db, user.id) + unlocked_ach += await check_dildo_achievements(db, user.id) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_collection_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) if success: prob_pct = round(base_probability, 1) if base_probability > 0 else 0 @@ -2877,7 +2902,7 @@ async def api_execute_upgrade( finally: _rpu_mod._BATCH_MODE = False - db.commit() + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "inventory_update"})) asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -3087,7 +3112,7 @@ async def crash_page( @app.post("/web/api/crash/bet") async def api_crash_bet( amount: float = Form(...), - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): g = crash_game @@ -3103,14 +3128,17 @@ async def api_crash_bet( # Проверка достижений from database import ActivityFeed as CrActivity - crash_count = db.query(CrActivity).filter( - CrActivity.user_id == user.id, - CrActivity.activity_type == "crash" - ).count() + 1 - unlocked_ach = check_crash_achievements(db, user.id, crash_count) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) - db.commit() + crash_count_result = await db.execute( + select(sa_func.count(CrActivity.id)).filter( + CrActivity.user_id == user.id, + CrActivity.activity_type == "crash" + ) + ) + crash_count = crash_count_result.scalar() + 1 + unlocked_ach = await check_crash_achievements(db, user.id, crash_count) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance})) @@ -3124,7 +3152,7 @@ async def api_crash_bet( @app.post("/web/api/crash/cashout") async def api_crash_cashout( - db: Session = Depends(get_db), + db: AsyncSession = Depends(get_async_db), user: User = Depends(get_current_user) ): g = crash_game @@ -3142,11 +3170,11 @@ async def api_crash_cashout( user.balance += payout # Проверка достижений - unlocked_ach = check_crash_cashout_achievements(db, user.id, g.current_multiplier) - unlocked_ach += check_balance_achievements(db, user.id) - unlocked_ach += check_achievements_count_achievements(db, user.id) + unlocked_ach = await check_crash_cashout_achievements(db, user.id, g.current_multiplier) + unlocked_ach += await check_balance_achievements(db, user.id) + unlocked_ach += await check_achievements_count_achievements(db, user.id) - db.commit() + await db.commit() asyncio.ensure_future(manager.send_personal(user.id, {"type": "balance_update", "balance": user.balance}))