This commit is contained in:
2026-04-25 16:36:34 +08:00
commit db90e7579b
1876 changed files with 189777 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
---
sidebar_position: 4
title: 自定义内置插件
---
在 Tailchat 的插件中心中可以看到系统已经内置了一部分插件默认给用户安装,且这部分插件是不可被卸载的。而对于自部署的企业用户来说,让所有的成员都默认安装上企业或者预设好的其他插件尤为重要。
接下来我们将学习如何自定义内置插件列表
*因为插件的加载时机很早,因此在 Tailchat 的设计中会将内置插件列表编译到源码中以确保尽可能快的加载页面。因此你需要手动编译镜像*
首先需要下载源码:
```bash
git clone https://github.com/msgbyte/tailchat.git
```
修改内置插件列表:
```bash
cd tailchat
vim client/web/src/plugin/builtin.ts
```
将你的配置文件(一般可以在插件目录的`manifest.json`文件中找到)按照已有的插件列表格式添加到导出的变量`builtinPlugins` 数组中。
:::info
已有的插件列表可以在这里看到 [插件列表](/docs/plugin-list/fe)
:::
当编辑完成后保存确保当前目录在tailchat的根目录。此时你的目录下应该可以直接看到 `Dockerfile` 文件
执行命令编译自己的镜像
```bash
docker build -t tailchat .
```
其中 `.` 表示当前目录,`-t tailchat` 表示编译的标签是 `tailchat`, 这可以直接被 `docker-compose.yml` 文件读取
编译完成后按照正常操作启动即可 `docker compose up -d`
:::info
自己编译镜像建议配置在 **2C4G** 以上
:::

View File

@@ -0,0 +1,49 @@
---
sidebar_position: 3
title: 外部存储
---
## 背景
随着使用规模的推移,用户对 Tailchat 文件系统的存储成本会逐步上升,因此私有化部署的对象存储服务`minio`可能会有很高的磁盘存储成本。为了降低成本 Tailchat 提供了使用外部第三方对象存储服务的解决方案
## 前提条件
- 该外部存储服务需要支持 `aws s3` 存储协议
- `Tailchat` 版本在 `1.8.7+`
## 配置
你需要通过环境变量配置如下:
- `MINIO_URL`: s3 服务地址,`<hostname>:<port>`,例如:`example.com:443`,不需要协议部分如 `https://`
- `MINIO_SSL`: s3服务是否启用ssl验证对于某些提供商是必须的。默认为`false`
- `MINIO_USER`: s3服务用户名
- `MINIO_PASS`: s3服务密码
- `MINIO_BUCKET_NAME`: s3服务 bucket 名
- `MINIO_PATH_STYLE`: 路径模式,可选值: `VirtualHosted``Path`
- S3 协议有两种风格,`VirtualHosted` 用于 `<bucketname>.example.com``Path` 用于 `example.com/<bucketname>`
- `STATIC_URL`: 上传后的静态路径地址,默认走服务器中转,如果想要走外部存储直连的话需要改为外部可访问的地址
> 对于 `aliyunoss` 我们可以参考该文档获得内容相关帮助: https://www.alibabacloud.com/help/en/oss/developer-reference/use-amazon-s3-sdks-to-access-oss
### 示例
**R2**:
```bash
MINIO_URL=<account-id>.r2.cloudflarestorage.com:443
MINIO_PATH_STYLE=Path
```
## 数据迁移
如果你是从私有化部署的 `minio` 服务迁移到公有云上,那么你需要对旧的数据进行迁移。
迁移文件: `files/**`
你可以通过`docker volume inspect tailchat_storage` 获取到存储卷的相信内容,其中 `Mountpoint` 表示路径,把 `<Mountpoint>/tailchat/files` 目录打包上传到对应的
### 数据库迁移脚本(可选)
> 这不是一个必须的操作, 因为就算不迁移也会按照原来的路径去走服务器中转
TODO: 欢迎共建

View File

@@ -0,0 +1,56 @@
---
sidebar_position: 2
title: Github 集成
---
:::caution
该篇内容仍在调整中...
:::
![](/img/github-app/github-integration.excalidraw.png)
## 普通用户使用
### 在项目安装应用
地址: https://github.com/apps/tailchat
安装到项目仓库中。
### 在项目中进行配置
在根目录创建 `.tailchat/topic.json` 文件:
```json
{
"groupId": "<your-notify-group-id>",
"panelId": "<your-topic-panel-id>"
}
```
## 自部署配置
应用启动前需要在github中注册一个应用:
![](/img/github-app/github-new-app.png)
部署时需要配置以下环境变量:
- `APP_ID`: 来自github 应用设置
- `WEBHOOK_SECRET`: 来自github 应用设置
- `PRIVATE_KEY`: 来自github 应用设置
- `TAILCHAT_APP_ID`: Tailchat 开放平台的id
- `TAILCHAT_APP_SECRET`: Tailchat 开放平台的秘钥
- `TAILCHAT_API_URL`: Tailchat 后台地址
为获取 `TAILCHAT_APP_ID``TAILCHAT_APP_SECRET` 需要在 Tailchat 开放平台中创建一个开放平台应用
同时开启机器人权限,并设置消息回调地址: `https://<your_app_url>/message/webhook`
### 部署开放平台应用
> 源码: [https://github.com/msgbyte/tailchat/tree/master/apps/github-app](https://github.com/msgbyte/tailchat/tree/master/apps/github-app)
拉取源码后部署到可供访问的线上,提供两种方式:
- 独立应用: `npm run build` 后执行 `node lib/index.js`运行应用
- Vercel: 直接推送到Vercel即可

View File

@@ -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` 来展示开放平台应用相关所需要的界面

View File

@@ -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)

View File

@@ -0,0 +1,14 @@
---
sidebar_position: 2
title: 创建开放平台应用
---
安装 `com.msgbyte.openapi` 插件后可以在左下角设置页面看到多出来一个开放API的功能
![](/img/advanced-usage/openapp/1.png)
填入应用名称与应用描述即可
![](/img/advanced-usage/openapp/2.png)
成功后你可以在你的应用列表中看到你的开放平台应用

View File

@@ -0,0 +1,94 @@
---
sidebar_position: 5
title: OAuth 第三方登录
---
`Tailchat` 开放平台支持 `OAuth` 登录协议, 你可以很方便的将 `Tailchat` 账号体系接入到你的系统中。正如我们常见的 `Github 登录``Google 登录``Apple 登录` 一样
而现在,你可以通过 `Tailchat` 对你的多个平台做统一的账号管理体系。
## 在 Tailchat 中新建开放平台应用
你需要创建一个开放平台应用并开启 **OAuth** 服务。
在**回调地址**处填入允许被重定向的地址。
![](/img/advanced-usage/openapp/3.png)
## 创建独立 应用发起并接受回调
首先我们在正式开始之前要大概了解一下 **OAuth** 的基本流程
![](/img/advanced-usage/openapp/4.png)
简单的来说,就是分为三步:
- 第一步访问授权要传client_id:客户端idredirect_uri:重定向uriresponse_type为codescope是授权范围默认填`openid profile`即可state是其它自定义参数
- 第二步授权通过会重定向到redirect_uricode码会作为它的参数
- 第三步拿到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是用户的唯一标识

View File

@@ -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);
});
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,16 @@
---
sidebar_position: 4
title: 自动加入群组
---
`com.msgbyte.autojoinGroup`
只需要配置环境:`AUTOJOIN_GROUP_ID=xxxxx`并重新启动服务器
您应该从admin或web端手动创建群组。 然后就可以得到一个groupId。
在 Web端您可以从 url 获取groupId形如`/main/group/<groupId>/<panelId>`
> 用户注册后如果想加入多个群组,可以用英文逗号`,`分割
>
> 例如AUTOJOIN_GROUP_ID=xxxxx,xxxx

View File

@@ -0,0 +1,40 @@
---
sidebar_position: 3
title: iam - 第三方登录
---
`com.msgbyte.iam`
`IAM` 插件提供第三方登录功能
目前支持:
- github
## 配置方式
### Github
`Github` 中创建 OAuth 应用。获得 `Client ID``Client secrets`
配置`Github`应用的授权回调地址`Authorization callback URL``{API_URL}/api/plugin:com.msgbyte.iam/github/redirect`。注意,`API_URL` 为环境变量中的值,两者应当保持一致。
配置Tailchat环境变量:
- IAM_GITHUB_ID
- IAM_GITHUB_SECRET
分别为之前获取到的`Client ID``Client secrets`
> 你也可以通过环境变量重写请求地址,例如使用代理:
>
> - IAM_GITHUB_URI_AUTHORIZE=https://github.com/login/oauth/authorize
> - IAM_GITHUB_URI_ACCESS_TOKEN=https://github.com/login/oauth/access_token
> - IAM_GITHUB_URI_USERINFO=https://api.github.com/user
## 安全强化
为了token的安全不被恶意应用获取建议增加前端域名校验。
在环境变量中配置`IAM_FE_URL`即可,值为前端域名。如: `IAM_FE_URL=http://localhost:11011`
> 用于 `window.opener.postMessage(<data>, "IAM_FE_URL")`

View File

@@ -0,0 +1,35 @@
---
sidebar_position: 5
title: livekit - 视频会议
---
`com.msgbyte.livekit`
## 使用文档
本插件提供了 `Tailchat` 视频会议的功能,安装插件后即可创建语音频道。
安装后可以在创建面板页面看见语音频道的面板类型
![](/img/advanced-usage/plugins/livekit/1.png)
语音频道入口大概是这样的:
![](/img/advanced-usage/plugins/livekit/2.png)
你可以在加入前准备好多媒体的选项,并切换媒体设备。
当然,在加入后也可以随时切换设备。就像下面这样
![](/img/advanced-usage/plugins/livekit/3.png)
你可以自由的与朋友们视频通话、分享屏幕、以及聊天。
最后,请自由切换页面,这并不会让你退出频道,你可以随时点击左下角的图标快速回到活动的频道.
![](/img/advanced-usage/plugins/livekit/4.png)
## 部署文档
见教程 [livekit](../../meeting/livekit.md)

View File

@@ -0,0 +1,36 @@
---
sidebar_position: 2
title: wxpusher
---
`com.msgbyte.wxpusher`
## 使用文档
- 在插件中心找到`wxpusher`插件,安装
-`左下角...` -> `更多` -> `wxpusher`
- 使用微信扫码绑定账号
- 之后 **@你** 的消息都会自动在微信中推送
## 部署文档
### 在wxpusher平台注册账号
在应用设置中设置回调地址, 如下:
![](./assets/wxpusher.png)
`https://<your backend domain>/api/plugin:com.msgbyte.wxpusher/callback`
### 获取appToken
在 [https://wxpusher.zjiecode.com/admin/main/app/appToken](https://wxpusher.zjiecode.com/admin/main/app/appToken) 中获取 appToken
### 配置Tailchat环境变量
将上一步获取到的appToken写入环境变量中如:
```
WXPUSHER_APP_TOKEN=xxxxxxxxxxxxxx
```
启动后生效, 你可以访问 `https://<your backend domain>/api/plugin:com.msgbyte.wxpusher/available`来检查服务可用性

View File

@@ -0,0 +1,34 @@
---
sidebar_position: 1
title: 富文本语法
---
## 对于普通用户
Tailchat 内置了 `com.msgbyte.bbcode` 插件用于对富文本消息做支持(且是默认安装的)。
以下是目前 `bbcode` 插件支持的语法列表:
| 关键字 | 描述 | 用法示例 | 预览 |
| ------ | ----- | ------ | ----- |
| b | 文本加粗 | `[b]foo[/b]` | <b>foo</b> |
| i | 文本倾斜 | `[i]foo[/i]` | <i>foo</i> |
| u | 文本下划线 | `[u]foo[/u]` | <ins>foo</ins> |
| s | 文本删除线 | `[s]foo[/s]` | <del>foo</del> |
| url | 超链接 | <div style={{width: 400}}>`[url]https://tailchat.msgbyte.com[/url]` / `[url=https://tailchat.msgbyte.com]官网[/url]`</div> | <a>https://tailchat.msgbyte.com</a> / <a href="https://tailchat.msgbyte.com">官网</a> |
| img | 图片 | `[img]https://tailchat.msgbyte.com/img/logo.svg[/img]` | <div style={{width: 60}}><img src="https://tailchat.msgbyte.com/img/logo.svg" /></div> |
| at | 提及 | `[at=<hereisuserid>]moonrailgun[/at]` | - |
| emoji | 表情 | `[emoji]smile[/emoji]` | - |
| markdown / md | markdown语法支持 | `[markdown]## Heading[/markdown]` / `[md]## Heading[/md]` | - |
## 对于插件开发者
如果你的插件需要使用统一的富文本支持,请在你的渲染函数中这样实现:
```jsx
import { getMessageRender } from '@capital/common';
const Component = (text: string) => {
return <div>{getMessageRender(text)}</div>
}
```

View File

@@ -0,0 +1,12 @@
---
sidebar_position: 3
title: 系统架构
---
## 服务端架构
![](/img/architecture/backend.excalidraw.svg)
## 插件机制架构
![](/img/architecture/plugin.excalidraw.svg)

View File

@@ -0,0 +1,112 @@
---
sidebar_position: 1
title: 命令行工具测试方式
---
首先需要确保已经安装了 `tailchat-cli`, 版本在 `1.5.8` 以上, 安装方式见: [命令行工具 tailchat-cli](../cli/tailchat-cli.md)
你可以在 Tailchat 的 Help 指令看到benchmark支持的如下命令:
```
tailchat benchmark
Tailchat Benchmark Test
Commands:
tailchat benchmark message Stress testing through Tailchat network
requests (suitable for pure business
testing)
tailchat benchmark connections <url> Test Tailchat Connections
tailchat benchmark register <url> Create Tailchat temporary account and
output token
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
```
其中我们主要使用的是`connections`命令与`register`命令
## 批量注册测试用户
首先我们需要批量注册测试用户, 这里我们需要用到`register`命令
```
tailchat benchmark register <url>
Create Tailchat temporary account and output token
Options:
--version Show version number [boolean]
--file Account Token Path [string] [required] [default: "./accounts"]
--count Register Count [number] [required] [default: 100]
--invite Invite Code [string]
-h, --help Show help [boolean]
--url [required]
```
如我们需要在本地批量注册账号
```bash
tailchat benchmark register http://127.0.0.1:11000
```
该命令会在`http://127.0.0.1:11000`服务下注册100个临时用户。注意结尾不需要'/'。
命令执行完毕后,会将用于登录的 token 保存到本地文件,默认是`./accounts`文件。
我们可以用`--count`指定注册的数量, 以及用`--invite` 来让其在注册后自动加入某个测试群组
如:
```bash
tailchat benchmark register http://127.0.0.1:11000 --count 10000 --invite <invite-code>
```
> 注意: 为了保证服务质量,注册操作是以串行方式进行发送的,即前一个注册操作完成后后一个注册操作才会开始。因此如果设定数量过大的话可能会导致耗时很长。
其中`<invite-code>`需要用户自行创建群组并创建一个邀请链接。一个邀请链接的格式形如: `http://localhost:11011/invite/<invite-code>`
完成后我们就可以获得对应数量的测试用户加入群组。
## 用户批量登录
我们要测试服务器在允许多人在线情况下的表现,我们需要使用`connections`命令来登录并建立连接。
`connections`命令会自动读取上个操作批量注册后的token文件作为需要登录的用户
```
tailchat benchmark connections <url>
Test Tailchat Connections
Options:
--version Show version number [boolean]
--file Account Token Path
[string] [required] [default: "./accounts"]
--groupId Group Id which send Message [string]
--converseId Converse Id which send Message [string]
-h, --help Show help [boolean]
--url [required]
```
如我们要直接登录到本地的服务:
```bash
tailchat benchmark connections http://127.0.0.1:11000
```
此时我们可以通过服务端的资源检测工具查看当测试用户都上线后服务端的内存占用与cpu占用情况。
### 消息推送用时检测
为了测试Tailchat聊天服务器在实际会话中的表现我们可以检测一条消息从客户端发送给服务端并且服务端将消息广播到所有用户所需要的用时。
这里我们需要指定要发送消息的目标,如下
```bash
tailchat benchmark connections http://127.0.0.1:11000 --groupId <groupId> --converseId <converseId>
```
在群组会话中的地址栏格式形如: `http://localhost:11011/main/group/<groupId>/<converseId>`
当所有会话接受完毕后,会打印出期间的耗时

View File

@@ -0,0 +1,239 @@
---
sidebar_position: 2
title: 压测报告
---
## 集群压测
:::info
测试版本: v1.7.6
测试集群基本信息:
- mongo: **0.2**cpu **256**Mi内存 单实例
- redis: **0.1**cpu **64**Mi内存 单实例
- minio: **0.1**cpu **128**Mi内存 单实例
- tailchat: **0.2**cpu **512**Mi内存 3实例
> 测试服务为完整服务即加载了service和plugins的完整服务没有进行任何为数据好看而做的任何定向优化(可以通过控制减少加载的服务以及关闭部分不必要的能力来获得更好的性能)
>
> 其中, cpu型号为: `Intel(R) Xeon(R) CPU @ 2.20GHz`
>
> 服务器网络使用的是`新加坡 谷歌云`,测试机器是使用的 `电信 上海`. 实际有一定网络损耗. 本次压测由 sealos 提供集群服务.
:::
### 测试方式
测试方式由一个实际观察者 + 若干个由cli启动的虚拟用户构成。测试方法见: [cli](./cli.md)
主要命令如下:
```
tailchat benchmark register https://<xxxxxx>.cloud.sealos.io --invite <inviteCode>
tailchat benchmark connections https://<xxxxxx>.cloud.sealos.io
tailchat benchmark connections https://<xxxxxx>.cloud.sealos.io --groupId <groupId> --converseId <converseId> --messageNum 5
```
> 以下关于cpu/内存的描述都是多个实例的平均值
### 百人在线测试
#### 在线情况
仅登录一个实际用户的情况下,系统占用情况为:
- cpu: 0.90 %
- 内存: 176.3 Mi
登录 100 个在线用户以后,系统占用情况为:
- cpu: 14.80 % -> 8.89% -> 1.33%(因为实际观察者一次性获取了所有的100个用户在线信息)
- 内存: 179.37 Mi
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 100 clients has been create.
Start send message test: 1
Start message receive test, message: 0c55e168904f02a3
✔ All client received, usage: 420ms
Start send message test: 2
Start message receive test, message: 6f000fb91dc85fe1
✔ All client received, usage: 89ms
Start send message test: 3
Start message receive test, message: 79cce2beee015c5f
✔ All client received, usage: 89ms
Start send message test: 4
Start message receive test, message: 8df7c58fdadb30aa
✔ All client received, usage: 96ms
Start send message test: 5
Start message receive test, message: 97c782b36312022c
✔ All client received, usage: 98ms
```
### 500人在线测试
#### 在线情况
不登录任何用户的情况下,系统占用情况为:
- cpu: 0.92 %
- 内存: 208.5533 Mi
登录 500 个在线用户以后,系统占用情况为:
- cpu: 3.30%
- 内存: 241.1933 Mi
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 500 clients has been create.
Start send message test: 1
Start message receive test, message: ef39144e96ce3ab8
✔ All client received, usage: 497ms
Start send message test: 2
Start message receive test, message: 5a86b397aab8ff92
✔ All client received, usage: 406ms
Start send message test: 3
Start message receive test, message: 69066c6d4a4402b0
✔ All client received, usage: 403ms
Start send message test: 4
Start message receive test, message: 3b066befc54b4835
✔ All client received, usage: 424ms
Start send message test: 5
Start message receive test, message: 3a6ef9cc7e8e6eac
✔ All client received, usage: 752ms
```
### 千人在线测试
#### 在线情况
不登录任何用户的情况下,系统占用情况为:
- cpu: 0.88 %
- 内存: 202.978 Mi
> 当我建立800以上的连接的时候会触发大量的`transport close`错误无法建立连接
>
> 为了让能够同时承载1000人我选择进行水平扩容将实例数拓展成5个实例
登录 1000 个在线用户以后,系统占用情况为:
- cpu: 3.27%
- 内存: 210.876 Mi
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 1000 clients has been create.
Start send message test: 1
Start message receive test, message: e65050aa6d4237bb
✔ All client received, usage: 2194ms
Start send message test: 2
Start message receive test, message: a7b02d30e25f02d0
✔ All client received, usage: 954ms
Start send message test: 3
Start message receive test, message: 75aa655a94cb308f
✔ All client received, usage: 988ms
Start send message test: 4
Start message receive test, message: 106b8830443002d9
✔ All client received, usage: 733ms
Start send message test: 5
Start message receive test, message: 0593646f9c7da288
✔ All client received, usage: 738ms
```
## 单机压测
:::info
测试版本: v1.7.6
测试环境基本信息:
- NAS部署依赖(DS220plus): Intel Celeron J4025, 2GB DDR4
- mongo
- redis
- minio
- 家用机, cpu: i7-8700K, 32G内存
- tailchat
:::
### 2000人在线测试
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 2000 clients has been create.
Start send message test: 1
Start message receive test, message: 8f4edd63886d80eb
✔ All client received, usage: 244ms
Start send message test: 2
Start message receive test, message: 20e0bc3e2ea1365c
✔ All client received, usage: 246ms
Start send message test: 3
Start message receive test, message: 7bed6a2cb12238a5
✔ All client received, usage: 248ms
Start send message test: 4
Start message receive test, message: 6f49353efa2467fc
✔ All client received, usage: 245ms
Start send message test: 5
Start message receive test, message: 850bed7ed8fa860c
✔ All client received, usage: 248ms
```
### 5000人在线测试
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 5000 clients has been create.
Start send message test: 1
Start message receive test, message: 85e2624234b8c66a
✔ All client received, usage: 933ms
Start send message test: 2
Start message receive test, message: ae025dd881ef5ae7
✔ All client received, usage: 714ms
Start send message test: 3
Start message receive test, message: 55a6c359fe74c90f
✔ All client received, usage: 691ms
Start send message test: 4
Start message receive test, message: 9eaefcc761c77c8c
✔ All client received, usage: 644ms
Start send message test: 5
Start message receive test, message: 856a49a1528ad5e1
✔ All client received, usage: 787ms
```
### 万人在线测试
#### 消息发送情况
测试5次所有消息发送与接收情况
```
✔ 10000 clients has been create.
Start send message test: 1
Start message receive test, message: 06b6bf829b66cca9
✔ All client received, usage: 1219ms
Start send message test: 2
Start message receive test, message: 3a544d3c0e6d8a14
✔ All client received, usage: 1189ms
Start send message test: 3
Start message receive test, message: b1d0ea01481b6717
✔ All client received, usage: 1089ms
Start send message test: 4
Start message receive test, message: af3512e57ce2ad0e
✔ All client received, usage: 1142ms
Start send message test: 5
Start message receive test, message: d09db4b9a348b32a
✔ All client received, usage: 1232ms
```

View File

@@ -0,0 +1,4 @@
{
"label": "命令行终端",
"position": 40
}

View File

@@ -0,0 +1,33 @@
---
sidebar_position: 1
title: 命令行工具 tailchat-cli
---
## 安装
```bash
npm install -g tailchat-cli@latest # 安装与更新同一命令
```
或直接使用
```bash
npx tailchat-cli <command>
```
安装成功后输入`tailchat` 后返回如下
```bash
tailchat <command>
Commands:
tailchat create [template] 创建 Tailchat 项目代码
tailchat connect 连接到 Tailchat 节点网络
tailchat app Tailchat cli 版本(WIP)
tailchat bench 压力测试
tailchat declaration <source> Tailchat 插件类型声明
tailchat docker Tailchat 镜像管理
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
```

View File

@@ -0,0 +1,4 @@
{
"label": "项目贡献",
"position": 90
}

View File

@@ -0,0 +1,27 @@
---
sidebar_position: 99
title: 生态与社区
---
`Tailchat` 是一个非常开放的平台,欢迎来自所有人的以任何形式的贡献。在这里收录一些`Tailchat`相关的第三方资源
欢迎提交 `pr/issue` 来提交你对`Tailchat`的贡献,让我们能够以下列表中收录:
## 交流社区
<img width="360" src="/img/wechat.jpg" />
## 项目/代码
- [Tailchat-Assistant](https://git.povario.com/powermaker450/Tailchat-Assistant): Tailchat Assistant is your very own AI-powered chat bot, ready to implement into your guild!
## 视频
- [【好玩儿的Docker项目】激情畅聊十分钟搭建一个插件化易拓展的开源即时聊天IM应用——Tailchat](https://www.bilibili.com/video/BV1aG411u7M8/)
- [简单搭建插件化易拓展的开源即时聊天IM应用——Tailchat](https://www.bilibili.com/video/BV1UN4y117M8/)
## 文章
- [【好玩儿的Docker项目】激情畅聊十分钟搭建一个插件化易拓展的开源即时聊天IM应用——Tailchat](https://blog.laoda.de/archives/docker-compose-install-tailchat)
- [Tailchat 群晖部署记录](/blog/2023/03/27/deploy-in-synology)
- [微信公众号: 重磅推荐:一个开源的即时通讯应用 Tailchat(from GitHub黑板报)](https://mp.weixin.qq.com/s/uImzeb_EQdQcm9LGGwGYuw)

View File

@@ -0,0 +1,4 @@
{
"label": "开发文档",
"position": 2
}

View File

@@ -0,0 +1,73 @@
---
sidebar_position: 1
title: 身份组与权限
---
身份组是在群组管理中划分用户权限点的形式(RBAC)。
身份组是由一系列权限点的开关组合而成的而一个用户可能是由多个身份组组合而成的比如身份组A拥有A权限身份组B拥有B权限那么作为同时拥有身份组A和身份组B的用户C则拥有权限A和权限B。为了简化权限的设计权限点则是通过简单的`true/false`实现的
更多关于 `RBAC` 可以查看相关wiki: https://en.wikipedia.org/wiki/Role-based_access_control 在此不做赘述。
下面主要讲讲在 `Tailchat` 是如何增加/修改权限点的
## 内置权限
权限点需要同时在前端和后端均做一次声明,前端负责前端的显示,后端负责做兜底的权限校验。如果没有权限的话处理接口应当直接范围一个报错。
### 前端管理
前端的权限点列表维护在 `client/shared/utils/role-helper.ts` 中, 包含权限点的权限点位, 如:
```tsx
export const PERMISSION = {
/**
* 非插件的权限点都叫core
*/
core: {
message: 'core.message',
},
};
```
以及权限点的在管理页面中的显示:
```tsx
export const getPermissionList = (): PermissionItemType[] => [
{
key: PERMISSION.core.message,
title: t('发送消息'),
desc: t('允许成员在文字频道发送消息'),
default: true,
}
];
```
使用方式则是通过hooks获取维护在群组下的权限点:
```tsx
const [allowSendMessage] = useHasGroupPermission(groupId, [
PERMISSION.core.message,
]);
```
使用数组的方式便于一些业务逻辑需要拥有多个权限点。
### 后端
后端的权限声明则是在 `server/packages/sdk/src/services/lib/role.ts` 中维护,使用方式也非常简单。如下:
```ts
const [hasPermission] = await call(ctx).checkUserPermissions(
groupId,
userId,
[PERMISSION.core.message]
);
if (!hasPermission) {
throw new NoPermissionError(t('没有操作权限'));
}
```
## 插件权限
TODO

View File

@@ -0,0 +1,63 @@
---
sidebar_position: 1
title: 贡献指南
---
`Tailchat` 是一个非常开放的项目,欢迎来自各种不同背景、任何形式的贡献。其插件的形式意味着允许`Tailchat` 可以承载任何想法的实现。
我们期望 `Tailchat` 不仅仅是一个简单的聊天应用,更是一个连接不同工具、不同想法的空间。
Github 地址: https://github.com/msgbyte/tailchat
-----------
目前 `Tailchat` 所急需要贡献者角色:
### 前端插件开发者
- 熟悉 React 的使用
- 拥有一定的抽象化思维
- 有基本的审美能力
- 对开源项目抱有热情
### 后端插件开发者
- 熟悉 Nodejs 的使用
- 对微服务有基本的认知
- 对开源项目抱有热情
### electron 应用开发者
- 了解跨平台的开发
- 熟悉代码注入,能够实现 render 进程与 main 进行数据交互
- 对开源项目抱有热情
### React Native 应用开发者
- 熟悉React Native应用的开发
- 熟悉React Native Web的使用
- 对开源项目抱有热情
### 运营同学
- 了解基本的运营能力,有当过大群群主的经验
- 了解开源项目的宣传渠道与方式
- 沟通能力强
- 对开源项目抱有热情
### 大使
- 掌握母语和英语(如英语为母语则仅英语即可)
- 对开源社群有一定了解
- 参与Tailchat使用方式与最佳实践的开发
- 沟通能力强
- 对开源项目抱有热情
### 其他
更多的一切可能性...
:::info
联系方式: 发送邮件到`moonrailgun@gmail.com` 或 [加入TailchatNightly频道](https://nightly.paw.msgbyte.com/invite/8Jfm1dWb)
:::

View File

@@ -0,0 +1,4 @@
{
"label": "应用部署",
"position": 10
}

View File

@@ -0,0 +1,41 @@
---
sidebar_position: 9
title: 部署管理后台(可选)
---
:::info
管理后台的功能还在不断迭代中,目前正处于前期体验版
后续会不断丰富内部的内容
:::
`github`获取最新的管理后台配置:
```bash
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/admin.yml
```
在环境变量 `docker-compose.env` 中设置管理后台的账号和密码:
```ini
ADMIN_USER=tailchat
ADMIN_PASS=<这里写入独立的后台密码, 不要告知其他人>
```
然后使用[多文件方式](https://docs.docker.com/compose/extends/#understanding-multiple-compose-files)启动应用:
```bash
docker compose -f docker-compose.yml -f admin.yml up -d
```
*注意先后顺序,因为`admin.yml`依赖`docker-compose.yml`所以要放在后面*
此时访问后台地址后面追加`/admin/`即可访问:
```
https://tailchat.example.com/admin/
```
*注意不要忘记在最后有一个`/`*
<details>
<summary>关于弃用的旧版admin</summary>
旧版本 <strong>admin-old</strong> 将于v1.8.6版本被移除,如果你依旧期望使用旧版本,可以切换到之前的版本获取
</details>

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1,34 @@
---
sidebar_position: 11
title: 前端分离部署(CDN部署前端)(可选)
---
有可能会出现前后端分开部署的情况比如想要把前端代码单独放在对象存储中管理增加CDN支持。则需要单独编译前端代码。
后端代码依旧建议使用 `docker` 来部署
为了单独编译前端代码,你需要下载源码来手动编译
```bash
git clone https://github.com/msgbyte/tailchat.git
cd tailchat
# 你可以通过 git checkout v1.8.8 来切换不同的发行版本
pnpm install # 你需要使用 `pnpm` 来安装依赖,使用其他的包管理工具可能会出现问题. 另外你最好使用 pnpm@8 来进行安装因为pnpm@9有一些不兼容的改动
```
耐心等待依赖安装完毕
进入前端代码中,进行编译
```bash
cd client/web
SERVICE_URL=<your-api-url> pnpm build
```
确保 `SERVICE_URL` 的值是后端的地址,形如: `http://127.0.0.1:11000`
编译完毕后你可以在 `tailchat/client/web/dist` 目录下获得所有的前端文件。
> 另外如果出现刷新页面后报404. 需要配置类似 [静态网站托管时,把根目录下的 index.html 文件设置为默认首页] 这样的配置

View File

@@ -0,0 +1,86 @@
---
sidebar_position: 99
title: 开发环境
---
对于开发环境的搭建Tailchat 提供了非常简单快捷的方式:
## 使用Docker快速搭建依赖环境
**mongodb**
```bash
docker run -d --name mongo -p 27017:27017 mongo:4
```
**redis**
```bash
docker run -d --name redis -p 6379:6379 redis
```
**minio**
```bash
docker run -d \
-p 19000:9000 \
-p 19001:9001 \
--name minio \
-e "MINIO_ROOT_USER=tailchat" \
-e "MINIO_ROOT_PASSWORD=com.msgbyte.tailchat" \
minio/minio server /data --console-address ":9001"
```
### 示例
这是一个 ".env" 的最小示例,可让您在开发环境中运行 `tailchat`
```ini
PORT=11000
MONGO_URL=mongodb://127.0.0.1:27017/tailchat
REDIS_URL=redis://localhost:6379/
MINIO_URL=127.0.0.1:19000
MINIO_USER=tailchat
MINIO_PASS=com.msgbyte.tailchat
```
## Node Version
Tailchat 是使用 `nodejs` 进行开发的请自行安装nodejs, 这里是nodejs的官方网站: [https://nodejs.org/](https://nodejs.org/)
建议使用 `nodejs18.x` 因为目前还不支持 `nodejs20.x`(nodejs 20 有一些break change)
## 启动开发服务器
```bash
pnpm install
pnpm dev
```
可以编辑`server/.env`的配置为自己相关的上下文
该文件可以从 `server/.env.example` 开始
现在你可以在 `http://localhost:11011` 访问你的 Tailchat 服务了
## 项目目录说明
- `apps`: 非核心应用
- `cli`: Tailchat 的命令行程序
- `github-app`: Tailchat 的github集成机器人
- `oauth-demo`: Tailchat 开放平台第三方登录演示程序
- `widget`: 网页嵌入小部件
- `client`: 客户端
- `desktop`: 桌面端
- `mobile`: 移动端
- `packages`: 依赖包
- `shared`: 平台无关的通用代码
- `web`: 网页端
- `plugins`: 纯前端插件
- `src`: 源码
- `packages`
- `types`: 前后端通用类型
- `server`: 服务端
- `admin`: 后台管理
- `models`: 数据库模型
- `plugins`: 服务端插件
- `services`: 微服务
- `website`: 官网

View File

@@ -0,0 +1,90 @@
---
sidebar_position: 104
title: Docker Compose 部署服务端(Deprecated)
---
:::caution 弃用警告
该文档已弃用。建议访问最新版的部署文档以获得最新的支持, [点击此处跳转](./docker-compose.mdx)
我们保留本篇文档是为了希望安装 `1.x` 版本之前的用户准备的
:::
## 安装环境
### Docker / Docker Compose
首先需要确保有 `Docker / Docker Compose` 环境
安装方式如下:
- [Docker](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)
### node 环境
- 从[官网下载](https://nodejs.org/en/download/)
- 或者使用[nvm](https://github.com/nvm-sh/nvm)
#### 安装pnpm
`pnpm` 是一个`nodejs`的包管理工具, 是`npm`的替代品, 为了确保能有与开发者一样依赖环境强烈建议你使用pnpm作为后续的包管理工具
```bash
npm install -g pnpm
```
## Clone 项目
将项目从远程下载到本地:
```bash
mkdir msgbyte && cd msgbyte
git clone https://github.com/msgbyte/tailchat.git # clone 客户端
git clone https://github.com/msgbyte/tailchat-server.git # clone 服务端
```
## 编译项目
#### 前端项目
```bash
cd tailchat/web
pnpm install # 安装依赖
export SERVICE_URL=http://127.0.0.1:11000 # 配置服务端地址这里的127.0.0.1 可以替换为任何网页可以访问到的服务端地址
pnpm build # 构建项目
```
构建完毕后会生成一个`tailchat/web/dist`目录,将该目录托管到任意网页托管服务器即可(如使用`http-server`进行静态代理或者直接上传到`oss`)
> NOTICE: 因为webpack编译需要比较大的内存资源占用在服务器资源不足的场合建议使用本地编译完毕以后上传到服务端
#### 使用docker-compose构建服务端
> 在启动前需要检查代码环境变量
修改 `docker-compose.env` 文件的配置,以下内容推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
```bash
cd tailchat-server
docker-compose build
docker-compose up -d
```
*在`docker-compose.env`文件中提供了部分环境变量可供配置。*
`tailchat``docker-compose.yml`配置默认提供了如下配置:
- `mongodb`: 持久化数据库
- `redis`: KV数据库与消息中转服务
- `minio`: 分布式文件服务
其中持久化文件(数据库, 文件存储)通过 `docker volume` 统一管理:
```
docker volume ls | grep "tailchat-server"
```

View File

@@ -0,0 +1,184 @@
---
sidebar_position: 4
title: Docker Compose 部署
---
## 建议配置
建议最低配置 **1核2G**
> 如果只有 **1核1G**? 请参阅我的博客: [Linux 小资源服务器使用经验总结](http://moonrailgun.com/posts/6769ba51/) 通过交换内存来拓展内存空间
>
> 可供参考的内存用量:
> ![](/img/misc/memory-usage.png)
## 前置环境
### Docker / Docker Compose
首先需要确保有 `Docker / Docker Compose` 环境
安装方式可参考: [安装 Docker 环境](./install-docker.md)
## 拉取镜像
你可以通过从**公共镜像拉取已经编译好的镜像**或者**通过源码手动编译**
> 使用已经编译好的镜像可以无需花费足够的计算机资源进行编译,对小资源配置的服务器会十分友好。另外相对于源码编译,公共镜像的代码更加稳定。
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs groupId="build">
<TabItem value="cli" label="使用cli一键安装" default>
> 使用 `cli` 请确保在你的服务器上已经拥有了node环境(建议node版本 16+)
> 如果对node不了解可以使用`从公共镜像中手动安装`方式
使用 命令行工具 tailchat-cli 一键拉取/更新镜像:
```bash
npx tailchat-cli docker update
```
</TabItem>
<TabItem value="public-image" label="从公共镜像中手动安装" default>
使用Docker原生命令手动安装:
```bash
docker pull moonrailgun/tailchat # 从公共镜像库拉取 tailchat镜像
docker tag moonrailgun/tailchat tailchat # 将下载的镜像改名为tailchat(和源码编译保持一致,如果不改的话会走源码编译流程)
```
:::info
可以从 [Docker Hub](https://hub.docker.com/r/moonrailgun/tailchat/tags) 查看历史支持的镜像版本
:::
</TabItem>
<TabItem value="source-code" label="从源码中编译">
*本节内容适用于高级玩家用于获取最新的tailchat实现请确保你有足够的 docker, nodejs, git 的使用常识*
#### 编译环境 node 环境
- 从 [官网下载](https://nodejs.org/en/download/)
- 或者使用 [nvm](https://github.com/nvm-sh/nvm)
#### 安装pnpm
`pnpm` 是一个`nodejs`的包管理工具, 是`npm`的替代品, 为了确保能有与开发者一样依赖环境强烈建议你使用pnpm作为后续的包管理工具
```bash
npm install -g pnpm
```
#### Clone 项目
将项目从远程下载到本地:
```bash
mkdir msgbyte && cd msgbyte
git clone https://github.com/msgbyte/tailchat.git # 克隆项目到本地
```
#### 编译项目
```bash
cd tailchat && docker compose build
```
*编译对服务器配置有一定要求2核4G编译约10分钟供参考*
编译完毕后可以通过 `docker images` 查看编译完毕的镜像。
</TabItem>
</Tabs>
## 启动项目
<Tabs groupId="build">
<TabItem value="cli" label="使用cli一键安装" default>
```bash
npx tailchat-cli docker init
```
执行该命令会以交互式的方式向你询问一些配置相关的问题(如下图),填写完毕后即可自动生成配置文件
![](./assets/docker-init.png)
</TabItem>
<TabItem value="public-image" label="从公共镜像中手动安装">
> 启动之前需要下载配置文件以告知 `docker-compose` 要如何启动镜像
> 从仓库下载配置文件与配置环境变量:
> - [docker-compose.yml](https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.yml)
> - [docker-compose.env](https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.env)
```bash
mkdir tailchat && cd tailchat
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.yml
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker-compose.env
```
在启动之前需要修改一下配置
修改 `docker-compose.env` 文件的配置,以下字段推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问, 可以是域名也可以是ip **如果出现发送图片不能正常显示就是这个变量没有设置**
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
</TabItem>
<TabItem value="source-code" label="从源码中编译">
在启动之前需要修改一下配置
修改 `docker-compose.env` 文件的配置,以下字段推荐修改:
- `API_URL` 对外可访问的url地址用于文件服务访问, 可以是域名也可以是ip
- `SECRET` 服务端加密秘钥用于生成Token. 默认为 `tailchat`
</TabItem>
</Tabs>
完成配置后使用`docker-compose` 一键启动 `Tailchat` 应用:
```bash
# 确保配置文件(docker-compose.yml和docker-compose.env)在当前目录下
# 执行以下命令一键启动
docker compose up -d
```
访问: `http://<server ip>:11000` 即可打开tailchat
注意部分云服务可能需要手动开放防火墙端口。
*在`docker-compose.env`文件中提供了部分环境变量可供配置。*
`tailchat` 的`docker-compose.yml`配置默认提供了如下配置:
- `mongodb`: 持久化数据库
- `redis`: KV数据库与消息中转服务
- `minio`: 分布式文件服务
其中持久化文件(数据库, 文件存储)通过 `docker volume` 统一管理:
```
docker volume ls | grep "tailchat-server"
```
:::info
完整的环境变量可以查询 [环境变量](./environment.md)
:::
## 更多部署相关文档
- [搭建 https 网关(可选)](./https-gateway.md)
- [部署管理后台(可选)](./admin.md)

View File

@@ -0,0 +1,79 @@
---
sidebar_position: 7
title: 环境变量
---
## 环境变量
| 变量名 | 默认值 | 描述 |
| ----- | ------ | --- |
| PORT | 11000 | 网关服务端口号 |
| SECRET | tailchat | 加密秘钥, 用于JWT |
| STATIC_HOST | "{BACKEND}" | 对外可访问的静态服务主机,用于文件服务访问, 默认为动态根据前端请求推断出的服务端地址如果期望存储在第三方OSS中需要进行修改 |
| STATIC_URL | "{BACKEND}/static/" | 对外可访问的静态服务完整地址前缀,用于文件服务访问, 默认为动态根据前端请求推断出的服务端地址如果期望存储在第三方OSS中需要进行修改, 如果设置了本变量则上面的 `STATIC_HOST` 值无效 |
| API_URL | http://127.0.0.1:11000 | 对外可访问的url地址用于开放平台的issuer签发或者作为文件服务的fallback |
| MONGO_URL | - | 数据库服务地址 |
| REDIS_URL | - | Redis服务地址 |
| MINIO_URL | - | 文件服务地址(minio) |
| MINIO_USER | - | 文件服务用户名 |
| MINIO_PASS | - | 文件服务密码 |
| MINIO_BUCKET_NAME | tailchat | 文件服务存储桶名 |
| MINIO_PATH_STYLE | "Path" | 是否使用路径形式的s3通信格式, `Path``Path Style`, `VirtualHosted``Virtual hosted style` |
| MINIO_SSL | false | 是否使用加密连接文件存储服务, 如果为 "1" 或者 "true" 则使用SSL协议 |
| SMTP_SENDER | - | 邮件服务发件人(示例: `"Tailchat" example@163.com`) |
| SMTP_URI | - | 邮件服务连接地址(示例: `smtp://username:password@smtp.example.com/?pool=true`) |
| FILE_LIMIT | 1048576 | 文件/图片上传的大小限制默认为1m请输入数字单位: 字节) |
| EMAIL_VERIFY | - | 是否开启邮箱校验, 如果为 "1" 或者 "true" 则在注册时增加邮箱校验控制 |
| REQUEST_TIMEOUT | 10000 | 请求超时毫秒数,请求超过该时间没有完成会抛出 `RequestTimeout` 错误。 如果需要禁用请求超时限制传0 |
| TIANJI_SCRIPT_URL | - | Tianji 脚本 URL如需监控 Tailchat 用户使用情况,可在天际网站代码模式中获取 (例如:`https://tianji.example.com/tracker.js`) |
| TIANJI_WEBSITE_ID | - | Tianji 网站 id |
| DISABLE_MESSAGEPACK | - | 是否禁用 openapi 的 sockio 使用 messagepack 作为 [解析器](https://socket.io/zh-CN/docs/v4/custom-parser/), 如果为 "1" 或者 "true" 则禁用该功能 |
| DISABLE_LOGGER | - | 是否禁用日志输出, 如果为 "1" 或者 "true" 则在运行中关闭日志 |
| DISABLE_TRACING | - | 是否禁用Tracing功能(开启可以节约大量日志), 如果为 "1" 或者 "true" 则在运行中关闭日志 |
| DISABLE_USER_REGISTER | - | 是否关闭用户注册功能, 如果为 "1" 或者 "true" 则关闭该功能 |
| DISABLE_GUEST_LOGIN | - | 是否关闭用户游客登录功能, 如果为 "1" 或者 "true" 则关闭该功能 |
| DISABLE_CREATE_GROUP | - | 是否关闭用户创建群组功能, 如果为 "1" 或者 "true" 则关闭该功能 |
| DISABLE_PLUGIN_STORE | - | 是否隐藏用户插件中心功能, 如果为 "1" 或者 "true" 则关闭该功能 |
| DISABLE_ADD_FRIEND | - | 是否隐藏用户添加好友功能, 如果为 "1" 或者 "true" 则关闭该功能 |
| DISABLE_TELEMETRY | - | 是否关闭遥测报告功能, 遥测是完全匿名的,如果为 "1" 或者 "true" 则关闭该功能 |
> 部分环境变量示例可见: https://github.com/msgbyte/tailchat/blob/master/server/.env.example
### 使用文件进行配置环境变量
- 如果是本地方式启动,请复制 `.env.example``.env` 然后进行编辑
```bash
mv .env.example .env
vi .env
```
- 如果是 `docker-compose` 启动,可以直接编辑 `docker-compose.env`, 改动后直接使用 `docker compose up -d` 即可生效
### 关于带空格的环境变量的使用
如果你的环境变量值包含空格,为了让系统能够识别这是一个完整的字符串而不是把空格视为分隔符。你需要在外部包一层双引号。
如下:
```bash
SMTP_SENDER="\"Tailchat\" example@163.com" # 如果有重复的双引号需要使用转义符对其进行转义
```
-----------
:::caution
部分环境变量修改可能需要清理缓存后才能生效
:::
### 如何清理缓存
一些环境变量的改动可能涉及到缓存的更新,如 `FILE_LIMIT`, 因为配置信息是需要发送到客户端的。
因此可能会出现修改环境变量后在客户端上的表现还是和以前一样的情况。这时候你需要清空旧的缓存来让更新生效。
以下有几种方案可以清理缓存:
- `docker compose down` 后执行 `docker compose up -d`. 这是因为 `redis` 服务的数据并没有被持久化,把服务关了再重启相当于一个全新的环境
- 手动进入 `redis` 服务清理名称包含 `config.client` 的缓存项,这里面包含了返回给客户端的配置项
- 进入 `admin` 管理后台的缓存管理页面。点击`清理配置缓存`按钮

View File

@@ -0,0 +1,45 @@
---
sidebar_position: 8
title: 搭建 https 网关(可选)
---
`Tailchat` 中,有一些服务是强依赖 `https` 的,比如音视频通话、嵌入外部的 `https` 媒体资源与网页等。
同时为了用户的安全性,我们非常建议将 `Tailchat` 对外以 `https` 服务的形式提供。
![](/img/architecture/https-gateway.excalidraw.svg)
如果你没有相关的经验,且在同一台机器上只部署了 `Tailchat` 服务(没有占用 **80**/**443** 端口),那么我们推荐从 `Tailchat` 自带的 `swag` 配置开始。
:::info
你可以在 [Github](https://github.com/msgbyte/tailchat/tree/master/docker) 看到原始的配置内容
:::
通过以下命令直接拉取所需要的配置文件
```bash
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/swag.yml
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/swag.env.example -O swag.env
mkdir config
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/config/nginx.conf -O ./config/nginx.conf
```
完成后应该会在在当前目录看到以下三个文件:
- `swag.yml`
- `swag.env`
- `config/nginx.conf`
修改`swag.env`的内容,将 `URL` 的值改为域名, 如: `URL=tailchat.example.com`
:::info
`https`协议是依赖域名做证书校验的,因此需要提前分配一个域名指向目标服务器
:::
域名的地址需要在购买域名的管理后台创建一条A指向记录。
在分配好域名后我们就可以启动服务了。
```bash
docker compose -f ./swag.yml up -d
```
如果一切顺利的话,此时`swag`服务已经自动为你申请了一个证书并启动了反向代理服务,此时在浏览器访问 `https://tailchat.example.com` 的话可以看到熟悉的界面已经出现了。

View File

@@ -0,0 +1,79 @@
---
sidebar_position: 2
title: 安装docker环境
---
> 因为 `Tailchat` 的环境对于初学者来说有一些些复杂,因此提供了 `docker` 为主的一键环境搭建配置。但是对于`docker`不熟的同学来说可能`docker`本身也是一种复杂度。
> 因此为了方便大家可以快速搭建 `Tailchat`,提供了本文作为引导。对于 `docker` 有一定了解的同学可以跳过本篇
> 本文以 `linux centos` 为例,目标是方便大家直接在服务器上部署。对于想要在其他系统(`windows`, `mac`) 使用的同学可以参考官方文档进行`docker`的安装
## 一键安装 docker
官方维护的一键安装 `Docker` 脚本, 适合不喜欢研究细节的同学
在服务器终端按照以下操作依次执行即可
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
如果安装成功的话就可以跳过后续内容了。
## 手动安装docker与docker compose
官方文档: [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)
```bash
# 如果之前有安装过docker可以执行以下命令删除旧的
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
```
```bash
sudo yum install -y yum-utils # yum-utils 提供了 yum-config-manager 命令
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
```
<!-- 安装docker 与 docker-compose 插件 -->
```bash
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
*PS: `docker-compose-plugin`提供了`docker compose`命令,用法同`docker-compose`*
> 如果`docker ps`显示守护进程没有启动(Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?)的话可以执行以下命令启动: `sudo systemctl start docker`
## 单独安装 docker-compose
如果购买的服务器已经预装了docker, 想要单独安装docker-compose的话可以看本节内容:
官方文档: [https://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/)
```bash
curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose # 下载二进制文件
sudo chmod +x /usr/local/bin/docker-compose # 给予执行权限
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose # 软链接到path, 可以直接调用
docker-compose --version # 该行命令返回版本号则成功安装
```
## NOTICE
因为历史原因,`docker compose` 拥有`docker`插件版本与 `docker compose` 独立版本。一般意义上可以认为 `docker compose xxx``docker-compose xxx` 是等价的
## 参考文档
- [Docker](https://docs.docker.com/engine/install/)
- [Docker Compose](https://docs.docker.com/compose/install/)

View File

@@ -0,0 +1,155 @@
---
sidebar_position: 12
title: 移动端自编译(可选)
---
`Tailchat` 移动端的源码位于 `client/mobile`. 技术栈为 `react-native`
你可以直接在官网中下载已经编译好的通用版本: [https://tailchat.msgbyte.com/downloads](https://tailchat.msgbyte.com/downloads),或者自行通过源码编译
本节内容主要就是讲解如何对 `Tailchat` 的移动端进行编译。
## 准备开发环境
你可以在 [https://reactnative.dev/docs/environment-setup](https://reactnative.dev/docs/environment-setup) 看到完整的开发环境准备操作,这里就不再赘述。
### 安装依赖
```bash
cd client/mobile
yarn
```
### 环境检查
```bash
yarn doctor
```
## 准备环境变量
```bash
cp .env.example .env
```
`.env` 文件中我们来配置所需的环境变量用于编译
```ini
TAILCHAT_UPLOAD_STORE_FILE=
TAILCHAT_UPLOAD_STORE_PASSWORD=
TAILCHAT_UPLOAD_KEY_ALIAS=
TAILCHAT_UPLOAD_KEY_PASSWORD=
GETUI_APPID=
GETUI_APPKEY=
GETUI_APPSECRET=
GETUI_HUAWEI_APP_ID=
```
## 证书签名
如果仅用于测试则可以跳过本节内容Tailchat 会为你使用公开测试证书进行签名
### Android
如果需要使用你自己的证书进行签名,你需要填入以下内容:
```ini
TAILCHAT_UPLOAD_STORE_FILE=
TAILCHAT_UPLOAD_STORE_PASSWORD=
TAILCHAT_UPLOAD_KEY_ALIAS=
TAILCHAT_UPLOAD_KEY_PASSWORD=
```
需要依次填入: 证书文件名、密码、别名、别名密码
证书文件需要放在`client/mobile/android/app`目录下,一般是 `*.keystore` 文件
> 至于具体如何生成,你可以使用 `Android Studio` 或者 `keytool` 工具来生成,这个有很多公开资料就不在此赘述了
### iOS
TODO
## 推送
`Tailchat` 通过集成个推作为中转来实现安卓多厂商的消息推送
你可以在 `getui` 的应用配置中获得所有所需要的配置
其中 `GETUI_APPID`, `GETUI_APPKEY`, `GETUI_APPSECRET` 依次填入
在服务端需要对应配置 `GETUI_APPID`, `GETUI_APPKEY`, `GETUI_MASTERSECRET` 来使自部署的推送服务能正确发送推送
![](/img/misc/getui.png)
### 厂商推送
厂商推送可以按需打开或者关闭
需要修改源码如下:
- `client/mobile/android/app/build.gradle``manifestPlaceholders` 部分 和 `dependencies` 部分
- `.env` 环境变量配置
## 编译
### 安卓
```bash
cd android
./gradlew assembleRelease
```
### iOS
iOS 编译需要通过 `xcode` 进行操作
> 因为缺少设备无法截图,请按照网络上公开资料进行操作即可
### 常见问题
如果出现以下类型的报错:
```
error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup.
Error: Command failed: gradlew.bat app:installDebug -PreactNativeDevServerPort=8081
FAILURE: Build failed with an exception.
* What went wrong:
Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.
> Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'.
> Could not create task ':app:generateDebugLintModel'.
> java.lang.NullPointerException (no error message)
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 27s
```
可能是因为你的环境变量有缺失, 你可以保留值为空,但该条目必须存在
如:
```ini
GETUI_APPID=xxxxxxxxxxxx
GETUI_APPKEY=yyyyyyyyy
GETUI_APPSECRET=zzzzzzzzzz
GETUI_HUAWEI_APP_ID=
```
而不是
```ini
GETUI_APPID=xxxxxxxxxxxx
GETUI_APPKEY=yyyyyyyyy
GETUI_APPSECRET=zzzzzzzzzz
```
#### 我能自己编译后发布到应用商店么
可以,但是请修改应用的名称、包名、图标等信息防止与官方应用冲突

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,40 @@
---
sidebar_position: 3
title: 使用宝塔安装
---
:::info
Tailchat 已上架宝塔应用商店你可以在应用商店中一键安装Tailchat
宝塔服务器面板,一键全能部署及管理: [https://www.bt.cn](https://www.bt.cn/u/P0shD8)
:::
## 安装宝塔
如果您已经有宝塔服务器,直接登录宝塔面板,跳过本节内容即可。
[![](./assets/bt-logo.jpg)](https://www.bt.cn/u/P0shD8)
点击以上链接跳转到宝塔官网,查看如何在你的服务器安装宝塔
## 在应用商店安装
登录到宝塔面板,在侧边栏点击 `docker` 菜单
![](./assets/bt1.png)
在应用商店中搜索 Tailchat点击安装按钮
![](./assets/bt2.png)
如果使用的是ip请勾选`允许外部访问`。端口默认为11000
![](./assets/bt3.png)
点击确定,需要等待一段时间,等待时间主要取决于服务器网络
![](./assets/bt4.png)
等待一段时间后,显示完成后在浏览器打开 `http://<your-ip>:11000`
![](./assets/bt5.png)

View File

@@ -0,0 +1,4 @@
{
"label": "Kubernetes",
"position": 2
}

View File

@@ -0,0 +1,176 @@
---
sidebar_position: 2
title: 在 Sealos 上部署Tailchat
---
`Sealos` 是一款开源的 Kubernetes 部署系统。通过 `Sealos` 我们可以快捷的创建一个按需付费的应用集群。
## 首先进入 Sealos 并打开「应用管理」
![](/img/kubernetes/sealos/1.png)
## 新建应用
![](/img/kubernetes/sealos/2.png)
### 创建依赖
`tailchat` 作为企业级的应用,最小依赖: `mongodb`, `redis`, `minio`.
接下来让我们来一一创建。
#### mongodb
为了方便起见我们固定一个实例,并且为数据库绑定本地存储。
使用的镜像是 `mongo:4`
需要注意的是因为我没有给数据库设置密码,因此不要对外网提供网络服务。容器暴露端口填数据库默认服务端口 `27017` 即可
内容如下:
![](/img/kubernetes/sealos/3.png)
点击部署应用提交部署
耐心等待一会,就可以看到应用已经启动起来了
![](/img/kubernetes/sealos/4.png)
> 需要注意的是初始分配的64m对于mongodb来说实在太小了所以通过变更应用改为了128m。可以随时分配资源大小这也是sealos/k8s很方便的一点
#### minio
接下来我们创建minio, minio是一个开源的对象存储服务。我们同样可以通过`sealos`的点点点来快速创建
使用的镜像是: `minio/minio`
需要注意的是我们要进行一些调整:
- 暴露端口: 9000
- 运行命令改为: `minio`
- 命令参数改为: `server /data`
- 设置环境变量:
- MINIO_ROOT_USER: tailchat
- MINIO_ROOT_PASSWORD: com.msgbyte.tailchat
- 本地存储: `/data`
最终结果如下:
![](/img/kubernetes/sealos/5.png)
点击部署按钮同样看到服务已经正常启动起来了。
#### redis
最后我们需要部署redis作为内容缓存与信息转发。
使用镜像: `redis:alpine`
暴露端口: `6379`
最终结果如下:
![](/img/kubernetes/sealos/6.png)
### 创建 Tailchat 本体
此时Tailchat所需要的依赖均已部署完毕如下:
![](/img/kubernetes/sealos/7.png)
现在我们来部署 `Tailchat` 本体。
`Tailchat` 的本体会相对复杂一点,不过因为`sealos`纯UI操作也不会太过复杂。
- 使用镜像: `moonrailgun/tailchat`
- 暴露端口: `11000`(记得要打开外网访问)
- 配置环境变量如下:
```
SERVICEDIR=services,plugins
TRANSPORTER=redis://redis:6379
REDIS_URL=redis://redis:6379
MONGO_URL=mongodb://mongo/tailchat
MINIO_URL=minio:9000
MINIO_USER=tailchat
MINIO_PASS=com.msgbyte.tailchat
```
最终效果如下:
![](/img/kubernetes/sealos/8.png)
耐心等待一段时间后可以看到`Tailchat` 服务已经启动起来了
![](/img/kubernetes/sealos/9.png)
## 预览服务
首先我们可以先检查一下`Tailchat`服务的可用性,可以通过外网地址提供的服务后面加上 `/health` 来检查服务可用性, 如: `https://<xxxxxxxxxx>.cloud.sealos.io/health`
当启动完毕后Tailchat服务会返回如下内容:
![](/img/kubernetes/sealos/10.png)
这段json字符串中包含了使用的镜像版本节点名称系统占用微服务加载情况。
这里我们可以看到我的常见的服务, 如`user`/`chat.message`以及一些带有插件前缀的服务如`plugin.registry`都已经正常启动起来了,说明我们的服务端是正常运行的。
现在我们可以直接访问我们的外网地址,可以看到经过短暂的加载后,页面正常打开自动跳转到了登录界面。
![](/img/kubernetes/sealos/11.png)
随便注册一个账号可以看到我们可以正常进入Tailchat的主界面, 如下图:
![](/img/kubernetes/sealos/12.png)
至此我们的服务已经成功在 sealos 中落地了。
## 扩容服务
当然,作为一个分布式架构的系统,`Tailchat` 天然是支持水平扩容的。而在 `sealos` 想要实现扩容也非常简单, 只需要通过变更操作修改实例数即可:
![](/img/kubernetes/sealos/13.png)
![](/img/kubernetes/sealos/14.png)
![](/img/kubernetes/sealos/15.png)
此时当我们访问 `https://<xxxxxxxxxx>.cloud.sealos.io/health` 可以看到我们可以访问到不同的节点
![](/img/kubernetes/sealos/16.png)
## 添加 Tailchat 入口到桌面
打开 Terminal, 输入`vim app.yml`创建并编辑一个配置文件
输入以下内容注意url要换成自己部署的网址
```yml
apiVersion: app.sealos.io/v1
kind: App
metadata:
name: tailchat-app-entry
spec:
name: Tailchat
icon:
type: iframe
data:
url: <Your url>
desc:
icon: https://tailchat.msgbyte.com/img/logo.svg
menuData:
nameColor: text-black
helpDropDown:
helpDocs:
displayType: normal
```
按`esc`退出编辑模式, 按`:wq`保存并退出vim
输入`kubectl apply -f app.yml`启动配置。
完毕后刷新页面,此时我们可以看到我们的入口就出现在`sealos`的桌面上了
![](/img/kubernetes/sealos/17.png)

View File

@@ -0,0 +1,116 @@
---
sidebar_position: 1
title: 简单部署
---
## 简介
Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它提供了一种容器编排的方法,可以自动化容器的部署、调度、负载均衡和故障恢复等任务,使得容器化应用程序可以在分布式系统中高效地运行。
Kubernetes 的优点包括:
- 自动化Kubernetes 可以自动化容器的部署、调度、负载均衡和故障恢复等任务,减少了人工干预的工作量。
- 可扩展性Kubernetes 可以在大规模集群中管理数千个容器化应用程序,具有良好的水平扩展性和垂直扩展性。
- 灵活性Kubernetes 支持多种容器运行时和多种云平台,可以在不同的环境中部署和管理应用程序。
- 可靠性Kubernetes 提供了强大的故障恢复机制和自我修复能力,可以确保应用程序的高可用性和可靠性。
- 社区支持Kubernetes 是一个活跃的开源项目,有庞大的社区支持和生态系统,可以快速获取更新和支持。
## 快速入门
如果您想要在 Kubernetes 上部署 Tailchat 项目,那么您可以在项目目录中的 `docker/simple/k8s` 子目录中找到已经准备好的简单 Tailchat 部署配置。这些配置文件包括了用于运行 Tailchat 的 Kubernetes 资源定义,例如 StatefulSet、Service 和 依赖的数据库、持久化存储 等等。这些资源定义可以让您快速地在 Kubernetes 上部署一个简单的 Tailchat 项目,而无需手动创建和配置这些资源。
:::info
需要注意的是,本教程部署的 Tailchat 不包含完整的 Tailchat 生态如**开放平台**与**Admin后台管理平台**
:::
### 环境依赖
为了开始本章的内容,我们假设你已经准备好了一个可用的 kubernetes 环境,关于如何搭建 k8s 环境本节不进行赘述。
### 开始
首先我们需要clone项目仓库:
```bash
git clone git@github.com:msgbyte/tailchat.git
```
将工作目录切到配置文件目录
```bash
cd docker/simple/k8s
```
此时我们可以看到有许多已经准备好了的配置文件,我们可以通过一条命令直接启动:
```bash
kubectl apply -f namespace.yml -f pv.yml -f mongo.yml -f minio.yml -f redis.yml -f tailchat.yml
```
这条命令会依次执行创建`namespace`、创建`pv``pvc`、创建`mongodb``minio``redis`等必须的第三方中间件,最后启动一个多实例的 `tailchat` 服务。
你可以通过以下命令检测各个服务的状态:
```bash
kubectl get svc -n tailchat
```
### 路由与负载均衡。
当所有的服务都就绪后我们的Tailchat服务目前已经在集群中运行起来了但是此时我们还无法访问因为还没有暴露在外部。
对于本地测试,我们可以用`port forward`功能将一个pod的端口映射到本地。而在生产环境我们则需要构建路由转发。
`traefik` 为例:
> Traefik 是一款开源的反向代理和负载均衡器专门用于处理容器化应用程序和微服务架构中的流量路由和负载均衡。Traefik 支持多种后端服务,包括 Docker、Kubernetes、Mesos、Swarm、Consul、Etcd 等等。它可以自动地发现和配置后端服务,并根据规则将流量路由到相应的服务实例。
#### 安装helm, 并增加仓库地址
`helm` 的安装不做赘述。我们执行以下命令将`traefik`添加到仓库列表
```bash
helm repo add traefik https://helm.traefik.io/traefik
```
#### 在 tailchat 命名空间中安装traefik
```bash
helm install traefik traefik/traefik -n tailchat
```
#### 启动 ingress 资源声明
```bash
kubectl apply -f ingress.yml
```
如果一切正常,则通过以下命令可以看到如下输出
```bash
kubectl get services -n tailchat
```
![](/img/kubernetes/traefik-svc.png)
#### 设置DNS服务
你可以在上述的`ingress.yml`中修改域名地址配置,默认是 `http://tailchat.internal.com/`
如果不期望修改或者没有域名则可以通过修改`hosts`文件来实现:
```bash
sudo vim /etc/hosts
```
然后增加如下路径:
```
127.0.0.1 tailchat.internal.com
```
现在你可以打开浏览器并打开`http://tailchat.internal.com`来访问部署在k8s中的tailchat服务
当然,你也可以访问如下地址检测服务可用性:
```
http://tailchat.internal.com/health
```

View File

@@ -0,0 +1,87 @@
---
sidebar_position: 1
title: 手动部署
---
:::caution
本章内容需要你对 nodejs, git, linux 有一定程度的了解。当出现如依赖问题、环境问题、系统问题等问题时需要具备自行解决和排查问题的能力。
如果你对此并不了解,不建议你使用本章内容进行部署。建议使用统一镜像进行部署。
:::
## 依赖
- git
- nodejs v16.18.0 或以上
- pnpm v8.3.1 或以上
- mongodb
- redis
- minio
## 下载源码
```bash
mkdir msgbyte && cd msgbyte
git clone https://github.com/msgbyte/tailchat.git
```
### 切换到稳定代码
因为克隆下来的代码是最新代码可能存在短时间内不稳定的情况因此如果想要切换到各个版本的稳定代码的话可以使用git的tag功能
如切换到`v1.7.6`则可以使用命令:
```bash
git checkout v1.7.6
```
## 编译项目
Tailchat 是一个前后端分离的项目。因此我们要分别处理前端代码和后端代码
### 安装依赖
我们假设你已经安装了 `nodejs v16.18.0+` 或者以上的版本。以及安装了 `pnpm v8.3.1` 或以上版本
```bash
cd tailchat
pnpm install
```
该命令会花费一些时间将Tailchat所有的依赖都安装一遍。当安装完毕后内部的插件会自动执行编译命令。
### 构建项目
```bash
NODE_ENV=production pnpm build
```
该命令会并行执行编译前端后端管理端的命令。并将前端产物移动到服务端的 `server/dist/public` 目录
当项目构建完毕后我们的产物就可以正常运行了
:::caution
请尽可能在 `macos` / `linux` 环境进行构建window 对 shell 命令支持并不一定完全
:::
## 运行项目
为了确保项目能够水平扩容,`Tailchat` 的核心代码虽然写在同一个项目中,但是实际启动起来的时候可以被划分为多个细分的微服务。通过传入不同的环境变量的组合来实现有选择的启用不同的服务。
在server目录下以`.env.example`目录为例创建一个环境变量文件
```bash
cp server/.env.example server/dist/.env
vim .env
```
将必要的环境变量修改为自己的,如 `MONGO_URL`, `REDIS_URL`, `MINIO_URL`
然后启动服务
```bash
SERVICEDIR=services,plugins pnpm start:service
```
> `SERVICEDIR` 表示加载微服务的目录

View File

@@ -0,0 +1,26 @@
---
sidebar_position: 1
title: 快速开始
---
## 演示环境
演示环境会持续部署最新前端代码和不定期更新后端代码
[https://nightly.paw.msgbyte.com/](https://nightly.paw.msgbyte.com/)
## 部署方式
### Docker/Docker Compose
强烈推荐使用 `docker-compose` 部署 `tailchat`
教程请翻阅: [Docker Compose 部署](./docker-compose.mdx)
### Kubernetes
教程请翻阅: [kubernetes 简易部署](./other-way/kubernetes/simple.md)
## 系统架构
见 [系统架构](../architecture.md)

View File

@@ -0,0 +1,45 @@
---
sidebar_position: 10
title: SMTP 服务(可选)
---
`Tailchat` 包含邮件服务, 使用的场景如 **密码找回**、**邮件认证**
因为仅需要单向的发送邮件而无需接受邮件,因此在 `Tailchat` 中仅使用简单邮件服务(SMTP).
为了启用该服务,我们需要在环境变量中设置如下内容:
- `SMTP_SENDER`: 发送人信息, 一般的格式是 `xxx@example.com``"YourName" xxx@example.com`
- `SMTP_URI`: SMTP 邮件服务地址, 遵循国际通用 URI 格式: `<protocol>://<username>:<password>@<host>:<port>/<other-info>`
## 使用 cli 进行辅助测试
如果你对 SMTP 服务不熟,为了提高检测效率你可以选择使用 `tailchat-cli` 来快速帮你验证 smtp 服务可靠性
> 关于 tailchat-cli 的使用见 [tailchat-cli](../cli/tailchat-cli.md)
```
tailchat smtp
SMTP Service
Commands:
tailchat smtp verify Verify smtp sender service
tailchat smtp test Send test email with smtp service
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
```
你可以使用 `tailchat smtp verify` 验证 URI 可用性,在这个操作中是不会实际发送邮件的。类似于账号登录
如果验证通过后依旧有问题,你可以使用`tailchat smtp test`来实际发送测试邮件来帮助你排查问题,因为实际生产环境中可能性非常多,比如各个服务商的审核问题导致的退信,比如验证程度不一样如有的服务商允许自定义发信人名称有的对其有严格的要求
## SMTP_URI 示例
因为不同的服务商提供的服务各有差异, 这里只能举出部分内容用于演示。如果你有其他的可以作为示例的 URI 欢迎提交 PR 来帮助我们一起完善文档:
- `smtps://<username>:<password>@smtp.exmail.qq.com/?pool=true`
- `smtps://<username>:<password>@smtp.163.com/?pool=true`
- `smtps://<qqNumber>:<password>@smtp.qq.com/?pool=true`

View File

@@ -0,0 +1,103 @@
---
sidebar_position: 50
title: 常见问题
---
## 部署相关
### 如何更新版本?
和部署时获取镜像一样
```bash
docker pull moonrailgun/tailchat
docker tag moonrailgun/tailchat tailchat
```
然后重启应用即可, 如 `docker compose up -d`
### 如何使用指定版本?
```bash
docker pull moonrailgun/tailchat:1.8.4
docker tag moonrailgun/tailchat:1.8.4 tailchat
```
在拉取镜像的时候指定版本号即可
## 服务端相关
### Websocket 连接访问不正确,表现形式是可以注册但是无法打开主界面
如果使用了 nginx 进行反向代理。请确保nginx的配置支持websocket一个参考的配置如下:
```
server {
server_name demo.example.com;
listen 443 ssl;
access_log /var/log/nginx/host.access.log main;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass http://127.0.0.1:11000/;
}
}
```
### 内网可以访问外网无法访问?
可以启动一个简单的http服务看下是不是docker-proxy层的问题。*该问题可能会出现在腾讯轻量云的docker-ce镜像机器上, 可以选择使用centos7镜像重装*
```bash
docker run --rm --name nginx-test -p 8080:80 nginx
```
### 启动时会出现随机hash的volume
见: [https://github.com/msgbyte/tailchat/issues/79](https://github.com/msgbyte/tailchat/issues/79)
### 发送邮件时出现 `502 Invalid paramenters`
如果提示类似: `Error: Mail command failed: 502 Invalid paramenters`
```
code:'EENVELOPE',
response: '502 Invalid paramenters',
responseCode: 502,
command: 'MAIL FROM'
```
请检查你的`SMTP_SENDER`内容是否正确,一般的格式是 `xxx@example.com``"YourName" xxx@example.com`
### Openapi 服务一直在重启
如果抛出了错误 `Issuer Identifier must be a valid web uri`
你应该确保在环境变量`API_URL`中填入了一个url(`http://xxxx``https://xxxx`)
## 开放平台相关
如果开放平台部署在代理之后,如果出现访问 `/open/.well-known/openid-configuration` 结果的json中endpoint不正确的情况请尝试修改代理的配置。
如nginx:
```
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:11000;
proxy_redirect off;
}
```

View File

@@ -0,0 +1,4 @@
{
"label": "运维操作",
"position": 15
}

View File

@@ -0,0 +1,22 @@
---
sidebar_position: 1
title: 数据库管理
---
`tailchat` 使用 mongodb 作为主要数据库存储用户信息
`docker`中,常见的运维命令如下:
```bash
# 备份
docker exec -i <IMAGE_NAME> mongodump -d tailchat --archive > ./backup.archive
# 还原
docker exec -i <IMAGE_NAME> mongorestore -d tailchat --archive < ./backup.archive
```
其中`<IMAGE_NAME>` 表示mongodb镜像名`-d tailchat` 表示使用的数据库的名字,默认启动的数据库名为`tailchat`, 你可以通过环境变量`MONGO_URL`进行修改
:::info
为了用户数据安全,建议创建定时任务定期备份数据库文件
:::

View File

@@ -0,0 +1,90 @@
---
sidebar_position: 1
title: 概述
---
`Tailchat` 是一款插件化易拓展的开源 IM 应用。可拓展架构赋予 `Tailchat` 无限可能性。
前端微内核架构 + 后端微服务架构 使得 `Tailchat` 能够驾驭任何定制化/私有化的场景
面向企业与私域用户打造,高度自由的群组管理与定制化的面板展示可以让私域主能够更好的展示自己的作品,管理用户,打造自己的品牌与圈子。
## 特性
- 完整的即时通讯基础能力
- 插件化架构的赋予的自由拓展能力
- 微服务架构赋予的水平拓展能力
## 亮点
- 基于[mini-star](https://ministar.moonrailgun.com/)的前端微内核架构与基于[moleculer](https://moleculer.services/)的后端微服务架构可以适应各种用户用量,便于拓展
- 完整的聊天系统支持提及、面板跳转、富文本、markdown、url链接等各种语法
- 消息reaction机制让你通过表情表达自己
- 文件分享与图片发送
- 支持语音通话与视频通话
- 完善的身份组管理,权限控制颗粒化
- 用户管理与用户禁言
- 邮箱认证与密码找回
- 多种面板: 网页嵌入, 自定义html, 话题面板
- 简易消息推送与github通知订阅
- 后台管理平台
- 开放平台
- 机器人
- OAuth
- 插件带来的更多奇妙化学反应
- 自定义主题
- 在线听音乐
- 消息加密
- url获取元数据
- 隔空投送
- 任务管理
- 在线绘图
- 字体放大
- 工具箱
- ...
## 技术栈
- 前端
- `React`
- `Redux`
- `mini-star`
- `tailwindcss`
- `iconify`
- 后端
- `Nodejs`
- `Socket.io`
- `koa`
- `moleculer`
## 截图
#### 概览
![](/img/intro/hello.png)
#### 插件中心
![](/img/intro/plugins.png)
#### 各类主题
![](/img/intro/theme.png)
#### 身份组与权限管理
![](/img/intro/roles.png)
#### Github订阅机器人
![](/img/intro/github-bot.png)
#### Admin 后台管理
![](/img/intro/admin-network.png)
## 开源协议
开源协议请主要参考以下文档:
[Apache 2.0](https://github.com/msgbyte/tailchat/blob/master/LICENSE)

View File

@@ -0,0 +1,93 @@
---
sidebar_position: 10
title: 声网插件部署指南
---
:::info
声网插件需要确保您的 `tailchat` 镜像版本在 1.4.0+
:::
## 在声网平台申请项目
Tailchat 声网集成是依赖声网服务实现的音视频通话功能,因此在使用前需要在声网平台上注册。
声网官方: [https://www.agora.io/](https://www.agora.io/)
### 获取配置参数
注册完毕后/登录后会自动跳转到控制台。在控制台中可以进行项目配置
![](./images/1.png)
如果没有创建项目则需要先创建项目。如下图所示
![](./images/2.png)
建议使用安全模式以避免被其他人盗用。
接下来我们需要获取一些配置项用于配置`Tailchat`的声网插件。
![](./images/3.png)
在项目配置中我们可以获取 `appid``app cert`。这两个分别是我们之后要用到的环境变量 `AGORA_APP_ID``AGORA_APP_CERT`
### 获取客户凭证
另外我们还需要在右上角的 `RESTful API` 处获得客户的权限,
操作如图所示:
![](./images/4.png)
![](./images/5.png)
这样我们就拿到了另外两个环境变量: `AGORA_CUSTOMER_KEY``AGORA_CUSTOMER_SECRET`
我们初步的准备工作就完成了
## 安装插件
目前声网插件的服务端插件已经被默认安装,您无需做任何事情。但是为了正常使用需要配置环境变量
### 配置环境变量
配置环境变量请见 [环境变量](../deployment/environment.md)
声网插件需要环境变量如下:
- `AGORA_APP_ID`: 声网项目应用id
- `AGORA_APP_CERT`: 声网项目证书
- `AGORA_CUSTOMER_KEY`: 声网客户id
- `AGORA_CUSTOMER_SECRET`: 声网客户秘钥
这些环境变量都可以在上面的教程中获取。
配置环境变量完毕后即可
## 申请服务状态回调
为了使通话状态能够同步给`Tailchat`, 需要在声网中申请服务端回调。
在项目配置中,我们需要在`服务配置` 中启用`消息通知服务`
![](./images/6.png)
需要订阅以下事件:
- channel create=101
- channel destroy=102
- broadcaster join channel=103
- broadcaster leave channel=104
接收服务器 URL 一般为: `https://<YOUR SERVER DOMAIN>/api/plugin:com.msgbyte.agora/webhook`, 其中`<YOUR SERVER DOMAIN>` 换成你的 `Tailchat` 域名。
:::info
声网的服务会对服务器做连通性检查,因此需要配置好环境变量启动服务后再执行本次步骤。
另外声网需要配置`https``webrtc`服务也依赖`https`, 因此需要确保服务器网关支持`https`协议
:::
配置完成后你会看到如下提示。等待声网工作人员确认完毕后即可生效。
![](./images/7.png)

View File

@@ -0,0 +1,100 @@
---
sidebar_position: 2
title: 部署视频会议
---
:::info
`Tailchat Meeting` 方案目前没有与 `Tailchat` 做集成如果你期望在Tailchat中使用视频会议方案请选择 `agora``livekit` 解决方案
:::
视频会议服务 `Tailchat Meeting` 可以作为一个独立应用单品存在。在本节中将会讲述如何独立部署 `Tailchat Meeting`
以下内容均基于`docker`环境,请确保服务端有 `docker` 最基本程度的环境。
如果还没有安装 `docker` + `docker-compose` 可以查看文档 [安装docker环境](../deployment/install-docker.md)
## 快速部署
```bash
git clone https://github.com/msgbyte/tailchat-meeting --depth=1
```
> NOTE: 接下来会使用docker 的 host 模式进行安装。即`docker-compose` 会自动绑定主机端口
需要服务器预留端口如下:
- swag(服务器网关, nginx 强化版, 端口可通过配置文件 tailchat-meeting/compose/nginx.conf 修改)
- 80
- 443
- tailchat-meeting
- 13001
- 40000-49999(用于RTC服务, 动态占用)
- redis
- 6379
**以上端口均会在宿主机上暴露为了服务器安全着想建议配置合适的防火墙策略仅暴露必要的端口443和40000-49999**
```bash
cd tailchat-meeting/compose
cp docker-compose.env.example docker-compose.env
vi docker-compose.env
```
修改环境变量。
环境变量如下:
```
# 内网IP
MEDIASOUP_IP=
# 公网IP
MEDIASOUP_ANNOUNCED_IP=
# swag相关
URL=
SUBDOMAINS=
TZ=Asia/Shanghai
```
其中
- 如果仅单机部署的话`MEDIASOUP_IP``MEDIASOUP_ANNOUNCED_IP`可以均填写服务器公网ip, **但是对于弹性部署网络的服务商(如国内的腾讯云,阿里云等)必须严格按照注释分别填写内网IP和公网IP**(因为该类服务商提供的外网IP并不是绑定在网卡上的)
- `tailchat-meeting` 基于 webrtc 服务,因此强依赖 https/wss 协议。swag服务可以为您自动申请https证书但是必须得分配一个有效的域名并确保dns指向已经指向到服务器上。
- 更多相关的文档可以查看 [README](https://github.com/linuxserver/docker-letsencrypt/blob/master/README.md)
- 示例配置:
```bash
URL=meeting.example.com # 这里请填入
SUBDOMAINS= # 该参数用于多域名证书申请,可留空
```
修改完毕以后可以直接执行以下命令
```bash
docker compose up -d
```
`docker compose` 会自动从网络下载镜像并构建`tailchat-meeting`
构建可能需要花费一定时间和资源。特别是构建前端代码,如果使用的小配置的服务器的话请耐心一点等待。
> 实际测试中使用1核2g的小资源服务器耗时参考如下:
> - 下载依赖包: 3分钟
> - 编译前端代码: 5分钟
访问 `https://meeting.example.com` 即可看到`tailchat-meeting`的页面
## 组合使用
对于傻瓜式部署来说只需要一键就可以执行。如果已经有现成的网关服务(比如nginx, caddy等)以及redis实例可以有选择的启动服务。
如:
```bash
docker compose up tailchat-meeting -d # 仅运行 tailchat-meeting 实例
```
## 使用host模式的原因
`tailchat-meeting` 核心的RTC服务需要在运行时申请端口但是对于docker来说并不能实现这个功能。而预先申请一定范围的端口绑定即会造成无意义端口的浪费也会在启动时瞬间占据大量资源并把系统打死。
**需要注意的是请不要把redis所在的6379端口暴露出去这可能会产生安全隐患。**

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,44 @@
---
sidebar_position: 1
title: 概述
---
:::info
音视频解决方案需要SSL支持因此只有支持https的网站才能正常使用
:::
`Tailchat` 提供以下方案用于视频语音通话,可以根据实际情况自行选择:
- ~~`tailchat-meeting` 自研视频会议(WIP)~~
- `agora` 声网集成, 详细说明见: [声网插件部署指南](./agora.md)
- `livekit` 可自部署的解决方案: [Livekit 插件部署指南](./livekit.md)
<details>
<summary>折叠内容已过时</summary>
视频会议模块是 `Tailchat` 系列的一套重要组成部分。提供能力如下:
- 语音通信
- 视频会话
- 屏幕共享
- 虚拟背景
- 文件传输
- 聊天记录
同时 `tailchat-meeting` 还可以作为独立单品存在,无需登录即可快速发起/加入会议
### 项目仓库
- 开源地址: [https://github.com/msgbyte/tailchat-meeting](https://github.com/msgbyte/tailchat-meeting)
- 开源协议: GPL-3.0
:::info 开源声明
本项目基于 [edumeet](https://github.com/edumeet/edumeet) 和 [mediasoup](https://github.com/versatica/mediasoup) 进行二次开发而来。
在此基础上进行了功能追加与SDK实现以及代码优化。如果想要找到开源协议更加宽松(MIT + ISC 协议)的实现可以看一下这两个项目
:::
### 项目架构
![](/img/architecture/meeting.excalidraw.svg)
</details>

View File

@@ -0,0 +1,73 @@
---
sidebar_position: 20
title: Livekit 插件部署指南
---
`Livekit` 是一款基于 `Apache-2.0` 开源协议的,允许自部署的开源视频会议解决方案,支持视频会议、视频直播、录制等场景
你可以使用他的云端服务或者自部署。以下我会介绍怎么将 `Livekit` 集成到 `Tailchat` 中:
## 云端服务
首先进入Livekit云平台: [https://cloud.livekit.io/](https://cloud.livekit.io/), 首次进入要创建一下项目:
此时会问一些问题,按照情况随便回答一下就行
![](/img/advanced-usage/livekit/1.png)
完成后我们会进入控制台主界面:
![](/img/advanced-usage/livekit/2.png)
### 获取需要的环境变量
为使插件工作,我们需要以下环境变量:
- `LIVEKIT_URL`
- `LIVEKIT_API_KEY`
- `LIVEKIT_API_SECRET`
其中 `LIVEKIT_URL` 我们可以直接从控制台上获取,形如 `wss://********.livekit.cloud`
在左边 `Settings` 菜单中,我们需要自行创建一对秘钥
![](/img/advanced-usage/livekit/3.png)
![](/img/advanced-usage/livekit/4.png)
![](/img/advanced-usage/livekit/5.png)
在这里我们可以获取到 `LIVEKIT_API_KEY``LIVEKIT_API_SECRET`.
记录下来填入环境变量后启动 `Tailchat` 即可.
### 启动 webhook
![](/img/advanced-usage/livekit/6.png)
如果你需要上述的频道在线提示能够即时更新,则需要单独启动一个 `webhook-receiver` 来接受来自 `livekit` 的推送并将接收到的事件转发给 `Tailchat`,让 `Tailchat` 来更新所有群组成员的显示。
官方已为您准备好了一键启动的`docker-compose`配置, 就像 `admin` 一样:
```bash
wget https://raw.githubusercontent.com/msgbyte/tailchat/master/docker/livekit.yml
docker compose -f docker-compose.yml -f livekit.yml up -d
```
此时你可以在docker运行的容器中看到一个 `tailchat-livekit-webhook-receiver` 服务.
然后我们切换到 `livekit` 控制台,在 `webhook` 中添加我们的地址。
![](/img/advanced-usage/livekit/7.png)
一般为 `https://<your tailchat url>/livekit/webhook`, 记得选择与服务一致的密钥对
![](/img/advanced-usage/livekit/8.png)
> PS: 在云端应用可能会有一些延时。
## 自部署
自部署可见官方文档: [https://docs.livekit.io/oss/deployment/](https://docs.livekit.io/oss/deployment/)
除了部署方式不一样与配置为先,其他的与使用云端服务一样

View File

@@ -0,0 +1,11 @@
---
sidebar_position: 100
title: 演示环境与群组
---
演示环境为体现在低配置服务器下 `Tailchat` 的表现(更少的资源占用是Tailchat的重点要求)。测试环境的服务器为 1C2G1M(一个cpu核心2g内存空间1mb带宽限制)。
另外, 这里有一些用于演示Tailchat功能的群组:
- [Tailchat Nightly](https://nightly.paw.msgbyte.com/invite/8Jfm1dWb)
- [原神](https://nightly.paw.msgbyte.com/invite/GFFzfD5H)

View File

@@ -0,0 +1,4 @@
{
"label": "API 接口",
"position": 99
}

View File

@@ -0,0 +1,249 @@
---
sidebar_position: 1
title: "@capital/common"
---
## 注册
### regGroupPanel
注册群组面板
```typescript
regGroupPanel({
name: `com.msgbyte.webview/grouppanel`,
label: '网页面板',
provider: PLUGIN_NAME,
extraFormMeta: [{ type: 'text', name: 'url', label: '网址' }],
render: GroupWebPanelRender,
});
```
参数类型: [PluginGroupPanel](#plugingrouppanel)
### regMessageInterpreter
注册消息解释器
```typescript
regMessageInterpreter({
name: '喵语翻译',
explainMessage(message: string) {
// 喵语 -> 人话
if (!isMiao(message)) {
return null;
}
return decode(message);
},
});
```
参数类型: [PluginMessageInterpreter](#pluginmessageinterpreter)
### regMessageRender
*注册多个仅生效最后一个*
注册消息渲染器, 输入消息文本返回渲染内容
```typescript
regMessageRender((message) => {
return <BBCode plainText={message} />;
});
```
### regChatInputAction
注册聊天输入框操作
```typescript
regChatInputAction({
label: '喵言喵语',
onClick: (actions) => {
openModal(createElement(SendMiaoModal, { actions }));
},
});
```
参数类型: [ChatInputAction](#chatinputaction)
### regPluginColorScheme
注册插件配色方案/主题
```typescript
regPluginColorScheme({
label: 'Miku 葱',
name: 'light+miku',
});
```
## 工具函数
### useGroupPanelParams
`hooks`中获取用户面板相关信息
```typescript
import { useGroupPanelParams } from '@capital/common';
const { groupId, panelId } = useGroupPanelParams();
```
### openModal
打开一个模态框
```typescript
openModal(
content: React.ReactNode,
props?: Pick<ModalProps, 'closable' | 'maskClosable'>
)
```
类型:
- [ModalProps](#modalprops)
### ModalWrapper
模态框包装器
```jsx
<ModalWrapper>
<div></div>
</ModalWrapper>
```
### useModalContext
获取模态框上下文
```typescript
const { closeModal } = useModalContext();
```
### getGlobalState
获取全局 `Redux` 状态上下文
```typescript
const state = getGlobalState();
```
### getCachedUserInfo
获取用户信息, 缓存版本
```typescript
const info = getCachedUserInfo(userId);
```
### getCachedConverseInfo
获取会话信息
```typescript
const info = getCachedConverseInfo(converseId);
```
## 类型
### PluginGroupPanel
```typescript
interface PluginGroupPanel {
/**
* 面板唯一标识
* @example com.msgbyte.webview/grouppanel
*/
name: string;
/**
* 面板显示名
*/
label: string;
/**
* 插件提供者, 用于引导没有安装插件的用户安装插件
*/
provider: string;
/**
* 额外的表单数据, 用于创建面板时使用
*/
extraFormMeta: FastFormFieldMeta[];
/**
* 该面板如何渲染
*/
render: React.ComponentType;
}
```
### PluginMessageInterpreter
插件消息解释器
```typescript
interface PluginMessageInterpreter {
name?: string;
explainMessage: (message: string) => React.ReactNode;
}
```
### ChatInputAction
消息输入框操作对象
```typescript
interface ChatInputAction {
label: string;
onClick: (actions: ChatInputActionContextProps) => void;
}
```
### GroupPanel
```typescript
interface GroupPanel {
id: string; // 在群组中唯一
name: string;
parentId?: string;
type: GroupPanelType;
provider?: string; // 面板提供者
pluginPanelName?: string; // 插件面板名
meta?: Record<string, unknown>;
}
```
### ModalProps
```typescript
interface ModalProps {
visible?: boolean;
onChangeVisible?: (visible: boolean) => void;
/**
* 是否显示右上角的关闭按钮
* @default false
*/
closable?: boolean;
/**
* 遮罩层是否可关闭
*/
maskClosable?: boolean;
}
```

View File

@@ -0,0 +1,22 @@
---
sidebar_position: 2
title: "@capital/component"
---
### Button
组件来自 [antd](https://ant.design/)
组件文档: [Button](https://ant.design/components/button-cn/)
### TextArea
组件来自 [antd](https://ant.design/)
组件文档: [TextArea](https://ant.design/components/input-cn/#components-input-demo-textarea)
### Image
组件来自 [antd](https://ant.design/)
组件文档: [Image](https://ant.design/components/image-cn/)

View File

@@ -0,0 +1,9 @@
---
sidebar_position: 3
title: 全局CSS变量
---
- `--tc-primary-color`: 主色调
- `--tc-background-image`: 背景图片
- `--tc-content-background-image`: 内容页背景图片
- `--tc-content-background-image-opacity`: 内容页背景图片透明度,默认 **0.15**

View File

@@ -0,0 +1,19 @@
---
sidebar_position: 4
title: "data-tc-role"
---
`Tailchat Role` 是一种通过`data-*`方式来标识DOM的一种方式表明该节点在`Tailchat`中的角色, 开发者可以通过这来找到对应角色的DOM节点
例如: `[data-tc-role=navbar]`
- `navbar`: 导航栏
- `navbar-personal`: 导航栏中的个人主页
- `navbar-groups`: 导航栏中的群组
- `navbar-settings`: 导航栏中的设置
- `sidebar-personal`: 个人主页中的侧边栏
- `sidebar-group`: 群组中的侧边栏
- `content-personal`: 个人主页中的内容
- `content-group`: 群组页面中的内容
- `modal`: 模态框
- `modal-mask`: 模态框的遮罩层

View File

@@ -0,0 +1,212 @@
---
sidebar_position: 3
title: 开发一个主题插件
---
`Tailchat` 中开发插件是非常方便的,我们从开发一个主题插件来开始
## 最终效果
![](/img/tutorial/plugin/2.png)
![](/img/tutorial/plugin/3.png)
![](/img/tutorial/plugin/4.png)
## 创建插件
> 如果是第一次开发需要确保已经初始化了插件开发环境。 [了解更多](./init-env.md)
```bash
tailchat create --template client-plugin
```
因为主题样式是一个纯前端的实现,因此我们选择`client-plugin`模板
通过交互式命令行提示完成创建工作
![](/img/tutorial/plugin/5.png)
此时的目录结构应该是这样的:
```
.
├── package-lock.json
├── package.json
├── node_modules
└── plugins
└── com.test.hutao
├── manifest.json
├── package.json
├── src
│   ├── index.tsx
│   └── translate.ts
├── tsconfig.json
└── types
└── tailchat.d.ts
```
这时候我们就可以立即开始编译插件了
```bash
npm run plugins:all
```
编译的产物会出现在 `/dist/plugins/com.test.hutao`。通过修改 `mini-star` 的配置可以让其输出在其他目录 *(这点会在服务端开发插件中会用到)*
## 在 Tailchat 中安装插件
对于前端插件我们需要把产物用一个http静态服务提供出来比如在本地开发中我们可以这样:
```bash
npx http-server .
```
![](/img/tutorial/plugin/6.png)
此时我们可以通过地址访问到我们编译出来的结果了,如 [http://127.0.0.1:8080/dist/plugins/com.test.hutao/index.js](http://127.0.0.1:8080/dist/plugins/com.test.hutao/index.js)
在 Tailchat 中提供了手动安装插件的方式,我们可以通过手动安装的方式安装插件。
复制插件目录下 `plugins/com.test.hutao/manifest.json` 的内容,粘贴到手动安装插件部分。
修改url为可以访问到的真实地址。点击确定按钮后自动执行安装命令:
![](/img/tutorial/plugin/7.png)
如果提示安装成功,打开控制台则可以看到对应输出:
![](/img/tutorial/plugin/8.png)
这里是插件里默认生成的逻辑,当日志输出了插件加载完毕的提示说明我们的插件已经被安装成功了。
## 编写样式文件并应用
因为我们需要修改主题样式,因此涉及到样式文件和静态资源的处理。接下来我们先来创建我们主题的样式
`plugins/com.test.hutao/src/theme.less`中写入样式:
```less
#tailchat-app.theme-genshin-hutao {
@primary-color: #dd5545;
--tc-primary-color: @primary-color;
--tc-background-image: url(./bg.jpg);
--tc-content-background-image: url(./avatar.png);
--tc-content-background-image-opacity: 0.15;
.bg-navbar-light {
background-color: @primary-color;
.bg-gray-400 {
background-color: darken(@primary-color, 10%);
}
}
.bg-sidebar-light {
background-color: lighten(@primary-color, 20%);
}
.bg-content-light {
background-color: lighten(@primary-color, 40%);
}
&.dark {
--tc-primary-color: darken(@primary-color, 10%);
.dark\:bg-navbar-dark {
background-color: darken(@primary-color, 40%);
}
.dark\:bg-sidebar-dark {
background-color: darken(@primary-color, 20%);
}
.dark\:bg-content-dark {
background-color: @primary-color;
}
}
}
```
这个样式文件做了三件事情:
- 通过 `less变量` 的方式指定主色调, 大幅度减少冗余代码
- 通过 `css变量` 的方式指定 `Tailchat` 的各处背景图, 主要是登录页的背景图与头像
- 在根节点使用`#tailchat-app.theme-genshin-hutao`选择器确保不会污染全局样式。
**对应的,需要在根节点下放入`bg.jpg`和`avatar.png`作为静态资源**
为了让 `Tailchat` 能够知道有这么一个主题存在,我们需要将这个主题相关的信息注册到 `Tailchat` 中.
```js
// plugins/com.test.hutao/src/index.tsx
import { regPluginColorScheme, sharedEvent } from '@capital/common';
regPluginColorScheme({
label: '原神-胡桃测试主题',
name: 'light+genshin-hutao',
});
sharedEvent.on('loadColorScheme', (colorSchemeName) => {
if (colorSchemeName === 'light+genshin-hutao') {
console.log('正在加载胡桃主题...');
import('./theme.less');
}
});
```
这个插件做了两件事情:
- 调用 `regPluginColorScheme` 将主题生命注册到 `Tailchat` 中,这样 `Tailchat` 就会在系统设置中显示该主题。
- 需要注意的是主题的 `name` 是以 `<color>+<theme-name>`的形式组成的,默认的 `Tailchat` 会提供 `auto`/`light`/`dark`三种配色方案,这里是指基于亮色模式追加样式覆盖的意思。
- 通过 `sharedEvent` 监听加载主题样式事件,如果配色主题是我们的主题,则异步加载主题(异步加载的目的是减少无意义的网络请求)
此时我们的编译是无法通过的因为对于less类型的文件还没有处理
`mini-star` 已经默认对less文件进行处理我们只需要安装一下 `less` 包以后 `mini-star` 会自动调用安装的less进行编译
```bash
npm install less
```
此时执行`npm run plugins:all`进行编译操作,最后目录应当如下:
```
.
├── dist
│   └── plugins
│   └── com.test.hutao
│   ├── index.js
│   ├── index.js.map
│   ├── theme-475203da.js
│   └── theme-475203da.js.map
├── package-lock.json
├── package.json
└── plugins
└── com.test.hutao
├── manifest.json
├── package.json
├── src
│   ├── avatar.png
│   ├── bg.jpg
│   ├── index.tsx
│   ├── theme.less
│   └── translate.ts
├── tsconfig.json
└── types
└── tailchat.d.ts
```
为了便于管理,`mini-star` 在处理less引用的静态资源时会直接以 `base64` 的格式把图片打包到样式文件中。因此主题文件会非常大,这也是为什么我们需要按需异步加载的原因
![](/img/tutorial/plugin/9.png)
因为我们之前已经在 Tailchat 中安装过我们开发中的插件了,因此直接刷新即可。
在左下角设置菜单中点开系统设置的主题页面,我们就可以看到我们的主题了。切换过去立即界面会变成我们想要的主题风格。
![](/img/tutorial/plugin/10.png)
## 源码参考
官方的该主题实现可以访问 [https://github.com/msgbyte/tailchat/tree/master/client/web/plugins/com.msgbyte.theme.genshin](https://github.com/msgbyte/tailchat/tree/master/client/web/plugins/com.msgbyte.theme.genshin) 查看

View File

@@ -0,0 +1,54 @@
---
sidebar_position: 90
title: 部署插件
---
:::info
插件的部署策略后续会进行优化目前tailchat对部署时自定义插件还做的不够便利因此可能会有些困惑。因此本文档仅代表现状后续会不断改进
:::
首先说一下 Tailchat 插件的分类Tailchat 的插件分为 `纯前端插件`, `纯后端插件`, `前后端插件`
`纯前端插件`最为容易理解表示插件仅运行在前端代码中依赖已有的上下文进行沟通无需Tailchat后端支持。特别的对于与自定义后端进行通信的也是前端插件`com.msgbyte.ai-assistant`插件)
`纯后端插件为`为与Tailchat网络进行通信的插件无前端界面通过rpc调用其他服务的action来实现一些目的。对于后端插件来说意味着插件本身接入了Tailchat后端网络拥有最高的权限可以访问一些可见性为`public`的action(默认只有`publish`级别的action可以被外部访问其他级别的都是只有内部服务才能访问),一个无前端的后端插件如`com.msgbyte.simplenotify`插件
`前后端插件` 表示既有前端又有后端的插件,是最复杂但是能力最完全的插件类型,通过前端插件与后端交互,通过后端插件与其他的服务进行交互,在不修改核心代码的前提下能完成大部分的开发工作
你可以在这个文档中查看对应的插件示例: [插件列表](/docs/plugin-list/fe)
## 部署流程
在不同的插件部署的流程是不一样的
### 纯前端插件
纯前端插件你可以将代码放置在项目内部`client/web/plugins`目录下或者使用单独的静态文件服务管理。确保项目的js文档都是能正常访问的。
如果这是一个个人使用的插件,你可以通过插件中心的手动安装来安装,输入`manifest.json`的json配置即可。注意确保配置文件中的地址都是可以正常访问的。
如果想让所有的用户都能够看见代码,你需要在`client/web/registry.json`中添加你自己的插件配置。
如果想要成为一个默认安装的内置插件,需要修改`client/web/src/plugin/builtin.ts`文件来让前端代码在启动时加载插件。
### 纯后端插件
为了让插件能够被自动加载,你可以将代码放置与 `server/plugins` 目录下或者独立部署,只需要确保能够连入同一个网络即可(共用同一个TRANSPORTER)
默认部署的插件服务会将该目录下的所有后端插件统一加载。需要确保插件服务的命名为`*.service.ts`/`*.service.js`
*如果仅想在开发环境运行而在生产环境忽略,请将文件命名为 `*.service.dev.ts`*
你可以访问后端 `/health`(如:`http://localhost:11000/health`) 路由或者使用`tailchat connect`工具查看已加载的微服务列表
### 前后端插件
前后端插件的部署与后端差不多,但是需要修改编译命令让构建时能够把前后端插件的前端代码部署到`public/plugins`目录下
具体方式是: 修改`package.json`, 在 `build:server` 命令中追加想要编译的插件名称
> 配置文件中的 {BACKEND} 指代后端地址,因为前后端分离的关系后端地址不一定和前端地址保持一致
--------
所有操作完毕后记得重新构建 docker 镜像

View File

@@ -0,0 +1,62 @@
---
sidebar_position: 1
title: 初始化插件开发环境
---
在开发一个插件之前,我们需要创建一个插件开发环境,这个环境可以是直接复用 Tailchat 官方源码的插件环境([https://github.com/msgbyte/tailchat/tree/master/client/web/plugins](https://github.com/msgbyte/tailchat/tree/master/client/web/plugins)),也可以是一个独立的项目
这里主要教大家怎么创建一个独立的插件开发环境
## 前端插件开发环境
创建一个插件非常简单, 在此之前如果我们没有初始化插件环境的话需要先初始化一下开发环境
我们先随便找个地方建一个项目文件夹:
```bash
mkdir tailchat-plugin-test && cd tailchat-plugin-test
```
在根目录下执行:
```bash
npm init -y
npm install mini-star
```
在根目录创建 `mini-star` 的配置文件 `.ministarrc.js`,内容如下:
```js
// .ministarrc.js
const path = require('path');
module.exports = {
externalDeps: [
'react',
'react-router',
'axios',
'styled-components',
'zustand',
'zustand/middleware/immer',
],
};
```
`package.json` 中写入编译脚本
```json
{
//...
"scripts": {
// ...
"plugins:all": "ministar buildPlugin all",
"plugins:watch": "ministar watchPlugin all",
// ...
}
//...
}
```
## 后端插件开发环境
TODO

View File

@@ -0,0 +1,51 @@
---
sidebar_position: 2
title: Typescript 类型支持
---
`Tailchat` 中拥有一些从核心项目共享出来的工具函数或者组件,你可以通过 `@capital/common``@capital/component` 来引用。
当然如果直接引用的话会有一些类型问题。因为此时typescript的类型系统是不知道能够引入什么以及有什么类型的。
在这里可能会有两种情况:
## 在Tailchat本体项目中进行开发
你可以通过`tsconfig.json``paths`字段来引入同一目录下的文件, 这样在解析时typescript可以直接加载完整的类型系统
如:
```json
{
"compilerOptions": {
"baseUrl": "./src",
"esModuleInterop": true,
"jsx": "react",
"paths": {
"@capital/*": ["../../../src/plugin/*"],
}
}
}
```
## 在独立项目中进行开发
你可以通过获取 Tailchat 预生成好的声明文件进行开发。
> 因为类型要手动重写因为有部分类型尚是any。但是能够保证开发者不会引入不存在的函数
如果你使用的是 `tailchat create` 命令创建的项目,命令行工具模板已为您添加了如下命令
```json
"scripts": {
"sync:declaration": "tailchat declaration github"
},
```
用法
```bash
pnpm sync:declaration
```
该命令会自动拉取远程的配置文件并写入当前目录下的 `types/tailchat.d.ts` 文件中。如果你是手动创建的项目,你可以将其添加到你的`package.json`中以方便后续使用

View File

@@ -0,0 +1,20 @@
---
sidebar_position: 10
title: Icon 图标
---
```ts
import { Icon } from '@capital/component';
```
`tailchat` 的 icon 解决方案来自 `iconify`
使用方法很简单:
- 在下述网站中选择想要的图标: [https://icon-sets.iconify.design/](https://icon-sets.iconify.design/)
- 复制选中的key。传给 `Icon` 组件, 示例:
```tsx
<Icon icon="mdi:account" />
```
推荐使用`mdi`来统一化图标视觉设计:
[https://icon-sets.iconify.design/mdi/](https://icon-sets.iconify.design/mdi/)

View File

@@ -0,0 +1,87 @@
---
sidebar_position: 1
title: 开始开发插件
---
## 认识 MiniStar
`MiniStar` 是一套完整的微内核架构开发工具链,`Tailchat`的插件架构就是基于 `MiniStar` 进行开发。
关于更多的 `MiniStar` 相关问题可以查看 `MiniStar` 的官方文档: [https://ministar.moonrailgun.com/](https://ministar.moonrailgun.com/)
## 创建一个基本项目
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<Tabs groupId="start">
<TabItem value="cli" label="使用命令行工具快速创建" default>
> 首先确保你已经安装了 `tailchat-cli`, 关于命令行工具可参照: [tailchat-cli](../cli/tailchat-cli)
移动到项目目录下(可以是自定义项目):
```bash
tailchat create
```
根据实际情况选择模板
![](/img/tutorial/plugin/1.png)
</TabItem>
<TabItem value="ministar" label="使用原生ministar创建插件项目" default>
创建一个基本的 npm 项目, 并全局安装 `MiniStar`
```bash
npm install --global mini-star
```
在项目中执行: `ministar createPlugin` 来创建一个基本的插件
在项目中执行: `ministar buildPlugin` 来编译插件
> 值得一提的是, 虽然 `Tailchat` 并没有强制规定插件命名规范,但是还是推荐使用 `反域名` 的命名方式(类似于java中的包命名), 然后对插件中的部件,使用 `/` 进行分割
>
> 如:
> 插件名: `com.msgbyte.webview`
>
> 注册内容: `com.msgbyte.webview/grouppanel`
</TabItem>
</Tabs>
## 安装插件
### 手动安装插件
在不经过任何预设的情况下,一个通用的办法是自己构造一个 `manifest` 配置, 然后在 `tailchat` 提供手动安装插件 Tab 中将配置文件粘贴进去安装。
插件的url路径可以通过 `oss对象存储服务` / `static-server` 等办法代理
一个作为示例的`manifest.json`配置如下:
```json
{
"label": "网页面板插件",
"name": "com.msgbyte.webview",
"url": "/plugins/com.msgbyte.webview/index.js",
"version": "0.0.0",
"author": "msgbyte",
"description": "为群组提供创建网页面板的功能",
"requireRestart": false
}
```
## 其他有用的资源
- 插件化架构内核依赖库 [MiniStar](https://ministar.moonrailgun.com/)
- 来自基础项目提供的API: [API 文档](./api/common)
- 导出接口源码
- [@capital/common](https://github.com/msgbyte/tailchat/blob/master/client/web/src/plugin/common/index.ts)
- [@capital/component](https://github.com/msgbyte/tailchat/blob/master/client/web/src/plugin/component/index.tsx)

View File

@@ -0,0 +1,26 @@
---
sidebar_position: 2
title: 使用场景
---
Tailchat 的设计之处就是以插件化的架构来满足不同人群对于不同需求的实现。
## 对于个人用户
- 如果希望和朋友一起玩
- 创建一个群组
- 通过多个频道分割不同的话题
- 使用网页面板来分享喜欢的网页
- 如果希望聚集自己的粉丝圈
- 使用机器人来订阅自己的信息并转发到聊天面板
- 让自己的粉丝集中在一起不需要创建无数个qq群/微信群
- 多个频道让多个话题能够一起产生
- 如果对于自己的隐私非常看中
- 自己部署让一切都能掌控在手中
## 对于企业用户
- 面板化设计满足企业自定义化设计需求
- 插件化架构可以方便基于核心进行二次开发
- 自部署的实现可以让企业价值得到保护,让企业安心
- 开源代码方便审查