435 lines
13 KiB
Python
435 lines
13 KiB
Python
"""Ownership map for Kernel commands and reviewed local extensions."""
|
||
|
||
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
|
||
|
||
LOCAL_COMMAND_ALIASES = {
|
||
"功能列表": "feature_list",
|
||
"帮助": "feature_list",
|
||
"help": "feature_list",
|
||
"丢骰子": "dice",
|
||
"骰子": "dice",
|
||
"丢骰子挑战": "dice_challenge",
|
||
"骰子挑战": "dice_challenge",
|
||
"翻硬币": "coin",
|
||
"随机数": "random_number",
|
||
"抽签": "draw_lot",
|
||
"今日运势": "daily_fortune",
|
||
"猜数字": "guess_number",
|
||
"猜": "guess_number",
|
||
"石头剪刀布": "rps",
|
||
"记住": "remember",
|
||
"我的记忆": "my_memory",
|
||
"忘记": "forget_memory",
|
||
"人物记忆": "person_memory",
|
||
"记忆帮助": "memory_help",
|
||
"扫码排行": "scan_ranking",
|
||
"扫码榜": "scan_ranking",
|
||
"今日扫码": "scan_ranking",
|
||
"复读榜": "repeat_ranking",
|
||
"复读": "repeat_ranking",
|
||
"查记录": "history_search",
|
||
"历史搜索": "history_search",
|
||
"状态": "local_status",
|
||
"status": "server_status",
|
||
"版本": "jwebot_version",
|
||
"version": "jwebot_version",
|
||
"debug": "telemetry_debug",
|
||
"余额": "deepseek_balance",
|
||
"steam": "steam_friends",
|
||
"上下文": "context_summary",
|
||
"context": "context_summary",
|
||
"摩拉": "wallet",
|
||
"金币": "wallet",
|
||
"wallet": "wallet",
|
||
"摩拉排行": "coin_ranking",
|
||
"摩拉排行榜": "coin_ranking",
|
||
"金币排行": "coin_ranking",
|
||
"金币排行榜": "coin_ranking",
|
||
"大富翁榜": "coin_ranking",
|
||
"richlist": "coin_ranking",
|
||
"Taffy摩拉": "taffy_coins",
|
||
"Taffy金币": "taffy_coins",
|
||
"taffycoins": "taffy_coins",
|
||
"原石": "wallet",
|
||
"原石祈愿": "primogem_wish",
|
||
"祈愿": "primogem_wish",
|
||
"wish": "primogem_wish",
|
||
"原石榜": "primogem_ranking",
|
||
"primogem榜": "primogem_ranking",
|
||
"扫码加权": "scan_boost",
|
||
"扫码概率": "scan_boost",
|
||
"Taffy发话": "taffy_say",
|
||
"taffysay": "taffy_say",
|
||
"回答": "trivia_answer",
|
||
"answer": "trivia_answer",
|
||
"转账": "transfer",
|
||
"transfer": "transfer",
|
||
"贷款": "loan",
|
||
"借款": "loan",
|
||
"loan": "loan",
|
||
"borrow": "loan",
|
||
"还款": "repay",
|
||
"repay": "repay",
|
||
"抽奖": "prize_draw",
|
||
"draw": "prize_draw",
|
||
"彩票": "lottery",
|
||
"买彩票": "lottery",
|
||
"lottery": "lottery",
|
||
"21点": "blackjack",
|
||
"二十一点": "blackjack",
|
||
"blackjack": "blackjack",
|
||
"游戏记录": "game_history",
|
||
"个人记录": "game_history",
|
||
"gamehistory": "game_history",
|
||
"游戏帮助": "game_rules",
|
||
"games": "game_rules",
|
||
"人物列表": "person_directory",
|
||
"别名列表": "person_directory",
|
||
"people": "person_directory",
|
||
"人物": "person_info",
|
||
"个人属性": "person_info",
|
||
"person": "person_info",
|
||
"自走棋": "cs_autochess",
|
||
"cs自走棋": "cs_autochess",
|
||
"autochess": "cs_autochess",
|
||
"选": "cs_autochess",
|
||
"刷新": "cs_autochess",
|
||
"锁定": "cs_autochess",
|
||
"战术": "cs_autochess",
|
||
"升级教练": "cs_autochess",
|
||
"上阵": "cs_autochess",
|
||
"下阵": "cs_autochess",
|
||
"出售": "cs_autochess",
|
||
"阵容": "cs_autochess",
|
||
"赛程": "cs_autochess",
|
||
"结束回合": "cs_autochess",
|
||
}
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class LocalExtensionDescriptor:
|
||
extension_id: str
|
||
author: str
|
||
description: str
|
||
help_entries: tuple[str, ...]
|
||
command_kinds: tuple[str, ...]
|
||
|
||
@property
|
||
def directory(self) -> str:
|
||
return self.author.casefold()
|
||
|
||
@property
|
||
def commands(self) -> tuple[str, ...]:
|
||
owned = set(self.command_kinds)
|
||
return tuple(
|
||
f"/{alias}"
|
||
for alias, kind in LOCAL_COMMAND_ALIASES.items()
|
||
if kind in owned
|
||
)
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class KernelCommandDescriptor:
|
||
description: str
|
||
help_entries: tuple[str, ...]
|
||
command_kinds: tuple[str, ...]
|
||
|
||
|
||
OFFICIAL_AUTHOR = "official"
|
||
JWEBOT_AUTHOR = "jwebot"
|
||
DIRECT_KERNEL_COMMANDS = (
|
||
KernelCommandDescriptor(
|
||
description="查看由插件元数据自动生成的功能列表",
|
||
help_entries=("/功能列表(别名 /帮助、/help)",),
|
||
command_kinds=("feature_list",),
|
||
),
|
||
KernelCommandDescriptor(
|
||
description="查看 DeepSeek 账户余额",
|
||
help_entries=("/余额",),
|
||
command_kinds=("deepseek_balance",),
|
||
),
|
||
)
|
||
DIRECT_KERNEL_COMMAND_KINDS = frozenset(
|
||
kind
|
||
for descriptor in DIRECT_KERNEL_COMMANDS
|
||
for kind in descriptor.command_kinds
|
||
)
|
||
|
||
LOCAL_EXTENSIONS = (
|
||
LocalExtensionDescriptor(
|
||
extension_id="context-summary",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="上下文总结",
|
||
help_entries=("/上下文 [100|200|300];/context [100|200|300]",),
|
||
command_kinds=("context_summary",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="single-player-games",
|
||
author=JWEBOT_AUTHOR,
|
||
description="摩拉游戏",
|
||
help_entries=(
|
||
"/摩拉/原石 /抽奖 /彩票 /21点 /游戏帮助",
|
||
),
|
||
command_kinds=(
|
||
"wallet",
|
||
"prize_draw",
|
||
"lottery",
|
||
"blackjack",
|
||
"game_rules",
|
||
),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="game-history",
|
||
author=JWEBOT_AUTHOR,
|
||
description="游戏记录",
|
||
help_entries=("/游戏记录 /个人记录 /gamehistory",),
|
||
command_kinds=("game_history",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="coin-transfer",
|
||
author=JWEBOT_AUTHOR,
|
||
description="摩拉转账",
|
||
help_entries=("/转账 对方 金额;/transfer",),
|
||
command_kinds=("transfer",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="coin-ranking",
|
||
author=JWEBOT_AUTHOR,
|
||
description="富榜",
|
||
help_entries=("/大富翁榜",),
|
||
command_kinds=("coin_ranking",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="coin-taffy",
|
||
author=JWEBOT_AUTHOR,
|
||
description="Taffy摩拉",
|
||
help_entries=("/Taffy摩拉(兼容 /Taffy金币)",),
|
||
command_kinds=("taffy_coins",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="primogem-economy",
|
||
author=JWEBOT_AUTHOR,
|
||
description="原石系统",
|
||
help_entries=(
|
||
"/原石祈愿 /原石榜;/扫码加权 人;/Taffy发话 [定时HH:MM] 内容",
|
||
),
|
||
command_kinds=(
|
||
"primogem_wish",
|
||
"primogem_ranking",
|
||
"scan_boost",
|
||
"taffy_say",
|
||
),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="coin-loan",
|
||
author=JWEBOT_AUTHOR,
|
||
description="贷款",
|
||
help_entries=("/贷款;/还款",),
|
||
command_kinds=("loan", "repay"),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="trivia-quiz",
|
||
author=JWEBOT_AUTHOR,
|
||
description="冷门知识问答",
|
||
help_entries=("/回答 A;/answer A",),
|
||
command_kinds=("trivia_answer",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="cs-major-autochess",
|
||
author=JWEBOT_AUTHOR,
|
||
description="自走棋",
|
||
help_entries=(
|
||
"/自走棋 开始|报名|选",
|
||
),
|
||
command_kinds=("cs_autochess",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="person-directory",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="人物索引",
|
||
help_entries=("/人物列表 [页码] /people;/人物 [名称或别名] /person",),
|
||
command_kinds=("person_directory", "person_info"),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="person-memory",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="管理个人和同群人物记忆",
|
||
help_entries=(
|
||
"/记住 内容;/我的记忆;/忘记 关键词或全部;"
|
||
"/人物记忆 [显示名]",
|
||
),
|
||
command_kinds=(
|
||
"remember",
|
||
"my_memory",
|
||
"forget_memory",
|
||
"person_memory",
|
||
"memory_help",
|
||
),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="server-status",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="服务器状态",
|
||
help_entries=("/状态;/status",),
|
||
command_kinds=("local_status", "server_status"),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="jwebot-version",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="JWeBot 版本",
|
||
help_entries=("/version /版本",),
|
||
command_kinds=("jwebot_version",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="debug-telemetry",
|
||
author=OFFICIAL_AUTHOR,
|
||
description="埋点 p50/p95",
|
||
help_entries=("/debug",),
|
||
command_kinds=("telemetry_debug",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="dice",
|
||
author=JWEBOT_AUTHOR,
|
||
description="骰子和多人骰子挑战",
|
||
help_entries=(
|
||
"/丢骰子 [NdM]",
|
||
"/丢骰子挑战 [5d6|5d20|状态|结算|战绩|结束]",
|
||
),
|
||
command_kinds=("dice", "dice_challenge"),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="coin",
|
||
author=JWEBOT_AUTHOR,
|
||
description="抛一枚硬币",
|
||
help_entries=("/翻硬币",),
|
||
command_kinds=("coin",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="random-number",
|
||
author=JWEBOT_AUTHOR,
|
||
description="在指定整数范围内取随机数",
|
||
help_entries=("/随机数 最小值 最大值",),
|
||
command_kinds=("random_number",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="draw-lot",
|
||
author=JWEBOT_AUTHOR,
|
||
description="抽取一条本地签文",
|
||
help_entries=("/抽签",),
|
||
command_kinds=("draw_lot",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="daily-fortune",
|
||
author=JWEBOT_AUTHOR,
|
||
description="生成当天稳定一致的运势",
|
||
help_entries=("/今日运势",),
|
||
command_kinds=("daily_fortune",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="guess-number",
|
||
author=JWEBOT_AUTHOR,
|
||
description="群内持久化猜数字游戏",
|
||
help_entries=(
|
||
"/猜数字 开始 [上限];/猜 数字;/猜数字 [状态|结束]",
|
||
),
|
||
command_kinds=("guess_number",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="rock-paper-scissors",
|
||
author=JWEBOT_AUTHOR,
|
||
description="多人石头剪刀布游戏",
|
||
help_entries=(
|
||
"/石头剪刀布 [开始|加入|出 选择|状态|结算|结束]",
|
||
),
|
||
command_kinds=("rps",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="scan-ranking",
|
||
author=JWEBOT_AUTHOR,
|
||
description="查看北京时间今日扫码排行",
|
||
help_entries=("/扫码排行",),
|
||
command_kinds=("scan_ranking",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="repeat-ranking",
|
||
author=JWEBOT_AUTHOR,
|
||
description="查看北京时间今日复读排行",
|
||
help_entries=("/复读榜",),
|
||
command_kinds=("repeat_ranking",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="history-search",
|
||
author=JWEBOT_AUTHOR,
|
||
description="搜索本地群聊文字记录",
|
||
help_entries=("/查记录 关键词",),
|
||
command_kinds=("history_search",),
|
||
),
|
||
LocalExtensionDescriptor(
|
||
extension_id="steam-presence",
|
||
author=JWEBOT_AUTHOR,
|
||
description="Steam 状态与时长",
|
||
help_entries=(
|
||
"/steam;/steam时长 游戏[、玩家]",
|
||
),
|
||
command_kinds=("steam_friends",),
|
||
),
|
||
)
|
||
|
||
|
||
def extension_for_kind(kind: str) -> LocalExtensionDescriptor | None:
|
||
return next(
|
||
(
|
||
extension
|
||
for extension in LOCAL_EXTENSIONS
|
||
if kind in extension.command_kinds
|
||
),
|
||
None,
|
||
)
|
||
|
||
|
||
def render_feature_list() -> str:
|
||
lines = ["功能列表(由内核和插件描述自动生成)"]
|
||
for descriptor in DIRECT_KERNEL_COMMANDS:
|
||
lines.append(
|
||
f"[内核] {descriptor.description}:"
|
||
+ ";".join(descriptor.help_entries)
|
||
)
|
||
for descriptor in LOCAL_EXTENSIONS:
|
||
lines.append(
|
||
f"{descriptor.description}:"
|
||
+ ";".join(descriptor.help_entries)
|
||
)
|
||
lines.extend(
|
||
(
|
||
"[DeepSeek] 普通 @JWeBot 消息走本地直连 DeepSeek",
|
||
"[OpenClaw] @JWeBot #任务进入 OpenClaw",
|
||
)
|
||
)
|
||
return "\n".join(lines)
|
||
|
||
|
||
def _validate_inventory() -> None:
|
||
extension_kinds = [
|
||
kind
|
||
for extension in LOCAL_EXTENSIONS
|
||
for kind in extension.command_kinds
|
||
]
|
||
if len(extension_kinds) != len(set(extension_kinds)):
|
||
raise RuntimeError("local extension command ownership overlaps")
|
||
known_kinds = set(LOCAL_COMMAND_ALIASES.values())
|
||
if set(extension_kinds) | DIRECT_KERNEL_COMMAND_KINDS != known_kinds:
|
||
raise RuntimeError("local command inventory is incomplete")
|
||
if set(extension_kinds) & DIRECT_KERNEL_COMMAND_KINDS:
|
||
raise RuntimeError("Kernel commands cannot be extension-owned")
|
||
if any(
|
||
not extension.description or not extension.help_entries
|
||
for extension in LOCAL_EXTENSIONS
|
||
):
|
||
raise RuntimeError("local extensions must provide help metadata")
|
||
|
||
|
||
_validate_inventory()
|