feat(tarots): 新增塔罗牌占卜插件

新增了一个功能完备的塔罗牌占卜插件,为机器人增加了娱乐和互动能力。

主要功能包括:

- **自然语言交互**:通过 Action 响应用户的抽牌请求,并由大模型进行个性化解牌。
- **多牌组与牌阵**:内置B站幻星集、经典韦特和东方塔罗牌组,支持单张、圣三角等多种牌阵。
- **智能图片缓存**:自动从网络下载并缓存卡牌图片,具备完整性校验和代理支持,提升响应速度。
- **管理指令**:提供 `/tarots` 指令,方便管理员一键缓存所有图片和切换当前使用的牌组。
This commit is contained in:
tt-P607
2025-09-17 15:27:23 +08:00
committed by Windpicker-owo
parent 81fc58ce41
commit c64a1f8ea5
6 changed files with 2376 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
{
"manifest_version": 1,
"name": "塔罗牌插件",
"version": "1.3.0",
"description": "提供了抽塔罗牌占卜功能具有模拟人类的调用方式和独特自定义风格的解牌回复。牌面为B站幻星集",
"author": {
"name": "A肆零西烛",
"url": "https://github.com/A0000Xz"
},
"license": "AGPL-v3.0",
"host_application": {
"min_version": "0.9.1",
"max_version": "0.10.0"
},
"keywords": ["tarot", "divination","moderation","bilibili"],
"categories": ["Moderation", "Entertainment-oriented divination"],
"repository_url": "https://github.com/A0000Xz/MaiBot-Tarots-Plugin",
"default_locale": "zh-CN",
"locales_path": "_locales"
}

View File

