Commit Graph

214 Commits

Author SHA1 Message Date
MingxuanGame
33f321952d feat(custom-rulesets): support custom rulesets (#23)
* feat(custom_ruleset): add custom rulesets support

* feat(custom-ruleset): add version check

* feat(custom-ruleset): add LegacyIO API to get ruleset hashes

* feat(pp): add check for rulesets whose pp cannot be calculated

* docs(readme): update README to include support for custom rulesets

* fix(custom-ruleset): make `rulesets` empty instead of throw a error when version check is disabled

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore(custom-ruleset): apply the latest changes of generator

c891bcd159

and

e25041ad3b

* feat(calculator): add fallback performance calculation for unsupported modes

* fix(calculator): remove debug print

* fix: resolve reviews

* feat(calculator): add difficulty calculation checks

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-26 21:10:36 +08:00
MingxuanGame
2c81e22749 feat(calculator): support generate PerformanceAttributes & DifficultyAttributes from JSON Schema (#59)
Prepare for custom rulesets.

Schema Genetator: https://github.com/GooGuTeam/custom-rulesets/tree/main/CustomRulesetMetadataGenerator

```bash
dotnet -- schemas path/to/rulesets -o schema.json
```

```bash
python scripts/generate_ruleset_attributes.py schema.json 
```
2025-10-25 19:10:53 +08:00
咕谷酱
a4dbb9a167 feat(matchmaking): support matchmaking (#48) 2025-10-19 00:05:06 +08:00
MingxuanGame
8790ccad64 feat(pp-calculator): support other pp calculators (#57)
New configurations:

- CALCULATOR="rosu": specific pp calculator
- CALCULATOR_CONFIG='{}': argument passed through into calculator
2025-10-18 19:10:53 +08:00
MingxuanGame
45ed9e51a9 feat(team): add playmode, description, website and statistics 2025-10-08 05:46:17 +00:00
MingxuanGame
95f7c010af fix(trusted-device): no location in response 2025-10-07 12:18:56 +00:00
MingxuanGame
10caa82320 feat(user-preference): add user preference support (#55)
APIs:

- GET `/api/private/user/preferences`: Get current user's preferences.
- PATCH `/api/private/user/preferences`: Modify current user's preferences. (body: Preferences)
- PUT `/api/private/user/preferences`: Overwrite current user's preferences. (body: Preferences)
- DELETE `/api/private/user/preferences`: Reset current user's preferences. (body: list[str])
  - body specifies the content to be reset. If body is empty, reset all preferences.

User:

- `User.g0v0_playmode`: show the special ruleset like `OSURX`, and custom rulesets in the future.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-06 20:57:17 +08:00
MingxuanGame
febc1d761f feat(user): implement user restrictions
## APIs Restricted for Restricted Users

A restricted user is blocked from performing the following actions, and will typically receive a `403 Forbidden` error:

*   **Chat & Notifications:**
    *   Sending any chat messages (public or private).
    *   Joining or leaving chat channels.
    *   Creating new PM channels.
*   **User Profile & Content:**
    *   Uploading a new avatar.
    *   Uploading a new profile cover image.
    *   Changing their username.
    *   Updating their userpage content.
*   **Scores & Gameplay:**
    *   Submitting scores in multiplayer rooms.
    *   Deleting their own scores (to prevent hiding evidence of cheating).
*   **Beatmaps:**
    *   Rating beatmaps.
    *   Taging beatmaps.
*   **Relationship:**
    *   Adding friends or blocking users.
    *   Removing friends or unblocking users.
*   **Teams:**
    *   Creating, updating, or deleting a team.
    *   Requesting to join a team.
    *   Handling join requests for a team they manage.
    *   Kicking a member from a team they manage.
*   **Multiplayer:**
    *   Creating or deleting multiplayer rooms.
    *   Joining or leaving multiplayer rooms.

## What is Invisible to Normal Users

*   **Leaderboards:**
    *   Beatmap leaderboards.
    *   Multiplayer (playlist) room leaderboards.
*   **User Search/Lists:**
    *   Restricted users will not appear in the results of the `/api/v2/users` endpoint.
    *   They will not appear in the list of a team's members.
*   **Relationship:**
    *   They will not appear in a user's friend list (`/friends`).
*   **Profile & History:**
    *   Attempting to view a restricted user's profile, events, kudosu history, or score history will result in a `404 Not Found` error, effectively making their profile invisible (unless the user viewing the profile is the restricted user themselves).
*   **Chat:**
    *   Normal users cannot start a new PM with a restricted user (they will get a `404 Not Found` error).
*   **Ranking:**
    *   Restricted users are excluded from any rankings.

### How to Restrict a User

Insert into `user_account_history` with `type=restriction`.

```sql
-- length is in seconds
INSERT INTO user_account_history (`description`, `length`, `permanent`, `timestamp`, `type`, `user_id`) VALUE ('some description', 86400, 0, '2025-10-05 01:00:00', 'RESTRICTION', 1);
```

---

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-06 11:10:25 +08:00
MingxuanGame
6f522847ec fix(playcount): show the sum of all users' playcount in BeatmapResp/BeatmapsetResp 2025-10-04 10:50:33 +00:00
MingxuanGame
1163a93053 refactor(scores): rename models of score to match with filename 2025-10-04 08:01:38 +00:00
MingxuanGame
470e8b3c06 fix(beatmapset): update cursor type of SearchBeatmapsetsResp to support string values 2025-10-04 07:35:35 +00:00
MingxuanGame
ca7c74f709 refactor(project): remove useless getattr 2025-10-04 06:43:55 +00:00
MingxuanGame
dfd656f2fb style(project): remove from __future__ import annotations 2025-10-03 17:15:41 +00:00
MingxuanGame
d490239f46 chore(linter): update ruff rules 2025-10-03 15:46:53 +00:00
MingxuanGame
0d9019c6cc refactor(signalr): remove SignalR server & msgpack_lazer_api
Maybe we can make `msgpack_lazer_api` independent?
2025-10-03 13:20:12 +00:00
MingxuanGame
d23f32f08d refactor(log): refactor the whole project
format: {time:YYYY-MM-DD HH:mm:ss} [{level}] | {name} | {message}
{name} is:
- Uvicorn: log from uvicorn server (#228B22)
- Service: log from class of `app.service` (blue)
- Fetcher: log from fetchers (magenta)
- Task: log from `app.tasks` (#FFD700)
- System: log from `system_logger` (red)
- Normal: log from `log(name)` (#FFC1C1)
- Default: the module name of caller

if you are writing services or tasks, you can just call `logger.`, we will pack it with name `Service` or `Task`
if you want to print fetcher logs, system-related logs, or normal logs, use `logger = (fetcher_logger / system_logger / log)(name)`
2025-10-03 11:53:05 +00:00
MingxuanGame
fce88272b5 refactor(task): move schedulers and startup/shutdown task into tasks directory 2025-10-03 10:15:22 +00:00
MingxuanGame
346c2557cf refactor(api): use Annotated-style dependency injection 2025-10-03 05:41:31 +00:00
MingxuanGame
37b4eadf79 refactor(database): rename filename to find the models by table name easily 2025-10-03 03:33:47 +00:00
MingxuanGame
40670c094b feat(auth): support trusted device (#52)
New API to maintain sessions and devices:

- GET /api/private/admin/sessions
- DELETE /api/private/admin/sessions/{session_id}
- GET /api/private/admin/trusted-devices
- DELETE /api/private/admin/trusted-devices/{device_id}

Auth:

web clients request `/oauth/token` and `/api/v2/session/verify` with `X-UUID` header to save the client as trusted device.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-03 11:26:43 +08:00
MingxuanGame
f34ed53a55 fix(beatmap): fix beatmap.beatmapset is None when it from from_resp 2025-10-02 16:41:40 +00:00
MingxuanGame
f31056ced3 perf(score): divide score processing into small parts and make them run in background
resolve #47
2025-10-02 14:30:57 +00:00
MingxuanGame
3f6776847e feat(beatmap,score): update beatmaps from Bancho & deleting scores (#50)
New API:

- DELETE /api/private/score/{score_id}: delete a score
- POST /api/private/beatmapsets/{beatmapset_id}/sync: request for syncing a beatmapset

New configuration:

- OLD_SCORE_PROCESSING_MODE
2025-10-02 13:36:09 +08:00
咕谷酱
86c7bbb74e 优化验证 2025-09-24 02:08:13 +08:00
MingxuanGame
1527e23b43 feat(session-verify): 添加 TOTP 支持 (#34)
* chore(deps): add pyotp

* feat(auth): implement TOTP verification

feat(auth): implement TOTP verification and email verification services

- Added TOTP keys management with a new database model `TotpKeys`.
- Introduced `EmailVerification` and `LoginSession` models for email verification.
- Created `verification_service` to handle email verification logic and TOTP processes.
- Updated user response models to include session verification methods.
- Implemented routes for TOTP creation, verification, and fallback to email verification.
- Enhanced login session management to support new location checks and verification methods.
- Added migration script to create `totp_keys` table in the database.

* feat(config): update config example

* docs(totp): complete creating TOTP flow

* refactor(totp): resolve review

* feat(api): forbid unverified request

* fix(totp): trace session by token id to avoid other sessions are forbidden

* chore(linter): make pyright happy

* fix(totp): only mark sessions with a specified token id
2025-09-21 19:50:11 +08:00
pre-commit-ci[bot]
6330e9b6e1 chore(linter): auto fix by pre-commit hooks 2025-09-17 17:39:21 +00:00
咕谷酱
55225366dc 临时修复成就事件格式问题 2025-09-15 20:35:44 +08:00
MingxuanGame
61639454a3 feat(room): use participated user count as participant count for playlist room 2025-09-14 06:31:29 +00:00
MingxuanGame
19f94fffbb feat(api): 支持 x-api-version (#29)
* feat(relationship): support legacy-compatible response format

* feat(score): add support for legacy score response format in API

* fix(score): avoid missing greenlet

* fix(score): fix missing field for model validation

* feat(user): apply legacy score format for user

* feat(api): use `int` to hint `APIVersion`
2025-09-14 14:09:53 +08:00
MingxuanGame
f4e6c3a58f feat(tags): add minimum vote count for top tags & provide official tags
Add configuration: `BEATMAP_TAG_TOP_COUNT` to control the minimun vote count

Tips: this is 10 in osu-web, but private server doesn't have enough player so we use 2 as default value

Official tags see: https://osu.ppy.sh/wiki/Beatmap/Beatmap_tags
2025-09-14 05:21:48 +00:00
MingxuanGame
7d0b2c657d feat(event): replace beatmap url with server url 2025-09-13 14:38:43 +00:00
MingxuanGame
e872c25918 fix(score): make scores of loved beatmap as ranked scores 2025-08-30 11:49:23 +00:00
MingxuanGame
554f1e6432 fix(daily-challenge): last_update will return correct time to display in client 2025-08-30 10:26:12 +00:00
陈晋瑭
6c2e88c485 feat(beatmap): 添加谱面用户标签功能 (#25)
* feat(tags): 添加 beatmap tags 相关功能

- 新增 BeatmapTags 模型类,用于表示 beatmap 的标签信息
- 实现加载标签数据、根据 ID 获取标签、获取所有标签等功能

* feat(database): 新增 BeatmapTagVote 数据库模型和迁移脚本

* fix(database): 修改 BeatmapTagVote 模型并创建新表

- 将 BeatmapTagVote 模型的表名从 "beatmap_tag_votes" 改为 "beatmap_tags"
- 创建新的数据库迁移文件以替换错误的原迁移文件
- 删除错误的迁移文件 "4a827ddba235_add_table_beatmap_tags.py"

* feat(tags): 添加用户标签功能

- 在 BeatmapResp 类中添加了 top_tag_ids 和 current_user_tag_ids 字段
- 新增了 /tags 相关的路由,包括获取所有标签和投票/取消投票功能
- 实现了标签投票和取消投票的数据库操作

* fix(tags): 修复标签投票查询和返回过程中的逻辑问题

- 修复 BeatmapResp 类中 current_user_tag_ids 字段的查询逻辑
- 优化 vote_beatmap_tags 函数中的标签验证过程

* fix(tags): add suggested changes from reviews

- 在 BeatmapResp 中添加 top_tag_ids 和 current_user_tag_ids 字段
- 实现用户标签投票功能,包括检查用户是否有资格投票
- 优化标签数据的加载方式
- 调整标签相关路由,增加路径参数描述

* fix(tags): apply changes from review

* fix(tag): apply changes from review suggests

- 更新标签接口文档,统一参数描述
- 修改标签投票接口状态码为 204
- 优化标签投票接口的用户认证方式
- 改进标签相关错误处理,使用更友好的错误信息

* fix(tag): use client authorization

* chore(linter): auto fix by pre-commit hooks

---------

Co-authored-by: MingxuanGame <MingxuanGame@outlook.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-08-30 16:23:59 +08:00
MingxuanGame
224e890e31 feat(recalculate): add scheduled job to recalculate failed scores 2025-08-28 16:53:15 +00:00
陈晋瑭
3c5336ed61 添加谱面用户打分(评分)相关接口 (#24)
* feat(database): 添加 beatmap_ratings 表用于用户评分

- 新增 BeatmapRating 模型类,用于表示 beatmap_ratings 表
- 该表包含 id、beatmapset_id、user_id 字段
- 建立与 Beatmapset 和 User 表的关联关系

* feat(beatmapset_ratings): 添加判断用户是否可以对谱面集进行评分的接口

- 新增 /beatmapsets/{beatmapset_id}/can_rate 接口
- 判断用户是否能对谱面集进行过评分,返回True/False

* feat(ratings): 添加为谱面评分的接口

- 新增 POST /beatmapsets/{beatmapset_id} 路由,用于用户给谱面集评分
- 实现谱面集评分的添加和更新逻辑
- 在 BeatmapRating 模型中添加 rating 字段 (漏了最重要的,我真tm丢脸)

* chore(database): 添加alembic数据库迁移脚本

* fix(ratings): 更改上传谱面打分的api路径,防止冲突

* fix(ratings): add changes from pr review

* refactor(ratings): remove swears from code

* feat(ratings): 从beatmapset中移除ratings字段,并改由从beatmap_ratings表中直接计算评分

* chore(deps): 添加 git 包并更新依赖项

- 在 builder 阶段添加了 git 包的安装

* chore(database): 更新数据库连接地址并删除意外的迁移脚本

- 将 Alembic 配置文件中的数据库连接地址从本地地址改为 Docker Compose 中的 mysql 服务地址
- 删除了 migrations/versions 目录下的 dba1f8d9992e_add_beatmap_ratings_table.py 文件

* chore(database): generate alembic script for beatmap ratings

* fix(ratings): apply changes suggested in review

- revert changes to alembic.ini
- add name to apis
- modify migration scripts

* chore: format server.py using ruff

- who forgot to do this?

* fix(migrate): fix remove achievement index

* perf(rating): optimize SQL query

* fix(rating): ensure user can rate beatmapset

* fix(rating): add boundary check

* chore(project): remove submodule

---------

Co-authored-by: MingxuanGame <MingxuanGame@outlook.com>
2025-08-28 20:55:00 +08:00
MingxuanGame
7ec716d4de feat(user): support get the user's first scores 2025-08-26 16:42:57 +00:00
MingxuanGame
bc12182770 fix(user): rank lost event uses the owner of the displaced score's username 2025-08-26 15:53:32 +00:00
MingxuanGame
60745c1269 feat(score): auto recalculate for banned beatmaps
Running every hour
2025-08-26 15:12:14 +00:00
MingxuanGame
900fa9b121 fix(score): fix incorrect best_id 2025-08-26 13:18:11 +08:00
MingxuanGame
9681aa68b4 feat(banchobot): show weighted pp in score commands 2025-08-26 13:18:11 +08:00
MingxuanGame
bab6f843a5 fix(user): fix online status 2025-08-26 13:18:11 +08:00
MingxuanGame
9d92fa0a68 fix(score): fix score process 2025-08-26 13:18:11 +08:00
MingxuanGame
8d38f230cb refactor(room): remove duplicated multiplayer event model 2025-08-26 13:18:11 +08:00
pre-commit-ci[bot]
7625cd99f5 chore(deps): auto fix by pre-commit hooks 2025-08-26 13:18:11 +08:00
咕谷酱
56d6911589 Add multiplayer room event model and channel ID allocation
Introduces the MultiplayerRealtimeRoomEvent SQLModel for tracking real-time room events. Adds an async helper to allocate unique channel IDs for rooms, and updates room creation logic to use this helper for assigning channel IDs automatically.
2025-08-26 13:18:11 +08:00
咕谷酱
fabc1e9e88 Refactor Playlist model and add timestamps migration
Simplifies the PlaylistBase id field to a non-optional int and updates database logic to use session.refresh for id assignment. Adds Alembic migration to include created_at and updated_at columns in room_playlists for timestamp tracking.
2025-08-26 13:18:11 +08:00
咕谷酱
97dcc86d4d Add endpoint to ensure beatmap presence and cache
Introduces a new /beatmaps/ensure API endpoint to verify and cache beatmap metadata and raw files. Updates Playlist model to use auto-incrementing primary key and improves playlist DB insertion logic. Minor formatting and import changes in room and lio modules.
2025-08-26 13:18:11 +08:00
咕谷酱
ea575de250 Add updated_at and created_at to Playlist model
Introduces created_at and updated_at fields to the Playlist model for tracking creation and modification times. Refactors room user removal logic to handle owner transfer and participant count updates more robustly. Updates room query logic for more accurate filtering by category and status. Adds migration stubs for updated_at column in room playlists.
2025-08-26 13:18:11 +08:00
咕谷酱
e0aae80f4b Add password support to multiplayer rooms
Introduces a password field to the Room model and database schema, enabling password-protected multiplayer rooms. Adds LIO router endpoints for room creation, user join/leave, and updates related imports and router registrations.
2025-08-26 13:18:11 +08:00