diff --git a/liteyuki/liteyuki_main/runtime.py b/liteyuki/liteyuki_main/runtime.py index 62723cb0..fdbcef3f 100644 --- a/liteyuki/liteyuki_main/runtime.py +++ b/liteyuki/liteyuki_main/runtime.py @@ -1,3 +1,4 @@ +import json import platform import nonebot @@ -7,15 +8,17 @@ from nonebot import on_command from nonebot.adapters.onebot.v11 import MessageSegment from nonebot.permission import SUPERUSER -from liteyuki.utils import __NAME__, __VERSION__ +from liteyuki.utils import __NAME__, __VERSION__, load_from_yaml from liteyuki.utils.htmlrender import template2image -from liteyuki.utils.language import get_user_lang +from liteyuki.utils.language import Language, get_default_lang, get_user_lang from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent from liteyuki.utils.resource import get_path from liteyuki.utils.tools import convert_size stats = on_command("stats", aliases={"状态"}, priority=5, permission=SUPERUSER) +config = load_from_yaml("config.yml") + protocol_names = { 0: "iPad", 1: "Android Phone", @@ -29,19 +32,108 @@ protocol_names = { @stats.handle() async def _(bot: T_Bot, event: T_MessageEvent): ulang = get_user_lang(str(event.user_id)) - fake_device_info: dict = bot.config.dict().get("fake_device_info", {}) - mem_total = fake_device_info.get('mem', {}).get('total', psutil.virtual_memory().total) + image = await template2image( + get_path("templates/stats.html", abs_path=True), + { + "data": await get_stats_data(bot.self_id, ulang.lang_code) + }, + debug=True + ) + await stats.finish(MessageSegment.image(image)) + + +async def get_bots_data(ulang: Language, self_id: "") -> list: + bots_data = [] + for bot_id, bot in nonebot.get_bots().items(): + groups = 0 + friends = 0 + status = {} + bot_name = bot_id + version_info = {} + try: + bot_name = (await bot.get_login_info())["nickname"] + groups = len(await bot.get_group_list()) + friends = len(await bot.get_friend_list()) + status = await bot.get_status() + version_info = await bot.get_version_info() + except Exception: + pass + + statistics = status.get("stat", {}) + app_name = version_info.get("app_name", "UnknownImplementation") + if app_name in ["Lagrange.OneBot", "LLOneBot", "Shamrock"]: + icon = f"https://q.qlogo.cn/g?b=qq&nk={bot_id}&s=640" + else: + icon = "./img/liteyuki.png" + bot_data = { + "name": bot_name, + "icon": icon, + "id" : bot_id, + "tags": [ + protocol_names.get(version_info.get("protocol_name"), "Online"), + f"{ulang.get('liteyuki.stats.groups')} {groups}", + f"{ulang.get('liteyuki.stats.friends')} {friends}", + f"{ulang.get('liteyuki.stats.sent')} {statistics.get('message_sent', 0)}", + f"{ulang.get('liteyuki.stats.received')} {statistics.get('message_received', 0)}", + app_name, + + ], + "self": bot_id == self_id, # 判断是否是自己 + } + bots_data.append(bot_data) + bots_data.append( + { + "name": "Liteyuki", + "icon": "./img/liteyuki.png", + "id" : "liteyuki", + "tags": [ + f"{__NAME__} {__VERSION__}", + f"{ulang.get('liteyuki.stats.plugins')} {len(nonebot.get_loaded_plugins())}", + f"Nonebot {nonebot.__version__}", + f"{platform.python_implementation()} {platform.python_version()}", + ] + } + ) + return bots_data + + +async def get_stats_data(self_id: str = None, lang: str = None): + if self_id is None: + self_id = list(nonebot.get_bots().keys())[0] if len(nonebot.get_bots()) > 0 else "liteyuki" + if lang is None: + ulang = get_default_lang() + else: + ulang = Language(lang) + + fake_device_info: dict = config.get("fake_device_info", {}) + + mem_info = psutil.virtual_memory() + mem_total = fake_device_info.get('mem', {}).get('total', mem_info.total) + + convert_size(mem_total, 1, False) + mem_total_show = convert_size(mem_total, 1) # 格式化带单位 mem_used_bot = psutil.Process().memory_info().rss - mem_used_other = psutil.virtual_memory().used - mem_used_bot - mem_free = mem_total - mem_used_other - mem_used_bot + mem_used_bot_show = convert_size(mem_used_bot, 1) + mem_used_other = mem_info.used - mem_used_bot + mem_free = mem_total - mem_info.used + mem_used_show = convert_size(mem_total - mem_used_bot - mem_used_other, 1) # 计算已用格式化带单位 - groups = len(await bot.get_group_list()) - friends = len(await bot.get_friend_list()) + swap_info = psutil.swap_memory() - status = await bot.get_status() - statistics = status.get("stat", {}) - version_info = await bot.get_version_info() + disk_data = [] + for disk in psutil.disk_partitions(all=True): + disk_usage = psutil.disk_usage(disk.mountpoint) + disk_total_show = convert_size(disk_usage.total, 1) + disk_free_show = convert_size(disk_usage.free, 1) + disk_data.append( + { + "name" : disk.device, + "total" : disk_total_show, + "free" : disk_free_show, + "percent": disk_usage.percent, + } + ) cpu_info = get_cpu_info() if "AMD" in cpu_info.get("brand_raw", ""): @@ -56,7 +148,7 @@ async def _(bot: T_Bot, event: T_MessageEvent): cpu_info = get_cpu_info() templ = { - "CPUDATA" : [ + "cpu" : [ { "name" : "USED", "value": psutil.cpu_percent(interval=1) @@ -66,7 +158,7 @@ async def _(bot: T_Bot, event: T_MessageEvent): "value": 100 - psutil.cpu_percent(interval=1) } ], - "MEMDATA" : [ + "mem" : [ { "name" : "OTHER", @@ -81,7 +173,7 @@ async def _(bot: T_Bot, event: T_MessageEvent): "value": mem_used_bot }, ], - "SWAPDATA" : [ + "swap" : [ { "name" : "USED", "value": psutil.swap_memory().used @@ -91,44 +183,30 @@ async def _(bot: T_Bot, event: T_MessageEvent): "value": psutil.swap_memory().free } ], - "BOT_ID" : bot.self_id, - "BOT_NAME" : (await bot.get_login_info())["nickname"], - "BOT_TAGS" : [ - protocol_names.get(version_info.get("protocol_name"), "Online"), - f"{ulang.get('liteyuki.stats.plugins')} {len(nonebot.get_loaded_plugins())}", - f"{ulang.get('liteyuki.stats.groups')} {groups}", - f"{ulang.get('liteyuki.stats.friends')} {friends}", - f"{ulang.get('liteyuki.stats.sent')} {statistics.get('message_sent', 0)}", - f"{ulang.get('liteyuki.stats.received')} {statistics.get('message_received', 0)}", - f"{__NAME__} {__VERSION__}", - f"Nonebot {nonebot.__version__}", - f"{platform.python_implementation()} {platform.python_version()}", - version_info.get("app_name"), - ], - "CPU_TAGS" : [ + "disk" : disk_data, # list[{"name":"C", "total":100, "used":50, "free":50}] + "bot" : await get_bots_data(ulang, self_id), + "cpuTags" : [ f"{brand} {cpu_info.get('arch', 'Unknown')}", f"{fake_device_info.get('cpu', {}).get('cores', psutil.cpu_count(logical=False))}C " f"{fake_device_info.get('cpu', {}).get('logical_cores', psutil.cpu_count(logical=True))}T", f"{fake_device_info.get('cpu', {}).get('frequency', psutil.cpu_freq().current) / 1000}GHz" ], - "MEM_TAGS" : [ - f"Bot {convert_size(mem_used_bot, 1)}", - f"{ulang.get('main.monitor.used')} {convert_size(mem_used_other + mem_used_bot, 1)}", - f"{ulang.get('main.monitor.total')} {convert_size(mem_total, 1)}", + "memTags" : [ + f"Bot {mem_used_bot_show}", + f"{ulang.get('main.monitor.used')} {mem_used_show}", + f"{ulang.get('main.monitor.total')} {mem_total_show}", + f"{ulang.get('main.monitor.free')} {convert_size(mem_free, 1)}", ], - "SWAP_TAGS": [ - f"{ulang.get('main.monitor.used')} {convert_size(psutil.swap_memory().used, 1)}", - f"{ulang.get('main.monitor.total')} {convert_size(psutil.swap_memory().total, 1)}", + "swapTags" : [ + f"{ulang.get('main.monitor.used')} {convert_size(swap_info.used, 1)}", + f"{ulang.get('main.monitor.total')} {convert_size(swap_info.total, 1)}", + f"{ulang.get('main.monitor.free')} {convert_size(swap_info.free, 1)}", ], - "CPU" : ulang.get("main.monitor.cpu"), - "MEM" : ulang.get("main.monitor.memory"), - "SWAP" : ulang.get("main.monitor.swap"), + "cpu_trans" : ulang.get("main.monitor.cpu"), + "mem_trans" : ulang.get("main.monitor.memory"), + "swap_trans" : ulang.get("main.monitor.swap"), + "used_trans" : ulang.get("main.monitor.used"), + "free_trans" : ulang.get("main.monitor.free"), + "total_trans": ulang.get("main.monitor.total"), } - image_bytes = await template2image( - template=get_path("templates/stats.html", abs_path=True), - templates=templ, - scale_factor=1, - debug=True - ) - # await md.send_image(image_bytes, bot, event=event) - await stats.finish(MessageSegment.image(image_bytes)) + return templ diff --git a/liteyuki/plugins/liteyuki_weather/models.py b/liteyuki/plugins/liteyuki_weather/models.py index 3937f986..0b6340b2 100644 --- a/liteyuki/plugins/liteyuki_weather/models.py +++ b/liteyuki/plugins/liteyuki_weather/models.py @@ -1,4 +1,4 @@ - +from nonebot import on_command from liteyuki.utils.data import LiteModel @@ -11,3 +11,30 @@ class WeatherNow(LiteModel): time: str = "" city: str = "" + +weather = on_command("weather", aliases={"天气", "查天气", "天气预报", "查天气预报"}) +weather_now = on_command("weather_now", aliases={"实时天气", "查实时天气", "实时天气预报", "查实时天气预报"}) +weather_forecast = on_command("weather_forecast", aliases={"天气预报", "查天气预报", "未来天气", "查未来天气"}) +weather_warning = on_command("weather_warning", aliases={"天气预警", "查天气预警", "天气警告", "查天气警告"}) +weather_life = on_command("weather_life", aliases={"生活指数", "查生活指数", "生活指数预报", "查生活指数预报"}) +weather_air = on_command("weather_air", aliases={"空气质量", "查空气质量", "空气质量预报", "查空气质量预报"}) +weather_rain = on_command("weather_rain", aliases={"降雨预报", "查降雨预报", "降雨量", "查降雨量"}) +weather_snow = on_command("weather_snow", aliases={"降雪预报", "查降雪预报", "降雪量", "查降雪量"}) + + +@weather.handle() +async def handle_weather(bot, event): + args = str(event.get_message()).strip() + if not args: + await weather.finish("请输入要查询的城市") + else: + pass + + +@weather_now.handle() +async def handle_weather_now(bot, event): + pass + +@weather_forecast.handle() +async def handle_weather_forecast(bot, event): + pass diff --git a/liteyuki/resources/fonts/bold.ttf b/liteyuki/resources/fonts/bold.ttf deleted file mode 100644 index eda4bea1..00000000 Binary files a/liteyuki/resources/fonts/bold.ttf and /dev/null differ diff --git a/liteyuki/resources/fonts/heavy.ttf b/liteyuki/resources/fonts/heavy.ttf deleted file mode 100644 index 16d5c2b1..00000000 Binary files a/liteyuki/resources/fonts/heavy.ttf and /dev/null differ diff --git a/liteyuki/resources/fonts/normal.ttf b/liteyuki/resources/fonts/normal.ttf deleted file mode 100644 index efaedf2a..00000000 Binary files a/liteyuki/resources/fonts/normal.ttf and /dev/null differ diff --git a/liteyuki/resources/fonts/thin.ttf b/liteyuki/resources/fonts/thin.ttf deleted file mode 100644 index 17dd2a50..00000000 Binary files a/liteyuki/resources/fonts/thin.ttf and /dev/null differ diff --git a/liteyuki/resources/lang/de.lang b/liteyuki/resources/lang/de.lang index 43559e5e..09bcdccb 100644 --- a/liteyuki/resources/lang/de.lang +++ b/liteyuki/resources/lang/de.lang @@ -97,4 +97,5 @@ user.profile.set_failed={ATTR} festlegen fehlgeschlagen. Bitte überprüfen Sie, liteyuki.image_mode_on=Markdown-Bild liteyuki.image_mode_off=Markdown-Link -npm.page=Page {PAGE}/{TOTAL} \ No newline at end of file +npm.page=Page {PAGE}/{TOTAL} +main.monitor.free=Free \ No newline at end of file diff --git a/liteyuki/resources/lang/en.lang b/liteyuki/resources/lang/en.lang index ff5c223c..cc18e2a3 100644 --- a/liteyuki/resources/lang/en.lang +++ b/liteyuki/resources/lang/en.lang @@ -1,10 +1,10 @@ language.name=English -log.debug=Debug -log.info=Info -log.warning=Warning -log.error=Error -log.success=Success +log.debug=DEBUG +log.info=INFO +log.warning=WARNING +log.error=ERROR +log.success=SUCCESS liteyuki.restart=Restart liteyuki.restart_now=Restart Now @@ -97,4 +97,5 @@ user.profile.set_failed=Setting {ATTR} failed. Please check if the input is vali liteyuki.image_mode_on=Enable markdown image liteyuki.image_mode_off=Closed markdown image -npm.page=Page {PAGE}/{TOTAL} \ No newline at end of file +npm.page=Page {PAGE}/{TOTAL} +main.monitor.free=Free \ No newline at end of file diff --git a/liteyuki/resources/lang/es.lang b/liteyuki/resources/lang/es.lang index a345e7f4..742a3bdd 100644 --- a/liteyuki/resources/lang/es.lang +++ b/liteyuki/resources/lang/es.lang @@ -92,4 +92,10 @@ user.profile.nickname.desc=Establecer el apodo del Bot para el usuario user.profile.input_value=Por favor ingresa {ATTR} user.profile.set_success={ATTR} establecido correctamente a {VALUE} -user.profile.set_failed=Fallo al establecer {ATTR}. Por favor, verifica si la entrada es válida. \ No newline at end of file +user.profile.set_failed=Fallo al establecer {ATTR}. Por favor, verifica si la entrada es válida. + +liteyuki.image_mode_on=Markdown de imagen abierta +liteyuki.image_mode_off=Markdown de imagen cerrada + +npm.page=Página {PAGE}/{TOTAL} +main.monitor.free=Libre \ No newline at end of file diff --git a/liteyuki/resources/lang/fr.lang b/liteyuki/resources/lang/fr.lang index 59cf1b4d..0eabb100 100644 --- a/liteyuki/resources/lang/fr.lang +++ b/liteyuki/resources/lang/fr.lang @@ -92,4 +92,7 @@ user.profile.nickname.desc=Définir le pseudo du Bot pour l'utilisateur user.profile.input_value=Veuillez entrer {ATTR} user.profile.set_success={ATTR} défini avec succès sur {VALUE} -user.profile.set_failed=Échec de la définition de {ATTR}. Veuillez vérifier si l'entrée est valide. \ No newline at end of file +user.profile.set_failed=Échec de la définition de {ATTR}. Veuillez vérifier si l'entrée est valide. + +liteyuki.image_mode_on=Ouvert markdown image +liteyuki.image_mode_off=Fermé markdown image \ No newline at end of file diff --git a/liteyuki/resources/lang/zh-CN.lang b/liteyuki/resources/lang/zh-CN.lang index ce32624f..c9bd3517 100644 --- a/liteyuki/resources/lang/zh-CN.lang +++ b/liteyuki/resources/lang/zh-CN.lang @@ -97,4 +97,5 @@ user.profile.set_failed=设置 {ATTR} 失败,请检查输入是否合法 liteyuki.image_mode_on=开启Markdown图片模式 liteyuki.image_mode_off=关闭Markdown图片模式 -npm.page=第{PAGE}/{TOTAL}页 \ No newline at end of file +npm.page=第{PAGE}/{TOTAL}页 +main.monitor.free=空闲 \ No newline at end of file diff --git a/liteyuki/resources/templates/css/fonts.css b/liteyuki/resources/templates/css/fonts.css index f33f5267..f80e5eef 100644 --- a/liteyuki/resources/templates/css/fonts.css +++ b/liteyuki/resources/templates/css/fonts.css @@ -1,13 +1,54 @@ +/*MiSans*/ + @font-face { font-family: 'MiSans'; - src: url('../../fonts/normal.ttf') format('truetype'); + src: url('../fonts/MiSans/MiSans-Normal.woff2') format('truetype'); font-weight: normal; - font-style: normal; } @font-face { font-family: 'MiSans'; - src: url('../../fonts/bold.ttf') format('truetype'); + src: url('../fonts/MiSans/MiSans-Bold.woff2') format('truetype'); font-weight: bold; - font-style: normal; } + +/*MapleMono*/ +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-Light.woff2') format('truetype'); + font-weight: 200; +} + +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-LightItalic.woff2') format('truetype'); + font-weight: 200; + font-style: italic; +} + + +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-Regular.woff2') format('truetype'); + font-weight: 400; +} + +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-Italic.woff2') format('truetype'); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-Bold.woff2') format('truetype'); + font-weight: 700; +} + +@font-face { + font-family: 'MapleMono'; + src: url('../fonts/MapleMono/MapleMono-BoldItalic.woff2') format('truetype'); + font-weight: 700; + font-style: italic; +} \ No newline at end of file diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Bold.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Bold.woff2 new file mode 100644 index 00000000..bedd45b5 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Bold.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-BoldItalic.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-BoldItalic.woff2 new file mode 100644 index 00000000..c4acc5af Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-BoldItalic.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Italic.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Italic.woff2 new file mode 100644 index 00000000..6b044cce Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Italic.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Light.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Light.woff2 new file mode 100644 index 00000000..e5f93c46 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Light.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-LightItalic.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-LightItalic.woff2 new file mode 100644 index 00000000..f8b95a6b Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-LightItalic.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Regular.woff2 b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Regular.woff2 new file mode 100644 index 00000000..cbbe6f8c Binary files /dev/null and b/liteyuki/resources/templates/fonts/MapleMono/MapleMono-Regular.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Bold.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Bold.woff2 new file mode 100644 index 00000000..f966f5af Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Bold.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Demibold.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Demibold.woff2 new file mode 100644 index 00000000..7cf38819 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Demibold.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-ExtraLight.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-ExtraLight.woff2 new file mode 100644 index 00000000..b93c8505 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-ExtraLight.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Heavy.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Heavy.woff2 new file mode 100644 index 00000000..2eb66cd6 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Heavy.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Light.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Light.woff2 new file mode 100644 index 00000000..6067ea25 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Light.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Medium.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Medium.woff2 new file mode 100644 index 00000000..993d1f6f Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Medium.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Normal.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Normal.woff2 new file mode 100644 index 00000000..ae0649f2 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Normal.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Regular.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Regular.woff2 new file mode 100644 index 00000000..7544be21 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Regular.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Semibold.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Semibold.woff2 new file mode 100644 index 00000000..e98f6cf2 Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Semibold.woff2 differ diff --git a/liteyuki/resources/templates/fonts/MiSans/MiSans-Thin.woff2 b/liteyuki/resources/templates/fonts/MiSans/MiSans-Thin.woff2 new file mode 100644 index 00000000..0ef3e88e Binary files /dev/null and b/liteyuki/resources/templates/fonts/MiSans/MiSans-Thin.woff2 differ diff --git a/liteyuki/resources/templates/img/bg2.jpg b/liteyuki/resources/templates/img/bg2.jpg new file mode 100644 index 00000000..75e9e44e Binary files /dev/null and b/liteyuki/resources/templates/img/bg2.jpg differ diff --git a/liteyuki/resources/templates/img/bg3.jpg b/liteyuki/resources/templates/img/bg3.jpg new file mode 100644 index 00000000..3e0f0781 Binary files /dev/null and b/liteyuki/resources/templates/img/bg3.jpg differ diff --git a/liteyuki/resources/templates/img/bg4.jpg b/liteyuki/resources/templates/img/bg4.jpg new file mode 100644 index 00000000..66229d15 Binary files /dev/null and b/liteyuki/resources/templates/img/bg4.jpg differ diff --git a/liteyuki/resources/templates/img/liteyuki.png b/liteyuki/resources/templates/img/liteyuki.png new file mode 100644 index 00000000..6512544c Binary files /dev/null and b/liteyuki/resources/templates/img/liteyuki.png differ diff --git a/liteyuki/resources/templates/stats.html b/liteyuki/resources/templates/stats.html index ede0fc03..24fb3534 100644 --- a/liteyuki/resources/templates/stats.html +++ b/liteyuki/resources/templates/stats.html @@ -1,13 +1,27 @@ - + - - Document + + Liteyuki Stats - -
- - BotIcon - - - - {{ BOT_NAME }} - -
-
-
-
-
-
+
+
-
-
+
+
-
-
+
+
- - - - - - - +
+
+ + diff --git a/liteyuki/utils/htmlrender.py b/liteyuki/utils/htmlrender.py index 5d8bd1e1..7347ae0e 100644 --- a/liteyuki/utils/htmlrender.py +++ b/liteyuki/utils/htmlrender.py @@ -31,6 +31,21 @@ from nonebot_plugin_htmlrender import * # """ # return await html_to_pic(html, wait=wait, template_path=template_path, scale_factor=scale_factor) +async def template2html( + template: str, + templates: dict, +) -> str: + """ + Args: + template: str: 模板文件 + **templates: dict: 模板参数 + Returns: + HTML 正文 + """ + template_path = os.path.dirname(template) + template_name = os.path.basename(template) + return await template_to_html(template_path, template_name, **templates) + async def template2image( template: str, @@ -81,3 +96,32 @@ async def template2image( wait=wait, device_scale_factor=scale_factor, ) + + +async def url2image( + url: str, + wait: int = 0, + scale_factor: float = 1, + type: str = "png", + quality: int = 100, + **kwargs +) -> bytes: + """ + Args: + quality: + type: + url: str: URL + wait: int: 等待时间 + scale_factor: float: 缩放因子 + **kwargs: page 参数 + Returns: + 图片二进制数据 + """ + async with get_new_page(scale_factor) as page: + await page.goto(url) + await page.wait_for_timeout(wait) + return await page.screenshot( + full_page=True, + type=type, + quality=quality + ) diff --git a/liteyuki/utils/log.py b/liteyuki/utils/log.py index 9e1db87c..f692f9ae 100644 --- a/liteyuki/utils/log.py +++ b/liteyuki/utils/log.py @@ -67,8 +67,8 @@ def init_log(): warning = lang.get("log.warning", default="WARNING") error = lang.get("log.error", default="==ERROR") - logger.level("DEBUG", color="", icon=f"{'*️⃣' if show_icon else ''}{debug}") - logger.level("INFO", color="", icon=f"{'ℹ️' if show_icon else ''}{info}") + 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("ERROR", color="", icon=f"{'⭕' if show_icon else ''}{error}") diff --git a/liteyuki/utils/tools.py b/liteyuki/utils/tools.py index 4b1ef66a..9def663a 100644 --- a/liteyuki/utils/tools.py +++ b/liteyuki/utils/tools.py @@ -15,13 +15,13 @@ def clamp(value: float, min_value: float, max_value: float) -> float | int: return max(min(value, max_value), min_value) -def convert_size(size: int, precision: int = 2, add_unit: bool = True, suffix: str = "iB") -> str: +def convert_size(size: int, precision: int = 2, add_unit: bool = True, suffix: str = " XiB") -> str | float: """把字节数转换为人类可读的字符串,计算正负 Args: add_unit: 是否添加单位,False后则suffix无效 - suffix: iB或B + suffix: XiB或XB precision: 浮点数的小数点位数 size (int): 字节数 @@ -29,23 +29,18 @@ def convert_size(size: int, precision: int = 2, add_unit: bool = True, suffix: s str: The human-readable string, e.g. "1.23 GB". """ - is_negative = False - if size < 0: - is_negative = True - size = -size - - for unit in ["", "K", "M", "G", "T", "P", "E", "Z", "Y"]: + is_negative = size < 0 + size = abs(size) + for unit in ("", "K", "M", "G", "T", "P", "E", "Z"): if size < 1024: - if add_unit: - result = f"{size:.{precision}f} {unit}" + suffix - return f"-{result}" if is_negative else result - else: - return f"{size:.{precision}f}" + break size /= 1024 + if is_negative: + size = -size if add_unit: - return f"{size:.{precision}f} Y" + suffix + return f"{size:.{precision}f}{suffix.replace('X', unit)}" else: - return f"{size:.{precision}f}" + return size def keywords_in_text(keywords: list[str], text: str, all_matched: bool) -> bool: diff --git a/requirements.txt b/requirements.txt index cc38fb72..59bcee80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,10 @@ aiohttp==3.9.3 aiofiles==23.2.1 -arclet-alconna==1.8.5 -arclet-alconna-tools==0.7.0 colored==2.2.4 dash==2.16.1 GitPython==3.1.42 -jinja2==3.1.3 -markdown==3.3.6 -nonebot2[fastapi]==2.2.1 +nonebot2[fastapi,httpx,websockets]==2.2.1 +nonebot-plugin-htmlrender==0.3.1 nonebot-adapter-onebot==2.4.3 nonebot-plugin-alconna==0.41.0 playwright==1.17.2 @@ -16,13 +13,9 @@ py-cpuinfo==9.0.0 pydantic==1.10.14 Pygments==2.17.2 pytz==2024.1 -python-markdown-math==0.8 -pymdown-extensions==10.7.1 PyYAML~=6.0.1 starlette~=0.36.3 loguru==0.7.2 importlib_metadata==7.0.2 requests==2.31.0 pillow==10.2.0 -pyppeteer==2.0.0 -weasyprint==61.2