From 8d97d194243737d8119d6281cec6891b98cea6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=8F=B6?= <1936472877@qq.com> Date: Wed, 30 Oct 2024 15:17:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=95=B0=E6=8D=AE=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E5=8F=AF=E5=8C=BA=E5=88=86Bot,=E5=A2=9E=E5=8A=A0=E6=80=BB?= =?UTF-8?q?=E8=AE=A1=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改动了插件调用和插件发送的redisKey,会导致更新日期以及之前的数据为0 --- config/default_config/stats.yaml | 12 +++ src/api/Bot/stats/index.ts | 142 +++++++++++++++++++++++++------ src/api/login/index.ts | 2 +- src/common/config.ts | 8 +- 4 files changed, 135 insertions(+), 29 deletions(-) diff --git a/config/default_config/stats.yaml b/config/default_config/stats.yaml index da2363f0..64a6809f 100644 --- a/config/default_config/stats.yaml +++ b/config/default_config/stats.yaml @@ -1,6 +1,18 @@ # 以下数据均由YePanel统计, 设置为ture即开启统计功能 # 若改动, 需重启生效 +# 是否额外单独Bot统计 +alone: false + +# 总计统计 +totalStats: + # 总发送消息次数 + sent: false + # 总接收消息次数 + recv: false + # 总插件触发次数 + plugin: false + # 数量统计图表, 在一个图表中 countChart: # 发送消息次数 diff --git a/src/api/Bot/stats/index.ts b/src/api/Bot/stats/index.ts index a300a17a..b9f4c16d 100644 --- a/src/api/Bot/stats/index.ts +++ b/src/api/Bot/stats/index.ts @@ -9,19 +9,32 @@ Bot.on('message', (e) => { if (version.BotName === 'Miao') { // 接收消息数量 - incr(`YePanel:recv:${day}`) + incr(`YePanel:recv:${day}`, 31) + if (config.stats.totalStats.recv) { + incr('YePanel:recv:total', 0) + } + if (config.stats.alone && e.self_id) { + incr(`YePanel:recv:${e.self_id}:total`, 0) + incr(`YePanel:${e.self_id}:recv:${day}`, 31) + } } // 接收群消息数量 if (e.group_id && config.stats.rankChart.groupRecv) { const key = e?.group_name ? `${e.group_name}(${e.group_id})` : e.group_id incr(`YePanel:recv:group:${key}:${day}`, 31) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:recv:group:${key}:${day}`, 31) + } } // 接收用户消息数量 if (e.user_id && config.stats.rankChart.userRecv) { const key = e?.sender?.nickname ? `${e.sender.nickname}(${e.user_id})` : e.user_id incr(`YePanel:recv:user:${key}:${day}`, 31) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:recv:user:${key}:${day}`, 31) + } } }) @@ -33,16 +46,29 @@ if (config.stats.rankChart.pluginUse || config.stats.countChart.plugin) { const res = target.apply(thisArg, args) if (res) { const day = utils.getTime() - // 插件总调用数量 + const [e] = args + // 插件今日总调用数量 if (config.stats.countChart.plugin) { incr(`YePanel:plugin:total:${day}`, 31) + if (config.stats.alone && e?.self_id) { + incr(`YePanel:${e.self_id}:plugin:total:${day}`, 31) + } + } + // 插件今日总调用数量应该用use:total的 现在累计调用数量只能用totla:total了 + if (config.stats.totalStats.plugin) { + incr('YePanel:plugin:total:total', 0) + if (config.stats.alone && e?.self_id) { + incr(`YePanel:${e.self_id}:plugin:total:total`, 0) + } } // 插件调用排行榜 if (config.stats.rankChart.pluginUse) { - const [e] = args const { name, fnc } = getLog(e?.logFnc) if (name && fnc) { - incr(`YePanel:plugin:use:${day}:${name}(${fnc})`) + incr(`YePanel:plugin:use:${name}(${fnc}):${day}`) + if (config.stats.alone && e?.self_id) { + incr(`YePanel${e.self_id}::plugin:use:${name}(${fnc}):${day}`) + } } } } @@ -61,21 +87,40 @@ if ( apply (target, thisArg, args) { const [e, type, msg] = args const day = utils.getTime() + // 总发送消息统计 + if (!msg) { + if (config.stats.totalStats.sent) { + incr('YePanel:sent:total', 0) + } + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:sent:total`, 0) + incr(`YePanel:${e.self_id}:sent:${day}`, 31) + } + } // 群消息发送数量 if (e?.group_id && config.stats.rankChart.groupSent && type !== 'receive') { const key = e?.group_name ? `${e.group_name}(${e.group_id})` : e.group_id incr(`YePanel:sent:group:${key}:${day}`) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:sent:group:${key}:${day}`) + } } // 用户消息发送数量 if (e?.user_id && config.stats.rankChart.userSent && type !== 'receive') { const key = e?.sender?.nickname ? `${e.sender.nickname}(${e.user_id})` : e.user_id incr(`YePanel:sent:user:${key}:${day}`) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:sent:user:${key}:${day}`) + } } // 插件发送消息排行 if (e?.logFnc && config.stats.rankChart.pluginSent) { const { name, fnc } = getLog(e.logFnc) if (name && fnc) { - incr(`YePanel:plugin:sent:${day}:${name}(${fnc})`) + incr(`YePanel:plugin:sent:${name}(${fnc}):${day}`) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:plugin:sent:${name}(${fnc}):${day}`) + } } } // 发送消息类型排行 @@ -83,6 +128,9 @@ if ( const message = version.BotName === 'Miao' ? type : msg for (const i of Array.isArray(message) ? message : [message]) { incr(`YePanel:sent:type:${i?.type || 'text'}:${day}`) + if (config.stats.alone && e.self_id) { + incr(`YePanel:${e.self_id}:sent:type:${i?.type || 'text'}:${day}`) + } } } return target.apply(thisArg, args) @@ -109,7 +157,7 @@ function getLog (log: string) { function incr (key: string, day: number = 8) { redis.incr(key).then((i: number) => { - if (i == 1) { + if (i == 1 && day > 0) { redis.expire(key, 60 * 60 * 24 * day).catch(() => {}) } }).catch(() => {}) @@ -148,7 +196,8 @@ export default [ { url: '/get-stats-count-data', method: 'get', - handler: async () => { + handler: async ({ query }: { query: { uin?: string } }) => { + const uin = query.uin ? `${query.uin}:` : '' const data: { sent: number[], recv: number[], @@ -176,9 +225,13 @@ export default [ // 发送消息数量 if (countConfig.sent) { if (version.BotName === 'Miao') { - tasks.push(redis.get(`Yz:count:sendMsg:day:${date.format('MMDD')}`)) + if (uin) { + tasks.push(redis.get(`YePanel:${uin}sent:${time}`)) + } else { + tasks.push(redis.get(`Yz:count:sendMsg:day:${date.format('MMDD')}`)) + } } else if (version.BotName === 'TRSS') { - tasks.push(redis.get(`Yz:count:send:msg:total:${time}`)) + tasks.push(redis.get(`Yz:count:send:msg:${uin ? `bot:${uin}` : 'total:'}${time}`)) } } else { tasks.push(Promise.resolve(false)) @@ -187,9 +240,9 @@ export default [ // 接收消息数量 if (countConfig.recv) { if (version.BotName === 'Miao') { - tasks.push(redis.get(`YePanel:recv:${time}`)) + tasks.push(redis.get(`YePanel:${uin}recv:${time}`)) } else if (version.BotName === 'TRSS') { - tasks.push(redis.get(`Yz:count:receive:msg:total:${time}`)) + tasks.push(redis.get(`Yz:count:receive:msg:${uin ? `bot:${uin}` : 'total:'}${time}`)) } } else { tasks.push(Promise.resolve(false)) @@ -197,7 +250,7 @@ export default [ // 插件总调用数量 if (countConfig.plugin) { - tasks.push(redis.get(`YePanel:plugin:total:${time}`)) + tasks.push(redis.get(`YePanel:${uin}plugin:total:${time}`)) } else { tasks.push(Promise.resolve(false)) } @@ -245,30 +298,26 @@ export default [ userSent: false, sentType: false } - const { time } = query as {time: string} + const { time, uin } = query as {time: string, uin?: string} + const uinKey = uin ? `${uin}:` : '' const keys = [ { config: 'pluginSent', redis: 'plugin:sent' }, { config: 'pluginUse', redis: 'plugin:use' }, - { config: 'groupRecv', redis: 'recv:group', reg: true }, - { config: 'groupSent', redis: 'sent:group', reg: true }, - { config: 'userRecv', redis: 'recv:user', reg: true }, - { config: 'userSent', redis: 'sent:user', reg: true }, - { config: 'sentType', redis: 'sent:type', reg: true } + { config: 'groupRecv', redis: 'recv:group' }, + { config: 'groupSent', redis: 'sent:group' }, + { config: 'userRecv', redis: 'recv:user' }, + { config: 'userSent', redis: 'sent:user' }, + { config: 'sentType', redis: 'sent:type' } ] as { config: 'pluginSent'|'pluginUse'|'groupRecv'|'groupSent'|'userRecv'|'userSent'|'sentType', - redis: 'plugin:sent'|'plugin:use'|'group:recv'|'group:sent'|'user:recv'|'user:sent'|'sent:type', - reg?: boolean + redis: 'plugin:sent'|'plugin:use'|'recv:group'|'sent:group'|'recv:user'|'sent:user'|'sent:type', }[] for (const i of keys) { if (config.stats.rankChart[i.config]) { - const rkey = i.reg ? `YePanel:${i.redis}:*:${time.replace(/-/g, ':')}` : `YePanel:${i.redis}:${time.replace(/-/g, ':')}:*` + const rkey = `YePanel:${uinKey}${i.redis}:*:${time.replace(/-/g, ':')}` const getName = (key: string) => { - if (i.reg) { - const reg = new RegExp(rkey.replace('*', '(.+?)')) - return reg.exec(key)?.[1] || '' - } else { - return key.replace(rkey.replace('*', ''), '') - } + const reg = new RegExp(rkey.replace('*', '(.+?)')) + return reg.exec(key)?.[1] || '' } data[i.config] = await scan(rkey, getName) } @@ -278,5 +327,44 @@ export default [ data } } + }, + { + url: '/get-stats-total-data', + method: 'get', + handler: async ({ query }: { query: { uin?: string } }) => { + const uin = query.uin ? `${query.uin}:` : '' + const data: { + sent: number | false, + recv: number | false, + plugin: number | false, + } = { + sent: false, + recv: false, + plugin: false + } + const keys = [ + { config: 'sent', trss: 'send' }, + { config: 'recv', trss: 'receive' } + ] as { + config: 'sent'|'recv', + trss: 'send'|'receive' + }[] + for (const i of keys) { + if (config.stats.totalStats[i.config]) { + if (version.BotName === 'TRSS') { + data[i.config] = Number(await redis.get(`Yz:count:${i.trss}:msg:${uin ? `bot:${uin}` : 'total:'}total`)) + } else if (version.BotName === 'Miao') { + data[i.config] = Number(await redis.get(`YePanel:${uin}${i.config}:total`)) + } + } + } + if (config.stats.totalStats.plugin) { + data.plugin = Number(await redis.get(`YePanel:${uin}plugin:total:total`)) + } + return { + success: true, + data + } + } } ] as RouteOptions[] diff --git a/src/api/login/index.ts b/src/api/login/index.ts index a7262c18..babeb436 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -122,7 +122,7 @@ export default [ for (const i of router.children) { i.path = `/${plugin}${i.path}` i.name = `${plugin}/${i.name}` - i.component = 'plugins/index' + i.component = 'plugins/YePanel/index' } data.code[plugin] = { main: {}, components: {} } // 收集Vue页面 diff --git a/src/common/config.ts b/src/common/config.ts index 3f106af8..f550e545 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -35,7 +35,7 @@ class Config { const saveKeys: string[] = [] const merge = (defValue: any, value: any, prefix: string = '') => { const defKeys = Object.keys(defValue) - const configKeys = Object.keys(value) + const configKeys = Object.keys(value || {}) for (const key of defKeys) { switch (typeof defValue[key]) { case 'object': @@ -87,6 +87,12 @@ class Config { } get stats (): { + alone: boolean, + totalStats: { + sent: boolean + recv: boolean + plugin: boolean + }, countChart: { sent: boolean recv: boolean