feat: 抽卡签到功能 - 首次抽卡/三连自动签到获随机积分
- data_manager: 新增 daily_sign_in 表、has_signed_in_today、record_sign_in 方法 - utils: 新增 get_luck_description、format_sign_in_message 函数 - __init__: 新增 try_handle_daily_sign_in 签到入口 - handle_gacha/handle_triple_gacha 成功路径 finish()→send()+签到+return - 签到失败不影响抽卡主流程,UNIQUE约束防并发重复
This commit is contained in:
95
test_onmyoji_gacha_sign_in.py
Normal file
95
test_onmyoji_gacha_sign_in.py
Normal file
@@ -0,0 +1,95 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
import importlib.util
|
||||
import sys
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def ensure_package(package_name: str, package_path: Path) -> None:
|
||||
if package_name in sys.modules:
|
||||
return
|
||||
package = types.ModuleType(package_name)
|
||||
package.__path__ = [str(package_path)]
|
||||
sys.modules[package_name] = package
|
||||
|
||||
|
||||
def load_module(module_name: str, relative_path: str):
|
||||
module_path = PROJECT_ROOT / relative_path
|
||||
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
assert spec and spec.loader
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
ensure_package("danding_bot", PROJECT_ROOT / "danding_bot")
|
||||
ensure_package("danding_bot.plugins", PROJECT_ROOT / "danding_bot/plugins")
|
||||
ensure_package(
|
||||
"danding_bot.plugins.onmyoji_gacha",
|
||||
PROJECT_ROOT / "danding_bot/plugins/onmyoji_gacha",
|
||||
)
|
||||
load_module(
|
||||
"danding_bot.plugins.onmyoji_gacha.config",
|
||||
"danding_bot/plugins/onmyoji_gacha/config.py",
|
||||
)
|
||||
data_manager_module = load_module(
|
||||
"danding_bot.plugins.onmyoji_gacha.data_manager",
|
||||
"danding_bot/plugins/onmyoji_gacha/data_manager.py",
|
||||
)
|
||||
utils = load_module(
|
||||
"danding_bot.plugins.onmyoji_gacha.utils",
|
||||
"danding_bot/plugins/onmyoji_gacha/utils.py",
|
||||
)
|
||||
|
||||
|
||||
class DataManagerSignInTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
self.temp_dir = tempfile.TemporaryDirectory()
|
||||
base_path = Path(self.temp_dir.name)
|
||||
self.original_db_file = data_manager_module.config.DB_FILE
|
||||
self.original_img_dir = data_manager_module.config.SHIKIGAMI_IMG_DIR
|
||||
data_manager_module.config.DB_FILE = str(base_path / "gacha.db")
|
||||
data_manager_module.config.SHIKIGAMI_IMG_DIR = str(base_path / "images")
|
||||
Path(data_manager_module.config.SHIKIGAMI_IMG_DIR).mkdir(parents=True, exist_ok=True)
|
||||
self.manager = data_manager_module.DataManager()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
data_manager_module.config.DB_FILE = self.original_db_file
|
||||
data_manager_module.config.SHIKIGAMI_IMG_DIR = self.original_img_dir
|
||||
self.temp_dir.cleanup()
|
||||
|
||||
def test_record_sign_in_is_idempotent_for_same_day(self) -> None:
|
||||
user_id = "10001"
|
||||
|
||||
self.assertFalse(self.manager.has_signed_in_today(user_id))
|
||||
self.assertTrue(self.manager.record_sign_in(user_id, 88))
|
||||
self.assertTrue(self.manager.has_signed_in_today(user_id))
|
||||
self.assertFalse(self.manager.record_sign_in(user_id, 99))
|
||||
|
||||
|
||||
class UtilsSignInTests(unittest.TestCase):
|
||||
def test_get_luck_description_uses_document_ranges(self) -> None:
|
||||
self.assertEqual(utils.get_luck_description(1), ("非酋", "😭"))
|
||||
self.assertEqual(utils.get_luck_description(11), ("一般", "😐"))
|
||||
self.assertEqual(utils.get_luck_description(31), ("小欧", "😊"))
|
||||
self.assertEqual(utils.get_luck_description(61), ("大欧", "🎉"))
|
||||
self.assertEqual(utils.get_luck_description(91), ("欧皇", "👑"))
|
||||
|
||||
def test_format_sign_in_message_matches_required_format(self) -> None:
|
||||
message = utils.format_sign_in_message("10001", "小夏", 87, 1247)
|
||||
expected = (
|
||||
"@小夏 📅 每日签到成功!\n"
|
||||
"🎁 获得积分:87\n"
|
||||
"🎉 今日运气:大欧\n"
|
||||
"💰 当前积分:1247"
|
||||
)
|
||||
self.assertEqual(message, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user