diff --git a/packages/core/src/app.ts b/packages/core/src/app.ts index f47c666d92..6dcaaf7aee 100644 --- a/packages/core/src/app.ts +++ b/packages/core/src/app.ts @@ -55,7 +55,7 @@ export class App extends Context { if (!key) return const segments = key.split('.') let i = 1, name = segments[0], cmd: Command - while ((cmd = this._commands.get(name)) && i < segments.length) { + while ((cmd = this.getCommand(name)) && i < segments.length) { name = cmd.name + '.' + segments[i++] } return cmd diff --git a/packages/core/src/command.ts b/packages/core/src/command.ts index 57c2c63991..f72263fd04 100644 --- a/packages/core/src/command.ts +++ b/packages/core/src/command.ts @@ -104,7 +104,7 @@ export class Command(def: D, config?: Command.Config): Command> command(def: D, desc: string, config?: Command.Config): Command> command(def: string, ...args: [Command.Config?] | [string, Command.Config?]) { @@ -500,7 +504,7 @@ export class Context { segments.forEach((segment, index) => { const code = segment.charCodeAt(0) const name = code === 46 ? parent.name + segment : code === 47 ? segment.slice(1) : segment - let command = this.app._commands.get(name) + let command = this.getCommand(name) if (command) { if (parent) { if (command === parent) { diff --git a/packages/core/src/internal/help.ts b/packages/core/src/internal/help.ts index 9f02292382..0f78f43f2f 100644 --- a/packages/core/src/internal/help.ts +++ b/packages/core/src/internal/help.ts @@ -17,15 +17,7 @@ export interface HelpConfig extends Command.Config { } export function enableHelp(cmd: Command) { - return cmd - .option('help', '-h 显示此信息', { hidden: true }) - .before(async ({ session, options }, ...args) => { - if (cmd['_actions'].length && !options['help']) return - return session.execute({ - name: 'help', - args: [cmd.name], - }) - }) + return cmd.option('help', '-h 显示此信息', { hidden: true }) } export default function help(ctx: Context, config: HelpConfig = {}) { @@ -73,7 +65,7 @@ export default function help(ctx: Context, config: HelpConfig = {}) { prefix: template('internal.help-suggestion-prefix'), suffix: template('internal.help-suggestion-suffix'), async apply(suggestion) { - return showHelp(app._commands.get(suggestion), this as any, options) + return showHelp(ctx.getCommand(suggestion), this as any, options) }, }) return diff --git a/packages/core/src/internal/runtime.ts b/packages/core/src/internal/runtime.ts index 1a4727d312..e41a4efa9c 100644 --- a/packages/core/src/internal/runtime.ts +++ b/packages/core/src/internal/runtime.ts @@ -1,6 +1,7 @@ import { defineProperty, template, valueMap } from '@koishijs/utils' import { Argv } from '../parser' import { Context } from '../context' +import { Session } from '../session' import { getCommandNames } from './help' export default function runtime(ctx: Context) { @@ -83,4 +84,28 @@ export default function runtime(ctx: Context) { }, }) }) + + function executeHelp(session: Session, name: string) { + if (!ctx.getCommand('help')) return + return session.execute({ + name: 'help', + args: [name], + }) + } + + ctx.before('command/execute', (argv) => { + const { args, command, options, session } = argv + if (options['help'] && command._options.help) { + return executeHelp(session, command.name) + } + + if (command['_actions'].length) return + const arg0 = args.shift() || '' + const subcommand = ctx.getCommand(command.name + '.' + arg0) + if (subcommand) { + return session.execute({ ...argv, command: subcommand }) + } else { + return executeHelp(session, command.name) + } + }) } diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index afc702471f..856bc16ace 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -340,7 +340,7 @@ export class Session { it('disable help command', async () => { const app = new App({ help: false }) app.plugin(mock) - app.command('foo') + app.command('foo').action(() => {}) await app.start() const client = app.mock.client('123') @@ -149,7 +149,7 @@ describe('Help Command', () => { it('disable help options', async () => { const app = new App({ help: { options: false } }) app.plugin(mock) - app.command('foo') + app.command('foo').action(() => {}) await app.start() const client = app.mock.client('123') diff --git a/plugins/common/forward/src/index.ts b/plugins/common/forward/src/index.ts index fb2a2eaf4d..330698e988 100644 --- a/plugins/common/forward/src/index.ts +++ b/plugins/common/forward/src/index.ts @@ -1,4 +1,4 @@ -import { Context, Session, Dict, Time, template, Schema } from 'koishi' +import { Context, Session, Dict, Time, template, Schema, Command } from 'koishi' import { parsePlatform } from '@koishijs/helpers' declare module 'koishi' { @@ -95,48 +95,46 @@ export function apply(ctx: Context, { rules, interval }: Config) { }) ctx.using(['database'], (ctx) => { - ctx.command('forward ', '设置消息转发', { authority: 3, checkUnknown: true }) - .channelFields(['forward']) - .option('add', '-a 添加目标频道') - .option('delete', '-d 移除目标频道') - .option('clear', '-c 移除全部目标频道') - .option('list', '-l 查看目标频道列表') + const cmd = ctx + .command('forward [operation:string] ', '设置消息转发', { authority: 3 }) .usage(session => `当前频道 ID:${session.cid}`) - .before(async ({ session, options }, id) => { - if (options.add || options.delete) { - return id ? null : '请提供目标频道。' - } else if (Object.keys(options).length) { - return - } - return session.execute({ - name: 'help', - args: ['forward'], - }) - }) - .action(async ({ session, options }, id) => { - const { forward } = session.channel - if (options.add) { - if (forward.includes(id)) { - return `${id} 已经是当前频道的目标频道。` - } else { - forward.push(id) - return `已成功添加目标频道 ${id}。` - } - } else if (options.delete) { - const index = forward.indexOf(id) - if (index >= 0) { - forward.splice(index, 1) - return `已成功移除目标频道 ${id}。` - } else { - return `${id} 不是当前频道的目标频道。` - } - } else if (options.clear) { - session.channel.forward = [] - return '已成功移除全部目标频道。' - } else if (options.list) { - if (!forward.length) return '当前频道没有设置目标频道。' - return ['当前频道的目标频道列表为:', ...forward].join('\n') - } - }) + .alias('fwd') + + const register = (def: string, desc: string, callback: Command.Action) => cmd + .subcommand(def, desc, { authority: 3, checkArgCount: true }) + .channelFields(['forward']) + .action(callback) + + register('.add ', '添加目标频道', async ({ session }, id) => { + const { forward } = session.channel + if (forward.includes(id)) { + return `${id} 已经是当前频道的目标频道。` + } else { + forward.push(id) + return `已成功添加目标频道 ${id}。` + } + }) + + register('.remove ', '移除目标频道', async ({ session }, id) => { + const { forward } = session.channel + const index = forward.indexOf(id) + if (index >= 0) { + forward.splice(index, 1) + return `已成功移除目标频道 ${id}。` + } else { + return `${id} 不是当前频道的目标频道。` + } + }).alias('forward.rm') + + register('.clear', '移除全部目标频道', async ({ session }) => { + session.channel.forward = [] + return '已成功移除全部目标频道。' + }) + + register('.list', '查看目标频道列表', async ({ session }) => { + const { forward } = session.channel + if (!forward.length) return '当前频道没有设置目标频道。' + return ['当前频道的目标频道列表为:', ...forward].join('\n') + }).alias('forward.ls') }) } diff --git a/plugins/common/forward/tests/index.spec.ts b/plugins/common/forward/tests/index.spec.ts index 8cc7059d74..a1c0bf5218 100644 --- a/plugins/common/forward/tests/index.spec.ts +++ b/plugins/common/forward/tests/index.spec.ts @@ -50,10 +50,10 @@ describe('@koishijs/plugin-forward', () => { await app.mock.initUser('123', 3) await session2.shouldReply('forward', /设置消息转发/) - await session2.shouldReply('forward -a #123', '已成功添加目标频道 mock:123。') - await session2.shouldReply('forward -l', '当前频道的目标频道列表为:\nmock:123') - await session2.shouldReply('forward -d #123', '已成功移除目标频道 mock:123。') - await session2.shouldReply('forward -l', '当前频道没有设置目标频道。') - await session2.shouldReply('forward -c', '已成功移除全部目标频道。') + await session2.shouldReply('forward add #123', '已成功添加目标频道 mock:123。') + await session2.shouldReply('forward ls', '当前频道的目标频道列表为:\nmock:123') + await session2.shouldReply('forward rm #123', '已成功移除目标频道 mock:123。') + await session2.shouldReply('forward ls', '当前频道没有设置目标频道。') + await session2.shouldReply('forward clear', '已成功移除全部目标频道。') }) })