""" 表情裸词操作 nonebot-plugin-memes 0.5+ 改用 Alconna 后,表情选项只能用 `-右`/`--right` 形式 (0.4.x 旧版是 `对称 /右`)。本插件为表情作者声明的短别名(左/右/上/下/前/后/圆/爷) 追加裸词形式,恢复 `表情 操作词` 的用法,如: 对称 右 / 鬼畜 下 / 循环 上 / 摸 圆 / 小丑 爷 / 小丑面具 前 / ba说 左 实现方式:patch `nonebot_plugin_memes.matchers.command` 的 `build_option` (追加裸词别名)和 `on_alconna`(重建的 matcher 用 priority=11 + block 抢占原 priority=12 的 matcher),然后为受影响的表情重建 matcher。 注意:本补丁针对 nonebot-plugin-memes 0.8.1 的内部结构编写;插件大版本更新后 若内部改名导致补丁失败,会记日志并自动跳过,原插件按默认方式工作(退回 `-右` 语法)。 """ from nonebot import require require("nonebot_plugin_memes") from importlib.metadata import PackageNotFoundError, version from nonebot import logger from nonebot.plugin import PluginMetadata from meme_generator import BooleanOption, FloatOption, IntegerOption from nonebot_plugin_alconna import Args, Option, store_false, store_true from nonebot_plugin_memes.manager import meme_manager from nonebot_plugin_memes.matchers import command as memes_command __plugin_meta__ = PluginMetadata( name="表情裸词操作", description="恢复“表情 操作词”的裸词用法(对称 右、摸 圆、小丑 爷 等)", usage="对称 右 / 鬼畜 下 / 摸 圆 / 小丑 爷 / 小丑面具 前", type="application", ) try: _memes_version = version("nonebot-plugin-memes") except PackageNotFoundError: _memes_version = "?" if _memes_version != "0.8.1": logger.warning( f"表情裸词操作:当前 nonebot-plugin-memes 版本为 {_memes_version}," "本补丁按 0.8.1 编写,若下方出现补丁失败日志请检查兼容性" ) # 幂等:热重载本插件时不重复打补丁 if getattr(memes_command.build_option, "_memes_ops_patched", False): logger.info("表情裸词操作:补丁已应用过,跳过") else: try: _original_build_option = memes_command.build_option _original_on_alconna = memes_command.on_alconna def _build_option(option): """原版 build_option,并在选项名中追加作者声明的裸词短别名(如 `右`)。""" declared_short_aliases = list(option.parser_flags.short_aliases) names: list[str] = [] parser_flags = option.parser_flags short_aliases = parser_flags.short_aliases if parser_flags.short: short_aliases.insert(0, option.name[0]) long_aliases = parser_flags.long_aliases if parser_flags.long: long_aliases.insert(0, option.name) names.extend([f"-{flag}" for flag in short_aliases]) names.extend([f"--{flag}" for flag in long_aliases]) names.extend(declared_short_aliases) if isinstance(option, BooleanOption): action = None if option.default is not None: action = store_false if option.default else store_true return Option( name="|".join(names), dest=option.name, default=option.default, action=action, help_text=option.description, ) args = Args() if isinstance(option, IntegerOption): arg_type = int elif isinstance(option, FloatOption): arg_type = float else: arg_type = str args.add(name=option.name, value=arg_type) return Option( name="|".join(names), args=args, dest=option.name, help_text=option.description, ) def _on_alconna(command, *args, **kwargs): """重建的 matcher 提高优先级并 block,抢占原 priority=12 的 matcher。""" kwargs["priority"] = 11 kwargs["block"] = True return _original_on_alconna(command, *args, **kwargs) memes_command.build_option = _build_option memes_command.on_alconna = _on_alconna _build_option._memes_ops_patched = True # noqa: B010 patched: list[str] = [] for meme in meme_manager.get_memes(): aliases = [ flag for option in meme.info.params.options for flag in option.parser_flags.short_aliases ] if aliases: memes_command.create_matcher(meme) patched.append(f"{meme.key}({','.join(aliases)})") logger.info(f"表情裸词操作:已为 {len(patched)} 个表情启用裸词操作: {patched}") except Exception: # 版本不兼容时优雅降级,恢复原函数,不影响原插件 memes_command.build_option = _original_build_option # type: ignore[possibly-undefined] memes_command.on_alconna = _original_on_alconna # type: ignore[possibly-undefined] logger.exception( "表情裸词操作:补丁应用失败(可能与 nonebot-plugin-memes 版本不兼容)," "已恢复原状,表情仍按 `-右` 形式使用" )