63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
|
|
from fastapi import APIRouter
|
||
|
|
from sqlalchemy import select, func
|
||
|
|
from sqlalchemy.orm import selectinload
|
||
|
|
|
||
|
|
from app.api.deps import DbSession, CurrentUser
|
||
|
|
from app.models import Activity, Participant
|
||
|
|
from app.schemas import FeedResponse, ActivityResponse, UserPublic
|
||
|
|
|
||
|
|
router = APIRouter(tags=["feed"])
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/marathons/{marathon_id}/feed", response_model=FeedResponse)
|
||
|
|
async def get_feed(
|
||
|
|
marathon_id: int,
|
||
|
|
current_user: CurrentUser,
|
||
|
|
db: DbSession,
|
||
|
|
limit: int = 20,
|
||
|
|
offset: int = 0,
|
||
|
|
):
|
||
|
|
"""Get activity feed for marathon"""
|
||
|
|
# Check user is participant
|
||
|
|
result = await db.execute(
|
||
|
|
select(Participant).where(
|
||
|
|
Participant.user_id == current_user.id,
|
||
|
|
Participant.marathon_id == marathon_id,
|
||
|
|
)
|
||
|
|
)
|
||
|
|
if not result.scalar_one_or_none():
|
||
|
|
return FeedResponse(items=[], total=0, has_more=False)
|
||
|
|
|
||
|
|
# Get total count
|
||
|
|
total = await db.scalar(
|
||
|
|
select(func.count()).select_from(Activity).where(Activity.marathon_id == marathon_id)
|
||
|
|
)
|
||
|
|
|
||
|
|
# Get activities
|
||
|
|
result = await db.execute(
|
||
|
|
select(Activity)
|
||
|
|
.options(selectinload(Activity.user))
|
||
|
|
.where(Activity.marathon_id == marathon_id)
|
||
|
|
.order_by(Activity.created_at.desc())
|
||
|
|
.limit(limit)
|
||
|
|
.offset(offset)
|
||
|
|
)
|
||
|
|
activities = result.scalars().all()
|
||
|
|
|
||
|
|
items = [
|
||
|
|
ActivityResponse(
|
||
|
|
id=a.id,
|
||
|
|
type=a.type,
|
||
|
|
user=UserPublic.model_validate(a.user),
|
||
|
|
data=a.data,
|
||
|
|
created_at=a.created_at,
|
||
|
|
)
|
||
|
|
for a in activities
|
||
|
|
]
|
||
|
|
|
||
|
|
return FeedResponse(
|
||
|
|
items=items,
|
||
|
|
total=total,
|
||
|
|
has_more=(offset + limit) < total,
|
||
|
|
)
|