diff --git a/packages/plugin-common/src/basic.ts b/packages/plugin-common/src/basic.ts index c69c25f3c9..594d2ad1da 100644 --- a/packages/plugin-common/src/basic.ts +++ b/packages/plugin-common/src/basic.ts @@ -12,13 +12,6 @@ template.set('common', { 'relay': '{0}: {1}', }) -interface RelayOptions { - source: string - destination: string - selfId?: string - lifespan?: number -} - export function broadcast(ctx: Context) { ctx.select('database') .command('common/broadcast ', '全服广播', { authority: 4 }) @@ -169,6 +162,40 @@ export function feedback(ctx: Context, operators: string[]) { }) } +export interface RecallConfig { + recallCount?: number +} + +export function recall(ctx: Context, { recallCount = 10 }: RecallConfig) { + ctx = ctx.group() + const recent: Record = {} + + ctx.on('send', (session) => { + const list = recent[session.channelId] ||= [] + list.unshift(session.messageId) + if (list.length > recallCount) { + list.pop() + } + }) + + ctx.command('common/recall [count:number]', '撤回 bot 发送的消息', { authority: 2 }) + .action(({ session }, count = 1) => { + const list = recent[session.channelId] + if (!list) return '近期没有发送消息。' + list.splice(0, count).map((id) => { + return session.bot.deleteMessage(session.channelId, id) + }) + if (!list.length) delete recent[session.channelId] + }) +} + +interface RelayOptions { + source: string + destination: string + selfId?: string + lifespan?: number +} + export function relay(ctx: Context, relays: RelayOptions[]) { const relayMap: Record = {} @@ -212,7 +239,7 @@ export function respond(ctx: Context, respondents: Respondent[]) { }) } -export interface BasicConfig { +export interface BasicConfig extends RecallConfig { echo?: boolean broadcast?: boolean contextify?: boolean @@ -225,6 +252,7 @@ export default function apply(ctx: Context, config: BasicConfig = {}) { if (config.broadcast !== false) ctx.plugin(broadcast) if (config.contextify !== false) ctx.plugin(contextify) if (config.echo !== false) ctx.plugin(echo) + if (config.recallCount !== 0) ctx.plugin(recall, config) const operators = makeArray(config.operator) if (operators.length) ctx.plugin(feedback, operators) diff --git a/packages/plugin-common/tests/basic.spec.ts b/packages/plugin-common/tests/basic.spec.ts index 199680a030..d0772fcce0 100644 --- a/packages/plugin-common/tests/basic.spec.ts +++ b/packages/plugin-common/tests/basic.spec.ts @@ -109,6 +109,14 @@ describe('Common Plugin - Basic', () => { expect(send2.mock.calls).to.have.shape([['private:123', 'bar']]) }) + it('recall', async () => { + const del = app.bots[0].deleteMessage = jest.fn() + await session2.shouldReply('recall', '近期没有发送消息。') + app.receive(app.bots[0].createSession({ messageId: '1234', channelId: '456', groupId: '456' }).toJSON()) + await session2.shouldNotReply('recall') + expect(del.mock.calls).to.have.shape([[session2.meta.channelId, '1234']]) + }) + it('relay', async () => { const send = app.bots[0].sendMessage = jest.fn(async () => '2000') await session2.shouldNotReply('hello')