Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
K
Koishi Nestjs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
3rdeye
Koishi Nestjs
Commits
d84f8313
Commit
d84f8313
authored
Jan 29, 2022
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
readme
parent
6a95751a
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
114 additions
and
468 deletions
+114
-468
README.md
README.md
+92
-446
package-lock.json
package-lock.json
+21
-21
package.json
package.json
+1
-1
No files found.
README.md
View file @
d84f8313
#
Koishi-Nest
#
koishi-nestjs
[
Nest.js
](
http://nestjs.com/
)
下的
[
Koishi
](
https://koishi.js.org
)
模块。
Koishi-Nest
在 Nest.js 下使用 Koishi 打造规模化的机器人应用。
[
Nest.js
](
http://nestjs.com/
)
下的
[
Koishi
](
https://koishi.js.org
)
模块。
koishi-nestjs
在 Nest.js 下使用 Koishi 打造规模化的机器人应用。
目前只支持 Koishi v4 和 Nest v8 。
...
...
@@ -10,7 +10,11 @@
npm
install
koishi-nestjs koishi
```
## 配置
## 配置模块
koishi-nestjs 中,Koishi 以 Nest.js 的模块的形式引入到项目工程中。我们支持同步和异步两种配置方式。
另外,KoishiModule 会被注册为
[
全局模块
](
https://docs.nestjs.cn/8/modules?id=%e5%85%a8%e5%b1%80%e6%a8%a1%e5%9d%97
)
。在项目的任何模块中注册 KoishiModule 后,在项目的任何位置均能使用 Koishi 的功能。
### 同步
...
...
@@ -45,7 +49,7 @@ export class AppModule {}
import
{
Module
}
from
'
@nestjs/common
'
;
import
{
ConfigModule
,
ConfigService
}
from
'
@nestjs/config
'
;
import
{
KoishiModule
,
PluginDef
}
from
'
koishi-nestjs
'
;
import
PluginOnebot
from
'
@koishijs/plugin-onebot
'
;
import
PluginOnebot
from
'
@koishijs/plugin-
adapter-
onebot
'
;
@
Module
({
imports
:
[
...
...
@@ -73,47 +77,83 @@ export class AppModule {}
### 配置项
Koishi-Nest 的配置项和 Koishi 配置项一致,参照
[
Koishi 文档
](
https://koishi.js.org/api/core/app.html#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E9%80%89%E9%A1%B9
)
。下列配置项为 Koishi-Nest 特有的配置项。
koishi-nestjs 的配置项和
[
Koishi 配置项
](
https://koishi.js.org/api/core/app.html
)
基本一致,下面是 koishi-nestjs 特有的配置项:
*
`loggerPrefix`
:
`string`
Nest 日志中 Logger 的前缀。默认
`koishi`
。
-
`loggerPrefix`
:
`string`
Nest 日志中 Logger 的前缀。默认
`koishi`
。
*
`loggerColor`
:
`number`
Nest 日志中 Logger 的颜色支持。默认
`0`
。
-
`loggerColor`
:
`number`
Nest 日志中 Logger 的颜色支持。默认
`0`
。
*
`usePlugins`
:
`KoishiModulePlugin[]`
可选。预先安装的 Koishi 插件列表。使用
`PluginDef(plugin, options, select)`
方法生成该项的定义。该配置项的成员参数如下。
-
`usePlugins`
:
`KoishiModulePlugin[]`
可选。预先安装的 Koishi 插件列表。使用
`PluginDef(plugin, options, select)`
方法生成该项的定义。该配置项的成员参数如下。
*
`plugin`
Koishi 插件。
*
`options`
Koishi 插件配置。等同于
`ctx.plugin(plugin, options)`
。
*
上下文选择器见本文
**上下文选择器**
部分
。
-
`plugin`
Koishi 插件。
-
`options`
Koishi 插件配置。等同于
`ctx.plugin(plugin, options)`
。
-
`select`
可选,Selection 对象,指定插件的
[
上下文选择器
](
https://koishi.js.org/guide/plugin/context.html#配置插件上下文
)
。
*
`moduleSelection`
`KoishiModuleSelection[]`
可选。选择 Nest 实例加载的其他 Nest 模块注入的 Koishi 上下文作用域,参数如下。
-
`moduleSelection`
`KoishiModuleSelection[]`
可选。指定 Nest 实例加载的其他 Nest 模块注入的 Koishi 上下文选择器,参数如下:
*
`module`
Nest 模块名。
*
上下文选择器见本文
**上下文选择器**
部分
。
-
`module`
Nest 模块名。
-
`select`
Selection 对象,指定插件的
[
上下文选择器
](
https://koishi.js.org/guide/plugin/context.html#配置插件上下文
)
。
*
`globalInterceptors`
全局命令拦截器,详见
**命令拦截器**
部分。
-
`useWs`
:
`boolean`
默认
`false`
。是否启用 WebSocket 网关。
**异步配置该项应写入异步配置项中。**
插件的使用可以参考
[
Koishi 文档
](
https://koishi.js.org/guide/plugin/plugin.html
)
。
`moduleSelection`
的使用见本文
**复用性**
部分。
#### 不支持的配置项
*
`useWs`
:
`boolean`
默认
`false`
。是否启用 WebSocket 。
**异步配置该项应写入异步配置项中。**
详见本文的
**WebSocket**
部分。
由于 koishi-nestjs 复用了 Nest.js 实例的 HttpServer 对象,因此下列关于 HttpServer 监听的选项将不受支持:
*
`isGlobal`
:
`boolean`
默认
`true`
。指示 Koishi-Nest 模块是否应被注册为全局模块,建议开启。当安装了其他模块的情况下,需要将 Koishi-Nest 注册为全局模块使得其他模块可以正常注入 Koishi-Nest 作为依赖项。
**异步配置该项应写入异步配置项中。**
关于全局模块请参考
[
Nest.js 文档
](
https://docs.nestjs.cn/8/modules?id=%e5%85%a8%e5%b1%80%e6%a8%a1%e5%9d%97
)
。
-
`port`
-
`host`
##
WebSocket
##
# WebSocket 服务器
Koishi-Nest 针对 Koishi 的 WebSocket 功能进行了针对 Nest.js 的适配
。
和直接运行 Koishi 不同,Nest.js 中的 Koishi 模块并不会直接注册 HttpServer,而是将 HttpServer 与 Nest.js 中的 HttpServer 进行绑定。而 WebSocket 使用的也是 Nest.js 中的
[
WebSocket 网关
](
https://docs.nestjs.cn/8/websockets
)
。因此若要使用到如
`console`
或
`adapter-onebot`
的反向 WebSocket 功能的插件,需要在 Nest.js 实例注册时进行一些额外的配置
。
若要使用 Koishi 的与 WebSocket 服务器相关的插件或功能,需要在 Koishi-Nest 配置项中,把
`useWs`
设置为
`true`
,并在
`main.ts`
修改下列部分。
为了与 Koishi 更好地适配 Nest.js 的 WebSocket,koishi-nestjs 提供了基于
`@nestjs/platform-ws`
的专用 Nest WebSocket 适配器。我们需要在 Koishi 模块配置中设置
`useWs`
为
`true`
,并加载专用 WebSocket 适配器:
```
ts
const
app
=
await
NestFactory
.
create
(
AppModule
);
app
.
useWebSocketAdapter
(
new
KoishiWsAdapter
(
app
));
// app.module.ts
import
{
Module
}
from
'
@nestjs/common
'
;
import
{
ConfigModule
,
ConfigService
}
from
'
@nestjs/config
'
;
import
{
KoishiModule
,
PluginDef
}
from
'
koishi-nestjs
'
;
import
PluginOnebot
from
'
@koishijs/plugin-adapter-onebot
'
;
@
Module
({
imports
:
[
KoishiModule
.
registerAsync
({
imports
:
[
ConfigModule
.
forRoot
()],
inject
:
[
ConfigService
],
useWs
:
true
,
useFactory
:
async
(
config
:
ConfigService
)
=>
({
// 在这里填写 Koishi 配置参数
prefix
:
'
.
'
,
usePlugins
:
[
// 预安装的插件
PluginDef
(
PluginOnebot
,
{
protocol
:
'
ws
'
,
endpoint
:
config
.
get
(
'
CQ_ENDPOINT
'
),
selfId
:
config
.
get
(
'
CQ_SELFID
'
),
token
:
config
.
get
(
'
CQ_TOKEN
'
),
}),
],
})
})
]
})
export
class
AppModule
{}
// main.ts
const
app
=
await
NestFactory
.
create
(
AppModule
);
app
.
useWebSocketAdapter
(
new
KoishiWsAdapter
(
app
));
```
## 注入 Koishi 实例
该适配器拥有和
`@nestjs/platform-ws`
基本一致的功能。在 Nest.js 工程内您可以如同正常的 WebSocket 适配器一般使用它。
## 注入实例
在 Nest.js 你可以在控制器或提供者类中直接对 Koishi 实例或上下文进行注入操作。
可以直接注入 Koishi 实例或上下文进行注册操作。这种情况下,建议让 Nest 提供者
实现
`OnModuleInit`
接口,并在该事件方法中进行 Koishi 指令注册操作。
这种情况下,建议让 Nest 提供者类
实现
`OnModuleInit`
接口,并在该事件方法中进行 Koishi 指令注册操作。
Koishi-Nest 将在应用程序
启动时启动 Koishi 实例。
koishi-nestjs 将在 Nest.js 应用
启动时启动 Koishi 实例。
### 注入完整 Koishi 实例
...
...
@@ -123,10 +163,10 @@ import { Injectable, OnModuleInit } from '@nestjs/common';
@
Injectable
()
export
class
AppService
implements
OnModuleInit
{
constructor
(
private
koishi
:
KoishiService
)
{}
constructor
(
private
koishi
App
:
KoishiService
)
{}
onModuleInit
()
{
this
.
koishi
.
on
(
'
message
'
,
(
session
)
=>
{})
this
.
koishi
App
.
on
(
'
message
'
,
(
session
)
=>
{})
}
}
```
...
...
@@ -169,19 +209,19 @@ export class AppService implements OnModuleInit {
在 Nest 提供者构造函数参数列表中使用下列装饰器即可进行注入操作。
*
`@InjectContext()`
注入全体上下文。等价于
`ctx.any()`
-
`@InjectContext()`
注入全体上下文。等价于
`ctx.any()`
*
`@InjectContextPrivate(...values[]: string)`
注入私聊上下文。等价于
`ctx.private(...values)`
-
`@InjectContextPrivate(...values[]: string)`
注入私聊上下文。等价于
`ctx.private(...values)`
*
`@InjectContextChannel(...values[]: string)`
注入频道上下文。等价于
`ctx.channel(...values)`
-
`@InjectContextChannel(...values[]: string)`
注入频道上下文。等价于
`ctx.channel(...values)`
*
`@InjectContextGuild(...values[]: string)`
注入群组上下文。等价于
`ctx.guild(...values)`
-
`@InjectContextGuild(...values[]: string)`
注入群组上下文。等价于
`ctx.guild(...values)`
*
`@InjectContextSelf(...values[]: string)`
注入机器人账户上下文。等价于
`ctx.self(...values)`
-
`@InjectContextSelf(...values[]: string)`
注入机器人账户上下文。等价于
`ctx.self(...values)`
*
`@InjectContextUser(...values[]: string)`
注入用户上下文。等价于
`ctx.user(...values)`
-
`@InjectContextUser(...values[]: string)`
注入用户上下文。等价于
`ctx.user(...values)`
*
`@InjectContextPlatform(...values[]: string)`
注入平台上下文。等价于
`ctx.platform(...values)`
-
`@InjectContextPlatform(...values[]: string)`
注入平台上下文。等价于
`ctx.platform(...values)`
### 在自定义提供者注入 Koishi 上下文
...
...
@@ -210,437 +250,43 @@ export class AppModule {}
#### 函数定义
`getContextProvideToken(scopeType?: ContextScopeTypes, values: string[] = [])`
*
`scopeType`
作用域类型,可以是
`private`
`channel`
`guild`
`self`
`user`
`platform`
之一。留空表示全局上下文。
*
`values`
作用域值。例如
`getContextProvideToken('platform', ['onebot'])`
等价于
`ctx.platform('onebot')`
.
## 使用装饰器注册 Koishi 指令
您也可以在完全不注入任何 Koishi 上下文的情况下注册 Koishi 指令,只需要在提供者类中使用装饰器即可。下面是一个例子。
```
ts
@
Injectable
()
// 可以在提供者类中指定上下文选择器,等价于 `ctx.guild('111111111')`
@
OnGuild
(
'
111111111
'
)
export
class
AppService
{
// 等价于 `ctx.on('message', (session) => { })`
@
UseEvent
(
'
message
'
)
async
onMessage
(
session
:
Session
.
Payload
<
'
message
'
>
)
{
console
.
log
(
`event
${
session
.
userId
}
:
${
session
.
content
}
`
);
}
// 也可以在类成员方法中指定上下文选择器
@
OnPlatform
(
'
onebot
'
)
// 等价于 `ctx.middleware((session, next) => { })`
@
UseMiddleware
(
true
)
async
onMiddleware
(
session
:
Session
.
Payload
<
'
message
'
>
,
next
:
NextFunction
)
{
console
.
log
(
`middleware
${
session
.
userId
}
:
${
session
.
content
}
`
);
next
();
}
// 注册插件,可以异步注册插件
@
UsePlugin
()
async
installPlugin
()
{
const
config
=
await
someAsyncThings
();
return
PluginDef
(
PluginCommon
,
config
);
}
// 定义命令
@
UseCommand
(
'
my-echo <content:string>
'
)
@
CommandDescription
(
'
Echo command from decorators!
'
)
@
CommandUsage
(
'
Command usage
'
)
@
CommandExample
(
'
Command example
'
)
testEchoCommand
(@
PutArgv
()
argv
:
Argv
,
@
PutArg
(
0
)
content
:
string
)
{
return
content
;
}
}
```
### 装饰器定义
#### 选择器
选择器装饰器可以注册在提供者类,也可以注册在提供者方法函数。
选择器的使用请参照
[
Koishi 文档
](
https://koishi.js.org/guide/plugin/context.html#%E4%BD%BF%E7%94%A8%E9%80%89%E6%8B%A9%E5%99%A8
)
。
*
`@OnAnywhere()`
等价于
`ctx.any()`
。
*
*
`@OnNowhere()`
等价于
`ctx.never()`
。
*
*
`@OnUser(value)`
等价于
`ctx.user(value)`
。
*
`@OnSelf(value)`
等价于
`ctx.self(value)`
。
*
`@OnGuild(value)`
等价于
`ctx.guild(value)`
。
*
`@OnChannel(value)`
等价于
`ctx.channel(value)`
。
*
`@OnPlatform(value)`
等价于
`ctx.platform(value)`
。
*
`@OnPrivate(value)`
等价于
`ctx.private(value)`
。
*
`@OnSelection(value)`
等价于
`ctx.select(value)`
。
*
`@OnContext((ctx: Context) => Context)`
手动指定上下文选择器,用于 Koishi-Nest 不支持的选择器。例如,
```
ts
@
OnContext
(
ctx
=>
ctx
.
platform
(
'
onebot
'
))
function
getContextProvideToken
(
scopeType
?:
ContextScopeTypes
,
values
:
string
[]
=
[]);
```
#### Koishi 注册
注册装饰器只能注册于提供者类方法中,如下。
*
`@UseMiddleware(prepend?: boolean)`
注册中间件,等价于
`ctx.middleware((session, next) => { }, prepend)`
。
[
参考
](
https://koishi.js.org/guide/message/message.html#%E6%B3%A8%E5%86%8C%E5%92%8C%E5%8F%96%E6%B6%88%E4%B8%AD%E9%97%B4%E4%BB%B6
)
*
`@UseEvent(name: EventName, prepend?: boolean)`
注册事件监听器。等价于
`ctx.on(name, (session) => { }, prepend)`
。
[
参考
](
https://koishi.js.org/guide/plugin/lifecycle.html#%E4%BA%8B%E4%BB%B6%E7%B3%BB%E7%BB%9F
)
*
`@UsePlugin()`
使用该方法注册插件。在 Koishi 实例注册时该方法会自动被调用。该方法需要返回插件定义,可以使用
`PluginDef(plugin, options, select)`
方法生成。
[
参考
](
https://koishi.js.org/guide/plugin/plugin.html#%E5%AE%89%E8%A3%85%E6%8F%92%E4%BB%B6
)
*
`@UseCommand(def: string, desc?: string, config?: Command.Config)`
注册指令。指令系统可以参考
[
Koishi 文档
](
https://koishi.js.org/guide/command.html
)
。指令回调参数位置和类型和 Koishi 指令一致。
#### 指令描述装饰器
Koishi-Nest 使用一组装饰器进行描述指令的行为。这些装饰器需要和
`@UseCommand(def)`
一起使用。
*
`@CommandUse(callback, ...args)`
指令功能配置。等价于
`cmd.use(callback, ...args)`
。
*
`@CommandDescription(text: string)`
指令描述。等价于
`ctx.command(def, desc)`
中的描述。
*
`@CommandUsage(text: Command.Usage)`
指令介绍。等价于
`cmd.usage(text)`
。
*
`@CommandExample(text: string)`
指令示例。等价于
`cmd.example(text)`
。
*
`@CommandAlias(def: string)`
指令别名。等价于
`cmd.alias(def)`
。
*
`@CommandShortcut(def: string, config?: Command.Shortcut)`
指令快捷方式。等价于
`cmd.shortcut(def, config)`
。
#### 指令参数
指令参数也使用一组装饰器对指令参数进行注入。下列装饰器应对提供者方法参数进行操作。
*
`@PutArgv(field?: keyof Argv)`
注入
`Argv`
对象,或
`Argv`
对象的指定字段。
*
`@PutSession(field?: keyof Session)`
注入
`Session`
对象,或
`Session`
对象的指定字段。
*
`@PutArg(index: number)`
注入指令的第 n 个参数。
*
`@PutOption(name: string, desc: string, config: Argv.OptionConfig = {})`
给指令添加选项并注入到该参数。等价于
`cmd.option(name, desc, config)`
。
*
`@PutUser(fields: string[])`
添加一部分字段用于观测,并将 User 对象注入到该参数。
-
`scopeType`
选择器类型,可以是
`private`
`channel`
`guild`
`self`
`user`
`platform`
之一。留空表示全局上下文。
*
`@PutChannel(fields: string[])`
添加一部分字段用于观测,并将 Channel 对象注入到该参数。
-
`values`
选择器值。例如
`getContextProvideToken('platform', ['onebot'])`
等价于
`ctx.platform('onebot')`
.
*
`@PutNext()`
注入指令的 Next 方法。
关于 Koishi 的观察者概念详见
[
Koishi 文档
](
https://koishi.js.org/guide/database/observer.html#%E8%A7%82%E5%AF%9F%E8%80%85%E5%AF%B9%E8%B1%A1
)
。
## 在提供者类中注册方法
*
`@PutUserName(useDatabase: boolean = true)`
注入当前用户的用户名。
*
`useDatabase`
是否尝试从数据库获取用户名。
您也可以在提供者类中,使用装饰器进行 Koishi 的中间件,事件,指令等方法注册,也可以加载插件。
### 指令拦截器
装饰器定义与 koishi-thirdeye 中一致,请参阅
[
相关文档
](
https://koishi.js.org/guide/misc/decorators.html#注册事件
)
。
和 Koishi 中的
[
`command.before`
](
https://koishi.js.org/guide/message/command.html#%E4%BD%BF%E7%94%A8%E6%A3%80%E6%9F%A5%E5%99%A8
)
对应,Koishi-Nest 提供了
**指令拦截器**
,便于在指令运行之前进行一些操作,如参数检查,记录日志等。
## 使用服务
#### 定义
指令拦截器需要实现
`KoishiCommandInterceptor`
接口,提供
`intercept`
方法。该方法的参数与
`command.before`
的回调函数一致。
> 不要将指令拦截器与 Nest.js 的拦截器混淆。
下面是一个指令拦截器的例子。
```
ts
import
{
KoishiCommandInterceptor
}
from
"
koishi-nestjs
"
;
export
class
MyCommandInterceptor
implements
KoishiCommandInterceptor
{
intercept
(
argv
:
Argv
,
arg1
:
string
)
{
if
(
arg1
.
startsWith
(
'
foo
'
))
{
return
'
Intercepted!
'
;
}
}
}
```
#### 注册
要注册拦截器,只需要在指令对应的提供者方法或提供者本人使用
`@CommandInterceptors`
装饰器即可。也可以指定多个拦截器。
其中,在注册过拦截器的提供者类中,使用
`@InjectContext()`
或类似方法注入的上下文对象,也会应用拦截器。
> 这些上下文内安装的 Koishi 插件不会应用拦截器。
```
ts
import
{
InjectContext
}
from
'
koishi-nestjs
'
;
import
{
Context
}
from
'
koishi
'
;
@
Injectable
()
// 可以在提供者类中指定上下文选择器,等价于 `ctx.guild('111111111')`
@
CommandInterceptors
(
MyGlobalInterceptor
)
export
class
AppService
{
// 这里的 Koishi 上下文注册的任何指令也会应用拦截器
constructor
(@
InjectContext
()
private
ctx
:
Context
)
{}
@
UseCommand
(
'
my-echo <content:string>
'
)
@
CommandInterceptors
(
MyInterceptor1
,
MyInterceptor2
)
// 可以指定多个拦截器。
testEchoCommand
(@
PutArgv
()
argv
:
Argv
,
@
PutArg
(
0
)
content
:
string
)
{
return
content
;
}
}
```
也可以在 Koishi-Nest 启动配置中,使用
`globalInterceptors`
方法注册拦截器。
## 上下文 Service 交互
您可以使用装饰器与 Koishi 的 Service 系统进行交互。
### 注入上下文 Service
注入的 Service 通常来自 Koishi 插件,或是自行提供的 Service 。
您也可以在 Nest.js 的提供者类中,注入 Koishi 的服务对象。
```
ts
import
{
Injectable
,
OnApplicationBootstrap
}
from
"
@nestjs/common
"
;
import
{
WireContextService
,
UseEvent
}
from
'
koishi-nestjs
'
;
import
{
Cach
e
}
from
'
koishi
'
;
import
{
WireContextService
}
from
'
koishi-nestjs
'
;
import
{
Databas
e
}
from
'
koishi
'
;
@
Injectable
()
export
class
AppService
implements
OnApplicationBootstrap
{
constructor
(@
InjectContextGuild
(
'
1111111111
'
)
private
ctx
:
Context
)
{
}
// 注入 Service
// 注入服务对象
@
WireContextService
(
'
cache
'
)
private
cache2
:
Cach
e
;
private
database
:
Databas
e
;
// 成员变量名与
Service
名称一致时 name 可省略。
// 成员变量名与
服务
名称一致时 name 可省略。
@
WireContextService
()
private
cache
:
Cach
e
;
private
database2
:
Databas
e
;
async
onApplicationBootstrap
()
{
// 可以在 onApplicationBootstrap 访问上下文 Service
const
user
=
this
.
cache
.
get
(
'
user
'
,
'
111111111
'
);
}
@
UseEvent
(
'
service/cache
'
)
async
onCacheAvailable
()
{
// 建议监听 Service 事件
const
user
=
this
.
cache
.
get
(
'
user
'
,
'
111111112
'
);
}
}
```
### 提供上下文 Service
您也可以使用 Nest 提供者提供 Koishi 需要的 Service 的实现。
```
ts
import
{
Injectable
}
from
'
@nestjs/common
'
;
import
{
ProvideContextService
}
from
'
koishi-nestjs
'
;
declare
module
'
koishi
'
{
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace
Context
{
interface
Services
{
testProvide
:
TestProvideService
;
}
// onApplicationBootstrap 钩子方法中,插件已经加载完毕,因此在这里可以确保能访问服务对象
const
user
=
this
.
database
.
getUser
(
'
114514
'
);
}
}
// `@ProvideContextService(name)` 装饰器会自动完成 `Context.service(name)` 的声明操作
@
Injectable
()
@
ProvideContextService
(
'
testProvide
'
)
export
class
TestProvideService
{
// 该类会作为 Koishi 的 Service 供其他 Koishi 插件进行引用
}
```
### 定义
*
`@WireContextService(name?: string)`
在 Nest 提供者类某一属性注入特定上下文 Service 。
`name`
默认为类方法名。
*
`@ProvideContextService(name: string)`
使用某一 Nest 提供者类提供 Koishi 上下文 Service 。会自动完成 Koishi 的 Service 声明操作。
## 复用性
Nest 提供了模块系统,我们可以编写功能模块,并在功能模块进行 Koishi 指令注册操作,从而进行代码的有效复用。
### 编写模块
由于 Koishi-Nest 是全局定义的模块,功能模块
**不需要**
引入
`KoishiModule`
作为依赖。
> 功能模块中,请使用 `@InjectContext()` 注册上下文,避免直接注入 `KoishiService` 导致上下文泄漏。
```
ts
import
{
Injectable
,
Module
,
OnModuleInit
}
from
'
@nestjs/common
'
;
import
{
InjectContext
,
OnGuild
,
OnPlatform
,
OnUser
,
UseCommand
,
}
from
'
koishi-nestjs
'
;
import
{
Context
}
from
'
koishi
'
;
@
Injectable
()
export
class
MyService
implements
OnModuleInit
{
constructor
(@
InjectContext
()
private
ctx
:
Context
)
{}
onModuleInit
():
any
{
this
.
ctx
.
command
(
'
my-echo2 <content:string>
'
)
.
action
((
_
,
content
)
=>
content
);
}
@
OnPlatform
(
'
onebot
'
)
@
UseCommand
(
'
my-echo3 <content:string>
'
)
onCommand3
(
_
:
any
,
content
:
string
)
{
return
content
;
}
}
@
Module
({
// Koishi-Nestjs 默认定义为全局模块,因此不需要引入依赖
imports
:
[],
providers
:
[
MyService
],
})
export
class
MyModule
{}
```
为了保证模块的可配置性,我们应该把模块编写为动态模块。关于动态模块的文档可以参照
[
Nest.js 文档
](
https://docs.nestjs.cn/8/fundamentals?id=%e5%8a%a8%e6%80%81%e6%a8%a1%e5%9d%97
)
。
### 使用模块
把要使用的模块填入
`imports`
内即可。
```
ts
import
{
Module
}
from
'
@nestjs/common
'
;
import
{
KoishiModule
}
from
'
koishi-nestjs
'
;
@
Module
({
imports
:
[
KoishiModule
.
register
({
// 在这里填写 Koishi 配置参数
moduleSelection
:
[
// 定义 MyModule 的 Koishi 指令注册只对 OneBot 平台有效
{
module
:
MyModule
,
select
:
{
$platform
:
'
onebot
'
}
}
]
}),
MyModule
]
})
export
class
AppModule
{}
```
## 其他
### 上下文选择器
在 Koishi-Nest 中,选择器对象有下列定义,用于上下文的选择。
*
`select`
: 对象选择器,定义作用上下文。定义参照
[
Koishi 文档
](
https://koishi.js.org/guide/plugin/context.html#%E5%9C%A8%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E4%BD%BF%E7%94%A8%E9%80%89%E6%8B%A9%E5%99%A8
)
的写法。
*
`useSelector`
:
`(ctx: Context) => Context`
使用函数进行选择。该函数接受1个 Context 参数,同时也需要返回1个 Context 对象。
### 帮助函数
*
`PluginDef(plugin: Plugin, options?: PluginConfig, select?: Selection)`
生成指令注册定义。用于 Koishi-Nest 启动参数和
`@UsePlugin()`
返回值。指令注册定义成员参数如下。
*
`plugin`
: Koishi 插件。
*
`options`
: Koishi 插件配置。等同于
`ctx.plugin(plugin, options)`
。
*
上下文选择器见本文
**上下文选择器**
部分。
## 更新历史
### 4.4.0
*
适配 Koishi v4.1。
*
使用 koishi-decorators 重构。
### 4.2.1
*
调整了
`@CommandUsage`
的类型。
### 4.3.0
*
适配 Koishi v4 正式版。
### 4.2.0
*
适配新版 Koishi 。
*
增加了对应
`cmd.use`
的
`@CommandUse`
。
*
`@PutArgv`
现在支持参数,用于注入 Argv 对象的指定字段。
### 4.1.0
*
支持在提供者类顶层配置指令描述。
### 4.0.0
*
适配新版 Koishi 。
### 3.0.0
*
适配新版 Koishi 。
### 2.4.0
*
适配新版 Koishi 。
*
增加了从 koishi-thirdeye 移植而来的 empty 和
`@UseBeforeEvent`
。
*
修复了一个问题,这个问题曾导致
`@UseEvent`
的 prepend 不生效。
### 2.3.0
*
适配新版 Koishi 的 http server 启动机制。
*
添加了单元测试。
### 2.2.1
*
和新版 Service API 兼容。
### 2.0.2
*
`@ProvideContextService`
现在可以传入 Options 了。
### 2.0.1
*
优化了 Service 注入的一些逻辑。
### 2.0.0
*
适配 Koishi v4 beta 。
### 1.5.3
*
修复了一个 BUG ,这个 BUG 曾经导致: 在提供者类注入的 Koishi 上下文不受提供者作用域装饰器的约束。
### 1.5
*
增加了指令拦截器。
### 1.4.2
*
`KoishiWsAdapter`
: 支持正则表达式路径。
### 1.4
*
适配最新的 Koishi 版本的 Websocket 变动。
**使用涉及 Websocket 的 Koishi 插件需要使用附带的 `KoishiWsAdapter`。**
### 1.3.3
*
移除了
`http-proxy-middleware`
。
*
优化了 Nest 的 http 服务器与 Koishi 的 Koa 的对接过程。
### 1.3
*
`@UseCommand`
现在定义和 Koishi 的指令定义,即
`ctx.command(name, desc, config)`
或
`ctx.command(name, config)`
一致了。
*
增加了
`@CommandUserFields`
对应
`cmd.userFields`
以及
`@CommandChannelFields`
对应
`cmd.channelFields`
。
*
增加了用于注入 Koishi 指令调用信息的提供者方法参数装饰器。详见
**指令参数**
部分。
package-lock.json
View file @
d84f8313
...
...
@@ -36,7 +36,7 @@
"eslint-plugin-prettier"
:
"^3.4.1"
,
"express"
:
"^4.17.1"
,
"jest"
:
"^27.4.4"
,
"koishi"
:
"^4.1.
0
"
,
"koishi"
:
"^4.1.
1
"
,
"prettier"
:
"^2.4.1"
,
"reflect-metadata"
:
"^0.1.13"
,
"rimraf"
:
"^3.0.2"
,
...
...
@@ -1043,9 +1043,9 @@
"integrity"
:
"sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg=="
},
"node_modules/@koishijs/core"
:
{
"version"
:
"4.1.
0
"
,
"resolved"
:
"https://registry.npmjs.org/@koishijs/core/-/core-4.1.
0
.tgz"
,
"integrity"
:
"sha512-
f9SSEHxYt5OixXLhX0W9ME36JLQxdb8gwv8R5YOAd4y1IYchOX3qVfbnhRCd41SHUaKLhRWMBzwnl9R1dmqm4A
=="
,
"version"
:
"4.1.
1
"
,
"resolved"
:
"https://registry.npmjs.org/@koishijs/core/-/core-4.1.
1
.tgz"
,
"integrity"
:
"sha512-
UjlqQzT/xjpZPz7sNGdzzSFNUqCr9MgFfPBWZ9lcZ0qkpag9+j8aSW4BVH2q0ZTXoPrTArXTnesBSPpDN4k13g
=="
,
"dependencies"
:
{
"@koishijs/utils"
:
"^5.0.0"
,
"fastest-levenshtein"
:
"^1.0.12"
,
...
...
@@ -5330,12 +5330,12 @@
}
},
"node_modules/koishi"
:
{
"version"
:
"4.1.
0
"
,
"resolved"
:
"https://registry.npmjs.org/koishi/-/koishi-4.1.
0
.tgz"
,
"integrity"
:
"sha512-
jS1IWN5gi1GTUmoZ9bUxez6mIrGCPE/huVHEcF8uq1Fu2nzxlH8J9Xc5GD/UNzlyarB9/7fcOyOpv+K//uCM0A
=="
,
"version"
:
"4.1.
1
"
,
"resolved"
:
"https://registry.npmjs.org/koishi/-/koishi-4.1.
1
.tgz"
,
"integrity"
:
"sha512-
bYUJJzImHNNtV+2tO8WNsuPCCfa84PzB3AKbZSqTPCDFWb/0JsqcpNhZZZB4Os/xkauxznVpPh3XVJafLcBcqg
=="
,
"dependencies"
:
{
"@koa/router"
:
"^10.1.1"
,
"@koishijs/core"
:
"^4.1.
0
"
,
"@koishijs/core"
:
"^4.1.
1
"
,
"@koishijs/utils"
:
"^5.0.0"
,
"@types/koa"
:
"*"
,
"@types/koa__router"
:
"*"
,
...
...
@@ -6463,9 +6463,9 @@
}
},
"node_modules/schemastery"
:
{
"version"
:
"2.
1.3
"
,
"resolved"
:
"https://registry.npmjs.org/schemastery/-/schemastery-2.
1.3
.tgz"
,
"integrity"
:
"sha512-
AH6dgucxUSkuK/LvIJtPor8/6KCEq5L9weD5JQJ6/HEDFqD4KbO7NqQsJmbW4TKubZ4FtPj7eXSEaz5nie+y+
A=="
"version"
:
"2.
2.0
"
,
"resolved"
:
"https://registry.npmjs.org/schemastery/-/schemastery-2.
2.0
.tgz"
,
"integrity"
:
"sha512-
Nn3RGNn0SBptNr8wRI4WteUj3OUrXm6zBm2mRQY81sIZHsKTbrPoBgu8TzjSSFJ/WlvHREZ6IOqiULEq2AIeG
A=="
},
"node_modules/semver"
:
{
"version"
:
"7.3.5"
,
...
...
@@ -8342,9 +8342,9 @@
}
},
"@koishijs/core"
:
{
"version"
:
"4.1.
0
"
,
"resolved"
:
"https://registry.npmjs.org/@koishijs/core/-/core-4.1.
0
.tgz"
,
"integrity"
:
"sha512-
f9SSEHxYt5OixXLhX0W9ME36JLQxdb8gwv8R5YOAd4y1IYchOX3qVfbnhRCd41SHUaKLhRWMBzwnl9R1dmqm4A
=="
,
"version"
:
"4.1.
1
"
,
"resolved"
:
"https://registry.npmjs.org/@koishijs/core/-/core-4.1.
1
.tgz"
,
"integrity"
:
"sha512-
UjlqQzT/xjpZPz7sNGdzzSFNUqCr9MgFfPBWZ9lcZ0qkpag9+j8aSW4BVH2q0ZTXoPrTArXTnesBSPpDN4k13g
=="
,
"requires"
:
{
"@koishijs/utils"
:
"^5.0.0"
,
"fastest-levenshtein"
:
"^1.0.12"
,
...
...
@@ -11618,12 +11618,12 @@
}
},
"koishi"
:
{
"version"
:
"4.1.
0
"
,
"resolved"
:
"https://registry.npmjs.org/koishi/-/koishi-4.1.
0
.tgz"
,
"integrity"
:
"sha512-
jS1IWN5gi1GTUmoZ9bUxez6mIrGCPE/huVHEcF8uq1Fu2nzxlH8J9Xc5GD/UNzlyarB9/7fcOyOpv+K//uCM0A
=="
,
"version"
:
"4.1.
1
"
,
"resolved"
:
"https://registry.npmjs.org/koishi/-/koishi-4.1.
1
.tgz"
,
"integrity"
:
"sha512-
bYUJJzImHNNtV+2tO8WNsuPCCfa84PzB3AKbZSqTPCDFWb/0JsqcpNhZZZB4Os/xkauxznVpPh3XVJafLcBcqg
=="
,
"requires"
:
{
"@koa/router"
:
"^10.1.1"
,
"@koishijs/core"
:
"^4.1.
0
"
,
"@koishijs/core"
:
"^4.1.
1
"
,
"@koishijs/utils"
:
"^5.0.0"
,
"@types/koa"
:
"*"
,
"@types/koa__router"
:
"*"
,
...
...
@@ -12470,9 +12470,9 @@
}
},
"schemastery"
:
{
"version"
:
"2.
1.3
"
,
"resolved"
:
"https://registry.npmjs.org/schemastery/-/schemastery-2.
1.3
.tgz"
,
"integrity"
:
"sha512-
AH6dgucxUSkuK/LvIJtPor8/6KCEq5L9weD5JQJ6/HEDFqD4KbO7NqQsJmbW4TKubZ4FtPj7eXSEaz5nie+y+
A=="
"version"
:
"2.
2.0
"
,
"resolved"
:
"https://registry.npmjs.org/schemastery/-/schemastery-2.
2.0
.tgz"
,
"integrity"
:
"sha512-
Nn3RGNn0SBptNr8wRI4WteUj3OUrXm6zBm2mRQY81sIZHsKTbrPoBgu8TzjSSFJ/WlvHREZ6IOqiULEq2AIeG
A=="
},
"semver"
:
{
"version"
:
"7.3.5"
,
...
...
package.json
View file @
d84f8313
...
...
@@ -55,7 +55,7 @@
"
eslint-plugin-prettier
"
:
"
^3.4.1
"
,
"
express
"
:
"
^4.17.1
"
,
"
jest
"
:
"
^27.4.4
"
,
"
koishi
"
:
"
^4.1.
0
"
,
"
koishi
"
:
"
^4.1.
1
"
,
"
prettier
"
:
"
^2.4.1
"
,
"
reflect-metadata
"
:
"
^0.1.13
"
,
"
rimraf
"
:
"
^3.0.2
"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment