diff --git a/packages/plugin-common/src/contextify.ts b/packages/plugin-common/src/contextify.ts deleted file mode 100644 index 087e03a277..0000000000 --- a/packages/plugin-common/src/contextify.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Context, getTargetId, Group, User, Session } from 'koishi-core' -import {} from 'koishi-adapter-cqhttp' - -export function apply(ctx: Context) { - ctx.command('contextify ', '在特定上下文中触发指令', { authority: 3 }) - .alias('ctxf') - .userFields(['authority']) - .before(session => !session.$app.database) - .option('user', '-u [id] 使用私聊上下文') - .option('group', '-g [id] 使用群聊上下文') - .option('member', '-m [id] 使用当前群/讨论组成员上下文') - .option('type', '-t [type] 确定发送信息的子类型') - .usage([ - '私聊的子类型包括 other(默认),friend,group。', - '群聊的子类型包括 normal(默认),notice,anonymous。', - '讨论组聊天没有子类型。', - ].join('\n')) - .action(async ({ session, options }, message) => { - if (!message) return '请输入要触发的指令。' - - if (options.member) { - if (session.messageType === 'private') { - return '无法在私聊上下文使用 --member 选项。' - } - options.group = session.groupId - options.user = options.member - } - - if (!options.user && !options.group) { - return '请提供新的上下文。' - } - - const newSession = new Session(ctx.app, session) - newSession.$send = session.$send.bind(session) - newSession.$sendQueued = session.$sendQueued.bind(session) - - delete newSession.groupId - - if (options.group) { - newSession.groupId = +options.group - newSession.messageType = 'group' - newSession.subType = options.type || 'normal' - delete newSession.$group - await newSession.$observeGroup(Group.fields) - } else { - newSession.messageType = 'private' - newSession.subType = options.type || 'other' - } - - if (options.user) { - const id = getTargetId(options.user) - if (!id) return '未指定目标。' - - newSession.userId = id - newSession.sender.userId = id - - delete newSession.$user - const user = await newSession.$observeUser(User.fields) - if (session.$user.authority <= user.authority) { - return '权限不足。' - } - } - - if (options.group) { - const info = await session.$bot.getGroupMemberInfo(newSession.groupId, newSession.userId).catch(() => ({})) - Object.assign(newSession.sender, info) - } else if (options.user) { - const info = await session.$bot.getStrangerInfo(newSession.userId).catch(() => ({})) - Object.assign(newSession.sender, info) - } - - return newSession.$execute(message) - }) -} diff --git a/packages/plugin-common/src/index.ts b/packages/plugin-common/src/index.ts index 4e0b94bf86..381c227a09 100644 --- a/packages/plugin-common/src/index.ts +++ b/packages/plugin-common/src/index.ts @@ -2,16 +2,15 @@ import { Context } from 'koishi-core' import { DebugOptions } from './debug' import repeater, { RepeaterOptions } from './repeater' import handler, { HandlerOptions } from './handler' -import sender, { SenderConfig } from './sender' +import sender from './sender' export * from './admin' export * from './info' export * from './repeater' -export interface Config extends HandlerOptions, RepeaterOptions, SenderConfig { +export interface Config extends HandlerOptions, RepeaterOptions { admin?: false broadcast?: false - contextify?: false echo?: false info?: false debug?: DebugOptions @@ -25,7 +24,6 @@ export function apply(ctx: Context, config: Config = {}) { ctx.plugin(sender, config) if (config.admin !== false) ctx.plugin(require('./admin')) - if (config.contextify !== false) ctx.plugin(require('./contextify')) if (config.debug) ctx.plugin(require('./debug'), config.debug) if (config.info !== false) ctx.plugin(require('./info')) } diff --git a/packages/plugin-common/src/sender.ts b/packages/plugin-common/src/sender.ts index 265b49be41..2e2f6ab0f3 100644 --- a/packages/plugin-common/src/sender.ts +++ b/packages/plugin-common/src/sender.ts @@ -1,14 +1,8 @@ -import { Context, Group } from 'koishi-core' +import { Context, getTargetId, Group, Session, User } from 'koishi-core' import { CQCode } from 'koishi-utils' -export interface SenderConfig { - broadcast?: false - echo?: false -} - -export default function apply(ctx: Context, config: SenderConfig = {}) { - config.broadcast !== false && ctx - .command('broadcast ', '全服广播', { authority: 4 }) +export default function apply(ctx: Context) { + ctx.command('broadcast ', '全服广播', { authority: 4 }) .before(session => !session.$app.database) .option('forced', '-f 无视 silent 标签进行广播') .option('only', '-o 仅向当前 Bot 负责的群进行广播') @@ -26,8 +20,7 @@ export default function apply(ctx: Context, config: SenderConfig = {}) { await session.$bot.broadcast(groups.map(g => g.id), message) }) - config.echo !== false && ctx - .command('echo ', '向当前上下文发送消息', { authority: 2 }) + ctx.command('echo ', '向当前上下文发送消息', { authority: 2 }) .option('anonymous', '-a 匿名发送消息', { authority: 3 }) .option('forceAnonymous', '-A 匿名发送消息', { authority: 3 }) .option('unescape', '-e 发送非转义的消息', { authority: 3 }) @@ -46,4 +39,75 @@ export default function apply(ctx: Context, config: SenderConfig = {}) { return message }) + + ctx.command('contextify ', '在特定上下文中触发指令', { authority: 3 }) + .alias('ctxf') + .userFields(['authority']) + .before(session => !session.$app.database) + .option('user', '-u [id] 使用私聊上下文') + .option('group', '-g [id] 使用群聊上下文') + .option('member', '-m [id] 使用当前群/讨论组成员上下文') + .option('type', '-t [type] 确定发送信息的子类型') + .usage([ + '私聊的子类型包括 other(默认),friend,group。', + '群聊的子类型包括 normal(默认),notice,anonymous。', + '讨论组聊天没有子类型。', + ].join('\n')) + .action(async ({ session, options }, message) => { + if (!message) return '请输入要触发的指令。' + + if (options.member) { + if (session.messageType === 'private') { + return '无法在私聊上下文使用 --member 选项。' + } + options.group = session.groupId + options.user = options.member + } + + if (!options.user && !options.group) { + return '请提供新的上下文。' + } + + const newSession = new Session(ctx.app, session) + newSession.$send = session.$send.bind(session) + newSession.$sendQueued = session.$sendQueued.bind(session) + + delete newSession.groupId + + if (!options.group) { + newSession.messageType = 'private' + newSession.subType = options.type || 'other' + delete newSession.$group + } else if (options.group !== session.groupId) { + newSession.groupId = +options.group + newSession.messageType = 'group' + newSession.subType = options.type || 'normal' + delete newSession.$group + await newSession.$observeGroup(Group.fields) + } + + if (options.user) { + const id = getTargetId(options.user) + if (!id) return '未指定目标。' + + newSession.userId = id + newSession.sender.userId = id + + delete newSession.$user + const user = await newSession.$observeUser(User.fields) + if (session.$user.authority <= user.authority) { + return '权限不足。' + } + } + + if (options.group) { + const info = await session.$bot.getGroupMemberInfo(newSession.groupId, newSession.userId).catch(() => ({})) + Object.assign(newSession.sender, info) + } else if (options.user) { + const info = await session.$bot.getStrangerInfo(newSession.userId).catch(() => ({})) + Object.assign(newSession.sender, info) + } + + return newSession.$execute(message) + }) } diff --git a/packages/plugin-common/tests/contextify.spec.ts b/packages/plugin-common/tests/contextify.spec.ts deleted file mode 100644 index fe354b14c3..0000000000 --- a/packages/plugin-common/tests/contextify.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { MockedApp } from 'koishi-test-utils' -import { contextify } from '../src' -import 'koishi-database-memory' - -const app = new MockedApp({ database: { memory: {} } }) -const session1 = app.session(123) -const session2 = app.session(123, 654) - -app.plugin(contextify) -app.command('show-context') - .action(({ meta }) => { - return meta.$send(`${meta.userId},${meta.$ctxType},${meta.$ctxId},${meta.$user?.id},${meta.$group?.id}`) - }) - -beforeAll(async () => { - await app.start() - await app.database.getUser(123, 3) - await app.database.getUser(456, 2) - await app.database.getUser(789, 4) - await app.database.getGroup(654, app.selfId) -}) - -test('check input', async () => { - await session1.shouldReply('ctxf -u 456', '请输入要触发的指令。') - await session2.shouldReply('ctxf -m foo show-context', '未指定目标。') - await session1.shouldReply('ctxf show-context', '请提供新的上下文。') - await session1.shouldReply('ctxf -u 789 show-context', '权限不足。') - await session1.shouldReply('ctxf -m 456 show-context', '无法在私聊上下文使用 --member 选项。') -}) - -test('user context', async () => { - await session1.shouldReply('ctxf -u 456 show-context', '456,user,456,456,undefined') - await session1.shouldReply('ctxf -g 654 show-context', '123,group,654,123,654') - await session1.shouldReply('ctxf -d 654 show-context', '123,discuss,654,123,undefined') - await session1.shouldReply('ctxf -u 456 -g 654 show-context', '456,group,654,456,654') - await session1.shouldReply('ctxf -u 456 -d 654 show-context', '456,discuss,654,456,undefined') -}) - -test('group context', async () => { - await session2.shouldReply('ctxf -u 456 show-context', '456,user,456,456,undefined') - await session2.shouldReply('ctxf -m 456 show-context', '456,group,654,456,654') -}) diff --git a/packages/plugin-common/tests/sender.spec.ts b/packages/plugin-common/tests/sender.spec.ts index 6df5043303..5e7cdc5d75 100644 --- a/packages/plugin-common/tests/sender.spec.ts +++ b/packages/plugin-common/tests/sender.spec.ts @@ -2,35 +2,71 @@ import { App } from 'koishi-test-utils' import { fn } from 'jest-mock' import { expect } from 'chai' import sender from '../src/sender' +import { StrangerInfo } from 'koishi-core' +import { GroupMemberInfo } from 'koishi-adapter-cqhttp' const app = new App({ mockDatabase: true }) -const session = app.session(123) +const session1 = app.session(123) +const session2 = app.session(123, 456) app.plugin(sender) +app.command('show-context') + .userFields(['id']) + .groupFields(['id']) + .action(({ session }) => { + return `${session.userId},${session.$user?.id},${session.$group?.id}` + }) + before(async () => { await app.database.getUser(123, 4) - await app.database.getGroup(456, 514) + await app.database.getUser(456, 3) + await app.database.getUser(789, 5) + await app.database.getGroup(456, app.selfId) }) describe('Sender Commands', () => { it('echo', async () => { - await session.shouldReply('echo', '请输入要发送的文本。') - await session.shouldReply('echo foo', 'foo') - await session.shouldReply('echo -e []', '[]') - await session.shouldReply('echo -A foo', '[CQ:anonymous]foo') - await session.shouldReply('echo -a foo', '[CQ:anonymous,ignore=true]foo') + await session1.shouldReply('echo', '请输入要发送的文本。') + await session1.shouldReply('echo foo', 'foo') + await session1.shouldReply('echo -e []', '[]') + await session1.shouldReply('echo -A foo', '[CQ:anonymous]foo') + await session1.shouldReply('echo -a foo', '[CQ:anonymous,ignore=true]foo') }) it('broadcast', async () => { const sendGroupMsg = app.bots[0].sendGroupMsg = fn() - await session.shouldReply('broadcast', '请输入要发送的文本。') + await session1.shouldReply('broadcast', '请输入要发送的文本。') expect(sendGroupMsg.mock.calls).to.have.length(0) - await session.shouldNotReply('broadcast foo') + await session1.shouldNotReply('broadcast foo') expect(sendGroupMsg.mock.calls).to.have.length(1) - await session.shouldNotReply('broadcast -o foo') + await session1.shouldNotReply('broadcast -o foo') expect(sendGroupMsg.mock.calls).to.have.length(2) - await session.shouldNotReply('broadcast -of foo') + await session1.shouldNotReply('broadcast -of foo') expect(sendGroupMsg.mock.calls).to.have.length(3) }) + + describe('Contextify', () => { + app.bots[0].getStrangerInfo = fn(async () => ({} as StrangerInfo)) + app.bots[0].getGroupMemberInfo = fn(async () => ({} as GroupMemberInfo)) + + it('check input', async () => { + await session1.shouldReply('ctxf -u 456', '请输入要触发的指令。') + await session2.shouldReply('ctxf -m foo show-context', '未指定目标。') + await session1.shouldReply('ctxf show-context', '请提供新的上下文。') + await session1.shouldReply('ctxf -u 789 show-context', '权限不足。') + await session1.shouldReply('ctxf -m 456 show-context', '无法在私聊上下文使用 --member 选项。') + }) + + it('user context', async () => { + await session1.shouldReply('ctxf -u 456 show-context', '456,456,undefined') + await session1.shouldReply('ctxf -g 456 show-context', '123,123,456') + await session1.shouldReply('ctxf -u 456 -g 456 show-context', '456,456,456') + }) + + it('group context', async () => { + await session2.shouldReply('ctxf -u 456 show-context', '456,456,undefined') + await session2.shouldReply('ctxf -m 456 show-context', '456,456,456') + }) + }) })