From 66fdf1bb940a3289837c49d3c3fca341b209b884 Mon Sep 17 00:00:00 2001 From: Shigma <1700011071@pku.edu.cn> Date: Wed, 26 Aug 2020 01:42:40 +0800 Subject: [PATCH] eval/addons: load user on demand --- packages/plugin-eval-addons/src/index.ts | 31 ++++++++++++++--------- packages/plugin-eval-addons/src/worker.ts | 16 +++++++----- packages/plugin-eval/src/index.ts | 3 +-- packages/plugin-eval/src/worker.ts | 8 +++--- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/packages/plugin-eval-addons/src/index.ts b/packages/plugin-eval-addons/src/index.ts index 302000c26f..e6b98eb5ab 100644 --- a/packages/plugin-eval-addons/src/index.ts +++ b/packages/plugin-eval-addons/src/index.ts @@ -1,4 +1,4 @@ -import { Context, CommandAction, CommandConfig, OptionConfig, User } from 'koishi-core' +import { Context, CommandConfig, OptionConfig, User } from 'koishi-core' import { resolve } from 'path' import {} from 'koishi-plugin-eval' import { assertProperty, Logger, noop } from 'koishi-utils' @@ -14,24 +14,26 @@ export interface Config { exclude?: RegExp } -interface Option extends OptionConfig { +interface OptionManifest extends OptionConfig { name: string desc: string } -interface Command extends CommandConfig { +type Permission = T[] | { + read?: T[] + write?: T[] +} + +interface CommandManifest extends CommandConfig { name: string desc: string - options?: Option[] + options?: OptionManifest[] + userFields?: Permission } interface Manifest { version: number - commands?: Command[] -} - -const addonAction: CommandAction = ({ session, command: { name }, options, rest }, ...args) => { - return session.$app.evalRemote.addon(session.$uuid, session.$user, { name, args, options, rest }) + commands?: CommandManifest[] } export function apply(ctx: Context, config: Config) { @@ -76,15 +78,20 @@ export function apply(ctx: Context, config: Config) { if (!content) return const { commands = [] } = safeLoad(content) as Manifest commands.forEach((config) => { - const { name: rawName, desc, options = [] } = config + const { name: rawName, desc, options = [], userFields = [] } = config const [name] = rawName.split(' ', 1) if (!response.commands.includes(name)) { return logger.warn('unregistered command manifest: %c', name) } + const { read = [] } = Array.isArray(userFields) ? { read: userFields } : userFields const cmd = addon .subcommand(rawName, desc, config) - .userFields(User.fields) - .action(addonAction) + .userFields(read) + .action(async ({ session, command: { name }, options }, ...args) => { + const { $app, $user, $uuid } = session + const result = await $app.evalRemote.addon($uuid, $user, { name, args, options }) + return result + }) options.forEach((config) => { const { name, desc } = config cmd.option(name, desc, config) diff --git a/packages/plugin-eval-addons/src/worker.ts b/packages/plugin-eval-addons/src/worker.ts index 2bcb67c3f7..88bf4afbe0 100644 --- a/packages/plugin-eval-addons/src/worker.ts +++ b/packages/plugin-eval-addons/src/worker.ts @@ -1,6 +1,7 @@ -import { config, context, internal, WorkerAPI, contextFactory, response } from 'koishi-plugin-eval/dist/worker' +import { config, context, internal, WorkerAPI, createContext, response } from 'koishi-plugin-eval/dist/worker' import { promises, readFileSync } from 'fs' import { resolve, posix, dirname } from 'path' +import { User } from 'koishi-core' import { Logger } from 'koishi-utils' import { Config } from '.' import ts from 'typescript' @@ -17,7 +18,7 @@ declare module 'koishi-plugin-eval/dist/worker' { } interface WorkerAPI { - addon(sid: string, user: {}, argv: WorkerArgv): string | void | Promise + addon(sid: string, user: Partial, argv: AddonArgv): Promise } interface Response { @@ -25,20 +26,23 @@ declare module 'koishi-plugin-eval/dist/worker' { } } -interface WorkerArgv { +interface AddonArgv { name: string args: string[] options: Record - rest: string } -type AddonAction = (argv: WorkerArgv) => string | void | Promise +interface AddonContext extends AddonArgv { + user: Partial +} + +type AddonAction = (ctx: AddonContext) => string | void | Promise const commandMap: Record = {} WorkerAPI.prototype.addon = async function (sid, user, argv) { const callback = commandMap[argv.name] try { - return await callback({ ...argv, ...contextFactory(sid, user) }) + return await callback({ user, ...argv, ...createContext(sid) }) } catch (error) { logger.warn(error) } diff --git a/packages/plugin-eval/src/index.ts b/packages/plugin-eval/src/index.ts index 974d681509..27e9f98583 100644 --- a/packages/plugin-eval/src/index.ts +++ b/packages/plugin-eval/src/index.ts @@ -148,7 +148,7 @@ export function apply(ctx: Context, config: Config = {}) { const evaluate = ctx.command('evaluate [expr...]', '执行 JavaScript 脚本') .alias('eval') - .userFields(User.fields) + .userFields(['authority']) .option('slient', '-s 不输出最后的结果') .option('restart', '-r 重启子线程', { authority: 3 }) .before((session) => { @@ -191,7 +191,6 @@ export function apply(ctx: Context, config: Config = {}) { app.evalWorker.on('error', listener) app.evalRemote.eval({ sid: session.$uuid, - user: session.$user, silent: options.slient, source: expr, }).then(_resolve, (error) => { diff --git a/packages/plugin-eval/src/worker.ts b/packages/plugin-eval/src/worker.ts index d596c14110..b5dd756bb7 100644 --- a/packages/plugin-eval/src/worker.ts +++ b/packages/plugin-eval/src/worker.ts @@ -29,7 +29,6 @@ export const config: WorkerData = { interface EvalOptions { sid: string - user: {} silent: boolean source: string } @@ -72,9 +71,8 @@ function formatError(error: Error) { const main = wrap(parentPort) -export function contextFactory(sid: string, user: {}) { +export function createContext(sid: string) { return { - user, async send(...param: [string, ...any[]]) { return await main.send(sid, formatResult(...param)) }, @@ -97,10 +95,10 @@ export class WorkerAPI { } async eval(options: EvalOptions) { - const { sid, source, user, silent } = options + const { sid, source, silent } = options const key = 'koishi-eval-session:' + sid - internal.setGlobal(Symbol.for(key), contextFactory(sid, user), false, true) + internal.setGlobal(Symbol.for(key), createContext(sid), false, true) let result: any try {