184 lines
5.9 KiB
Python
184 lines
5.9 KiB
Python
from pydantic import Field, field_validator, model_validator
|
||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||
import os
|
||
import logging
|
||
|
||
logger = logging.getLogger("onmyoji_gacha")
|
||
|
||
|
||
def _read_nonebot_config(name: str) -> str:
|
||
"""从 NoneBot driver.config 读取配置;测试或独立加载模块时静默回退。"""
|
||
|
||
try:
|
||
from nonebot import get_driver
|
||
|
||
driver_config = get_driver().config
|
||
except Exception:
|
||
return ""
|
||
value = getattr(driver_config, name.lower(), "")
|
||
return str(value) if value is not None else ""
|
||
|
||
|
||
def _read_setting(name: str) -> str:
|
||
"""按单个配置名读取系统环境变量,再读取 NoneBot 配置对象。"""
|
||
|
||
return os.getenv(name, "") or _read_nonebot_config(name)
|
||
|
||
|
||
def _first_setting(*names: str, default: str = "") -> str:
|
||
"""按业务优先级读取多个兼容配置名。"""
|
||
|
||
for name in names:
|
||
value = _read_setting(name)
|
||
if value:
|
||
return value
|
||
return default
|
||
|
||
|
||
class Config(BaseSettings):
|
||
model_config = SettingsConfigDict(extra="ignore")
|
||
|
||
# 抽卡概率配置
|
||
RARITY_PROBABILITY: dict = {
|
||
"R": 78.75,
|
||
"SR": 20.0,
|
||
"SSR": 1.0,
|
||
"SP": 0.25
|
||
}
|
||
|
||
# 每日抽卡限制
|
||
DAILY_LIMIT: int = 3
|
||
|
||
# 数据文件路径
|
||
DB_FILE: str = "data/onmyoji_gacha/gacha.db"
|
||
|
||
# 式神图片目录
|
||
SHIKIGAMI_IMG_DIR: str = "data/chouka/"
|
||
|
||
# 触发指令
|
||
GACHA_COMMANDS: list = ["抽卡","抽奖", "召唤"]
|
||
STATS_COMMANDS: list = ["我的抽卡","我的抽奖", "我的图鉴"]
|
||
DAILY_STATS_COMMANDS: list = ["今日抽卡", "今日统计", "抽卡统计"]
|
||
TRIPLE_GACHA_COMMANDS: list = ["三连", "三连抽"]
|
||
ACHIEVEMENT_COMMANDS: list = ["查询成就", "抽卡成就"]
|
||
INTRO_COMMANDS: list = ["抽卡介绍", "抽卡说明", "抽卡帮助"]
|
||
|
||
# 成就系统配置
|
||
ACHIEVEMENTS: dict = {
|
||
"consecutive_days_30_1": {
|
||
"name": "勤勤恳恳Ⅰ",
|
||
"description": "连续抽卡30天",
|
||
"reward": "天卡",
|
||
"threshold": 30,
|
||
"type": "consecutive_days",
|
||
"level": 1,
|
||
"repeatable": True
|
||
},
|
||
"consecutive_days_30_2": {
|
||
"name": "勤勤恳恳Ⅱ",
|
||
"description": "连续抽卡60天",
|
||
"reward": "天卡",
|
||
"threshold": 60,
|
||
"type": "consecutive_days",
|
||
"level": 2,
|
||
"repeatable": True
|
||
},
|
||
"consecutive_days_30_3": {
|
||
"name": "勤勤恳恳Ⅲ",
|
||
"description": "连续抽卡90天",
|
||
"reward": "天卡",
|
||
"threshold": 90,
|
||
"type": "consecutive_days",
|
||
"level": 3,
|
||
"repeatable": True
|
||
},
|
||
"consecutive_days_30_4": {
|
||
"name": "勤勤恳恳Ⅳ",
|
||
"description": "连续抽卡120天",
|
||
"reward": "周卡",
|
||
"threshold": 120,
|
||
"type": "consecutive_days",
|
||
"level": 4,
|
||
"repeatable": True
|
||
},
|
||
"consecutive_days_30_5": {
|
||
"name": "勤勤恳恳Ⅴ",
|
||
"description": "连续抽卡150天",
|
||
"reward": "周卡",
|
||
"threshold": 150,
|
||
"type": "consecutive_days",
|
||
"level": 5,
|
||
"repeatable": True,
|
||
"repeat_reward": "天卡"
|
||
},
|
||
"no_ssr_60": {
|
||
"name": "非酋",
|
||
"description": "连续60次未抽到SSR/SP",
|
||
"reward": "天卡",
|
||
"threshold": 60,
|
||
"type": "no_ssr_streak"
|
||
},
|
||
"no_ssr_120": {
|
||
"name": "顶级非酋",
|
||
"description": "连续120次未抽到SSR/SP",
|
||
"reward": "周卡",
|
||
"threshold": 120,
|
||
"type": "no_ssr_streak"
|
||
},
|
||
"no_ssr_180": {
|
||
"name": "月见黑",
|
||
"description": "连续180次未抽到SSR/SP",
|
||
"reward": "月卡",
|
||
"threshold": 180,
|
||
"type": "no_ssr_streak"
|
||
}
|
||
}
|
||
|
||
# 权限配置
|
||
ALLOWED_GROUP_ID: int = 621016172
|
||
ALLOWED_USER_ID: int = 1424473282
|
||
|
||
# 特殊概率用户配置
|
||
SPECIAL_PROBABILITY_USERS: list = [] # 100%抽到SSR或SP的用户列表
|
||
|
||
# Web后台管理配置
|
||
WEB_ADMIN_TOKEN: str = Field(
|
||
default_factory=lambda: _first_setting("WEB_ADMIN_TOKEN", default="onmyoji_admin_token_2024")
|
||
)
|
||
WEB_ADMIN_PORT: int = Field(default_factory=lambda: int(_first_setting("WEB_ADMIN_PORT", default="8080")))
|
||
|
||
# 蛋定服务器对接配置
|
||
DD_API_HOST: str = "https://api.danding.vip/DD/"
|
||
GACHA_API_HOST: str = Field(
|
||
default_factory=lambda: _first_setting(
|
||
"DANDING_GACHA_API_HOST",
|
||
default="https://api.danding.vip/bot/gacha",
|
||
)
|
||
)
|
||
BOT_TOKEN: str = Field(
|
||
default_factory=lambda: _first_setting(
|
||
"DANDING_BOT_TOKEN",
|
||
"ONMYOJI_BOT_TOKEN",
|
||
"DANDING_API_TOKEN",
|
||
"BOT_TOKEN",
|
||
)
|
||
)
|
||
BOT_USER_ID: str = Field(default_factory=lambda: _first_setting("DANDING_BOT_USER", default="1424473282"))
|
||
|
||
# 时区
|
||
TIMEZONE: str = "Asia/Shanghai"
|
||
|
||
@field_validator("GACHA_API_HOST")
|
||
@classmethod
|
||
def validate_gacha_api_host(cls, value):
|
||
if not value:
|
||
raise ValueError("GACHA_API_HOST cannot be empty")
|
||
return value.rstrip("/")
|
||
|
||
@model_validator(mode="after")
|
||
def _warn_default_token(self):
|
||
"""运行时警告:如果使用默认admin token,在生产环境可能被猜解"""
|
||
if self.WEB_ADMIN_TOKEN == "onmyoji_admin_token_2024":
|
||
logger.warning("⚠️ WEB_ADMIN_TOKEN 使用默认值,生产环境请务必通过环境变量覆盖!")
|
||
return self
|