Skip to content

Commit

Permalink
feat(common): enhance repeater config
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Mar 5, 2021
1 parent e255886 commit 4280a42
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 115 deletions.
25 changes: 18 additions & 7 deletions packages/plugin-common/src/repeater.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context } from 'koishi-core'
import { Context, Session, Random } from 'koishi-core'

declare module 'koishi-core' {
interface EventMap {
Expand All @@ -13,11 +13,22 @@ interface RepeatState {
users: Record<number, number>
}

type RepeatHandler = (state: RepeatState, content: string, userId: string) => void | string
type StateCallback = (state: RepeatState, session: Session) => void | string

interface RepeatHandler {
minTimes: number
probability?: number
}

export interface RepeaterOptions {
onRepeat?: RepeatHandler
onInterrupt?: RepeatHandler
onRepeat?: RepeatHandler | StateCallback
onInterrupt?: StateCallback
}

function onRepeat(options: RepeatHandler | StateCallback): StateCallback {
if (!options || typeof options !== 'object') return options as StateCallback
const { minTimes, probability = 1 } = options
return ({ repeated, times, content }) => times >= minTimes && !repeated && Random.bool(probability) ? content : ''
}

export default function apply(ctx: Context, options: RepeaterOptions = {}) {
Expand Down Expand Up @@ -53,8 +64,8 @@ export default function apply(ctx: Context, options: RepeaterOptions = {}) {
if (ctx.bots[uid]) return

const state = getState(session.cid)
const check = (handle: RepeatHandler) => {
const text = handle?.(state, content, userId)
const check = (handle: StateCallback) => {
const text = handle?.(state, session)
return text && next(() => {
ctx.emit('repeater', session, state)
return session.send(text)
Expand All @@ -65,7 +76,7 @@ export default function apply(ctx: Context, options: RepeaterOptions = {}) {
if (content === state.content) {
state.times += 1
state.users[userId] = (state.users[userId] || 0) + 1
return check(options.onRepeat) || next()
return check(onRepeat(options.onRepeat)) || next()
}

// interrupt repeating
Expand Down
17 changes: 1 addition & 16 deletions packages/plugin-common/tests/handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import { sleep, Session } from 'koishi-core'
import jest from 'jest-mock'
import * as common from 'koishi-plugin-common'

const app = new App({ mockDatabase: true })

const app = new App()
const session = app.session('123')

const options: common.Config = {
Expand All @@ -20,11 +19,6 @@ const options: common.Config = {

app.plugin(common, options)

before(async () => {
await app.database.initUser('123', 3)
await app.database.initChannel('123')
})

function receive(session: Partial<Session>) {
app.receive(session)
return sleep(0)
Expand Down Expand Up @@ -78,15 +72,12 @@ describe('Common Handlers', () => {
options.onGroupMemberRequest = 'bar'

await receiveFriendRequest('321')
expect(handleFriendRequest.mock.calls).to.have.length(1)
expect(handleFriendRequest.mock.calls).to.have.shape([['flag', true, 'foo']])

await receiveGroupRequest('321')
expect(handleGroupRequest.mock.calls).to.have.length(1)
expect(handleGroupRequest.mock.calls).to.have.shape([['flag', false, 'baz']])

await receiveGroupMemberRequest('321')
expect(handleGroupMemberRequest.mock.calls).to.have.length(1)
expect(handleGroupMemberRequest.mock.calls).to.have.shape([['flag', false, 'bar']])
})

Expand All @@ -96,15 +87,12 @@ describe('Common Handlers', () => {
options.onGroupMemberRequest = false

await receiveFriendRequest('321')
expect(handleFriendRequest.mock.calls).to.have.length(1)
expect(handleFriendRequest.mock.calls).to.have.shape([['flag', false]])

await receiveGroupRequest('321')
expect(handleGroupRequest.mock.calls).to.have.length(1)
expect(handleGroupRequest.mock.calls).to.have.shape([['flag', false]])

await receiveGroupMemberRequest('321')
expect(handleGroupMemberRequest.mock.calls).to.have.length(1)
expect(handleGroupMemberRequest.mock.calls).to.have.shape([['flag', false]])
})

Expand All @@ -114,15 +102,12 @@ describe('Common Handlers', () => {
options.onGroupMemberRequest = () => true

await receiveFriendRequest('321')
expect(handleFriendRequest.mock.calls).to.have.length(1)
expect(handleFriendRequest.mock.calls).to.have.shape([['flag', true]])

await receiveGroupRequest('321')
expect(handleGroupRequest.mock.calls).to.have.length(1)
expect(handleGroupRequest.mock.calls).to.have.shape([['flag', true]])

await receiveGroupMemberRequest('321')
expect(handleGroupMemberRequest.mock.calls).to.have.length(1)
expect(handleGroupMemberRequest.mock.calls).to.have.shape([['flag', true]])
})

Expand Down
40 changes: 0 additions & 40 deletions packages/plugin-common/tests/info.spec.ts

This file was deleted.

92 changes: 40 additions & 52 deletions packages/plugin-common/tests/repeater.spec.ts
Original file line number Diff line number Diff line change
@@ -1,67 +1,55 @@
import { App } from 'koishi-test-utils'
import repeater from '../src/repeater'
import * as common from 'koishi-plugin-common'

it.only('repeat', async () => {
const app = new App()
const session1 = app.session(123, 123)
const app = new App()
const session1 = app.session('123', '123')
const session2 = app.session('456', '123')
const session3 = app.session('789', '123')

app.plugin(repeater, {
onRepeat: ({ repeated, times }, message) => !repeated && times >= 2 ? message : '',
})
const options: common.Config = {}
app.plugin(common, options)

await session1.shouldNotReply('foo')
await session1.shouldReply('foo', 'foo')
await session1.shouldNotReply('foo')
await session1.shouldNotReply('foo')
})
describe('Repeater', () => {
beforeEach(async () => {
options.onRepeat = null
options.onInterrupt = null
await session1.shouldNotReply('clear')
})

it('interrupt', async () => {
const app = new App()
const session1 = app.session(123, 123)
it('repeat (basic config)', async () => {
options.onRepeat = { minTimes: 2 }

app.plugin(repeater, {
repeat: (_, times) => times >= 2,
interrupt: (_, times) => times >= 4,
repeatCheck: false,
interruptCheck: false,
await session1.shouldNotReply('foo')
await session1.shouldReply('foo', 'foo')
await session1.shouldNotReply('foo')
await session1.shouldNotReply('foo')
})

await session1.shouldNotReply('foo')
await session1.shouldReply('foo', 'foo')
await session1.shouldReply('foo', '打断复读!')
})

it('repeat check', async () => {
const app = new App()
const session1 = app.session(123, 123)
const session2 = app.session(456, 123)
it('repeat check', async () => {
options.onRepeat = ({ users }, { userId }) => users[userId] > 2 ? '在?为什么重复复读?' : ''

app.plugin(repeater, {
repeat: (_, times) => times >= 2,
interrupt: false,
repeatCheck: (_, times) => times >= 2,
interruptCheck: false,
await session1.shouldNotReply('foo')
await session2.shouldNotReply('foo')
await session3.shouldNotReply('foo')
await session1.shouldNotReply('foo')
await session1.shouldReply('foo', '在?为什么重复复读?')
})

await session1.shouldNotReply('foo')
await session1.shouldReply('foo', 'foo')
await session2.shouldReply('foo', 'foo')
await session2.shouldReply('foo', `[CQ:at,qq=${session2.userId}] 在?为什么重复复读?`)
})

it('interrupt check', async () => {
const app = new App()
const session1 = app.session(123, 123)
it('interrupt', async () => {
options.onRepeat = ({ times }) => times >= 3 ? '打断复读!' : ''

app.plugin(repeater, {
repeat: (_, times) => times >= 2,
interrupt: false,
repeatCheck: false,
interruptCheck: (_, times) => times >= 2,
await session1.shouldNotReply('foo')
await session2.shouldNotReply('foo')
await session3.shouldReply('foo', '打断复读!')
})

await session1.shouldNotReply('foo')
await session1.shouldNotReply('bar')
await session1.shouldReply('bar', 'bar')
await session1.shouldReply('foo', `[CQ:at,qq=${session1.userId}] 在?为什么打断复读?`)
it('interrupt check', async () => {
options.onInterrupt = ({ times }) => times >= 2 ? '在?为什么打断复读?' : ''

await session1.shouldNotReply('foo')
await session2.shouldNotReply('bar')
await session1.shouldNotReply('foo')
await session2.shouldNotReply('foo')
await session3.shouldReply('bar', '在?为什么打断复读?')
})
})

0 comments on commit 4280a42

Please sign in to comment.