diff --git a/liteyuki/utils.py b/liteyuki/utils.py index 629f5d7..50fe7f5 100644 --- a/liteyuki/utils.py +++ b/liteyuki/utils.py @@ -7,7 +7,7 @@ import inspect import multiprocessing import threading from pathlib import Path -from typing import Any, Callable, Coroutine +from typing import Any, Callable, Coroutine, Sequence from liteyuki.log import logger @@ -104,3 +104,23 @@ def async_wrapper(func: Callable[..., Any]) -> Callable[..., Coroutine]: wrapper.__signature__ = inspect.signature(func) return wrapper + + +def for_in( + elements: Sequence, + test_list: Sequence, +): + """ + 判断元素是否在列表中 + Args: + elements: 元素列表 + test_list: 测试列表 + Returns: + List 在列表中的元素 + """ + return [element for element in elements if element in test_list] + # for element in elements: + # if element in test_list: + # return True + + # return False diff --git a/src/nonebot_plugins/liteyuki_status/__init__.py b/src/nonebot_plugins/liteyuki_status/__init__.py index dc1e9d5..4e4699b 100644 --- a/src/nonebot_plugins/liteyuki_status/__init__.py +++ b/src/nonebot_plugins/liteyuki_status/__init__.py @@ -3,18 +3,18 @@ from .status import * __author__ = "神羽SnowyKami & 金羿Eilles" __plugin_meta__ = PluginMetadata( - name="状态查看器", + name="灵温状态查看", description="", usage=( "MARKDOWN### 状态查看器\n" "查看机器人的状态\n" "### 用法\n" "- `/status` 查看基本情况\n" - "- `/status memory` 查看内存使用情况\n" - "- `/status process` 查看进程情况\n" + "- `/status -r` 强制刷新状态情况\n" + "- `/status -d` 使用简化markdown渲染状态\n" ), type="application", - homepage="https://github.com/snowykami/LiteyukiBot", + homepage="https://gitee.com/TriM-Organization/LiteyukiBot-TriM", extra={ "liteyuki": True, "toggleable": False, diff --git a/src/nonebot_plugins/liteyuki_status/api.py b/src/nonebot_plugins/liteyuki_status/api.py index d847708..179a0e4 100644 --- a/src/nonebot_plugins/liteyuki_status/api.py +++ b/src/nonebot_plugins/liteyuki_status/api.py @@ -4,16 +4,16 @@ import time import nonebot import psutil from cpuinfo import cpuinfo -from nonebot import require from nonebot.adapters import satori -from src.utils import __NAME__ from liteyuki import __version__ +from liteyuki.utils import for_in +from src.utils import __NAME__ from src.utils.base.config import get_config from src.utils.base.data_manager import TempConfig, common_db from src.utils.base.language import Language from src.utils.base.resource import get_loaded_resource_packs, get_path -from src.utils.message.html_tool import template2image +from src.utils.message.html_tool import template2image, md_to_pic from src.utils import satori_utils from .counter_for_satori import satori_counter from git import Repo @@ -32,6 +32,7 @@ protocol_names = { 6: "安卓平板", } + """ Universal Interface data @@ -87,6 +88,207 @@ data # ) +# 用markdown文字展示状态卡片 +async def generate_status_card_markdown( + bot: dict, + hardware: dict, + liteyuki: dict, + lang="zh-CN", + motto={"text": "风朗气清", "source": "成语一则"}, +) -> bytes: + from .md_status_utils import ( + markdown_status_bot_card_text, + markdown_status_card_text, + markdown_status_disk_card_text, + convert_size, + seconds2texttime, + ) + + local_dt = await get_local_data(lang) + bytes_suffix = " X" + local_dt["units"]["Byte"] + bin_units = local_dt["units"]["Bin_Units"] + + markdown_status_bot_card_text__ = ( + markdown_status_bot_card_text.replace( + r"{local_groups}", + local_dt["groups"], + ) + .replace( + r"{local_friends}", + local_dt["friends"], + ) + .replace( + r"{local_message_sent}", + local_dt["message_sent"], + ) + .replace( + r"{local_message_received}", + local_dt["message_received"], + ) + ) + + markdown_status_disk_card_text__ = ( + markdown_status_disk_card_text.replace( + r"{local_used}", + local_dt["used"], + ) + .replace( + r"{local_free}", + local_dt["free"], + ) + .replace( + r"{local_total}", + local_dt["total"], + ) + ) + + fnl_text = markdown_status_card_text.format( + local_description=local_dt["description"], + liteyuki_name=liteyuki["name"], + liteyuki_version=liteyuki["version"], + liteyuki_nonebot=liteyuki["nonebot"], + liteyuki_system=liteyuki["system"], + liteyuki_python=liteyuki["python"], + local_plugins=local_dt["plugins"], + liteyuki_plugins=liteyuki["plugins"], + local_resources=local_dt["resources"], + liteyuki_resources=liteyuki["resources"], + local_bots=local_dt["bots"], + liteyuki_bots=liteyuki["bots"], + local_runtime=local_dt["runtime"], + liteyuki_runtime=seconds2texttime( + liteyuki["runtime"], + unit_days=local_dt["days"], + unit_hours=local_dt["hours"], + unit_minutes=local_dt["minutes"], + unit_seconds=local_dt["seconds"], + ), + for_bots="\n".join( + [ + markdown_status_bot_card_text__.format( + bot_name=s_bot["name"], + bot_icon=s_bot["icon"], + bot_app_name=s_bot["app_name"], + bot_protocol_name=s_bot["protocol_name"], + bot_groups=s_bot["groups"], + bot_friends=s_bot["friends"], + bot_message_sent=s_bot["message_sent"], + bot_message_received=s_bot["message_received"], + ) + for s_bot in bot["bots"] + ] + ), + local_cpu=local_dt["cpu"], + hardware_cpu_percent=hardware["cpu"]["percent"], + hardware_cpu_name=hardware["cpu"]["name"], + hardware_cpu_cores=hardware["cpu"]["cores"], + local_cores=local_dt["cores"], + hardware_cpu_threads=hardware["cpu"]["threads"], + local_threads=local_dt["threads"], + hardware_cpu_freq=hardware["cpu"]["freq"] / 1000, + local_units_GHz=local_dt["units"]["GHz"], + local_memory=local_dt["memory"], + hardware_memory_percent=hardware["memory"]["percent"], + local_process=local_dt["process"], + hardware_memory_processmem=convert_size( + hardware["memory"]["usedProcess"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + local_used=local_dt["used"], + hardware_memory_usedmem=convert_size( + hardware["memory"]["used"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + local_free=local_dt["free"], + hardware_memory_freemem=convert_size( + hardware["memory"]["free"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + local_total=local_dt["total"], + hardware_memory_totalmem=convert_size( + hardware["memory"]["total"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + local_swap=local_dt["swap"], + hardware_swap_percent=hardware["swap"]["percent"], + hardware_swap_usedswap=convert_size( + hardware["swap"]["used"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + hardware_swap_freeswap=convert_size( + hardware["swap"]["free"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + hardware_swap_totalswap=convert_size( + hardware["swap"]["total"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + local_disk=local_dt["disk"], + for_disk="\n".join( + [ + markdown_status_disk_card_text__.format( + hardware_disk_name=s_disk["name"], + hardware_disk_percent=s_disk["percent"], + hardware_disk_useddisk=convert_size( + s_disk["used"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + hardware_disk_freedisk=convert_size( + s_disk["free"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + hardware_disk_totaldisk=convert_size( + s_disk["total"], + precision=2, + is_unit_added=True, + suffix=bytes_suffix, + bin_units=bin_units, + ), + ) + for s_disk in hardware["disk"] + ] + ), + motto_text=motto["text"], + motto_source=motto["source"], + acknowledgement=get_config("status_acknowledgement"), + ) + + return await md_to_pic(fnl_text, width=540, device_scale_factor=4) + + +# def gogop(x): +# from rich.console import Console +# Console().print(x) +# return x + + # 获取状态卡片 # bot_id 参数已经是bot参数的一部分了,不需要保留,但为了“兼容性”…… async def generate_status_card( @@ -95,8 +297,9 @@ async def generate_status_card( liteyuki: dict, lang="zh-CN", motto={"text": "风朗气清", "source": "成语一则"}, - bot_id="0", + bot_id="0", # 兼容性 ) -> bytes: + # print(get_config("status_acknowledgement")) return await template2image( get_path("templates/status.html", abs_path=True), { @@ -104,15 +307,17 @@ async def generate_status_card( "bot": bot, "hardware": hardware, "liteyuki": liteyuki, - "localization": get_local_data(lang), + "localization": await get_local_data(lang), "motto": motto, + "acknowledgement": get_config("status_acknowledgement"), } }, ) -def get_local_data(lang_code) -> dict: +async def get_local_data(lang_code) -> dict: lang = Language(lang_code) + bin_forcase = lang.get("status.unit.binary_middile") return { "friends": lang.get("status.friends"), "groups": lang.get("status.groups"), @@ -138,6 +343,18 @@ def get_local_data(lang_code) -> dict: "process": lang.get("status.process"), "resources": lang.get("status.resources"), "description": lang.get("status.description"), + "units": { + "GHz": lang.get("status.unit.GHz"), + "Byte": lang.get("status.unit.Byte"), + "Bin_Units": [ + ( + ((bin_forcase + i) if "zh" in lang_code else (i + bin_forcase)) + if i.strip() + else "" + ) + for i in lang.get("status.unit.Bit_Units").split(";") + ], + }, } @@ -161,7 +378,7 @@ async def get_bots_data(self_id: str = "0") -> dict: groups = str(await satori_utils.count_groups(bot)) friends = str(await satori_utils.count_friends(bot)) status = {} - version_info = await bot.get_version_info() + version_info = await bot.get_version_info() # type: ignore except Exception: pass else: @@ -210,7 +427,8 @@ async def get_bots_data(self_id: str = "0") -> dict: return result -async def get_hardware_data() -> dict: +async def get_hardware_data(lang_code) -> dict: + lang = Language(lang_code) mem = psutil.virtual_memory() all_processes = psutil.Process().children(recursive=True) all_processes.append(psutil.Process()) @@ -227,30 +445,27 @@ async def get_hardware_data() -> dict: except Exception: pass swap = psutil.swap_memory() - cpu_brand_raw = cpuinfo.get_cpu_info().get("brand_raw", "未知处理器") - if "amd" in cpu_brand_raw.lower(): - brand = "AMD" - elif "intel" in cpu_brand_raw.lower(): - brand = "英特尔" - elif "apple" in cpu_brand_raw.lower(): - brand = "苹果" - elif "qualcomm" in cpu_brand_raw.lower(): - brand = "高通" - elif "mediatek" in cpu_brand_raw.lower(): - brand = "联发科" - elif "samsung" in cpu_brand_raw.lower(): - brand = "三星" - elif "nvidia" in cpu_brand_raw.lower(): - brand = "英伟达" + cpu_infos = cpuinfo.get_cpu_info() + cpu_brand_raw = cpu_infos.get( + "hardware_raw", + cpu_infos.get("brand_raw", "未知处理器"), # 此处之汉文不会被直接使用 + ).lower() + if cpu_brand_selected := for_in( + ("amd", "intel", "apple", "qualcomm", "mediatek", "samsung", "nvidia"), + cpu_brand_raw, + ): + brand = lang.get("status.cpubrand." + cpu_brand_selected[0]) else: - brand = "未知处理器" + brand = lang.get("status.cpubrand.unknown") result = { "cpu": { "percent": psutil.cpu_percent(), - "name": f"{brand} {cpuinfo.get_cpu_info().get('arch', '未知架构')}", + "name": "{} {}".format( + brand, cpu_infos.get("arch_string_raw", lang.get("status.arch.unknown")) + ), "cores": psutil.cpu_count(logical=False), "threads": psutil.cpu_count(logical=True), - "freq": psutil.cpu_freq().current, # MHz + "freq": psutil.cpu_freq().current, # 单位 MHz }, "memory": { "percent": mem.percent, @@ -268,25 +483,39 @@ async def get_hardware_data() -> dict: "disk": [], } + other_disk = { + "name": lang.get("status.disk.other"), + "percent": 0, + "total": 0, + "used": 0, + "free": 0, + } for disk in psutil.disk_partitions(all=True): try: disk_usage = psutil.disk_usage(disk.mountpoint) if disk_usage.total == 0 or disk.mountpoint.startswith( ("/var", "/boot", "/run", "/proc", "/sys", "/dev", "/tmp", "/snap") ): - continue # 虚拟磁盘 - result["disk"].append( - { - "name": disk.mountpoint, - "percent": disk_usage.percent, - "total": disk_usage.total, - "used": disk_usage.used, - "free": disk_usage.free, - } - ) + other_disk["percent"] = (other_disk["percent"] + disk_usage.percent) / 2 + other_disk["total"] += disk_usage.total + other_disk["used"] += disk_usage.used + other_disk["free"] += disk_usage.free + else: + result["disk"].append( + { + "name": disk.mountpoint, + "percent": disk_usage.percent, + "total": disk_usage.total, + "used": disk_usage.used, + "free": disk_usage.free, + } + ) except: pass + if other_disk["total"] > 0: # 避免除零错误 + result["disk"].append(other_disk) + return result diff --git a/src/nonebot_plugins/liteyuki_status/md_status_utils.py b/src/nonebot_plugins/liteyuki_status/md_status_utils.py new file mode 100644 index 0000000..7486929 --- /dev/null +++ b/src/nonebot_plugins/liteyuki_status/md_status_utils.py @@ -0,0 +1,123 @@ +markdown_status_bot_card_text = """ +### **{bot_name}  |  ** + + - {bot_app_name} : {bot_protocol_name} + - {local_groups}{bot_groups} | {local_friends}{bot_friends} | {local_message_sent}{bot_message_sent} | {local_message_received}{bot_message_received} +""" + +markdown_status_disk_card_text = """ - {hardware_disk_name} + +\t{local_used} {hardware_disk_useddisk} {hardware_disk_percent}% | {local_free} {hardware_disk_freedisk} | {local_total} {hardware_disk_totaldisk}""" + +markdown_status_card_text = """ +

