From a0b76bbde361b41ae382d9d8555e61480d673fb1 Mon Sep 17 00:00:00 2001 From: MingxuanGame Date: Fri, 22 Aug 2025 10:06:26 +0000 Subject: [PATCH] docs(readme): update readme --- .env.example | 128 +++++++++++++++++-------------- README.en.md | 129 +------------------------------ README.md | 143 +---------------------------------- app/config.py | 15 ++-- app/service/email_service.py | 6 -- main.py | 39 +++++----- 6 files changed, 101 insertions(+), 359 deletions(-) diff --git a/.env.example b/.env.example index 56febcc..9615669 100644 --- a/.env.example +++ b/.env.example @@ -1,94 +1,107 @@ -# 数据库设置 +# see https://github.com/GooGuTeam/g0v0-server/wiki/Configuration +# Database Settings MYSQL_HOST="localhost" MYSQL_PORT=3306 MYSQL_DATABASE="osu_api" MYSQL_USER="osu_api" MYSQL_PASSWORD="password" MYSQL_ROOT_PASSWORD="password" -# Redis URL REDIS_URL="redis://127.0.0.1:6379/0" -# JWT 密钥,使用 openssl rand -hex 32 生成 +# JWT Settings +# Use `openssl rand -hex 32` to generate a secure key JWT_SECRET_KEY="your_jwt_secret_here" -# JWT 算法 ALGORITHM="HS256" -# JWT 过期时间 ACCESS_TOKEN_EXPIRE_MINUTES=1440 -# 服务器地址 +# OAuth Settings +OSU_CLIENT_ID=5 +OSU_CLIENT_SECRET="FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk" +OSU_WEB_CLIENT_ID=6 +# Use `openssl rand -hex 40` to generate a secure key +OSU_WEB_CLIENT_SECRET="your_osu_web_client_secret_here" + +# Server Settings HOST="0.0.0.0" PORT=8000 -# 服务器 URL -SERVER_URL="http://localhost:8000" -# 额外的 CORS 允许的域名列表 -CORS_URLS='[]' -# 前端 URL,当访问从游戏打开的 URL 时会重定向到这个 URL,为空表示不重定向 -FRONTEND_URL -# 调试模式,生产环境请设置为 false DEBUG=false +CORS_URLS='[]' +SERVER_URL="http://localhost:8000" +FRONTEND_URL= -# osu! 登录设置 -OSU_CLIENT_ID=5 # lazer client ID -OSU_CLIENT_SECRET="FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk" # lazer client secret -OSU_WEB_CLIENT_ID=6 # 网页端 client ID -OSU_WEB_CLIENT_SECRET="your_osu_web_client_secret_here" # 网页端 client secret,使用 openssl rand -hex 40 生成 - -# SignalR 服务器设置 +# SignalR Settings SIGNALR_NEGOTIATE_TIMEOUT=30 SIGNALR_PING_INTERVAL=15 -# Fetcher 设置 +# Fetcher Settings FETCHER_CLIENT_ID="" FETCHER_CLIENT_SECRET="" -FETCHER_SCOPES=public +FETCHER_SCOPES="public" -# 日志设置 +# Logging Settings LOG_LEVEL="INFO" -# 邮件服务设置 -SMTP_SERVER="smtp.gmail.com" # SMTP 服务器地址 -SMTP_PORT=587 # SMTP 端口 -SMTP_USERNAME="your-email@gmail.com" # 邮箱用户名 -SMTP_PASSWORD="your-app-password" # 邮箱密码或应用专用密码 -FROM_EMAIL="noreply@your-server.com" # 发送方邮箱 -FROM_NAME="osu! Private Server" # 发送方名称 +# Email Service Settings +ENABLE_EMAIL_VERIFICATION=false +SMTP_SERVER="localhost" +SMTP_PORT=587 +SMTP_USERNAME="" +SMTP_PASSWORD="" +FROM_EMAIL="noreply@example.com" +FROM_NAME="osu! server" -# 邮件验证功能开关 -ENABLE_EMAIL_VERIFICATION=true # 是否启用邮件验证功能(新位置登录时需要邮件验证) -ENABLE_EMAIL_SENDING=false # 是否真实发送邮件(false时仅模拟发送,输出到日志) +# Sentry Configuration +SENTRY_DSN= -# Sentry 设置,为空表示不启用 -SENTRY_DSN +# New Relic Configuration +NEW_RELIC_ENVIRONMENT= -# GeoIP 配置 - MaxMind License Key(用于 IP 地址地理位置查询) +# GeoIP Configuration MAXMIND_LICENSE_KEY="" -# GeoIP 数据库存储目录 GEOIP_DEST_DIR="./geoip" -# GeoIP 每周更新的星期几(0=周一,6=周日) GEOIP_UPDATE_DAY=1 -# GeoIP 每周更新时间(小时,0-23) GEOIP_UPDATE_HOUR=2 -# 游戏设置 -ENABLE_RX=false # 启用 RX mod 统计数据 -ENABLE_AP=false # 启用 AP mod Z统计数据 -ENABLE_ALL_MODS_PP=false # 启用所有 Mod 的 PP 计算 -ENABLE_SUPPORTER_FOR_ALL_USERS=false # 启用所有新注册用户的支持者状态 -ENABLE_ALL_BEATMAP_LEADERBOARD=false # 启用所有谱面的排行榜(没有排行榜的谱面会以 APPROVED 状态返回) -ENABLE_ALL_BEATMAP_PP=false # 允许任何谱面获得 PP -SUSPICIOUS_SCORE_CHECK=true # 是否检查可疑的分数,默认开启 -SEASONAL_BACKGROUNDS='[]' # 季节背景图 URL 列表 -BANNED_NAME='["mrekk", "vaxei", "btmc", "cookiezi", "peppy", "saragi", "chocomint"]' # 禁止使用的用户名列表 +# Game Settings +ENABLE_RX=false +ENABLE_AP=false +ENABLE_ALL_MODS_PP=false +ENABLE_SUPPORTER_FOR_ALL_USERS=false +ENABLE_ALL_BEATMAP_LEADERBOARD=false +ENABLE_ALL_BEATMAP_PP=false +SEASONAL_BACKGROUNDS='[]' -# 存储服务设置 -# 支持的存储类型:local(本地存储)、r2(Cloudflare R2)、s3(AWS S3) +# Beatmap Cache Settings +ENABLE_BEATMAP_PRELOAD=true +BEATMAP_CACHE_EXPIRE_HOURS=24 + +# Ranking Cache Settings +ENABLE_RANKING_CACHE=true +RANKING_CACHE_EXPIRE_MINUTES=10 +RANKING_CACHE_REFRESH_INTERVAL_MINUTES=10 +RANKING_CACHE_MAX_PAGES=20 +RANKING_CACHE_TOP_COUNTRIES=20 + +# User Cache Settings +ENABLE_USER_CACHE_PRELOAD=true +USER_CACHE_EXPIRE_SECONDS=300 +USER_SCORES_CACHE_EXPIRE_SECONDS=60 +USER_BEATMAPSETS_CACHE_EXPIRE_SECONDS=600 +USER_CACHE_MAX_PRELOAD_USERS=200 +USER_CACHE_CONCURRENT_LIMIT=10 + +# Anti-cheat Settings +SUSPICIOUS_SCORE_CHECK=true +BANNED_NAME='["mrekk", "vaxei", "btmc", "cookiezi", "peppy", "saragi", "chocomint"]' + +# Storage Settings +# Supported storage services: local, r2, s3 STORAGE_SERVICE="local" -# 存储服务配置 (JSON 格式) -# 本地存储配置(当 STORAGE_SERVICE=local 时) -STORAGE_SETTINGS='{"local_storage_path": "./storage"}' +# Local Storage Settings (when STORAGE_SERVICE=local) +# STORAGE_SETTINGS='{"local_storage_path": "./storage"}' -# Cloudflare R2 存储配置(当 STORAGE_SERVICE=r2 时) +# Cloudflare R2 Storage Settings (when STORAGE_SERVICE=r2) # STORAGE_SETTINGS='{ # "r2_account_id": "your_cloudflare_r2_account_id", # "r2_access_key_id": "your_r2_access_key_id", @@ -97,11 +110,10 @@ STORAGE_SETTINGS='{"local_storage_path": "./storage"}' # "r2_public_url_base": "https://your-custom-domain.com" # }' -# AWS S3 存储配置(当 STORAGE_SERVICE=s3 时) +# AWS S3 Storage Settings (when STORAGE_SERVICE=s3) # STORAGE_SETTINGS='{ # "s3_access_key_id": "your_aws_access_key_id", # "s3_secret_access_key": "your_aws_secret_access_key", # "s3_bucket_name": "your_s3_bucket_name", # "s3_region_name": "us-east-1", -# "s3_public_url_base": "https://your-custom-domain.com" -# }' +# "s3_public_url_base": "https://your-custom diff --git a/README.en.md b/README.en.md index 5bceb03..661cc58 100644 --- a/README.en.md +++ b/README.en.md @@ -25,7 +25,7 @@ This is an osu! API server implemented with FastAPI + MySQL + Redis, supporting ``` 2. Create a `.env` file - Please see the server configuration below to modify the .env file. + Please see [wiki](https://github.com/GooGuTeam/g0v0-server/wiki/Configuration) to modify the .env file. ```bash cp .env.example .env ``` @@ -40,131 +40,6 @@ This is an osu! API server implemented with FastAPI + MySQL + Redis, supporting Use a [custom osu!lazer client](https://github.com/GooGuTeam/osu), or use [LazerAuthlibInjection](https://github.com/MingxuanGame/LazerAuthlibInjection), and change the server settings to the server's address. -## Configuration - -### Database Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `MYSQL_HOST` | MySQL host address | `localhost` | -| `MYSQL_PORT` | MySQL port | `3306` | -| `MYSQL_DATABASE` | MySQL database name | `osu_api` | -| `MYSQL_USER` | MySQL username | `osu_api` | -| `MYSQL_PASSWORD` | MySQL password | `password` | -| `MYSQL_ROOT_PASSWORD` | MySQL root password | `password` | -| `REDIS_URL` | Redis connection string | `redis://127.0.0.1:6379/0` | - -### JWT Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `JWT_SECRET_KEY` | JWT signing key | `your_jwt_secret_here` | -| `ALGORITHM` | JWT algorithm | `HS256` | -| `ACCESS_TOKEN_EXPIRE_MINUTES` | Access token expiration time (minutes) | `1440` | - -### Server Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `HOST` | Server listening address | `0.0.0.0` | -| `PORT` | Server listening port | `8000` | -| `DEBUG` | Debug mode | `false` | -| `SERVER_URL` | Server URL | `http://localhost:8000` | -| `CORS_URLS` | Additional CORS allowed domain list (JSON format) | `[]` | -| `FRONTEND_URL` | Frontend URL, redirects to this URL when accessing URLs opened from the game. Empty means no redirection. | `(null)` | - -### OAuth Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `OSU_CLIENT_ID` | OAuth client ID | `5` | -| `OSU_CLIENT_SECRET` | OAuth client secret | `FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk` | -| `OSU_WEB_CLIENT_ID` | Web OAuth client ID | `6` | -| `OSU_WEB_CLIENT_SECRET` | Web OAuth client secret | `your_osu_web_client_secret_here` | - -### SignalR Server Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `SIGNALR_NEGOTIATE_TIMEOUT` | SignalR negotiation timeout (seconds) | `30` | -| `SIGNALR_PING_INTERVAL` | SignalR ping interval (seconds) | `15` | - -### Fetcher Settings - -The Fetcher is used to get data from the official osu! API using OAuth 2.0 authentication. - -| Variable Name | Description | Default Value | -|---|---|---| -| `FETCHER_CLIENT_ID` | Fetcher client ID | `""` | -| `FETCHER_CLIENT_SECRET` | Fetcher client secret | `""` | -| `FETCHER_SCOPES` | Fetcher scopes | `public` | - -### Log Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `LOG_LEVEL` | Log level | `INFO` | - -### Sentry Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `SENTRY_DSN` | Sentry DSN, empty to disable Sentry | `(null)` | - -### Game Settings -| Variable Name | Description | Default Value | -|---|---|---| -| `ENABLE_RX` | Enable RX mod statistics | `false` | -| `ENABLE_AP` | Enable AP mod statistics | `false` | -| `ENABLE_ALL_MODS_PP` | Enable PP calculation for all mods | `false` | -| `ENABLE_SUPPORTER_FOR_ALL_USERS` | Enable supporter status for all new users | `false` | -| `ENABLE_ALL_BEATMAP_LEADERBOARD` | Enable leaderboards for all beatmaps | `false` | -| `ENABLE_ALL_BEATMAP_PP` | Allow any beatmap to grant PP | `false` | -| `SUSPICIOUS_SCORE_CHECK` | Enable suspicious score check (star>25 & acc<80 or pp>2300) | `true` | -| `SEASONAL_BACKGROUNDS` | List of seasonal background URLs | `[]` | -| `BANNED_NAME` | List of banned usernames | `["mrekk", "vaxei", "btmc", "cookiezi", "peppy", "saragi", "chocomint"]` | - -### Storage Service Settings - -Used for storing replay files, avatars, and other static assets. - -| Variable Name | Description | Default Value | -|---|---|---| -| `STORAGE_SERVICE` | Storage service type: `local`, `r2`, `s3` | `local` | -| `STORAGE_SETTINGS` | Storage service configuration (JSON format), see below for configuration | `{"local_storage_path": "./storage"}` | - -## Storage Service Configuration - -### Local Storage (Recommended for development) - -Local storage saves files to the server's local filesystem, suitable for development and small-scale deployments. - -```bash -STORAGE_SERVICE="local" -STORAGE_SETTINGS='{"local_storage_path": "./storage"}' -``` - -### Cloudflare R2 Storage (Recommended for production) - -```bash -STORAGE_SERVICE="r2" -STORAGE_SETTINGS='{ - "r2_account_id": "your_cloudflare_account_id", - "r2_access_key_id": "your_r2_access_key_id", - "r2_secret_access_key": "your_r2_secret_access_key", - "r2_bucket_name": "your_bucket_name", - "r2_public_url_base": "https://your-custom-domain.com" -}' -``` - -### AWS S3 Storage - -```bash -STORAGE_SERVICE="s3" -STORAGE_SETTINGS='{ - "s3_access_key_id": "your_aws_access_key_id", - "s3_secret_access_key": "your_aws_secret_access_key", - "s3_bucket_name": "your_s3_bucket_name", - "s3_region_name": "us-east-1", - "s3_public_url_base": "https://your-custom-domain.com" -}' -``` - -> **Note**: In a production environment, be sure to change the default keys and passwords! - ### Updating the Database Refer to the [Database Migration Guide](https://github.com/GooGuTeam/g0v0-server/wiki/Migrate-Database) @@ -177,6 +52,8 @@ MIT License The project is currently in a state of rapid iteration. Issues and Pull Requests are welcome! +See [Contributing Guide](./CONTRIBUTING.md) for more information. + ## Discussion - Discord: https://discord.gg/AhzJXXWYfF diff --git a/README.md b/README.md index 15cdc8f..1f64fe2 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ cd g0v0-server 2. 创建 `.env` 文件 -请参考下方的服务器配置修改 .env 文件 +请参考 [wiki](https://github.com/GooGuTeam/g0v0-server/wiki/Configuration) 来修改 `.env` 文件 ```bash cp .env.example .env @@ -44,145 +44,6 @@ docker-compose -f docker-compose-osurx.yml up -d 使用[自定义的 osu!lazer 客户端](https://github.com/GooGuTeam/osu),或者使用 [LazerAuthlibInjection](https://github.com/MingxuanGame/LazerAuthlibInjection),修改服务器设置为服务器的 IP -## 环境变量配置 - -### 数据库设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `MYSQL_HOST` | MySQL 主机地址 | `localhost` | -| `MYSQL_PORT` | MySQL 端口 | `3306` | -| `MYSQL_DATABASE` | MySQL 数据库名 | `osu_api` | -| `MYSQL_USER` | MySQL 用户名 | `osu_api` | -| `MYSQL_PASSWORD` | MySQL 密码 | `password` | -| `MYSQL_ROOT_PASSWORD` | MySQL root 密码 | `password` | -| `REDIS_URL` | Redis 连接字符串 | `redis://127.0.0.1:6379/0` | - -### JWT 设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `JWT_SECRET_KEY` | JWT 签名密钥 | `your_jwt_secret_here` | -| `ALGORITHM` | JWT 算法 | `HS256` | -| `ACCESS_TOKEN_EXPIRE_MINUTES` | 访问令牌过期时间(分钟) | `1440` | - -### 服务器设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `HOST` | 服务器监听地址 | `0.0.0.0` | -| `PORT` | 服务器监听端口 | `8000` | -| `DEBUG` | 调试模式 | `false` | -| `SERVER_URL` | 服务器 URL | `http://localhost:8000` | -| `CORS_URLS` | 额外的 CORS 允许的域名列表 (JSON 格式) | `[]` | -| `FRONTEND_URL` | 前端 URL,当访问从游戏打开的 URL 时会重定向到这个 URL,为空表示不重定向 | `(null)` | - -### OAuth 设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `OSU_CLIENT_ID` | OAuth 客户端 ID | `5` | -| `OSU_CLIENT_SECRET` | OAuth 客户端密钥 | `FGc9GAtyHzeQDshWP5Ah7dega8hJACAJpQtw6OXk` | -| `OSU_WEB_CLIENT_ID` | Web OAuth 客户端 ID | `6` | -| `OSU_WEB_CLIENT_SECRET` | Web OAuth 客户端密钥 | `your_osu_web_client_secret_here` - -### SignalR 服务器设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `SIGNALR_NEGOTIATE_TIMEOUT` | SignalR 协商超时时间(秒) | `30` | -| `SIGNALR_PING_INTERVAL` | SignalR ping 间隔(秒) | `15` | - -### Fetcher 设置 - -Fetcher 用于从 osu! 官方 API 获取数据,使用 osu! 官方 API 的 OAuth 2.0 认证 - -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `FETCHER_CLIENT_ID` | Fetcher 客户端 ID | `""` | -| `FETCHER_CLIENT_SECRET` | Fetcher 客户端密钥 | `""` | -| `FETCHER_SCOPES` | Fetcher 权限范围 | `public` | - -### 日志设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `LOG_LEVEL` | 日志级别 | `INFO` | - -### Sentry 设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `SENTRY_DSN` | Sentry DSN,为空不启用 Sentry | `(null)` | - -### GeoIP 配置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `MAXMIND_LICENSE_KEY` | MaxMind License Key(用于下载离线IP库) | `""` | -| `GEOIP_DEST_DIR` | GeoIP 数据库存储目录 | `"./geoip"` | -| `GEOIP_UPDATE_DAY` | GeoIP 每周更新的星期几(0=周一,6=周日) | `1` | -| `GEOIP_UPDATE_HOUR` | GeoIP 每周更新时间(小时,0-23) | `2` | - -### New Relic 设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `NEW_RELIC_ENVIRONMENT` | New Relic 环境标识 | `"production"` 或 `"development"` | - -将 `newrelic.ini` 配置文件放入项目根目录即可自动启用 New Relic 监控。如果配置文件不存在或 newrelic 包未安装,将跳过 New Relic 初始化。可通过环境变量 `NEW_RELIC_ENVIRONMENT` 指定运行环境。 - -### 游戏设置 -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `ENABLE_RX` | 启用 RX mod 统计数据 | `false` | -| `ENABLE_AP` | 启用 AP mod 统计数据 | `false` | -| `ENABLE_ALL_MODS_PP` | 启用所有 Mod 的 PP 计算 | `false` | -| `ENABLE_SUPPORTER_FOR_ALL_USERS` | 启用所有新注册用户的支持者状态 | `false` | -| `ENABLE_ALL_BEATMAP_LEADERBOARD` | 启用所有谱面的排行榜 | `false` | -| `ENABLE_ALL_BEATMAP_PP` | 允许任何谱面获得 PP | `false` | -| `SUSPICIOUS_SCORE_CHECK` | 启用可疑分数检查(star>25&acc<80 或 pp>2300) | `true` | -| `SEASONAL_BACKGROUNDS` | 季节背景图 URL 列表 | `[]` | -| `BANNED_NAME` | 禁止使用的用户名列表 | `["mrekk", "vaxei", "btmc", "cookiezi", "peppy", "saragi", "chocomint"]` | - -### 存储服务设置 - -用于存储回放文件、头像等静态资源。 - -| 变量名 | 描述 | 默认值 | -|--------|------|--------| -| `STORAGE_SERVICE` | 存储服务类型:`local`、`r2`、`s3` | `local` | -| `STORAGE_SETTINGS` | 存储服务配置 (JSON 格式),配置见下 | `{"local_storage_path": "./storage"}` | - -## 存储服务配置 - -### 本地存储 (推荐用于开发环境) - -本地存储将文件保存在服务器的本地文件系统中,适合开发和小规模部署。 - -```bash -STORAGE_SERVICE="local" -STORAGE_SETTINGS='{"local_storage_path": "./storage"}' -``` - -### Cloudflare R2 存储 (推荐用于生产环境) - -```bash -STORAGE_SERVICE="r2" -STORAGE_SETTINGS='{ - "r2_account_id": "your_cloudflare_account_id", - "r2_access_key_id": "your_r2_access_key_id", - "r2_secret_access_key": "your_r2_secret_access_key", - "r2_bucket_name": "your_bucket_name", - "r2_public_url_base": "https://your-custom-domain.com" -}' -``` - -### AWS S3 存储 - -```bash -STORAGE_SERVICE="s3" -STORAGE_SETTINGS='{ - "s3_access_key_id": "your_aws_access_key_id", - "s3_secret_access_key": "your_aws_secret_access_key", - "s3_bucket_name": "your_s3_bucket_name", - "s3_region_name": "us-east-1", - "s3_public_url_base": "https://your-custom-domain.com" -}' -``` - -> **注意**: 在生产环境中,请务必更改默认的密钥和密码! ### 更新数据库 @@ -196,6 +57,8 @@ MIT License 项目目前处于快速迭代状态,欢迎提交 Issue 和 Pull Request! +查看 [贡献指南](./CONTRIBUTING.md) 获取更多信息。 + ## 参与讨论 - QQ 群:`1059561526` diff --git a/app/config.py b/app/config.py index ed29100..5761f61 100644 --- a/app/config.py +++ b/app/config.py @@ -118,6 +118,7 @@ class Settings(BaseSettings): log_level: str = "INFO" # 邮件服务设置 + enable_email_verification: bool = Field(default=False, description="是否启用邮件验证功能") smtp_server: str = "localhost" smtp_port: int = 587 smtp_username: str = "" @@ -125,13 +126,12 @@ class Settings(BaseSettings): from_email: str = "noreply@example.com" from_name: str = "osu! server" - # 邮件验证功能开关 - enable_email_verification: bool = Field(default=True, description="是否启用邮件验证功能") - enable_email_sending: bool = Field(default=False, description="是否真实发送邮件(False时仅模拟发送)") - # Sentry 配置 sentry_dsn: HttpUrl | None = None + # New Relic 配置 + new_relic_environment: None | str = None + # GeoIP 配置 maxmind_license_key: str = "" geoip_dest_dir: str = "./geoip" @@ -145,11 +145,11 @@ class Settings(BaseSettings): enable_supporter_for_all_users: bool = False enable_all_beatmap_leaderboard: bool = False enable_all_beatmap_pp: bool = False - # 性能优化设置 + seasonal_backgrounds: Annotated[list[str], BeforeValidator(_parse_list)] = [] + + # 谱面缓存设置 enable_beatmap_preload: bool = True beatmap_cache_expire_hours: int = 24 - max_concurrent_pp_calculations: int = 10 - enable_pp_calculation_threading: bool = True # 排行榜缓存设置 enable_ranking_cache: bool = True @@ -168,7 +168,6 @@ class Settings(BaseSettings): # 反作弊设置 suspicious_score_check: bool = True - seasonal_backgrounds: Annotated[list[str], BeforeValidator(_parse_list)] = [] banned_name: list[str] = [ "mrekk", "vaxei", diff --git a/app/service/email_service.py b/app/service/email_service.py index 12cb70c..32f7124 100644 --- a/app/service/email_service.py +++ b/app/service/email_service.py @@ -140,12 +140,6 @@ class EmailService: msg.attach(MIMEText(html_content, "html", "utf-8")) - # 发送邮件 - if not settings.enable_email_sending: - # 邮件发送功能禁用时只记录日志,不实际发送 - logger.info(f"[Email Verification] Mock sending verification code to {email}: {code}") - return True - with smtplib.SMTP(self.smtp_server, self.smtp_port) as server: if self.smtp_username and self.smtp_password: server.starttls() diff --git a/main.py b/main.py index 3031213..c6e414b 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ import asyncio from contextlib import asynccontextmanager from datetime import datetime import os +from pathlib import Path from app.config import settings from app.dependencies.database import engine, redis_client @@ -42,27 +43,6 @@ from app.service.redis_message_system import redis_message_system from app.service.stats_scheduler import start_stats_scheduler, stop_stats_scheduler from app.utils import bg_tasks -# 检查 New Relic 配置文件是否存在,如果存在则初始化 New Relic -newrelic_config_path = os.path.join(os.path.dirname(__file__), "newrelic.ini") -if os.path.exists(newrelic_config_path): - try: - import newrelic.agent - - environment = os.environ.get( - "NEW_RELIC_ENVIRONMENT", - "production" if not settings.debug else "development", - ) - - newrelic.agent.initialize(newrelic_config_path, environment) - logger.info(f"[NewRelic] Enabled, environment: {environment}") - except ImportError: - logger.warning("[NewRelic] Config file found but 'newrelic' package is not installed") - except Exception as e: - logger.error(f"[NewRelic] Initialization failed: {e}") -else: - logger.info("[NewRelic] No newrelic.ini config file found, skipping initialization") - - from fastapi import FastAPI, HTTPException, Request from fastapi.exceptions import RequestValidationError from fastapi.middleware.cors import CORSMiddleware @@ -110,6 +90,23 @@ desc = ( "V1 API 文档:[osu-api](https://github.com/ppy/osu-api/wiki)" ) +# 检查 New Relic 配置文件是否存在,如果存在则初始化 New Relic +newrelic_config_path = Path("newrelic.ini") +if newrelic_config_path.exists(): + try: + import newrelic.agent + + environment = settings.new_relic_environment or ("production" if not settings.debug else "development") + + newrelic.agent.initialize(newrelic_config_path, environment) + logger.info(f"[NewRelic] Enabled, environment: {environment}") + except ImportError: + logger.warning("[NewRelic] Config file found but 'newrelic' package is not installed") + except Exception as e: + logger.error(f"[NewRelic] Initialization failed: {e}") +else: + logger.info("[NewRelic] No newrelic.ini config file found, skipping initialization") + if settings.sentry_dsn is not None: sentry_sdk.init( dsn=str(settings.sentry_dsn),