Skip to content

Commit

Permalink
eval/addons: load user on demand
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Aug 25, 2020
1 parent 8bf16d6 commit 66fdf1b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 25 deletions.
31 changes: 19 additions & 12 deletions packages/plugin-eval-addons/src/index.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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> = T[] | {
read?: T[]
write?: T[]
}

interface CommandManifest extends CommandConfig {
name: string
desc: string
options?: Option[]
options?: OptionManifest[]
userFields?: Permission<User.Field>
}

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) {
Expand Down Expand Up @@ -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)
Expand Down
16 changes: 10 additions & 6 deletions packages/plugin-eval-addons/src/worker.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -17,28 +18,31 @@ declare module 'koishi-plugin-eval/dist/worker' {
}

interface WorkerAPI {
addon(sid: string, user: {}, argv: WorkerArgv): string | void | Promise<string | void>
addon(sid: string, user: Partial<User>, argv: AddonArgv): Promise<string | void>
}

interface Response {
commands: string[]
}
}

interface WorkerArgv {
interface AddonArgv {
name: string
args: string[]
options: Record<string, any>
rest: string
}

type AddonAction = (argv: WorkerArgv) => string | void | Promise<string | void>
interface AddonContext extends AddonArgv {
user: Partial<User>
}

type AddonAction = (ctx: AddonContext) => string | void | Promise<string | void>
const commandMap: Record<string, AddonAction> = {}

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)
}
Expand Down
3 changes: 1 addition & 2 deletions packages/plugin-eval/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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) => {
Expand Down
8 changes: 3 additions & 5 deletions packages/plugin-eval/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const config: WorkerData = {

interface EvalOptions {
sid: string
user: {}
silent: boolean
source: string
}
Expand Down Expand Up @@ -72,9 +71,8 @@ function formatError(error: Error) {

const main = wrap<MainAPI>(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))
},
Expand All @@ -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 {
Expand Down

0 comments on commit 66fdf1b

Please sign in to comment.