@@ -0,0 +1,850 @@
from src.plugin_system.base.base_plugin import BasePlugin
from src.plugin_system.apis.plugin_register_api import register_plugin
from src.plugin_system.base.base_action import BaseAction, ActionActivationType, ChatMode
from src.plugin_system.base.base_command import BaseCommand
from src.plugin_system.base.component_types import ComponentInfo
from src.plugin_system.base.config_types import ConfigField
from src.plugin_system.apis import generator_api
from src.plugin_system.apis import database_api
from src.plugin_system.apis import config_api
from src.plugin_system.apis import send_api
from src.common.database.sqlalchemy_models import Messages, PersonInfo
from src.common.data_models.database_data_model import DatabaseMessages
from src.person_info.person_info import get_person_info_manager
from src.common.logger import get_logger
from PIL import Image
from typing import Tuple, Dict, Optional, List, Any, Type
from pathlib import Path
import traceback
import tomlkit
import json
import random
import asyncio
import aiohttp
import base64
import toml
import io
import os
import re
logger = get_logger("tarots")
class TarotsAction(BaseAction):
action_name = "tarots"
# 双激活类型配置
focus_activation_type = ActionActivationType.LLM_JUDGE
normal_activation_type = ActionActivationType.ALWAYS
activation_keywords = ["抽一张塔罗牌", "抽张塔罗牌"]
keyword_case_sensitive = False
# 模式和并行控制
mode_enable = ChatMode.ALL
parallel_action = False
action_description = "执行塔罗牌占卜,支持多种抽牌方式" # action描述
action_parameters = {
"card_type": "塔罗牌的抽牌范围,必填,只能填一个参数,这里请根据用户的要求填'全部''大阿卡纳''小阿卡纳',如果用户的要求并不明确,默认填'全部'",
"formation": "塔罗牌的抽牌方式,必填,只能填一个参数,这里请根据用户的要求填'单张''圣三角''时间之流''四要素''五牌阵''吉普赛十字''马蹄''六芒星',如果用户的要求并不明确,默认填'单张'",
"target_message": "提出抽塔罗牌的对方的发言内容,格式必须为:(用户名:发言内容若不清楚是回复谁的话可以为None"
}
action_require = [
"当消息包含'抽塔罗牌''塔罗牌占卜'等关键词,且用户明确表达了要求你帮忙抽牌的意向时,你看心情调用就行(这意味着你可以拒绝抽塔罗牌,拒绝执行这个动作)。",
"用户需要明确指定抽牌范围和抽牌类型,如果用户未明确指定抽牌范围则默认为'全部',未明确指定抽牌类型则默认为'单张'",
"请仔细辨别对方到底是不是在让你抽塔罗牌!如果用户只是单独说了'抽卡''抽牌''占卜''算命'等,而且并没有上文内容验证用户是想抽塔罗牌的意思,就不要抽塔罗牌,不要执行这个动作!",
"在完成一次抽牌后,请仔细确定用户有没有明确要求再抽一次,没有再次要求就不要继续执行这个动作。"
]
associated_types = ["image", "text"] #该插件会发送的消息类型
def __init__(self,
action_data: dict,
reasoning: str,
cycle_timers: dict,
thinking_id: str,
global_config: Optional[dict] = None,
action_message: Optional[dict] = None,
**kwargs,
):
# 显式调用父类初始化
super().__init__(
action_data=action_data,
reasoning=reasoning,
cycle_timers=cycle_timers,
thinking_id=thinking_id,
global_config=global_config,
action_message=action_message,
**kwargs
)
self.action_message = action_message
# 初始化基本路径
self.base_dir = Path(__file__).parent.absolute()
# 扫描并更新可用牌组
self.config = self._load_config()
self._update_available_card_sets()
# 初始化路径
self.using_cards = self.config["cards"].get("using_cards", 'bilibili')
if not self.using_cards:
self.cache_dir = self.base_dir / "tarots_cache" / "default"
else:
self.cache_dir = self.base_dir / "tarots_cache" / self.using_cards # 定义图片缓存主文件夹为tarots_cache后面紧随牌组文件夹名
self.cache_dir.mkdir(parents=True, exist_ok=True) # 不存在该文件夹就创建
# 加载卡牌数据
self.card_map: Dict = {}
self.formation_map: Dict = {}
self._load_resources()
def _load_resources(self):
"""同步加载资源文件(显式指定UTF-8编码)"""
try:
if not self.using_cards:
logger.info("没有加载到任何可用牌组")
return
# 加载卡牌数据
with open(
self.base_dir / f"tarot_jsons/{self.using_cards}/tarots.json",
encoding="utf-8"
) as f:
self.card_map = json.load(f)
# 加载牌阵配置
with open(
self.base_dir / "tarot_jsons/formation.json",
encoding="utf-8"
) as f:
self.formation_map = json.load(f)
logger.info(f"{self.log_prefix} 已加载{self.card_map['_meta']['total_cards']}张卡牌和{len(self.formation_map)}种抽牌方式")
except UnicodeDecodeError as e:
logger.error(f"{self.log_prefix} 编码错误: 请确保JSON文件为UTF-8格式 - {str(e)}")
raise
except Exception as e:
logger.error(f"{self.log_prefix} 资源加载失败: {str(e)}")
raise
async def execute(self) -> Tuple[bool, str]:
"""实现基类要求的入口方法"""
try:
if not self.card_map:
await self.send_text("没有牌组,无法使用")
return False, "没有牌组,无法使用"
logger.info(f"{self.log_prefix} 开始执行塔罗占卜")
# 参数解析
request_type = self.action_data.get("card_type", "全部")
formation_name = self.action_data.get("formation", "单张")
card_type = self.get_available_card_type(request_type)
# 参数校验
if card_type not in ["全部", "大阿卡纳", "小阿卡纳"]:
await self.send_text("不存在这样的抽牌范围")
return False, "参数错误"
if formation_name not in self.formation_map:
await self.send_text("不存在这样的抽牌方法")
return False, "参数错误"
# 获取牌阵配置
formation = self.formation_map[formation_name] # 根据确定好的抽牌方式名称获取具体牌阵的字典
cards_num = formation["cards_num"] # 该抽牌方式要抽几张牌
is_cut = formation["is_cut"] # 该抽牌方式要不要切牌
represent_list = formation["represent"] # 该抽牌方式所包含的预言方向内容
# 获取有效卡牌范围
valid_ids = self._get_card_range(card_type)
if not valid_ids:
await self.send_text("当前牌堆不对")
return False, "参数错误"
# 抽牌逻辑
selected_ids = random.sample(valid_ids, cards_num)
if is_cut:
selected_cards = [
(cid, random.random() < 0.5) # 切牌时50%概率逆位
for cid in selected_ids
]
else:
selected_cards = [
(cid, False) # 不切牌时全部正位
for cid in selected_ids
]
# 结果处理
result_text = f"{formation_name}牌阵 - {self.using_cards}牌组】\n"
failed_images = [] # 记录获取失败的图片
# 优先使用target_message来定位精确的回复目标
target_message_str = self.action_data.get("target_message")
reply_target_message = self.action_message # 默认引用触发消息
user_nickname = self.user_nickname
if target_message_str:
try:
# 解析用户名
if ":" in target_message_str:
target_nickname = target_message_str.split(":", 1)[0].strip()
elif "" in target_message_str:
target_nickname = target_message_str.split("", 1)[0].strip()
else:
target_nickname = None
if target_nickname:
user_nickname = target_nickname # 更新为正确的用户昵称
# 在数据库中查找该用户的最近一条消息
found_message = await database_api.db_get(
Messages,
filters={"user_nickname": target_nickname},
order_by="-time",
limit=1,
single_result=True
)
if found_message:
# 将字典转换为标准的数据模型对象,再转回字典,以确保格式正确
reply_target_obj = DatabaseMessages(**found_message)
reply_target_message = reply_target_obj.to_dict()
logger.info(f"已定位到来自'{target_nickname}'的最新消息进行引用: {found_message.get('message_id')}")
else:
logger.warning(f"未能找到来自'{target_nickname}'的任何消息,将回退至默认引用")
except Exception as e:
logger.warning(f"解析target_message时出错: {e}, 将回退至默认引用")
for idx, (card_id, is_reverse) in enumerate(selected_cards):
card_data = self.card_map[card_id]
card_info = card_data["info"]
pos_name = represent_list[0][idx] if idx < len(represent_list[0]) else f"位置{idx+1}"
# 轮询发送图片
img_data = await self._get_card_image(card_id, is_reverse)
if img_data:
b64_data = base64.b64encode(img_data).decode('utf-8')
await send_api.custom_to_stream(
message_type="image",
content=b64_data,
stream_id=self.chat_id,
reply_to_message=reply_target_message,
set_reply=True
)
else:
# 记录失败的图片
failed_images.append(f"{card_data['name']}({'逆位' if is_reverse else '正位'})")
logger.warning(f"{self.log_prefix} 卡牌图片获取失败: {card_id}")
# 轮询构建文本
desc = card_info['reverseDescription'] if is_reverse else card_info['description']
result_text += (
f"\n{pos_name} - {'逆位' if is_reverse else '正位'} {card_data['name']}\n"
f"{desc[:100]}...\n"
)
await asyncio.sleep(0.3) # 防止消息频率限制
if failed_images:
error_msg = f"以下卡牌图片获取失败,占卜中断: {', '.join(failed_images)}"
await self.send_text(error_msg)
return False, ""
# 发送最终文本
await asyncio.sleep(1.5) # 权宜之计给最后一张图片1.5s的发送起跑时间,无可奈何的办法
original_text = self.config["adjustment"].get("enable_original_text", False)
self_id = config_api.get_global_config("bot.qq_account")
# 查询自己机器人本体的名字,因为可乐允许机器人自己更改自己的绰号,还一直在不断的改!
self_personinfo = await database_api.db_get(
PersonInfo,
filters={"user_id": f"{self_id}"},
limit=1,
single_result = True
)
message_text = ""
result_status, result_message, _ = await generator_api.rewrite_reply(
chat_stream=self.chat_stream,
reply_data={
"raw_reply": result_text,
"reason": "抽出了塔罗牌结果,请根据其内容为用户进行解牌"
},
reply_to=target_message_str or "",
enable_splitter=False,
enable_chinese_typo=False
) # 让你的麦麦用自己的语言风格阐释结果
# 获取数据库内最近1条记录
records = await database_api.db_get(
Messages,
filters={"user_id": f"{self_id}"},
order_by="-time",
limit=1,
single_result = True
)
# 处理records文本中的引用格式
processed_record_text = ""
if records:
processed_record_text = records['processed_plain_text']
# 处理回复格式
reply_match = re.search(r"回复<([^:<>]+):([^:<>]+)>", processed_record_text)
if reply_match:
person_id = get_person_info_manager().get_person_id("qq", reply_match.group(2))
person_name = await get_person_info_manager().get_value(person_id, "person_name") or reply_match.group(1)
processed_record_text = re.sub(r"回复<[^:<>]+:[^:<>]+>", f"回复 {person_name}", processed_record_text, count=1)
# 处理@格式
for match in re.finditer(r"@<([^:<>]+):([^:<>]+)>", processed_record_text):
person_id = get_person_info_manager().get_person_id("qq", match.group(2))
person_name = await get_person_info_manager().get_value(person_id, "person_name") or match.group(1)
processed_record_text = processed_record_text.replace(match.group(0), f"@{person_name}")
if original_text:
await self.send_text(result_text)
logger.info("原始文本已发送")
if result_status:
# 合并所有消息片段
message_text = result_message[0][1]
# 一次性发送合并的消息
if message_text:
await send_api.text_to_stream(
text=message_text,
stream_id=self.chat_id,
reply_to_message=reply_target_message
)
logger.info("合并消息已发送")
else:
return False, "消息生成错误很可能是generator炸了"
# 记录动作信息
await self.store_action_info(
action_build_into_prompt=True,
action_prompt_display=f"已为{user_nickname}抽取了塔罗牌并成功解牌。",
action_done=True
)
return True, f"已为{user_nickname}抽取了塔罗牌并成功解牌,占卜成功。"
except Exception as e:
error_msg = traceback.format_exc()
logger.error(f"{self.log_prefix} 执行失败: {error_msg}")
await self.send_text(f"占卜失败: {str(e)}")
return False, "执行错误"
def _get_card_range(self, card_type: str) -> list:
"""获取卡牌范围"""
if card_type == "大阿卡纳":
return [str(i) for i in range(22)]
elif card_type == "小阿卡纳":
return [str(i) for i in range(22, 78)]
return [str(i) for i in range(78)] # 既不是大阿卡纳也不是小阿卡纳就返回全部的
async def _get_card_image(self, card_id: str, is_reverse: bool) -> Optional[bytes]:
"""获取卡牌图片(有缓存机制)"""
try:
filename = f"{card_id}_norm.png"
cache_path = self.cache_dir / filename
# 检查缓存文件是否存在且有效
if not cache_path.exists() or not self._validate_image_integrity(cache_path):
if cache_path.exists():
logger.warning(f"{self.log_prefix} 发现损坏的缓存文件,准备重新下载: {cache_path}")
try:
cache_path.unlink()
except Exception as e:
logger.error(f"{self.log_prefix} 删除损坏文件失败: {str(e)}")
return None
# 下载图片,现在返回布尔值
success = await self._download_image(card_id, cache_path)
if not success:
return None
with open(cache_path, "rb") as f:
img_data = f.read()
if is_reverse:
img_data = self._rotate_image(img_data) # 如果是逆位牌直接把正位牌扭180度
if not img_data: # 旋转失败
return None
return img_data
except Exception as e:
logger.warning(f"{self.log_prefix} 获取图片失败: {str(e)}")
return None
def _rotate_image(self, img_data: bytes) -> Optional[bytes]:
"""将图片旋转180度生成逆位图片"""
try:
# bytes → PIL Image对象
image = Image.open(io.BytesIO(img_data))
# 旋转180度逆时针
rotated_image = image.rotate(180)
# PIL Image对象 → bytes
buffer = io.BytesIO()
rotated_image.save(buffer, format='PNG')
return buffer.getvalue()
except Exception as e:
logger.error(f"{self.log_prefix} 图片旋转失败: {str(e)}")
# 旋转失败时返回None
return None
async def _download_image(self, card_id: str, save_path: Path):
"""图片本地缓存"""
MAX_RETRIES = 3
RETRY_DELAY = 2 # 初始重试间隔(秒)
try:
# 获取卡牌数据
card_info = self.card_map[card_id]["info"]
img_path = card_info['imgUrl']
base_url = self.card_map["_meta"]["base_url"]
# 获取代理数据
enable_proxy = self.config["proxy"].get("enable_proxy", False)
if enable_proxy:
proxy_url = self.config["proxy"].get("proxy_url", "")
else:
proxy_url = None
# 构建完整的下载URL
full_url = f"{base_url}{img_path}"
# 下载尝试循环
for attempt in range(1, MAX_RETRIES + 1):
try:
logger.info(f"[图片下载] 尝试 {attempt}/{MAX_RETRIES} - {card_id} - {full_url}")
async with aiohttp.ClientSession() as session:
async with session.get(full_url, timeout=15, proxy=proxy_url) as resp:
if resp.status == 200:
# 确保目录存在
save_path.parent.mkdir(parents=True, exist_ok=True)
# 写入文件
with open(save_path, "wb") as f:
f.write(await resp.read())
# 立即进行完整性检测
if self._validate_image_integrity(save_path):
logger.info(f"[图片下载] 成功并通过完整性检测 {save_path.name} (尝试 {attempt}次)")
return True
else:
# 完整性检测失败,删除文件
logger.warning(f"[图片下载] 完整性检测失败,删除文件: {save_path}")
try:
save_path.unlink()
except Exception as delete_error:
logger.error(f"[图片下载] 删除损坏文件失败: {delete_error}")
# 如果不是最后一次尝试,继续重试
if attempt < MAX_RETRIES:
logger.info(f"[图片下载] 完整性检测失败,准备重试 (尝试 {attempt+1}/{MAX_RETRIES})")
continue
else:
logger.error(f"[图片下载] 完整性检测失败且已达最大重试次数: {save_path}")
break
else:
logger.warning(f"[图片下载] 异常状态码 {resp.status} - {full_url}")
except (aiohttp.ClientError, asyncio.TimeoutError) as e:
logger.warning(f"[图片下载] 尝试 {attempt}/{MAX_RETRIES} 失败: {str(e)}")
# 指数退避等待
if attempt < MAX_RETRIES:
await asyncio.sleep(RETRY_DELAY ** attempt)
# 最终失败处理
logger.error(f"[图片下载] 终极失败 {full_url},已达最大重试次数 {MAX_RETRIES}")
return False
except KeyError:
logger.error(f"[图片下载] 致命错误:卡牌 {card_id} 不存在于card_map中")
return False
except Exception as e:
logger.error(f"{self.log_prefix} 图片下载失败: {str(e)}")
return False
def _load_config(self) -> Dict[str, Any]:
"""从同级目录的config.toml文件直接加载配置"""
try:
# 获取当前文件所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(script_dir, "config.toml")
# 读取并解析TOML配置文件
with open(config_path, 'r', encoding='utf-8') as f:
config_data = toml.load(f)
# 构建配置字典使用get方法安全访问嵌套值
config = {
"permissions": {
"admin_users": config_data.get("permissions", {}).get("admin_users", [])
},
"proxy": {
"enable_proxy": config_data.get("proxy", {}).get("enable_proxy", False),
"proxy_url": config_data.get("proxy", {}).get("proxy_url", "")
},
"cards": {
"using_cards": config_data.get("cards", {}).get("using_cards", 'bilibili'),
"use_cards": config_data.get("cards", {}).get("use_cards", ['bilibili','east'])
},
"adjustment": {
"enable_original_text": config_data.get("adjustment", {}).get("enable_original_text", False)
}
}
return config
except Exception as e:
logger.error(f"{self.log_prefix} 加载配置失败: {e}")
raise
def _validate_image_integrity(self, file_path: Path) -> bool:
"""检查图片文件完整性"""
try:
# 检查文件是否存在
if not file_path.exists():
logger.debug(f"{self.log_prefix} 图片文件不存在: {file_path}")
return False
# 检查文件大小至少要有内容不能是0字节
if file_path.stat().st_size == 0:
logger.warning(f"{self.log_prefix} 图片文件为空: {file_path}")
return False
# 尝试使用PIL打开图片来验证完整性
try:
with Image.open(file_path) as img:
# 验证图片基本信息
if img.size[0] <= 0 or img.size[1] <= 0:
logger.warning(f"{self.log_prefix} 图片尺寸异常: {file_path}")
return False
# 尝试加载图片数据以确保文件没有损坏
img.load()
logger.debug(f"{self.log_prefix} 图片完整性校验通过: {file_path}")
return True
except (Image.UnidentifiedImageError, OSError, IOError) as e:
logger.warning(f"{self.log_prefix} 图片损坏或格式错误: {file_path} - {str(e)}")
return False
except Exception as e:
logger.error(f"{self.log_prefix} 图片完整性校验异常: {file_path} - {str(e)}")
return False
def get_available_card_type(self, user_requested_type):
"""获取当前牌组支持的卡牌类型"""
supported_type = self.card_map.get("_meta", {}).get("card_types", "")
# 如果牌组支持全部,或者用户请求与牌组支持的一致,就用用户请求的
if supported_type == '全部' or user_requested_type == supported_type:
return user_requested_type
else:
# 否则用牌组支持的类型
return supported_type
def _update_available_card_sets(self):
"""更新配置文件中的可用牌组列表"""
try:
current_using = self.config["cards"].get("using_cards", "")
available_sets = self._scan_available_card_sets()
# 如果当前使用的牌组不存在于可用牌组中
if not current_using or current_using not in available_sets:
# 尝试从可用牌组中选择一个有效的
new_using = available_sets[0] if available_sets else ""
logger.warning(
f"当前使用牌组 '{current_using}' 不存在,已自动切换至 '{new_using}'"
)
# 更新当前使用牌组
self.set_card(new_using)
if available_sets:
self.set_cards(available_sets)
logger.info(f"已更新可用牌组配置: {available_sets}")
else:
logger.error("未发现任何可用牌组")
self.set_card("")
self.set_cards([])
self.config = self._load_config()
except Exception as e:
logger.error(f"更新牌组配置失败: {e}")
def _scan_available_card_sets(self) -> List[str]:
"""扫描tarot_jsons文件夹返回可用牌组列表"""
try:
tarot_jsons_dir = self.base_dir / "tarot_jsons"
available_sets = []
if not tarot_jsons_dir.exists():
logger.warning(f"tarot_jsons目录不存在: {tarot_jsons_dir}")
return []
for item in tarot_jsons_dir.iterdir():
if item.is_dir():
tarots_json_path = item / "tarots.json"
if tarots_json_path.exists():
available_sets.append(item.name)
logger.info(f"发现可用牌组: {item.name}")
return available_sets
except Exception as e:
logger.error(f"扫描牌组失败: {e}")
return []
def set_cards(self, cards: List):
"""使用tomlkit修改配置文件保持注释和格式"""
try:
config_path = os.path.join(self.base_dir, "config.toml")
# 使用tomlkit读取保持格式和注释
with open(config_path, 'r', encoding='utf-8') as f:
config_data = tomlkit.load(f)
# 只有在列表内容不同的情况下才写入
# 只有在列表内容不同的情况下才写入
if set(config_data.get("cards", {}).get("use_cards", [])) != set(cards):
config_data["cards"]["use_cards"] = cards
# 使用tomlkit写入保持格式和注释
with open(config_path, 'w', encoding='utf-8') as f:
tomlkit.dump(config_data, f)
except Exception as e:
logger.error(f"{self.log_prefix} 扫描牌组失败: {e}")
raise
def _check_cards(self, cards: str) -> bool:
"""权限检查逻辑"""
use_cards = self.config["cards"].get("use_cards", ['bilibili','east'])
if not use_cards:
logger.warning(f"{self.log_prefix} 未配置可使用牌组列表")
return ""
return cards in use_cards
def set_card(self, cards: str):
"""使用tomlkit修改配置文件保持注释和格式"""
try:
config_path = os.path.join(self.base_dir, "config.toml")
# 使用tomlkit读取保持格式和注释
with open(config_path, 'r', encoding='utf-8') as f:
config_data = tomlkit.load(f)
config_data["cards"]["using_cards"] = cards
# 使用tomlkit写入保持格式和注释
with open(config_path, 'w', encoding='utf-8') as f:
tomlkit.dump(config_data, f)
except Exception as e:
logger.error(f"{self.log_prefix} 更新配置文件失败: {e}")
raise
class TarotsCommand(BaseCommand, TarotsAction):
command_name = "tarots_command"
command_description = "塔罗牌命令,目前仅做缓存"
command_pattern = r"^/tarots\s+(?P<target_type>\w+)(?:\s+(?P<action_value>\w+))?\s*$"
command_help = "使用方法: /tarots cache - 缓存所有牌面;/tarots switch 牌组名称 - 切换当前使用的牌组"
command_examples = [
"/tarots cache - 开始缓存全部牌面",
"/tarots switch 牌组名称 - 切换当前使用的牌组"
]
enable_command = True
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 初始化 TarotsAction 的属性
self.base_dir = Path(__file__).parent.absolute()
self.config = self._load_config()
self._update_available_card_sets()
self.using_cards = self.config["cards"].get("using_cards", 'bilibili')
if not self.using_cards:
self.cache_dir = self.base_dir / "tarots_cache" / "default"
else:
self.cache_dir = self.base_dir / "tarots_cache" / self.using_cards
self.cache_dir.mkdir(parents=True, exist_ok=True)
self.card_map = {}
self.formation_map = {}
self._load_resources()
async def execute(self) -> Tuple[bool, Optional[str]]:
try:
sender = self.message.message_info.user_info
if not self._check_person_permission(sender.user_id):
await self.send_text("权限不足,你无权使用此命令")
return False,"权限不足,无权使用此命令", True
if not self.card_map:
await self.send_text("没有牌组,无法使用")
return False, "没有牌组,无法使用", True
target_type = self.matched_groups.get("target_type")
action_value = self.matched_groups.get("action_value")
support_type = self.get_available_card_type("全部")
if support_type == '全部':
check_count=[str(i) for i in range(78)]
elif support_type == '大阿卡纳':
check_count=[str(i) for i in range(22)]
elif support_type == '小阿卡纳':
check_count=[str(i) for i in range(22,78)]
else:
await self.send_text("这不在可用牌组中")
return False, "非可用牌组", True
if target_type == "cache" and not action_value:
# 添加进度提示
await self.send_text("开始缓存全部牌面,请稍候...")
success_count = 0
redownload_count = 0 # 记录重新下载的数量
for card in check_count:
try:
filename = f"{card}_norm.png"
cache_path = self.cache_dir / filename
# 检查文件是否存在且完整
if not cache_path.exists() or not self._validate_image_integrity(cache_path):
if cache_path.exists():
# 文件存在但损坏,记录重新下载
logger.warning(f"{self.log_prefix} 发现损坏的缓存文件,准备重新下载: {cache_path}")
redownload_count += 1
try:
cache_path.unlink() # 删除损坏的文件
except Exception as e:
logger.error(f"{self.log_prefix} 删除损坏文件失败: {str(e)}")
continue
# 下载图片
download_success = await self._download_image(card, cache_path)
if download_success:
success_count += 1
else:
logger.warning(f"{self.log_prefix} 下载卡牌 {card} 失败")
else:
# 文件存在且完整
success_count += 1
except Exception as e:
logger.warning(f"{self.log_prefix} 缓存卡牌 {card} 失败: {str(e)}")
continue
# 构建结果消息
result_msg = f"缓存完成,成功缓存 {success_count}/{len(check_count)} 张牌面"
if redownload_count > 0:
result_msg += f",其中重新下载了 {redownload_count} 张损坏的图片"
await self.send_text(result_msg)
return True, result_msg, True
elif target_type == "switch" and action_value:
cards = self._check_cards(action_value)
if cards:
self.set_card(action_value)
await self.send_text(f"已更换当前牌组为{action_value}")
return True, f"成功更换使用牌组至{action_value}", True
else:
await self.send_text(f"{action_value}并不在当前可用牌组里")
return False, f"{action_value}并不在当前可用牌组里", True
else:
await self.send_text("没有这种参数只能填cache或者switch哦")
return False, "没有这种参数", True
except Exception as e:
await self.send_text(f"{self.log_prefix} 命令执行错误: {e}")
logger.error(f"{self.log_prefix} 命令执行错误: {e}")
return False, f"执行失败: {str(e)}", True
def _check_person_permission(self, user_id: str) -> bool:
"""权限检查逻辑"""
admin_users = self.config["permissions"].get("admin_users", [])
if not admin_users:
logger.warning(f"{self.log_prefix} 未配置管理员用户列表")
return False
return user_id in admin_users
@register_plugin
class TarotsPlugin(BasePlugin):
"""塔罗牌插件
- 支持多种牌阵抽取
- 支持区分大小阿卡纳抽取
- 会在本地逐步缓存牌面图片
- 拥有一键缓存所有牌面的指令
- 完整的错误处理
- 日志记录和监控
"""
# 插件基本信息
plugin_name = "tarots_plugin"
enable_plugin = True
config_file_name = "config.toml"
dependencies = []
python_dependencies = []
# 配置节描述
config_section_descriptions = {
"plugin": "插件基本配置",
"components": "组件启用控制",
"proxy": "代理设置(支持热重载)",
"cards": "牌组相关设置(支持热重载)",
"adjustment": "功能微调向(支持热重载)",
"permissions": "管理者用户配置(支持热重载)",
"logging": "日志记录配置",
}
# 配置Schema定义
config_schema = {
"plugin": {
"config_version": ConfigField(type=str, default="1.3.0", description="插件配置文件版本号"),
"enabled": ConfigField(type=bool, default=True, description="是否启用插件"),
},
"components": {
"enable_tarots": ConfigField(type=bool, default=True, description="是否启用塔罗牌插件抽牌功能"),
"enable_tarots_command": ConfigField(type=bool, default=True, description="是否启用塔罗牌指令功能")
},
"proxy":{
"enable_proxy": ConfigField(type=bool, default=False, description="是否启用代理功能"),
"proxy_url": ConfigField(type=str, default="", description="请在双引号中填入你要使用的代理地址")
},
"cards":{
"using_cards": ConfigField(type=str, default='bilibili', description="塔罗牌插件使用哪套牌组"),
"use_cards": ConfigField(type=List, default=['bilibili','east'], description="塔罗牌插件可用的牌组,目前默认有'bilibili''east'两套默认牌组可选")
},
"adjustment":{
"enable_original_text": ConfigField(type=bool, default=False, description="是否启用塔罗牌原始文本,开启该功能可以额外发出初始的解牌文本")
},
"permissions": {
"admin_users": ConfigField(type=List, default=["123456789"], description="请写入被许可用户的QQ号记得用英文单引号包裹并使用逗号分隔。这个配置会决定谁被允许使用塔罗牌指令注意这个选项支持热重载你可以不重启麦麦改动会即刻生效"),
},
"logging": {
"level": ConfigField(
type=str, default="INFO", description="日志级别", choices=["DEBUG", "INFO", "WARNING", "ERROR"]
),
"prefix": ConfigField(type=str, default="[Tarots]", description="日志前缀"),
},
}
def get_plugin_components(self) -> List[Tuple[ComponentInfo, Type]]:
"""返回插件包含的组件列表"""
components = []
if self.get_config("components.enable_tarots", True):
components.append((TarotsAction.get_action_info(), TarotsAction))
if self.get_config("components.enable_tarots_command", True):
components.append((TarotsCommand.get_command_info(), TarotsCommand))
return components

