diff --git a/build/dtsc.ts b/build/dtsc.ts index fdc0adc784..716be51c1d 100644 --- a/build/dtsc.ts +++ b/build/dtsc.ts @@ -34,7 +34,7 @@ async function bundle(path: string) { const importMap: Record> = {} const namespaceMap: Record = {} - let prolog = '', cap: RegExpExecArray + let prolog = '', epilog = '', cap: RegExpExecArray let content = await fs.readFile(entry, 'utf8') content = content.split(EOL).filter((line) => { if (cap = /^ {4}import \* as (.+) from ["'](.+)["'];$/.exec(line)) { @@ -59,6 +59,8 @@ async function bundle(path: string) { } } else if (line.startsWith('///')) { prolog += line + EOL + } else if (line.startsWith(' export default ')) { + epilog = line.trimStart() + EOL } else { return true } @@ -85,8 +87,9 @@ async function bundle(path: string) { if (identifier) return `declare namespace ${identifier} {` return '' }) + .replace(/^( {4})((module|class|namespace) .+ \{)$/gm, (_, $1, $2) => `${$1}declare ${$2}`) .replace(/\r?\n}/g, '') - .replace(/^ {4}/gm, '')) + .replace(/^ {4}/gm, '') + epilog) } async function bundleAll(names: readonly string[]) { @@ -95,15 +98,13 @@ async function bundleAll(names: readonly string[]) { } } -const targets = ['koishi-utils', 'koishi-core'] -const databases = ['mongo', 'mysql'] +const targets = ['koishi-utils', 'koishi-core', 'plugin-mysql', 'plugin-mongo'] const corePlugins = ['common', 'eval', 'puppeteer', 'teach'] function precedence(name: string) { if (name.startsWith('adapter')) return 1 if (name.startsWith('koishi')) return 5 const plugin = name.slice(7) - if (databases.includes(plugin)) return 2 if (corePlugins.includes(plugin)) return 3 return 4 } diff --git a/packages/adapter-discord/package.json b/packages/adapter-discord/package.json index 041451ad98..3289132c15 100644 --- a/packages/adapter-discord/package.json +++ b/packages/adapter-discord/package.json @@ -1,7 +1,7 @@ { "name": "koishi-adapter-discord", "description": "Discord adapter for Koishi", - "version": "1.0.3", + "version": "1.0.4", "main": "dist/index.js", "typings": "dist/index.d.ts", "files": [ @@ -28,7 +28,7 @@ "koishi" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "devDependencies": { "@types/ws": "^7.4.0", diff --git a/packages/adapter-discord/src/bot.ts b/packages/adapter-discord/src/bot.ts index 351bf74f7b..a467f2aa29 100644 --- a/packages/adapter-discord/src/bot.ts +++ b/packages/adapter-discord/src/bot.ts @@ -106,7 +106,7 @@ export class DiscordBot extends Bot<'discord'> { }) sentMessageId = r.id } - if (type === 'image' || type === 'video') { + if (type === 'image' || type === 'video' && data.url) { if (data.url.startsWith('http://') || data.url.startsWith('https://')) { const a = await axios({ url: data.url, diff --git a/packages/adapter-discord/src/index.ts b/packages/adapter-discord/src/index.ts index dc4a4c56b9..106da66e85 100644 --- a/packages/adapter-discord/src/index.ts +++ b/packages/adapter-discord/src/index.ts @@ -2,6 +2,7 @@ import { Adapter } from 'koishi-core' import { AxiosRequestConfig } from 'axios' import { DiscordBot } from './bot' import WsClient from './ws' +import { Embed } from './types' export * from './bot' export * as dc from './types' @@ -15,6 +16,12 @@ declare module 'koishi-core' { discord?: DiscordOptions } + interface Session { + discord?: { + embeds: Embed[] + } + } + namespace Bot { interface Platforms { discord: DiscordBot diff --git a/packages/adapter-discord/src/utils.ts b/packages/adapter-discord/src/utils.ts index 24a818796b..55cffadc66 100644 --- a/packages/adapter-discord/src/utils.ts +++ b/packages/adapter-discord/src/utils.ts @@ -28,7 +28,7 @@ export const adaptAuthor = (author: DC.Author): AuthorInfo => ({ nickname: author.username, }) -export async function adaptMessage(bot: DiscordBot, meta: DC.DiscordMessage, session: MessageInfo = {}) { +export async function adaptMessage(bot: DiscordBot, meta: DC.DiscordMessage, session: Partial> = {}) { if (meta.author) { session.author = adaptAuthor(meta.author) session.userId = meta.author.id @@ -90,7 +90,9 @@ export async function adaptMessage(bot: DiscordBot, meta: DC.DiscordMessage, ses session.content += segment('video', { url: embed.video.url, proxy_url: embed.video.proxy_url }) } } - session.content = meta.embeds.map(v => segment('embed', { data: JSON.stringify(v) })).join('') + session.content + session.discord = { + embeds: meta.embeds + } return session } diff --git a/packages/adapter-kaiheila/package.json b/packages/adapter-kaiheila/package.json index 64c1ebf073..d6b09821ec 100644 --- a/packages/adapter-kaiheila/package.json +++ b/packages/adapter-kaiheila/package.json @@ -24,14 +24,14 @@ "koishi" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" }, "dependencies": { "axios": "^0.21.1", - "koishi-utils": "^4.0.1", + "koishi-utils": "^4.0.2", "ws": "^7.4.4" } } diff --git a/packages/adapter-onebot/package.json b/packages/adapter-onebot/package.json index efdc4f39a1..45673008c9 100644 --- a/packages/adapter-onebot/package.json +++ b/packages/adapter-onebot/package.json @@ -27,7 +27,7 @@ "koishi" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "devDependencies": { "@types/ws": "^7.4.0", @@ -36,7 +36,7 @@ }, "dependencies": { "axios": "^0.21.1", - "koishi-utils": "^4.0.1", + "koishi-utils": "^4.0.2", "ws": "^7.4.4" } } diff --git a/packages/adapter-telegram/package.json b/packages/adapter-telegram/package.json index 24c611d3df..656f644c40 100644 --- a/packages/adapter-telegram/package.json +++ b/packages/adapter-telegram/package.json @@ -28,7 +28,7 @@ "koishi" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" @@ -36,6 +36,6 @@ "dependencies": { "axios": "^0.21.1", "form-data": "^4.0.0", - "koishi-utils": "^4.0.1" + "koishi-utils": "^4.0.2" } } diff --git a/packages/adapter-tomon/package.json b/packages/adapter-tomon/package.json index c68d964861..cadb9ccd5f 100644 --- a/packages/adapter-tomon/package.json +++ b/packages/adapter-tomon/package.json @@ -24,7 +24,7 @@ "koishi" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "devDependencies": { "@types/pako": "^1.0.1", @@ -32,7 +32,7 @@ }, "dependencies": { "axios": "^0.21.1", - "koishi-utils": "^4.0.1", + "koishi-utils": "^4.0.2", "pako": "^2.0.3", "ws": "^7.4.4" } diff --git a/packages/koishi-core/package.json b/packages/koishi-core/package.json index a3400598f0..0a1a8aa6b4 100644 --- a/packages/koishi-core/package.json +++ b/packages/koishi-core/package.json @@ -1,7 +1,7 @@ { "name": "koishi-core", "description": "Core features for Koishi", - "version": "3.2.0", + "version": "3.2.1", "main": "dist/index.js", "typings": "dist/index.d.ts", "engines": { @@ -42,7 +42,7 @@ "fastest-levenshtein": "^1.0.12", "koa": "^2.13.1", "koa-bodyparser": "^4.3.0", - "koishi-utils": "^4.0.1", + "koishi-utils": "^4.0.2", "lru-cache": "^6.0.0" } } diff --git a/packages/koishi-core/src/adapter.ts b/packages/koishi-core/src/adapter.ts index 3f2f304d14..6bac0727ba 100644 --- a/packages/koishi-core/src/adapter.ts +++ b/packages/koishi-core/src/adapter.ts @@ -1,4 +1,4 @@ -import { Logger, paramCase, sleep, Time } from 'koishi-utils' +import { Logger, paramCase, remove, sleep, Time } from 'koishi-utils' import { Session } from './session' import { App } from './app' import WebSocket from 'ws' @@ -34,6 +34,7 @@ export abstract class Adapter

{ const bot = new this.Bot(this, options) this.bots.push(bot) this.app.bots.push(bot) + return bot } dispatch(session: Session) { @@ -254,6 +255,12 @@ export class Bot

{ } return messageIds } + + dispose() { + const bot = this as Bot.Instance

+ remove(this.adapter.bots, bot) + remove(this.app.bots, bot) + } } export namespace Bot { diff --git a/packages/koishi-core/src/app.ts b/packages/koishi-core/src/app.ts index 2f65e812e0..8b1cfd7349 100644 --- a/packages/koishi-core/src/app.ts +++ b/packages/koishi-core/src/app.ts @@ -235,7 +235,7 @@ export class App extends Context { if (this.database) { if (session.subtype === 'group') { // attach group data - const channelFields = new Set(['flag', 'assignee', 'disable']) + const channelFields = new Set(['flag', 'assignee']) this.emit('before-attach-channel', session, channelFields) const channel = await session.observeChannel(channelFields) @@ -346,11 +346,12 @@ export class App extends Context { return argv } - private _handleShortcut(content: string, { parsed, quote }: Session) { + private _handleShortcut(content: string, session: Session) { + const { parsed, quote } = session if (parsed.prefix || quote) return for (const shortcut of this._shortcuts) { const { name, fuzzy, command, greedy, prefix, options = {}, args = [] } = shortcut - if (prefix && !parsed.appel) continue + if (prefix && !parsed.appel || !command.context.match(session)) continue if (typeof name === 'string') { if (!fuzzy && content !== name || !content.startsWith(name)) continue const message = content.slice(name.length) diff --git a/packages/koishi-core/src/command.ts b/packages/koishi-core/src/command.ts index 3e93d985eb..3760ae24e9 100644 --- a/packages/koishi-core/src/command.ts +++ b/packages/koishi-core/src/command.ts @@ -1,4 +1,4 @@ -import { Logger, coerce, Time, template } from 'koishi-utils' +import { Logger, coerce, Time, template, remove } from 'koishi-utils' import { Argv, Domain } from './parser' import { Context, NextFunction } from './context' import { User, Channel } from './database' @@ -245,11 +245,9 @@ export class Command s.command !== this) this._aliases.forEach(name => delete this.app._commandMap[name]) - const index = this.app._commands.indexOf(this) - this.app._commands.splice(index, 1) + remove(this.app._commands, this) if (this.parent) { - const index = this.parent.children.indexOf(this) - this.parent.children.splice(index, 1) + remove(this.parent.children, this) } } } @@ -260,6 +258,8 @@ export function getUsageName(command: Command) { export type ValidationField = 'authority' | 'usage' | 'timers' +Command.channelFields(['disable']) + Command.userFields(({ tokens, command, options = {} }, fields) => { if (!command) return const { maxUsage, minInterval, authority } = command.config diff --git a/packages/koishi-core/src/context.ts b/packages/koishi-core/src/context.ts index 6ff099f36b..d52f217ce7 100644 --- a/packages/koishi-core/src/context.ts +++ b/packages/koishi-core/src/context.ts @@ -1,4 +1,4 @@ -import { Logger, defineProperty } from 'koishi-utils' +import { Logger, defineProperty, remove } from 'koishi-utils' import { Command } from './command' import { Session } from './session' import { User, Channel, Database } from './database' @@ -139,14 +139,6 @@ export class Context { return this.app.registry.get(this._plugin) } - private removeDisposable(listener: Disposable) { - const index = this.state.disposables.indexOf(listener) - if (index >= 0) { - this.state.disposables.splice(index, 1) - return true - } - } - addSideEffect(state = this.state) { while (state && !state.sideEffect) { state.sideEffect = true @@ -208,6 +200,7 @@ export class Context { ...state.disposables.map(dispose => dispose()), ]).finally(() => { this.app.registry.delete(plugin) + remove(state.parent.children, plugin) const index = state.parent.children.indexOf(plugin) if (index >= 0) state.parent.children.splice(index, 1) this.emit('registry', this.app.registry) @@ -292,7 +285,7 @@ export class Context { return _listener(), () => false } else if (name === 'before-disconnect') { this.state.disposables[method](_listener) - return () => this.removeDisposable(_listener) + return () => remove(this.state.disposables, _listener) } else if (name === 'before-connect') { // before-connect is side effect this.addSideEffect() @@ -342,7 +335,7 @@ export class Context { private createTimerDispose(timer: NodeJS.Timeout) { const dispose = () => { clearTimeout(timer) - return this.removeDisposable(dispose) + return remove(this.state.disposables, dispose) } this.state.disposables.push(dispose) return dispose @@ -502,8 +495,7 @@ Router.prototype.register = function (this: Router, ...args) { const layer = register.apply(this, args) const context: Context = this['_koishiContext'] context.state.disposables.push(() => { - const index = this.stack.indexOf(layer) - if (index) this.stack.splice(index, 1) + remove(this.stack, layer) }) return layer } diff --git a/packages/koishi-core/src/session.ts b/packages/koishi-core/src/session.ts index 7d71f37e60..48abb76696 100644 --- a/packages/koishi-core/src/session.ts +++ b/packages/koishi-core/src/session.ts @@ -2,7 +2,7 @@ import LruCache from 'lru-cache' import { distance } from 'fastest-levenshtein' import { User, Channel, TableType, Tables } from './database' import { Command } from './command' -import { contain, observe, Logger, defineProperty, Random, template } from 'koishi-utils' +import { contain, observe, Logger, defineProperty, Random, template, remove } from 'koishi-utils' import { Argv } from './parser' import { Middleware, NextFunction } from './context' import { App } from './app' @@ -169,8 +169,7 @@ export class Session< const hook = () => { resolve() clearTimeout(timer) - const index = this._hooks.indexOf(hook) - if (index >= 0) this._hooks.splice(index, 1) + remove(this._hooks, hook) } this._hooks.push(hook) const timer = setTimeout(async () => { diff --git a/packages/koishi-core/tsconfig.json b/packages/koishi-core/tsconfig.json index e27408c68b..b7549d1c0b 100644 --- a/packages/koishi-core/tsconfig.json +++ b/packages/koishi-core/tsconfig.json @@ -3,7 +3,6 @@ "compilerOptions": { "rootDir": "src", "outFile": "temp/index.d.ts", - "tsBuildInfoFile": "tsconfig.tsbuildinfo" }, "include": [ "src" diff --git a/packages/koishi-test-utils/package.json b/packages/koishi-test-utils/package.json index 4a4a35d878..3a423b9034 100644 --- a/packages/koishi-test-utils/package.json +++ b/packages/koishi-test-utils/package.json @@ -37,8 +37,8 @@ "dependencies": { "chai": "^4.3.3", "chai-as-promised": "^7.1.1", - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "devDependencies": { "@types/chai": "^4.2.15", diff --git a/packages/koishi-utils/package.json b/packages/koishi-utils/package.json index 6869cac482..78539d2ea8 100644 --- a/packages/koishi-utils/package.json +++ b/packages/koishi-utils/package.json @@ -1,7 +1,7 @@ { "name": "koishi-utils", "description": "Utilities for Koishi", - "version": "4.0.1", + "version": "4.0.2", "main": "dist/index.js", "typings": "dist/index.d.ts", "files": [ diff --git a/packages/koishi-utils/src/set.ts b/packages/koishi-utils/src/set.ts index bd098c4b43..697676667a 100644 --- a/packages/koishi-utils/src/set.ts +++ b/packages/koishi-utils/src/set.ts @@ -17,3 +17,11 @@ export function union(array1: readonly T[], array2: readonly T[]) { export function deduplicate(array: readonly T[]) { return [...new Set(array)] } + +export function remove(list: T[], item: T) { + const index = list.indexOf(item) + if (index >= 0) { + list.splice(index, 1) + return true + } +} diff --git a/packages/koishi-utils/tsconfig.json b/packages/koishi-utils/tsconfig.json index e27408c68b..b7549d1c0b 100644 --- a/packages/koishi-utils/tsconfig.json +++ b/packages/koishi-utils/tsconfig.json @@ -3,7 +3,6 @@ "compilerOptions": { "rootDir": "src", "outFile": "temp/index.d.ts", - "tsBuildInfoFile": "tsconfig.tsbuildinfo" }, "include": [ "src" diff --git a/packages/koishi/ecosystem.json b/packages/koishi/ecosystem.json index 89d68d20b8..a340d163bb 100644 --- a/packages/koishi/ecosystem.json +++ b/packages/koishi/ecosystem.json @@ -1,6 +1,6 @@ { "koishi-adapter-discord": { - "version": "1.0.3", + "version": "1.0.4", "description": "Discord adapter for Koishi" }, "koishi-adapter-kaiheila": { @@ -48,14 +48,14 @@ "description": "Image searching plugin for Koishi" }, "koishi-plugin-mongo": { - "version": "2.0.0", + "version": "2.1.0", "description": "MongoDB support for Koishi" }, "koishi-plugin-monitor": { "version": "1.0.0-beta.27" }, "koishi-plugin-mysql": { - "version": "3.0.0", + "version": "3.1.0", "description": "MySQL support for Koishi" }, "koishi-plugin-puppeteer": { @@ -71,7 +71,7 @@ "description": "Schedule plugin for Koishi" }, "koishi-plugin-status": { - "version": "4.0.0-alpha.0", + "version": "4.0.0-alpha.1", "description": "Show Status of Koishi" }, "koishi-plugin-teach": { diff --git a/packages/koishi/package.json b/packages/koishi/package.json index 683c23af72..1a8165c8e9 100644 --- a/packages/koishi/package.json +++ b/packages/koishi/package.json @@ -1,7 +1,7 @@ { "name": "koishi", "description": "A QQ bot framework based on CQHTTP", - "version": "3.2.0", + "version": "3.2.1", "main": "index.js", "typings": "index.d.ts", "engines": { @@ -38,8 +38,8 @@ "cac": "^6.7.2", "chokidar": "^3.5.1", "kleur": "^4.1.4", - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1", + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2", "prompts": "^2.4.0" } } diff --git a/packages/plugin-adventure/package.json b/packages/plugin-adventure/package.json index 58502d7e52..8e39991323 100644 --- a/packages/plugin-adventure/package.json +++ b/packages/plugin-adventure/package.json @@ -28,11 +28,11 @@ "adventure" ], "peerDependencies": { - "koishi-core": "^3.2.0", + "koishi-core": "^3.2.1", "koishi-plugin-common": "^4.1.2", - "koishi-plugin-mysql": "^3.0.0", + "koishi-plugin-mysql": "^3.1.0", "koishi-plugin-teach": "^2.0.0", - "koishi-utils": "^4.0.1" + "koishi-utils": "^4.0.2" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" diff --git a/packages/plugin-chess/package.json b/packages/plugin-chess/package.json index 44973afe2c..98299c345c 100644 --- a/packages/plugin-chess/package.json +++ b/packages/plugin-chess/package.json @@ -29,8 +29,8 @@ "game" ], "peerDependencies": { - "koishi-core": "^3.2.0", + "koishi-core": "^3.2.1", "koishi-plugin-puppeteer": "^2.0.0", - "koishi-utils": "^4.0.1" + "koishi-utils": "^4.0.2" } } diff --git a/packages/plugin-common/package.json b/packages/plugin-common/package.json index 3b04c7652b..61aa244d33 100644 --- a/packages/plugin-common/package.json +++ b/packages/plugin-common/package.json @@ -30,8 +30,8 @@ "plugin" ], "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" diff --git a/packages/plugin-dice/package.json b/packages/plugin-dice/package.json index 971abcf19b..a8f883d77f 100644 --- a/packages/plugin-dice/package.json +++ b/packages/plugin-dice/package.json @@ -31,8 +31,8 @@ "dice" ], "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" diff --git a/packages/plugin-eval/package.json b/packages/plugin-eval/package.json index 0f36d3a9d4..299d527688 100644 --- a/packages/plugin-eval/package.json +++ b/packages/plugin-eval/package.json @@ -33,7 +33,7 @@ "code" ], "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "dependencies": { "js-yaml": "^4.0.0", diff --git a/packages/plugin-github/package.json b/packages/plugin-github/package.json index 0b15b482c1..90e3764f70 100644 --- a/packages/plugin-github/package.json +++ b/packages/plugin-github/package.json @@ -32,9 +32,9 @@ "koishi-test-utils": "^6.0.0-beta.10" }, "peerDependencies": { - "koishi-core": "^3.2.0", + "koishi-core": "^3.2.1", "koishi-plugin-puppeteer": "^2.0.0", - "koishi-utils": "^4.0.1" + "koishi-utils": "^4.0.2" }, "dependencies": { "@octokit/webhooks-definitions": "^3.62.5", diff --git a/packages/plugin-image-search/package.json b/packages/plugin-image-search/package.json index a87d50d109..c85c4f25b5 100644 --- a/packages/plugin-image-search/package.json +++ b/packages/plugin-image-search/package.json @@ -33,8 +33,8 @@ "pixiv" ], "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "dependencies": { "axios": "^0.21.1", diff --git a/packages/plugin-mongo/package.json b/packages/plugin-mongo/package.json index 099b394894..192ae4673d 100644 --- a/packages/plugin-mongo/package.json +++ b/packages/plugin-mongo/package.json @@ -1,7 +1,7 @@ { "name": "koishi-plugin-mongo", "description": "MongoDB support for Koishi", - "version": "2.0.0", + "version": "2.1.0", "main": "dist/index.js", "typings": "dist/index.d.ts", "files": [ @@ -35,7 +35,7 @@ "@types/mongodb": "^3.6.9" }, "peerDependencies": { - "koishi-core": "^3.2.0" + "koishi-core": "^3.2.1" }, "dependencies": { "mongodb": "^3.6.4" diff --git a/packages/plugin-mongo/src/database.ts b/packages/plugin-mongo/src/database.ts index 36331a0904..3ccf3220c7 100644 --- a/packages/plugin-mongo/src/database.ts +++ b/packages/plugin-mongo/src/database.ts @@ -1,7 +1,11 @@ import { MongoClient, Db, Collection } from 'mongodb' -import { App, Channel, Database, Tables, TableType, User } from 'koishi-core' +import { App, Channel, Database, User, Tables as KoishiTables } from 'koishi-core' import { URLSearchParams } from 'url' +type TableType = keyof Tables + +export interface Tables extends KoishiTables {} + export interface Config { username?: string password?: string diff --git a/packages/plugin-mongo/tsconfig.json b/packages/plugin-mongo/tsconfig.json index 54a917908e..8b165bdac1 100644 --- a/packages/plugin-mongo/tsconfig.json +++ b/packages/plugin-mongo/tsconfig.json @@ -1,8 +1,8 @@ { "extends": "../../tsconfig.base", "compilerOptions": { - "outDir": "dist", "rootDir": "src", + "outFile": "temp/index.d.ts", }, "include": [ "src", diff --git a/packages/plugin-monitor/package.json b/packages/plugin-monitor/package.json index 451e620d2d..89e47eb357 100644 --- a/packages/plugin-monitor/package.json +++ b/packages/plugin-monitor/package.json @@ -17,7 +17,7 @@ }, "homepage": "https://github.com/koishijs/koishi#readme", "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" } } diff --git a/packages/plugin-mysql/package.json b/packages/plugin-mysql/package.json index 48524be8aa..f85b1c5f6e 100644 --- a/packages/plugin-mysql/package.json +++ b/packages/plugin-mysql/package.json @@ -1,7 +1,7 @@ { "name": "koishi-plugin-mysql", "description": "MySQL support for Koishi", - "version": "3.0.0", + "version": "3.1.0", "main": "dist/index.js", "typings": "dist/index.d.ts", "files": [ @@ -35,8 +35,8 @@ "@types/mysql": "^2.15.18" }, "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "dependencies": { "mysql": "^2.18.1" diff --git a/packages/plugin-mysql/src/database.ts b/packages/plugin-mysql/src/database.ts index 8df9530839..eb24290157 100644 --- a/packages/plugin-mysql/src/database.ts +++ b/packages/plugin-mysql/src/database.ts @@ -1,5 +1,5 @@ import { createPool, Pool, PoolConfig, escape as mysqlEscape, escapeId, format, OkPacket, TypeCast } from 'mysql' -import { TableType, Tables, App, Database } from 'koishi-core' +import { Tables as KoishiTables, App, Database } from 'koishi-core' import { Logger } from 'koishi-utils' import { types } from 'util' @@ -9,6 +9,10 @@ declare module 'mysql' { } } +type TableType = keyof Tables + +export interface Tables extends KoishiTables {} + const logger = new Logger('mysql') export interface Config extends PoolConfig {} diff --git a/packages/plugin-mysql/tsconfig.json b/packages/plugin-mysql/tsconfig.json index a497f05e83..b9a2903071 100644 --- a/packages/plugin-mysql/tsconfig.json +++ b/packages/plugin-mysql/tsconfig.json @@ -1,8 +1,8 @@ { "extends": "../../tsconfig.base", "compilerOptions": { - "outDir": "dist", "rootDir": "src", + "outFile": "temp/index.d.ts", }, "include": [ "src", diff --git a/packages/plugin-puppeteer/package.json b/packages/plugin-puppeteer/package.json index e43fe44946..4c6dfd5a6e 100644 --- a/packages/plugin-puppeteer/package.json +++ b/packages/plugin-puppeteer/package.json @@ -33,8 +33,8 @@ "koishi-test-utils": "^6.0.0-beta.10" }, "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "dependencies": { "chrome-finder": "^1.0.7", diff --git a/packages/plugin-rss/package.json b/packages/plugin-rss/package.json index d5f6de7df4..dbaf7cf1ab 100644 --- a/packages/plugin-rss/package.json +++ b/packages/plugin-rss/package.json @@ -31,8 +31,8 @@ "rss" ], "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" }, "devDependencies": { "koishi-test-utils": "^6.0.0-beta.10" diff --git a/packages/plugin-schedule/package.json b/packages/plugin-schedule/package.json index db8ca7bd17..7451cd7455 100644 --- a/packages/plugin-schedule/package.json +++ b/packages/plugin-schedule/package.json @@ -29,12 +29,12 @@ "task" ], "devDependencies": { - "koishi-plugin-mongo": "^2.0.0", - "koishi-plugin-mysql": "^3.0.0", + "koishi-plugin-mongo": "^2.1.0", + "koishi-plugin-mysql": "^3.1.0", "koishi-test-utils": "^6.0.0-beta.10" }, "peerDependencies": { - "koishi-core": "^3.2.0", - "koishi-utils": "^4.0.1" + "koishi-core": "^3.2.1", + "koishi-utils": "^4.0.2" } } diff --git a/packages/plugin-status/client/app.vue b/packages/plugin-status/client/app.vue deleted file mode 100644 index 60bbb8a1d6..0000000000 --- a/packages/plugin-status/client/app.vue +++ /dev/null @@ -1,34 +0,0 @@ - - - - - diff --git a/packages/plugin-status/client/components/bot-table.vue b/packages/plugin-status/client/components/bot-table.vue deleted file mode 100644 index 972a41ab28..0000000000 --- a/packages/plugin-status/client/components/bot-table.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - - - diff --git a/packages/plugin-status/client/components/button.vue b/packages/plugin-status/client/components/button.vue new file mode 100644 index 0000000000..5bfdb078d3 --- /dev/null +++ b/packages/plugin-status/client/components/button.vue @@ -0,0 +1,125 @@ + + + + + diff --git a/packages/plugin-status/client/components/card.vue b/packages/plugin-status/client/components/card.vue new file mode 100644 index 0000000000..dd8b6edfac --- /dev/null +++ b/packages/plugin-status/client/components/card.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/packages/plugin-status/client/components/input.vue b/packages/plugin-status/client/components/input.vue new file mode 100644 index 0000000000..552f72f32f --- /dev/null +++ b/packages/plugin-status/client/components/input.vue @@ -0,0 +1,149 @@ + + + + + \ No newline at end of file diff --git a/packages/plugin-status/client/components/load-chart.vue b/packages/plugin-status/client/components/load-chart.vue deleted file mode 100644 index da53efde3b..0000000000 --- a/packages/plugin-status/client/components/load-chart.vue +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/packages/plugin-status/client/components/plugin-list.vue b/packages/plugin-status/client/components/plugin-list.vue deleted file mode 100644 index 9c5d2acff9..0000000000 --- a/packages/plugin-status/client/components/plugin-list.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/packages/plugin-status/client/global.d.ts b/packages/plugin-status/client/global.d.ts index 7c590f0ffc..e251d395c6 100644 --- a/packages/plugin-status/client/global.d.ts +++ b/packages/plugin-status/client/global.d.ts @@ -9,6 +9,7 @@ declare module '*.vue' { } declare module '~/server' { + import {} from 'koishi-plugin-status/server' export * from 'koishi-plugin-status/server/webui' } @@ -16,8 +17,4 @@ declare module '~/client' { export * from 'koishi-plugin-status/client' } -declare module '~/layout' { - export * from 'koishi-plugin-status/client/app.vue' -} - declare const KOISHI_ENDPOINT: string diff --git a/packages/plugin-status/client/index.scss b/packages/plugin-status/client/index.scss index 3ff79052e9..7fce8efabf 100644 --- a/packages/plugin-status/client/index.scss +++ b/packages/plugin-status/client/index.scss @@ -10,34 +10,38 @@ $success: #67c23a; $error: #F56C6C; $warning: #E6A23C; -.el-card { - max-width: 960px; - margin: 2rem auto; - border-radius: 6px; +// color schemes +$activeColor: #7fffd4; +$accentColor: #409eff; +$warningColor: #f56c6c; +$successColor: #67c23a; +$borderColor: #eaecef; - .el-card__header { - font-size: 1.25rem; - font-weight: bolder; - padding: 1rem 1.5rem; - text-align: center; - } +$tableBdColor: #dfe2e5; - .frameless > & .el-card__body { - padding: 0; +// transparent +$tpColor1: #c0c4cc80; +$tpColor2: #c0c4ccb0; +$tpColor3: #c0c4cc; +$tpFgColor1: #e4e7ed60; +$tpFgColor2: #e4e7ed90; +$tpFgColor3: #f2f6fcc0; +$tpFgColor4: #f2f6fc; +$tpFgColor5: #f5f8fd; +$tpBgColor0: transparent; +$tpBgColor1: #fff2; +$tpBgColor2: #fff4; +$tpBorderColor1: #dcdfe640; +$tpBorderColor2: #dcdfe680; +$tpBorderColor3: #dcdfe6; +$tpInsetColor: #0004; - p { - margin: 1.5rem 2rem; - } - } +// breakpoints +$bp_lg: 1440px; +$bp_md: 1024px; +$bp_sm: 768px; +$bp_xs: 480px; - .footer { - border-top: 1px solid #EBEEF5; - } -} - -.echarts { - width: 800px; - height: 400px; - max-width: 100%; - margin: 0 auto; -} +$navbarHeight: 4rem; +$sidebarWidth: 16rem; +$mainPadding: 2rem; diff --git a/packages/plugin-status/client/index.ts b/packages/plugin-status/client/index.ts index 9969a59f4a..12f09ac28a 100644 --- a/packages/plugin-status/client/index.ts +++ b/packages/plugin-status/client/index.ts @@ -1,36 +1,83 @@ -import { ref, onMounted } from 'vue' -import type { Payload } from '~/server' -import BotTable from './components/bot-table.vue' -import GroupChart from './components/group-chart.vue' -import HistoryChart from './components/history-chart.vue' -import HourChart from './components/hour-chart.vue' -import LoadChart from './components/load-chart.vue' -import PluginList from './components/plugin-list.vue' -import WordCloud from './components/word-cloud.vue' - -export { - BotTable, - GroupChart, - HistoryChart, - HourChart, - LoadChart, - PluginList, - WordCloud, +/* eslint-disable no-undef */ + +import { ref, watch } from 'vue' +import type { User } from 'koishi-core' +import type { Registry, Profile, Statistics } from '~/server' + +const prefix = 'koishi:' + +export namespace storage { + export function get(key: string) { + if (typeof localStorage === 'undefined') return + const rawData = localStorage.getItem(prefix + key) + if (!rawData) return + try { + return JSON.parse(rawData) + } catch {} + } + + export function set(key: string, value: any) { + if (typeof localStorage === 'undefined') return + localStorage.setItem(prefix + key, JSON.stringify(value)) + } + + export function create(key: string, fallback?: T) { + const wrapper = ref({ ...fallback, ...get(key) }) + watch(wrapper, () => set(key, wrapper.value), { + deep: typeof fallback === 'object', + }) + return wrapper + } +} + +interface Config { + authType: 0 | 1 + username?: string + password?: string + platform?: string + userId?: string + showPass?: boolean } -export function useStatus() { - const status = ref(null) - - onMounted(async () => { - const socket = new WebSocket(KOISHI_ENDPOINT) - socket.onmessage = (ev) => { - const data = JSON.parse(ev.data) - console.log('receive', data) - if (data.type === 'update') { - status.value = data.body - } +export const user = storage.create('user') +export const config = storage.create('config', { authType: 0 }) +export const profile = ref(null) +export const registry = ref(null) +export const stats = ref(null) +export const socket = ref(null) + +const listeners: Record void> = {} + +export function start() { + socket.value = new WebSocket(KOISHI_ENDPOINT.replace(/^http/, 'ws')) + socket.value.onmessage = (ev) => { + const data = JSON.parse(ev.data) + console.log(data) + if (data.type in listeners) { + listeners[data.type](data.body) } - }) + } + receive('profile', data => profile.value = data) + receive('registry', data => registry.value = data) + receive('stats', data => stats.value = data) + receive('user', data => user.value = data) +} + +export function send(type: string, body: any) { + socket.value.send(JSON.stringify({ type, body })) +} + +export function receive(event: string, listener: (data: T) => void) { + listeners[event] = listener +} - return status +export async function sha256(password: string) { + const data = new TextEncoder().encode(password) + const buffer = await crypto.subtle.digest('SHA-256', data) + const view = new DataView(buffer) + let output = '' + for (let i = 0; i < view.byteLength; i += 4) { + output += ('00000000' + view.getUint32(i).toString(16)).slice(-8) + } + return output } diff --git a/packages/plugin-status/client/main.ts b/packages/plugin-status/client/main.ts index 3d5240b0e5..b95ed8a4a1 100644 --- a/packages/plugin-status/client/main.ts +++ b/packages/plugin-status/client/main.ts @@ -1,22 +1,99 @@ import { createApp } from 'vue' -import { ElCard, ElButton, ElCollapseTransition } from 'element-plus' +import { ElButton, ElCollapseTransition } from 'element-plus' import { THEME_KEY } from 'vue-echarts' -import Layout from '~/layout' +import { createRouter, createWebHistory } from 'vue-router' +import Card from './components/card.vue' +import Button from './components/button.vue' +import Input from './components/input.vue' +import App from './views/layout/index.vue' +import { start, user, receive } from '.' // for el-collapse-transition import 'element-plus/lib/theme-chalk/base.css' import 'element-plus/lib/theme-chalk/el-icon.css' -import 'element-plus/lib/theme-chalk/el-card.css' import 'element-plus/lib/theme-chalk/el-button.css' +import '@fortawesome/fontawesome-free/css/fontawesome.css' +import '@fortawesome/fontawesome-free/css/brands.css' +import '@fortawesome/fontawesome-free/css/regular.css' +import '@fortawesome/fontawesome-free/css/solid.css' + import './index.scss' -const app = createApp(Layout) +declare module 'vue-router' { + interface RouteMeta { + icon?: string + hidden?: boolean + authorize?: boolean + frameless?: boolean + require?: ('stats' | 'profile' | 'registry')[] + } +} + +const app = createApp(App) + +const router = createRouter({ + history: createWebHistory(), + routes: [{ + path: '/', + name: '仪表盘', + meta: { icon: 'tachometer-alt', require: ['stats', 'profile', 'registry'] }, + component: () => import('./views/home/index.vue'), + }, { + path: '/bots', + name: '机器人', + meta: { icon: 'robot', require: ['stats', 'profile'] }, + component: () => import('./views/bots.vue'), + }, { + path: '/plugins', + name: '插件', + meta: { icon: 'plug', require: ['registry'] }, + component: () => import('./views/plugins/index.vue'), + }, { + path: '/sandbox', + name: '沙盒', + meta: { icon: 'laptop-code', authorize: true }, + component: () => import('./views/sandbox.vue'), + }, { + path: '/profile', + name: '资料', + meta: { icon: 'user-circle', authorize: true, hidden: true }, + component: () => import('./views/profile.vue'), + }, { + path: '/login', + name: '登录', + meta: { icon: 'sign-in-alt', frameless: true, hidden: true }, + component: () => import('./views/login.vue'), + }], +}) -app.provide(THEME_KEY, 'light') +app.component('k-card', Card) +app.component('k-button', Button) +app.component('k-input', Input) + +app.provide(THEME_KEY, 'dark-blue') -app.use(ElCard) app.use(ElButton) app.use(ElCollapseTransition) +app.use(router) + +receive('expire', () => { + router.push('/login') +}) + +router.beforeEach((route) => { + if (route.meta.authorize && !user.value) { + return '/login' + } +}) + +router.afterEach((route) => { + if (typeof route.name === 'string') { + document.title = route.name + ' | Koishi 控制台' + } +}) + +start() + app.mount('#app') diff --git a/packages/plugin-status/client/views/bots.vue b/packages/plugin-status/client/views/bots.vue new file mode 100644 index 0000000000..4b1b3da842 --- /dev/null +++ b/packages/plugin-status/client/views/bots.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/packages/plugin-status/client/views/home/card-numeric.vue b/packages/plugin-status/client/views/home/card-numeric.vue new file mode 100644 index 0000000000..030d70f019 --- /dev/null +++ b/packages/plugin-status/client/views/home/card-numeric.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/packages/plugin-status/client/components/group-chart.vue b/packages/plugin-status/client/views/home/group-chart.vue similarity index 73% rename from packages/plugin-status/client/components/group-chart.vue rename to packages/plugin-status/client/views/home/group-chart.vue index 6be2442328..efbda0ffff 100644 --- a/packages/plugin-status/client/components/group-chart.vue +++ b/packages/plugin-status/client/views/home/group-chart.vue @@ -1,14 +1,14 @@ + + diff --git a/packages/plugin-status/client/components/load-bar.vue b/packages/plugin-status/client/views/home/load-bar.vue similarity index 52% rename from packages/plugin-status/client/components/load-bar.vue rename to packages/plugin-status/client/views/home/load-bar.vue index 2f181d5337..98f10b7b6f 100644 --- a/packages/plugin-status/client/components/load-bar.vue +++ b/packages/plugin-status/client/views/home/load-bar.vue @@ -1,12 +1,14 @@ @@ -22,8 +24,12 @@ function percentage(value: number, digits = 3) { return (value * 100).toFixed(digits) + '%' } -const mainly = computed(() => { - return 1 + props.rate[0] > 2 * props.rate[1] ? 'free' : 'busy' +const segments = ['used', 'app', 'free'] as const + +const mainly = computed(() => { + const length = [props.rate[1] - props.rate[0], props.rate[0], 1 - props.rate[1]] + const index = length.indexOf(Math.max(...length)) + return segments[index] }) const caption = computed(() => { @@ -32,11 +38,9 @@ const caption = computed(() => { - \ No newline at end of file diff --git a/packages/plugin-status/client/views/home/load-chart.vue b/packages/plugin-status/client/views/home/load-chart.vue new file mode 100644 index 0000000000..82533f02ff --- /dev/null +++ b/packages/plugin-status/client/views/home/load-chart.vue @@ -0,0 +1,13 @@ + + + diff --git a/packages/plugin-status/client/components/word-cloud.vue b/packages/plugin-status/client/views/home/word-cloud.vue similarity index 76% rename from packages/plugin-status/client/components/word-cloud.vue rename to packages/plugin-status/client/views/home/word-cloud.vue index 374d9ca148..917d40e357 100644 --- a/packages/plugin-status/client/components/word-cloud.vue +++ b/packages/plugin-status/client/views/home/word-cloud.vue @@ -1,5 +1,5 @@