Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jan 13, 2020
2 parents fddc2fc + 12b1f52 commit 350a952
Show file tree
Hide file tree
Showing 53 changed files with 772 additions and 629 deletions.
6 changes: 1 addition & 5 deletions .gitignore
Expand Up @@ -4,11 +4,7 @@ temp
/docs
/bots
/coverage

/packages/plugin-*
!/packages/plugin-common
!/packages/plugin-schedule
!/packages/plugin-teach
/plugins

todo.md
yarn.lock
Expand Down
54 changes: 35 additions & 19 deletions README.md
@@ -1,8 +1,8 @@
<div align="center">
<a href="https://koishijs.github.io/" target="_blank">
<img width="160" src="https://koishijs.github.io/koishi.png" alt="logo">
<a href="https://koishi.js.org/" target="_blank">
<img width="160" src="https://koishi.js.org/koishi.png" alt="logo">
</a>
<h1 id="koishi"><a href="https://koishijs.github.io/" target="_blank">Koishi</a></h1>
<h1 id="koishi"><a href="https://koishi.js.org/" target="_blank">Koishi</a></h1>

[![Status](https://img.shields.io/github/workflow/status/koishijs/koishi/CI/master?style=flat-square)](https://github.com/koishijs/koishi/actions?query=workflow:CI)
[![Codecov](https://img.shields.io/codecov/c/github/koishijs/koishi?style=flat-square)](https://codecov.io/gh/koishijs/koishi)
Expand All @@ -22,35 +22,35 @@ Koishi 是一个在 [Node.js](https://nodejs.org/) 环境下运行,基于 [Coo

Koishi 高度配置化的 CLI 命令可以让你无需写代码就搭建属于你的机器人。与此同时,CLI 还配备了丰富和人性化的提示,进一步提高调试体验。

参见:[快速上手](https://koishijs.github.io/guide/getting-started.html) / [配置文件](https://koishijs.github.io/guide/config-file.html)
参见:[快速上手](https://koishi.js.org/guide/getting-started.html) / [配置文件](https://koishi.js.org/guide/config-file.html)

### 功能强大的 API

Koishi 的 API 包括下面几个部分:

- [Receiver](https://koishijs.github.io/guide/receive-and-send.html#接收器):将收到的信息转化为事件进行分发,且同时支持 HTTP 和 WebSocket
- [Sender](https://koishijs.github.io/guide/receive-and-send.html#发送器):完美契合 CQHTTP API 的一套异步发送器,同样支持 HTTP 和 WebSocket
- [Middleware](https://koishijs.github.io/guide/receive-and-send.html#中间件):支持异步操作的中间件系统,可以让你高效地处理每一条信息
- [Context](https://koishijs.github.io/guide/plugin-and-context.html#创建上下文):用上下文描述了机器人可能的运行环境,让你得以对不同的群进行不同的处理
- [Plugin](https://koishijs.github.io/guide/plugin-and-context.html#使用插件):将逻辑以插件的形式封装,可以实现更好的模块化和配置化
- [Command](https://koishijs.github.io/guide/command-system.html):Koishi 的核心功能之一,使用链式调用轻松创建指令,同时提供了大量的实用特性
- [Database](https://koishijs.github.io/guide/using-database.html):内置的数据库系统,但并不依赖具体的数据库实现,无论何种数据库都可以在 Koishi 中使用
- [Receiver](https://koishi.js.org/guide/receive-and-send.html#接收器):将收到的信息转化为事件进行分发,且同时支持 HTTP 和 WebSocket
- [Sender](https://koishi.js.org/guide/receive-and-send.html#发送器):完美契合 CQHTTP API 的一套异步发送器,同样支持 HTTP 和 WebSocket
- [Middleware](https://koishi.js.org/guide/receive-and-send.html#中间件):支持异步操作的中间件系统,可以让你高效地处理每一条信息
- [Context](https://koishi.js.org/guide/plugin-and-context.html#创建上下文):用上下文描述了机器人可能的运行环境,让你得以对不同的群进行不同的处理
- [Plugin](https://koishi.js.org/guide/plugin-and-context.html#使用插件):将逻辑以插件的形式封装,可以实现更好的模块化和配置化
- [Command](https://koishi.js.org/guide/command-system.html):Koishi 的核心功能之一,使用链式调用轻松创建指令,同时提供了大量的实用特性
- [Database](https://koishi.js.org/guide/using-database.html):内置的数据库系统,但并不依赖具体的数据库实现,无论何种数据库都可以在 Koishi 中使用

每一个部分都经过了精心的编写,可以让你轻松实现任何需求。

参见:[API 文档](https://koishijs.github.io/api/index.html)
参见:[API 文档](https://koishi.js.org/api/index.html)

### 丰富的生态系统

Koishi 在编写时,也同样编写了大量的官方插件作为补充。它们有些 Koishi 的基础功能,有些则为 Koishi 的使用提供了许多便利。更重要的是,这数十个插件都可以作为 Koishi 插件开发的极好示范。

参见:[官方插件](https://koishijs.github.io/plugins/common.html)
参见:[官方插件](https://koishi.js.org/plugins/common.html)

### 多机器人支持

Koishi 原生地支持了多机器人开发,同时为这些机器人之间互通数据、共用服务器、保证数据安全提供了原生的解决方案,这有助于在保持高性能的同时,将腾讯风控造成的影响降低到最小。

参见:[多机器人开发](https://koishijs.github.io/guide/multiple-bots.html)
参见:[多机器人开发](https://koishi.js.org/guide/multiple-bots.html)

### 类型与单元测试

Expand All @@ -66,9 +66,9 @@ Koishi 在开发时借助了下面的工具:

### 对比

| 特性 | koishi<br>1.0.0 | cqhttp<br>1.1.1 | cq-websocket<br>2.0.2 | lemon-bot<br>0.5.1 | @ionjs/core<br>0.6.5 |
| 特性 | [koishi<br>1.3.0](https://www.npmjs.com/package/koishi/v/1.3.0) | [cqhttp<br>1.2.0](https://www.npmjs.com/package/cqhttp/v/1.2.0) | [cq-websocket<br>2.0.2](https://www.npmjs.com/package/cq-websocket/v/2.0.2) | [lemon-bot<br>0.6.0](https://www.npmjs.com/package/lemon-bot/v/0.6.0) | [@ionjs/core<br>0.6.5](https://www.npmjs.com/package/@ionjs/core/v/0.6.5) |
|:--:|:--:|:--:|:--:|:--:|:--:|
| 依赖数量 | [17](http://npm.anvaka.com/#/view/2d/koishi/1.0.0-alpha.6) | [63](http://npm.anvaka.com/#/view/2d/cqhttp/1.1.1) | [37](http://npm.anvaka.com/#/view/2d/cq-websocket/2.0.2) | [55](http://npm.anvaka.com/#/view/2d/lemon-bot/0.5.1) | [73](http://npm.anvaka.com/#/view/2d/%2540ionjs%252Fcore/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) |
| HTTP | ✔️ | ✔️ || ✔️ | ✔️ |
| WebSocket | ✔️ || ✔️ |||
| 反向 WebSocket ||||||
Expand All @@ -77,7 +77,8 @@ Koishi 在开发时借助了下面的工具:
| 中间件 | ✔️ |||| ✔️ |
| 命令行 | ✔️ |||||
| 指令 | ✔️ ||| ✔️ ||
| 会话 |||| ✔️ | ✔️ |

注:依赖数量如果表示为 X/Y,则 X 表示命令行工具依赖数量, Y 表示核心库依赖数量。

## 安装

Expand All @@ -104,7 +105,22 @@ koishi run

**注意:** Koishi 要求您的 Node.js 的版本不小于 10,CQHTTP 的版本不小于 3.0。过低的 CQHTTP 版本将不会支持 Koishi 的某些功能。因此,我们建议您保持较新的 CQHTTP 版本以确保所有功能可用。

完整的文档在 [这里](https://koishijs.github.io/guide/getting-started.html)
完整的文档在 [这里](https://koishi.js.org/guide/getting-started.html)

## 最新版本

| 包名 | 版本 |
|:-:|:-:|
| [koishi](https://github.com/koishijs/koishi/tree/master/packages/koishi-cli) | [![npm](https://img.shields.io/npm/v/koishi?style=flat-square)](https://www.npmjs.com/package/koishi) |
| [koishi-core](https://github.com/koishijs/koishi/tree/master/packages/koishi-core) | [![npm](https://img.shields.io/npm/v/koishi-core?style=flat-square)](https://www.npmjs.com/package/koishi-core) |
| [koishi-utils](https://github.com/koishijs/koishi/tree/master/packages/koishi-utils) | [![npm](https://img.shields.io/npm/v/koishi-utils?style=flat-square)](https://www.npmjs.com/package/koishi-utils) |
| [koishi-test-utils](https://github.com/koishijs/koishi/tree/master/packages/test-utils) | [![npm](https://img.shields.io/npm/v/koishi-test-utils?style=flat-square)](https://www.npmjs.com/package/koishi-test-utils) |
| [koishi-database-level](https://github.com/koishijs/koishi/tree/master/packages/database-level) | [![npm](https://img.shields.io/npm/v/koishi-database-level?style=flat-square)](https://www.npmjs.com/package/koishi-database-level) |
| [koishi-database-mysql](https://github.com/koishijs/koishi/tree/master/packages/database-mysql) | [![npm](https://img.shields.io/npm/v/koishi-database-mysql?style=flat-square)](https://www.npmjs.com/package/koishi-database-mysql) |
| [koishi-database-sqlite](https://github.com/koishijs/koishi/tree/master/packages/database-sqlite) | [![npm](https://img.shields.io/npm/v/koishi-database-sqlite?style=flat-square)](https://www.npmjs.com/package/koishi-database-sqlite) |
| [koishi-plugin-common](https://github.com/koishijs/koishi/tree/master/packages/plugin-common) | [![npm](https://img.shields.io/npm/v/koishi-plugin-common?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-common) |
| [koishi-plugin-schedule](https://github.com/koishijs/koishi/tree/master/packages/plugin-schedule) | [![npm](https://img.shields.io/npm/v/koishi-plugin-schedule?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-schedule) |
| [koishi-plugin-teach](https://github.com/koishijs/koishi/tree/master/packages/plugin-teach) | [![npm](https://img.shields.io/npm/v/koishi-plugin-teach?style=flat-square)](https://www.npmjs.com/package/koishi-plugin-teach) |

## 更新日志

Expand All @@ -122,7 +138,7 @@ koishi run

### 完善 Koishi 的文档

与上面类似,但是针对的是 [这个项目](https://github.com/koishijs/koishijs.github.io)
与上面类似,但是针对的是 [这个项目](https://github.com/koishijs/koishi.js.org)

### 开发 Koishi 插件

Expand Down
39 changes: 19 additions & 20 deletions build/bump.ts
Expand Up @@ -22,12 +22,14 @@ class Package {
name: string
meta: PackageJson
oldVersion: string
metaVersion: string
version: SemVer
dirty: boolean

static async from (path: string) {
try {
const pkg = packages[path] = new Package(path)
pkg.metaVersion = pkg.meta.version
pkg.oldVersion = pkg.meta.version
if (pkg.meta.private) return
pkg.oldVersion = await latest(pkg.name)
Expand Down Expand Up @@ -103,25 +105,18 @@ function bumpPkg (source: Package, flag: BumpType, only = false) {
if (!newVersion) return
const dependents = new Set<Package>()
each((target) => {
const { meta } = target
if (target.name === source.name) return
Object.keys(meta.devDependencies || {}).forEach((name) => {
if (name !== source.name) return
meta.devDependencies[name] = '^' + newVersion
target.dirty = true
})
Object.keys(meta.peerDependencies || {}).forEach((name) => {
if (name !== source.name) return
meta.peerDependencies[name] = '^' + newVersion
target.dirty = true
dependents.add(target)
})
Object.keys(meta.dependencies || {}).forEach((name) => {
if (name !== source.name) return
meta.dependencies[name] = '^' + newVersion
target.dirty = true
dependents.add(target)
})
const { devDependencies, peerDependencies, dependencies } = target.meta
const { name } = source
if (target.name === name) return
Object.entries({ devDependencies, peerDependencies, dependencies })
.filter(([_, dependencies = {}]) => dependencies[name])
.forEach(([type]) => {
target.meta[type][name] = '^' + newVersion
target.dirty = true
if (type !== 'devDependencies') {
dependents.add(target)
}
})
})
if (only) return
dependents.forEach(dep => bumpPkg(dep, flag))
Expand All @@ -148,7 +143,11 @@ const flag = options.major ? 'major' : options.minor ? 'minor' : options.patch ?

await Promise.all(each((pkg) => {
if (!pkg.dirty) return
console.log(`- ${pkg.name}: ${cyan(pkg.oldVersion)} => ${green(pkg.meta.version)}`)
if (pkg.metaVersion === pkg.meta.version) {
console.log(`- ${pkg.name}: updated`)
} else {
console.log(`- ${pkg.name}: ${cyan(pkg.oldVersion)} => ${green(pkg.meta.version)}`)
}
return pkg.save()
}))
})()
2 changes: 1 addition & 1 deletion build/start.ts
Expand Up @@ -4,7 +4,7 @@ import spawn from 'cross-spawn'
const name = process.argv[2]
if (!name) process.exit(0)

spawn('npx', ['koishi', 'run'], {
spawn('npx', ['koishi', 'run', ...process.argv.slice(3)], {
cwd: resolve(__dirname, '../bots', name),
stdio: 'inherit',
})
2 changes: 1 addition & 1 deletion jest.config.js
Expand Up @@ -10,7 +10,7 @@ module.exports = {
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'js', 'json'],
moduleNameMapper: {
"koishi-(test-utils|database-[\\w-]+)": "<rootDir>/packages/$1/src",
"koishi-(test-utils|(database|plugin)-[\\w-]+)": "<rootDir>/packages/$1/src",
"koishi-[\\w-]+": "<rootDir>/packages/$0/src",
},
coverageReporters: ['text', 'lcov'],
Expand Down
13 changes: 7 additions & 6 deletions package.json
Expand Up @@ -3,7 +3,8 @@
"private": true,
"workspaces": [
"bots/*",
"packages/*"
"packages/*",
"plugins/*"
],
"scripts": {
"build": "tsc -b",
Expand All @@ -21,17 +22,17 @@
"@types/cross-spawn": "^6.0.1",
"@types/fs-extra": "^8.0.1",
"@types/jest": "^24.0.25",
"@types/node": "^13.1.5",
"@types/node": "^13.1.6",
"@types/semver": "^6.2.0",
"@typescript-eslint/eslint-plugin": "^2.15.0",
"@typescript-eslint/parser": "^2.15.0",
"cac": "^6.5.3",
"cac": "^6.5.4",
"cross-spawn": "^7.0.1",
"del": "^5.1.0",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.0",
"eslint-plugin-import": "^2.19.1",
"eslint-plugin-jest": "^23.3.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-jest": "^23.6.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
Expand All @@ -46,7 +47,7 @@
"prompts": "^2.3.0",
"semver": "^7.1.1",
"ts-jest": "^24.3.0",
"ts-node": "^8.5.4",
"ts-node": "^8.6.1",
"typescript": "^3.7.4"
}
}
8 changes: 8 additions & 0 deletions packages/database-level/README.md
@@ -1,3 +1,11 @@
# koishi-database-level

[![Status](https://img.shields.io/github/workflow/status/koishijs/koishi/CI/master?style=flat-square)](https://github.com/koishijs/koishi/actions?query=workflow:CI)
[![npm](https://img.shields.io/npm/v/koishi-database-level?style=flat-square)](https://www.npmjs.com/package/koishi-database-level)

Leveldb implementation for Koishi.

## Usage

- [Using Database with Koishi](https://koishi.js.org/guide/using-database.html)
- [Full API Reference](https://koishi.js.org/api/database.html)
2 changes: 1 addition & 1 deletion packages/database-level/package.json
Expand Up @@ -38,7 +38,7 @@
"dependencies": {
"@types/leveldown": "^4.0.2",
"@types/levelup": "^4.3.0",
"koishi-core": "^1.2.0",
"koishi-core": "^1.3.0",
"koishi-utils": "^1.0.2",
"leveldown": "^5.4.1",
"levelup": "^4.3.2",
Expand Down
8 changes: 8 additions & 0 deletions packages/database-mysql/README.md
@@ -1,3 +1,11 @@
# koishi-database-mysql

[![Status](https://img.shields.io/github/workflow/status/koishijs/koishi/CI/master?style=flat-square)](https://github.com/koishijs/koishi/actions?query=workflow:CI)
[![npm](https://img.shields.io/npm/v/koishi-database-mysql?style=flat-square)](https://www.npmjs.com/package/koishi-database-mysql)

MySQL implementation for Koishi.

## Usage

- [Using Database with Koishi](https://koishi.js.org/guide/using-database.html)
- [Full API Reference](https://koishi.js.org/api/database.html)
4 changes: 2 additions & 2 deletions packages/database-mysql/package.json
@@ -1,7 +1,7 @@
{
"name": "koishi-database-mysql",
"description": "MySQL support for Koishi",
"version": "1.0.3",
"version": "1.0.4",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
Expand Down Expand Up @@ -35,7 +35,7 @@
"@types/mysql": "^2.15.8"
},
"dependencies": {
"koishi-core": "^1.2.0",
"koishi-core": "^1.3.0",
"koishi-utils": "^1.0.2",
"mysql": "^2.17.1"
}
Expand Down
18 changes: 7 additions & 11 deletions packages/database-mysql/src/group.ts
@@ -1,4 +1,4 @@
import { contain, observe, difference } from 'koishi-utils'
import { contain, observe } from 'koishi-utils'
import { getSelfIds, injectMethods, GroupData, createGroup, groupFields, GroupField, Group } from 'koishi-core'

declare module './database' {
Expand All @@ -18,8 +18,8 @@ injectMethods('mysql', 'group', {
const fields = args[0] as never || groupFields
const timestamp = Date.now()
const cache = groupCache[groupId]
const upToDate = timestamp - cache._timestamp < (this.config.groupRefreshInterval ?? defaultRefreshInterval)
if (cache && contain(Object.keys(cache), fields) && upToDate) return cache
if (cache && contain(Object.keys(cache), fields)
&& timestamp - cache._timestamp < (this.config.groupRefreshInterval ?? defaultRefreshInterval)) return cache

const [data] = await this.select<GroupData[]>('group', fields, '`id` = ?', [groupId])
let fallback: GroupData
Expand Down Expand Up @@ -74,15 +74,11 @@ injectMethods('mysql', 'group', {

const selfId = typeof args[0] === 'number' ? args.shift() as number : 0
const fields = args[0] as never || groupFields
const additionalFields = difference(fields, Object.keys(group))
const additionalData = additionalFields.length
? await this.getGroup(group.id, selfId, difference(fields, Object.keys(group)))
const additionalData = fields.length
? await this.getGroup(group.id, selfId, fields)
: {} as Partial<GroupData>
if ('_diff' in group) {
return (group as Group)._merge(additionalData)
} else {
return observe(Object.assign(group, additionalData), diff => this.setGroup(group.id, diff), `group ${group.id}`)
}
if ('_diff' in group) return (group as Group)._merge(additionalData)
return observe(Object.assign(group, additionalData), diff => this.setGroup(group.id, diff), `group ${group.id}`)
},

async getGroupCount () {
Expand Down
16 changes: 6 additions & 10 deletions packages/database-mysql/src/user.ts
@@ -1,5 +1,5 @@
import { injectMethods, userFields, UserData, createUser, User, UserField } from 'koishi-core'
import { observe, difference } from 'koishi-utils'
import { observe } from 'koishi-utils'
import { arrayTypes } from './database'

arrayTypes.push('user.endings', 'user.achievement', 'user.inference')
Expand Down Expand Up @@ -31,7 +31,7 @@ injectMethods('mysql', 'user', {
if (args.length > 1) {
ids = args[0]
fields = args[1]
} else if (args.length && typeof args[0][0] === 'number') {
} else if (args.length && typeof args[0][0] !== 'string') {
ids = args[0]
fields = userFields
} else {
Expand All @@ -53,15 +53,11 @@ injectMethods('mysql', 'user', {

const authority = typeof args[0] === 'number' ? args.shift() as number : 0
const fields = args[0] as never || userFields
const additionalFields = difference(fields, Object.keys(user))
const additionalData = additionalFields.length
? await this.getUser(user.id, authority, difference(fields, Object.keys(user)))
const additionalData = fields.length
? await this.getUser(user.id, authority, fields)
: {} as Partial<UserData>
if ('_diff' in user) {
return (user as User)._merge(additionalData)
} else {
return observe(Object.assign(user, additionalData), diff => this.setUser(user.id, diff), `user ${user.id}`)
}
if ('_diff' in user) return (user as User)._merge(additionalData)
return observe(Object.assign(user, additionalData), diff => this.setUser(user.id, diff), `user ${user.id}`)
},

async getUserCount () {
Expand Down
11 changes: 11 additions & 0 deletions packages/database-sqlite/README.md
@@ -0,0 +1,11 @@
# koishi-database-sqlite

[![Status](https://img.shields.io/github/workflow/status/koishijs/koishi/CI/master?style=flat-square)](https://github.com/koishijs/koishi/actions?query=workflow:CI)
[![npm](https://img.shields.io/npm/v/koishi-database-sqlite?style=flat-square)](https://www.npmjs.com/package/koishi-database-sqlite)

sqlite implementation for Koishi.

## Usage

- [Using Database with Koishi](https://koishi.js.org/guide/using-database.html)
- [Full API Reference](https://koishi.js.org/api/database.html)

0 comments on commit 350a952

Please sign in to comment.