View File

@@ -0,0 +1,632 @@
{
"_meta": {
"card_types": "全部",
"total_cards": 78,
"description": "B站幻星集塔罗牌组 - 包含全部牌面",
"base_url": "https://raw.githubusercontent.com/FloatTech/zbpdata/main/Tarot/"
},
"0": {
"name": "愚者",
"info": {
"description": "新的开始、冒险、自信、乐观、好的时机",
"reverseDescription": "时机不对、鲁莽、轻信、承担风险",
"imgUrl": "MajorArcana/0.png"
}
},
"1": {
"name": "魔术师",
"info": {
"description": "创造力、主见、激情、发展潜力",
"reverseDescription": "缺乏创造力、优柔寡断、才能平庸、计划不周",
"imgUrl": "MajorArcana/1.png"
}
},
"2": {
"name": "女祭司",
"info": {
"description": "潜意识、洞察力、知性、研究精神",
"reverseDescription": "自我封闭、内向、神经质、缺乏理性",
"imgUrl": "MajorArcana/2.png"
}
},
"3": {
"name": "皇后",
"info": {
"description": "母性、女性特质、生命力、接纳",
"reverseDescription": "生育问题、不安全感、敏感、困扰于细枝末节",
"imgUrl": "MajorArcana/3.png"
}
},
"4": {
"name": "皇帝",
"info": {
"description": "控制、意志、领导力、权力、影响力",
"reverseDescription": "混乱、固执、暴政、管理不善、不务实",
"imgUrl": "MajorArcana/4.png"
}
},
"5": {
"name": "教皇",
"info": {
"description": "值得信赖的、顺从、遵守规则",
"reverseDescription": "失去信赖、固步自封、质疑权威、恶意的规劝",
"imgUrl": "MajorArcana/5.png"
}
},
"6": {
"name": "恋人",
"info": {
"description": "爱、肉体的连接、新的关系、美好时光、互相支持",
"reverseDescription": "纵欲过度、不忠、违背诺言、情感的抉择",
"imgUrl": "MajorArcana/6.png"
}
},
"7": {
"name": "战车",
"info": {
"description": "高效率、把握先机、坚韧、决心、力量、克服障碍",
"reverseDescription": "失控、挫折、诉诸暴力、冲动",
"imgUrl": "MajorArcana/7.png"
}
},
"8": {
"name": "力量",
"info": {
"description": "勇气、决断、克服阻碍、胆识过人",
"reverseDescription": "恐惧、精力不足、自我怀疑、懦弱",
"imgUrl": "MajorArcana/8.png"
}
},
"9": {
"name": "隐士",
"info": {
"description": "内省、审视自我、探索内心、平静",
"reverseDescription": "孤独、孤立、过分慎重、逃避",
"imgUrl": "MajorArcana/9.png"
}
},
"10": {
"name": "命运之轮",
"info": {
"description": "把握时机、新的机会、幸运降临、即将迎来改变",
"reverseDescription": "厄运、时机未到、计划泡汤",
"imgUrl": "MajorArcana/10.png"
}
},
"11": {
"name": "正义",
"info": {
"description": "公平、正直、诚实、正义、表里如一",
"reverseDescription": "失衡、偏见、不诚实、表里不一",
"imgUrl": "MajorArcana/11.png"
}
},
"12": {
"name": "倒吊人",
"info": {
"description": "进退两难、接受考验、因祸得福、舍弃行动追求顿悟",
"reverseDescription": "无畏的牺牲、利己主义、内心抗拒、缺乏远见",
"imgUrl": "MajorArcana/12.png"
}
},
"13": {
"name": "死神",
"info": {
"description": "失去、舍弃、离别、死亡、新生事物的来临",
"reverseDescription": "起死回生、回心转意、逃避现实",
"imgUrl": "MajorArcana/13.png"
}
},
"14": {
"name": "节制",
"info": {
"description": "平衡、和谐、治愈、节制",
"reverseDescription": "失衡、失谐、沉溺愉悦、过度放纵",
"imgUrl": "MajorArcana/14.png"
}
},
"15": {
"name": "恶魔",
"info": {
"description": "负面影响、贪婪的欲望、物质主义、固执己见",
"reverseDescription": "逃离束缚、拒绝诱惑、治愈病痛、直面现实",
"imgUrl": "MajorArcana/15.png"
}
},
"16": {
"name": "塔",
"info": {
"description": "急剧的转变、突然的动荡、毁灭后的重生、政权更迭",
"reverseDescription": "悬崖勒马、害怕转变、发生内讧、风暴前的寂静",
"imgUrl": "MajorArcana/16.png"
}
},
"17": {
"name": "星辰",
"info": {
"description": "希望、前途光明、曙光出现",
"reverseDescription": "好高骛远、异想天开、事与愿违、失去目标",
"imgUrl": "MajorArcana/17.png"
}
},
"18": {
"name": "月亮",
"info": {
"description": "虚幻、不安与动摇、迷惘、欺骗",
"reverseDescription": "状况逐渐好转、疑虑渐消、排解恐惧",
"imgUrl": "MajorArcana/18.png"
}
},
"19": {
"name": "太阳",
"info": {
"description": "活力充沛、生机、远景明朗、积极",
"reverseDescription": "意志消沉、情绪低落、无助、消极",
"imgUrl": "MajorArcana/19.png"
}
},
"20": {
"name": "审判",
"info": {
"description": "命运好转、复活的喜悦、恢复健康",
"reverseDescription": "一蹶不振、尚未开始便已结束、自我怀疑、不予理睬",
"imgUrl": "MajorArcana/20.png"
}
},
"21": {
"name": "世界",
"info": {
"description": "愿望达成、获得成功、到达目的地",
"reverseDescription": "无法投入、不安现状、半途而废、盲目接受",
"imgUrl": "MajorArcana/21.png"
}
},
"22": {
"name": "圣杯ACE",
"info": {
"description": "新恋情或新友情、精神愉悦、心灵满足",
"reverseDescription": "情感缺失、缺乏交流、虚情假意",
"imgUrl": "MinorArcana/Cups/圣杯-01.png"
}
},
"23": {
"name": "圣杯2",
"info": {
"description": "和谐对等的关系、情侣间的相互喜爱、合作顺利",
"reverseDescription": "两性关系趋于极端、情感的割裂、双方不平等、冲突",
"imgUrl": "MinorArcana/Cups/圣杯-02.png"
}
},
"24": {
"name": "圣杯3",
"info": {
"description": "达成合作、努力取得成果",
"reverseDescription": "乐极生悲、无法达成共识、团队不和",
"imgUrl": "MinorArcana/Cups/圣杯-03.png"
}
},
"25": {
"name": "圣杯4",
"info": {
"description": "身心俱疲、缺乏动力、对事物缺乏兴趣、情绪低潮",
"reverseDescription": "新的人际关系、有所行动、脱离低潮期",
"imgUrl": "MinorArcana/Cups/圣杯-04.png"
}
},
"26": {
"name": "圣杯5",
"info": {
"description": "过度注意失去的事物、自责、自我怀疑、因孤傲而拒绝外界帮助",
"reverseDescription": "走出悲伤、破釜沉舟、东山再起",
"imgUrl": "MinorArcana/Cups/圣杯-05.png"
}
},
"27": {
"name": "圣杯6",
"info": {
"description": "思乡、美好的回忆、纯真的情感、简单的快乐、安全感",
"reverseDescription": "沉溺于过去、不美好的回忆、不甘受束缚",
"imgUrl": "MinorArcana/Cups/圣杯-06.png"
}
},
"28": {
"name": "圣杯7",
"info": {
"description": "不切实际的幻想、不踏实的人际关系、虚幻的情感、生活混乱",
"reverseDescription": "看清现实、对物质的不满足、做出明智的选择",
"imgUrl": "MinorArcana/Cups/圣杯-07.png"
}
},
"29": {
"name": "圣杯8",
"info": {
"description": "离开熟悉的人事物、不沉醉于目前的成果、经考虑后的行动",
"reverseDescription": "犹豫不决、失去未来的规划、维持现状",
"imgUrl": "MinorArcana/Cups/圣杯-08.png"
}
},
"30": {
"name": "圣杯9",
"info": {
"description": "愿望极有可能实现、满足现状、物质与精神富足",
"reverseDescription": "物质受损失、不懂节制、寻求更高层次的快乐",
"imgUrl": "MinorArcana/Cups/圣杯-09.png"
}
},
"31": {
"name": "圣杯10",
"info": {
"description": "团队和谐、人际关系融洽、家庭和睦",
"reverseDescription": "团队不和、人际关系不和、冲突",
"imgUrl": "MinorArcana/Cups/圣杯-10.png"
}
},
"32": {
"name": "圣杯侍从",
"info": {
"description": "情感的表达与奉献、积极的消息即将传来、情感的追求但不成熟",
"reverseDescription": "情感的追求但错误、感情暧昧、过度执着于情感或问题",
"imgUrl": "MinorArcana/Cups/圣杯侍从.png"
}
},
"33": {
"name": "圣杯国王",
"info": {
"description": "创造力、决策力、某方面的专家、有条件的分享或交换",
"reverseDescription": "表里不一、行为另有所图、对自我创造力的不信任",
"imgUrl": "MinorArcana/Cups/圣杯国王.png"
}
},
"34": {
"name": "圣杯王后",
"info": {
"description": "感情丰富而细腻、重视直觉、感性的思考",
"reverseDescription": "过度情绪化、用情不专、心灵的孤立",
"imgUrl": "MinorArcana/Cups/圣杯皇后.png"
}
},
"35": {
"name": "圣杯骑士",
"info": {
"description": "在等待与行动之间做出决定、新的机会即将到来",
"reverseDescription": "用情不专、消极的等待、对于情感的行动错误",
"imgUrl": "MinorArcana/Cups/圣杯骑士.png"
}
},
"36": {
"name": "星币ACE",
"info": {
"description": "新的机遇、顺利发展、物质回报",
"reverseDescription": "金钱上的损失、发展不顺、物质丰富但精神虚空",
"imgUrl": "MinorArcana/Pentacles/星币-01.png"
}
},
"37": {
"name": "星币2",
"info": {
"description": "收支平衡、财富的流通、生活的波动与平衡",
"reverseDescription": "用钱过度、难以维持平衡、面临物质的损失",
"imgUrl": "MinorArcana/Pentacles/星币-02.png"
}
},
"38": {
"name": "星币3",
"info": {
"description": "团队合作、沟通顺畅、工作熟练、关系稳定",
"reverseDescription": "分工不明确、人际关系不和、专业技能不足",
"imgUrl": "MinorArcana/Pentacles/星币-03.png"
}
},
"39": {
"name": "星币4",
"info": {
"description": "安于现状、吝啬、守财奴、财富停滞、精神匮乏",
"reverseDescription": "入不敷出、奢侈无度、挥霍",
"imgUrl": "MinorArcana/Pentacles/星币-04.png"
}
},
"40": {
"name": "星币5",
"info": {
"description": "经济危机、同甘共苦、艰难时刻",
"reverseDescription": "居住问题、生活混乱、劳燕分飞",
"imgUrl": "MinorArcana/Pentacles/星币-05.png"
}
},
"41": {
"name": "星币6",
"info": {
"description": "慷慨、给予、礼尚往来、财务稳定且乐观",
"reverseDescription": "自私、暗藏心机、负债或在情义上亏欠于人",
"imgUrl": "MinorArcana/Pentacles/星币-06.png"
}
},
"42": {
"name": "星币7",
"info": {
"description": "等待时机成熟、取得阶段性成果、思考计划",
"reverseDescription": "事倍功半、投资失利、踟蹰不决",
"imgUrl": "MinorArcana/Pentacles/星币-07.png"
}
},
"43": {
"name": "星币8",
"info": {
"description": "工作专注、技能娴熟、进取心、做事有条理",
"reverseDescription": "精力分散、工作乏味、工作产出不佳",
"imgUrl": "MinorArcana/Pentacles/星币-08.png"
}
},
"44": {
"name": "星币9",
"info": {
"description": "事业收获、持续为自己创造有利条件、懂得理财储蓄",
"reverseDescription": "失去财富、舍弃金钱追求生活、管理能力欠缺",
"imgUrl": "MinorArcana/Pentacles/星币-09.png"
}
},
"45": {
"name": "星币10",
"info": {
"description": "团队和谐、成功的事业伙伴、家族和谐",
"reverseDescription": "团队不和、投资合伙暂缓、家庭陷入不和",
"imgUrl": "MinorArcana/Pentacles/星币-10.png"
}
},
"46": {
"name": "星币侍从",
"info": {
"description": "善于思考和学习、求知欲旺盛、与知识或者研究工作有关的好消息",
"reverseDescription": "知识贫乏、自我认知不足、金钱上面临损失、视野狭窄",
"imgUrl": "MinorArcana/Pentacles/星币侍从.png"
}
},
"47": {
"name": "星币国王",
"info": {
"description": "成功人士、追求物质、善于经营、值得信赖、成熟务实",
"reverseDescription": "缺乏经济头脑、缺乏信任、管理不善、失去信赖",
"imgUrl": "MinorArcana/Pentacles/星币国王.png"
}
},
"48": {
"name": "星币王后",
"info": {
"description": "成熟、繁荣、值得信赖、温暖、安宁",
"reverseDescription": "爱慕虚荣、生活浮华、态度恶劣",
"imgUrl": "MinorArcana/Pentacles/星币皇后.png"
}
},
"49": {
"name": "星币骑士",
"info": {
"description": "讲究效率、责任感赖、稳重、有计划",
"reverseDescription": "懈怠、思想保守、发展停滞不前",
"imgUrl": "MinorArcana/Pentacles/星币骑士.png"
}
},
"50": {
"name": "宝剑ACE",
"info": {
"description": "有进取心和攻击性、敏锐、理性、成功的开始",
"reverseDescription": "易引起争端、逞强而招致灾难、偏激专横、不公正的想法",
"imgUrl": "MinorArcana/Swords/宝剑-01.png"
}
},
"51": {
"name": "宝剑2",
"info": {
"description": "想法的对立、选择的时机、意见不合且暗流汹涌",
"reverseDescription": "做出选择但流言与欺诈会浮出水面、犹豫不决导致错失机会",
"imgUrl": "MinorArcana/Swords/宝剑-02.png"
}
},
"52": {
"name": "宝剑3",
"info": {
"description": "感情受到伤害、生活中出现麻烦、自怜自哀",
"reverseDescription": "心理封闭、情绪不安、逃避、伤害周边的人",
"imgUrl": "MinorArcana/Swords/宝剑-03.png"
}
},
"53": {
"name": "宝剑4",
"info": {
"description": "养精蓄锐、以退为进、放缓行动、留意总结",
"reverseDescription": "即刻行动、投入生活、未充分准备却慌忙应对",
"imgUrl": "MinorArcana/Swords/宝剑-04.png"
}
},
"54": {
"name": "宝剑5",
"info": {
"description": "矛盾冲突、不择手段伤害对方、赢得比赛却失去关系",
"reverseDescription": "找到应对方法、冲突有解决的可能性、双方愿意放下武器",
"imgUrl": "MinorArcana/Swords/宝剑-05.png"
}
},
"55": {
"name": "宝剑6",
"info": {
"description": "伤口迟迟没能痊愈、现在没有很好的对策、未来存在更多的艰难",
"reverseDescription": "深陷于困难、鲁莽地解决却忽视背后更大的问题、需要其他人的帮助或救援",
"imgUrl": "MinorArcana/Swords/宝剑-06.png"
}
},
"56": {
"name": "宝剑7",
"info": {
"description": "疏忽大意、有隐藏很深的敌人、泄密、非常手段或小伎俩无法久用",
"reverseDescription": "意想不到的好运、计划不周全、掩耳盗铃",
"imgUrl": "MinorArcana/Swords/宝剑-07.png"
}
},
"57": {
"name": "宝剑8",
"info": {
"description": "孤立无助、陷入艰难处境、受困于想法导致行动受阻",
"reverseDescription": "摆脱束缚、脱离危机、重新起步",
"imgUrl": "MinorArcana/Swords/宝剑-08.png"
}
},
"58": {
"name": "宝剑9",
"info": {
"description": "精神上的恐惧、害怕、焦虑、前路不顺的预兆",
"reverseDescription": "事情出现转机、逐渐摆脱困境、沉溺于过去、正视现实",
"imgUrl": "MinorArcana/Swords/宝剑-09.png"
}
},
"59": {
"name": "宝剑10",
"info": {
"description": "进展严重受阻、无路可走、面临绝境、重新归零的机会",
"reverseDescription": "绝处逢生、东山再起的希望、物极必反",
"imgUrl": "MinorArcana/Swords/宝剑-10.png"
}
},
"60": {
"name": "宝剑侍从",
"info": {
"description": "思维发散、洞察力、谨慎的判断",
"reverseDescription": "短见、做事虎头蛇尾、对信息不加以过滤分析",
"imgUrl": "MinorArcana/Swords/宝剑侍从.png"
}
},
"61": {
"name": "宝剑国王",
"info": {
"description": "公正、权威、领导力、冷静",
"reverseDescription": "思想偏颇、强加观念、极端、不择手段",
"imgUrl": "MinorArcana/Swords/宝剑国王.png"
}
},
"62": {
"name": "宝剑王后",
"info": {
"description": "理性、思考敏捷、有距离感、公正不阿",
"reverseDescription": "固执、想法偏激、高傲、盛气凌人",
"imgUrl": "MinorArcana/Swords/宝剑皇后.png"
}
},
"63": {
"name": "宝剑骑士",
"info": {
"description": "勇往直前的行动力、充满激情",
"reverseDescription": "计划不周、天马行空、缺乏耐心、做事轻率、自负",
"imgUrl": "MinorArcana/Swords/宝剑骑士.png"
}
},
"64": {
"name": "权杖4",
"info": {
"description": "和平繁荣、关系稳固、学业或事业发展稳定",
"reverseDescription": "局势失衡、稳固的基础被打破、人际关系不佳、收成不佳",
"imgUrl": "MinorArcana/Wands/权杖-04.png"
}
},
"65": {
"name": "权杖ACE",
"info": {
"description": "新的开端、新的机遇、燃烧的激情、创造力",
"reverseDescription": "新行动失败的可能性比较大、开端不佳、意志力薄弱",
"imgUrl": "MinorArcana/Wands/权杖-01.png"
}
},
"66": {
"name": "权杖2",
"info": {
"description": "高瞻远瞩、规划未来、在习惯与希望间做选择",
"reverseDescription": "犹豫不决、行动受阻、花费太多时间在选择上",
"imgUrl": "MinorArcana/Wands/权杖-02.png"
}
},
"67": {
"name": "权杖3",
"info": {
"description": "探索的好时机、身心灵的契合、领导能力、主导地位",
"reverseDescription": "合作不顺、欠缺领导能力、团队不和谐",
"imgUrl": "MinorArcana/Wands/权杖-03.png"
}
},
"68": {
"name": "权杖5",
"info": {
"description": "竞争、冲突、内心的矛盾、缺乏共识",
"reverseDescription": "不公平的竞争、达成共识",
"imgUrl": "MinorArcana/Wands/权杖-05.png"
}
},
"69": {
"name": "权杖6",
"info": {
"description": "获得胜利、成功得到回报、进展顺利、有望水到渠成",
"reverseDescription": "短暂的成功、骄傲自满、失去自信",
"imgUrl": "MinorArcana/Wands/权杖-06.png"
}
},
"70": {
"name": "权杖7",
"info": {
"description": "坚定信念、态度坚定、内芯的权衡与决断、相信自己的观点与能力",
"reverseDescription": "对自己的能力产生怀疑、缺乏自信与动力、缺乏意志力",
"imgUrl": "MinorArcana/Wands/权杖-07.png"
}
},
"71": {
"name": "权杖8",
"info": {
"description": "目标明确、一鼓作气、进展神速、趁热打铁、旅行",
"reverseDescription": "方向错误、行动不一致、急躁冲动、计划延误",
"imgUrl": "MinorArcana/Wands/权杖-08.png"
}
},
"72": {
"name": "权杖9",
"info": {
"description": "做好准备以应对困难、自我防御、蓄势待发、力量的对立",
"reverseDescription": "遭遇逆境、失去自信、士气低落",
"imgUrl": "MinorArcana/Wands/权杖-09.png"
}
},
"73": {
"name": "权杖10",
"info": {
"description": "责任感、内芯的热忱、过重的负担、过度劳累",
"reverseDescription": "难以承受的压力、高估自身的能力、调整自己的步调、逃避责任",
"imgUrl": "MinorArcana/Wands/权杖-10.png"
}
},
"74": {
"name": "权杖侍从",
"info": {
"description": "新计划的开始、尝试新事物、好消息传来",
"reverseDescription": "三分钟热度、规划太久导致进展不顺、坏消息传来",
"imgUrl": "MinorArcana/Wands/权杖侍从.png"
}
},
"75": {
"name": "权杖国王",
"info": {
"description": "行动力强、态度明确、运筹帷幄、领袖魅力",
"reverseDescription": "独断专行、严苛、态度傲慢",
"imgUrl": "MinorArcana/Wands/权杖国王.png"
}
},
"76": {
"name": "权杖王后",
"info": {
"description": "刚柔并济、热情而温和、乐观而活泼",
"reverseDescription": "情绪化、信心不足、热情消退、孤独",
"imgUrl": "MinorArcana/Wands/权杖皇后.png"
}
},
"77": {
"name": "权杖骑士",
"info": {
"description": "行动力、精力充沛、新的旅程、对现状不满足的改变",
"reverseDescription": "有勇无谋、鲁莽、行动延迟、计划不周、急躁",
"imgUrl": "MinorArcana/Wands/权杖骑士.png"
}
}
}

