Skip to content

Commit

Permalink
feat(status): setup mysql database
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Mar 10, 2021
1 parent 66a46a6 commit b3b4711
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 31 deletions.
6 changes: 4 additions & 2 deletions packages/plugin-status/client/components/bot-table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
<table>
<tr>
<th>账号信息</th>
<th>消息频率</th>
<th>当前消息频率</th>
<th>近期消息频率</th>
</tr>
<tr v-for="(bot, index) in bots" :key="index">
<td>{{ bot.username }} ({{ bot.platform }}:{{ bot.selfId }})</td>
<td>接收 {{ bot.received }}/min,发送 {{ bot.sent }}/min</td>
<td>发送 {{ bot.currentRate[0] }}/min,接收 {{ bot.currentRate[1] }}/min</td>
<td>发送 {{ bot.recentRate[0] }}/min,接收 {{ bot.recentRate[1] }}/min</td>
</tr>
</table>
</el-card>
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-status/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@
"@types/ws": "^7.4.0",
"@vitejs/plugin-vue": "^1.1.5",
"@vue/compiler-sfc": "^3.0.7",
"echarts": "^5.0.2",
"element-plus": "^1.0.2-beta.33",
"sass": "^1.32.8",
"systeminformation": "^5.6.1",
"vite": "^2.0.5",
"vue": "^3.0.7",
"vue-echarts": "^6.0.0-rc.3",
"ws": "^7.4.3"
}
}
2 changes: 1 addition & 1 deletion packages/plugin-status/server/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface BotData {
platform: Platform
code: Bot.Status
currentRate: MessageRate
recentRate?: MessageRate[]
recentRate?: MessageRate
}

export namespace BotData {
Expand Down
66 changes: 39 additions & 27 deletions packages/plugin-status/server/stats.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, Channel, noop, Session, Logger, Time, Bot, App, Platform } from 'koishi'
import { Context, Channel, noop, Session, Logger, Time, Bot, Platform, Database } from 'koishi'
import {} from 'koishi-plugin-teach'
import MysqlDatabase from 'koishi-plugin-mysql'
import Profile from './profile'
Expand Down Expand Up @@ -100,6 +100,12 @@ namespace Stat {
}).join(', ')})`
},
})

Database.extend('koishi-plugin-mysql', ({ tables, Domain }) => {
tables[table] = Object.assign([
'primary key (`time`)',
], Object.fromEntries(fields.map(key => [key, new Domain.Json('text')])))
})
}

add(field: K, key: string | number) {
Expand All @@ -118,6 +124,12 @@ namespace Stat {
return `\`${key}\` = \`${key}\` + ${value}`
},
})

Database.extend('koishi-plugin-mysql', ({ tables }) => {
tables[table] = Object.assign([
'primary key (`time`)',
], Object.fromEntries(fields.map(key => [key, 'int unsigned'])))
})
}
}
}
Expand Down Expand Up @@ -204,15 +216,15 @@ type DataPack = [
Pick<Channel, 'id' | 'name' | 'assignee'>[],
]

async function getStatusData(app: App, date: string) {
async function getStatusData(ctx: Context, date: string) {
const extension = {} as Statistics

const db = app.database.mysql
const db = ctx.database.mysql
const [historyDaily, historyHourly, historyLongterm, groups] = await db.query<DataPack>([
'SELECT * FROM `stats_daily` WHERE `time` < DATE(?) ORDER BY `time` DESC LIMIT ?',
'SELECT * FROM `stats_hourly` WHERE `time` < DATE(?) ORDER BY `time` DESC LIMIT ?',
'SELECT * FROM `stats_longterm` WHERE `time` < DATE(?) ORDER BY `time` DESC',
'SELECT `id`, `name`, `assignee` FROM `group`',
'SELECT `id`, `name`, `assignee` FROM `channel`',
], [date, RECENT_LENGTH, date, 24 * RECENT_LENGTH, date])

// history
Expand Down Expand Up @@ -244,12 +256,12 @@ async function getStatusData(app: App, date: string) {
platform: bot.platform,
value: messageMap[id],
last: historyDaily[0].group[id],
assignee: app.bots[assignee].selfId,
assignee: ctx.bots[assignee].selfId,
})
}
}

await Promise.all(db.app.bots.map(bot => getGroupInfo(bot).catch(noop)))
await Promise.all(ctx.bots.map(bot => getGroupInfo(bot).catch(noop)))

for (const key in messageMap) {
if (!groupSet.has(key) && groupMap[key]) {
Expand All @@ -260,7 +272,7 @@ async function getStatusData(app: App, date: string) {
name: name || key,
value: messageMap[key],
last: historyDaily[0].group[key],
assignee: app.bots[assignee].selfId,
assignee: ctx.bots[assignee].selfId,
})
}
}
Expand All @@ -272,22 +284,24 @@ async function getStatusData(app: App, date: string) {
})

// dialogue
const dialogueMap = average(historyDaily.map(data => data.dialogue))
const dialogues = await app.database.getDialoguesById(Object.keys(dialogueMap) as any, ['id', 'original'])
const questionMap: Record<string, QuestionData> = {}
for (const dialogue of dialogues) {
const { id, original: name } = dialogue
if (name.includes('[CQ:') || name.startsWith('hook:')) continue
if (!questionMap[name]) {
questionMap[name] = {
name,
value: dialogueMap[id],
if (db.getDialoguesById) {
const dialogueMap = average(historyDaily.map(data => data.dialogue))
const dialogues = await ctx.database.getDialoguesById(Object.keys(dialogueMap) as any, ['id', 'original'])
const questionMap: Record<string, QuestionData> = {}
for (const dialogue of dialogues) {
const { id, original: name } = dialogue
if (name.includes('[CQ:') || name.startsWith('hook:')) continue
if (!questionMap[name]) {
questionMap[name] = {
name,
value: dialogueMap[id],
}
} else {
questionMap[name].value += dialogueMap[id]
}
} else {
questionMap[name].value += dialogueMap[id]
}
extension.questions = Object.values(questionMap)
}
extension.questions = Object.values(questionMap)

return { extension, historyDaily }
}
Expand All @@ -309,21 +323,19 @@ namespace Statistics {
let cachedDate: string
let cachedData: Promise<CachedData>

export async function patch(profile: Profile) {
export async function patch(ctx: Context, profile: Profile) {
const date = new Date().toLocaleDateString('zh-CN')
if (date !== cachedDate) {
cachedData = getStatusData(this, date)
cachedData = getStatusData(ctx, date)
cachedDate = date
}
const { extension, historyDaily } = await cachedData

Object.assign(profile, extension)

const botSend = average(historyDaily.map(stat => stat.botSend))
const botReceive = average(historyDaily.map(stat => stat.botReceive))
profile.bots.forEach((bot) => {
bot.recentRate = historyDaily.map(daily => [
daily.botSend[bot.selfId] || 0,
daily.botReceive[bot.selfId] || 0,
])
bot.recentRate = [botSend[bot.selfId] || 0, botReceive[bot.selfId] || 0]
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-status/server/webui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export function apply(ctx: Context, config: Config = {}) {

async function updateProfile() {
profile = await Profile.from(ctx)
await Statistics.patch(profile)
await Statistics.patch(ctx, profile)
}

ctx.on('registry', () => {
Expand Down

0 comments on commit b3b4711

Please sign in to comment.