feat: evolve textfx into a mini shell

This commit is contained in:
2026-03-14 23:35:29 +08:00
parent 00f42dbdf1
commit 1331f8f893
6 changed files with 915 additions and 246 deletions

View File

@ -1,4 +1,5 @@
from typing import cast
import asyncio
from loguru import logger
from nonebot import on_command
import nonebot
@ -31,8 +32,11 @@ from konabot.plugins.handle_text.handlers.random_handlers import THShuffle, THSo
from konabot.plugins.handle_text.handlers.unix_handlers import (
THCat,
THEcho,
THFalse,
THReplace,
THRm,
THTest,
THTrue,
)
from konabot.plugins.handle_text.handlers.whitespace_handlers import (
THLines,
@ -43,11 +47,37 @@ from konabot.plugins.handle_text.handlers.whitespace_handlers import (
)
TEXTFX_MAX_RUNTIME_SECONDS = 60
_textfx_running_users: set[str] = set()
def _get_textfx_user_key(evt: Event) -> str:
user_id = getattr(evt, "user_id", None)
self_id = getattr(evt, "self_id", None)
group_id = getattr(evt, "group_id", None)
if user_id is not None:
if group_id is not None:
return f"{self_id}:{group_id}:{user_id}"
return f"{self_id}:private:{user_id}"
session_id = getattr(evt, "get_session_id", None)
if callable(session_id):
try:
return f"session:{evt.get_session_id()}"
except Exception:
pass
return f"event:{evt.__class__.__name__}:{id(evt)}"
cmd = on_command(cmd="textfx", aliases={"处理文字", "处理文本"})
@cmd.handle()
async def _(msg: UniMsg, evt: Event, bot: Bot, target: DepLongTaskTarget):
user_key = _get_textfx_user_key(evt)
if user_key in _textfx_running_users:
await target.send_message("你当前已有一个 textfx 脚本正在运行,请等待它结束后再试。")
return
istream = ""
if isinstance(evt, OB11MessageEvent):
if evt.reply is not None:
@ -71,9 +101,22 @@ async def _(msg: UniMsg, evt: Event, bot: Bot, target: DepLongTaskTarget):
return
env = TextHandlerEnvironment(is_trusted=False, event=evt)
results = await runner.run_pipeline(res, istream or None, env)
# 检查是否有错误
_textfx_running_users.add(user_key)
try:
results = await asyncio.wait_for(
runner.run_pipeline(res, istream or None, env),
timeout=TEXTFX_MAX_RUNTIME_SECONDS,
)
except asyncio.TimeoutError:
rendered = await render_error_message(
f"处理指令时出现问题:脚本执行超时(超过 {TEXTFX_MAX_RUNTIME_SECONDS} 秒)"
)
await target.send_message(rendered)
return
finally:
_textfx_running_users.discard(user_key)
for r in results:
if r.code != 0:
message = f"处理指令时出现问题:{r.ostream}"
@ -81,7 +124,6 @@ async def _(msg: UniMsg, evt: Event, bot: Bot, target: DepLongTaskTarget):
await target.send_message(rendered)
return
# 收集所有组的文本输出和附件
ostreams = [r.ostream for r in results if r.ostream is not None]
attachments = [r.attachment for r in results if r.attachment is not None]
@ -108,6 +150,9 @@ async def _():
THCat(),
THEcho(),
THRm(),
THTrue(),
THFalse(),
THTest(),
THShuffle(),
THReplace(),
THBase64(),