From 5b180ce94c6dbb8e5b24226299a0ea013b37ebb4 Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 3 Jul 2023 02:41:44 +0800 Subject: [PATCH] feat(core): support slash commands --- packages/core/package.json | 2 +- packages/core/src/command/command.ts | 34 ++++++++++++++++++++++++++-- packages/core/src/command/index.ts | 18 ++++++++++++++- packages/core/src/middleware.ts | 5 ++++ packages/koishi/package.json | 2 +- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 6e01fd50e2..37a1079c8d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -33,7 +33,7 @@ "@koishijs/i18n-utils": "^1.0.0", "@koishijs/utils": "^7.0.2", "@minatojs/core": "^2.3.2", - "@satorijs/core": "^2.4.0", + "@satorijs/core": "^2.5.0", "cordis": "^2.8.0", "cosmokit": "^1.4.2", "fastest-levenshtein": "^1.0.16" diff --git a/packages/core/src/command/command.ts b/packages/core/src/command/command.ts index 1097421f4a..01ba40d7e8 100644 --- a/packages/core/src/command/command.ts +++ b/packages/core/src/command/command.ts @@ -1,6 +1,6 @@ -import { Awaitable, camelize, Dict, isNullable, remove } from 'cosmokit' +import { Awaitable, camelize, Dict, isNullable, remove, valueMap } from 'cosmokit' import { coerce } from '@koishijs/utils' -import { Context, Fragment, Logger, Schema, Session } from '@satorijs/core' +import { Context, Fragment, Logger, Schema, Session, Universal } from '@satorijs/core' import { Disposable } from 'cordis' import { Argv } from './parser' import { Next, SessionError } from '../middleware' @@ -334,6 +334,33 @@ export class Command store[`commands.${this.name}.description`] as string), + arguments: this._arguments.map(arg => ({ + name: arg.name, + type: toStringType(arg.type), + description: { '': toStringType(arg.type) }, + required: arg.required, + })), + options: Object.entries(this._options).map(([name, option]) => ({ + name, + type: toStringType(option.type), + description: valueMap(this.ctx.i18n._data, (store) => store[`commands.${this.name}.options.${name}`] as string), + required: option.required, + })), + children: this.children + .filter(child => child.name.includes('.')) + .map(child => child.toJSON()), + } + } +} + +function toStringType(type: Argv.Type) { + return typeof type === 'string' ? type : 'string' } export namespace Command { @@ -350,10 +377,13 @@ export namespace Command { handleError?: boolean | ((error: Error, argv: Argv) => Awaitable) /** depend on existing commands */ patch?: boolean + /** enable slash integration */ + slash?: boolean } export const Config: Schema = Schema.object({ authority: Schema.computed(Schema.natural()).description('指令的权限等级。').default(1), + slash: Schema.boolean().description('启用 slash 集成功能。'), checkUnknown: Schema.boolean().description('是否检查未知选项。').default(false).hidden(), checkArgCount: Schema.boolean().description('是否检查参数数量。').default(false).hidden(), showWarning: Schema.boolean().description('是否显示警告。').default(true).hidden(), diff --git a/packages/core/src/command/index.ts b/packages/core/src/command/index.ts index 67e90f1c93..ac66579ea6 100644 --- a/packages/core/src/command/index.ts +++ b/packages/core/src/command/index.ts @@ -1,5 +1,5 @@ import { Awaitable, defineProperty } from 'cosmokit' -import { Context, h, Schema, Session } from '@satorijs/core' +import { Bot, Context, h, Schema, Session } from '@satorijs/core' import { Command } from './command' import { Argv } from './parser' import validate from './validate' @@ -105,6 +105,22 @@ export class Commander extends Map { ctx.schema.extend('command-option', Schema.object({ authority: Schema.computed(Schema.natural()).description('选项的权限等级。').default(0), }), 1000) + + ctx.on('ready', () => { + const bots = ctx.bots.filter(v => v.status === 'online' && v.updateCommands) + bots.forEach(bot => this.updateCommands(bot)) + }) + + ctx.on('bot-status-updated', async (bot) => { + if (bot.status !== 'online' || !bot.updateCommands) return + this.updateCommands(bot) + }) + } + + updateCommands(bot: Bot) { + return bot.updateCommands(this._commandList + .filter(cmd => !cmd.name.includes('.')) + .map(cmd => cmd.toJSON())) } private _resolvePrefixes(session: Session) { diff --git a/packages/core/src/middleware.ts b/packages/core/src/middleware.ts index 81a8d1e9ba..3f7e83e0e8 100644 --- a/packages/core/src/middleware.ts +++ b/packages/core/src/middleware.ts @@ -83,6 +83,11 @@ export class Processor { this.middleware(this._process.bind(this), true) ctx.on('message', this._handleMessage.bind(this)) + ctx.on('interaction/command', (session) => { + const { name, options, arguments: args } = session.data.command + session.execute({ name, args, options }) + }) + ctx.before('attach-user', (session, fields) => { session.collect('user', session.argv, fields) }) diff --git a/packages/koishi/package.json b/packages/koishi/package.json index 746e8b6f8c..dbe81900c6 100644 --- a/packages/koishi/package.json +++ b/packages/koishi/package.json @@ -49,7 +49,7 @@ "@koishijs/core": "4.13.5", "@koishijs/loader": "4.0.0", "@koishijs/utils": "^7.0.2", - "@satorijs/satori": "^2.4.0", + "@satorijs/satori": "^2.5.0", "cac": "^6.7.14", "kleur": "^4.1.5", "ns-require": "^1.1.4"