{local_description}

+ +

bot-icon   {liteyuki_name} - 睿乐

+ + - 灵温 {liteyuki_version} | Nonebot {liteyuki_nonebot} + - {liteyuki_system} {liteyuki_python} + - {local_plugins}{liteyuki_plugins} | {local_resources}{liteyuki_resources} | {local_bots}{liteyuki_bots} + - {local_runtime}{liteyuki_runtime} + +{for_bots} + +## {local_cpu} : {hardware_cpu_percent}% + + - {hardware_cpu_name} | {hardware_cpu_cores}{local_cores} {hardware_cpu_threads}{local_threads} | {hardware_cpu_freq}{local_units_GHz} + + +## {local_memory} : {hardware_memory_percent}% + + - {local_process} {hardware_memory_processmem} + - {local_used} {hardware_memory_usedmem} + - {local_free} {hardware_memory_freemem} + - {local_total} {hardware_memory_totalmem} + +## {local_swap} : {hardware_swap_percent}% + + - {local_used} {hardware_swap_usedswap} + - {local_free} {hardware_swap_freeswap} + - {local_total} {hardware_swap_totalswap} + +## {local_disk} + +{for_disk} + +----------------------- + +### {motto_text} + +
——{motto_source}
+ +####
{acknowledgement}
+ +####
该页样式由 金羿Eilles 设计
+""" + + +def convert_size( + size: int | float, + precision: int = 2, + is_unit_added: bool = True, + suffix: str = " X字节", + bin_units: list[str] = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"], +): + """ + 将字节转换为带单位的大小 + + :param size: 要转换的字节大小 + :param precision: 保留小数位数 + :param is_unit_added: 是否添加单位 + :param suffix: 单位后缀 + :param bin_units: 单位列表 + :return: 转换后的大小字符串 + """ + is_negative = size < 0 + size = abs(size) + # let units = ["", "千", "兆", "吉", "太", "拍", "艾", "泽"]; + unit = "" + + for sg_unit in bin_units: + if size < 1024: + unit = sg_unit + break + size /= 1024 + + if is_negative: + size = -size + + if is_unit_added: + return ("{" + ":.{}f".format(precision) + "}").format(size) + suffix.replace( + "X", unit + ) + else: + return size + + +def seconds2texttime( + seconds: int, + unit_days: str = "日", + unit_hours: str = "时", + unit_minutes: str = "分", + unit_seconds: str = "秒", +): + """ + 将秒数转换为时间文本 + + :param seconds: 要转换的秒数 + :param unit_days: 天的单位 + :param unit_hours: 小时的单位 + :param unit_minutes: 分钟的单位 + :param unit_seconds: 秒的单位 + :return: 转换后的时间文本 + """ + return "{dt}{ld} {ht}{lh} {mt}{lm} {st}{ls}".format( + dt=seconds // 86400, + ld=unit_days, + ht=(seconds % 86400) // 3600, + lh=unit_hours, + mt=(seconds % 3600) // 60, + lm=unit_minutes, + st=seconds % 60, + ls=unit_seconds, + ) diff --git a/src/nonebot_plugins/liteyuki_status/status.py b/src/nonebot_plugins/liteyuki_status/status.py index ecf9c26..12a4102 100644 --- a/src/nonebot_plugins/liteyuki_status/status.py +++ b/src/nonebot_plugins/liteyuki_status/status.py @@ -2,6 +2,7 @@ import random import aiohttp import zhDateTime +from nonebot import require from src.utils import event as event_utils from src.utils.base.language import get_user_lang, get_default_lang_code, Language @@ -35,6 +36,12 @@ status_alc = on_alconna( alias={"refr", "r", "刷新"}, action=store_true, ), + Option( + "-t|-md|--markdown", + default=False, + # alias={"refr", "r", "刷新"}, + action=store_true, + ), Subcommand( "memory", alias={"mem", "m", "内存"}, @@ -72,7 +79,7 @@ yanlun_path = "https://nd.liteyuki.icu/api/v3/share/content/Xpue?path=null" # 每天4点更新 @scheduler.scheduled_job("cron", hour=4) async def every_day_update(): - ulang = Language(get_default_lang_code(), "zh-WY") + ulang = Language(get_default_lang_code(), "zh-CN") nonebot.logger.success( ulang.get("yanlun.refresh.success", COUNT=await update_yanlun()) ) @@ -88,7 +95,7 @@ async def update_yanlun(): resp = await client.get(yanlun_path, timeout=15) yanlun_texts = (await resp.text()).strip("\n").split("\n") except (ConnectionError, aiohttp.ClientError, aiohttp.WebSocketError) as err: - nonebot.logger.warning("读取言·论信息发生 客户端或通道 错误:\n{}".format(err)) + nonebot.logger.warning("读取言·论信息发生 连接 错误:\n{}".format(err)) yanlun_texts = ["以梦想为驱使 创造属于自己的未来"] # noinspection PyBroadException except BaseException as err: @@ -117,14 +124,22 @@ async def _(): yanlun_seqs = yanlun_texts = ["金羿ELS 生日快乐~!", "Happy Birthday, Eilles!"] elif solar_date == (8, 6): yanlun_seqs = yanlun_texts = [ - "诸葛亮与八卦阵 生日快乐~!", - "Happy Birthday, bgArray~!", + "玉衡 生日快乐~!", + "Happy Birthday, Alioth~!", ] elif solar_date == (8, 16): yanlun_seqs = yanlun_texts = [ "鱼旧梦 生日快乐~!", "Happy Birthday, ElapsingDreams~!", ] + elif lunar_date == (1, 1): + yanlun_seqs = yanlun_texts = [ + "新春快乐~", + "千门万户曈曈日,总把新桃换旧符\t——王安石《元日》", + "爆竹声中一岁除,春风送暖入屠苏\t——王安石《元日》", + "半盏屠苏犹未举,灯前小草写桃符\t—— 陆游《除夜雪》", + "愿得长如此,年年物候新\t—— 卢照邻《元日述怀》", + ] else: await update_yanlun() @@ -163,13 +178,25 @@ async def _( ) ): status_card_cache[ulang.lang_code] = ( - await generate_status_card( - bot=await get_bots_data(), - hardware=await get_hardware_data(), - liteyuki=await get_liteyuki_data(), - lang=ulang.lang_code, - motto=dict(zip(["text", "source"], random_yanlun())), - bot_id=bot.self_id, + ( + await generate_status_card_markdown( + bot=await get_bots_data(), + hardware=await get_hardware_data(ulang.lang_code), + liteyuki=await get_liteyuki_data(), + lang=ulang.lang_code, + motto=dict(zip(["text", "source"], random_yanlun())), + ) + if result.options["markdown"].value + else ( + await generate_status_card( + bot=await get_bots_data(), + hardware=await get_hardware_data(ulang.lang_code), + liteyuki=await get_liteyuki_data(), + lang=ulang.lang_code, + motto=dict(zip(["text", "source"], random_yanlun())), + bot_id=bot.self_id, + ) + ) ), time.time(), ) diff --git a/src/nonebot_plugins/trimo_plugin_msctconverter/mspvexec.py b/src/nonebot_plugins/trimo_plugin_msctconverter/mspvexec.py index 47e2922..c0f7edb 100644 --- a/src/nonebot_plugins/trimo_plugin_msctconverter/mspvexec.py +++ b/src/nonebot_plugins/trimo_plugin_msctconverter/mspvexec.py @@ -53,6 +53,7 @@ from .msctexec import ( add_memory_to_temporary, read_memory_from_temporary, get_stored_path, + get_user_lang, ) from .utils import hanzi_timeid @@ -116,6 +117,7 @@ async def _( nonebot.logger.info(result.options) usr_id = event.get_user_id() + ulang = get_user_lang(usr_id) superuser_permission = await SUPERUSER(bot, event) @@ -124,9 +126,10 @@ async def _( ): await mspv_sync.finish( UniMessage.text( - "转换点数不足,当前剩余:⌊p⌋≈{:.2f}|{}".format( - qres[1], - configdict["maxPersonConvert"]["music"], + ulang.get( + "convet.not_enough_point", + NOW=qres[1], + TOTAL=configdict["maxPersonConvert"]["music"], ) ), at_sender=True, @@ -168,12 +171,18 @@ async def _( ) ): await mspv_sync.finish( - UniMessage.text("服务器内未存入你的任何文件,请先上传midi文件吧") + UniMessage.text(ulang.get("convert.no_file", TYPE="midi")) ) if _args["mode"] not in [0, 1, 2, 3, 4]: await mspv_sync.finish( - UniMessage.text("模式 {} 不存在,请详阅文档。".format(_args["mode"])) + UniMessage.text( + ulang.get( + "convert.something_not_exist", + WHAT="模式", + NAME=_args["mode"], + ) + ) ) if _args["get-value-method"] not in [ @@ -182,7 +191,11 @@ async def _( ]: await mspv_sync.finish( UniMessage.text( - "取值法 {} 不存在,请详阅文档。".format(_args["get-value-method"]) + ulang.get( + "convert.something_not_exist", + WHAT="取值法", + NAME=_args["get-value-method"], + ) ) ) @@ -212,7 +225,11 @@ async def _( pitched_notechart.update(json.load(_ppnt.open("r"))) else: await mspv_sync.finish( - UniMessage.text("乐器对照表 {} 不存在".format(_args["pitched-note-table"])) + ulang.get( + "convert.something_not_exist", + WHAT="乐音乐器对照表", + NAME=_args["pitched-note-table"], + ) ) return @@ -240,7 +257,11 @@ async def _( else: await mspv_sync.finish( UniMessage.text( - "乐器对照表 {} 不存在".format(_args["percussion-note-table"]) + ulang.get( + "convert.something_not_exist", + WHAT="打击乐器对照表", + NAME=_args["percussion-note-table"], + ) ) ) return @@ -257,7 +278,11 @@ async def _( else: await mspv_sync.finish( UniMessage.text( - "音量处理曲线 {} 不存在".format(_args["volume-processing-function"]) + ulang.get( + "convert.something_not_exist", + WHAT="音量处理曲线", + NAME=_args["volume-processing-function"], + ) ) ) return @@ -274,10 +299,10 @@ async def _( random.random() % 1.6 + 1.3, ) if not res: - buffer.write("中途退出,转换点不足:{}\n".format(pnt)) + buffer.write(ulang.get("convert.break.not_enough_point", NOW=pnt)) return res - await mspv_sync.send(UniMessage.text("转换开始……")) + await mspv_sync.send(UniMessage.text(ulang.get("convert.start"))) try: diff --git a/src/resources/trim_plugin_msctconverter/lang/zh-CN.lang b/src/resources/trim_plugin_msctconverter/lang/zh-CN.lang index a0df149..47e2e89 100644 --- a/src/resources/trim_plugin_msctconverter/lang/zh-CN.lang +++ b/src/resources/trim_plugin_msctconverter/lang/zh-CN.lang @@ -12,7 +12,7 @@ writefile.write_success=文件{NAME}已写入{SIZE}字节 convet.not_enough_point=转换点数不足,当前剩余:⌊p⌋≈{NOW:.2f}|{TOTAL} convert.break.not_enough_point=中途退出,转换点不足:{NOW} convert.no_file=服务器内未存入你的任何文件,请先上传{TYPE}文件吧 -convert.something_not_exist={WHAT} {NAME} 不存在 +convert.something_not_exist={WHAT} {NAME} 不存在,请详阅文档。 convert.start=转换开始…… cmd2struct.axis_wrong=生成结构的生成方向格式错误,输入数据应符合“轴正负”(如x+、z-)的格式。 diff --git a/src/resources/trim_plugin_msctconverter/lang/zh-WY.lang b/src/resources/trim_plugin_msctconverter/lang/zh-WY.lang index 308470c..20b0ffb 100644 --- a/src/resources/trim_plugin_msctconverter/lang/zh-WY.lang +++ b/src/resources/trim_plugin_msctconverter/lang/zh-WY.lang @@ -13,6 +13,6 @@ convet.not_enough_point=点阙,余{NOW:.2f},满{TOTAL} convert.break.not_enough_point=点阙而不可继,现{NOW} convert.no_file=无案机内,先传之{TYPE} convert.table_not_exist={WHAT}曰 {NAME} 者虚 -convert.start=始…… +convert.start=始变之…… cmd2struct.axis_wrong=产型误指,应合此法,曰“轴正负”,类x+、z-。 diff --git a/src/resources/vanilla_language/lang/en.lang b/src/resources/vanilla_language/lang/en.lang index 8c31470..2de85f2 100644 --- a/src/resources/vanilla_language/lang/en.lang +++ b/src/resources/vanilla_language/lang/en.lang @@ -30,8 +30,8 @@ liteyuki.list_resources=Resource Pack List liteyuki.reload_resources_success=Resource reload successful, {NUM} resource packs in total liteyuki.loaded_resources={NUM} resource packs loaded, sorted by priority liteyuki.unloaded_resources=Unloaded resource packs -liteyuki.load_resource_success=Resource pack {NAME} loaded successfully -liteyuki.unload_resource_success=Resource pack {NAME} unloaded successfully +liteyuki.load_resource_success=Resource pack {NAME} successfully loaded +liteyuki.unload_resource_success=Resource pack {NAME} successfully unloaded liteyuki.load_resource_failed=Failed to load resource pack {NAME} liteyuki.unload_resource_failed=Failed to unload resource pack {NAME} liteyuki.resource_not_found=Resource pack {NAME} does not exist or is not operable @@ -39,12 +39,12 @@ liteyuki.resource_already_loaded=Resource pack {NAME} already loaded, do not rep liteyuki.resource_already_unloaded=Resource pack {NAME} already unloaded, do not repeat operation liteyuki.need_reload=Please {BTN} reload to apply these updates liteyuki.dont_repeat=Do not repeat operation -liteyuki.change_priority_success=Resource pack {NAME} priority changed successfully +liteyuki.change_priority_success=Resource pack {NAME} priority successfully changed liteyuki.change_priority_failed=Failed to change priority of resource pack {NAME} liteyuki.group_already=Group {GROUP} is already {STATUS}, no need to repeat operation liteyuki.group_success=Group {GROUP} {STATUS} successful liteyuki.permission_denied=Permission denied -liteyuki.config_remove_success=Configuration {KEY} removed successfully +liteyuki.config_remove_success=Configuration {KEY} successfully removed main.current_language=Current configuration language is: {LANG} main.enable_webdash=Web monitoring panel enabled: {URL} @@ -75,14 +75,14 @@ npm.uninstall=Uninstall npm.installing=Installing {NAME} npm.cannot_uninstall=Cannot Uninstall npm.no_description=No Description -npm.store_update_success=Plugin store data updated successfully +npm.store_update_success=Plugin store data successfully updated npm.store_update_failed=Plugin store data update failed npm.search_result=Search Result npm.search_no_result=No search result npm.too_many_results=Too many items, {HIDE_NUM} items hidden, please limit the keyword search -npm.install_success={NAME} installed successfully +npm.install_success={NAME} has been successfully installed npm.install_failed={NAME} installation failed, please check the log for detailed information. If you cannot resolve it, visit {HOMEPAGE} for help -npm.uninstall_success={NAME} uninstalled successfully, effective next restart +npm.uninstall_success={NAME} successfully uninstalled, effective after next restart npm.uninstall_failed={NAME} uninstallation failed npm.load_failed={NAME} loading failed, please check the console for detailed information, check if dependencies or configurations are correct, if cannot resolve, visit {HOMEPAGE} for help npm.plugin_not_found={NAME} not found in the store, please try updating the store information or checking the spelling @@ -122,7 +122,7 @@ user.profile.location.desc=Set user location information user.profile.nickname=Nickname user.profile.nickname.desc=Set how the bot calls the user user.profile.input_value=Please enter the value of {ATTR} -user.profile.set_success={ATTR} set to {VALUE} successfully +user.profile.set_success={ATTR} has been successfully set to {VALUE} user.profile.set_failed=Failed to set {ATTR}, please check the input legality rpm.move_up=Move Up @@ -157,3 +157,31 @@ status.cores=Core(s) status.threads=Thread(s) status.process=Processe(s) status.description=Liteyuki Dashboard + +status.cpubrand.amd=AMD +status.cpubrand.intel=Intel +status.cpubrand.apple=Apple +status.cpubrand.qualcomm=Qualcomm +status.cpubrand.mediatek=MediaTeK +status.cpubrand.samsung=SamSung +status.cpubrand.nvidia=NVidia +status.cpubrand.huawei=Huawei +status.cpubrand.unknown=Unknown + +status.arch.unknown=?? +status.disk.other=Virtual and Other Disk + +status.unit.GHz=GHz +status.unit.Byte=B +status.unit.binary_middile=i +status.unit.Bit_Units= ;K;M;G;T;P;E;Z;Y;R;Q + +yanlun.refresh.success=Yanlun cuccessfully updated to {COUNT} pieces now. +yanlun.refresh.failed=Error {ERR} occured in updating Yanlun with code {ERRCODE} +yanlun.errtype.net=Connection Error +yanlun.errtype.unknown=Unknown Error +yanlun.count.head=FromtttCount(Percentage) +yanlun.count.tail=...({NUM} in Total) +yanlun.length.toolong=Too many Yanlun to display +yanlun.length.tooshort=Too few Yanlun to display +yanlun.length.float=The number of Yanlun must be an integer, not a float diff --git a/src/resources/vanilla_language/lang/zh-CN.lang b/src/resources/vanilla_language/lang/zh-CN.lang index bf93aa6..62c91d0 100644 --- a/src/resources/vanilla_language/lang/zh-CN.lang +++ b/src/resources/vanilla_language/lang/zh-CN.lang @@ -155,15 +155,33 @@ status.minutes=分 status.seconds=秒 status.cores=核心 status.threads=线程 -status.process=进程 +status.process=进程占用 status.description=轻雪机器人状态面板 +status.cpubrand.amd=超微 +status.cpubrand.intel=英特尔 +status.cpubrand.apple=苹果 +status.cpubrand.qualcomm=高通 +status.cpubrand.mediatek=联发科 +status.cpubrand.samsung=三星 +status.cpubrand.nvidia=英伟达 +status.cpubrand.huawei=华为 +status.cpubrand.unknown=未知处理器 + +status.arch.unknown=未知架构 +status.disk.other=虚拟磁盘及其他 + +status.unit.GHz=吉赫兹 +status.unit.Byte=字节 +status.unit.binary_middile=二幂 +status.unit.Bit_Units= ;千;兆;吉;太;拍;艾;泽;尧;容;昆 + yanlun.refresh.success=言·论 更新成功,共 {COUNT} 条 yanlun.refresh.failed=更新 言·论 信息发生 {ERR} 错误:{ERRCODE} yanlun.errtype.net=互联网连接 yanlun.errtype.unknown=未知 yanlun.count.head=出处ttt数量(占比) yanlun.count.tail=...(共 {NUM} 条) -yanlun.length.toolong=言·论过长 -yanlun.length.tooshort=言·论过短 -yanlun.length.float=言·论不可是非整数长度 +yanlun.length.toolong=言·论过多 +yanlun.length.tooshort=言·论过少 +yanlun.length.float=言·论数量不可为非整数 diff --git a/src/resources/vanilla_language/lang/zh-HK.lang b/src/resources/vanilla_language/lang/zh-HK.lang index de108fa..aa812dc 100644 --- a/src/resources/vanilla_language/lang/zh-HK.lang +++ b/src/resources/vanilla_language/lang/zh-HK.lang @@ -155,4 +155,33 @@ status.minutes=分鐘 status.seconds=秒 status.cores=核心 status.threads=線程 -status.process=進程 \ No newline at end of file +status.process=進程所占用 +status.description=轻雪 Bot 狀態面板 + +status.cpubrand.amd=超威 +status.cpubrand.intel=英特爾 +status.cpubrand.apple=蘋果 +status.cpubrand.qualcomm=高通 +status.cpubrand.mediatek=聯發科 +status.cpubrand.samsung=三星 +status.cpubrand.nvidia=英偉達 +status.cpubrand.huawei=華為 +status.cpubrand.unknown=未知處理器 + +status.arch.unknown=未知架構 +status.disk.other=虛擬磁碟和其他 + +status.unit.GHz=吉赫茲 +status.unit.Byte=位元組 +status.unit.binary_middile=二進 +status.unit.Bit_Units= ;千;百萬;吉;兆;拍;艾;皆;佑;羅;昆 + +yanlun.refresh.success=言·論 成功更新得 {COUNT} 條 +yanlun.refresh.failed=言·論因 {ERR} 其 {ERRCODE} 而無法更新 +yanlun.errtype.net=網際網路連結 +yanlun.errtype.unknown=不可知 +yanlun.count.head=出處ttt數目(比例) +yanlun.count.tail=...(縂 {NUM} 條) +yanlun.length.toolong=言·論數目不可過多 +yanlun.length.tooshort=言·論數目不可為無或負 +yanlun.length.float=言·論數目不可謂為小數 diff --git a/src/resources/vanilla_language/lang/zh-WY.lang b/src/resources/vanilla_language/lang/zh-WY.lang index 772c5ac..58c17c7 100644 --- a/src/resources/vanilla_language/lang/zh-WY.lang +++ b/src/resources/vanilla_language/lang/zh-WY.lang @@ -148,14 +148,14 @@ status.usage=计用 status.total=合 status.used=占 status.free=余 -status.runtime=所启时分 +status.runtime=运期 status.days=日 status.hours=小时 status.minutes=分 status.seconds=秒 -status.cores=轮核 -status.threads=程线 -status.process=行轨 +status.cores=核 +status.threads=线程 +status.process=进程占 status.description=轻雪灵机台 yanlun.refresh.success=言·论 方新,合{COUNT}条 diff --git a/src/resources/vanilla_resource/templates/img/bg1.jpg b/src/resources/vanilla_resource/templates/img/bg1.jpg index 3c884f7..809a8ef 100644 Binary files a/src/resources/vanilla_resource/templates/img/bg1.jpg and b/src/resources/vanilla_resource/templates/img/bg1.jpg differ diff --git a/src/resources/vanilla_resource/templates/img/bg4.jpg b/src/resources/vanilla_resource/templates/img/bg4.jpg index 5e93522..21986bc 100644 Binary files a/src/resources/vanilla_resource/templates/img/bg4.jpg and b/src/resources/vanilla_resource/templates/img/bg4.jpg differ diff --git a/src/resources/vanilla_resource/templates/js/status.js b/src/resources/vanilla_resource/templates/js/status.js index 4344c7a..b6747d9 100644 --- a/src/resources/vanilla_resource/templates/js/status.js +++ b/src/resources/vanilla_resource/templates/js/status.js @@ -1,9 +1,12 @@ const data = JSON.parse(document.getElementById("data").innerText); const bot_data = data["bot"]; // 机器人数据 -const hardwareData = data["hardware"]; // 硬件数据 -const liteyukiData = data["liteyuki"]; // LiteYuki数据 -const localData = data["localization"]; // 本地化语言数据 +const hardware_data = data["hardware"]; // 硬件数据 +const liteyuki_data = data["liteyuki"]; // LiteYuki数据 +const local_data = data["localization"]; // 本地化语言数据 const motto_ = data["motto"]; // 言论数据 +const acknowledgement = data["acknowledgement"]; // 鸣谢内容数据 +const o_units = local_data["units"]; // 单位的翻译 +const bin_units = o_units["Bin_Units"]; // 字节单位(千、兆…) /** * 创建CPU/内存/交换饼图 @@ -64,15 +67,20 @@ function createPieChartOption(title, data) { }; } -function convertSize(size, precision = 2, addUnit = true, suffix = " X字节") { +function convertSize( + size, + precision = 2, + addUnit = true, + suffix = ` X${o_units["Byte"]}` +) { let isNegative = size < 0; size = Math.abs(size); - let units = ["", "千", "兆", "吉", "太", "拍", "艾", "泽"]; + // let units = ["", "千", "兆", "吉", "太", "拍", "艾", "泽"]; let unit = ""; - for (let i = 0; i < units.length; i++) { + for (let i = 0; i < bin_units.length; i++) { if (size < 1024) { - unit = units[i]; + unit = bin_units[i]; break; } size /= 1024; @@ -125,7 +133,7 @@ function secondsToTextTime(seconds) { let hours = Math.floor((seconds % 86400) / 3600); let minutes = Math.floor((seconds % 3600) / 60); let seconds_ = Math.floor(seconds % 60); - return `${days}${localData["days"]} ${hours}${localData["hours"]} ${minutes}${localData["minutes"]} ${seconds_}${localData["seconds"]}`; + return `${days}${local_data["days"]} ${hours}${local_data["hours"]} ${minutes}${local_data["minutes"]} ${seconds_}${local_data["seconds"]}`; } // 主函数 @@ -140,15 +148,17 @@ function main() { // 设置机器人信息 botInfoDiv.className = "info-box bot-info"; - botInfoDiv.querySelector(".bot-icon-img").setAttribute("src", bot["icon"]); + botInfoDiv + .querySelector(".bot-icon-img") + .setAttribute("src", bot["icon"]); botInfoDiv.querySelector(".bot-name").innerText = bot["name"]; let tagArray = [ bot["protocol_name"], `${bot["app_name"]}`, - `${localData["groups"]}${bot["groups"]}`, - `${localData["friends"]}${bot["friends"]}`, - `${localData["message_sent"]}${bot["message_sent"]}`, - `${localData["message_received"]}${bot["message_received"]}`, + `${local_data["groups"]}${bot["groups"]}`, + `${local_data["friends"]}${bot["friends"]}`, + `${local_data["message_sent"]}${bot["message_sent"]}`, + `${local_data["message_received"]}${bot["message_received"]}`, ]; // 添加一些标签 tagArray.forEach((tag, index) => { @@ -156,7 +166,10 @@ function main() { tagSpan.className = "bot-tag"; tagSpan.innerText = tag; // 给最后一个标签不添加后缀 - tagSpan.setAttribute("suffix", index === 0 || tag[0] == "\n" ? "0" : "1"); + tagSpan.setAttribute( + "suffix", + index === 0 || tag[0] == "\n" ? "0" : "1" + ); botInfoDiv.querySelector(".bot-tags").appendChild(tagSpan); }); document.body.insertBefore( @@ -176,24 +189,27 @@ function main() { .setAttribute("src", "./img/litetrimo.png"); liteyukiInfoDiv.querySelector( ".bot-name" - ).innerText = `${liteyukiData["name"]} - 睿乐`; + ).innerText = `${liteyuki_data["name"]} - 睿乐`; let tagArray = [ - `灵温 ${liteyukiData["version"]}`, - `Nonebot ${liteyukiData["nonebot"]}`, - `${liteyukiData["python"]}`, - liteyukiData["system"], - `${localData["plugins"]}${liteyukiData["plugins"]}`, - `${localData["resources"]}${liteyukiData["resources"]}`, - `${localData["bots"]}${liteyukiData["bots"]}`, - `${localData["runtime"]} ${secondsToTextTime(liteyukiData["runtime"])}`, + `灵温 ${liteyuki_data["version"]}`, + `Nonebot ${liteyuki_data["nonebot"]}`, + `${liteyuki_data["python"]}`, + liteyuki_data["system"], + `${local_data["plugins"]}${liteyuki_data["plugins"]}`, + `${local_data["resources"]}${liteyuki_data["resources"]}`, + `${local_data["bots"]}${liteyuki_data["bots"]}`, + `${local_data["runtime"]} ${secondsToTextTime(liteyuki_data["runtime"])}`, ]; tagArray.forEach((tag, index) => { let tagSpan = document.createElement("span"); tagSpan.className = "bot-tag"; tagSpan.innerText = tag; // 给最后一个标签不添加后缀 - tagSpan.setAttribute("suffix", index === 0 || tag[0] == "\n" ? "0" : "1"); + tagSpan.setAttribute( + "suffix", + index === 0 || tag[0] == "\n" ? "0" : "1" + ); liteyukiInfoDiv.querySelector(".bot-tags").appendChild(tagSpan); }); document.body.insertBefore( @@ -202,27 +218,27 @@ function main() { ); // 插入对象 // 添加硬件信息 - const cpuData = hardwareData["cpu"]; - const memData = hardwareData["memory"]; - const swapData = hardwareData["swap"]; + const cpuData = hardware_data["cpu"]; + const memData = hardware_data["memory"]; + const swapData = hardware_data["swap"]; const cpuTagArray = [ cpuData["name"], - `${cpuData["cores"]}${localData["cores"]} ${cpuData["threads"]}${localData["threads"]}`, - `${(cpuData["freq"] / 1000).toFixed(2)}吉赫兹`, + `${cpuData["cores"]}${local_data["cores"]} ${cpuData["threads"]}${local_data["threads"]}`, + `${(cpuData["freq"] / 1000).toFixed(2)}${o_units["GHz"]}`, ]; const memTagArray = [ - `${localData["process"]} ${convertSize(memData["usedProcess"])}`, - `${localData["used"]} ${convertSize(memData["used"])}`, - `${localData["free"]} ${convertSize(memData["free"])}`, - `${localData["total"]} ${convertSize(memData["total"])}`, + `${local_data["process"]} ${convertSize(memData["usedProcess"])}`, + `${local_data["used"]} ${convertSize(memData["used"])}`, + `${local_data["free"]} ${convertSize(memData["free"])}`, + `${local_data["total"]} ${convertSize(memData["total"])}`, ]; const swapTagArray = [ - `${localData["used"]} ${convertSize(swapData["used"])}`, - `${localData["free"]} ${convertSize(swapData["free"])}`, - `${localData["total"]} ${convertSize(swapData["total"])}`, + `${local_data["used"]} ${convertSize(swapData["used"])}`, + `${local_data["free"]} ${convertSize(swapData["free"])}`, + `${local_data["total"]} ${convertSize(swapData["total"])}`, ]; let cpuDeviceInfoDiv = document.importNode( document.getElementById("device-info").content, @@ -237,8 +253,12 @@ function main() { true ); - cpuDeviceInfoDiv.querySelector(".device-info").setAttribute("id", "cpu-info"); - memDeviceInfoDiv.querySelector(".device-info").setAttribute("id", "mem-info"); + cpuDeviceInfoDiv + .querySelector(".device-info") + .setAttribute("id", "cpu-info"); + memDeviceInfoDiv + .querySelector(".device-info") + .setAttribute("id", "mem-info"); swapDeviceInfoDiv .querySelector(".device-info") .setAttribute("id", "swap-info"); @@ -276,7 +296,10 @@ function main() { tagDiv.className = "device-tag"; tagDiv.innerText = tag; // 给最后一个标签不添加后缀 - tagDiv.setAttribute("suffix", index === tagArray.length - 1 ? "0" : "1"); + tagDiv.setAttribute( + "suffix", + index === tagArray.length - 1 ? "0" : "1" + ); devices[device].querySelector(".device-tags").appendChild(tagDiv); }); } @@ -292,7 +315,7 @@ function main() { cpuChart.setOption( createPieChartOption( - `${localData["cpu"]}\n${cpuData["percent"].toFixed(1)}%`, + `${local_data["cpu"]}\n${cpuData["percent"].toFixed(1)}%`, [ { name: "used", value: cpuData["percent"] }, { name: "free", value: 100 - cpuData["percent"] }, @@ -302,10 +325,13 @@ function main() { memChart.setOption( createPieChartOption( - `${localData["memory"]}\n${memData["percent"].toFixed(1)}%`, + `${local_data["memory"]}\n${memData["percent"].toFixed(1)}%`, [ { name: "process", value: memData["usedProcess"] }, - { name: "used", value: memData["used"] - memData["usedProcess"] }, + { + name: "used", + value: memData["used"] - memData["usedProcess"], + }, { name: "free", value: memData["free"] }, ] ) @@ -313,7 +339,7 @@ function main() { swapChart.setOption( createPieChartOption( - `${localData["swap"]}\n${swapData["percent"].toFixed(1)}%`, + `${local_data["swap"]}\n${swapData["percent"].toFixed(1)}%`, [ { name: "used", value: swapData["used"] }, { name: "free", value: swapData["free"] }, @@ -322,24 +348,28 @@ function main() { ); // 磁盘信息 - const diskData = hardwareData["disk"]; + const diskData = hardware_data["disk"]; diskData.forEach((disk) => { - let diskTitle = `${localData['free']} ${convertSize(disk['free'])} ${localData['total']} ${convertSize(disk['total'])}`; - let diskDiv = createBarChart(diskTitle, disk['percent'], disk['name']); + let diskTitle = `${local_data["free"]} ${convertSize(disk["free"])} ${ + local_data["total"] + } ${convertSize(disk["total"])}`; + let diskDiv = createBarChart(diskTitle, disk["percent"], disk["name"]); // 最后一个把margin-bottom去掉 if (disk === diskData[diskData.length - 1]) { diskDiv.style.marginBottom = "0"; } - document.getElementById('disk-info').appendChild(diskDiv); + document.getElementById("disk-info").appendChild(diskDiv); }); // 随机一言 - let mottoText = motto_["text"]; - let mottoFrom = motto_["source"]; - document.getElementById("motto-text").innerText = mottoText; - document.getElementById("motto-from").innerText = mottoFrom; + // let mottoText = ; + // let mottoFrom = ; + document.getElementById("motto-text").innerText = motto_["text"]; + document.getElementById("motto-from").innerText = motto_["source"]; // 致谢 - document.getElementById("addition-info").innerText = - "感谢 锅炉 云裳工作室 提供服务器支持"; + if (acknowledgement.length > 0) { + document.getElementById("addition-info").innerText = acknowledgement; + // "感谢 锅炉 云裳工作室 提供服务器支持"; + } } main(); @@ -351,4 +381,4 @@ window.addEventListener('resize', () => { updateDiskNameWidth(diskInfo); }); }); -*/ \ No newline at end of file +*/ diff --git a/src/resources/vanilla_resource/templates/status.md b/src/resources/vanilla_resource/templates/status.md new file mode 100644 index 0000000..fb1b9dc --- /dev/null +++ b/src/resources/vanilla_resource/templates/status.md @@ -0,0 +1,50 @@ + + +

{local_description}

+ +

  {liteyuki_name} - 睿乐

+ + - 灵温 {liteyuki_version} | Nonebot {liteyuki_nonebot} + - {liteyuki_system} {liteyuki_python} + - {local_plugins}{liteyuki_plugins} | {local_resources}{liteyuki_resources} + - {local_bots}{liteyuki_bots} + - {local_runtime}{liteyuki_runtime} + + +### **{bot_name}  |  ** + + - {bot_app_name} : {bot_protocol_name} + - {local_groups}{bot_groups} | {local_friends}{bot_friends} | {local_message_sent}{bot_message_sent} | {local_message_received}{bot_message_received} + +## {local_cpu} : {hardware_cpu_percent}% + + - {hardware_cpu_name} | {hardware_cpu_cores}{local_cores} {hardware_cpu_threads}{local_threads} | {hardware_cpu_freq}{local_units_GHz} + + +## {local_memory} : {hardware_memory_percent}% + + - {local_process} {hardware_memory_processmem} + - {local_used} {hardware_memory_usedmem} + - {local_free} {hardware_memory_freemem} + - {local_total} {hardware_memory_totalmem} + +## {local_swap} : {hardware_swap_percent}% + + - {local_used} {hardware_swap_usedswap} + - {local_free} {hardware_swap_freeswap} + - {local_total} {hardware_swap_totalswap} + +## {local_disk} + + - {hardware_disk_name} - {local_used} {hardware_disk_useddisk} | {hardware_disk_freedisk} | {local_total} {hardware_disk_totaldisk} + +----------------------- +
END.
+ +### {motto_text} + +
——{motto_source}
+ +####
{acknowledgement}
+ +####
该页样式由 金羿Eilles 设计
\ No newline at end of file diff --git a/src/utils/base/config.py b/src/utils/base/config.py index 85737e4..0f0a63c 100644 --- a/src/utils/base/config.py +++ b/src/utils/base/config.py @@ -32,6 +32,7 @@ class BasicConfig(BaseModel): command_start: list[str] = ["/", ""] nickname: list[str] = [f"灵温-{random_hex_string(6)}"] default_language: str = "zh-WY" + default_interact_language: str = "zh-CN" satori: SatoriConfig = SatoriConfig() data_path: str = "data/liteyuki" chromium_path: str = ( @@ -43,6 +44,7 @@ class BasicConfig(BaseModel): else "/usr/bin/chromium-browser" ) ) + status_acknowledgement: str = "" def load_from_yaml(file_: str) -> dict: diff --git a/src/utils/base/language.py b/src/utils/base/language.py index 5c4071b..d5d277c 100644 --- a/src/utils/base/language.py +++ b/src/utils/base/language.py @@ -104,7 +104,7 @@ def load_from_dict(data: dict, lang_code: str): class Language: # 三重fallback - # 用户语言 > 默认语言/系统语言 > zh-CN + # 用户语言 > 默认语言/系统语言 > zh-CN | en def __init__(self, lang_code: str = None, fallback_lang_code: str = None): self.lang_code = lang_code @@ -117,6 +117,12 @@ class Language: "default_language", get_system_lang_code() ) + self.__fallback_list = ( + self.lang_code, + self.fallback_lang_code, + "en" if "en" in self.lang_code else "zh-CN", + ) + def _get(self, item: str, *args, **kwargs) -> str | Any: """ 获取当前语言文本,kwargs中的default参数为默认文本 @@ -133,15 +139,14 @@ class Language: """ default = kwargs.pop("default", None) - fallback = (self.lang_code, self.fallback_lang_code, "zh-CN") - for lang_code in fallback: + for lang_code in self.__fallback_list: if lang_code in _language_data and item in _language_data[lang_code]: trans: str = _language_data[lang_code][item] try: return trans.format(*args, **kwargs) except Exception as e: - nonebot.logger.warning(f"Failed to format language data: {e}") + nonebot.logger.warning("因 {} 无法格式化本地化数据".format(e)) return trans return default or item @@ -203,7 +208,7 @@ def get_user_lang(user_id: str) -> Language: user_id, default=User(user_id=user_id, username="Unknown"), ) - lang_code = user.profile.get("lang", get_default_lang_code()) + lang_code = user.profile.get("lang", get_default_user_lang_code()) _user_lang[user_id] = lang_code return Language(_user_lang[user_id]) @@ -225,6 +230,13 @@ def get_default_lang_code() -> str: return get_config("default_language", default=get_system_lang_code()) +def get_default_user_lang_code() -> str: + """ + 获取默认用户语言代码,和上面的默认语言不同,此处为显示给用户的语言 + """ + return get_config("default_interact_language", default=get_default_lang_code()) + + def get_all_lang() -> dict[str, str]: """ 获取所有语言 diff --git a/src/utils/base/log.py b/src/utils/base/log.py index 65362bf..1b96900 100644 --- a/src/utils/base/log.py +++ b/src/utils/base/log.py @@ -20,18 +20,18 @@ def default_filter(record: "Record"): # DEBUG日志格式 debug_format: str = ( - "{time:YYYY-MM-DD HH:mm:ss} " - "[{level.icon}] " - "<{name}.{module}.{function}:{line}> " - "{message}" + "{time:YYYY-MM-DD HH:mm:ss} " + "[{level.icon}] " + "<{name}.{module}.{function}:{line}> " + "{message}" ) # 默认日志格式 default_format: str = ( - "{time:MM-DD HH:mm:ss} " - "[{level.icon}] " - "<{name}> " - "{message}" + "{time:MM-DD HH:mm:ss} " + "[{level.icon}] " + "<{name}> " + "{message}" ) @@ -74,6 +74,10 @@ def init_log(): logger.level("DEBUG", color="", icon=f"{'🐛' if show_icon else ''}{debug}") logger.level("INFO", color="", icon=f"{'ℹ️' if show_icon else ''}{info}") - logger.level("SUCCESS", color="", icon=f"{'✅' if show_icon else ''}{success}") - logger.level("WARNING", color="", icon=f"{'⚠️' if show_icon else ''}{warning}") + logger.level( + "SUCCESS", color="", icon=f"{'✅' if show_icon else ''}{success}" + ) + logger.level( + "WARNING", color="", icon=f"{'⚠️' if show_icon else ''}{warning}" + ) logger.level("ERROR", color="", icon=f"{'⭕' if show_icon else ''}{error}")