refactor(app): update database code

This commit is contained in:
MingxuanGame
2025-08-18 16:37:30 +00:00
parent 6bae937e01
commit 1c65b21bb9
34 changed files with 167 additions and 188 deletions

View File

@@ -6,7 +6,7 @@ import json
from app.database import Beatmap, BeatmapResp, User
from app.database.beatmap import calculate_beatmap_attributes
from app.dependencies.database import get_db, get_redis
from app.dependencies.database import Database, get_redis
from app.dependencies.fetcher import get_fetcher
from app.dependencies.user import get_current_user
from app.fetcher import Fetcher
@@ -24,7 +24,6 @@ from pydantic import BaseModel
from redis.asyncio import Redis
import rosu_pp_py as rosu
from sqlmodel import col, select
from sqlmodel.ext.asyncio.session import AsyncSession
class BatchGetResp(BaseModel):
@@ -47,13 +46,13 @@ class BatchGetResp(BaseModel):
),
)
async def lookup_beatmap(
db: Database,
id: int | None = Query(default=None, alias="id", description="谱面 ID"),
md5: str | None = Query(default=None, alias="checksum", description="谱面文件 MD5"),
filename: str | None = Query(
default=None, alias="filename", description="谱面文件名"
),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
if id is None and md5 is None and filename is None:
@@ -80,9 +79,9 @@ async def lookup_beatmap(
description="获取单个谱面详情。",
)
async def get_beatmap(
db: Database,
beatmap_id: int = Path(..., description="谱面 ID"),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
try:
@@ -103,11 +102,11 @@ async def get_beatmap(
),
)
async def batch_get_beatmaps(
db: Database,
beatmap_ids: list[int] = Query(
alias="ids[]", default_factory=list, description="谱面 ID 列表 (最多 50 个)"
),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
if not beatmap_ids:
@@ -157,6 +156,7 @@ async def batch_get_beatmaps(
description=("计算谱面指定 mods / ruleset 下谱面的难度属性 (难度/PP 相关属性)。"),
)
async def get_beatmap_attributes(
db: Database,
beatmap_id: int = Path(..., description="谱面 ID"),
current_user: User = Security(get_current_user, scopes=["public"]),
mods: list[str] = Query(
@@ -170,7 +170,6 @@ async def get_beatmap_attributes(
default=None, description="以数字指定 ruleset (与 ruleset 二选一)", ge=0, le=3
),
redis: Redis = Depends(get_redis),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
mods_ = []

View File

@@ -7,7 +7,7 @@ from urllib.parse import parse_qs
from app.database import Beatmap, Beatmapset, BeatmapsetResp, FavouriteBeatmapset, User
from app.database.beatmapset import SearchBeatmapsetsResp
from app.dependencies.beatmap_download import get_beatmap_download_service
from app.dependencies.database import engine, get_db, get_redis
from app.dependencies.database import Database, get_redis, with_db
from app.dependencies.fetcher import get_fetcher
from app.dependencies.geoip import get_client_ip, get_geoip_helper
from app.dependencies.user import get_client_user, get_current_user
@@ -30,11 +30,10 @@ from fastapi import (
from fastapi.responses import RedirectResponse
from httpx import HTTPError
from sqlmodel import exists, select
from sqlmodel.ext.asyncio.session import AsyncSession
async def _save_to_db(sets: SearchBeatmapsetsResp):
async with AsyncSession(engine) as session:
async with with_db() as session:
for s in sets.beatmapsets:
if not (
await session.exec(select(exists()).where(Beatmapset.id == s.id))
@@ -49,13 +48,13 @@ async def _save_to_db(sets: SearchBeatmapsetsResp):
response_model=SearchBeatmapsetsResp,
)
async def search_beatmapset(
db: Database,
query: Annotated[SearchQueryModel, Query(...)],
request: Request,
background_tasks: BackgroundTasks,
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
redis = Depends(get_redis),
redis=Depends(get_redis),
):
params = parse_qs(qs=request.url.query, keep_blank_values=True)
cursor = {}
@@ -112,9 +111,9 @@ async def search_beatmapset(
description=("通过谱面 ID 查询所属谱面集。"),
)
async def lookup_beatmapset(
db: Database,
beatmap_id: int = Query(description="谱面 ID"),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
beatmap = await Beatmap.get_or_fetch(db, fetcher, bid=beatmap_id)
@@ -132,9 +131,9 @@ async def lookup_beatmapset(
description="获取单个谱面集详情。",
)
async def get_beatmapset(
db: Database,
beatmapset_id: int = Path(..., description="谱面集 ID"),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
fetcher: Fetcher = Depends(get_fetcher),
):
try:
@@ -196,12 +195,12 @@ async def download_beatmapset(
description="**客户端专属**\n收藏或取消收藏指定谱面集。",
)
async def favourite_beatmapset(
db: Database,
beatmapset_id: int = Path(..., description="谱面集 ID"),
action: Literal["favourite", "unfavourite"] = Form(
description="操作类型favourite 收藏 / unfavourite 取消收藏"
),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
assert current_user.id is not None
existing_favourite = (

View File

@@ -3,13 +3,12 @@ from __future__ import annotations
from app.database import User, UserResp
from app.database.lazer_user import ALL_INCLUDED
from app.dependencies import get_current_user
from app.dependencies.database import get_db
from app.dependencies.database import Database
from app.models.score import GameMode
from .router import router
from fastapi import Depends, Path, Security
from sqlmodel.ext.asyncio.session import AsyncSession
from fastapi import Path, Security
@router.get(
@@ -20,9 +19,9 @@ from sqlmodel.ext.asyncio.session import AsyncSession
tags=["用户"],
)
async def get_user_info_with_ruleset(
session: Database,
ruleset: GameMode = Path(description="指定 ruleset"),
current_user: User = Security(get_current_user, scopes=["identify"]),
session: AsyncSession = Depends(get_db),
):
return await UserResp.from_db(
current_user,
@@ -40,8 +39,8 @@ async def get_user_info_with_ruleset(
tags=["用户"],
)
async def get_user_info_default(
session: Database,
current_user: User = Security(get_current_user, scopes=["identify"]),
session: AsyncSession = Depends(get_db),
):
return await UserResp.from_db(
current_user,

View File

@@ -5,15 +5,14 @@ from typing import Literal
from app.database import User
from app.database.statistics import UserStatistics, UserStatisticsResp
from app.dependencies import get_current_user
from app.dependencies.database import get_db
from app.dependencies.database import Database
from app.models.score import GameMode
from .router import router
from fastapi import Depends, Path, Query, Security
from fastapi import Path, Query, Security
from pydantic import BaseModel
from sqlmodel import col, select
from sqlmodel.ext.asyncio.session import AsyncSession
class CountryStatistics(BaseModel):
@@ -36,10 +35,10 @@ class CountryResponse(BaseModel):
tags=["排行榜"],
)
async def get_country_ranking(
session: Database,
ruleset: GameMode = Path(..., description="指定 ruleset"),
page: int = Query(1, ge=1, description="页码"), # TODO
current_user: User = Security(get_current_user, scopes=["public"]),
session: AsyncSession = Depends(get_db),
):
response = CountryResponse(ranking=[])
countries = (await session.exec(select(User.country_code).distinct())).all()
@@ -85,6 +84,7 @@ class TopUsersResponse(BaseModel):
tags=["排行榜"],
)
async def get_user_ranking(
session: Database,
ruleset: GameMode = Path(..., description="指定 ruleset"),
type: Literal["performance", "score"] = Path(
..., description="排名类型performance 表现分 / score 计分成绩总分"
@@ -92,7 +92,6 @@ async def get_user_ranking(
country: str | None = Query(None, description="国家代码"),
page: int = Query(1, ge=1, description="页码"),
current_user: User = Security(get_current_user, scopes=["public"]),
session: AsyncSession = Depends(get_db),
):
wheres = [
col(UserStatistics.mode) == ruleset,

View File

@@ -1,15 +1,14 @@
from __future__ import annotations
from app.database import Relationship, RelationshipResp, RelationshipType, User
from app.dependencies.database import get_db
from app.dependencies.database import Database
from app.dependencies.user import get_client_user, get_current_user
from .router import router
from fastapi import Depends, HTTPException, Path, Query, Request, Security
from fastapi import HTTPException, Path, Query, Request, Security
from pydantic import BaseModel
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
@router.get(
@@ -27,9 +26,9 @@ from sqlmodel.ext.asyncio.session import AsyncSession
description="获取当前用户的屏蔽用户列表。",
)
async def get_relationship(
db: Database,
request: Request,
current_user: User = Security(get_current_user, scopes=["friends.read"]),
db: AsyncSession = Depends(get_db),
):
relationship_type = (
RelationshipType.FOLLOW
@@ -67,10 +66,10 @@ class AddFriendResp(BaseModel):
description="**客户端专属**\n添加或更新与目标用户的屏蔽关系。",
)
async def add_relationship(
db: Database,
request: Request,
target: int = Query(description="目标用户 ID"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
assert current_user.id is not None
relationship_type = (
@@ -141,10 +140,10 @@ async def add_relationship(
description="**客户端专属**\n删除与目标用户的屏蔽关系。",
)
async def delete_relationship(
db: Database,
request: Request,
target: int = Path(..., description="目标用户 ID"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
relationship_type = (
RelationshipType.BLOCK

View File

@@ -12,7 +12,7 @@ from app.database.playlists import Playlist, PlaylistResp
from app.database.room import APIUploadedRoom, Room, RoomResp
from app.database.room_participated_user import RoomParticipatedUser
from app.database.score import Score
from app.dependencies.database import get_db, get_redis
from app.dependencies.database import Database, get_redis
from app.dependencies.user import get_client_user, get_current_user
from app.models.room import RoomCategory, RoomStatus
from app.service.room import create_playlist_room_from_api
@@ -36,6 +36,7 @@ from sqlmodel.ext.asyncio.session import AsyncSession
description="获取房间列表。支持按状态/模式筛选",
)
async def get_all_rooms(
db: Database,
mode: Literal["open", "ended", "participated", "owned", None] = Query(
default="open",
description=(
@@ -51,7 +52,6 @@ async def get_all_rooms(
),
),
status: RoomStatus | None = Query(None, description="房间状态(可选)"),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_current_user, scopes=["public"]),
):
resp_list: list[RoomResp] = []
@@ -149,8 +149,8 @@ async def _participate_room(
description="**客户端专属**\n创建一个新的房间。",
)
async def create_room(
db: Database,
room: APIUploadedRoom,
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
):
@@ -173,6 +173,7 @@ async def create_room(
description="获取单个房间详情。",
)
async def get_room(
db: Database,
room_id: int = Path(..., description="房间 ID"),
category: str = Query(
default="",
@@ -181,7 +182,6 @@ async def get_room(
" / DAILY_CHALLENGE 每日挑战 (可选)"
),
),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
):
@@ -201,8 +201,8 @@ async def get_room(
description="**客户端专属**\n结束歌单模式房间。",
)
async def delete_room(
db: Database,
room_id: int = Path(..., description="房间 ID"),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_client_user),
):
db_room = (await db.exec(select(Room).where(Room.id == room_id))).first()
@@ -221,9 +221,9 @@ async def delete_room(
description="**客户端专属**\n加入指定歌单模式房间。",
)
async def add_user_to_room(
db: Database,
room_id: int = Path(..., description="房间 ID"),
user_id: int = Path(..., description="用户 ID"),
db: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
current_user: User = Security(get_client_user),
):
@@ -245,9 +245,9 @@ async def add_user_to_room(
description="**客户端专属**\n离开指定歌单模式房间。",
)
async def remove_user_from_room(
db: Database,
room_id: int = Path(..., description="房间 ID"),
user_id: int = Path(..., description="用户 ID"),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_client_user),
redis: Redis = Depends(get_redis),
):
@@ -289,8 +289,8 @@ class APILeaderboard(BaseModel):
description="获取房间内累计得分排行榜。",
)
async def get_room_leaderboard(
db: Database,
room_id: int = Path(..., description="房间 ID"),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_current_user, scopes=["public"]),
):
db_room = (await db.exec(select(Room).where(Room.id == room_id))).first()
@@ -345,8 +345,8 @@ class RoomEvents(BaseModel):
description="获取房间事件列表 (倒序,可按 after / before 进行范围截取)。",
)
async def get_room_events(
db: Database,
room_id: int = Path(..., description="房间 ID"),
db: AsyncSession = Depends(get_db),
current_user: User = Security(get_current_user, scopes=["public"]),
limit: int = Query(100, ge=1, le=1000, description="返回条数 (1-1000)"),
after: int | None = Query(None, ge=0, description="仅包含大于该事件 ID 的事件"),

View File

@@ -32,7 +32,7 @@ from app.database.score import (
process_score,
process_user,
)
from app.dependencies.database import get_db, get_redis
from app.dependencies.database import Database, get_redis
from app.dependencies.fetcher import get_fetcher
from app.dependencies.storage import get_storage_service
from app.dependencies.user import get_client_user, get_current_user
@@ -220,6 +220,7 @@ class BeatmapScores(BaseModel):
description="获取指定谱面在特定条件下的排行榜及当前用户成绩。",
)
async def get_beatmap_scores(
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
mode: GameMode = Query(description="指定 auleset"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
@@ -233,7 +234,6 @@ async def get_beatmap_scores(
),
),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
limit: int = Query(50, ge=1, le=200, description="返回条数 (1-200)"),
):
if legacy_only:
@@ -277,13 +277,13 @@ class BeatmapUserScore(BaseModel):
description="获取指定用户在指定谱面上的最高成绩。",
)
async def get_user_beatmap_score(
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
user_id: int = Path(description="用户 ID"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
mode: GameMode | None = Query(None, description="指定 ruleset (可选)"),
mods: str = Query(None, description="筛选使用的 Mods (暂未实现)"),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
):
if legacy_only:
raise HTTPException(
@@ -322,12 +322,12 @@ async def get_user_beatmap_score(
description="获取指定用户在指定谱面上的全部成绩列表。",
)
async def get_user_all_beatmap_scores(
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
user_id: int = Path(description="用户 ID"),
legacy_only: bool = Query(None, description="是否只查询 Stable 分数"),
ruleset: GameMode | None = Query(None, description="指定 ruleset (可选)"),
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
):
if legacy_only:
raise HTTPException(
@@ -357,12 +357,12 @@ async def get_user_all_beatmap_scores(
)
async def create_solo_score(
background_task: BackgroundTasks,
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
version_hash: str = Form("", description="游戏版本哈希"),
beatmap_hash: str = Form(description="谱面文件哈希"),
ruleset_id: int = Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
assert current_user.id is not None
background_task.add_task(_preload_beatmap_for_pp_calculation, beatmap_id)
@@ -387,11 +387,11 @@ async def create_solo_score(
)
async def submit_solo_score(
req: Request,
db: Database,
beatmap_id: int = Path(description="谱面 ID"),
token: int = Path(description="成绩令牌 ID"),
info: SoloScoreSubmissionInfo = Body(description="成绩提交信息"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
fetcher=Depends(get_fetcher),
):
@@ -407,6 +407,7 @@ async def submit_solo_score(
description="**客户端专属**\n为房间游玩项目创建成绩提交令牌。",
)
async def create_playlist_score(
session: Database,
background_task: BackgroundTasks,
room_id: int,
playlist_id: int,
@@ -415,7 +416,6 @@ async def create_playlist_score(
ruleset_id: int = Form(..., ge=0, le=3, description="ruleset 数字 ID (0-3)"),
version_hash: str = Form("", description="谱面版本哈希"),
current_user: User = Security(get_client_user),
session: AsyncSession = Depends(get_db),
):
assert current_user.id is not None
room = await session.get(Room, room_id)
@@ -483,12 +483,12 @@ async def create_playlist_score(
description="**客户端专属**\n提交房间游玩项目成绩。",
)
async def submit_playlist_score(
session: Database,
room_id: int,
playlist_id: int,
token: int,
info: SoloScoreSubmissionInfo,
current_user: User = Security(get_client_user),
session: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
fetcher: Fetcher = Depends(get_fetcher),
):
@@ -541,6 +541,7 @@ class IndexedScoreResp(MultiplayerScores):
tags=["成绩"],
)
async def index_playlist_scores(
session: Database,
room_id: int,
playlist_id: int,
limit: int = Query(50, ge=1, le=50, description="返回条数 (1-50)"),
@@ -548,7 +549,6 @@ async def index_playlist_scores(
2000000, alias="cursor[total_score]", description="分页游标(上一页最低分)"
),
current_user: User = Security(get_current_user, scopes=["public"]),
session: AsyncSession = Depends(get_db),
):
room = await session.get(Room, room_id)
if not room:
@@ -607,11 +607,11 @@ async def index_playlist_scores(
tags=["成绩"],
)
async def show_playlist_score(
session: Database,
room_id: int,
playlist_id: int,
score_id: int,
current_user: User = Security(get_client_user),
session: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
):
room = await session.get(Room, room_id)
@@ -678,11 +678,11 @@ async def show_playlist_score(
tags=["成绩"],
)
async def get_user_playlist_score(
session: Database,
room_id: int,
playlist_id: int,
user_id: int,
current_user: User = Security(get_client_user),
session: AsyncSession = Depends(get_db),
):
score_record = None
start_time = time.time()
@@ -716,9 +716,9 @@ async def get_user_playlist_score(
tags=["成绩"],
)
async def pin_score(
db: Database,
score_id: int = Path(description="成绩 ID"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
score_record = (
await db.exec(
@@ -758,9 +758,9 @@ async def pin_score(
tags=["成绩"],
)
async def unpin_score(
db: Database,
score_id: int = Path(description="成绩 ID"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
score_record = (
await db.exec(
@@ -797,11 +797,11 @@ async def unpin_score(
tags=["成绩"],
)
async def reorder_score_pin(
db: Database,
score_id: int = Path(description="成绩 ID"),
after_score_id: int | None = Body(default=None, description="放在该成绩之后"),
before_score_id: int | None = Body(default=None, description="放在该成绩之前"),
current_user: User = Security(get_client_user),
db: AsyncSession = Depends(get_db),
):
score_record = (
await db.exec(
@@ -892,8 +892,8 @@ async def reorder_score_pin(
)
async def download_score_replay(
score_id: int,
db: Database,
current_user: User = Security(get_current_user, scopes=["public"]),
db: AsyncSession = Depends(get_db),
storage_service: StorageService = Depends(get_storage_service),
):
score = (await db.exec(select(Score).where(Score.id == score_id))).first()

View File

@@ -15,17 +15,16 @@ from app.database.events import EventResp
from app.database.lazer_user import SEARCH_INCLUDED
from app.database.pp_best_score import PPBestScore
from app.database.score import Score, ScoreResp
from app.dependencies.database import get_db
from app.dependencies.database import Database
from app.dependencies.user import get_current_user
from app.models.score import GameMode
from app.models.user import BeatmapsetType
from .router import router
from fastapi import Depends, HTTPException, Path, Query, Security
from fastapi import HTTPException, Path, Query, Security
from pydantic import BaseModel
from sqlmodel import exists, false, select
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlmodel.sql.expression import col
@@ -43,6 +42,7 @@ class BatchUserResponse(BaseModel):
@router.get("/users/lookup", response_model=BatchUserResponse, include_in_schema=False)
@router.get("/users/lookup/", response_model=BatchUserResponse, include_in_schema=False)
async def get_users(
session: Database,
user_ids: list[int] = Query(
default_factory=list, alias="ids[]", description="要查询的用户 ID 列表"
),
@@ -50,7 +50,6 @@ async def get_users(
include_variant_statistics: bool = Query(
default=False, description="是否包含各模式的统计信息"
), # TODO: future use
session: AsyncSession = Depends(get_db),
):
if user_ids:
searched_users = (
@@ -79,9 +78,9 @@ async def get_users(
tags=["用户"],
)
async def get_user_info_ruleset(
session: Database,
user_id: str = Path(description="用户 ID 或用户名"),
ruleset: GameMode | None = Path(description="指定 ruleset"),
session: AsyncSession = Depends(get_db),
# current_user: User = Security(get_current_user, scopes=["public"]),
):
searched_user = (
@@ -112,8 +111,8 @@ async def get_user_info_ruleset(
tags=["用户"],
)
async def get_user_info(
session: Database,
user_id: str = Path(description="用户 ID 或用户名"),
session: AsyncSession = Depends(get_db),
# current_user: User = Security(get_current_user, scopes=["public"]),
):
searched_user = (
@@ -142,10 +141,10 @@ async def get_user_info(
tags=["用户"],
)
async def get_user_beatmapsets(
session: Database,
user_id: int = Path(description="用户 ID"),
type: BeatmapsetType = Path(description="谱面集类型"),
current_user: User = Security(get_current_user, scopes=["public"]),
session: AsyncSession = Depends(get_db),
limit: int = Query(100, ge=1, le=1000, description="返回条数 (1-1000)"),
offset: int = Query(0, ge=0, description="偏移量"),
):
@@ -202,6 +201,7 @@ async def get_user_beatmapsets(
tags=["用户"],
)
async def get_user_scores(
session: Database,
user_id: int = Path(description="用户 ID"),
type: Literal["best", "recent", "firsts", "pinned"] = Path(
description=(
@@ -216,7 +216,6 @@ async def get_user_scores(
),
limit: int = Query(100, ge=1, le=1000, description="返回条数 (1-1000)"),
offset: int = Query(0, ge=0, description="偏移量"),
session: AsyncSession = Depends(get_db),
current_user: User = Security(get_current_user, scopes=["public"]),
):
db_user = await session.get(User, user_id)
@@ -267,10 +266,10 @@ async def get_user_scores(
"/users/{user}/recent_activity", tags=["用户"], response_model=list[EventResp]
)
async def get_user_events(
session: Database,
user: int,
limit: int | None = Query(None),
offset: str | None = Query(None), # TODO: 搞清楚并且添加这个奇怪的分页偏移
session: AsyncSession = Depends(get_db),
):
db_user = await session.get(User, user)
if db_user is None or db_user.id == BANCHOBOT_ID: