add img to bonus and endpoint toogle activation bonus
This commit is contained in:
@ -45,3 +45,12 @@ async def upgrade_user_bonus(username: str = Body(...), bonus_id: str = Body(...
|
|||||||
from app.services.bonus import BonusService
|
from app.services.bonus import BonusService
|
||||||
return await BonusService().upgrade_bonus(username, bonus_id)
|
return await BonusService().upgrade_bonus(username, bonus_id)
|
||||||
|
|
||||||
|
@router.post("/toggle-activation")
|
||||||
|
async def toggle_bonus_activation(username: str = Body(...), bonus_id: str = Body(...)):
|
||||||
|
"""
|
||||||
|
Переключить активность бонуса пользователя.
|
||||||
|
Передаём username и bonus_id, is_active переключается на противоположное значение.
|
||||||
|
"""
|
||||||
|
from app.services.bonus import BonusService
|
||||||
|
return await BonusService().toggle_bonus_activation(username, bonus_id)
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ class CreateBonusType(BaseModel):
|
|||||||
upgrade_price: int
|
upgrade_price: int
|
||||||
duration: int # в секундах
|
duration: int # в секундах
|
||||||
max_level: int = 0
|
max_level: int = 0
|
||||||
|
image_url: Optional[str] = None
|
||||||
|
|
||||||
class PurchaseBonus(BaseModel):
|
class PurchaseBonus(BaseModel):
|
||||||
username: str
|
username: str
|
||||||
@ -33,6 +34,7 @@ class BonusType(BaseModel):
|
|||||||
upgrade_price: int # Цена улучшения за уровень
|
upgrade_price: int # Цена улучшения за уровень
|
||||||
duration: int # Длительность в секундах (0 для бесконечных)
|
duration: int # Длительность в секундах (0 для бесконечных)
|
||||||
max_level: int = 0 # 0 = без ограничения уровней
|
max_level: int = 0 # 0 = без ограничения уровней
|
||||||
|
image_url: Optional[str] = None
|
||||||
|
|
||||||
class UserTypeBonus(BaseModel):
|
class UserTypeBonus(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
@ -47,6 +49,7 @@ class UserTypeBonus(BaseModel):
|
|||||||
expires_at: Optional[datetime] = None
|
expires_at: Optional[datetime] = None
|
||||||
is_active: bool = True
|
is_active: bool = True
|
||||||
is_permanent: bool
|
is_permanent: bool
|
||||||
|
image_url: Optional[str] = None
|
||||||
|
|
||||||
class UserBonus(BaseModel):
|
class UserBonus(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
|
|||||||
@ -25,7 +25,8 @@ class BonusService:
|
|||||||
"price": bonus_data.price,
|
"price": bonus_data.price,
|
||||||
"upgrade_price": bonus_data.upgrade_price,
|
"upgrade_price": bonus_data.upgrade_price,
|
||||||
"duration": bonus_data.duration,
|
"duration": bonus_data.duration,
|
||||||
"max_level": bonus_data.max_level
|
"max_level": bonus_data.max_level,
|
||||||
|
"image_url": bonus_data.image_url,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Проверка на дубликат имени
|
# Проверка на дубликат имени
|
||||||
@ -112,7 +113,8 @@ class BonusService:
|
|||||||
"level": level,
|
"level": level,
|
||||||
"purchased_at": bonus["purchased_at"].isoformat(),
|
"purchased_at": bonus["purchased_at"].isoformat(),
|
||||||
"can_upgrade": bonus_type["max_level"] == 0 or level < bonus_type["max_level"],
|
"can_upgrade": bonus_type["max_level"] == 0 or level < bonus_type["max_level"],
|
||||||
"upgrade_price": bonus_type["upgrade_price"]
|
"upgrade_price": bonus_type["upgrade_price"],
|
||||||
|
"image_url": bonus_type.get("image_url"),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Для временных бонусов добавляем срок
|
# Для временных бонусов добавляем срок
|
||||||
@ -125,6 +127,47 @@ class BonusService:
|
|||||||
result.append(bonus_data)
|
result.append(bonus_data)
|
||||||
|
|
||||||
return {"bonuses": result}
|
return {"bonuses": result}
|
||||||
|
|
||||||
|
async def toggle_bonus_activation(self, username: str, bonus_id: str):
|
||||||
|
"""Переключить активность бонуса у пользователя"""
|
||||||
|
from app.db.database import users_collection
|
||||||
|
|
||||||
|
# Находим пользователя
|
||||||
|
user = await users_collection.find_one({"username": username})
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(status_code=404, detail="Пользователь не найден")
|
||||||
|
|
||||||
|
# Находим бонус пользователя
|
||||||
|
user_bonus = await user_bonuses_collection.find_one({
|
||||||
|
"id": bonus_id,
|
||||||
|
"user_id": str(user["_id"]),
|
||||||
|
})
|
||||||
|
|
||||||
|
if not user_bonus:
|
||||||
|
raise HTTPException(status_code=404, detail="Бонус не найден или не принадлежит вам")
|
||||||
|
|
||||||
|
# Проверяем, не истек ли бонус при попытке включить
|
||||||
|
if user_bonus.get("expires_at") and user_bonus["expires_at"] < datetime.utcnow():
|
||||||
|
# На всякий случай зафиксируем в БД, что он не активен
|
||||||
|
await user_bonuses_collection.update_one(
|
||||||
|
{"id": bonus_id},
|
||||||
|
{"$set": {"is_active": False}}
|
||||||
|
)
|
||||||
|
raise HTTPException(status_code=400, detail="Срок действия бонуса истёк и он не может быть активирован")
|
||||||
|
|
||||||
|
new_status = not user_bonus.get("is_active", False)
|
||||||
|
|
||||||
|
await user_bonuses_collection.update_one(
|
||||||
|
{"id": bonus_id},
|
||||||
|
{"$set": {"is_active": new_status}}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": "success",
|
||||||
|
"message": "Активность бонуса переключена",
|
||||||
|
"bonus_id": bonus_id,
|
||||||
|
"is_active": new_status,
|
||||||
|
}
|
||||||
|
|
||||||
async def purchase_bonus(self, username: str, bonus_type_id: str):
|
async def purchase_bonus(self, username: str, bonus_type_id: str):
|
||||||
"""Покупка базового бонуса пользователем"""
|
"""Покупка базового бонуса пользователем"""
|
||||||
|
|||||||
@ -46,6 +46,28 @@ class CoinsService:
|
|||||||
# Первое обновление (ограничиваем для безопасности)
|
# Первое обновление (ограничиваем для безопасности)
|
||||||
minutes_to_reward = min(online_time // 60, 5)
|
minutes_to_reward = min(online_time // 60, 5)
|
||||||
|
|
||||||
|
# НА ВСЯКИЙ ЕСЛИ ПОПЫ ВСЕ-РАВНО НЕПРАВИЛЬНО НАЧИСЛЯЮТСЯ
|
||||||
|
|
||||||
|
# if last_update:
|
||||||
|
# last_timestamp = last_update["timestamp"]
|
||||||
|
# seconds_since_update = int((now - last_timestamp).total_seconds())
|
||||||
|
|
||||||
|
# # Берём минимум: сколько прошло по часам и сколько игрок реально онлайн
|
||||||
|
# seconds_for_reward = min(seconds_since_update, online_time)
|
||||||
|
|
||||||
|
# # Начисляем только за полные минуты
|
||||||
|
# minutes_to_reward = seconds_for_reward // 60
|
||||||
|
|
||||||
|
# if minutes_to_reward < 1:
|
||||||
|
# return
|
||||||
|
|
||||||
|
# minutes_to_reward = min(minutes_to_reward, MAX_MINUTES_PER_UPDATE)
|
||||||
|
# else:
|
||||||
|
# # Первое обновление — считаем только от online_time, с лимитом для безопасности
|
||||||
|
# minutes_to_reward = min(online_time // 60, 5)
|
||||||
|
# if minutes_to_reward < 1:
|
||||||
|
# return
|
||||||
|
|
||||||
if minutes_to_reward > 0:
|
if minutes_to_reward > 0:
|
||||||
# Обновляем монеты и время
|
# Обновляем монеты и время
|
||||||
new_coins = current_coins + minutes_to_reward
|
new_coins = current_coins + minutes_to_reward
|
||||||
|
|||||||
Reference in New Issue
Block a user