View File

@@ -0,0 +1,632 @@
{
"_meta": {
"card_types": "全部",
"total_cards": 78,
"description": "经典塔罗牌组 - 包含全部牌面",
"base_url": "https://raw.githubusercontent.com/lambiengcode/flutter-tarot-card/master/images/"
},
"0": {
"name": "愚者",
"info": {
"description": "新的开始、冒险、自信、乐观、好的时机",
"reverseDescription": "时机不对、鲁莽、轻信、承担风险",
"imgUrl": "m00.jpg"
}
},
"1": {
"name": "魔术师",
"info": {
"description": "创造力、主见、激情、发展潜力",
"reverseDescription": "缺乏创造力、优柔寡断、才能平庸、计划不周",
"imgUrl": "m01.jpg"
}
},
"2": {
"name": "女祭司",
"info": {
"description": "潜意识、洞察力、知性、研究精神",
"reverseDescription": "自我封闭、内向、神经质、缺乏理性",
"imgUrl": "m02.jpg"
}
},
"3": {
"name": "皇后",
"info": {
"description": "母性、女性特质、生命力、接纳",
"reverseDescription": "生育问题、不安全感、敏感、困扰于细枝末节",
"imgUrl": "m03.jpg"
}
},
"4": {
"name": "皇帝",
"info": {
"description": "控制、意志、领导力、权力、影响力",
"reverseDescription": "混乱、固执、暴政、管理不善、不务实",
"imgUrl": "m04.jpg"
}
},
"5": {
"name": "教皇",
"info": {
"description": "值得信赖的、顺从、遵守规则",
"reverseDescription": "失去信赖、固步自封、质疑权威、恶意的规劝",
"imgUrl": "m05.jpg"
}
},
"6": {
"name": "恋人",
"info": {
"description": "爱、肉体的连接、新的关系、美好时光、互相支持",
"reverseDescription": "纵欲过度、不忠、违背诺言、情感的抉择",
"imgUrl": "m06.jpg"
}
},
"7": {
"name": "战车",
"info": {
"description": "高效率、把握先机、坚韧、决心、力量、克服障碍",
"reverseDescription": "失控、挫折、诉诸暴力、冲动",
"imgUrl": "m07.jpg"
}
},
"8": {
"name": "力量",
"info": {
"description": "勇气、决断、克服阻碍、胆识过人",
"reverseDescription": "恐惧、精力不足、自我怀疑、懦弱",
"imgUrl": "m08.jpg"
}
},
"9": {
"name": "隐士",
"info": {
"description": "内省、审视自我、探索内心、平静",
"reverseDescription": "孤独、孤立、过分慎重、逃避",
"imgUrl": "m09.jpg"
}
},
"10": {
"name": "命运之轮",
"info": {
"description": "把握时机、新的机会、幸运降临、即将迎来改变",
"reverseDescription": "厄运、时机未到、计划泡汤",
"imgUrl": "m10.jpg"
}
},
"11": {
"name": "正义",
"info": {
"description": "公平、正直、诚实、正义、表里如一",
"reverseDescription": "失衡、偏见、不诚实、表里不一",
"imgUrl": "m11.jpg"
}
},
"12": {
"name": "倒吊人",
"info": {
"description": "进退两难、接受考验、因祸得福、舍弃行动追求顿悟",
"reverseDescription": "无畏的牺牲、利己主义、内心抗拒、缺乏远见",
"imgUrl": "m12.jpg"
}
},
"13": {
"name": "死神",
"info": {
"description": "失去、舍弃、离别、死亡、新生事物的来临",
"reverseDescription": "起死回生、回心转意、逃避现实",
"imgUrl": "m13.jpg"
}
},
"14": {
"name": "节制",
"info": {
"description": "平衡、和谐、治愈、节制",
"reverseDescription": "失衡、失谐、沉溺愉悦、过度放纵",
"imgUrl": "m14.jpg"
}
},
"15": {
"name": "恶魔",
"info": {
"description": "负面影响、贪婪的欲望、物质主义、固执己见",
"reverseDescription": "逃离束缚、拒绝诱惑、治愈病痛、直面现实",
"imgUrl": "m15.jpg"
}
},
"16": {
"name": "塔",
"info": {
"description": "急剧的转变、突然的动荡、毁灭后的重生、政权更迭",
"reverseDescription": "悬崖勒马、害怕转变、发生内讧、风暴前的寂静",
"imgUrl": "m16.jpg"
}
},
"17": {
"name": "星辰",
"info": {
"description": "希望、前途光明、曙光出现",
"reverseDescription": "好高骛远、异想天开、事与愿违、失去目标",
"imgUrl": "m17.jpg"
}
},
"18": {
"name": "月亮",
"info": {
"description": "虚幻、不安与动摇、迷惘、欺骗",
"reverseDescription": "状况逐渐好转、疑虑渐消、排解恐惧",
"imgUrl": "m18.jpg"
}
},
"19": {
"name": "太阳",
"info": {
"description": "活力充沛、生机、远景明朗、积极",
"reverseDescription": "意志消沉、情绪低落、无助、消极",
"imgUrl": "m19.jpg"
}
},
"20": {
"name": "审判",
"info": {
"description": "命运好转、复活的喜悦、恢复健康",
"reverseDescription": "一蹶不振、尚未开始便已结束、自我怀疑、不予理睬",
"imgUrl": "m20.jpg"
}
},
"21": {
"name": "世界",
"info": {
"description": "愿望达成、获得成功、到达目的地",
"reverseDescription": "无法投入、不安现状、半途而废、盲目接受",
"imgUrl": "m21.jpg"
}
},
"22": {
"name": "圣杯ACE",
"info": {
"description": "新恋情或新友情、精神愉悦、心灵满足",
"reverseDescription": "情感缺失、缺乏交流、虚情假意",
"imgUrl": "c01.jpg"
}
},
"23": {
"name": "圣杯2",
"info": {
"description": "和谐对等的关系、情侣间的相互喜爱、合作顺利",
"reverseDescription": "两性关系趋于极端、情感的割裂、双方不平等、冲突",
"imgUrl": "c02.jpg"
}
},
"24": {
"name": "圣杯3",
"info": {
"description": "达成合作、努力取得成果",
"reverseDescription": "乐极生悲、无法达成共识、团队不和",
"imgUrl": "c03.jpg"
}
},
"25": {
"name": "圣杯4",
"info": {
"description": "身心俱疲、缺乏动力、对事物缺乏兴趣、情绪低潮",
"reverseDescription": "新的人际关系、有所行动、脱离低潮期",
"imgUrl": "c04.jpg"
}
},
"26": {
"name": "圣杯5",
"info": {
"description": "过度注意失去的事物、自责、自我怀疑、因孤傲而拒绝外界帮助",
"reverseDescription": "走出悲伤、破釜沉舟、东山再起",
"imgUrl": "c05.jpg"
}
},
"27": {
"name": "圣杯6",
"info": {
"description": "思乡、美好的回忆、纯真的情感、简单的快乐、安全感",
"reverseDescription": "沉溺于过去、不美好的回忆、不甘受束缚",
"imgUrl": "c06.jpg"
}
},
"28": {
"name": "圣杯7",
"info": {
"description": "不切实际的幻想、不踏实的人际关系、虚幻的情感、生活混乱",
"reverseDescription": "看清现实、对物质的不满足、做出明智的选择",
"imgUrl": "c07.jpg"
}
},
"29": {
"name": "圣杯8",
"info": {
"description": "离开熟悉的人事物、不沉醉于目前的成果、经考虑后的行动",
"reverseDescription": "犹豫不决、失去未来的规划、维持现状",
"imgUrl": "c08.jpg"
}
},
"30": {
"name": "圣杯9",
"info": {
"description": "愿望极有可能实现、满足现状、物质与精神富足",
"reverseDescription": "物质受损失、不懂节制、寻求更高层次的快乐",
"imgUrl": "c09.jpg"
}
},
"31": {
"name": "圣杯10",
"info": {
"description": "团队和谐、人际关系融洽、家庭和睦",
"reverseDescription": "团队不和、人际关系不和、冲突",
"imgUrl": "c10.jpg"
}
},
"32": {
"name": "圣杯侍从",
"info": {
"description": "情感的表达与奉献、积极的消息即将传来、情感的追求但不成熟",
"reverseDescription": "情感的追求但错误、感情暧昧、过度执着于情感或问题",
"imgUrl": "c11.jpg"
}
},
"33": {
"name": "圣杯骑士",
"info": {
"description": "在等待与行动之间做出决定、新的机会即将到来",
"reverseDescription": "用情不专、消极的等待、对于情感的行动错误",
"imgUrl": "c12.jpg"
}
},
"34": {
"name": "圣杯王后",
"info": {
"description": "感情丰富而细腻、重视直觉、感性的思考",
"reverseDescription": "过度情绪化、用情不专、心灵的孤立",
"imgUrl": "c13.jpg"
}
},
"35": {
"name": "圣杯国王",
"info": {
"description": "创造力、决策力、某方面的专家、有条件的分享或交换",
"reverseDescription": "表里不一、行为另有所图、对自我创造力的不信任",
"imgUrl": "c14.jpg"
}
},
"36": {
"name": "星币ACE",
"info": {
"description": "新的机遇、顺利发展、物质回报",
"reverseDescription": "金钱上的损失、发展不顺、物质丰富但精神虚空",
"imgUrl": "p01.jpg"
}
},
"37": {
"name": "星币2",
"info": {
"description": "收支平衡、财富的流通、生活的波动与平衡",
"reverseDescription": "用钱过度、难以维持平衡、面临物质的损失",
"imgUrl": "p02.jpg"
}
},
"38": {
"name": "星币3",
"info": {
"description": "团队合作、沟通顺畅、工作熟练、关系稳定",
"reverseDescription": "分工不明确、人际关系不和、专业技能不足",
"imgUrl": "p03.jpg"
}
},
"39": {
"name": "星币4",
"info": {
"description": "安于现状、吝啬、守财奴、财富停滞、精神匮乏",
"reverseDescription": "入不敷出、奢侈无度、挥霍",
"imgUrl": "p04.jpg"
}
},
"40": {
"name": "星币5",
"info": {
"description": "经济危机、同甘共苦、艰难时刻",
"reverseDescription": "居住问题、生活混乱、劳燕分飞",
"imgUrl": "p05.jpg"
}
},
"41": {
"name": "星币6",
"info": {
"description": "慷慨、给予、礼尚往来、财务稳定且乐观",
"reverseDescription": "自私、暗藏心机、负债或在情义上亏欠于人",
"imgUrl": "p06.jpg"
}
},
"42": {
"name": "星币7",
"info": {
"description": "等待时机成熟、取得阶段性成果、思考计划",
"reverseDescription": "事倍功半、投资失利、踟蹰不决",
"imgUrl": "p07.jpg"
}
},
"43": {
"name": "星币8",
"info": {
"description": "工作专注、技能娴熟、进取心、做事有条理",
"reverseDescription": "精力分散、工作乏味、工作产出不佳",
"imgUrl": "p08.jpg"
}
},
"44": {
"name": "星币9",
"info": {
"description": "事业收获、持续为自己创造有利条件、懂得理财储蓄",
"reverseDescription": "失去财富、舍弃金钱追求生活、管理能力欠缺",
"imgUrl": "p09.jpg"
}
},
"45": {
"name": "星币10",
"info": {
"description": "团队和谐、成功的事业伙伴、家族和谐",
"reverseDescription": "团队不和、投资合伙暂缓、家庭陷入不和",
"imgUrl": "p10.jpg"
}
},
"46": {
"name": "星币侍从",
"info": {
"description": "善于思考和学习、求知欲旺盛、与知识或者研究工作有关的好消息",
"reverseDescription": "知识贫乏、自我认知不足、金钱上面临损失、视野狭窄",
"imgUrl": "p11.jpg"
}
},
"47": {
"name": "星币骑士",
"info": {
"description": "讲究效率、责任感赖、稳重、有计划",
"reverseDescription": "懈怠、思想保守、发展停滞不前",
"imgUrl": "p12.jpg"
}
},
"48": {
"name": "星币王后",
"info": {
"description": "成熟、繁荣、值得信赖、温暖、安宁",
"reverseDescription": "爱慕虚荣、生活浮华、态度恶劣",
"imgUrl": "p13.jpg"
}
},
"49": {
"name": "星币国王",
"info": {
"description": "成功人士、追求物质、善于经营、值得信赖、成熟务实",
"reverseDescription": "缺乏经济头脑、缺乏信任、管理不善、失去信赖",
"imgUrl": "p14.jpg"
}
},
"50": {
"name": "宝剑ACE",
"info": {
"description": "有进取心和攻击性、敏锐、理性、成功的开始",
"reverseDescription": "易引起争端、逞强而招致灾难、偏激专横、不公正的想法",
"imgUrl": "s01.jpg"
}
},
"51": {
"name": "宝剑2",
"info": {
"description": "想法的对立、选择的时机、意见不合且暗流汹涌",
"reverseDescription": "做出选择但流言与欺诈会浮出水面、犹豫不决导致错失机会",
"imgUrl": "s02.jpg"
}
},
"52": {
"name": "宝剑3",
"info": {
"description": "感情受到伤害、生活中出现麻烦、自怜自哀",
"reverseDescription": "心理封闭、情绪不安、逃避、伤害周边的人",
"imgUrl": "s03.jpg"
}
},
"53": {
"name": "宝剑4",
"info": {
"description": "养精蓄锐、以退为进、放缓行动、留意总结",
"reverseDescription": "即刻行动、投入生活、未充分准备却慌忙应对",
"imgUrl": "s04.jpg"
}
},
"54": {
"name": "宝剑5",
"info": {
"description": "矛盾冲突、不择手段伤害对方、赢得比赛却失去关系",
"reverseDescription": "找到应对方法、冲突有解决的可能性、双方愿意放下武器",
"imgUrl": "s05.jpg"
}
},
"55": {
"name": "宝剑6",
"info": {
"description": "伤口迟迟没能痊愈、现在没有很好的对策、未来存在更多的艰难",
"reverseDescription": "深陷于困难、鲁莽地解决却忽视背后更大的问题、需要其他人的帮助或救援",
"imgUrl": "s06.jpg"
}
},
"56": {
"name": "宝剑7",
"info": {
"description": "疏忽大意、有隐藏很深的敌人、泄密、非常手段或小伎俩无法久用",
"reverseDescription": "意想不到的好运、计划不周全、掩耳盗铃",
"imgUrl": "s07.jpg"
}
},
"57": {
"name": "宝剑8",
"info": {
"description": "孤立无助、陷入艰难处境、受困于想法导致行动受阻",
"reverseDescription": "摆脱束缚、脱离危机、重新起步",
"imgUrl": "s08.jpg"
}
},
"58": {
"name": "宝剑9",
"info": {
"description": "精神上的恐惧、害怕、焦虑、前路不顺的预兆",
"reverseDescription": "事情出现转机、逐渐摆脱困境、沉溺于过去、正视现实",
"imgUrl": "s09.jpg"
}
},
"59": {
"name": "宝剑10",
"info": {
"description": "进展严重受阻、无路可走、面临绝境、重新归零的机会",
"reverseDescription": "绝处逢生、东山再起的希望、物极必反",
"imgUrl": "s10.jpg"
}
},
"60": {
"name": "宝剑侍从",
"info": {
"description": "思维发散、洞察力、谨慎的判断",
"reverseDescription": "短见、做事虎头蛇尾、对信息不加以过滤分析",
"imgUrl": "s11.jpg"
}
},
"61": {
"name": "宝剑骑士",
"info": {
"description": "勇往直前的行动力、充满激情",
"reverseDescription": "计划不周、天马行空、缺乏耐心、做事轻率、自负",
"imgUrl": "s12.jpg"
}
},
"62": {
"name": "宝剑王后",
"info": {
"description": "理性、思考敏捷、有距离感、公正不阿",
"reverseDescription": "固执、想法偏激、高傲、盛气凌人",
"imgUrl": "s13.jpg"
}
},
"63": {
"name": "宝剑国王",
"info": {
"description": "公正、权威、领导力、冷静",
"reverseDescription": "思想偏颇、强加观念、极端、不择手段",
"imgUrl": "s14.jpg"
}
},
"64": {
"name": "权杖ACE",
"info": {
"description": "新的开端、新的机遇、燃烧的激情、创造力",
"reverseDescription": "新行动失败的可能性比较大、开端不佳、意志力薄弱",
"imgUrl": "w01.jpg"
}
},
"65": {
"name": "权杖2",
"info": {
"description": "高瞻远瞩、规划未来、在习惯与希望间做选择",
"reverseDescription": "犹豫不决、行动受阻、花费太多时间在选择上",
"imgUrl": "w02.jpg"
}
},
"66": {
"name": "权杖3",
"info": {
"description": "探索的好时机、身心灵的契合、领导能力、主导地位",
"reverseDescription": "合作不顺、欠缺领导能力、团队不和谐",
"imgUrl": "w03.jpg"
}
},
"67": {
"name": "权杖4",
"info": {
"description": "和平繁荣、关系稳固、学业或事业发展稳定",
"reverseDescription": "局势失衡、稳固的基础被打破、人际关系不佳、收成不佳",
"imgUrl": "w04.jpg"
}
},
"68": {
"name": "权杖5",
"info": {
"description": "竞争、冲突、内心的矛盾、缺乏共识",
"reverseDescription": "不公平的竞争、达成共识",
"imgUrl": "w05.jpg"
}
},
"69": {
"name": "权杖6",
"info": {
"description": "获得胜利、成功得到回报、进展顺利、有望水到渠成",
"reverseDescription": "短暂的成功、骄傲自满、失去自信",
"imgUrl": "w06.jpg"
}
},
"70": {
"name": "权杖7",
"info": {
"description": "坚定信念、态度坚定、内芯的权衡与决断、相信自己的观点与能力",
"reverseDescription": "对自己的能力产生怀疑、缺乏自信与动力、缺乏意志力",
"imgUrl": "w07.jpg"
}
},
"71": {
"name": "权杖8",
"info": {
"description": "目标明确、一鼓作气、进展神速、趁热打铁、旅行",
"reverseDescription": "方向错误、行动不一致、急躁冲动、计划延误",
"imgUrl": "w08.jpg"
}
},
"72": {
"name": "权杖9",
"info": {
"description": "做好准备以应对困难、自我防御、蓄势待发、力量的对立",
"reverseDescription": "遭遇逆境、失去自信、士气低落",
"imgUrl": "w09.jpg"
}
},
"73": {
"name": "权杖10",
"info": {
"description": "责任感、内芯的热忱、过重的负担、过度劳累",
"reverseDescription": "难以承受的压力、高估自身的能力、调整自己的步调、逃避责任",
"imgUrl": "w10.jpg"
}
},
"74": {
"name": "权杖侍从",
"info": {
"description": "新计划的开始、尝试新事物、好消息传来",
"reverseDescription": "三分钟热度、规划太久导致进展不顺、坏消息传来",
"imgUrl": "w11.jpg"
}
},
"75": {
"name": "权杖骑士",
"info": {
"description": "行动力、精力充沛、新的旅程、对现状不满足的改变",
"reverseDescription": "有勇无谋、鲁莽、行动延迟、计划不周、急躁",
"imgUrl": "w12.jpg"
}
},
"76": {
"name": "权杖王后",
"info": {
"description": "刚柔并济、热情而温和、乐观而活泼",
"reverseDescription": "情绪化、信心不足、热情消退、孤独",
"imgUrl": "w13.jpg"
}
},
"77": {
"name": "权杖国王",
"info": {
"description": "行动力强、态度明确、运筹帷幄、领袖魅力",
"reverseDescription": "独断专行、严苛、态度傲慢",
"imgUrl": "w14.jpg"
}
}
}

View File

@@ -0,0 +1,184 @@
{
"_meta": {
"card_types": "大阿卡纳",
"total_cards": 22,
"description": "东方塔罗牌组 - 仅包含大阿卡纳",
"base_url": "https://raw.githubusercontent.com/MinatoAquaCrews/nonebot_plugin_tarot/master/nonebot_plugin_tarot/resource/TouhouTarot/"
},
"0": {
"name": "愚者",
"info": {
"description": "新的开始、冒险、自信、乐观、好的时机",
"reverseDescription": "时机不对、鲁莽、轻信、承担风险",
"imgUrl": "MajorArcana/0-愚者.jpg"
}
},
"1": {
"name": "魔术师",
"info": {
"description": "创造力、主见、激情、发展潜力",
"reverseDescription": "缺乏创造力、优柔寡断、才能平庸、计划不周",
"imgUrl": "MajorArcana/01-魔术师.jpg"
}
},
"2": {
"name": "女祭司",
"info": {
"description": "潜意识、洞察力、知性、研究精神",
"reverseDescription": "自我封闭、内向、神经质、缺乏理性",
"imgUrl": "MajorArcana/02-女祭司.jpg"
}
},
"3": {
"name": "皇后",
"info": {
"description": "母性、女性特质、生命力、接纳",
"reverseDescription": "生育问题、不安全感、敏感、困扰于细枝末节",
"imgUrl": "MajorArcana/03-女皇.jpg"
}
},
"4": {
"name": "皇帝",
"info": {
"description": "控制、意志、领导力、权力、影响力",
"reverseDescription": "混乱、固执、暴政、管理不善、不务实",
"imgUrl": "MajorArcana/04-皇帝.jpg"
}
},
"5": {
"name": "教皇",
"info": {
"description": "值得信赖的、顺从、遵守规则",
"reverseDescription": "失去信赖、固步自封、质疑权威、恶意的规劝",
"imgUrl": "MajorArcana/05-教皇.jpg"
}
},
"6": {
"name": "恋人",
"info": {
"description": "爱、肉体的连接、新的关系、美好时光、互相支持",
"reverseDescription": "纵欲过度、不忠、违背诺言、情感的抉择",
"imgUrl": "MajorArcana/06-恋人.jpg"
}
},
"7": {
"name": "战车",
"info": {
"description": "高效率、把握先机、坚韧、决心、力量、克服障碍",
"reverseDescription": "失控、挫折、诉诸暴力、冲动",
"imgUrl": "MajorArcana/07-战车.jpg"
}
},
"8": {
"name": "力量",
"info": {
"description": "勇气、决断、克服阻碍、胆识过人",
"reverseDescription": "恐惧、精力不足、自我怀疑、懦弱",
"imgUrl": "MajorArcana/08-力量.jpg"
}
},
"9": {
"name": "隐士",
"info": {
"description": "内省、审视自我、探索内心、平静",
"reverseDescription": "孤独、孤立、过分慎重、逃避",
"imgUrl": "MajorArcana/09-隐士.jpg"
}
},
"10": {
"name": "命运之轮",
"info": {
"description": "把握时机、新的机会、幸运降临、即将迎来改变",
"reverseDescription": "厄运、时机未到、计划泡汤",
"imgUrl": "MajorArcana/10-命运之轮.jpg"
}
},
"11": {
"name": "正义",
"info": {
"description": "公平、正直、诚实、正义、表里如一",
"reverseDescription": "失衡、偏见、不诚实、表里不一",
"imgUrl": "MajorArcana/11-正义.jpg"
}
},
"12": {
"name": "倒吊人",
"info": {
"description": "进退两难、接受考验、因祸得福、舍弃行动追求顿悟",
"reverseDescription": "无畏的牺牲、利己主义、内心抗拒、缺乏远见",
"imgUrl": "MajorArcana/12-倒吊人.jpg"
}
},
"13": {
"name": "死神",
"info": {
"description": "失去、舍弃、离别、死亡、新生事物的来临",
"reverseDescription": "起死回生、回心转意、逃避现实",
"imgUrl": "MajorArcana/13-死神.jpg"
}
},
"14": {
"name": "节制",
"info": {
"description": "平衡、和谐、治愈、节制",
"reverseDescription": "失衡、失谐、沉溺愉悦、过度放纵",
"imgUrl": "MajorArcana/14-节制.jpg"
}
},
"15": {
"name": "恶魔",
"info": {
"description": "负面影响、贪婪的欲望、物质主义、固执己见",
"reverseDescription": "逃离束缚、拒绝诱惑、治愈病痛、直面现实",
"imgUrl": "MajorArcana/15-恶魔.jpg"
}
},
"16": {
"name": "塔",
"info": {
"description": "急剧的转变、突然的动荡、毁灭后的重生、政权更迭",
"reverseDescription": "悬崖勒马、害怕转变、发生内讧、风暴前的寂静",
"imgUrl": "MajorArcana/16-高塔.jpg"
}
},
"17": {
"name": "星辰",
"info": {
"description": "希望、前途光明、曙光出现",
"reverseDescription": "好高骛远、异想天开、事与愿违、失去目标",
"imgUrl": "MajorArcana/17-星星.jpg"
}
},
"18": {
"name": "月亮",
"info": {
"description": "虚幻、不安与动摇、迷惘、欺骗",
"reverseDescription": "状况逐渐好转、疑虑渐消、排解恐惧",
"imgUrl": "MajorArcana/18-月亮.jpg"
}
},
"19": {
"name": "太阳",
"info": {
"description": "活力充沛、生机、远景明朗、积极",
"reverseDescription": "意志消沉、情绪低落、无助、消极",
"imgUrl": "MajorArcana/19-太阳.jpg"
}
},
"20": {
"name": "审判",
"info": {
"description": "命运好转、复活的喜悦、恢复健康",
"reverseDescription": "一蹶不振、尚未开始便已结束、自我怀疑、不予理睬",
"imgUrl": "MajorArcana/20-审判.jpg"
}
},
"21": {
"name": "世界",
"info": {
"description": "愿望达成、获得成功、到达目的地",
"reverseDescription": "无法投入、不安现状、半途而废、盲目接受",
"imgUrl": "MajorArcana/21-世界.jpg"
}
}
}

