mirror of
https://github.com/LiteyukiStudio/LiteyukiBot.git
synced 2024-11-23 07:57:37 +08:00
✨ 独立status插件...
This commit is contained in:
parent
ece71ca1e7
commit
53bc6df30f
@ -48,7 +48,7 @@ for lang in get_all_lang():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@scheduler.scheduled_job("cron", second="*/20")
|
@scheduler.scheduled_job("cron", minute="*/20")
|
||||||
async def _():
|
async def _():
|
||||||
nonebot.logger.info("数据已刷新")
|
nonebot.logger.info("数据已刷新")
|
||||||
for lang_code in get_all_lang():
|
for lang_code in get_all_lang():
|
||||||
|
@ -0,0 +1,195 @@
|
|||||||
|
import platform
|
||||||
|
import time
|
||||||
|
|
||||||
|
import nonebot
|
||||||
|
import psutil
|
||||||
|
from cpuinfo import cpuinfo
|
||||||
|
from liteyuki.utils import __NAME__, __VERSION__
|
||||||
|
from liteyuki.utils.base.data_manager import TempConfig, common_db
|
||||||
|
from liteyuki.utils.base.language import Language
|
||||||
|
from liteyuki.utils.base.resource import get_path
|
||||||
|
from liteyuki.utils.message.html_tool import template2image
|
||||||
|
|
||||||
|
protocol_names = {
|
||||||
|
0: "iPad",
|
||||||
|
1: "Android Phone",
|
||||||
|
2: "Android Watch",
|
||||||
|
3: "Mac",
|
||||||
|
5: "iPad",
|
||||||
|
6: "Android Pad",
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
Universal Interface
|
||||||
|
data
|
||||||
|
- bot
|
||||||
|
- name: str
|
||||||
|
icon: str
|
||||||
|
id: int
|
||||||
|
protocol_name: str
|
||||||
|
groups: int
|
||||||
|
friends: int
|
||||||
|
message_sent: int
|
||||||
|
message_received: int
|
||||||
|
app_name: str
|
||||||
|
- hardware
|
||||||
|
- cpu
|
||||||
|
- percent: float
|
||||||
|
- name: str
|
||||||
|
- mem
|
||||||
|
- percent: float
|
||||||
|
- total: int
|
||||||
|
- used: int
|
||||||
|
- free: int
|
||||||
|
- swap
|
||||||
|
- percent: float
|
||||||
|
- total: int
|
||||||
|
- used: int
|
||||||
|
- free: int
|
||||||
|
- disk: list
|
||||||
|
- name: str
|
||||||
|
- percent: float
|
||||||
|
- total: int
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
async def generate_status_card(bot: dict, hardware: dict, liteyuki: dict, lang="zh-CN", bot_id="0") -> bytes:
|
||||||
|
return await template2image(
|
||||||
|
get_path("templates/status.html", abs_path=True),
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"bot" : bot,
|
||||||
|
"hardware" : hardware,
|
||||||
|
"liteyuki" : liteyuki,
|
||||||
|
"localization": get_local_data(lang)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
debug=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_local_data(lang_code) -> dict:
|
||||||
|
lang = Language(lang_code)
|
||||||
|
return {
|
||||||
|
"friends" : lang.get("status.friends"),
|
||||||
|
"groups" : lang.get("status.groups"),
|
||||||
|
"plugins" : lang.get("status.plugins"),
|
||||||
|
"message_sent" : lang.get("status.message_sent"),
|
||||||
|
"message_received": lang.get("status.message_received"),
|
||||||
|
"cpu" : lang.get("status.cpu"),
|
||||||
|
"memory" : lang.get("status.memory"),
|
||||||
|
"swap" : lang.get("status.swap"),
|
||||||
|
"disk" : lang.get("status.disk"),
|
||||||
|
|
||||||
|
"usage" : lang.get("status.usage"),
|
||||||
|
"total" : lang.get("status.total"),
|
||||||
|
"used" : lang.get("status.used"),
|
||||||
|
"free" : lang.get("status.free"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def get_bots_data(self_id: str = "0") -> dict:
|
||||||
|
"""获取当前所有机器人数据
|
||||||
|
Returns:
|
||||||
|
"""
|
||||||
|
result = {
|
||||||
|
"self_id": self_id,
|
||||||
|
"bots" : [],
|
||||||
|
}
|
||||||
|
for bot_id, bot in nonebot.get_bots().items():
|
||||||
|
groups = 0
|
||||||
|
friends = 0
|
||||||
|
status = {}
|
||||||
|
bot_name = bot_id
|
||||||
|
version_info = {}
|
||||||
|
try:
|
||||||
|
# API fetch
|
||||||
|
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 = None
|
||||||
|
bot_data = {
|
||||||
|
"name" : bot_name,
|
||||||
|
"icon" : icon,
|
||||||
|
"id" : bot_id,
|
||||||
|
"protocol_name" : protocol_names.get(version_info.get("protocol_name"), "Online"),
|
||||||
|
"groups" : groups,
|
||||||
|
"friends" : friends,
|
||||||
|
"message_sent" : statistics.get("message_sent"),
|
||||||
|
"message_received": statistics.get("message_received"),
|
||||||
|
"app_name" : app_name
|
||||||
|
}
|
||||||
|
result["bots"].append(bot_data)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def get_hardware_data() -> dict:
|
||||||
|
mem = psutil.virtual_memory()
|
||||||
|
swap = psutil.swap_memory()
|
||||||
|
cpu_brand_raw = cpuinfo.get_cpu_info().get("brand_raw", "Unknown")
|
||||||
|
if "AMD" in cpu_brand_raw:
|
||||||
|
brand = "AMD"
|
||||||
|
elif "Intel" in cpu_brand_raw:
|
||||||
|
brand = "Intel"
|
||||||
|
else:
|
||||||
|
brand = "Unknown"
|
||||||
|
result = {
|
||||||
|
"cpu" : {
|
||||||
|
"percent": psutil.cpu_percent(),
|
||||||
|
"name" : f"{brand} {cpuinfo.get_cpu_info().get('arch', 'Unknown')}"
|
||||||
|
},
|
||||||
|
"mem" : {
|
||||||
|
"percent": mem.percent,
|
||||||
|
"total" : mem.total,
|
||||||
|
"used" : mem.used,
|
||||||
|
"free" : mem.free
|
||||||
|
},
|
||||||
|
"swap": {
|
||||||
|
"percent": swap.percent,
|
||||||
|
"total" : swap.total,
|
||||||
|
"used" : swap.used,
|
||||||
|
"free" : swap.free
|
||||||
|
},
|
||||||
|
"disk": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
for disk in psutil.disk_partitions(all=True):
|
||||||
|
try:
|
||||||
|
disk_usage = psutil.disk_usage(disk.mountpoint)
|
||||||
|
result["disk"].append({
|
||||||
|
"name" : disk.mountpoint,
|
||||||
|
"percent": disk_usage.percent,
|
||||||
|
"total" : disk_usage.total,
|
||||||
|
"used" : disk_usage.used,
|
||||||
|
"free" : disk_usage.free
|
||||||
|
})
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def get_liteyuki_data() -> dict:
|
||||||
|
temp_data: TempConfig = common_db.first(TempConfig(), default=TempConfig())
|
||||||
|
result = {
|
||||||
|
"name" : __NAME__,
|
||||||
|
"version": __VERSION__,
|
||||||
|
"plugins": len(nonebot.get_loaded_plugins()),
|
||||||
|
"nonebot": f"{nonebot.__version__}",
|
||||||
|
"python" : f"{platform.python_implementation()} {platform.python_version()}",
|
||||||
|
"system" : f"{platform.system()} {platform.release()}",
|
||||||
|
"runtime": time.time() - temp_data.data.get("start_time", time.time()), # 运行时间秒数
|
||||||
|
}
|
||||||
|
return result
|
@ -1,12 +1,18 @@
|
|||||||
from nonebot import require
|
from nonebot import require
|
||||||
|
|
||||||
|
from liteyuki.utils.base.resource import get_path
|
||||||
|
from liteyuki.utils.message.html_tool import template2image
|
||||||
|
from liteyuki.utils.base.language import get_user_lang
|
||||||
|
from .api import *
|
||||||
|
from ...utils.base.ly_typing import T_Bot, T_MessageEvent
|
||||||
|
|
||||||
require("nonebot_plugin_alconna")
|
require("nonebot_plugin_alconna")
|
||||||
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Subcommand, Arparma
|
from nonebot_plugin_alconna import on_alconna, Alconna, Args, Subcommand, Arparma, UniMessage
|
||||||
|
|
||||||
status_alc = on_alconna(
|
status_alc = on_alconna(
|
||||||
aliases={"status"},
|
aliases={"#状态"},
|
||||||
command=Alconna(
|
command=Alconna(
|
||||||
"status",
|
"#status",
|
||||||
Subcommand(
|
Subcommand(
|
||||||
"memory",
|
"memory",
|
||||||
alias={"mem", "m", "内存"},
|
alias={"mem", "m", "内存"},
|
||||||
@ -19,6 +25,19 @@ status_alc = on_alconna(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@status_alc.handle()
|
||||||
|
async def _(event: T_MessageEvent, bot: T_Bot):
|
||||||
|
ulang = get_user_lang(event.user_id)
|
||||||
|
image = await generate_status_card(
|
||||||
|
bot=await get_bots_data(),
|
||||||
|
hardware=await get_hardware_data(),
|
||||||
|
liteyuki=await get_liteyuki_data(),
|
||||||
|
lang=ulang.lang_code,
|
||||||
|
bot_id=bot.self_id
|
||||||
|
)
|
||||||
|
await status_alc.finish(UniMessage.image(raw=image))
|
||||||
|
|
||||||
|
|
||||||
@status_alc.assign("memory")
|
@status_alc.assign("memory")
|
||||||
async def _():
|
async def _():
|
||||||
print("memory")
|
print("memory")
|
||||||
|
@ -133,3 +133,17 @@ rpm.move_top=置顶
|
|||||||
weather.city_not_found=未找到城市 {CITY}
|
weather.city_not_found=未找到城市 {CITY}
|
||||||
weather.weather_not_found=未找到城市 {CITY} 的天气信息
|
weather.weather_not_found=未找到城市 {CITY} 的天气信息
|
||||||
weather.no_key=未设置天气api key,请在配置文件添加weather_key
|
weather.no_key=未设置天气api key,请在配置文件添加weather_key
|
||||||
|
|
||||||
|
status.friends=好友
|
||||||
|
status.groups=群
|
||||||
|
status.plugins=插件
|
||||||
|
status.message_sent=发送消息
|
||||||
|
status.message_received=接收消息
|
||||||
|
status.cpu=处理器
|
||||||
|
status.memory=内存
|
||||||
|
status.swap=交换空间
|
||||||
|
status.disk=磁盘
|
||||||
|
status.usage=使用率
|
||||||
|
status.total=总计
|
||||||
|
status.used=已用
|
||||||
|
status.free=空闲
|
@ -1,9 +1,84 @@
|
|||||||
const data = JSON.parse(document.getElementById('data').innerText);
|
const data = JSON.parse(document.getElementById('data').innerText);
|
||||||
|
const bot_data = data['bot']; // 机器人数据
|
||||||
|
const hardware_data = data['hardware']; // 硬件数据
|
||||||
|
const liteyuki_data = data['liteyuki']; // LiteYuki数据
|
||||||
|
const local_data = data['localization']; // 本地化语言数据
|
||||||
|
|
||||||
function createPieChartOption(title, data){
|
console.log(data)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建饼图
|
||||||
|
* @param title
|
||||||
|
* @param {Array<{name: string, value: number}>} data 数据
|
||||||
|
*/
|
||||||
|
function createPieChartOption(title, data) {
|
||||||
// data为各项占比列表
|
// data为各项占比列表
|
||||||
|
return {
|
||||||
|
animation: false,
|
||||||
|
title: {
|
||||||
|
text: title,
|
||||||
|
left: 'center',
|
||||||
|
top: 'center',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 30
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true,
|
||||||
|
trigger: 'item',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
},
|
||||||
|
color: data.length === 3 ? ['#00a6ff', '#a2d8f4', "#ffffff44"] : ['#a2d8f4', '#ffffff44'],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'info',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['80%', '100%'],
|
||||||
|
center: ['50%', '50%'],
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
label: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
textStyle: {
|
||||||
|
fontSize: '50',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBarChartOption(title, percent){
|
/**
|
||||||
|
* 创建柱状图
|
||||||
|
* @param title
|
||||||
|
* @param percent 数据
|
||||||
|
*/
|
||||||
|
function createBarChartOption(title, percent) {
|
||||||
// percent为百分比,最大值为100
|
// percent为百分比,最大值为100
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 主函数
|
||||||
|
function main() {
|
||||||
|
bot_data['bots'].forEach(
|
||||||
|
(bot, index) => {
|
||||||
|
let botInfoDiv = document.importNode(document.getElementById('bot-template').content, true)
|
||||||
|
document.body.insertBefore(botInfoDiv, document.getElementById('hardware-info'))
|
||||||
|
botInfoDiv.className = 'info-box bot-info'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
@ -7,9 +7,24 @@
|
|||||||
<link rel="stylesheet" href="./css/status.css">
|
<link rel="stylesheet" href="./css/status.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<template id="bot-template">
|
||||||
|
<div class="info-box bot-info">
|
||||||
|
<div id="bot-icon">
|
||||||
|
<img id="bot-icon-img" src="" alt="">
|
||||||
|
</div>
|
||||||
|
<div id="bot-detail">
|
||||||
|
<div id="bot-name">
|
||||||
|
Liteyuki
|
||||||
|
</div>
|
||||||
|
<div id="bot-tags">
|
||||||
|
<!-- tag span-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="data-storage" id="data">{{ data | tojson }}</div>
|
<div class="data-storage" id="data">{{ data | tojson }}</div>
|
||||||
<div class="info-box" id="system-info"></div>
|
<div class="info-box" id="hardware-info"></div>
|
||||||
<div class="info-box" id="disk-info"></div>
|
<div class="info-box" id="disk-info"></div>
|
||||||
<div class="info-box" id="motto-info"></div>
|
<div class="info-box" id="motto-info"></div>
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import json
|
|||||||
import os.path
|
import os.path
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
import nonebot
|
import nonebot
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ import requests
|
|||||||
|
|
||||||
from liteyuki.utils.base.config import load_from_yaml, config
|
from liteyuki.utils.base.config import load_from_yaml, config
|
||||||
from liteyuki.utils.base.log import init_log
|
from liteyuki.utils.base.log import init_log
|
||||||
from liteyuki.utils.base.data_manager import auto_migrate
|
from liteyuki.utils.base.data_manager import TempConfig, auto_migrate, common_db
|
||||||
|
|
||||||
major, minor, patch = map(int, __VERSION__.split("."))
|
major, minor, patch = map(int, __VERSION__.split("."))
|
||||||
__VERSION_I__ = major * 10000 + minor * 100 + patch
|
__VERSION_I__ = major * 10000 + minor * 100 + patch
|
||||||
@ -54,6 +55,10 @@ def init():
|
|||||||
if sys.version_info < (3, 10):
|
if sys.version_info < (3, 10):
|
||||||
nonebot.logger.error("This project requires Python3.10+ to run, please upgrade your Python Environment.")
|
nonebot.logger.error("This project requires Python3.10+ to run, please upgrade your Python Environment.")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
temp_data: TempConfig = common_db.first(TempConfig(), default=TempConfig())
|
||||||
|
temp_data.data["start_time"] = time.time()
|
||||||
|
common_db.upsert(temp_data)
|
||||||
|
|
||||||
auto_migrate()
|
auto_migrate()
|
||||||
# 在加载完成语言后再初始化日志
|
# 在加载完成语言后再初始化日志
|
||||||
nonebot.logger.info("Liteyuki is initializing...")
|
nonebot.logger.info("Liteyuki is initializing...")
|
||||||
|
@ -6,10 +6,10 @@ from .data import Database, LiteModel, Database
|
|||||||
|
|
||||||
DATA_PATH = "data/liteyuki"
|
DATA_PATH = "data/liteyuki"
|
||||||
|
|
||||||
user_db = Database(os.path.join(DATA_PATH, "users.ldb"))
|
user_db: Database = Database(os.path.join(DATA_PATH, "users.ldb"))
|
||||||
group_db = Database(os.path.join(DATA_PATH, "groups.ldb"))
|
group_db: Database = Database(os.path.join(DATA_PATH, "groups.ldb"))
|
||||||
plugin_db = Database(os.path.join(DATA_PATH, "plugins.ldb"))
|
plugin_db: Database = Database(os.path.join(DATA_PATH, "plugins.ldb"))
|
||||||
common_db = Database(os.path.join(DATA_PATH, "common.ldb"))
|
common_db: Database = Database(os.path.join(DATA_PATH, "common.ldb"))
|
||||||
|
|
||||||
|
|
||||||
class User(LiteModel):
|
class User(LiteModel):
|
||||||
|
@ -47,7 +47,7 @@ def load_resource_from_dir(path: str):
|
|||||||
_loaded_resource_packs.insert(0, ResourceMetadata(**metadata))
|
_loaded_resource_packs.insert(0, ResourceMetadata(**metadata))
|
||||||
|
|
||||||
|
|
||||||
def get_path(path: str, abs_path: bool = False, default: Any = None, debug: bool=False) -> str | Any:
|
def get_path(path: str, abs_path: bool = True, default: Any = None, debug: bool=False) -> str | Any:
|
||||||
"""
|
"""
|
||||||
获取资源包中的文件
|
获取资源包中的文件
|
||||||
Args:
|
Args:
|
||||||
|
@ -62,7 +62,6 @@ async def template2image(
|
|||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
# 重载资源
|
# 重载资源
|
||||||
load_resources()
|
|
||||||
|
|
||||||
raw_html = await template_to_html(
|
raw_html = await template_to_html(
|
||||||
template_name=template_name,
|
template_name=template_name,
|
||||||
|
1
main.py
1
main.py
@ -9,7 +9,6 @@ from liteyuki.utils.base.ly_api import liteyuki_api
|
|||||||
init()
|
init()
|
||||||
|
|
||||||
store_config: dict = common_db.first(StoredConfig(), default=StoredConfig()).config
|
store_config: dict = common_db.first(StoredConfig(), default=StoredConfig()).config
|
||||||
|
|
||||||
static_config = load_from_yaml("config.yml")
|
static_config = load_from_yaml("config.yml")
|
||||||
store_config.update(static_config)
|
store_config.update(static_config)
|
||||||
nonebot.init(**store_config)
|
nonebot.init(**store_config)
|
||||||
|
Loading…
Reference in New Issue
Block a user