From 8debcd14b79538804a6d027d210438c9a997f7f8 Mon Sep 17 00:00:00 2001 From: Shigma Date: Wed, 15 May 2024 02:41:40 +0800 Subject: [PATCH] feat(status): add status plugin --- packages/status/client/bots/index.ts | 9 ++ packages/status/client/bots/index.vue | 78 ++++++++++++++ packages/status/client/bots/light.vue | 32 ++++++ packages/status/client/bots/preview.vue | 114 ++++++++++++++++++++ packages/status/client/bots/utils.ts | 11 ++ packages/status/client/config.vue | 40 +++++++ packages/status/client/icons/arrow-down.vue | 5 + packages/status/client/icons/arrow-up.vue | 5 + packages/status/client/icons/index.ts | 12 +++ packages/status/client/icons/platform.vue | 5 + packages/status/client/icons/pulse.vue | 5 + packages/status/client/icons/robot.vue | 5 + packages/status/client/index.ts | 31 ++++++ packages/status/client/tsconfig.json | 11 ++ packages/status/package.json | 52 +++++++++ packages/status/src/index.ts | 109 +++++++++++++++++++ packages/status/tsconfig.json | 10 ++ 17 files changed, 534 insertions(+) create mode 100644 packages/status/client/bots/index.ts create mode 100644 packages/status/client/bots/index.vue create mode 100644 packages/status/client/bots/light.vue create mode 100644 packages/status/client/bots/preview.vue create mode 100644 packages/status/client/bots/utils.ts create mode 100644 packages/status/client/config.vue create mode 100644 packages/status/client/icons/arrow-down.vue create mode 100644 packages/status/client/icons/arrow-up.vue create mode 100644 packages/status/client/icons/index.ts create mode 100644 packages/status/client/icons/platform.vue create mode 100644 packages/status/client/icons/pulse.vue create mode 100644 packages/status/client/icons/robot.vue create mode 100644 packages/status/client/index.ts create mode 100644 packages/status/client/tsconfig.json create mode 100644 packages/status/package.json create mode 100644 packages/status/src/index.ts create mode 100644 packages/status/tsconfig.json diff --git a/packages/status/client/bots/index.ts b/packages/status/client/bots/index.ts new file mode 100644 index 0000000..ef133c0 --- /dev/null +++ b/packages/status/client/bots/index.ts @@ -0,0 +1,9 @@ +import { Context } from '@cordisjs/client' +import Bots from './index.vue' + +export default (ctx: Context) => { + ctx.slot({ + type: 'status-right', + component: Bots, + }) +} diff --git a/packages/status/client/bots/index.vue b/packages/status/client/bots/index.vue new file mode 100644 index 0000000..34499f5 --- /dev/null +++ b/packages/status/client/bots/index.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/packages/status/client/bots/light.vue b/packages/status/client/bots/light.vue new file mode 100644 index 0000000..09ae72b --- /dev/null +++ b/packages/status/client/bots/light.vue @@ -0,0 +1,32 @@ + + + diff --git a/packages/status/client/bots/preview.vue b/packages/status/client/bots/preview.vue new file mode 100644 index 0000000..26ff385 --- /dev/null +++ b/packages/status/client/bots/preview.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/packages/status/client/bots/utils.ts b/packages/status/client/bots/utils.ts new file mode 100644 index 0000000..c2906d6 --- /dev/null +++ b/packages/status/client/bots/utils.ts @@ -0,0 +1,11 @@ +import { Status } from '@satorijs/protocol' + +export function getStatus(status: Status) { + switch (status) { + case Status.OFFLINE: return 'offline' + case Status.ONLINE: return 'online' + case Status.CONNECT: return 'connect' + case Status.DISCONNECT: return 'disconnect' + case Status.RECONNECT: return 'reconnect' + } +} diff --git a/packages/status/client/config.vue b/packages/status/client/config.vue new file mode 100644 index 0000000..c82cf0f --- /dev/null +++ b/packages/status/client/config.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/packages/status/client/icons/arrow-down.vue b/packages/status/client/icons/arrow-down.vue new file mode 100644 index 0000000..7958a3e --- /dev/null +++ b/packages/status/client/icons/arrow-down.vue @@ -0,0 +1,5 @@ + diff --git a/packages/status/client/icons/arrow-up.vue b/packages/status/client/icons/arrow-up.vue new file mode 100644 index 0000000..b5ae6d9 --- /dev/null +++ b/packages/status/client/icons/arrow-up.vue @@ -0,0 +1,5 @@ + diff --git a/packages/status/client/icons/index.ts b/packages/status/client/icons/index.ts new file mode 100644 index 0000000..8c34935 --- /dev/null +++ b/packages/status/client/icons/index.ts @@ -0,0 +1,12 @@ +import { icons } from '@cordisjs/client' +import ArrowUp from './arrow-up.vue' +import ArrowDown from './arrow-down.vue' +import Platform from './platform.vue' +import Pulse from './pulse.vue' +import Robot from './robot.vue' + +icons.register('arrow-up', ArrowUp) +icons.register('arrow-down', ArrowDown) +icons.register('platform', Platform) +icons.register('analytic:pulse', Pulse) +icons.register('robot', Robot) diff --git a/packages/status/client/icons/platform.vue b/packages/status/client/icons/platform.vue new file mode 100644 index 0000000..0ce7bbf --- /dev/null +++ b/packages/status/client/icons/platform.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/packages/status/client/icons/pulse.vue b/packages/status/client/icons/pulse.vue new file mode 100644 index 0000000..bba0b60 --- /dev/null +++ b/packages/status/client/icons/pulse.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/packages/status/client/icons/robot.vue b/packages/status/client/icons/robot.vue new file mode 100644 index 0000000..289bd12 --- /dev/null +++ b/packages/status/client/icons/robot.vue @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/packages/status/client/index.ts b/packages/status/client/index.ts new file mode 100644 index 0000000..a7617f9 --- /dev/null +++ b/packages/status/client/index.ts @@ -0,0 +1,31 @@ +import { Context, Schema } from '@cordisjs/client' +import {} from '../src' +import Bots from './bots' +import Config from './config.vue' +import './icons' + +declare module '@cordisjs/client' { + interface Config { + mergeThreshold: number + } +} + +export default (ctx: Context) => { + ctx.plugin(Bots) + + // FIXME auto inject + ctx.inject(['manager'], (ctx) => { + ctx.slot({ + type: 'plugin-details', + component: Config, + order: -500, + }) + }) + + ctx.settings({ + id: 'status', + schema: Schema.object({ + mergeThreshold: Schema.number().default(10).description('当机器人的数量超过这个值时将合并显示状态指示灯。'), + }).description('机器人设置'), + }) +} diff --git a/packages/status/client/tsconfig.json b/packages/status/client/tsconfig.json new file mode 100644 index 0000000..1e774e2 --- /dev/null +++ b/packages/status/client/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../../tsconfig.client", + "include": [ + ".", + ], + "references": [ + { + "path": "../tsconfig.json", + }, + ], +} diff --git a/packages/status/package.json b/packages/status/package.json new file mode 100644 index 0000000..ecf8e54 --- /dev/null +++ b/packages/status/package.json @@ -0,0 +1,52 @@ +{ + "name": "@satorijs/plugin-status", + "description": "Show login status for Satori", + "version": "0.1.1", + "type": "module", + "main": "lib/index.js", + "files": [ + "lib", + "dist" + ], + "author": "Shigma ", + "license": "MIT", + "scripts": { + "lint": "eslint src --ext .ts" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/satorijs/webui.git", + "directory": "packages/status" + }, + "bugs": { + "url": "https://github.com/satorijs/webui/issues" + }, + "keywords": [ + "satori", + "plugin", + "webui", + "chat", + "status" + ], + "cordis": { + "service": { + "required": [ + "webui" + ], + "optional": [ + "manager" + ] + } + }, + "peerDependencies": { + "@cordisjs/plugin-manager": "^0.1.0", + "@cordisjs/plugin-webui": "^0.1.1", + "@satorijs/core": "^4.0.0" + }, + "devDependencies": { + "@cordisjs/client": "^0.1.1" + }, + "dependencies": { + "cosmokit": "^1.6.2" + } +} diff --git a/packages/status/src/index.ts b/packages/status/src/index.ts new file mode 100644 index 0000000..c591a1d --- /dev/null +++ b/packages/status/src/index.ts @@ -0,0 +1,109 @@ +import { Bot, Context, Dict, Schema, Time, Universal } from '@satorijs/core' +import {} from '@cordisjs/loader' +import {} from '@cordisjs/plugin-webui' + +declare module '@satorijs/core' { + interface Bot { + _messageSent: TickCounter + _messageReceived: TickCounter + } +} + +export interface Data { + bots: Dict +} + +export namespace Data { + export interface Bot extends Universal.Login { + error?: string + paths?: string[] + messageSent: number + messageReceived: number + } +} + +class TickCounter { + public stop: () => void + + private data = new Array(60).fill(0) + + private tick = () => { + this.data.unshift(0) + this.data.splice(-1, 1) + } + + constructor(ctx: Context) { + this.stop = ctx.setInterval(() => this.tick(), Time.second) + } + + public add(value = 1) { + this.data[0] += value + } + + public get() { + return this.data.reduce((prev, curr) => prev + curr, 0) + } + + static initialize(bot: Bot, ctx: Context) { + bot._messageSent = new TickCounter(ctx) + bot._messageReceived = new TickCounter(ctx) + } +} + +export const name = 'status' + +export const inject = ['webui'] + +export interface Config {} + +export const Config: Schema = Schema.object({}) + +export function apply(ctx: Context) { + const entry = ctx.webui.addEntry({ + dev: import.meta.resolve('../client/index.ts'), + prod: [ + import.meta.resolve('../dist/index.js'), + import.meta.resolve('../dist/style.css'), + ], + }, () => { + const bots: Dict = {} + for (const bot of ctx.bots) { + if (bot.hidden) continue + bots[bot.sid] = { + ...bot.toJSON(), + paths: ctx.get('loader')?.paths(bot.ctx.scope), + error: bot.error?.message, + messageSent: bot._messageSent.get(), + messageReceived: bot._messageReceived.get(), + } + } + return { bots } + }) + + const update = ctx.debounce(() => entry.refresh(), 0) + + ctx.on('before-send', (session) => { + session.bot._messageSent?.add(1) + }) + + ctx.on('message', (session) => { + session.bot._messageReceived?.add(1) + }) + + ctx.bots.forEach(bot => TickCounter.initialize(bot, ctx)) + + ctx.on('login-added', ({ bot }) => { + TickCounter.initialize(bot, ctx) + update() + }) + + ctx.on('login-removed', ({ bot }) => { + bot._messageSent.stop() + bot._messageReceived.stop() + update() + }) + + ctx.on('login-updated', () => { + update() + }) +} diff --git a/packages/status/tsconfig.json b/packages/status/tsconfig.json new file mode 100644 index 0000000..e193a11 --- /dev/null +++ b/packages/status/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + }, + "include": [ + "src", + ], +} \ No newline at end of file