fix(user): missing the first entry

This commit is contained in:
MingxuanGame
2026-01-03 16:37:55 +08:00
parent 282eda3250
commit 1c3b309804

View File

@@ -1,4 +1,5 @@
from datetime import timedelta from datetime import datetime, timedelta
import sys
from typing import Annotated, Literal from typing import Annotated, Literal
from app.config import settings from app.config import settings
@@ -141,20 +142,39 @@ async def get_users(
async def get_user_events( async def get_user_events(
session: Database, session: Database,
user_id: Annotated[int, Path(description="用户 ID")], user_id: Annotated[int, Path(description="用户 ID")],
limit: Annotated[int | None, Query(description="限制返回的活动数量")] = None, limit: Annotated[int, Query(description="限制返回的活动数量")] = 50,
offset: Annotated[int | None, Query(description="活动日志的偏移量")] = None, offset: Annotated[int | None, Query(description="活动日志的偏移量")] = None,
current_user: User | None = Security(get_optional_user, scopes=["public"]), current_user: User | None = Security(get_optional_user, scopes=["public"]),
): ):
db_user = await session.get(User, user_id) db_user = await session.get(User, user_id)
if db_user is None or not await visible_to_current_user(db_user, current_user, session): if db_user is None or not await visible_to_current_user(db_user, current_user, session):
raise HTTPException(404, "User Not found") raise HTTPException(404, "User Not found")
if offset is None:
offset = 0
if limit > 100:
limit = 100
if offset == 0:
cursor = sys.maxsize
else:
cursor = (
await session.exec(
select(Event.id)
.where(Event.user_id == db_user.id, Event.created_at >= utcnow() - timedelta(days=30))
.order_by(col(Event.id).desc())
.limit(1)
.offset(offset - 1)
)
).first()
if cursor is None:
return []
events = ( events = (
await session.exec( await session.exec(
select(Event) select(Event)
.where(Event.user_id == db_user.id, Event.created_at >= utcnow() - timedelta(days=30)) .where(Event.user_id == db_user.id, Event.created_at >= utcnow() - timedelta(days=30), Event.id < cursor)
.order_by(col(Event.created_at).desc()) .order_by(col(Event.id).desc())
.limit(limit) .limit(limit)
.offset(offset)
) )
).all() ).all()
return events return events
@@ -434,9 +454,16 @@ async def get_user_beatmapsets(
resp = [] resp = []
elif type == BeatmapsetType.FAVOURITE: elif type == BeatmapsetType.FAVOURITE:
if offset == 0:
cursor = sys.maxsize
else:
cursor = ( cursor = (
await session.exec( await session.exec(
select(FavouriteBeatmapset.id).where(FavouriteBeatmapset.user_id == user_id).limit(1).offset(offset) select(FavouriteBeatmapset.id)
.where(FavouriteBeatmapset.user_id == user_id)
.order_by(col(FavouriteBeatmapset.id).desc())
.limit(1)
.offset(offset - 1)
) )
).first() ).first()
if cursor is None: if cursor is None:
@@ -444,7 +471,7 @@ async def get_user_beatmapsets(
favourites = ( favourites = (
await session.exec( await session.exec(
select(FavouriteBeatmapset) select(FavouriteBeatmapset)
.where(FavouriteBeatmapset.user_id == user_id, FavouriteBeatmapset.id > cursor) .where(FavouriteBeatmapset.user_id == user_id, FavouriteBeatmapset.id < cursor)
.order_by(col(FavouriteBeatmapset.id).desc()) .order_by(col(FavouriteBeatmapset.id).desc())
.limit(limit) .limit(limit)
) )
@@ -457,13 +484,16 @@ async def get_user_beatmapsets(
] ]
elif type == BeatmapsetType.MOST_PLAYED: elif type == BeatmapsetType.MOST_PLAYED:
if offset == 0:
cursor = sys.maxsize, sys.maxsize
else:
cursor = ( cursor = (
await session.exec( await session.exec(
select(BeatmapPlaycounts.playcount, BeatmapPlaycounts.id) select(BeatmapPlaycounts.playcount, BeatmapPlaycounts.id)
.where(BeatmapPlaycounts.user_id == user_id) .where(BeatmapPlaycounts.user_id == user_id)
.order_by(col(BeatmapPlaycounts.playcount).desc(), col(BeatmapPlaycounts.id).desc()) .order_by(col(BeatmapPlaycounts.playcount).desc(), col(BeatmapPlaycounts.id).desc())
.limit(1) .limit(1)
.offset(offset) .offset(offset - 1)
) )
).first() ).first()
if cursor is None: if cursor is None:
@@ -509,7 +539,6 @@ async def get_user_beatmapsets(
) )
@asset_proxy_response @asset_proxy_response
async def get_user_scores( async def get_user_scores(
request: Request,
session: Database, session: Database,
api_version: APIVersion, api_version: APIVersion,
background_task: BackgroundTasks, background_task: BackgroundTasks,
@@ -550,13 +579,16 @@ async def get_user_scores(
scores = [] scores = []
if type == "pinned": if type == "pinned":
where_clause &= Score.pinned_order > 0 where_clause &= Score.pinned_order > 0
if offset == 0:
cursor = 0, sys.maxsize
else:
cursor = ( cursor = (
await session.exec( await session.exec(
select(Score.pinned_order, Score.id) select(Score.pinned_order, Score.id)
.where(where_clause) .where(where_clause)
.order_by(col(Score.pinned_order).asc(), col(Score.id).desc()) .order_by(col(Score.pinned_order).asc(), col(Score.id).desc())
.limit(1) .limit(1)
.offset(offset) .offset(offset - 1)
) )
).first() ).first()
if cursor: if cursor:
@@ -576,13 +608,17 @@ async def get_user_scores(
elif type == "best": elif type == "best":
where_clause &= exists().where(col(BestScore.score_id) == Score.id) where_clause &= exists().where(col(BestScore.score_id) == Score.id)
includes.append("weight") includes.append("weight")
if offset == 0:
cursor = sys.maxsize, sys.maxsize
else:
cursor = ( cursor = (
await session.exec( await session.exec(
select(Score.pp, Score.id) select(Score.pp, Score.id)
.where(where_clause) .where(where_clause)
.order_by(col(Score.pp).desc(), col(Score.id).desc()) .order_by(col(Score.pp).desc(), col(Score.id).desc())
.limit(1) .limit(1)
.offset(offset) .offset(offset - 1)
) )
).first() ).first()
if cursor: if cursor:
@@ -596,13 +632,16 @@ async def get_user_scores(
elif type == "recent": elif type == "recent":
where_clause &= Score.ended_at > utcnow() - timedelta(hours=24) where_clause &= Score.ended_at > utcnow() - timedelta(hours=24)
if offset == 0:
cursor = datetime.max, sys.maxsize
else:
cursor = ( cursor = (
await session.exec( await session.exec(
select(Score.ended_at, Score.id) select(Score.ended_at, Score.id)
.where(where_clause) .where(where_clause)
.order_by(col(Score.ended_at).desc(), col(Score.id).desc()) .order_by(col(Score.ended_at).desc(), col(Score.id).desc())
.limit(1) .limit(1)
.offset(offset) .offset(offset - 1)
) )
).first() ).first()
if cursor: if cursor: