-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
194efd1
commit 7a91f39
Showing
44 changed files
with
3,077 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Config, Render } from '#components' | ||
import { logger, karin } from 'node-karin' | ||
import { si } from '../models/State/utils.js' | ||
import { getData, getMonitorData } from '../models/State/index.js' | ||
|
||
let interval = false | ||
|
||
export const State = karin.command(/^#(铃)?(状态|status)(pro)?(debug)?$/i, async (e) => { | ||
if (!/铃/.test(e.msg) && !Config.state.default) return false | ||
|
||
if (!si) return e.reply('没有检测到systeminformation依赖,请运行:"pnpm add systeminformation -w"进行安装') | ||
|
||
// 防止多次触发 | ||
if (interval) { return false } else interval = true | ||
try { | ||
// 获取数据 | ||
const data = await getData(e) | ||
// 渲染图片 | ||
const img = await Render.render('state/index', { | ||
...data, | ||
scale: 1.4 | ||
}) | ||
await e.reply(img) | ||
} catch (error) { | ||
logger.error(error) | ||
interval = false | ||
} | ||
interval = false | ||
}, { name: '铃状态', priority: '-1' }) | ||
|
||
export const Monitor = karin.command(/^#?(监控|monitor)$/i, async (e) => { | ||
const data = await getMonitorData() | ||
const img = await Render.render('state/monitor', data, { | ||
e, | ||
scale: 1.4 | ||
}) | ||
return e.reply(img) | ||
}, { name: '监控', priority: '-1' }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# 是否设置为默认状态 | ||
default: false | ||
|
||
# 测试访问的网址列表(可空)设置为true或default将使用默认配置 | ||
# show: 是否显示 true - 显示 - false - 不显示 pro - 只有pro显示 | ||
# name: 显示名称 | ||
# url: 要访问的网址 | ||
# timeout: 测试超时时间 | ||
# useProxy: 是否使用插件配置中的代理访问 | ||
psTestSites: | ||
show: pro | ||
list: | ||
- name: Baidu | ||
url: https://baidu.com | ||
- name: Google | ||
url: https://google.com | ||
- name: Google(proxy) | ||
url: https://google.com | ||
useProxy: true | ||
timeout: 5000 | ||
|
||
# 监控任务 | ||
statusTask: true | ||
|
||
# 如果出现内存异常的情况可将此配置项开启,如果打开后报错请将监控任务关闭 | ||
statusPowerShellStart: false | ||
|
||
# 背景图片api,设置为false则一直使用默认背景 | ||
# CF跳板(会损失一点访问时间,但后期API地址可以自动更新) | ||
# http://dir.dengfenglai.icu | ||
# 默认地址(直连,但是不确定是否会GG) | ||
# https://t.mwm.moe/mp/ | ||
backdrop: "http://dir.dengfenglai.icu" | ||
|
||
# 当api请求失败时使用的默认背景图,请放置在resources/state/img/bg目录下 | ||
# random - 随机选择state/img/bg目录里的一张图片 | ||
# default_bg.jpg 可直接指定bg目录里一张图片,注意请带上后缀名 | ||
backdropDefault: "random" | ||
|
||
# 关闭node的那个圈圈 | ||
closedNodeInfo: true | ||
|
||
# 关闭图表 | ||
closedChart: false | ||
|
||
# 是否显示FastFetch 参数:true, false, pro ,default | ||
# true - 开启 | ||
# false - 关闭 | ||
# pro - 只有状态pro显示 | ||
# default - win默认只有pro显示,liunx等其他正常也会显示 | ||
showFastFetch: default | ||
|
||
# Bot昵称的颜色 | ||
BotNameColor: "#000" | ||
# Bot昵称渐变色 设置了该值BotNameColor值将无效 如要使用BotNameColor请将该值设为none或false | ||
# 该值请参考https://developer.mozilla.org/zh-CN/docs/Web/CSS/gradient/linear-gradient | ||
# xxdeg 为渐变角度 后为渐变颜色 | ||
# 原来花里胡哨的渐变271.14deg,#001bff 0.98%,#00f0ff 25.79%,#fce84a 47.33%,#f34628 65.77%,#b275ff 91.4% | ||
BotNameColorGradient: "none" | ||
|
||
#主硬件进度条和磁盘进度条的颜色 | ||
#严重 | ||
highColor: "#d73403" | ||
#警告 | ||
mediumColor: "#ffa500" | ||
#正常 | ||
lowColor: "#21E488" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import moment from 'moment' | ||
import { Version } from '#components' | ||
import { Bot, redis } from 'node-karin' | ||
import { getImgPalette } from './utils.js' | ||
|
||
export default async function getBotState (e) { | ||
const botList = _getBotList(e) | ||
const dataPromises = botList.map(async (i) => { | ||
const bot = Bot.getBot(i) | ||
const uin = bot?.account?.uin || bot?.uin | ||
if (!uin) return false | ||
|
||
const { status = 11, version } = bot | ||
|
||
const nickname = bot.nickname || bot.account.name || '未知' | ||
|
||
// 头像 | ||
const avatarUrl = bot.avatar ?? (Number(uin) ? `https://q1.qlogo.cn/g?b=qq&s=0&nk=${uin}` : 'default') | ||
const avatar = await getAvatarColor(avatarUrl) | ||
|
||
const platform = version?.version ?? '未知' | ||
|
||
const messageCount = await getMessageCount(bot) | ||
|
||
const countContacts = await getCountContacts(bot) | ||
|
||
let startTime = bot?.stat?.start_time || bot.adapter?.start_time || Math.floor(Date.now() / 1000) | ||
if (startTime > 999999999) { | ||
startTime = Math.floor(startTime / 1000) | ||
} | ||
const botRunTime = formatDuration(Math.floor(Date.now() / 1000) - startTime) | ||
const botVersion = `${version.name} v${version?.version || ''}` | ||
|
||
return { | ||
avatar, | ||
nickname, | ||
botRunTime, | ||
status, | ||
platform, | ||
botVersion, | ||
messageCount, | ||
countContacts | ||
} | ||
}) | ||
|
||
return Promise.all(dataPromises).then(r => r.filter(Boolean)) | ||
} | ||
|
||
async function getAvatarColor (url) { | ||
const defaultAvatar = `${Version.pluginPath}/resources/state/img/default_avatar.jpg` | ||
try { | ||
if (url == 'default') { | ||
url = defaultAvatar | ||
} | ||
const avatar = await getImgPalette(url) | ||
return avatar | ||
} catch { | ||
return { | ||
similarColor1: '#fff1eb', | ||
similarColor2: '#ace0f9', | ||
path: url | ||
} | ||
} | ||
} | ||
async function getMessageCount (bot) { | ||
const today = moment().format('YYYY-MM-DD') | ||
const keys = (() => { | ||
return [ | ||
`karin:count:send:${today}`, | ||
`karin:count:recv:${today}` | ||
] | ||
})() | ||
|
||
// const values = await redis.mGet(keys) || [] | ||
const values = [] | ||
for (const i of keys) { | ||
values.push(await redis.get(i)) | ||
} | ||
|
||
const sent = values[0] || bot.stat?.sent_msg_cnt || 0 | ||
const recv = values[1] || bot.stat?.recv_msg_cnt || 0 | ||
const screenshot = values[2] || values[3] || 0 | ||
|
||
return { | ||
sent: sent > 0 ? '发送: ' + sent : 0, | ||
recv: recv > 0 ? '接收: ' + recv : 0, | ||
screenshot | ||
} | ||
} | ||
|
||
async function getCountContacts (bot) { | ||
const friend = (await bot.GetFriendList?.())?.length || bot.fl?.size || 0 | ||
const group = (await bot.GetGroupList?.())?.length || bot.gl?.size || 0 | ||
const groupMember = Array.from(bot?.gml?.values() || []).reduce((acc, curr) => acc + curr.size, 0) | ||
return { | ||
friend: friend > 0 ? '好友: ' + friend : 0, | ||
group: group > 0 ? '群: ' + group : 0, | ||
groupMember | ||
} | ||
} | ||
|
||
function _getBotList (e) { | ||
/** bot列表 */ | ||
let BotList = [e.self_id] | ||
|
||
// TODO: 多账号支持 | ||
if (e.isPro) { | ||
BotList = Bot.getBotAll().map(i => i.account.uin) | ||
} | ||
return BotList | ||
} | ||
|
||
function formatDuration (seconds) { | ||
const duration = moment.duration(seconds, 'seconds') | ||
const days = Math.floor(duration.asDays()) | ||
const hours = duration.hours() | ||
const minutes = duration.minutes() | ||
const secs = duration.seconds() | ||
|
||
return `${days}天${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(secs).padStart(2, '0')}` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { si, Circle } from './utils.js' | ||
|
||
/** 获取CPU占用 */ | ||
export default async function getCpuInfo () { | ||
let { currentLoad: { currentLoad }, cpu, fullLoad } = await si.get({ | ||
currentLoad: 'currentLoad', | ||
cpu: 'manufacturer,speed,cores', | ||
fullLoad: '*' | ||
}) | ||
let { manufacturer, speed, cores } = cpu | ||
if (currentLoad == null || currentLoad == undefined) return false | ||
fullLoad = Math.round(fullLoad) | ||
manufacturer = manufacturer?.split(' ')?.[0] ?? 'unknown' | ||
return { | ||
...Circle(currentLoad / 100), | ||
inner: Math.round(currentLoad) + '%', | ||
title: 'CPU', | ||
info: [ | ||
`${manufacturer} ${cores}核 ${speed}GHz`, | ||
`CPU满载率 ${fullLoad}%` | ||
] | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Config, Version } from '#components' | ||
import child_process from 'child_process' | ||
import { logger } from 'node-karin' | ||
/** | ||
* 获取FastFetch | ||
* @param e | ||
*/ | ||
export default async function getFastFetch (e) { | ||
if (!isFeatureVisible(e.isPro)) return '' | ||
const ret = await execSync(`bash plugins/${Version.pluginName}/resources/state/state.sh`) | ||
if (ret.error) { | ||
logger.error(`[${Version.pluginName}][状态]Error FastFetch 请检查是否使用git bash启动${Version.BotName},错误信息:${ret.stderr || ret.stdout}`) | ||
return '' | ||
} | ||
return ret.stdout.trim() | ||
} | ||
function isFeatureVisible (isPro) { | ||
const { showFastFetch } = Config.state | ||
if (showFastFetch === true) return true | ||
if (showFastFetch === 'pro' && isPro) return true | ||
if (showFastFetch === 'default') { | ||
if (!isPlatformWin() || isPro) return true | ||
} | ||
return false | ||
} | ||
function isPlatformWin () { | ||
return process.platform === 'win32' | ||
} | ||
async function execSync (cmd) { | ||
return new Promise((resolve, reject) => { | ||
child_process.exec(cmd, (error, stdout, stderr) => { | ||
resolve({ error, stdout, stderr }) | ||
}) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import _ from 'lodash' | ||
import { getFileSize, si } from './utils.js' | ||
import Monitor from './Monitor.js' | ||
|
||
/** | ||
* 获取硬盘 | ||
*/ | ||
export async function getFsSize () { | ||
// 去重 | ||
const HardDisk = _.uniqWith(await si.fsSize(), | ||
(a, b) => | ||
a.used === b.used && a.size === b.size && a.use === b.use && a.available === b.available | ||
) | ||
.filter(item => item.size && item.used && item.available && item.use) | ||
// 为空返回false | ||
if (_.isEmpty(HardDisk)) return false | ||
// 数值转换 | ||
return HardDisk.map(item => { | ||
item.used = getFileSize(item.used) | ||
item.size = getFileSize(item.size) | ||
item.use = Math.round(item.use) | ||
item.color = 'var(--low-color)' | ||
if (item.use >= 90) { | ||
item.color = 'var(--high-color)' | ||
} else if (item.use >= 70) { | ||
item.color = 'var(--medium-color)' | ||
} | ||
return item | ||
}) | ||
} | ||
/** | ||
* 获取磁盘读写速度 | ||
* @returns {object | boolean} 返回一个对象,包含读速度(rx_sec)和写速度(wx_sec),如果无法获取则返回false。 | ||
*/ | ||
export function getDiskSpeed () { | ||
const fsStats = Monitor.fsStats | ||
if (!fsStats || fsStats.rx_sec == null || fsStats.wx_sec == null) { | ||
return false | ||
} | ||
return { | ||
rx_sec: getFileSize(fsStats.rx_sec, { showByte: false, showSuffix: false }), | ||
wx_sec: getFileSize(fsStats.wx_sec, { showByte: false, showSuffix: false }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { Circle, si, initDependence } from './utils.js' | ||
import { logger } from 'node-karin' | ||
import { Version } from '#components' | ||
|
||
let isGPU = false; | ||
|
||
(async function initGetIsGPU () { | ||
if (!await initDependence()) return | ||
const { controllers } = await si.graphics() | ||
// 初始化GPU获取 | ||
if (controllers?.find(item => | ||
item.memoryUsed && item.memoryFree && item.utilizationGpu) | ||
) { | ||
isGPU = true | ||
} | ||
})() | ||
|
||
/** 获取GPU占用 */ | ||
export default async function getGPU () { | ||
if (!isGPU) return false | ||
try { | ||
const { controllers } = await si.graphics() | ||
const graphics = controllers?.find(item => | ||
item.memoryUsed && item.memoryFree && item.utilizationGpu | ||
) | ||
if (!graphics) { | ||
logger.warn(`[${Version.pluginName}][state]状态GPU数据异常:\n`, controllers) | ||
return false | ||
} | ||
let { | ||
vendor, temperatureGpu, utilizationGpu, | ||
memoryTotal, memoryUsed /* powerDraw */ | ||
} = graphics | ||
temperatureGpu && (temperatureGpu = temperatureGpu + '℃') | ||
// powerDraw && (powerDraw = powerDraw + "W") | ||
return { | ||
...Circle(utilizationGpu / 100), | ||
inner: Math.round(utilizationGpu) + '%', | ||
title: 'GPU', | ||
info: [ | ||
`${(memoryUsed / 1024).toFixed(2)} GB / ${(memoryTotal / 1024).toFixed(2)} GB`, | ||
`${vendor} ${temperatureGpu}` | ||
] | ||
} | ||
} catch (e) { | ||
logger.warn(`[${Version.pluginName}][State] 获取GPU失败`) | ||
return false | ||
} | ||
} |
Oops, something went wrong.