优化
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: 关于开放平台
|
||||
---
|
||||
|
||||
开放平台是常见且传统的应用与应用之间进行交互的方式,对于一些简单的需求我们可以通过开放平台来实现应用之间的数据传递。
|
||||
|
||||
在 Tailchat 中。目前主要提供两种形式的开放平台应用能力: `OAuth` 与 `Bot`
|
||||
|
||||
## 功能介绍
|
||||
|
||||
### OAuth
|
||||
|
||||
`OAuth` 能够使外部应用能够通过`Tailchat`的账号登录,就像是 `Google`, `Github` 登录方式一样,可以方便用户打造基于 `Tailchat` 的统一用户平台
|
||||
|
||||
:::info
|
||||
与 `com.msgbyte.iam` 插件的区别: `iam`插件是提供外部账号登录`Tailchat`的方式,如使用`Github`账号登录`Tailchat`, 而开放平台的OAuth能力则是以`Tailchat`账号登录其他平台。
|
||||
:::
|
||||
|
||||
[了解更多](./oauth)
|
||||
|
||||
### Bot
|
||||
|
||||
`Bot` 赋予聊天机器人可交互的应用能力,这意味着 Tailchat 不仅仅可以被动接收来自外部的消息,也可以主动将内部聊天的请求转发到外部应用代为处理。
|
||||
|
||||
[了解更多](./bot)
|
||||
|
||||
## 使用前提
|
||||
|
||||
在使用开放平台的相关能力前,请确保安装了对应的插件,并确保管理员已经部署与开放了相关的开放平台的能力。
|
||||
|
||||
作为用户,你需要安装 `com.msgbyte.integration` 插件来将应用加入到自己的群组
|
||||
|
||||
作为开放平台应用的开发者,你需要额外安装 `com.msgbyte.openapi` 来展示开放平台应用相关所需要的界面
|
||||
@@ -0,0 +1,230 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: 机器人
|
||||
---
|
||||
|
||||
开放平台的机器人是可交互式的机器人解决方案
|
||||
|
||||
他的主要流程是:
|
||||
|
||||
- 创建openapp
|
||||
- 获取appid和appsecret
|
||||
- 进入bot页面,开启bot能力
|
||||
- 回调地址填入可以访问到的公网http服务地址
|
||||
- 回到群组页面,在群组详情集成功能中输入appid,找到刚刚创建的应用,加入到群组中
|
||||
- 在群组中@机器人并输入文本,此时tailchat会向回调地址所示的地址发送一个带消息内容的http请求
|
||||
- 在机器人服务中接受到tailchat发送的请求,并通过机器人给对应群组的对应面板发送响应
|
||||
|
||||
当然,在开始一切工作前请[先在 Tailchat 中创建](./create)
|
||||
|
||||
下面我们来实际操作一下机器人的开发流程:
|
||||
|
||||
## 使用SDK进行开发(Node.js)
|
||||
|
||||
Tailchat 提供了sdk作为快速开发的工具,`tailchat-client-sdk`, 你可以通过以下命令安装
|
||||
|
||||
```bash
|
||||
npm install tailchat-client-sdk
|
||||
```
|
||||
|
||||
以`koa`为例,我们先创建一个简单的`koa`服务如下:
|
||||
|
||||
创建node项目:
|
||||
|
||||
```bash
|
||||
mkdir tailchat-bot && cd tailchat-bot
|
||||
npm init -y
|
||||
npm install koa koa-router tailchat-client-sdk
|
||||
```
|
||||
|
||||
创建`server.js`文件:
|
||||
|
||||
```js
|
||||
const Koa = require('koa');
|
||||
const Router = require('koa-router');
|
||||
const app = new Koa();
|
||||
const router = new Router();
|
||||
|
||||
// 定义路由
|
||||
router.get('/', async (ctx) => {
|
||||
ctx.body = 'Hello, World!';
|
||||
});
|
||||
|
||||
router.post('/bot/callback', async (ctx) => {
|
||||
ctx.body = 'Bot Callback Page';
|
||||
});
|
||||
|
||||
// 注册路由中间件
|
||||
app.use(router.routes());
|
||||
app.use(router.allowedMethods());
|
||||
|
||||
// 启动服务
|
||||
app.listen(3000, () => {
|
||||
console.log('Server is running on http://localhost:3000');
|
||||
});
|
||||
```
|
||||
|
||||
在此时我们建立了两个基本的路由,`/`与`/bot/callback`, 并监听了`3000`端口, 注意`/bot/callback`监听的是**POST**请求
|
||||
|
||||
此时我们执行 `node server.js` 可以看到我们的应用会被启动。
|
||||
|
||||
现在我们要增加一些逻辑,比如我们想要实现一个复读机器人, 那么修改 `/bot/callback` 路由的实现如下:
|
||||
|
||||
```js
|
||||
import { TailchatHTTPClient, stripMentionTag } from 'tailchat-client-sdk';
|
||||
|
||||
const host = '<your tailchat instance backend host>';
|
||||
const appId = '<appId>';
|
||||
const appSecret = '<appSecret>';
|
||||
|
||||
const client = new TailchatHTTPClient(host, appId, appSecret)
|
||||
|
||||
// ...
|
||||
|
||||
router.post('/bot/callback', async (ctx) => {
|
||||
const type = ctx.body.type;
|
||||
|
||||
if (type === 'message') {
|
||||
const payload = ctx.body.payload;
|
||||
try {
|
||||
const message = await client.replyMessage({
|
||||
messageId: payload.messageId,
|
||||
author: payload.messageAuthor,
|
||||
content: payload.messageSnippet
|
||||
}, {
|
||||
groupId: payload.groupId,
|
||||
converseId: payload.converseId,
|
||||
content: `Your message: ${stripMentionTag(payload.messageSnippet)}`,
|
||||
})
|
||||
|
||||
console.log('send message success:', message)
|
||||
} catch (err) {
|
||||
console.log('send message failed:', err)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.body = 'Bot Callback Page';
|
||||
});
|
||||
```
|
||||
|
||||
请将 `host` `appId` 和 `appSecret` 分别填入在创建时获取到的 `appId` 和 `appSecret`,`host` 填入 `Tailchat` 服务端的地址, 官方 `nightly` 的地址是 `https://tailchat-nightly.moonrailgun.com`
|
||||
|
||||
至于回复的内容并不重要,只需要确保不要主动返回错误信息即可,Tailchat并不关心返回内容
|
||||
|
||||
**请注意如果你要把你的代码分享出去的话请保管好你的`appSecret`, 这等价于你的账号的密码**
|
||||
|
||||
逻辑非常简单,从请求中拿到消息的内容, 作者, id, 以及所在的群组id, 会话id。以回复的形式将内容发送出去
|
||||
|
||||
将该应用部署到线上即可看到效果。
|
||||
|
||||
:::info
|
||||
在测试前请确保你已经开启了机器人能力并填入了正确的回调地址
|
||||
:::
|
||||
|
||||
## 使用其他语言进行开发
|
||||
|
||||
既然是网络应用,那么当然不仅仅局限于`nodejs`, 下面是所需要用到的一些网络请求的格式,主要是以开放平台机器人身份向Tailchat服务端发送请求。
|
||||
|
||||
官方 `nightly` 的api地址是 `https://tailchat-nightly.moonrailgun.com` , 自部署的请替换成自己的后端地址
|
||||
|
||||
### 登录
|
||||
|
||||
在所有的请求之前都需要先登录获取jwt token以表明身份,需要发送以下内容:
|
||||
|
||||
```
|
||||
POST /api/openapi/bot/login
|
||||
|
||||
Header
|
||||
Content-Type: application/json
|
||||
|
||||
Body
|
||||
{
|
||||
appId: <your app id>,
|
||||
token: <md5(appId+appSecret)>,
|
||||
}
|
||||
|
||||
Response
|
||||
{
|
||||
data: {
|
||||
jwt: "..........",
|
||||
userId: ".........."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
其中请求体的`token`是一个固定值,需要拼接 `appId` 和 `appSecret` 后以`md5`算法进行加密。最后拿到 `jwt`, `jwt` 要在之后的所有请求中在请求头带上
|
||||
|
||||
```
|
||||
Header
|
||||
X-Token: <your-jwt>
|
||||
```
|
||||
|
||||
### 调用
|
||||
|
||||
机器人可以和普通的用户一样调用接口,如:
|
||||
|
||||
```
|
||||
POST /api/xxx
|
||||
|
||||
Header
|
||||
Content-Type: application/json
|
||||
X-Token: <your-jwt>
|
||||
|
||||
Body
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
你可以将机器人视为一个普通用户来看待,普通用户所能做的事情机器人都能做,普通用户需要受到的权限限制机器人也会受到。
|
||||
|
||||
区别在于普通用户是用可视化进行交互的,而机器人是通过api进行交互的。
|
||||
|
||||
#### 发送信息
|
||||
|
||||
```
|
||||
POST /api/chat/message/sendMessage
|
||||
|
||||
Header
|
||||
Content-Type: application/json
|
||||
X-Token: <your-jwt>
|
||||
|
||||
Body
|
||||
{
|
||||
"converseId": "",
|
||||
"groupId": "",
|
||||
"content": "",
|
||||
"plain": "",
|
||||
"meta": {},
|
||||
}
|
||||
```
|
||||
|
||||
#### 回复信息
|
||||
|
||||
```
|
||||
POST /api/chat/message/sendMessage
|
||||
|
||||
Header
|
||||
Content-Type: application/json
|
||||
X-Token: <your-jwt>
|
||||
|
||||
Body
|
||||
{
|
||||
"converseId": "<converId/panelId>",
|
||||
"groupId": "<groupId, optional in DM>",
|
||||
"content": "<your message content>",
|
||||
"plain": "<your plained message, optional>",
|
||||
"meta": {
|
||||
mentions: ["<replyMessageAuthorId>"],
|
||||
reply: {
|
||||
_id: "<replyMessageId>",
|
||||
author: "<replyMessageAuthor>",
|
||||
content: "<replyMessageContent>",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 其他文档
|
||||
|
||||
- [Tailchat x Laf: 十分钟开发一个对话机器人](/blog/tailchat-laf-robot)
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: 创建开放平台应用
|
||||
---
|
||||
|
||||
安装 `com.msgbyte.openapi` 插件后可以在左下角设置页面看到多出来一个开放API的功能
|
||||
|
||||

|
||||
|
||||
填入应用名称与应用描述即可
|
||||
|
||||

|
||||
|
||||
成功后你可以在你的应用列表中看到你的开放平台应用
|
||||
@@ -0,0 +1,94 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
title: OAuth 第三方登录
|
||||
---
|
||||
|
||||
`Tailchat` 开放平台支持 `OAuth` 登录协议, 你可以很方便的将 `Tailchat` 账号体系接入到你的系统中。正如我们常见的 `Github 登录`、`Google 登录`、`Apple 登录` 一样
|
||||
|
||||
而现在,你可以通过 `Tailchat` 对你的多个平台做统一的账号管理体系。
|
||||
|
||||
## 在 Tailchat 中新建开放平台应用
|
||||
|
||||
你需要创建一个开放平台应用并开启 **OAuth** 服务。
|
||||
|
||||
在**回调地址**处填入允许被重定向的地址。
|
||||
|
||||

|
||||
|
||||
## 创建独立 应用发起并接受回调
|
||||
|
||||
首先我们在正式开始之前要大概了解一下 **OAuth** 的基本流程
|
||||
|
||||

|
||||
|
||||
简单的来说,就是分为三步:
|
||||
|
||||
- 第一步:访问授权,要传client_id:客户端id,redirect_uri:重定向uri,response_type为code,scope是授权范围,默认填`openid profile`即可,state是其它自定义参数
|
||||
- 第二步:授权通过,会重定向到redirect_uri,code码会作为它的参数
|
||||
- 第三步:拿到code后可以换取 access token, 之后就可以通过token直接访问资源
|
||||
|
||||
你可以参考 [https://github.com/msgbyte/tailchat/blob/master/server/test/demo/openapi-client-simple/index.ts](https://github.com/msgbyte/tailchat/blob/master/server/test/demo/openapi-client-simple/index.ts) 来实现你自己的 OAuth 应用
|
||||
|
||||
### 主要流程
|
||||
|
||||
这里简单简述一下过程:
|
||||
|
||||
首先构建一个请求地址,形如:
|
||||
```
|
||||
<API>/open/auth?client_id=<clientId>&redirect_uri=<redirect_uri>&scope=openid profile&response_type=code&state=123456789
|
||||
```
|
||||
|
||||
其中:
|
||||
- `API` 是你的tailchat后端地址,如果是使用默认部署方案的话就是你的访问地址。
|
||||
- `clientId` 是你第一步申请到的开放平台的地址。
|
||||
- `redirect_uri` 为你的回调地址,你需要确保其已经被添加到允许回调地址的白名单中
|
||||
- `scope` 是申请授权范围,目前固定填入 `openid profile` 即可
|
||||
- `response_type` 是响应类型,固定填入 `code` 即可
|
||||
- `state` 其他的自定义参数,会随着重定向和`code`参数一起调用.
|
||||
|
||||
用户访问该地址后,会跳转到 Tailchat 平台进行登录授权,如果授权通过的话会重定向到 `redirect_uri` 规定的地址. 此时接收地址可以在query string 中获取到 `code` 和 `state`.
|
||||
|
||||
下一步我们需要通过发送 POST 请求使用 `code` 换取 `token`. 后续我们需要通过 `token` 来获取用户信息
|
||||
|
||||
```
|
||||
POST <API>/open/token
|
||||
{
|
||||
"client_id": clientId,
|
||||
"client_secret": clientSecret,
|
||||
"redirect_uri": redirect_uri,
|
||||
"code": code,
|
||||
"grant_type": 'authorization_code',
|
||||
}
|
||||
```
|
||||
|
||||
返回值:
|
||||
```
|
||||
{
|
||||
access_token,
|
||||
expires_in,
|
||||
id_token,
|
||||
scope,
|
||||
token_type
|
||||
}
|
||||
```
|
||||
|
||||
此时我们拿到了 `access_token`, 我们可以用来请求用户信息:
|
||||
|
||||
```
|
||||
POST <API>/open/me
|
||||
{
|
||||
"access_token": access_token,
|
||||
}
|
||||
```
|
||||
|
||||
返回值:
|
||||
```
|
||||
{
|
||||
sub,
|
||||
nickname,
|
||||
discriminator,
|
||||
avatar,
|
||||
}
|
||||
```
|
||||
|
||||
其中`sub`可以理解为用户的id,是用户的唯一标识
|
||||
@@ -0,0 +1,49 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: Websocket 机器人
|
||||
---
|
||||
|
||||
除了传统的HTTP回调机器人以外,我们还支持基于websocket长连接协议的机器人。
|
||||
|
||||
长连接机器人可以如正常用户一样监听所有的消息,并无需通过 `@` 来唤起。
|
||||
|
||||
当然,缺点在于在一些只支持http请求的平台如`serverless`等不支持`websocket`的平台不够便利。且目前只有`nodejs`版本的实现。
|
||||
|
||||
以下是一个操作示例:
|
||||
|
||||
```ts
|
||||
import { TailchatWsClient } from 'tailchat-client-sdk';
|
||||
|
||||
const HOST = process.env.HOST;
|
||||
const APPID = process.env.APPID;
|
||||
const APPSECRET = process.env.APPSECRET;
|
||||
|
||||
if (!HOST || !APPID || !APPSECRET) {
|
||||
console.log('require env: HOST, APPID, APPSECRET');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = new TailchatWsClient(HOST, APPID, APPSECRET);
|
||||
|
||||
client.connect().then(async () => {
|
||||
console.log('Login Success!');
|
||||
|
||||
client.onMessage((message) => {
|
||||
console.log('Receive message', message);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
其中 `HOST`, `APPID`, `APPSECRET` 分别表示服务器地址,开放平台的id与秘钥。
|
||||
|
||||
**注意请不要在公共平台上泄露你的秘钥,秘钥等价于密码**
|
||||
|
||||
该操作在连接到服务器后创建了一个事件监听,当接收到任何消息的时候会把message的内容打印出来。
|
||||
|
||||
类似的,如果我们需要监听消息的更新事件的话,则可以使用监听消息更新操作
|
||||
|
||||
```ts
|
||||
client.onMessageUpdate((message) => {
|
||||
console.log('Receive message', message);
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user