View File

@@ -0,0 +1,58 @@
{
"单张": {
"cards_num": 1,
"is_cut": true,
"represent": [
["现状"]
]
},
"圣三角": {
"cards_num": 3,
"is_cut": false,
"represent": [
["现状", "愿望", "行动"]
]
},
"时间之流": {
"cards_num": 3,
"is_cut": true,
"represent": [
["过去", "现在", "未来", "问卜者的主观想法"]
]
},
"四要素": {
"cards_num": 4,
"is_cut": false,
"represent": [
["火,象征行动,行动上的建议", "气,象征言语,言语上的对策", "水,象征感情,感情上的态度", "土,象征物质,物质上的准备"]
]
},
"五牌阵": {
"cards_num": 5,
"is_cut": true,
"represent": [
["现在或主要问题", "过去的影响", "未来", "主要原因", "行动可能带来的结果"]
]
},
"吉普赛十字": {
"cards_num": 5,
"is_cut": false,
"represent": [
["对方的想法", "你的想法", "相处中存在的问题", "二人目前的环境", "关系发展的结果"]
]
},
"马蹄": {
"cards_num": 6,
"is_cut": true,
"represent": [
["现状", "可预知的情况", "不可预知的情况", "即将发生的", "结果", "问卜者的主观想法"]
]
},
"六芒星": {
"cards_num": 7,
"is_cut": true,
"represent": [
["过去", "现在", "未来", "对策", "环境", "态度", "预测结果"]
]
}
}