Compare commits

..

3 Commits

Author SHA1 Message Date
itqop c2510fa9dc fix: fix models
Build and Push Docker Image / build-and-push (push) Has been skipped Details
2025-11-26 23:54:44 +03:00
itqop 6a14e2d65c feat: fixes 2025-11-26 23:32:39 +03:00
itqop 527146e651 fix: cooldowns 2025-11-26 07:48:48 +03:00
7 changed files with 109 additions and 18 deletions

View File

@ -6,8 +6,9 @@ from fastapi import APIRouter, Depends
from hubgw.api.deps import get_homes_service, verify_api_key
from hubgw.core.errors import AppError, create_http_exception
from hubgw.schemas.homes import (Home, HomeGetRequest, HomeGetResponse,
HomeListResponse, HomeUpsertRequest)
from hubgw.schemas.homes import (Home, HomeCountResponse, HomeGetRequest,
HomeGetResponse, HomeListResponse,
HomeUpsertRequest)
from hubgw.services.homes_service import HomesService
router = APIRouter()
@ -39,6 +40,33 @@ async def get_home(
raise create_http_exception(e)
@router.post("/delete")
async def delete_home(
request: HomeGetRequest,
service: Annotated[HomesService, Depends(get_homes_service)],
_: Annotated[str, Depends(verify_api_key)],
):
"""Delete home by player UUID and name."""
try:
await service.delete_home(request)
return {"success": True}
except AppError as e:
raise create_http_exception(e)
@router.get("/count/{player_uuid}", response_model=HomeCountResponse)
async def count_homes(
player_uuid: str,
service: Annotated[HomesService, Depends(get_homes_service)],
_: Annotated[str, Depends(verify_api_key)],
):
"""Count homes for player."""
try:
return await service.count_homes(player_uuid)
except AppError as e:
raise create_http_exception(e)
@router.get("/{player_uuid}", response_model=HomeListResponse)
async def list_homes(
player_uuid: str,

View File

@ -1,5 +1,7 @@
"""Teleport History model."""
from __future__ import annotations
from sqlalchemy import Column, DateTime, Float, ForeignKey, String, Text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
@ -13,7 +15,11 @@ _LUCKPERMS_SCHEMA = APP_CONFIG.database.luckperms_schema
class TeleportHistory(Base):
"""Teleport History model."""
"""Teleport History model.
This is an append-only audit log table, so it doesn't have updated_at column.
We override updated_at to None to exclude it from this model.
"""
__tablename__ = "hub_teleport_history"
__table_args__ = {"schema": _HUB_SCHEMA}
@ -35,8 +41,11 @@ class TeleportHistory(Base):
to_x = Column(Float, nullable=False) # DOUBLE PRECISION
to_y = Column(Float, nullable=False) # DOUBLE PRECISION
to_z = Column(Float, nullable=False) # DOUBLE PRECISION
tp_type = Column(String(50), nullable=False)
tp_type = Column(String(50), nullable=False, index=True)
target_name = Column(String(255))
created_at = Column(
DateTime(timezone=True), server_default=func.now(), nullable=False
DateTime(timezone=True), server_default=func.now(), nullable=False, index=True
)
# Override updated_at from Base to exclude it
updated_at = None

View File

@ -4,6 +4,7 @@ from typing import List, Optional
from uuid import UUID
from sqlalchemy import delete, func, select
from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.ext.asyncio import AsyncSession
from hubgw.models.cooldown import Cooldown
@ -17,16 +18,30 @@ class CooldownsRepository:
self.session = session
async def create(self, request: CooldownCreate) -> Cooldown:
"""Create new cooldown."""
cooldown = Cooldown(
player_uuid=request.player_uuid,
cooldown_type=request.cooldown_type,
expires_at=request.expires_at,
cooldown_seconds=request.cooldown_seconds,
cooldown_metadata=request.metadata,
"""Create or update cooldown (UPSERT)."""
stmt = (
insert(Cooldown)
.values(
player_uuid=request.player_uuid,
cooldown_type=request.cooldown_type,
expires_at=request.expires_at,
cooldown_seconds=request.cooldown_seconds,
cooldown_metadata=request.metadata,
)
.on_conflict_do_update(
index_elements=["player_uuid", "cooldown_type"],
set_={
"expires_at": request.expires_at,
"cooldown_seconds": request.cooldown_seconds,
"metadata": request.metadata,
"updated_at": func.now(),
},
)
.returning(Cooldown)
)
self.session.add(cooldown)
result = await self.session.execute(stmt)
await self.session.commit()
cooldown = result.scalar_one()
await self.session.refresh(cooldown)
return cooldown

View File

@ -74,6 +74,13 @@ class HomesRepository:
await self.session.commit()
return result.rowcount > 0
async def delete_by_player_and_name(self, player_uuid: str, name: str) -> bool:
"""Delete home by player UUID and name."""
stmt = delete(Home).where(Home.player_uuid == player_uuid, Home.name == name)
result = await self.session.execute(stmt)
await self.session.commit()
return result.rowcount > 0
async def query(self, query: HomeQuery) -> tuple[List[Home], int]:
"""Query homes with filters and pagination."""
stmt = select(Home)
@ -119,3 +126,9 @@ class HomesRepository:
stmt = select(Home).where(Home.player_uuid == player_uuid).order_by(Home.name)
result = await self.session.execute(stmt)
return list(result.scalars().all())
async def count_by_player(self, player_uuid: str) -> int:
"""Count homes for a player."""
stmt = select(func.count(Home.id)).where(Home.player_uuid == player_uuid)
result = await self.session.execute(stmt)
return result.scalar()

View File

@ -73,6 +73,12 @@ class HomeListResponse(BaseModel):
total: int
class HomeCountResponse(BaseModel):
"""Home count response schema."""
total: int
class HomeQuery(PaginationParams):
"""Home query schema."""

View File

@ -6,7 +6,7 @@ from uuid import UUID
from pydantic import BaseModel
from hubgw.schemas.common import BaseSchema, PaginationParams
from hubgw.schemas.common import PaginationParams
class TeleportHistoryBase(BaseModel):
@ -30,8 +30,11 @@ class TeleportHistoryCreate(TeleportHistoryBase):
player_uuid: str
class TeleportHistory(TeleportHistoryBase, BaseSchema):
"""Teleport history schema."""
class TeleportHistory(TeleportHistoryBase):
"""Teleport history response schema.
This is an append-only audit log, so it only has created_at (no updated_at).
"""
id: UUID
player_uuid: str

View File

@ -5,8 +5,9 @@ from sqlalchemy.ext.asyncio import AsyncSession
from hubgw.core.errors import NotFoundError
from hubgw.repositories.homes_repo import HomesRepository
from hubgw.schemas.homes import (Home, HomeGetRequest, HomeGetResponse,
HomeListResponse, HomeUpsertRequest)
from hubgw.schemas.homes import (Home, HomeCountResponse, HomeGetRequest,
HomeGetResponse, HomeListResponse,
HomeUpsertRequest)
class HomesService:
@ -65,3 +66,19 @@ class HomesService:
]
return HomeListResponse(homes=home_list, total=len(home_list))
async def count_homes(self, player_uuid: str) -> HomeCountResponse:
"""Count homes for player."""
total = await self.repo.count_by_player(player_uuid)
return HomeCountResponse(total=total)
async def delete_home(self, request: HomeGetRequest) -> bool:
"""Delete home by player UUID and name."""
deleted = await self.repo.delete_by_player_and_name(
request.player_uuid, request.name
)
if not deleted:
raise NotFoundError(
f"Home '{request.name}' not found for player {request.player_uuid}"
)
return deleted