diff --git a/requirements.txt b/requirements.txt index c7ca623..404daba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,8 +13,8 @@ nonebot_plugin_apscheduler>=0.4.0 nonebot-adapter-satori>=0.11.5 # pyppeteer>=2.0.0 markdown>=3.3.6 -zhDateTime>=2.0.0 -numpy<2.0.0 +numba==0.65.1 +numpy==2.2.6 packaging>=23.1 psutil>=5.9.8 py-cpuinfo>=9.0.0 @@ -30,6 +30,7 @@ jieba>=0.42.1 python-dotenv>=1.0.1 nonebot_plugin_session pypinyin +zhDateTime>=2.0.0 Musicreater[full]>=2.4.0 librosa==0.10.1 TrimMCStruct diff --git a/src/nonebot_plugins/liteyuki_pacman/npm.py b/src/nonebot_plugins/liteyuki_pacman/npm.py index 9dfc7fd..4f9f731 100644 --- a/src/nonebot_plugins/liteyuki_pacman/npm.py +++ b/src/nonebot_plugins/liteyuki_pacman/npm.py @@ -5,7 +5,7 @@ import nonebot.plugin import pip from io import StringIO from arclet.alconna import MultiVar -from nonebot import Bot, require # type: ignore +from nonebot import Bot, require # type: ignore from nonebot.exception import FinishedException, IgnoredException, MockApiException from nonebot.internal.adapter import Event from nonebot.internal.matcher import Matcher @@ -25,7 +25,6 @@ from src.utils.message.markdown import MarkdownComponent as mdc, compile_md, esc from src.utils.message.html_tool import md_to_pic from .common import * - require("nonebot_plugin_alconna") from nonebot_plugin_alconna import ( UniMessage, @@ -37,6 +36,7 @@ from nonebot_plugin_alconna import ( Option, OptionResult, SubcommandResult, + store_true, ) # const @@ -103,6 +103,11 @@ disable = "disable" Subcommand( "list", Args["page", int, 1]["num", int, 10], + Option( + "-m|--markdown", + action=store_true, + help_text="以 Markdown 交互形式显示列表", + ), alias=["ls", "列表"], ), ), @@ -357,120 +362,165 @@ async def _(result: Arparma, event: T_MessageEvent, bot: T_Bot, npm: Matcher): elif sc.get("list"): loaded_plugin_list = sorted(nonebot.get_loaded_plugins(), key=lambda x: x.name) - num_per_page = result.subcommands.get("list").args.get("num") + num_per_page = result.subcommands["list"].args["num"] total = len(loaded_plugin_list) // num_per_page + ( 1 if len(loaded_plugin_list) % num_per_page else 0 ) + page = clamp(result.subcommands["list"].args["page"], 1, total) + markdown_mode = result.subcommands["list"].options["markdown"].value - page = clamp(result.subcommands.get("list").args.get("page"), 1, total) - - # 已加载插件 | 总计10 | 第1/3页 - reply = ( - f"# {ulang.get('npm.loaded_plugins')} | " - f"{ulang.get('npm.total', TOTAL=len(nonebot.get_loaded_plugins()))} | " - f"{ulang.get('npm.page', PAGE=page, TOTAL=total)} \n***\n" - ) - - permission_oas = ( - await GROUP_ADMIN(bot, event) - or await GROUP_OWNER(bot, event) - or await SUPERUSER(bot, event) - ) - permission_s = await SUPERUSER(bot, event) - - for storePlugin in loaded_plugin_list[ - (page - 1) - * num_per_page : min(page * num_per_page, len(loaded_plugin_list)) - ]: - # 检查是否有 metadata 属性 - # 添加帮助按钮 - - btn_usage = md.btn_cmd( - ulang.get("npm.usage"), f"help {storePlugin.name}", False + if not markdown_mode: + # 文字显示模式 + reply = " - {} | {} -\n".format( + ulang.get("npm.loaded_plugins"), + ulang.get("npm.page", PAGE=page, TOTAL=total), ) - store_plugin = await get_store_plugin(storePlugin.name) - session_enable = get_plugin_session_enable(event, storePlugin.name) - if store_plugin: - # btn_homepage = md.btn_link(ulang.get("npm.homepage"), store_plugin.homepage) - show_name = store_plugin.name - elif storePlugin.metadata: - # if storePlugin.metadata.extra.get("liteyuki"): - # btn_homepage = md.btn_link(ulang.get("npm.homepage"), "https://github.com/snowykami/LiteyukiBot") - # else: - # btn_homepage = ulang.get("npm.homepage") - show_name = storePlugin.metadata.name - else: - # btn_homepage = ulang.get("npm.homepage") - show_name = storePlugin.name - ulang.get("npm.no_description") + for pi in range( + (page - 1) * num_per_page, + min(page * num_per_page, len(loaded_plugin_list)), + ): + # 遍历插件,通过插件编号 + storePlugin = loaded_plugin_list[pi] + store_plugin = await get_store_plugin(storePlugin.name) + session_enable = get_plugin_session_enable(event, storePlugin.name) - if storePlugin.metadata: - reply += f"\n**{md.escape(show_name)}**\n" - else: - reply += f"**{md.escape(show_name)}**\n" + if store_plugin: + show_name = store_plugin.name + elif storePlugin.metadata: + show_name = storePlugin.metadata.name + else: + show_name = storePlugin.name + ulang.get("npm.no_description") - reply += f"\n > {btn_usage}" + reply += "{}. {}".format(pi + 1, show_name) - if permission_oas: - # 添加启用/停用插件按钮 - cmd_toggle = f"npm {'disable' if session_enable else 'enable'} {storePlugin.name}" - text_toggle = ulang.get( - "npm.disable" if session_enable else "npm.enable" + if not get_plugin_can_be_toggle(storePlugin.name): + reply += " [{}{}]".format(ulang.get('npm.cannot'), ulang.get( + "npm.disable" if session_enable else "npm.enable" + )) + + if not plugin_db.where_one( + InstalledPlugin(), "module_name = ?", storePlugin.name + ): + + reply += " [{}{}]".format(ulang.get('npm.cannot'), ulang.get("npm.uninstall")) + + reply += "\n>\t{}\n".format(storePlugin.name) + + await npm.send(reply) + + else: + # 已加载插件 | 总计10 | 第1/3页 + reply = ( + f"# {ulang.get('npm.loaded_plugins')} | " + f"{ulang.get('npm.total', TOTAL=len(nonebot.get_loaded_plugins()))} | " + f"{ulang.get('npm.page', PAGE=page, TOTAL=total)} \n***\n" + ) + + permission_oas = ( + await GROUP_ADMIN(bot, event) + or await GROUP_OWNER(bot, event) + or await SUPERUSER(bot, event) + ) + permission_s = await SUPERUSER(bot, event) + + for storePlugin in loaded_plugin_list[ + (page - 1) + * num_per_page : min(page * num_per_page, len(loaded_plugin_list)) + ]: + # 检查是否有 metadata 属性 + # 添加帮助按钮 + + btn_usage = md.btn_cmd( + ulang.get("npm.usage"), f"help {storePlugin.name}", False ) - can_be_toggle = get_plugin_can_be_toggle(storePlugin.name) - btn_toggle = ( - text_toggle - if not can_be_toggle - else md.btn_cmd(text_toggle, cmd_toggle) - ) - reply += f" {btn_toggle}" + store_plugin = await get_store_plugin(storePlugin.name) + session_enable = get_plugin_session_enable(event, storePlugin.name) + if store_plugin: + # btn_homepage = md.btn_link(ulang.get("npm.homepage"), store_plugin.homepage) + show_name = store_plugin.name + elif storePlugin.metadata: + # if storePlugin.metadata.extra.get("liteyuki"): + # btn_homepage = md.btn_link(ulang.get("npm.homepage"), "https://github.com/snowykami/LiteyukiBot") + # else: + # btn_homepage = ulang.get("npm.homepage") + show_name = storePlugin.metadata.name + else: + # btn_homepage = ulang.get("npm.homepage") + show_name = storePlugin.name + ulang.get("npm.no_description") - if permission_s: - plugin_in_database = plugin_db.where_one( - InstalledPlugin(), "module_name = ?", storePlugin.name + + # 何意味? —— 金羿 260510 + if storePlugin.metadata: + reply += f"\n**{md.escape(show_name)}**\n" + else: + reply += f"**{md.escape(show_name)}**\n" + + reply += f"\n > {btn_usage}" + + if permission_oas: + # 添加启用/停用插件按钮 + cmd_toggle = f"npm {'disable' if session_enable else 'enable'} {storePlugin.name}" + text_toggle = ulang.get( + "npm.disable" if session_enable else "npm.enable" ) - # 添加移除插件和全局切换按钮 - global_enable = get_plugin_global_enable(storePlugin.name) - btn_uninstall = ( - ( - md.btn_cmd( - ulang.get("npm.uninstall"), - f"npm uninstall {storePlugin.name}", - ) - ) - if plugin_in_database - else ulang.get("npm.uninstall") - ) - btn_toggle_global_text = ulang.get( - "npm.disable_global" if global_enable else "npm.enable_global" - ) - cmd_toggle_global = f"npm {'disable' if global_enable else 'enable'}-global {storePlugin.name}" - btn_toggle_global = ( - btn_toggle_global_text + can_be_toggle = get_plugin_can_be_toggle(storePlugin.name) + btn_toggle = ( + text_toggle if not can_be_toggle - else md.btn_cmd(btn_toggle_global_text, cmd_toggle_global) + else md.btn_cmd(text_toggle, cmd_toggle) ) + reply += f" {btn_toggle}" - reply += f" {btn_uninstall} {btn_toggle_global}" - reply += "\n\n***\n" - # 根据页数添加翻页按钮。第一页显示上一页文本而不是按钮,最后一页显示下一页文本而不是按钮 - btn_prev = ( - md.btn_cmd( - ulang.get("npm.prev_page"), f"npm list {page - 1} {num_per_page}" + if permission_s: + plugin_in_database = plugin_db.where_one( + InstalledPlugin(), "module_name = ?", storePlugin.name + ) + # 添加移除插件和全局切换按钮 + global_enable = get_plugin_global_enable(storePlugin.name) + btn_uninstall = ( + ( + md.btn_cmd( + ulang.get("npm.uninstall"), + f"npm uninstall {storePlugin.name}", + ) + ) + if plugin_in_database + else ulang.get("npm.uninstall") + ) + btn_toggle_global_text = ulang.get( + "npm.disable_global" + if global_enable + else "npm.enable_global" + ) + cmd_toggle_global = f"npm {'disable' if global_enable else 'enable'}-global {storePlugin.name}" + btn_toggle_global = ( + btn_toggle_global_text + if not can_be_toggle + else md.btn_cmd(btn_toggle_global_text, cmd_toggle_global) + ) + + reply += f" {btn_uninstall} {btn_toggle_global}" + reply += "\n\n***\n" + # 根据页数添加翻页按钮。第一页显示上一页文本而不是按钮,最后一页显示下一页文本而不是按钮 + btn_prev = ( + md.btn_cmd( + ulang.get("npm.prev_page"), f"npm list {page - 1} {num_per_page}" + ) + if page > 1 + else ulang.get("npm.prev_page") ) - if page > 1 - else ulang.get("npm.prev_page") - ) - btn_next = ( - md.btn_cmd( - ulang.get("npm.next_page"), f"npm list {page + 1} {num_per_page}" + btn_next = ( + md.btn_cmd( + ulang.get("npm.next_page"), f"npm list {page + 1} {num_per_page}" + ) + if page < total + else ulang.get("npm.next_page") ) - if page < total - else ulang.get("npm.next_page") - ) - reply += f"\n{btn_prev} {page}/{total} {btn_next}" - img_bytes = await md_to_pic(reply) - await UniMessage.send(UniMessage.image(raw=img_bytes)) + reply += f"\n{btn_prev} {page}/{total} {btn_next}" + img_bytes = await md_to_pic(reply) + await UniMessage.send(UniMessage.image(raw=img_bytes)) else: if await SUPERUSER(bot, event): diff --git a/src/nonebot_plugins/trimo_plugin_handle/__init__.py b/src/nonebot_plugins/trimo_plugin_handle/__init__.py index 160b003..a86969d 100644 --- a/src/nonebot_plugins/trimo_plugin_handle/__init__.py +++ b/src/nonebot_plugins/trimo_plugin_handle/__init__.py @@ -236,6 +236,79 @@ async def _(matcher: Matcher, user_id: UserId, matched: Dict[str, Any] = RegexDi await UniMessage.image(raw=await run_sync(game.draw)()).send() +handle_update_pinyin = on_alconna( + Alconna( + "更正成语拼音", + Args["idiom", str, ""], + Args["pinyin1", str, ""], + Args["pinyin2", str, ""], + Args["pinyin3", str, ""], + Args["pinyin4", str, ""], + ), + aliases=( + "更新猜成语词库拼音", + "猜成语更新拼音", + "更新猜成语拼音", + "更新成语拼音", + "更正猜成语拼音", + ), + use_cmd_start=True, + permission=SUPERUSER, + block=True, + priority=13, +) + + +@handle_update_pinyin.handle() +async def _( + result: Arparma, + matcher: Matcher, + user_id: UserId, + bot: T_Bot, +): + + if not ( + (idiom := result.main_args["idiom"]) + and (pinyin1 := result.main_args["pinyin1"]) + and (pinyin2 := result.main_args["pinyin2"]) + and (pinyin3 := result.main_args["pinyin3"]) + and (pinyin4 := result.main_args["pinyin4"]) + ): + await handle_update_pinyin.finish( + "用法:更正成语拼音 <成语> <拼音1> <拼音2> <拼音3> <拼音4>" + ) + + if idiom not in HANDLE_LEGAL_PHRASES: + await handle_update_pinyin.finish( + "未在词库中找到该成语,请使用 `新成语 <成语>` 来添加成语" + ) + + HANDLE_ANSWER_PHRASES[idiom]["pinyin"] = pynow = [ + pinyin1, + pinyin2, + pinyin3, + pinyin4, + ] + + json.dump( + HANDLE_ANSWER_PHRASES, + handle_answer_path.open("w", encoding="utf-8"), + ensure_ascii=False, + indent=4, + sort_keys=True, + ) + await handle_update_idiom.finish( + "成功修改:{}\n当前词库总数:{}个,普通模式成语:{}个\n当前成语信息如下:{}".format( + idiom, + len(HANDLE_LEGAL_PHRASES), + len(HANDLE_COMMON_PHRASES), + "\n\t释义:{}\n\t拼音:{}".format( + HANDLE_ANSWER_PHRASES[idiom]["explanation"], " ".join(pynow) + ), + ) + ) + + handle_update_idiom = on_alconna( Alconna( "新成语", @@ -267,31 +340,39 @@ async def _( bot: T_Bot, ): - try: - if result.options["explanation"].args["explanation"]: - explanation = result.options["explanation"].args["explanation"] - else: - nonebot.logger.info("!!!!这里永远不可能被执行到") - explanation = "未提供该成语的解释说明" - except: - explanation = None - - if hard := result.options["hard"].value: - if not explanation: - explanation = "未提供该成语的解释说明" - if not (idiom := result.main_args["idiom"]): await handle_update_idiom.finish("请在命令后带上你要增加的成语") - HANDLE_LEGAL_PHRASES.append(idiom) - json.dump( - HANDLE_LEGAL_PHRASES, - handle_all_idiom_path.open("w", encoding="utf-8"), - ensure_ascii=False, - indent=4, - sort_keys=True, - ) - if not hard: + existance = idiom in HANDLE_LEGAL_PHRASES + + try: + explanation = ( + result.options["explanation"].args["explanation"] + if result.options["explanation"].args["explanation"] + else None + ) + except: + explanation = None + + if existance and (not explanation): + # 这个判断的顺序必须高于下面的判断语句 + explanation = HANDLE_ANSWER_PHRASES[idiom]["explanation"] + + if not explanation: + explanation = "未提供该成语的解释说明" + + if not existance: + HANDLE_LEGAL_PHRASES.append(idiom) + json.dump( + HANDLE_LEGAL_PHRASES, + handle_all_idiom_path.open("w", encoding="utf-8"), + ensure_ascii=False, + indent=4, + sort_keys=True, + ) + if (not (hard := result.options["hard"].value)) and ( + idiom not in HANDLE_COMMON_PHRASES + ): HANDLE_COMMON_PHRASES.append(idiom) json.dump( HANDLE_COMMON_PHRASES, @@ -301,25 +382,33 @@ async def _( sort_keys=True, ) - if explanation: - HANDLE_ANSWER_PHRASES[idiom] = { - "explanation": explanation, - "pinyin": [ - j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i - ], - } - json.dump( - HANDLE_ANSWER_PHRASES, - handle_answer_path.open("w", encoding="utf-8"), - ensure_ascii=False, - indent=4, - sort_keys=True, - ) + HANDLE_ANSWER_PHRASES[idiom] = { + "explanation": explanation, + "pinyin": ( + pynow := ( + HANDLE_ANSWER_PHRASES[idiom]["pinyin"].copy() + if existance + else [ + j for i in pinyin(idiom, style=Style.TONE3, v_to_u=True) for j in i + ] + ) + ), + } + json.dump( + HANDLE_ANSWER_PHRASES, + handle_answer_path.open("w", encoding="utf-8"), + ensure_ascii=False, + indent=4, + sort_keys=True, + ) await handle_update_idiom.finish( - "新增成功,当前词库总数:{}个\n可用普通模式成语:{}个".format( + "成功{}:{}\n当前词库总数:{}个,普通模式成语:{}个\n当前成语信息如下:{}".format( + "修改" if existance else "新增", + idiom, len(HANDLE_LEGAL_PHRASES), len(HANDLE_COMMON_PHRASES), + "\n\t释义:{}\n\t拼音:{}".format(explanation, " ".join(pynow)), ) ) diff --git a/src/resources/vanilla_language/lang/en.lang b/src/resources/vanilla_language/lang/en.lang index 2de85f2..3a417c2 100644 --- a/src/resources/vanilla_language/lang/en.lang +++ b/src/resources/vanilla_language/lang/en.lang @@ -99,6 +99,7 @@ npm.plugin_already=Plugin {NAME} is already {STATUS}, no need to repeat operatio npm.toggle_failed=Plugin {NAME} {STATUS} failed: {ERROR} npm.toggle_success=Plugin {NAME} {STATUS} successful npm.page=Page {PAGE}/{TOTAL} +npm.cannot=Cannot npm.update_index=Update Plugin Index npm.list_plugins=Plugin List npm.disable_session=Disable plugin for current session diff --git a/src/resources/vanilla_language/lang/zh-CN.lang b/src/resources/vanilla_language/lang/zh-CN.lang index 62c91d0..89e8d9e 100644 --- a/src/resources/vanilla_language/lang/zh-CN.lang +++ b/src/resources/vanilla_language/lang/zh-CN.lang @@ -99,6 +99,7 @@ npm.plugin_already=插件 {NAME} 已经是 {STATUS} 状态,无需重复操作 npm.toggle_failed=插件 {NAME} {STATUS} 失败: {ERROR} npm.toggle_success=插件 {NAME} {STATUS} 成功 npm.page=第{PAGE}/{TOTAL}页 +npm.cannot=不可 npm.update_index=更新插件索引 npm.list_plugins=插件列表 npm.disable_session=当前会话停用插件 diff --git a/src/resources/vanilla_language/lang/zh-WY.lang b/src/resources/vanilla_language/lang/zh-WY.lang index 58c17c7..b7ef6c6 100644 --- a/src/resources/vanilla_language/lang/zh-WY.lang +++ b/src/resources/vanilla_language/lang/zh-WY.lang @@ -98,7 +98,8 @@ npm.plugin_cannot_be_toggled=不可变易件曰 {NAME} 者 npm.plugin_already=件曰 {NAME} 者,乃{STATUS},勿复行 npm.toggle_failed=因 {ERROR} 所误,良机尽失,{NAME} 无以{STATUS} npm.toggle_success=件曰 {NAME} 者,方{STATUS}成 -npm.page=页第 {PAGE} 之于 {TOTAL} +npm.page=第 {PAGE} 之于 {TOTAL} 页 +npm.cannot=不可 npm.update_index=阁引 npm.list_plugins=件目 npm.disable_session=是处去 @@ -125,8 +126,8 @@ user.profile.input_value=求 {ATTR} 之量 user.profile.set_success=君 {ATTR} 方设 {VALUE} 而成 user.profile.set_failed={ATTR} 无以设,子阙否 -rpm.move_up=右移 -rpm.move_down=左移 +rpm.move_up=上移 +rpm.move_down=下移 rpm.move_top=归首 weather.city_not_found=无城谓 {CITY} 者 @@ -138,8 +139,8 @@ status.groups=羣 status.plugins=附件 status.resources=件资 status.bots=工造灵机 -status.message_sent=方传 -status.message_received=方受 +status.message_sent=方送 +status.message_received=方迎 status.cpu=卷枢 status.memory=暂贮 status.swap=变贮 @@ -148,7 +149,7 @@ status.usage=计用 status.total=合 status.used=占 status.free=余 -status.runtime=运期 +status.runtime=期时 status.days=日 status.hours=小时 status.minutes=分