from __future__ import annotations import uuid from datetime import UTC, datetime, timedelta from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.db.base import ensure_aware_utc from app.models.unban_request import UnbanRequest class UnbanRequestRepository: def __init__(self, db: AsyncSession) -> None: self.db = db async def get(self, request_id: uuid.UUID) -> UnbanRequest | None: result = await self.db.execute(select(UnbanRequest).where(UnbanRequest.id == request_id)) return result.scalar_one_or_none() async def delete(self, request_id: uuid.UUID) -> None: request = await self.get(request_id) if request is not None: await self.db.delete(request) await self.db.flush() async def most_recent_for_ip(self, ip_address: str) -> UnbanRequest | None: result = await self.db.execute( select(UnbanRequest) .where(UnbanRequest.ip_address == ip_address) .order_by(UnbanRequest.created_at.desc()) .limit(1) ) return result.scalar_one_or_none() async def within_cooldown(self, ip_address: str, cooldown_hours: int = 24) -> bool: latest = await self.most_recent_for_ip(ip_address) if latest is None: return False cutoff = datetime.now(UTC) - timedelta(hours=cooldown_hours) return ensure_aware_utc(latest.created_at) > cutoff async def create(self, ip_address: str, message: str | None) -> UnbanRequest: record = UnbanRequest(ip_address=ip_address, message=message) self.db.add(record) await self.db.flush() return record async def list_all(self, limit: int = 100) -> list[UnbanRequest]: result = await self.db.execute( select(UnbanRequest).order_by(UnbanRequest.created_at.desc()).limit(limit) ) return list(result.scalars().all())