diff --git a/README.md b/README.md
index e1e5a590b6..02ad1fc05a 100644
--- a/README.md
+++ b/README.md
@@ -68,7 +68,8 @@ Koishi 在开发时借助了下面的工具:
| 特性 | [koishi
1.3.0](https://www.npmjs.com/package/koishi/v/1.3.0) | [cqhttp
1.2.0](https://www.npmjs.com/package/cqhttp/v/1.2.0) | [cq-websocket
2.0.2](https://www.npmjs.com/package/cq-websocket/v/2.0.2) | [lemon-bot
0.6.0](https://www.npmjs.com/package/lemon-bot/v/0.6.0) | [@ionjs/core
0.6.5](https://www.npmjs.com/package/@ionjs/core/v/0.6.5) |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| 依赖数量 | [22](http://npm.anvaka.com/#/view/2d/koishi/1.3.0) / [10](http://npm.anvaka.com/#/view/2d/koishi-core/1.3.0) | [62](http://npm.anvaka.com/#/view/2d/cqhttp/1.1.1) | [37](http://npm.anvaka.com/#/view/2d/cq-websocket/2.0.2) | [65](http://npm.anvaka.com/#/view/2d/lemon-bot/0.6.0) | [73](http://npm.anvaka.com/#/view/2d/%2540ionjs%252Fcore/0.6.5) |
+| 依赖数量 | [10](http://npm.anvaka.com/#/view/2d/koishi-core/1.3.0) / [21](http://npm.anvaka.com/#/view/2d/koishi/1.3.0) | [62](http://npm.anvaka.com/#/view/2d/cqhttp/1.1.1) | [37](http://npm.anvaka.com/#/view/2d/cq-websocket/2.0.2) | [65](http://npm.anvaka.com/#/view/2d/lemon-bot/0.6.0) | [73](http://npm.anvaka.com/#/view/2d/%2540ionjs%252Fcore/0.6.5) |
+| 安装体积 (MB) | [0.78](https://packagephobia.now.sh/result?p=koishi-core@1.3.0) / [2.14](https://packagephobia.now.sh/result?p=koishi@1.3.0) | [1.86](https://packagephobia.now.sh/result?p=cqhttp@1.1.1) | [2.82](https://packagephobia.now.sh/result?p=cq-websocket) | [2.56](https://packagephobia.now.sh/result?p=lemon-bot) | [2.32](https://packagephobia.now.sh/result?p=@ionjs/core) |
| HTTP | ✔️ | ✔️ | ❌ | ✔️ | ✔️ |
| WebSocket | ✔️ | ❌ | ✔️ | ❌ | ❌ |
| 反向 WebSocket | ❌ | ❌ | ❌ | ❌ | ❌ |
@@ -78,7 +79,7 @@ Koishi 在开发时借助了下面的工具:
| 命令行 | ✔️ | ❌ | ❌ | ❌ | ❌ |
| 指令 | ✔️ | ❌ | ❌ | ✔️ | ❌ |
-注:依赖数量如果表示为 X/Y,则 X 表示命令行工具依赖数量, Y 表示核心库依赖数量。
+注:依赖数量如果表示为 X/Y,则 X 表示核心库依赖数量,Y 表示命令行工具依赖数量。
## 安装
diff --git a/build/bump.ts b/build/bump.ts
index cb5d965d01..b95eb3d871 100644
--- a/build/bump.ts
+++ b/build/bump.ts
@@ -89,6 +89,7 @@ function getPackage (name: string) {
|| packages[`packages/koishi-${name}`]
|| packages[`packages/database-${name}`]
|| packages[`packages/plugin-${name}`]
+ || packages[`plugins/plugin-${name}`]
}
function each (callback: (pkg: Package, name: string) => T) {
diff --git a/build/start.ts b/build/start.ts
index 9ebfb9907f..3f4fcf1a28 100644
--- a/build/start.ts
+++ b/build/start.ts
@@ -4,7 +4,7 @@ import spawn from 'cross-spawn'
const name = process.argv[2]
if (!name) process.exit(0)
-spawn('npx', ['koishi', 'run', ...process.argv.slice(3)], {
+spawn('npx', ['koishi', 'run', ...process.argv.slice(3), '--', '-r', 'ts-node/register'], {
cwd: resolve(__dirname, '../bots', name),
stdio: 'inherit',
})
diff --git a/packages/database-level/package.json b/packages/database-level/package.json
index 3c75971e64..75f21d27e6 100644
--- a/packages/database-level/package.json
+++ b/packages/database-level/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-database-level",
"description": "Leveldb support for Koishi",
- "version": "1.0.4",
+ "version": "1.0.5",
"main": "dist/index.js",
"files": [
"dist"
@@ -33,12 +33,12 @@
"leveldb"
],
"devDependencies": {
- "koishi-test-utils": "^1.0.3"
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
"@types/leveldown": "^4.0.2",
"@types/levelup": "^4.3.0",
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2",
"leveldown": "^5.4.1",
"levelup": "^4.3.2",
diff --git a/packages/database-mysql/package.json b/packages/database-mysql/package.json
index 8b36638b6d..74e1334290 100644
--- a/packages/database-mysql/package.json
+++ b/packages/database-mysql/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-database-mysql",
"description": "MySQL support for Koishi",
- "version": "1.0.4",
+ "version": "1.0.5",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@@ -35,7 +35,7 @@
"@types/mysql": "^2.15.8"
},
"dependencies": {
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2",
"mysql": "^2.17.1"
}
diff --git a/packages/database-sqlite/package.json b/packages/database-sqlite/package.json
index 3ca76136c2..0ab3624a36 100644
--- a/packages/database-sqlite/package.json
+++ b/packages/database-sqlite/package.json
@@ -1,6 +1,6 @@
{
"name": "koishi-database-sqlite",
- "version": "1.0.0-alpha.0",
+ "version": "1.0.0-alpha.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@@ -22,10 +22,10 @@
"homepage": "https://github.com/koishijs/koishi/tree/master/packages/database-sqlite#readme",
"devDependencies": {
"@types/sqlite3": "^3.1.6",
- "koishi-test-utils": "^1.1.0"
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2",
"sqlite3": "^4.1.1"
}
diff --git a/packages/database-sqlite/src/database.ts b/packages/database-sqlite/src/database.ts
index 1da608af41..22fc4dc780 100644
--- a/packages/database-sqlite/src/database.ts
+++ b/packages/database-sqlite/src/database.ts
@@ -8,7 +8,7 @@ declare module 'koishi-core/dist/database' {
}
interface DatabaseConfig {
- sqlite: SqliteConfig
+ sqlite?: SqliteConfig
}
}
diff --git a/packages/koishi-cli/README.md b/packages/koishi-cli/README.md
index 482b85d8a1..fd3e344048 100644
--- a/packages/koishi-cli/README.md
+++ b/packages/koishi-cli/README.md
@@ -61,7 +61,8 @@ Koishi 在开发时借助了下面的工具:
| 特性 | [koishi
1.3.0](https://www.npmjs.com/package/koishi/v/1.3.0) | [cqhttp
1.2.0](https://www.npmjs.com/package/cqhttp/v/1.2.0) | [cq-websocket
2.0.2](https://www.npmjs.com/package/cq-websocket/v/2.0.2) | [lemon-bot
0.6.0](https://www.npmjs.com/package/lemon-bot/v/0.6.0) | [@ionjs/core
0.6.5](https://www.npmjs.com/package/@ionjs/core/v/0.6.5) |
|:--:|:--:|:--:|:--:|:--:|:--:|
-| 依赖数量 | [22](http://npm.anvaka.com/#/view/2d/koishi/1.3.0) / [10](http://npm.anvaka.com/#/view/2d/koishi-core/1.3.0) | [62](http://npm.anvaka.com/#/view/2d/cqhttp/1.1.1) | [37](http://npm.anvaka.com/#/view/2d/cq-websocket/2.0.2) | [65](http://npm.anvaka.com/#/view/2d/lemon-bot/0.6.0) | [73](http://npm.anvaka.com/#/view/2d/%2540ionjs%252Fcore/0.6.5) |
+| 依赖数量 | [10](http://npm.anvaka.com/#/view/2d/koishi-core/1.3.0) / [21](http://npm.anvaka.com/#/view/2d/koishi/1.3.0) | [62](http://npm.anvaka.com/#/view/2d/cqhttp/1.1.1) | [37](http://npm.anvaka.com/#/view/2d/cq-websocket/2.0.2) | [65](http://npm.anvaka.com/#/view/2d/lemon-bot/0.6.0) | [73](http://npm.anvaka.com/#/view/2d/%2540ionjs%252Fcore/0.6.5) |
+| 安装体积 (MB) | [0.78](https://packagephobia.now.sh/result?p=koishi-core@1.3.0) / [2.14](https://packagephobia.now.sh/result?p=koishi@1.3.0) | [1.86](https://packagephobia.now.sh/result?p=cqhttp@1.1.1) | [2.82](https://packagephobia.now.sh/result?p=cq-websocket) | [2.56](https://packagephobia.now.sh/result?p=lemon-bot) | [2.32](https://packagephobia.now.sh/result?p=@ionjs/core) |
| HTTP | ✔️ | ✔️ | ❌ | ✔️ | ✔️ |
| WebSocket | ✔️ | ❌ | ✔️ | ❌ | ❌ |
| 反向 WebSocket | ❌ | ❌ | ❌ | ❌ | ❌ |
@@ -71,7 +72,7 @@ Koishi 在开发时借助了下面的工具:
| 命令行 | ✔️ | ❌ | ❌ | ❌ | ❌ |
| 指令 | ✔️ | ❌ | ❌ | ✔️ | ❌ |
-注:依赖数量如果表示为 X/Y,则 X 表示命令行工具依赖数量, Y 表示核心库依赖数量。
+注:依赖数量如果表示为 X/Y,则 X 表示核心库依赖数量,Y 表示命令行工具依赖数量。
## 安装
diff --git a/packages/koishi-cli/package.json b/packages/koishi-cli/package.json
index 8fd4ca0ef9..b483f295dc 100644
--- a/packages/koishi-cli/package.json
+++ b/packages/koishi-cli/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi",
"description": "A QQ bot framework based on CQHTTP",
- "version": "1.3.0",
+ "version": "1.3.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@@ -40,9 +40,9 @@
"cac": "^6.5.4",
"js-yaml": "^3.13.1",
"kleur": "^3.0.3",
- "koishi-core": "^1.3.0",
- "koishi-plugin-common": "^1.0.4",
- "koishi-plugin-schedule": "^1.0.0",
+ "koishi-core": "^1.3.1",
+ "koishi-plugin-common": "^1.0.5",
+ "koishi-plugin-schedule": "^1.0.1",
"koishi-utils": "^1.0.2",
"prompts": "^2.3.0"
}
diff --git a/packages/koishi-cli/src/run.ts b/packages/koishi-cli/src/run.ts
index 79349c7b7e..1a35de07c2 100644
--- a/packages/koishi-cli/src/run.ts
+++ b/packages/koishi-cli/src/run.ts
@@ -7,8 +7,14 @@ import CAC from 'cac/types/CAC'
process.env.KOISHI_START_TIME = '' + performance.now()
-function createWorker () {
- const child = fork(resolve(__dirname, 'worker'))
+interface WorkerOptions {
+ '--'?: string[]
+}
+
+function createWorker (options: WorkerOptions) {
+ const child = fork(resolve(__dirname, 'worker'), [], {
+ execArgv: options['--'],
+ })
let started = false
child.on('message', (data: any) => {
@@ -28,20 +34,20 @@ function createWorker () {
} else {
logger.warn('an error was encounted. restarting...')
}
- createWorker()
+ createWorker(options)
})
}
export default function (cli: CAC) {
cli.command('run [file]', 'start a koishi bot')
.alias('start')
- .option('--log-level ', 'specify log level (default: 3)')
+ .option('--log-level ', 'specify log level (default: 2)')
.option('--silent', 'use log level 0 (print no message)')
- .option('--debug', 'use log level 4 (print all messages)')
+ .option('--debug', 'use log level 3 (print all messages)')
.action((file, options) => {
let logLevel = options.logLevel
if (options.silent) logLevel = 0
- if (options.debug) logLevel = 4
+ if (options.debug) logLevel = 3
if (logLevel !== undefined) {
if (!isInteger(logLevel) || logLevel < 0) {
logger.error('log level should be a positive integer.')
@@ -50,6 +56,6 @@ export default function (cli: CAC) {
process.env.KOISHI_LOG_LEVEL = '' + logLevel
}
process.env.KOISHI_CONFIG_FILE = file || ''
- createWorker()
+ createWorker(options)
})
}
diff --git a/packages/koishi-cli/src/utils.ts b/packages/koishi-cli/src/utils.ts
index a9388838b8..eea24a1206 100644
--- a/packages/koishi-cli/src/utils.ts
+++ b/packages/koishi-cli/src/utils.ts
@@ -2,7 +2,7 @@ import kleur from 'kleur'
export namespace logger {
export function info (message: string, logLevel?: number) {
- if (logLevel < 3) return
+ if (logLevel < 2) return
console.log(`${kleur.blue('info')}`, message)
}
@@ -22,7 +22,7 @@ export namespace logger {
}
export function debug (message: string, logLevel?: number) {
- if (logLevel < 4) return
+ if (logLevel < 3) return
console.log(`${kleur.magenta('debug')}`, message)
}
}
diff --git a/packages/koishi-cli/src/worker.ts b/packages/koishi-cli/src/worker.ts
index 7b3503af27..662933cfa7 100644
--- a/packages/koishi-cli/src/worker.ts
+++ b/packages/koishi-cli/src/worker.ts
@@ -136,13 +136,11 @@ process.on('unhandledRejection', (error) => {
})
appList.forEach((app) => {
- const { logLevel = 0, logFilter = {} } = app.options as AppConfig
+ const { logLevel = 2, logFilter = {} } = app.options as AppConfig
- for (const type of logTypes) {
- app.receiver.on(`logger/${type}` as LogEvents, (scope, message) => {
- logger[type](message, Math.min(logFilter[scope] ?? logLevel, baseLogLevel))
- })
- }
+ app.receiver.on('logger', (scope, message, type) => {
+ logger[type](message, Math.min(logFilter[scope] ?? logLevel, baseLogLevel))
+ })
})
startAll().catch((error) => {
diff --git a/packages/koishi-core/package.json b/packages/koishi-core/package.json
index c950bf1ecf..49f80434a6 100644
--- a/packages/koishi-core/package.json
+++ b/packages/koishi-core/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-core",
"description": "Core features for Koishi",
- "version": "1.3.0",
+ "version": "1.3.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@@ -35,7 +35,7 @@
"@types/debug": "^4.1.5",
"@types/ws": "^6.0.4",
"get-port": "^5.1.0",
- "koishi-test-utils": "^1.0.3"
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
"axios": "^0.19.1",
diff --git a/packages/koishi-core/src/app.ts b/packages/koishi-core/src/app.ts
index 8e4edfcd49..a02e730950 100644
--- a/packages/koishi-core/src/app.ts
+++ b/packages/koishi-core/src/app.ts
@@ -8,6 +8,7 @@ import { showSuggestions } from './utils'
import { Meta, MessageMeta } from './meta'
import { simplify, noop } from 'koishi-utils'
import { errors, messages } from './messages'
+import { ParsedLine } from './parser'
export interface AppOptions {
port?: number
@@ -287,10 +288,11 @@ export class App extends Context {
if (prefix && !nickname) continue
if (!fuzzy && message !== name) continue
if (message.startsWith(name)) {
- let _message = message.slice(name.length)
+ const _message = message.slice(name.length)
if (fuzzy && !nickname && _message.match(/^\S/)) continue
- if (oneArg) _message = `'${_message.trim()}'`
- const result = command.parse(_message)
+ const result: ParsedLine = oneArg
+ ? { rest: '', options: {}, unknown: [], args: [_message.trim()] }
+ : command.parse(_message)
result.options = { ...options, ...result.options }
result.args.unshift(...args)
parsedArgv = { meta, command, ...result }
@@ -304,7 +306,7 @@ export class App extends Context {
// attach group data
const groupFields = new Set(['flag', 'assignee'])
this.receiver.emit('before-group', groupFields, parsedArgv || { meta })
- const group = await this.database.observeGroup(meta.groupId, 0, Array.from(groupFields))
+ const group = await this.database.observeGroup(meta.groupId, Array.from(groupFields))
Object.defineProperty(meta, '$group', { value: group, writable: true })
// ignore some group calls
@@ -320,7 +322,7 @@ export class App extends Context {
// attach user data
const userFields = new Set(['name', 'flag'])
this.receiver.emit('before-user', userFields, parsedArgv || { meta })
- const user = await this.database.observeUser(meta.userId, 0, Array.from(userFields))
+ const user = await this.database.observeUser(meta.userId, Array.from(userFields))
Object.defineProperty(meta, '$user', { value: user, writable: true })
// ignore some user calls
diff --git a/packages/koishi-core/src/database.ts b/packages/koishi-core/src/database.ts
index 9b17ba8e4c..7fc04ac9aa 100644
--- a/packages/koishi-core/src/database.ts
+++ b/packages/koishi-core/src/database.ts
@@ -60,6 +60,8 @@ export enum GroupFlag {
noEmit = 4,
}
+export const groupFlags: (keyof typeof GroupFlag)[] = ['noCommand', 'noResponse', 'noEmit']
+
export type Group = Observed>
export type GroupField = keyof GroupData
export const groupFields: GroupField[] = []
diff --git a/packages/koishi-core/tests/middleware.spec.ts b/packages/koishi-core/tests/middleware.spec.ts
index 2aa87b4659..2dde439767 100644
--- a/packages/koishi-core/tests/middleware.spec.ts
+++ b/packages/koishi-core/tests/middleware.spec.ts
@@ -43,48 +43,22 @@ describe('Middleware API', () => {
})
test('middleware-1', async () => {
- await app.receive({
- ...shared,
- messageType: 'private',
- subType: 'friend',
- message: 'foo',
- })
-
+ await app.receiveMessage('user', 'foo', 10000)
expect(flag.toString(2).split('').reverse().join('')).toBe('1101')
})
test('middleware-2', async () => {
- await app.receive({
- ...shared,
- messageType: 'group',
- subType: 'normal',
- message: 'bar',
- groupId: 20000,
- })
-
+ await app.receiveMessage('group', 'bar', 10000, 20000)
expect(flag.toString(2).split('').reverse().join('')).toBe('1011')
})
test('middleware-3', async () => {
- await app.receive({
- ...shared,
- messageType: 'private',
- subType: 'friend',
- message: 'baz',
- })
-
+ await app.receiveMessage('user', 'baz', 10000)
expect(flag.toString(2).split('').reverse().join('')).toBe('1101011')
})
test('middleware-4', async () => {
- await app.receive({
- ...shared,
- messageType: 'group',
- subType: 'normal',
- message: 'baz',
- groupId: 20000,
- })
-
+ await app.receiveMessage('group', 'baz', 10000, 20000)
expect(flag.toString(2).split('').reverse().join('')).toBe('10111')
})
})
@@ -110,14 +84,7 @@ describe('runtime checks', () => {
next()
})
- await app.receive({
- ...shared,
- messageType: 'group',
- subType: 'normal',
- message: 'bar',
- })
-
- await sleep(0)
+ await app.receiveMessage('group', 'bar', 10000, 20000)
expect(errorCallback).toBeCalledTimes(1)
expect(errorCallback).toBeCalledWith(errors.ISOLATED_NEXT)
@@ -135,12 +102,7 @@ describe('runtime checks', () => {
throw new Error(errorMessage)
})
- await app.receive({
- ...shared,
- messageType: 'group',
- subType: 'normal',
- message: 'bar',
- })
+ await app.receiveMessage('group', 'bar', 10000, 20000)
expect(errorCallback).toBeCalledTimes(1)
expect(errorCallback).toBeCalledWith(errorMessage)
diff --git a/packages/koishi-core/tests/receiver.spec.ts b/packages/koishi-core/tests/receiver.spec.ts
index 34c1e61888..0107afdeab 100644
--- a/packages/koishi-core/tests/receiver.spec.ts
+++ b/packages/koishi-core/tests/receiver.spec.ts
@@ -1,7 +1,17 @@
-import { createMeta, MockedApp } from 'koishi-test-utils'
+import { MockedApp, BASE_SELF_ID } from 'koishi-test-utils'
+import { PostType, MetaTypeMap, SubTypeMap, Meta } from '../dist'
+import { camelCase } from 'koishi-utils'
const app = new MockedApp()
+function createMeta (postType: T, type: MetaTypeMap[T], subType: SubTypeMap[T], meta: Meta = {}) {
+ if (!meta.selfId) meta.selfId = BASE_SELF_ID
+ meta.postType = postType
+ meta[camelCase(postType) + 'Type'] = type
+ meta.subType = subType
+ return meta
+}
+
describe('Receiver API', () => {
test('user/*/message/friend', async () => {
const meta = createMeta('message', 'private', 'friend', { userId: 10000 })
diff --git a/packages/plugin-common/package.json b/packages/plugin-common/package.json
index 7cb5e99aae..5a2829f98a 100644
--- a/packages/plugin-common/package.json
+++ b/packages/plugin-common/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-plugin-common",
"description": "Common plugins for Koishi",
- "version": "1.0.4",
+ "version": "1.0.5",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"author": "Shigma <1700011071@pku.edu.cn>",
@@ -28,10 +28,10 @@
"plugin"
],
"devDependencies": {
- "koishi-test-utils": "^1.1.0"
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2"
}
}
diff --git a/packages/plugin-common/src/admin.ts b/packages/plugin-common/src/admin.ts
index 5de6db7dab..f808468782 100644
--- a/packages/plugin-common/src/admin.ts
+++ b/packages/plugin-common/src/admin.ts
@@ -1,4 +1,4 @@
-import { Context, User, userFlags, UserFlag, Meta, UserField, getTargetId, CommandConfig, GroupField, UserData, GroupData } from 'koishi-core'
+import { Context, User, userFlags, UserFlag, Meta, UserField, getTargetId, CommandConfig, GroupField, UserData, GroupData, GroupFlag, groupFlags, Group, userFields, groupFields } from 'koishi-core'
import { isInteger, difference, Observed, paramCase } from 'koishi-utils'
type ActionCallback =
@@ -17,11 +17,11 @@ export interface GroupAction {
const userActionMap: Record = {}
const groupActionMap: Record = {}
-export function registerUserAction (name: string, callback: ActionCallback, fields: K[] = []) {
+export function registerUserAction (name: string, callback: ActionCallback, fields?: K[]) {
userActionMap[paramCase(name)] = { callback, fields }
}
-export function registerGroupAction (name: string, callback: ActionCallback, fields: K[] = []) {
+export function registerGroupAction (name: string, callback: ActionCallback, fields?: K[]) {
groupActionMap[paramCase(name)] = { callback, fields }
}
@@ -36,7 +36,7 @@ registerUserAction('setAuth', async (meta, user, value) => {
await user._update()
return meta.$send('用户权限已修改。')
}
-})
+}, ['authority'])
registerUserAction('setFlag', async (meta, user, ...flags) => {
if (!flags.length) return meta.$send(`可用的标记有 ${userFlags.join(', ')}。`)
@@ -47,10 +47,10 @@ registerUserAction('setFlag', async (meta, user, ...flags) => {
}
await user._update()
return meta.$send('用户信息已修改。')
-})
+}, ['flag'])
registerUserAction('unsetFlag', async (meta, user, ...flags) => {
- if (!flags.length) return meta.$send(`可用的 flag 有:${userFlags.join(', ')}。`)
+ if (!flags.length) return meta.$send(`可用的标记有 ${userFlags.join(', ')}。`)
const notFound = difference(flags, userFlags)
if (notFound.length) return meta.$send(`未找到标记 ${notFound.join(', ')}。`)
for (const name of flags) {
@@ -58,7 +58,7 @@ registerUserAction('unsetFlag', async (meta, user, ...flags) => {
}
await user._update()
return meta.$send('用户信息已修改。')
-})
+}, ['flag'])
registerUserAction('clearUsage', async (meta, user, ...commands) => {
if (commands.length) {
@@ -70,7 +70,7 @@ registerUserAction('clearUsage', async (meta, user, ...commands) => {
}
await user._update()
return meta.$send('用户信息已修改。')
-})
+}, ['usage'])
registerUserAction('showUsage', async (meta, user, ...commands) => {
const { usage } = user
@@ -80,7 +80,29 @@ registerUserAction('showUsage', async (meta, user, ...commands) => {
'用户今日各指令的调用次数为:',
...commands.sort().map(name => `${name}:${usage[name] ? usage[name].count : 0} 次`),
].join('\n'))
-})
+}, ['usage'])
+
+registerGroupAction('setFlag', async (meta, group, ...flags) => {
+ if (!flags.length) return meta.$send(`可用的标记有 ${groupFlags.join(', ')}。`)
+ const notFound = difference(flags, groupFlags)
+ if (notFound.length) return meta.$send(`未找到标记 ${notFound.join(', ')}。`)
+ for (const name of flags) {
+ group.flag |= GroupFlag[name]
+ }
+ await group._update()
+ return meta.$send('群信息已修改。')
+}, ['flag'])
+
+registerGroupAction('unsetFlag', async (meta, group, ...flags) => {
+ if (!flags.length) return meta.$send(`可用的标记有 ${groupFlags.join(', ')}。`)
+ const notFound = difference(flags, groupFlags)
+ if (notFound.length) return meta.$send(`未找到标记 ${notFound.join(', ')}。`)
+ for (const name of flags) {
+ group.flag &= ~GroupFlag[name]
+ }
+ await group._update()
+ return meta.$send('群信息已修改。')
+}, ['flag'])
export default function apply (ctx: Context, options: CommandConfig) {
const userActions = Object.keys(userActionMap).map(paramCase).join(', ')
@@ -92,35 +114,34 @@ export default function apply (ctx: Context, options: CommandConfig) {
.option('-G, --this-group', '指定目标群为本群')
.action(async ({ meta, options }, name: string, ...args: string[]) => {
const isGroup = 'g' in options || 'G' in options
- if ('user' in options && isGroup) {
- return meta.$send('不能同时目标为指定用户和群。')
- }
+ if ('user' in options && isGroup) return meta.$send('不能同时目标为指定用户和群。')
+
const actionList = isGroup ? groupActions : userActions
const actionMap = isGroup ? groupActionMap : userActionMap
- if (!name) {
- return meta.$send(`当前的可用指令有:${actionList}。`)
- }
+ if (!name) return meta.$send(`当前的可用指令有:${actionList}。`)
+
const action = actionMap[paramCase(name)]
if (!action) return meta.$send(`指令未找到。当前的可用指令有:${actionList}。`)
if (isGroup) {
- let group: Observed
+ const fields = action.fields ? action.fields.slice() as GroupField[] : groupFields
+ let group: Group
if (options.thisGroup) {
- group = await ctx.database.observeGroup(meta.$group)
- } else if (typeof options.group === 'number') {
- group = await ctx.database.observeGroup(options.group)
+ group = await ctx.database.observeGroup(meta.$group, fields)
+ } else if (isInteger(options.group) && options.group > 0) {
+ group = await ctx.database.observeGroup(options.group, fields)
}
if (!group) return meta.$send('未找到指定的群。')
return action.callback.call(ctx, meta, group, ...args)
} else {
- const fields = action.fields.slice() as UserField[]
+ const fields = action.fields ? action.fields.slice() as UserField[] : userFields
if (!fields.includes('authority')) fields.push('authority')
let user: User
if (options.user) {
const qq = getTargetId(options.user)
if (!qq) return meta.$send('未指定目标。')
user = await ctx.database.observeUser(qq, -1, fields)
- if (!user) return meta.$send('未找到用户。')
+ if (!user) return meta.$send('未找到指定的用户。')
if (qq !== meta.$user.id && meta.$user.authority <= user.authority) return meta.$send('权限不足。')
} else {
user = await ctx.database.observeUser(meta.$user, 0, fields)
diff --git a/packages/plugin-common/src/authorize.ts b/packages/plugin-common/src/authorize.ts
index e71909538d..2a0356f81f 100644
--- a/packages/plugin-common/src/authorize.ts
+++ b/packages/plugin-common/src/authorize.ts
@@ -66,7 +66,6 @@ export default function apply (ctx: Context, config: AuthorizeConfig) {
}
app.receiver.once('ready', async () => {
- logger.info('foo bar')
await Promise.all([
...Object.keys(authorizeUserInverseMap).map(key => updateAuthorizeInfo(+key, authorizeUserInverseMap[+key])),
...Object.entries(authorizeGroup).map(async ([key, value]) => {
diff --git a/packages/plugin-common/src/help.ts b/packages/plugin-common/src/help.ts
index 948478801e..8896ea13c0 100644
--- a/packages/plugin-common/src/help.ts
+++ b/packages/plugin-common/src/help.ts
@@ -2,6 +2,7 @@ import { Context, Command, UserData, CommandConfig, MessageMeta } from 'koishi-c
export default function apply (ctx: Context, options: CommandConfig) {
ctx.command('help [command]', '显示帮助信息', { authority: 0, ...options })
+ .userFields(['authority', 'usage'])
.shortcut('帮助', { fuzzy: true })
.shortcut('全局指令', { options: { shortcut: true } })
.option('-e, --expand', '展开指令列表')
diff --git a/packages/plugin-common/src/index.ts b/packages/plugin-common/src/index.ts
index 99d73e4579..9573ea787b 100644
--- a/packages/plugin-common/src/index.ts
+++ b/packages/plugin-common/src/index.ts
@@ -11,7 +11,7 @@ import info from './info'
import likeme, { LikemeOptions } from './likeme'
import rank from './rank'
import repeater, { RepeaterOptions } from './repeater'
-import requestHandler, { HandlerConfig } from './requestHandler'
+import requestHandler, { HandlerConfig } from './request-handler'
import respondent, { Respondent } from './respondent'
import welcome, { WelcomeMessage } from './welcome'
diff --git a/packages/plugin-common/src/request-handler.ts b/packages/plugin-common/src/request-handler.ts
new file mode 100644
index 0000000000..180b3a3735
--- /dev/null
+++ b/packages/plugin-common/src/request-handler.ts
@@ -0,0 +1,61 @@
+import { App, Meta } from 'koishi-core'
+
+type RequestHandler = string | boolean | ((meta: Meta<'request'>, app: App) => string | boolean | void | Promise)
+
+export interface HandlerConfig {
+ handleFriend?: RequestHandler
+ handleGroupAdd?: RequestHandler
+ handleGroupInvite?: RequestHandler
+}
+
+const defaultHandlers: HandlerConfig = {
+ async handleFriend (meta, app) {
+ if (!app.database) return
+ const user = await app.database.getUser(meta.userId, ['authority'])
+ if (user.authority >= 1) return true
+ },
+ async handleGroupInvite (meta, app) {
+ if (!app.database) return
+ const user = await app.database.getUser(meta.userId, ['authority'])
+ if (user.authority >= 4) return true
+ },
+}
+
+async function getHandleResult (handler: RequestHandler, meta: Meta<'request'>, ctx: App) {
+ return typeof handler === 'function' ? handler(meta, ctx) : handler
+}
+
+function setFriendResult (meta: Meta, result: string | boolean | void) {
+ if (typeof result === 'boolean') {
+ return result ? meta.$approve() : meta.$reject()
+ } else if (typeof result === 'string') {
+ return meta.$approve(result)
+ }
+}
+
+function setGroupResult (meta: Meta, result: string | boolean | void) {
+ if (typeof result === 'boolean') {
+ return result ? meta.$approve() : meta.$reject()
+ } else if (typeof result === 'string') {
+ return meta.$reject(result)
+ }
+}
+
+export default function apply (ctx: App, options: HandlerConfig = {}) {
+ const { handleFriend, handleGroupAdd, handleGroupInvite } = { ...defaultHandlers, ...options }
+
+ ctx.receiver.on('request/friend', async (meta) => {
+ const result = await getHandleResult(handleFriend, meta, ctx)
+ return setFriendResult(meta, result)
+ })
+
+ ctx.receiver.on('request/group/add', async (meta) => {
+ const result = await getHandleResult(handleGroupAdd, meta, ctx)
+ return setGroupResult(meta, result)
+ })
+
+ ctx.receiver.on('request/group/invite', async (meta) => {
+ const result = await getHandleResult(handleGroupInvite, meta, ctx)
+ return setGroupResult(meta, result)
+ })
+}
diff --git a/packages/plugin-common/src/requestHandler.ts b/packages/plugin-common/src/requestHandler.ts
deleted file mode 100644
index 4d4c49467a..0000000000
--- a/packages/plugin-common/src/requestHandler.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { App, Meta } from 'koishi-core'
-
-type RequestHandler = boolean | ((meta: Meta<'request'>, app: App) => string | boolean | void | Promise)
-
-export interface HandlerConfig {
- handleFriend?: RequestHandler
- handleGroupAdd?: RequestHandler
- handleGroupInvite?: RequestHandler
-}
-
-const defaultHandlers: HandlerConfig = {
- async handleFriend (meta, app) {
- if (!app.database) return
- const user = await app.database.getUser(meta.userId, 0, ['authority'])
- if (user.authority >= 1) return true
- },
- async handleGroupInvite (meta, app) {
- if (!app.database) return
- const user = await app.database.getUser(meta.userId, 0, ['authority'])
- if (user.authority >= 4) return true
- },
-}
-
-async function getHandleResult (handler: RequestHandler, meta: Meta<'request'>, ctx: App) {
- return typeof handler === 'function' ? handler(meta, ctx) : handler
-}
-
-export default function apply (ctx: App, options: HandlerConfig = {}) {
- const { handleFriend, handleGroupAdd, handleGroupInvite } = { ...defaultHandlers, ...options }
-
- ctx.users.receiver.on('request/friend', async (meta) => {
- const result = await getHandleResult(handleFriend, meta, ctx)
- if (typeof result === 'boolean') {
- return result ? meta.$approve() : meta.$reject()
- } else if (typeof result === 'string') {
- return meta.$approve(result)
- }
- })
-
- ctx.groups.receiver.on('request/group/add', async (meta) => {
- const result = await getHandleResult(handleGroupAdd, meta, ctx)
- if (typeof result === 'boolean') {
- return result ? meta.$approve() : meta.$reject()
- } else if (typeof result === 'string') {
- return meta.$reject(result)
- }
- })
-
- ctx.groups.receiver.on('request/group/invite', async (meta) => {
- const result = await getHandleResult(handleGroupInvite, meta, ctx)
- if (typeof result === 'boolean') {
- return result ? meta.$approve() : meta.$reject()
- } else if (typeof result === 'string') {
- return meta.$reject(result)
- }
- })
-}
diff --git a/packages/plugin-common/tests/__snapshots__/admin.spec.ts.snap b/packages/plugin-common/tests/__snapshots__/admin.spec.ts.snap
new file mode 100644
index 0000000000..df5f3f4613
--- /dev/null
+++ b/packages/plugin-common/tests/__snapshots__/admin.spec.ts.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`group operations list actions: admin -G 1`] = `"当前的可用指令有:set-flag, unset-flag。"`;
+
+exports[`group operations list actions: admin -G foo 1`] = `"指令未找到。当前的可用指令有:set-flag, unset-flag。"`;
+
+exports[`user operations list actions: admin 1`] = `"当前的可用指令有:set-auth, set-flag, unset-flag, clear-usage, show-usage。"`;
+
+exports[`user operations list actions: admin foo 1`] = `"指令未找到。当前的可用指令有:set-auth, set-flag, unset-flag, clear-usage, show-usage。"`;
diff --git a/packages/plugin-common/tests/admin.spec.ts b/packages/plugin-common/tests/admin.spec.ts
new file mode 100644
index 0000000000..93608cf55a
--- /dev/null
+++ b/packages/plugin-common/tests/admin.spec.ts
@@ -0,0 +1,113 @@
+import { MockedApp, MemoryDatabase } from 'koishi-test-utils'
+import { registerDatabase, userFlags, groupFlags, UserFlag, GroupFlag } from 'koishi-core'
+import admin, { registerUserAction, registerGroupAction } from '../src/admin'
+
+registerDatabase('memory', MemoryDatabase)
+
+const app = new MockedApp({ database: { memory: {} } })
+const session = app.createSession('group', 123, 321)
+
+app.plugin(admin)
+app.command('foo', { maxUsage: 10 }).action(({ meta }) => meta.$send('bar'))
+app.command('bar', { maxUsage: 10 }).action(({ meta }) => meta.$send('foo'))
+
+beforeAll(async () => {
+ await app.start()
+ await app.database.getUser(123, 4)
+ await app.database.getUser(456, 3)
+ await app.database.getUser(789, 4)
+ await app.database.getGroup(321, app.selfId)
+ await app.database.getGroup(654, app.selfId)
+})
+
+describe('basic features', () => {
+ test('check', async () => {
+ await session.shouldHaveReply('admin -u 456 -g 321', '不能同时目标为指定用户和群。')
+ })
+})
+
+describe('user operations', () => {
+ test('list actions', async () => {
+ await session.shouldMatchSnapshot('admin')
+ await session.shouldMatchSnapshot('admin foo')
+ })
+
+ test('check target', async () => {
+ await session.shouldHaveReply('admin -u bar set-flag', '未指定目标。')
+ await session.shouldHaveReply('admin -u 233 set-flag', '未找到指定的用户。')
+ await session.shouldHaveReply('admin -u 789 show-usage', '权限不足。')
+ })
+
+ test('setAuth', async () => {
+ await session.shouldHaveReply('admin -u 456 set-auth -1', '参数错误。')
+ await session.shouldHaveReply('admin -u 456 set-auth 3', '用户权限未改动。')
+ await session.shouldHaveReply('admin -u 456 set-auth 2', '用户权限已修改。')
+ await session.shouldHaveReply('admin -u 456 set-auth 4', '权限不足。')
+ })
+
+ test('setFlag', async () => {
+ await session.shouldHaveReply('admin -u 456 set-flag', `可用的标记有 ${userFlags.join(', ')}。`)
+ await session.shouldHaveReply('admin -u 456 set-flag foo', '未找到标记 foo。')
+ await session.shouldHaveReply('admin -u 456 set-flag ignore', '用户信息已修改。')
+ await expect(app.database.getUser(456)).resolves.toHaveProperty('flag', UserFlag.ignore)
+ })
+
+ test('unsetFlag', async () => {
+ await session.shouldHaveReply('admin -u 456 unset-flag', `可用的标记有 ${userFlags.join(', ')}。`)
+ await session.shouldHaveReply('admin -u 456 unset-flag foo', '未找到标记 foo。')
+ await session.shouldHaveReply('admin -u 456 unset-flag ignore', '用户信息已修改。')
+ await expect(app.database.getUser(456)).resolves.toHaveProperty('flag', 0)
+ })
+
+ test('showUsage', async () => {
+ await session.shouldHaveReply('admin show-usage', '用户今日没有调用过指令。')
+ await session.shouldHaveReply('foo', 'bar')
+ await session.shouldHaveReply('admin show-usage', '用户今日各指令的调用次数为:\nfoo:1 次')
+ await session.shouldHaveReply('admin show-usage foo bar', '用户今日各指令的调用次数为:\nbar:0 次\nfoo:1 次')
+ })
+
+ test('clearUsage', async () => {
+ await session.shouldHaveReply('bar', 'foo')
+ await session.shouldHaveReply('admin clear-usage foo', '用户信息已修改。')
+ await session.shouldHaveReply('admin show-usage', '用户今日各指令的调用次数为:\nbar:1 次')
+ await session.shouldHaveReply('admin clear-usage', '用户信息已修改。')
+ await session.shouldHaveReply('admin show-usage', '用户今日没有调用过指令。')
+ })
+})
+
+describe('group operations', () => {
+ test('list actions', async () => {
+ await session.shouldMatchSnapshot('admin -G')
+ await session.shouldMatchSnapshot('admin -G foo')
+ })
+
+ test('check target', async () => {
+ await session.shouldHaveReply('admin -g bar set-flag', '未找到指定的群。')
+ })
+
+ test('setFlag', async () => {
+ await session.shouldHaveReply('admin -G set-flag', `可用的标记有 ${groupFlags.join(', ')}。`)
+ await session.shouldHaveReply('admin -g 654 set-flag foo', '未找到标记 foo。')
+ await session.shouldHaveReply('admin -g 654 set-flag noCommand noEmit', '群信息已修改。')
+ await expect(app.database.getGroup(654)).resolves.toHaveProperty('flag', GroupFlag.noCommand | GroupFlag.noEmit)
+ })
+
+ test('unsetFlag', async () => {
+ await session.shouldHaveReply('admin -G unset-flag', `可用的标记有 ${groupFlags.join(', ')}。`)
+ await session.shouldHaveReply('admin -g 654 unset-flag foo', '未找到标记 foo。')
+ await session.shouldHaveReply('admin -g 654 unset-flag noEmit noResponse', '群信息已修改。')
+ await expect(app.database.getGroup(654)).resolves.toHaveProperty('flag', GroupFlag.noCommand)
+ })
+})
+
+describe('custom actions', () => {
+ test('user action', async () => {
+ registerUserAction('test', meta => meta.$send('foo'))
+ await session.shouldHaveReply('admin test', 'foo')
+ })
+
+ test('group action', async () => {
+ registerGroupAction('test', meta => meta.$send('bar'))
+ await session.shouldHaveReply('admin -G test', 'bar')
+ })
+})
diff --git a/packages/plugin-common/tests/echo.spec.ts b/packages/plugin-common/tests/echo.spec.ts
index 1f3f38ddff..5d6ac3e4ce 100644
--- a/packages/plugin-common/tests/echo.spec.ts
+++ b/packages/plugin-common/tests/echo.spec.ts
@@ -1,4 +1,4 @@
-import { MockedApp, createMeta } from 'koishi-test-utils'
+import { MockedApp } from 'koishi-test-utils'
import echo from '../src/echo'
const app = new MockedApp()
@@ -7,18 +7,18 @@ app.plugin(echo)
describe('echo command', () => {
test('basic support', async () => {
- await app.receive(createMeta('message', 'private', 'friend', { message: 'echo foo', userId: 123 }))
+ await app.receiveMessage('user', 'echo foo', 123)
app.shouldHaveLastRequest('send_private_msg', { message: 'foo', userId: 123 })
- await app.receive(createMeta('message', 'group', 'normal', { message: 'echo foo', groupId: 123 }))
- app.shouldHaveLastRequest('send_group_msg', { message: 'foo', groupId: 123 })
- await app.receive(createMeta('message', 'discuss', null, { message: 'echo foo', discussId: 123 }))
- app.shouldHaveLastRequest('send_discuss_msg', { message: 'foo', discussId: 123 })
+ await app.receiveMessage('group', 'echo foo', 123, 456)
+ app.shouldHaveLastRequest('send_group_msg', { message: 'foo', groupId: 456 })
+ await app.receiveMessage('discuss', 'echo foo', 123, 789)
+ app.shouldHaveLastRequest('send_discuss_msg', { message: 'foo', discussId: 789 })
})
test('send to other contexts', async () => {
- await app.receive(createMeta('message', 'private', 'friend', { message: 'echo -u 456 foo', userId: 123 }))
+ await app.receiveMessage('user', 'echo -u 456 foo', 123)
app.shouldHaveLastRequest('send_private_msg', { message: 'foo', userId: 456 })
- await app.receive(createMeta('message', 'private', 'friend', { message: 'echo -g 456 -d 789 foo', userId: 123 }))
+ await app.receiveMessage('user', 'echo -g 456 -d 789 foo', 123)
app.shouldHaveLastRequests([
['send_group_msg', { message: 'foo', groupId: 456 }],
['send_discuss_msg', { message: 'foo', discussId: 789 }],
diff --git a/packages/plugin-common/tests/handler.spec.ts b/packages/plugin-common/tests/handler.spec.ts
new file mode 100644
index 0000000000..c4bfe3e300
--- /dev/null
+++ b/packages/plugin-common/tests/handler.spec.ts
@@ -0,0 +1,106 @@
+import { MockedApp, MemoryDatabase } from 'koishi-test-utils'
+import requestHandler, { HandlerConfig } from '../src/request-handler'
+import { registerDatabase } from 'koishi-core'
+
+registerDatabase('memory', MemoryDatabase)
+
+let app: MockedApp
+
+describe('support string', () => {
+ beforeAll(async () => {
+ app = new MockedApp()
+ app.plugin(requestHandler, {
+ handleFriend: 'foo',
+ handleGroupAdd: 'bar',
+ })
+ })
+
+ test('friend add', async () => {
+ await app.receiveFriendRequest(321)
+ app.shouldHaveLastRequest('set_friend_add_request', { approve: true, remark: 'foo' })
+ })
+
+ test('group add', async () => {
+ await app.receiveGroupRequest(321, 'add')
+ app.shouldHaveLastRequest('set_group_add_request', { approve: false, reason: 'bar' })
+ })
+})
+
+describe('support boolean', () => {
+ beforeAll(async () => {
+ app = new MockedApp()
+ app.plugin(requestHandler, {
+ handleFriend: false,
+ handleGroupInvite: false,
+ })
+ })
+
+ test('friend add', async () => {
+ await app.receiveFriendRequest(321)
+ app.shouldHaveLastRequest('set_friend_add_request', { approve: false })
+ })
+
+ test('group invite', async () => {
+ await app.receiveGroupRequest(321, 'invite')
+ app.shouldHaveLastRequest('set_group_add_request', { approve: false })
+ })
+})
+
+describe('default behaviour without database', () => {
+ beforeAll(async () => {
+ app = new MockedApp()
+ app.plugin(requestHandler)
+ })
+
+ test('friend add', async () => {
+ await app.receiveFriendRequest(321)
+ app.shouldHaveNoRequests()
+ })
+
+ test('group invite', async () => {
+ await app.receiveGroupRequest(654, 'invite')
+ app.shouldHaveNoRequests()
+ })
+
+ test('group add', async () => {
+ await app.receiveGroupRequest(456, 'add')
+ app.shouldHaveNoRequests()
+ })
+})
+
+describe('default behaviour with database', () => {
+ beforeAll(async () => {
+ app = new MockedApp({ database: { memory: {} } })
+ app.plugin(requestHandler)
+
+ await app.start()
+ await app.database.getUser(123, 1)
+ await app.database.getUser(456, 4)
+ await app.database.getUser(654, 3)
+ })
+
+ test('friend add with authority 0', async () => {
+ await app.receiveFriendRequest(321)
+ app.shouldHaveNoRequests()
+ })
+
+ test('friend add with authority 1', async () => {
+ await app.receiveFriendRequest(123)
+ app.shouldHaveLastRequest('set_friend_add_request', { approve: true })
+ })
+
+ test('group invite with authority 3', async () => {
+ await app.receiveGroupRequest(654, 'invite')
+ app.shouldHaveNoRequests()
+ })
+
+ test('group invite with authority 4', async () => {
+ await app.receiveGroupRequest(456, 'invite')
+ app.shouldHaveLastRequest('set_group_add_request', { approve: true, subType: 'invite' })
+ })
+
+ test('group add with authority 4', async () => {
+ await app.receiveGroupRequest(456, 'add')
+ app.shouldHaveNoRequests()
+ })
+})
diff --git a/packages/plugin-schedule/package.json b/packages/plugin-schedule/package.json
index d5bbfb35e4..340010d036 100644
--- a/packages/plugin-schedule/package.json
+++ b/packages/plugin-schedule/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-plugin-schedule",
"description": "Schedule plugin for Koishi",
- "version": "1.0.0",
+ "version": "1.0.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"author": "Shigma <1700011071@pku.edu.cn>",
@@ -31,12 +31,12 @@
],
"devDependencies": {
"@types/ms": "^0.7.31",
- "koishi-database-level": "^1.0.4",
- "koishi-database-mysql": "^1.0.4",
- "koishi-test-utils": "^1.1.0"
+ "koishi-database-level": "^1.0.5",
+ "koishi-database-mysql": "^1.0.5",
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2",
"ms": "^2.1.2"
}
diff --git a/packages/plugin-teach/package.json b/packages/plugin-teach/package.json
index 2c7d7fbe8b..bee7206305 100644
--- a/packages/plugin-teach/package.json
+++ b/packages/plugin-teach/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-plugin-teach",
"description": "Teach plugin for Koishi",
- "version": "0.1.9",
+ "version": "0.1.10",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"author": "Shigma <1700011071@pku.edu.cn>",
@@ -31,12 +31,12 @@
"conversation"
],
"devDependencies": {
- "koishi-database-level": "^1.0.4",
- "koishi-database-mysql": "^1.0.4",
- "koishi-test-utils": "^1.1.0"
+ "koishi-database-level": "^1.0.5",
+ "koishi-database-mysql": "^1.0.5",
+ "koishi-test-utils": "^1.2.1"
},
"dependencies": {
- "koishi-core": "^1.3.0",
+ "koishi-core": "^1.3.1",
"koishi-utils": "^1.0.2"
}
}
diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json
index 471163602b..9eb8fc7f16 100644
--- a/packages/test-utils/package.json
+++ b/packages/test-utils/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-test-utils",
"description": "Test utilities for Koishi",
- "version": "1.1.0",
+ "version": "1.2.1",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
@@ -34,7 +34,7 @@
],
"peerDependencies": {
"jest": "^24.9.0",
- "koishi-core": "^1.3.0"
+ "koishi-core": "^1.3.1"
},
"devDependencies": {
"@types/debug": "^4.1.5",
diff --git a/packages/test-utils/src/mocks.ts b/packages/test-utils/src/mocks.ts
index e9d97d80e5..16e5b56230 100644
--- a/packages/test-utils/src/mocks.ts
+++ b/packages/test-utils/src/mocks.ts
@@ -1,6 +1,7 @@
import { BASE_SELF_ID, RequestData } from './utils'
import { snakeCase, sleep } from 'koishi-utils'
-import { AppOptions, App, Sender, Server, ContextType, ResponsePayload, MessageMeta, Meta } from 'koishi-core'
+import { AppOptions, App, Sender, Server, ContextType, ResponsePayload, MessageMeta, Meta, MetaTypeMap } from 'koishi-core'
+import debug from 'debug'
class MockedServer extends Server {
constructor (app: App) {
@@ -39,9 +40,12 @@ export class MockedApp extends App {
super({ selfId: BASE_SELF_ID, ...options })
this.sender = new MockedSender(this)
this.server = new MockedServer(this)
+ this.receiver.on('logger', (scope, message) => {
+ debug('koishi:' + scope)(message)
+ })
}
- receive (meta: Meta): Promise {
+ receive (meta: Meta) {
this.server.dispatchMeta({
selfId: this.selfId,
...meta,
@@ -49,6 +53,39 @@ export class MockedApp extends App {
return sleep(0)
}
+ receiveFriendRequest (userId: number, flag = 'flag') {
+ return this.receive({
+ postType: 'request',
+ requestType: 'friend',
+ userId,
+ flag,
+ })
+ }
+
+ receiveGroupRequest (userId: number, subType: 'add' | 'invite', groupId = 10000, flag = 'flag') {
+ return this.receive({
+ postType: 'request',
+ requestType: 'group',
+ subType,
+ userId,
+ groupId,
+ flag,
+ })
+ }
+
+ receiveMessage (type: 'user', message: string, userId: number): Promise
+ receiveMessage (type: 'group', message: string, userId: number, groupId: number): Promise
+ receiveMessage (type: 'discuss', message: string, userId: number, discussId: number): Promise
+ receiveMessage (ctxType: ContextType, message: string, userId: number, ctxId?: number) {
+ return this.receive({
+ [ctxType + 'Id']: ctxId,
+ postType: 'message',
+ messageType: ctxType === 'user' ? 'private' : ctxType,
+ message,
+ userId,
+ })
+ }
+
clearRequests () {
this.sender.requests = []
}
diff --git a/packages/test-utils/src/utils.ts b/packages/test-utils/src/utils.ts
index 701d497463..db55b2b17a 100644
--- a/packages/test-utils/src/utils.ts
+++ b/packages/test-utils/src/utils.ts
@@ -1,11 +1,10 @@
-import { SenderInfo, PostType, MetaTypeMap, SubTypeMap, Meta } from 'koishi-core'
-import { camelCase } from 'koishi-utils'
+import { SenderInfo } from 'koishi-core'
import debug from 'debug'
export const BASE_SELF_ID = 514
export const showTestLog = debug('koishi:test')
-export type RequestData = readonly [string, Record]
+export type RequestData = readonly [string, Record]
/**
* polyfill for node < 12.0
@@ -18,14 +17,6 @@ export function fromEntries (entries: Iterable) {
return result
}
-export function createMeta (postType: T, type: MetaTypeMap[T], subType: SubTypeMap[T], meta: Meta = {}) {
- if (!meta.selfId) meta.selfId = BASE_SELF_ID
- meta.postType = postType
- meta[camelCase(postType) + 'Type'] = type
- meta.subType = subType
- return meta
-}
-
export function createArray (length: number, create: (index: number) => T) {
return Array(length).fill(undefined).map((_, index) => create(index))
}