Files
HeXi/hexi/plugins/memes_ops/__init__.py
T
sansenhoshiandClaude b61d09f09f Add HeXi bot codebase: custom plugins, web frontends, tests
- hexi core: message handling, rate limiting, cooldown, plugin manager
- Custom plugins: BF stats, daily check-in, quotes, persona cards, etc.
- Community plugins vendored under hexi/plugins with local fixes
- Web admin frontends (learning-chat, persona-admin), unified hexi/web
- Tests for rate_limit/cooldown/memes/persona; poetry.lock

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-01 13:13:40 +08:00

126 lines
5.2 KiB
Python

"""
表情裸词操作
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="对称 右 / 鬼畜 下 / 摸 圆 / 小丑 爷 / 小丑面具 前",
)
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 版本不兼容),"
"已恢复原状,表情仍按 `-右` 形式使用"
)