chore: import upstream snapshot with attribution
@@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: api
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: app
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: changelog
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: config
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: faq
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: getting-start
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: install
|
||||
---
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
id: script
|
||||
---
|
||||
@@ -0,0 +1,117 @@
|
||||
module.exports = {
|
||||
title: 'fiora docs',
|
||||
tagline: 'An interesting open source chat application',
|
||||
url: 'https://fiora.suisuijiang.com',
|
||||
baseUrl: '/fiora/',
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
favicon: 'img/favicon.png',
|
||||
organizationName: 'yinxin630', // Usually your GitHub org/user name.
|
||||
projectName: 'fiora', // Usually your repo name.
|
||||
themeConfig: {
|
||||
navbar: {
|
||||
title: 'fiora',
|
||||
logo: {
|
||||
alt: 'Logo',
|
||||
src: 'img/favicon.png',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
to: 'docs/getting-start',
|
||||
activeBasePath: 'docs',
|
||||
label: 'Docs',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/yinxin630/fiora',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
type: 'localeDropdown',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{
|
||||
label: 'Overview',
|
||||
to: '/',
|
||||
},
|
||||
{
|
||||
label: 'Getting Start',
|
||||
to: 'docs/getting-start',
|
||||
},
|
||||
{
|
||||
label: 'Change Log',
|
||||
to: 'docs/changelog',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'Feedback',
|
||||
href:
|
||||
'https://fiora.suisuijiang.com/invite/group/5adacdcfa109ce59da3e83d3',
|
||||
},
|
||||
{
|
||||
label: 'Issues',
|
||||
href: 'https://github.com/yinxin630/fiora/issues',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'Author',
|
||||
href: 'https://suisuijiang.com',
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/yinxin630/fiora',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © 2015 - ${new Date().getFullYear()} developed by 碎碎酱`,
|
||||
},
|
||||
colorMode: {
|
||||
disableSwitch: true,
|
||||
},
|
||||
},
|
||||
presets: [
|
||||
[
|
||||
'@docusaurus/preset-classic',
|
||||
{
|
||||
docs: {
|
||||
sidebarPath: require.resolve('./sidebars.js'),
|
||||
// Please change this to your repo.
|
||||
editUrl: 'https://github.com/yinxin630/fiora/edit/master/docs/',
|
||||
},
|
||||
theme: {
|
||||
customCss: require.resolve('./src/css/custom.css'),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en', 'zh-Hans'],
|
||||
localeConfigs: {
|
||||
en: {
|
||||
label: 'English',
|
||||
},
|
||||
'zh-Hans': {
|
||||
label: '简体中文',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"Title": {
|
||||
"message": "fiora"
|
||||
},
|
||||
"TagLine": {
|
||||
"message": "An interesting open source chat application"
|
||||
},
|
||||
"Keywords": {
|
||||
"message": "fiora, fiora docs, node.js, chatroom"
|
||||
},
|
||||
"Description": {
|
||||
"message": "This site is for fiora doc. Fiora is an interesting open source chat application"
|
||||
},
|
||||
|
||||
"Richness": {
|
||||
"message": "Fiora contains backend, frontend, Android and iOS apps"
|
||||
},
|
||||
"Cross Platform": {
|
||||
"message": "Fiora is developed with node.js. Supports Windows / Linux / macOS systems"
|
||||
},
|
||||
"Open Source": {
|
||||
"message": "Fiora follows the MIT open source license"
|
||||
},
|
||||
|
||||
"Join Chat Title": {
|
||||
"message": "Join Chat"
|
||||
},
|
||||
"Join Chat Content": {
|
||||
"message": "Register an account to join the chat. Join or create new group. Chat privately with funny strangers and add them as friends. Your account and messages will be stored forever"
|
||||
},
|
||||
"Rich Feature Title": {
|
||||
"message": "Rich Feature"
|
||||
},
|
||||
"Rich Feature Content": {
|
||||
"message": "You can send text, emoticons, pictures, codes and files to others. You can also withdraw the sent message. In addition, you can modify your name and avatar. The most exciting is you can choose or customize different themes"
|
||||
},
|
||||
"Deploy By Yourself Title": {
|
||||
"message": "Deploy By Yourself"
|
||||
},
|
||||
"Deploy By Yourself Content": {
|
||||
"message": "Fiora is an open source project. You can clone the source code and deploy to your own server. It supports windows / Linux and macOS systems. But recommended that you deploy on a linux server"
|
||||
},
|
||||
|
||||
"Interested": {
|
||||
"message": "Are you very interested?"
|
||||
},
|
||||
"Getting Start": {
|
||||
"message": "Getting Start"
|
||||
},
|
||||
|
||||
"Try It Now": {
|
||||
"message": "Try It Now"
|
||||
},
|
||||
|
||||
"View Docs": {
|
||||
"message": "View Docs"
|
||||
},
|
||||
"DocsUrl": {
|
||||
"message": "/fiora/docs/getting-start/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
---
|
||||
id: api
|
||||
title: API
|
||||
sidebar_label: API
|
||||
---
|
||||
|
||||
## 如何调用接口
|
||||
|
||||
fiora 后端基于 socket.io, 首先需要与后端建立连接
|
||||
|
||||
```js
|
||||
import IO from 'socket.io-client';
|
||||
const socket = new IO(serverAddrress, options);
|
||||
```
|
||||
|
||||
接口调用格式为
|
||||
|
||||
```js
|
||||
socket.emit(event, data, callback);
|
||||
```
|
||||
|
||||
参数说明
|
||||
|
||||
- event {string} 接口名/事件名
|
||||
- data {object} 接口入参
|
||||
- callback {string|object => void} 接口回调, 返回 string 表示接口失败, string 内容为失败原因, 反正 object 表示接口成功, 里面包含返回数据
|
||||
|
||||
## 返回数据结构定义
|
||||
|
||||
### User
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
username, // {string} 用户名
|
||||
avatar, // {string} 头像
|
||||
groups, // {[Group]} 群组列表
|
||||
friends, // {[User]} 好友列表
|
||||
token, // {string} 免密登录token
|
||||
isAdmin, // {boolean} 是否为管理员
|
||||
}
|
||||
```
|
||||
|
||||
### Group
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
name, // {string} 群组名
|
||||
avatar, // {string} 头像
|
||||
creator, // {User ID} 群主id
|
||||
isDefault, // {boolean} 是否为默认群
|
||||
members, // {[User]} 成员列表
|
||||
messages, // {[Message]} 消息列表
|
||||
}
|
||||
```
|
||||
|
||||
### Message
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
from, // {User} 发送者
|
||||
to, // {string} 群聊: 群id, 私聊: 两人id拼接, 按字符串比较, 小的在前
|
||||
type, // {string} 消息类型 ['text', 'image', 'code', 'invite']
|
||||
content, // {string} 消息内容
|
||||
}
|
||||
```
|
||||
|
||||
## 接口列表
|
||||
|
||||
### 用户注册
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'register',
|
||||
{
|
||||
username, // {string} 用户名
|
||||
password, // {string} 密码
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 用户登录
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'login',
|
||||
{
|
||||
username, // {string} 用户名
|
||||
password, // {string} 密码
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 免密登录 / 断线重连
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'loginByToken',
|
||||
{
|
||||
token, // {string} 免密登录token
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 游客登录
|
||||
|
||||
游客仅能获取到默认群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'guest',
|
||||
{
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(defaultGroup) => {}, // {Group} 默认群组数据
|
||||
);
|
||||
```
|
||||
|
||||
### 修改头像
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeAvatar',
|
||||
{
|
||||
avatar, // {string} 新头像url
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 添加好友
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'addFriend',
|
||||
{
|
||||
userId, // {User ID} 目标的id
|
||||
},
|
||||
(friend) => {}, // {User} 好友信息
|
||||
);
|
||||
```
|
||||
|
||||
### 删除好友
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'deleteFriend',
|
||||
{
|
||||
userId, // {User ID} 目标的id
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 修改密码
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changePassword',
|
||||
{
|
||||
oldPassword, // {string} 旧密码
|
||||
newPassword, // {string} 新密码
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 修改用户名
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeUsername',
|
||||
{
|
||||
username, // {string} 新用户名
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 重置指定用户密码
|
||||
|
||||
仅管理员可调用
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'resetUserPassword',
|
||||
{
|
||||
username, // {string} 新用户名
|
||||
},
|
||||
(data) => { // {Object} 返回数据
|
||||
data.newPassword, // {string} 新密码
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 发送消息
|
||||
|
||||
通过 to 字段判断是发送给群, 还是发送给个人
|
||||
发送群的话, to 就是群 id
|
||||
发送个人的话, to 就是两个人的 id 拼接, 按字符串比较结果, 小的在前大的在后
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'sendMessage',
|
||||
{
|
||||
to, // {string} 目标群组, 或者俩用户id拼接结果
|
||||
type, // {string} 消息类型
|
||||
content, // {string} 消息内容
|
||||
},
|
||||
(message) => {}, // {Message} 新消息
|
||||
);
|
||||
```
|
||||
|
||||
### 获取联系人最后消息
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getLinkmansLastMessages',
|
||||
{
|
||||
linkmans, // {[string]} 联系人id列表, 与to同规则
|
||||
},
|
||||
(messages) => {}, // {object} 所有联系人的最后消息, key: 联系人id, value: [Message] 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取联系人历史消息
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getLinkmanHistoryMessages',
|
||||
{
|
||||
linkmanId, // {string} 联系人id
|
||||
existCount, // {number} 已有消息数量
|
||||
},
|
||||
(messages) => {}, // {[Message]} 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取默认群组的历史消息
|
||||
|
||||
不需要登录态
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getDefaultGroupHistoryMessages',
|
||||
{
|
||||
existCount, // {number} 已有消息数量
|
||||
},
|
||||
(messages) => {}, // {[Message]} 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 创建群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'createGroup',
|
||||
{
|
||||
name, // {string} 群组名
|
||||
},
|
||||
(group) => {}, // {Group} 新创建的群组
|
||||
);
|
||||
```
|
||||
|
||||
### 加入群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'joinGroup',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
(group) => {}, // {Group} 新创建的群组
|
||||
);
|
||||
```
|
||||
|
||||
### 退出群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'leaveGroup',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取群组在线用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getGroupOnlineMembers',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
(users) => {}, // {[User]} 在线用户列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取默认群组在线用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getDefaultGroupOnlineMembers',
|
||||
{},
|
||||
(users) => {}, // {[User]} 在线用户列表
|
||||
);
|
||||
```
|
||||
|
||||
### 修改群头像
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeGroupAvatar',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
avatar, // {string} 新头像url
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取七牛前端文件上传 token
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'uploadToken',
|
||||
{ },
|
||||
(data) => {
|
||||
// 服务端支持七牛
|
||||
data.token, // 上传token
|
||||
data.urlPrefix, // 文件上传后的路径前缀
|
||||
|
||||
// 服务端不支持七牛
|
||||
data.useUploadFile, // 不支持上传七牛, 需要客户端调用 uploadFile 上传文件到服务端
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 搜索用户/群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'search',
|
||||
{
|
||||
keywords, // {string} 搜索关键字
|
||||
},
|
||||
(data) => {
|
||||
data.users, // {[User]} 命中的用户
|
||||
data.groups, // {[Group]} 命中的群组
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 搜索表情包
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'searchExpression',
|
||||
{
|
||||
keywords, // {string} 搜索关键字
|
||||
},
|
||||
(imageUrls) => {}, // {[string]} 图片列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取百度语言合成 token
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getBaiduToken',
|
||||
{ },
|
||||
(data) => {
|
||||
data.token, // {string} token
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 封禁用户
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'sealUser',
|
||||
{
|
||||
username, // {string} 要封禁的用户名
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取封禁用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getSealList',
|
||||
{},
|
||||
(users) => {}, // {[string]} 被封禁的用户名列表
|
||||
);
|
||||
```
|
||||
|
||||
### 上传文件到服务端
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'uploadFile',
|
||||
{
|
||||
fileName, // {string} 文件名
|
||||
file, // {blob} 文件内容, blob格式
|
||||
},
|
||||
(data) => {
|
||||
data.url, // 文件url
|
||||
},
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
id: app
|
||||
title: Fiora App
|
||||
sidebar_label: Fiora App
|
||||
---
|
||||
|
||||
Fiora app is developed with [expo](https://expo.io/) and [react-native](https://reactnative.dev/). Support Android and iOS systems
|
||||
|
||||
## Download App
|
||||
|
||||
### Android
|
||||
|
||||
Click link or scan qrcode to download APK
|
||||
|
||||
[https://cdn.suisuijiang.com/fiora.apk](https://cdn.suisuijiang.com/fiora.apk)
|
||||
|
||||

|
||||
|
||||
### iOS
|
||||
|
||||
The iOS app is being submitted to the app store for review. You can now install unreviewed apps through testflight. Please contact 碎碎酱 or send an email to <yinxinmac@icloud.com>. Please attach your apple ID
|
||||
|
||||
## Hot to run
|
||||
|
||||
1. Install expo `yarn global add expo-cli`
|
||||
2. Install dependencies `yarn install`
|
||||
3. Start compilation `expo start`
|
||||
4. According to the console prompt, run the app in the simulator or real device
|
||||
|
||||
For more information, please see [https://docs.expo.io/](https://docs.expo.io/)
|
||||
|
||||
## Build Standalone App
|
||||
|
||||
Please refer to <https://docs.expo.io/distribution/building-standalone-apps/>
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
id: changelog
|
||||
title: Change Log
|
||||
sidebar_label: Change Log
|
||||
---
|
||||
|
||||
## 2021-6-24
|
||||
|
||||
- Support user names and user tags with Japanese characters
|
||||
|
||||
## 2021-5-11
|
||||
|
||||
- Use Aliyun OSS to replace Qiniu CDN
|
||||
|
||||
## 2021-3-24
|
||||
|
||||
- Fix the problem that the search function allows regular expression matching
|
||||
|
||||
## 2021-3-14
|
||||
|
||||
- Support the server to calculate the number of unread messages
|
||||
|
||||
## 2021-3-2
|
||||
|
||||
- When identifying the url in the message, support host as localhost or ip
|
||||
|
||||
## 2021-3-1
|
||||
|
||||
- No longer limit the number of groups created by the administrator
|
||||
|
||||
## 2021-2-28
|
||||
|
||||
- Multiple users use the same notification token
|
||||
|
||||
## 2021-2-27
|
||||
|
||||
- Modify app notification content
|
||||
- Messages sent by yourself no longer push notification to yourself
|
||||
- The progress bar is displayed when the webpack build production environment
|
||||
|
||||
## 2021-2-25
|
||||
|
||||
- Support push notification to fiora app
|
||||
|
||||
## 2021-2-21
|
||||
|
||||
- **Important** Fix the wrong logic of judging whether it is an administrator on the server side. Treat everyone as an administrator
|
||||
|
||||
## 2021-2-17
|
||||
|
||||
- Support sharing groups externally
|
||||
|
||||
## 2021-1-26
|
||||
|
||||
- File message size calculation error
|
||||
|
||||
## 2021-1-22
|
||||
|
||||
- A single ip can register up to 3 accounts within 24 hours
|
||||
|
||||
## 2020-12-17
|
||||
|
||||
- Support search expressions by input content. It is disabled default and you can enable it in setting
|
||||
|
||||
- Only limit send message frequency
|
||||
|
||||
## 2020-12-08
|
||||
|
||||
- **Breaking!!!** Refactor to use redis cache instead of memory variable cache. So you should run redis first before start fiora
|
||||
|
||||
## 2020-11-15
|
||||
|
||||
- Refactor to use webpack plugin to generate service worker script
|
||||
- Refacotr or add server scripts
|
||||
|
||||
## 2020-11-14
|
||||
|
||||
- Adapt to ios full screen devices
|
||||
|
||||
## 2020-11-12
|
||||
|
||||
- Support multiple administrators
|
||||
- Add getUserId and deleteUser scripts
|
||||
|
||||
## 2020-11-08
|
||||
|
||||
- Support to withdraw self's message
|
||||
|
||||
## 2020-11-07
|
||||
|
||||
- Support send file directly
|
||||
- Support display linkman realtime info. About user online status and group online members count
|
||||
|
||||
- Refactor webpack build config
|
||||
|
||||
- Fix the issue of right click on image viewer to copy image will close it
|
||||
|
||||
## 2020-11-04
|
||||
|
||||
- **Breaking!!!** Modify the config files. It no longer supports modifying config items through command line params
|
||||
- Remove pm2 ecosystem config and deploy shell script
|
||||
|
||||
## 2020-11-03
|
||||
|
||||
- Rename some npm scripts name
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: config
|
||||
title: Config
|
||||
sidebar_label: Config
|
||||
---
|
||||
|
||||
Server configuration `config/server.ts`
|
||||
Client configuration `config/client.ts`
|
||||
|
||||
Compared to directly modifying the configuration file, it is recommended to use environment variables to modify the configuration
|
||||
Create a `.env` file in the fiora root directory and enter `key=value` key-value pair (one per line) to modify the configuration. For example, modify the port number `Port=8888`
|
||||
|
||||
## Server Config
|
||||
|
||||
**Modifying the server configuration requires restarting the application**
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
| ------------------ | ------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| Host | string | your ip | backend server host |
|
||||
| Port | number | 9200 | backend server port |
|
||||
| Database | string | mongodb://localhost:27017/fiora | mongodbb address |
|
||||
| RedisHost | string | localhost | redis host |
|
||||
| RedisPort | number | 6379 | redis port |
|
||||
| JwtSecret | string | jwtSecret (Modify it to ensure safety) | jwt token encryption secret |
|
||||
| MaxGroupCount | number | 3 | Maximum number of groups created per user |
|
||||
| AllowOrigin | string | null | The list of allowed client origins. If null, all origins are allowed. Multiple values separated by comma |
|
||||
| tokenExpiresTime | number | 2592000000 (30days) | login token expires time |
|
||||
| Administrator | string | '' | Administrator userId list. Multiple values separated by comma |
|
||||
| DisableRegister | boolean | false | Disable register |
|
||||
| DisableCreateGroup | boolean | false | Disable create group |
|
||||
| ALIYUN_OSS | boolean | false | enable to use aliyun OSS |
|
||||
| ACCESS_KEY_ID | string | '' | aliyun OSS access key id. reference: https://help.aliyun.com/document_detail/48699.html |
|
||||
| ACCESS_KEY_SECRET | string | '' | aliyun OSS access key secret. reference like ACCESS_KEY_ID |
|
||||
| ROLE_ARN | string | '' | aliyun OSS RoleARN. reference: https://help.aliyun.com/document_detail/28649.html |
|
||||
| REGION | string | '' | aliyun OSS region. example: `oss-cn-zhangjiakou` |
|
||||
| BUCKET | string | '' | aliyun OSS bucket name |
|
||||
| ENDPOINT | string | '' | aliyun OSS domain. example: `cdn.suisuijiang.com` |
|
||||
|
||||
## Client Config
|
||||
|
||||
**Modifying the client configuration requires rebuilding the client**
|
||||
|
||||
| Key | Type | Default | Description |
|
||||
| ---------------------- | ------- | --------------- | ------------------------------------------------------------ |
|
||||
| Server | string | / | Server address of the client connection |
|
||||
| MaxImageSize | number | 3145728 (3MB) | The maximum image size that the client can upload |
|
||||
| MaxBackgroundImageSize | number | 5242880 (5MB) | The maximum background image size that the client can upload |
|
||||
| MaxAvatarSize | number | 1572864 (1.5MB) | The maximum avatar image size that the client can upload |
|
||||
| MaxFileSize | number | 10485760 (10MB) | The maximum file size that the client can upload |
|
||||
| DefaultTheme | string | cool | default theme |
|
||||
| Sound | string | default | default notification sound |
|
||||
| TagColorMode | string | fixedColor | default tag color mode |
|
||||
| FrontendMonitorAppId | string | fixedColor | appId of monitor <https://yueying.effirst.com/index> |
|
||||
| DisableDeleteMessage | boolean | false | disable user delete messages |
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
id: faq
|
||||
title: FAQ
|
||||
sidebar_label: FAQ
|
||||
---
|
||||
|
||||
## How to set up an administrator
|
||||
|
||||
1. Get user id. reference [getUserId](/docs/script#getuserid)
|
||||
2. Set `Administrator` in config to be administrator userId.
|
||||
3. Restart the server
|
||||
|
||||
## How to modify the default group name
|
||||
|
||||
reference [updateDefaultGroupname](/docs/script#updatedefaultgroupname)
|
||||
|
||||
## How to custom domain name
|
||||
|
||||
Recommend to use nginx reverse proxy
|
||||
|
||||
Example config, **Please modify the configuration of the comment item**
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
# Change to your domain name
|
||||
server_name fiora.suisuijiang.com;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://localhost:9200;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
HTTPS + HTTP 2.0 config
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
# Change to your domain name
|
||||
server_name fiora.suisuijiang.com;
|
||||
return 301 https://fiora.suisuijiang.com$request_uri;
|
||||
}
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
# Change to your domain name
|
||||
server_name fiora.suisuijiang.com;
|
||||
|
||||
ssl on;
|
||||
# Modify to your ssl certificate location
|
||||
ssl_certificate ./ssl/fiora.suisuijiang.com.crt;
|
||||
ssl_certificate_key ./ssl/fiora.suisuijiang.com.key;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://localhost:9200;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## How to Disable register, manual account assignment
|
||||
|
||||
Set `DisableRegister` in config to be true. Restart the server to take effect
|
||||
|
||||
Use scripts to manually register new users. Reference [register](/docs/script#register)
|
||||
|
||||
## How to delete user
|
||||
|
||||
Reference [deleteUser](/docs/script#deleteuser)
|
||||
|
||||
## The client throw an error "调用失败,处于萌新阶段"
|
||||
|
||||
In order to prevent newly registered users from sending messages randomly, users whose registration time is less than 24 hours can only send 5 messages per minute.
|
||||
|
||||
## An error is throwed when executing the command. "Couldn't find a package.json file in xxx"
|
||||
|
||||
First cd to the fiora root directory, and then execute the corresponding command
|
||||
|
||||
## Why the modified configuration does not take effect
|
||||
|
||||
1. First confirm whether the configuration modification is correct
|
||||
-If you modify the configuration file directly, please make sure that the modified part of the syntax and format is correct
|
||||
-If you modify the configuration through the .env file, please make sure the format is correct
|
||||
2. After modifying the configuration
|
||||
-If you modify the server configuration, you need to restart the server
|
||||
-If you modify the client configuration, you need to rebuild the client
|
||||
|
||||
## How to rebuild the web client
|
||||
|
||||
`yarn build:web`
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
id: getting-start
|
||||
title: Getting Start
|
||||
sidebar_label: Getting Start
|
||||
---
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
fiora is an interesting chat application. It is developed based on node.js, mongodb, react and socket.io technologies
|
||||
|
||||
The project started at [2015-11-04](https://github.com/yinxin630/chatroom-with-sails/commit/0a032372727550b8b4087f24ac299de03b677b9f)
|
||||
|
||||
Online address: [https://fiora.suisuijiang.com/](https://fiora.suisuijiang.com/)
|
||||
Android / iOS app: [https://github.com/yinxin630/fiora-app](https://github.com/yinxin630/fiora-app)
|
||||
|
||||
## Functions
|
||||
|
||||
1. Register an account and log in, it can save your data for a long time
|
||||
2. Join an existing group or create your own group to communicate with everyone
|
||||
3. Chat privately with anyone and add them as friends
|
||||
4. Multiple message types, including text / emoticons / pictures / codes / files / commands, you can also search for emoticons
|
||||
5. Push notification when you receive a new message, you can customize the notification ringtone, and it can also read the message out
|
||||
6. Choose the theme you like, and you can set it as any wallpaper and theme color you like
|
||||
7. Set up an administrator to manage users
|
||||
|
||||
## Screenshot
|
||||
|
||||
<img alt="PC screenshot" src={useBaseUrl('img/screenshots/screenshot-pc.png')} style={{'max-width':'800px'}} />
|
||||
<img alt="Mobile screenshot" src={useBaseUrl('img/screenshots/screenshot-phone.png')} style={{'max-height':'667px'}} />
|
||||
|
||||
## Directory
|
||||
|
||||
|-- [.githubb] // github actions
|
||||
|-- [.vscode] // vscode workspace config
|
||||
|-- [bin] // server scripts
|
||||
|-- [build] // webpack config
|
||||
|-- [client] // web client
|
||||
|-- [config] // application configs
|
||||
|-- [dist] // client buid output directory
|
||||
|-- [docs] // document
|
||||
|-- [public] // server static resources
|
||||
|-- [server] // server
|
||||
|-- [test] // unit test
|
||||
|-- [types] // typescript types
|
||||
|-- [utils] // util functions
|
||||
|-- .babelrc // babel config
|
||||
|-- .eslintignore // eslint ignore list
|
||||
|-- .eslintrc // eslint config
|
||||
|-- .gitignore // git ignore
|
||||
|-- .nodemonrc // nodemon config
|
||||
|-- .prettierrc // prettier config
|
||||
|-- Dockerfile // docker file
|
||||
|-- LICENSE // fiora license
|
||||
|-- docker-compose.yaml // docker compose config
|
||||
|-- jest.*.sj // jest config
|
||||
|-- package.json // npm
|
||||
|-- tsconfig.json // typescript config
|
||||
|-- yarn.lock // yarn
|
||||
...
|
||||
|
||||
## Contribution
|
||||
|
||||
If you want to add functionality or fix bugs, please follow the process below:
|
||||
|
||||
1. Fork this repository and clone the fork post to the local
|
||||
2. Installation dependencies `yarn install`
|
||||
3. Modify the code and confirm it is bug free
|
||||
4. Submit code, if eslint has reported error, please repair it and submit it again.
|
||||
5. Create a pull request
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
id: install
|
||||
title: Install
|
||||
sidebar_label: Install
|
||||
---
|
||||
|
||||
## Environmental Preparation
|
||||
|
||||
To run Fiora, you need Node.js(recommend v14 LTS version), MongoDB and redis
|
||||
|
||||
- Install Node.js
|
||||
- Official website <https://nodejs.org/en/download/>
|
||||
- It is recommended to use nvm to install Node.js
|
||||
- Install nvm <https://github.com/nvm-sh/nvm#install--update-script>
|
||||
- Install Node.js via nvm <https://github.com/nvm-sh/nvm#usage>
|
||||
- Install MongoDB
|
||||
- Official website <https://docs.mongodb.com/manual/installation/#install-mongodb>
|
||||
- Install redis
|
||||
- Official website <https://docs.mongodb.com/manual/installation/#install-mongodb>
|
||||
|
||||
Recommended to running on Linux or MacOS systems
|
||||
|
||||
## How to run
|
||||
|
||||
1. Clone the project `git clone https://github.com/yinxin630/fiora.git -b master`
|
||||
2. Ensure you have install [yarn](https://www.npmjs.com/package/yarn) before, if not please run `npm install -g yarn`
|
||||
3. Install project dependencies `yarn install`
|
||||
4. Build client `yarn build:web`
|
||||
5. Config JwtSecret `echo "JwtSecret=<string>" > .env2`. Change `<string>` to a secret text
|
||||
6. Start the server `yarn start`
|
||||
7. Open `http://[ip]:[port]`(such as `http://127.0.0.1:9200`) in browser
|
||||
|
||||
### Run in the background
|
||||
|
||||
Using `yarn start` to run the server will stop running after disconnecting the ssh connection, it is recommended to use pm2 to run
|
||||
|
||||
```bash
|
||||
# install pm2
|
||||
npm install -g pm2
|
||||
|
||||
# use pm2 to run fiora
|
||||
pm2 start yarn --name fiora -- start
|
||||
|
||||
# view pm2 apps status
|
||||
pm2 ls
|
||||
|
||||
# view pm2 fiora logging
|
||||
pm2 logs fiora
|
||||
```
|
||||
|
||||
### Run With Develop Mode
|
||||
|
||||
1. Start the server `yarn dev:server`
|
||||
2. Start the client `yarn dev:web`
|
||||
3. Open `http://localhost:8080` in browser
|
||||
|
||||
### Running on the docker
|
||||
|
||||
First install docker <https://docs.docker.com/install/>
|
||||
|
||||
#### Run directly from the DockerHub image
|
||||
|
||||
```bash
|
||||
# Pull mongo
|
||||
docker pull mongo
|
||||
|
||||
# Pull redis
|
||||
docker pull redis
|
||||
|
||||
# Pull fiora
|
||||
docker pull suisuijiang/fiora
|
||||
|
||||
# Create a virtual network
|
||||
docker network create fiora-network
|
||||
|
||||
# Run mongodB
|
||||
docker run --name fioradb -p 27017:27017 --network fiora-network mongo
|
||||
|
||||
# Run redis
|
||||
docker run --name fioraredis -p 6379:6379 --network fiora-network redis
|
||||
|
||||
# Run fiora
|
||||
docker run --name fiora -p 9200:9200 --network fiora-network -e Database=mongodb://fioradb:27017/fiora -e RedisHost=fioraredis suisuijiang/fiora
|
||||
```
|
||||
|
||||
#### Local build image and run
|
||||
|
||||
1. Clone the project to the local `git clone https://github.com/yinxin630/fiora.git -b master`
|
||||
2. Build the image `docker-compose build --no-cache --force-rm`
|
||||
3. Run it `docker-compose up`
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: script
|
||||
title: Script
|
||||
sidebar_label: Script
|
||||
---
|
||||
|
||||
Fiora has a built-in command line tool to manage the server. Execute `fiora` to view the tool
|
||||
|
||||
**Note!** Most of these scripts will directly modify the database. It is recommended (but not necessary) to backup the database in advance and stop the server before executing
|
||||
|
||||
## deleteMessages
|
||||
|
||||
`fiora deleteMessages`
|
||||
|
||||
Delete all historical message records, if the message pictures and files are stored on the server, they can also be deleted together
|
||||
|
||||
## deleteTodayRegisteredUsers
|
||||
|
||||
`fiora deleteTodayRegisteredUsers`
|
||||
|
||||
Delete all newly registered users on the day (based on server time)
|
||||
|
||||
## deleteUser
|
||||
|
||||
`fiora deleteUser [userId]`
|
||||
|
||||
Delete the specified user, delete its historical messages, exit the group that it has joined, and delete all its friends
|
||||
|
||||
## doctor
|
||||
|
||||
`fiora doctor`
|
||||
|
||||
Check the server configuration and status, which can be used to locate the cause of the server startup failure
|
||||
|
||||
## fixUsersAvatar
|
||||
|
||||
`fiora fixUsersAvatar`
|
||||
|
||||
Fix user error avatar path, please modify the script judgment logic according to your actual situation
|
||||
|
||||
## getUserId
|
||||
|
||||
`fiora getUserId [username]`
|
||||
|
||||
Get the userId of the specified user name
|
||||
|
||||
## register
|
||||
|
||||
`fiora register [username] [password]`
|
||||
|
||||
Register new users, when registration is prohibited, the administrator can register new users through it
|
||||
|
||||
## updateDefaultGroupName
|
||||
|
||||
`fiora updateDefaultGroupName [newName]`
|
||||
|
||||
Update default group name
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"link.title.Docs": {
|
||||
"message": "Docs"
|
||||
},
|
||||
"link.item.label.Overview": {
|
||||
"message": "Overview"
|
||||
},
|
||||
|
||||
"link.title.Community": {
|
||||
"message": "Community"
|
||||
},
|
||||
"link.item.label.Feedback": {
|
||||
"message": "Join Chat"
|
||||
},
|
||||
"link.item.label.Issues": {
|
||||
"message": "Submit Issue"
|
||||
},
|
||||
|
||||
"link.title.More": {
|
||||
"message": "More"
|
||||
},
|
||||
"link.item.label.Author": {
|
||||
"message": "About Author"
|
||||
},
|
||||
"link.item.label.GitHub": {
|
||||
"message": "GitHub"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"item.label.Docs": {
|
||||
"message": "Docs"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"Title": {
|
||||
"message": "fiora"
|
||||
},
|
||||
"TagLine": {
|
||||
"message": "一个有趣的开源聊天应用"
|
||||
},
|
||||
"Keywords": {
|
||||
"message": "fiora, fiora 文档, node.js, 聊天室"
|
||||
},
|
||||
"Description": {
|
||||
"message": "这是 fiora 文档网站, fiora 是一个有趣的开源聊天室应用"
|
||||
},
|
||||
|
||||
"Richness": {
|
||||
"message": "fiora 包括后端、前端、安卓和 iOS App"
|
||||
},
|
||||
"Cross Platform": {
|
||||
"message": "fiora 基于 node.js 开发, 支持 Windows / Linux / macOS 等操作系统"
|
||||
},
|
||||
"Open Source": {
|
||||
"message": "fiora 遵循 MIT 开源许可"
|
||||
},
|
||||
|
||||
"Join Chat Title": {
|
||||
"message": "加入聊天"
|
||||
},
|
||||
"Join Chat Content": {
|
||||
"message": "注册一个账号加入聊天, 加入或者新的群组, 和有趣的陌生人私聊并加为好友, 你的账号和消息会永久保留"
|
||||
},
|
||||
"Rich Feature Title": {
|
||||
"message": "丰富的功能"
|
||||
},
|
||||
"Rich Feature Content": {
|
||||
"message": "你可以发送文本、表情、图片、代码和文件给其他人, 你还可以撤回已发送的消息, 另外你还可以修改用户名和头像, 最令人兴奋的是你可以选择或者自定义不同的主题"
|
||||
},
|
||||
"Deploy By Yourself Title": {
|
||||
"message": "自己部署"
|
||||
},
|
||||
"Deploy By Yourself Content": {
|
||||
"message": "fiora 是一个开源项目, 你可以克隆源码并部署到自己的服务器, 支持 windows / Linux and macOS 操作系统, 但是推荐您部署到 Linux 服务器上"
|
||||
},
|
||||
|
||||
"Interested": {
|
||||
"message": "你是否非常感兴趣?"
|
||||
},
|
||||
"Getting Start": {
|
||||
"message": "查看文档"
|
||||
},
|
||||
|
||||
"Try It Now": {
|
||||
"message": "去体验看看"
|
||||
},
|
||||
|
||||
"View Docs": {
|
||||
"message": "查看文档"
|
||||
},
|
||||
"DocsUrl": {
|
||||
"message": "/fiora/zh-Hans/docs/getting-start/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
---
|
||||
id: api
|
||||
title: 接口
|
||||
sidebar_label: 接口
|
||||
---
|
||||
|
||||
## 如何调用接口
|
||||
|
||||
fiora 后端基于 socket.io, 首先需要与后端建立连接
|
||||
|
||||
```js
|
||||
import IO from 'socket.io-client';
|
||||
const socket = new IO(serverAddrress, options);
|
||||
```
|
||||
|
||||
接口调用格式为
|
||||
|
||||
```js
|
||||
socket.emit(event, data, callback);
|
||||
```
|
||||
|
||||
参数说明
|
||||
|
||||
- event {string} 接口名/事件名
|
||||
- data {object} 接口入参
|
||||
- callback {string|object => void} 接口回调, 返回 string 表示接口失败, string 内容为失败原因, 反正 object 表示接口成功, 里面包含返回数据
|
||||
|
||||
## 返回数据结构定义
|
||||
|
||||
### User
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
username, // {string} 用户名
|
||||
avatar, // {string} 头像
|
||||
groups, // {[Group]} 群组列表
|
||||
friends, // {[User]} 好友列表
|
||||
token, // {string} 免密登录token
|
||||
isAdmin, // {boolean} 是否为管理员
|
||||
}
|
||||
```
|
||||
|
||||
### Group
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
name, // {string} 群组名
|
||||
avatar, // {string} 头像
|
||||
creator, // {User ID} 群主id
|
||||
isDefault, // {boolean} 是否为默认群
|
||||
members, // {[User]} 成员列表
|
||||
messages, // {[Message]} 消息列表
|
||||
}
|
||||
```
|
||||
|
||||
### Message
|
||||
|
||||
```js
|
||||
{
|
||||
_id, // {string} id
|
||||
from, // {User} 发送者
|
||||
to, // {string} 群聊: 群id, 私聊: 两人id拼接, 按字符串比较, 小的在前
|
||||
type, // {string} 消息类型 ['text', 'image', 'code', 'invite']
|
||||
content, // {string} 消息内容
|
||||
}
|
||||
```
|
||||
|
||||
## 接口列表
|
||||
|
||||
### 用户注册
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'register',
|
||||
{
|
||||
username, // {string} 用户名
|
||||
password, // {string} 密码
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 用户登录
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'login',
|
||||
{
|
||||
username, // {string} 用户名
|
||||
password, // {string} 密码
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 免密登录 / 断线重连
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'loginByToken',
|
||||
{
|
||||
token, // {string} 免密登录token
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(user) => {}, // {User} 用户数据
|
||||
);
|
||||
```
|
||||
|
||||
### 游客登录
|
||||
|
||||
游客仅能获取到默认群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'guest',
|
||||
{
|
||||
os, // {string} 操作系统
|
||||
browser, // {string} 浏览器
|
||||
environment, // {string} 环境信息
|
||||
},
|
||||
(defaultGroup) => {}, // {Group} 默认群组数据
|
||||
);
|
||||
```
|
||||
|
||||
### 修改头像
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeAvatar',
|
||||
{
|
||||
avatar, // {string} 新头像url
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 添加好友
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'addFriend',
|
||||
{
|
||||
userId, // {User ID} 目标的id
|
||||
},
|
||||
(friend) => {}, // {User} 好友信息
|
||||
);
|
||||
```
|
||||
|
||||
### 删除好友
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'deleteFriend',
|
||||
{
|
||||
userId, // {User ID} 目标的id
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 修改密码
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changePassword',
|
||||
{
|
||||
oldPassword, // {string} 旧密码
|
||||
newPassword, // {string} 新密码
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 修改用户名
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeUsername',
|
||||
{
|
||||
username, // {string} 新用户名
|
||||
},
|
||||
() => {}, // {Object} 返回空对象
|
||||
);
|
||||
```
|
||||
|
||||
### 重置指定用户密码
|
||||
|
||||
仅管理员可调用
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'resetUserPassword',
|
||||
{
|
||||
username, // {string} 新用户名
|
||||
},
|
||||
(data) => { // {Object} 返回数据
|
||||
data.newPassword, // {string} 新密码
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 发送消息
|
||||
|
||||
通过 to 字段判断是发送给群, 还是发送给个人
|
||||
发送群的话, to 就是群 id
|
||||
发送个人的话, to 就是两个人的 id 拼接, 按字符串比较结果, 小的在前大的在后
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'sendMessage',
|
||||
{
|
||||
to, // {string} 目标群组, 或者俩用户id拼接结果
|
||||
type, // {string} 消息类型
|
||||
content, // {string} 消息内容
|
||||
},
|
||||
(message) => {}, // {Message} 新消息
|
||||
);
|
||||
```
|
||||
|
||||
### 获取联系人最后消息
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getLinkmansLastMessages',
|
||||
{
|
||||
linkmans, // {[string]} 联系人id列表, 与to同规则
|
||||
},
|
||||
(messages) => {}, // {object} 所有联系人的最后消息, key: 联系人id, value: [Message] 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取联系人历史消息
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getLinkmanHistoryMessages',
|
||||
{
|
||||
linkmanId, // {string} 联系人id
|
||||
existCount, // {number} 已有消息数量
|
||||
},
|
||||
(messages) => {}, // {[Message]} 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取默认群组的历史消息
|
||||
|
||||
不需要登录态
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getDefaultGroupHistoryMessages',
|
||||
{
|
||||
existCount, // {number} 已有消息数量
|
||||
},
|
||||
(messages) => {}, // {[Message]} 消息列表
|
||||
);
|
||||
```
|
||||
|
||||
### 创建群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'createGroup',
|
||||
{
|
||||
name, // {string} 群组名
|
||||
},
|
||||
(group) => {}, // {Group} 新创建的群组
|
||||
);
|
||||
```
|
||||
|
||||
### 加入群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'joinGroup',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
(group) => {}, // {Group} 新创建的群组
|
||||
);
|
||||
```
|
||||
|
||||
### 退出群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'leaveGroup',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取群组在线用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getGroupOnlineMembers',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
},
|
||||
(users) => {}, // {[User]} 在线用户列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取默认群组在线用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getDefaultGroupOnlineMembers',
|
||||
{},
|
||||
(users) => {}, // {[User]} 在线用户列表
|
||||
);
|
||||
```
|
||||
|
||||
### 修改群头像
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'changeGroupAvatar',
|
||||
{
|
||||
groupId, // {Group ID} 目标群id
|
||||
avatar, // {string} 新头像url
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取七牛前端文件上传 token
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'uploadToken',
|
||||
{ },
|
||||
(data) => {
|
||||
// 服务端支持七牛
|
||||
data.token, // 上传token
|
||||
data.urlPrefix, // 文件上传后的路径前缀
|
||||
|
||||
// 服务端不支持七牛
|
||||
data.useUploadFile, // 不支持上传七牛, 需要客户端调用 uploadFile 上传文件到服务端
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 搜索用户/群组
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'search',
|
||||
{
|
||||
keywords, // {string} 搜索关键字
|
||||
},
|
||||
(data) => {
|
||||
data.users, // {[User]} 命中的用户
|
||||
data.groups, // {[Group]} 命中的群组
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 搜索表情包
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'searchExpression',
|
||||
{
|
||||
keywords, // {string} 搜索关键字
|
||||
},
|
||||
(imageUrls) => {}, // {[string]} 图片列表
|
||||
);
|
||||
```
|
||||
|
||||
### 获取百度语言合成 token
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getBaiduToken',
|
||||
{ },
|
||||
(data) => {
|
||||
data.token, // {string} token
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 封禁用户
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'sealUser',
|
||||
{
|
||||
username, // {string} 要封禁的用户名
|
||||
},
|
||||
() => {}, // {object} 返回空数据
|
||||
);
|
||||
```
|
||||
|
||||
### 获取封禁用户列表
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'getSealList',
|
||||
{},
|
||||
(users) => {}, // {[string]} 被封禁的用户名列表
|
||||
);
|
||||
```
|
||||
|
||||
### 上传文件到服务端
|
||||
|
||||
```js
|
||||
socket.emit(
|
||||
'uploadFile',
|
||||
{
|
||||
fileName, // {string} 文件名
|
||||
file, // {blob} 文件内容, blob格式
|
||||
},
|
||||
(data) => {
|
||||
data.url, // 文件url
|
||||
},
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
id: app
|
||||
title: Fiora App
|
||||
sidebar_label: Fiora App
|
||||
---
|
||||
|
||||
fiora app 是基于 [expo](https://expo.io/) he [react-native](https://reactnative.dev/) 开发的, 支持 Android 和 iOS 系统
|
||||
|
||||
## 下载 App
|
||||
|
||||
### Android
|
||||
|
||||
点击链接或者扫描二维码下载 APK
|
||||
|
||||
[https://cdn.suisuijiang.com/fiora.apk](https://cdn.suisuijiang.com/fiora.apk)
|
||||
|
||||

|
||||
|
||||
### iOS
|
||||
|
||||
iOS app 已经提交给 App Store 审核了, 现在可以通过 testflight 来安装. 请联系碎碎酱或者发送邮件给 <yinxinmac@icloud.com>, 附上你的 Apple ID
|
||||
|
||||
## 如何运行
|
||||
|
||||
1. 安装 expo `yarn global add expo-cli`
|
||||
2. 安装依赖 `yarn install`
|
||||
3. 启动编译 `expo start`
|
||||
4. 根据控制台输出的提示, 在模拟器或者真实设备上运行 app
|
||||
|
||||
想要了解更多信息, 请查看 [https://docs.expo.io/](https://docs.expo.io/)
|
||||
|
||||
## 构建 App
|
||||
|
||||
请参考 <https://docs.expo.io/distribution/building-standalone-apps/>
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
id: changelog
|
||||
title: 更新日志
|
||||
sidebar_label: 更新日志
|
||||
---
|
||||
|
||||
## 2021-6-24
|
||||
|
||||
- 支持带有日文字符的用户名和用户标签
|
||||
|
||||
## 2021-5-11
|
||||
|
||||
- 使用阿里云 OSS 替代七牛 CDN
|
||||
|
||||
## 2021-3-24
|
||||
|
||||
- 修复搜索功能允许使用正则表达式匹配的问题
|
||||
|
||||
## 2021-3-14
|
||||
|
||||
- 支持服务端计算未读消息数量
|
||||
|
||||
## 2021-3-2
|
||||
|
||||
- 识别消息中的 URL 时, 支持 host 为 localhost 或者 ip
|
||||
|
||||
## 2021-3-1
|
||||
|
||||
- 管理员创建群组时, 不再限制数量
|
||||
|
||||
## 2021-2-28
|
||||
|
||||
- 多个用户可以使用相同的 notification token
|
||||
|
||||
## 2021-2-27
|
||||
|
||||
- 修改 app 通知内容
|
||||
- 自己发送的消息不再推送通知给自己
|
||||
- webpack 构建生成环境版本时显示进度条
|
||||
|
||||
## 2021-2-25
|
||||
|
||||
- 支持推送通知给 fiora app
|
||||
|
||||
## 2021-2-21
|
||||
|
||||
- **重要** 修复错误的服务端判断管理员的逻辑, 会将所有人当做管理员. 但是前端并不会展示管理员面板
|
||||
|
||||
## 2021-2-17
|
||||
|
||||
- 支持向 fiora 外部分享群组
|
||||
|
||||
## 2021-1-26
|
||||
|
||||
- 文件消息的文件大小计算错误
|
||||
|
||||
## 2021-1-22
|
||||
|
||||
- 一个 ip 在 24 小时内只允许创建三个账号
|
||||
|
||||
## 2020-12-17
|
||||
|
||||
- 支持根据输入框内容自动搜索表情, 该功能默认是关闭的, 可以在用户设置中打开
|
||||
|
||||
- 只限制发消息的频率
|
||||
|
||||
## 2020-12-08
|
||||
|
||||
- **兼容性!!!** 使用 redis 缓存来替代内存缓存, 所以你需要在运行 fiora 之前配置并启动 redis
|
||||
|
||||
## 2020-11-15
|
||||
|
||||
- 使用 webpack 插件来生成 service worker script
|
||||
- 重构并新增服务端脚本
|
||||
|
||||
## 2020-11-14
|
||||
|
||||
- 适配 iOS 全面屏设备
|
||||
|
||||
## 2020-11-12
|
||||
|
||||
- 支持设置多个管理员
|
||||
|
||||
## 2020-11-08
|
||||
|
||||
- 支持撤回自己发的消息
|
||||
|
||||
## 2020-11-07
|
||||
|
||||
- 支持发送文件
|
||||
- 支持展示实时(数据有 60s 缓存时间)的群组在线人数和用户在线状态
|
||||
|
||||
- 重构 webpack 构建配置
|
||||
|
||||
- 修复在图片查看大图时右键会关闭的问题
|
||||
|
||||
## 2020-11-04
|
||||
|
||||
- **兼容性!!!** 修改 config 文件配置方法, 不再支持通过命令行参数来设置
|
||||
|
||||
## 2020-11-03
|
||||
|
||||
- 重命名一部分 npm script 名
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
id: config
|
||||
title: 配置
|
||||
sidebar_label: 配置
|
||||
---
|
||||
|
||||
服务器配置 `config/server.ts`
|
||||
客户端配置 `config/client.ts`
|
||||
|
||||
相比于直接修改配置文件, 推荐用环境变量来修改配置
|
||||
在 fiora 根目录创建 `.env` 文件, 在里面填写 `key=value` 键值对(每行一个), 即可修改相应配置. 比如修改端口号 `Port=8888`
|
||||
|
||||
## 服务端配置
|
||||
|
||||
**修改服务端配置需要重启应用**
|
||||
|
||||
| Key | 类型 | 默认值 | 描述 |
|
||||
| ------------------ | ------- | ---------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| Host | string | your ip | 服务端 host |
|
||||
| Port | number | 9200 | 服务端端口号 |
|
||||
| Database | string | mongodb://localhost:27017/fiora | mongoDB 数据库地址 |
|
||||
| RedisHost | string | localhost | redis 地址主机名 |
|
||||
| RedisPort | number | 6379 | redis 端口 |
|
||||
| JwtSecret | string | jwtSecret (推荐修改它来保证安全性) | jwt token 加密 secret |
|
||||
| MaxGroupCount | number | 3 | 用户最大可以创建的群组个数 |
|
||||
| AllowOrigin | string | null | 允许的客户端 origin 列表, null 时允许所有 origin 连接, 多个值逗号分割 |
|
||||
| tokenExpiresTime | number | 2592000000 (30 天) | 登陆 token 过期时间 |
|
||||
| Administrator | string | '' | 管理员用户 id 列表, 多个值逗号分割 |
|
||||
| DisableRegister | boolean | false | 禁止注册账号 |
|
||||
| DisableCreateGroup | boolean | false | 禁止创建群组 |
|
||||
| ALIYUN_OSS | boolean | false | 启用阿里云 OSS |
|
||||
| ACCESS_KEY_ID | string | '' | 阿里云 OSS access key id. 参考: https://help.aliyun.com/document_detail/48699.html |
|
||||
| ACCESS_KEY_SECRET | string | '' | 阿里云 OSS access key secret. 参考和 ACCESS_KEY_ID 相同 |
|
||||
| ROLE_ARN | string | '' | 阿里云 OSS RoleARN. 参考: https://help.aliyun.com/document_detail/28649.html |
|
||||
| REGION | string | '' | 阿里云 OSS 地域. 例如: `oss-cn-zhangjiakou` |
|
||||
| BUCKET | string | '' | 阿里云 OSS bucket 名称 |
|
||||
| ENDPOINT | string | '' | 阿里云 OSS 域名. 例如: `cdn.suisuijiang.com` |
|
||||
|
||||
## 客户端配置
|
||||
|
||||
**修改客户端配置需要重新构建客户端**
|
||||
|
||||
| Key | 类型 | 默认值 | 描述 |
|
||||
| ---------------------- | ------- | --------------- | -------------------------------------------------- |
|
||||
| Server | string | / | 客户端要连接的服务端地址 |
|
||||
| MaxImageSize | number | 3145728 (3MB) | 客户端可以上传的最大图片大小 |
|
||||
| MaxBackgroundImageSize | number | 5242880 (5MB) | 客户端可以上传的最大背景图大小 |
|
||||
| MaxAvatarSize | number | 1572864 (1.5MB) | 客户端可以上传的最大头像图片大小 |
|
||||
| MaxFileSize | number | 10485760 (10MB) | 客户端可以上传的最大文件大小 |
|
||||
| DefaultTheme | string | cool | 默认主题 |
|
||||
| Sound | string | default | 默认通知音 |
|
||||
| TagColorMode | string | fixedColor | 默认标签颜色模式 |
|
||||
| FrontendMonitorAppId | string | fixedColor | 岳鹰监控 appId <https://yueying.effirst.com/index> |
|
||||
| DisableDeleteMessage | boolean | false | 禁止用户撤回消息 |
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
id: faq
|
||||
title: 问题解答
|
||||
sidebar_label: 问题解答
|
||||
---
|
||||
|
||||
## 如何设置管理员
|
||||
|
||||
1. 获取用户 id, 参考 [getUserId](/docs/script#getuserid)
|
||||
2. 修改 `Administrator` 配置项, 改为上一步获取的 id
|
||||
3. 重启服务端
|
||||
|
||||
## 如何修改默认群组名称
|
||||
|
||||
参考 [updateDefaultGroupName](/docs/script#updatedefaultgroupname)
|
||||
|
||||
## 如何自定义域名
|
||||
|
||||
推荐使用 nginx 反向代理
|
||||
|
||||
示例配置, **请修改注释项的配置**
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
# 修改为你的域名
|
||||
server_name fiora.suisuijiang.com;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://localhost:9200;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
配置 HTTPS + HTTP 2.0
|
||||
|
||||
```
|
||||
server {
|
||||
listen 80;
|
||||
# 修改为你的域名
|
||||
server_name fiora.suisuijiang.com;
|
||||
return 301 https://fiora.suisuijiang.com$request_uri;
|
||||
}
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
# 修改为你的域名
|
||||
server_name fiora.suisuijiang.com;
|
||||
|
||||
ssl on;
|
||||
# 修改为你的ssl证书位置
|
||||
ssl_certificate ./ssl/fiora.suisuijiang.com.crt;
|
||||
ssl_certificate_key ./ssl/fiora.suisuijiang.com.key;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
|
||||
ssl_prefer_server_ciphers on;
|
||||
|
||||
location / {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_http_version 1.1;
|
||||
proxy_pass http://localhost:9200;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 如何禁止注册, 手动分配账号
|
||||
|
||||
将 `DisableRegister` 配置项设置为 true, 重启服务器生效
|
||||
|
||||
使用脚本手动注册新用户. 参考 [register](/docs/script#register)
|
||||
|
||||
## 如何删除用户
|
||||
|
||||
参考 [deleteUser](/docs/script#deleteuser)
|
||||
|
||||
## 客户端报错 "调用失败,处于萌新阶段"
|
||||
|
||||
为了避免新注册的用户乱发消息刷屏, 注册时间未满 24 小时的用户每分钟限制只能发 5 条消息
|
||||
|
||||
## 执行命令时报错 "Couldn't find a package.json file in xxx"
|
||||
|
||||
先 cd 到 fiora 根目录下, 再执行相应命令
|
||||
|
||||
## 为什么修改配置不生效
|
||||
|
||||
1. 先确认配置修改是否正确
|
||||
- 如果是直接修改配置文件, 请确认修改的部分语法和格式正确
|
||||
- 如果是通过 .env 文件修改配置, 请确认格式正确
|
||||
2. 修改配置后
|
||||
- 如果修改的是服务端配置, 需要重启服务端
|
||||
- 如果修改的是客户端配置, 需要重新构建客户端
|
||||
|
||||
## 怎么重新构建客户端
|
||||
|
||||
`yarn build:web`
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
id: getting-start
|
||||
title: 入门指南
|
||||
sidebar_label: 入门指南
|
||||
---
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
fiora 是一款有趣的聊天应用. 基于 node.js, mongodb, react 和 socket.io 等技术开发
|
||||
|
||||
该项目起始于 [2015-11-04](https://github.com/yinxin630/chatroom-with-sails/commit/0a032372727550b8b4087f24ac299de03b677b9f)
|
||||
|
||||
在线地址: [https://fiora.suisuijiang.com/](https://fiora.suisuijiang.com/)
|
||||
安卓/iOS app: [https://github.com/yinxin630/fiora-app](https://github.com/yinxin630/fiora-app)
|
||||
|
||||
## 功能
|
||||
|
||||
1. 注册账号并登录, 可以长久保存你的数据
|
||||
2. 加入现有群组或者创建自己的群组, 来和大家交流
|
||||
3. 和任意人私聊, 并添加其为好友
|
||||
4. 多种消息类型, 包括文本 / 表情 / 图片 / 代码 / 文件 / 命令, 还可以搜索表情包
|
||||
5. 当收到新消息时推送通知, 可以自定义通知铃声, 还可以把消息读出来
|
||||
6. 选择你喜欢的主题, 并且可以设置为任何你喜欢的壁纸以及主题颜色
|
||||
7. 设置管理员来管理用户
|
||||
|
||||
## 运行截图
|
||||
|
||||
<img src={useBaseUrl('img/screenshots/screenshot-pc.png')} alt="PC" style={{'max-width':'800px'}} />
|
||||
<img src={useBaseUrl('img/screenshots/screenshot-phone.png')} alt="Phone" height="667" style={{'max-width':'667px'}} />
|
||||
|
||||
## 目录结构
|
||||
|
||||
|-- [.githubb] // github actions
|
||||
|-- [.vscode] // vscode 工作区配置
|
||||
|-- [bin] // 服务端脚本
|
||||
|-- [build] // webpack 配置
|
||||
|-- [client] // web 客户端
|
||||
|-- [config] // 应用配置
|
||||
|-- [dist] // 构建客户端输出目录
|
||||
|-- [docs] // 文档
|
||||
|-- [public] // 服务端静态资源
|
||||
|-- [server] // 服务端
|
||||
|-- [test] // 单元测试
|
||||
|-- [types] // typescript 类型
|
||||
|-- [utils] // 工具方法
|
||||
|-- .babelrc // babel 配置
|
||||
|-- .eslintignore // eslint 忽略
|
||||
|-- .eslintrc // eslint 配置
|
||||
|-- .gitignore // git 忽略
|
||||
|-- .nodemonrc // nodemon 配置
|
||||
|-- .prettierrc // prettier 配置
|
||||
|-- Dockerfile // docker 文件
|
||||
|-- LICENSE // fiora 许可
|
||||
|-- docker-compose.yaml // docker compose 配置
|
||||
|-- jest.*.sj // jest 配置
|
||||
|-- package.json // npm
|
||||
|-- tsconfig.json // typescript 配置
|
||||
|-- yarn.lock // yarn
|
||||
...
|
||||
|
||||
## 贡献代码
|
||||
|
||||
如果你想要添加功能或者修复 BUG. 请遵守下列流程.
|
||||
|
||||
1. fork 本仓库并克隆 fork 后的仓库到本地
|
||||
2. 安装依赖 `yarn install`
|
||||
3. 修改代码并确认无 bug
|
||||
4. 提交代码, 如果 eslint 有报错, 请修复后再次提交
|
||||
5. 创建一个 pull request
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
id: install
|
||||
title: 安装
|
||||
sidebar_label: 安装
|
||||
---
|
||||
|
||||
## 环境准备
|
||||
|
||||
要运行 Fiora, 你需要 Node.js(推荐 v14 LTS 版本), MongoDB 和 redis
|
||||
|
||||
- 安装 Node.js
|
||||
- 官网 <http://nodejs.cn/download/>
|
||||
- 更推荐使用 nvm 安装 Node.js
|
||||
- 安装 nvm <https://github.com/nvm-sh/nvm#install--update-script>
|
||||
- 通过 nvm 安装 Node.js <https://github.com/nvm-sh/nvm#usage>
|
||||
- 安装 MongoDB
|
||||
- 官网 <https://docs.mongodb.com/manual/installation/#install-mongodb>
|
||||
- 安装 redis
|
||||
- 官网 <https://redis.io/topics/quickstart>
|
||||
|
||||
推荐在 Linux 或者 MacOS 系统上运行
|
||||
|
||||
## 如何运行
|
||||
|
||||
1. 克隆项目到本地 `git clone https://github.com/yinxin630/fiora.git -b master`
|
||||
2. 确保安装了 [yarn](https://www.npmjs.com/package/yarn), 如果没有安装请执行 `npm install -g yarn`
|
||||
3. 安装项目依赖 `yarn install`
|
||||
4. 构建客户端代码 `yarn build:web`
|
||||
5. 配置 JwtSecret `echo "JwtSecret=<string>" > .env2`. 要将 `<string>` 替换为一个秘密文本
|
||||
6. 启动服务端 `yarn start`
|
||||
7. 使用浏览器打开 `http://[ip地址]:[端口]`(比如 `http://127.0.0.1:9200`)
|
||||
|
||||
### 在后台运行
|
||||
|
||||
使用 `yarn start` 运行服务端会在断开 ssh 连接后停止运行, 推荐使用 pm2 来运行
|
||||
|
||||
```bash
|
||||
# 安装 pm2
|
||||
npm install -g pm2
|
||||
|
||||
# 使用 pm2 运行 fiora
|
||||
pm2 start yarn --name fiora -- start
|
||||
|
||||
# 查看 pm2 应用状态
|
||||
pm2 ls
|
||||
|
||||
# 查看 pm2 fiora 日志
|
||||
pm2 logs fiora
|
||||
```
|
||||
|
||||
### 运行开发模式
|
||||
|
||||
1. 启动服务端 `yarn dev:server`
|
||||
2. 启动客户端 `yarn dev:web`
|
||||
3. 使用浏览器打开 `http://localhost:8080`
|
||||
|
||||
### docker 运行
|
||||
|
||||
首先安装 docker <https://docs.docker.com/install/>
|
||||
|
||||
#### 直接从 DockerHub 镜像运行
|
||||
|
||||
```bash
|
||||
# 拉取 mongo
|
||||
docker pull mongo
|
||||
|
||||
# 拉取 redis
|
||||
docker pull redis
|
||||
|
||||
# 拉取 fiora
|
||||
docker pull suisuijiang/fiora
|
||||
|
||||
# 创建虚拟网络
|
||||
docker network create fiora-network
|
||||
|
||||
# 启动 mongodB
|
||||
docker run --name fioradb -p 27017:27017 --network fiora-network mongo
|
||||
|
||||
# 启动 redis
|
||||
docker run --name fioraredis -p 6379:6379 --network fiora-network redis
|
||||
|
||||
# 启动 fiora
|
||||
docker run --name fiora -p 9200:9200 --network fiora-network -e Database=mongodb://fioradb:27017/fiora -e RedisHost=fioraredis suisuijiang/fiora
|
||||
```
|
||||
|
||||
#### 本地构建镜像运行
|
||||
|
||||
1. 克隆项目到本地 `git clone https://github.com/yinxin630/fiora.git -b master`
|
||||
2. 构建镜像 `docker-compose build --no-cache --force-rm`
|
||||
3. 运行 `docker-compose up`
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
id: script
|
||||
title: 脚本
|
||||
sidebar_label: 脚本
|
||||
---
|
||||
|
||||
fiora 内置了一个命令行工具, 用来管理服务器. 执行 `fiora` 查看工具
|
||||
|
||||
> **注意!** 这些脚本大多会直接修改数据库, 推荐(但非必需)提前备份数据库并停止服务端后再执行
|
||||
|
||||
## deleteMessages
|
||||
|
||||
`fiora deleteMessages`
|
||||
|
||||
删除所有历史消息记录, 如果消息图片和文件是存储在服务器上, 也可以一并删除
|
||||
|
||||
## deleteTodayRegisteredUsers
|
||||
|
||||
`fiora deleteTodayRegisteredUsers`
|
||||
|
||||
删除当天(以服务器时间为准)新注册的所有用户
|
||||
|
||||
## deleteUser
|
||||
|
||||
`fiora deleteUser [userId]`
|
||||
|
||||
删除指定用户, 同时删除其历史消息, 退出其已加入的群组并删除其所有好友关系
|
||||
|
||||
## doctor
|
||||
|
||||
`fiora doctor`
|
||||
|
||||
检查服务端配置和状态, 可以用来定位服务端启动失败的原因
|
||||
|
||||
## fixUsersAvatar
|
||||
|
||||
`fiora fixUsersAvatar`
|
||||
|
||||
修复用户错误头像路径, 请根据你的实际情况修改脚本判断逻辑
|
||||
|
||||
## getUserId
|
||||
|
||||
`fiora getUserId [username]`
|
||||
|
||||
获取指定用户名的 userId
|
||||
|
||||
## register
|
||||
|
||||
`fiora register [username] [password]`
|
||||
|
||||
注册新用户, 当禁止注册时可以由管理员通过其注册新用户
|
||||
|
||||
## updateDefaultGroupName
|
||||
|
||||
`fiora updateDefaultGroupName [newName]`
|
||||
|
||||
更新默认群组名
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"link.title.Docs": {
|
||||
"message": "文档"
|
||||
},
|
||||
"link.item.label.Overview": {
|
||||
"message": "首页"
|
||||
},
|
||||
"link.item.label.Getting Start": {
|
||||
"message": "入门指南"
|
||||
},
|
||||
"link.item.label.Change Log": {
|
||||
"message": "更新日志"
|
||||
},
|
||||
|
||||
"link.title.Community": {
|
||||
"message": "社区"
|
||||
},
|
||||
"link.item.label.Feedback": {
|
||||
"message": "加入聊天群"
|
||||
},
|
||||
"link.item.label.Issues": {
|
||||
"message": "Bug 反馈"
|
||||
},
|
||||
|
||||
"link.title.More": {
|
||||
"message": "更多"
|
||||
},
|
||||
"link.item.label.Author": {
|
||||
"message": "关于作者"
|
||||
},
|
||||
"link.item.label.GitHub": {
|
||||
"message": "GitHub"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"item.label.Docs": {
|
||||
"message": "文档"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@fiora/docs",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"dev:docs": "docusaurus start",
|
||||
"build:docs": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy:docs": "docusaurus deploy",
|
||||
"serve": "docusaurus serve",
|
||||
"clear": "docusaurus clear",
|
||||
"write-translations": "docusaurus write-translations"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "^2.0.0-alpha.71",
|
||||
"@docusaurus/preset-classic": "^2.0.0-alpha.71",
|
||||
"@mdx-js/react": "^1.6.21",
|
||||
"clsx": "^1.1.1",
|
||||
"react": "^16.8.4",
|
||||
"react-dom": "^16.8.4"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
docs: {
|
||||
fiora: ['getting-start', 'install', 'config', 'script', 'faq', 'changelog'],
|
||||
'fiora-app': ['app'],
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #25c2a0;
|
||||
--ifm-color-primary-dark: rgb(33, 175, 144);
|
||||
--ifm-color-primary-darker: rgb(31, 165, 136);
|
||||
--ifm-color-primary-darkest: rgb(26, 136, 112);
|
||||
--ifm-color-primary-light: rgb(70, 203, 174);
|
||||
--ifm-color-primary-lighter: rgb(102, 212, 189);
|
||||
--ifm-color-primary-lightest: rgb(146, 224, 208);
|
||||
--ifm-code-font-size: 95%;
|
||||
}
|
||||
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgb(72, 77, 91);
|
||||
display: block;
|
||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||
padding: 0 var(--ifm-pre-padding);
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Layout from '@theme/Layout';
|
||||
import Link from '@docusaurus/Link';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import Translate, { translate } from '@docusaurus/Translate';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: 'Richness',
|
||||
imageUrl: 'img/website-app.png',
|
||||
description: translate({
|
||||
message: 'Richness',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Cross Platform',
|
||||
imageUrl: 'img/cross-platform.png',
|
||||
description: translate({
|
||||
message: 'Cross Platform',
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'Open Source',
|
||||
imageUrl: 'img/open-source.png',
|
||||
description: translate({
|
||||
message: 'Open Source',
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
function Feature({ imageUrl, title, description }) {
|
||||
const imgUrl = useBaseUrl(imageUrl);
|
||||
return (
|
||||
<div className={clsx('col col--4', styles.feature)}>
|
||||
{imgUrl && (
|
||||
<div className="text--center">
|
||||
<img className={styles.featureImage} src={imgUrl} alt={title} />
|
||||
</div>
|
||||
)}
|
||||
<h3 className="text--center">{title}</h3>
|
||||
<p className={clsx('text--center', styles.featureDescription)}>{description}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const descriptions = [
|
||||
{
|
||||
title: translate({ message: 'Join Chat Title' }),
|
||||
content: translate({ message: 'Join Chat Content' }),
|
||||
image: `img/undraw_youtube_tutorial.svg`,
|
||||
imageAlign: 'right',
|
||||
},
|
||||
{
|
||||
title: translate({ message: 'Rich Feature Title' }),
|
||||
content: translate({ message: 'Rich Feature Content' }),
|
||||
image: `img/undraw_note_list.svg`,
|
||||
imageAlign: 'left',
|
||||
},
|
||||
{
|
||||
title: translate({ message: 'Deploy By Yourself Title' }),
|
||||
content: translate({ message: 'Deploy By Yourself Content' }),
|
||||
image: `img/undraw_code_review.svg`,
|
||||
imageAlign: 'right',
|
||||
},
|
||||
];
|
||||
|
||||
function Description({ title, content, image, index }) {
|
||||
return (
|
||||
<div className={clsx(styles.description, index % 2 === 0 && styles.lightBackground)}>
|
||||
<div className={clsx(styles.descriptionContent, index % 2 === 1 && styles.rightImage)}>
|
||||
<div className={clsx('col col--6', 'text--center')}>
|
||||
<img className={styles.descriptionImage} src={image} alt={title} />
|
||||
</div>
|
||||
<div className={clsx('col col--6')}>
|
||||
<h3 className="text--center">{title}</h3>
|
||||
<p className="text--center">{content}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function DeployByYourself({ url }) {
|
||||
return (
|
||||
<div className={styles.deployByYourself}>
|
||||
<h2 className={styles.deployTitle}>{translate({ message: 'Interested' })}</h2>
|
||||
<div>
|
||||
<Link
|
||||
className={clsx(
|
||||
'button button--outline button--secondary button--lg',
|
||||
styles.getStarted,
|
||||
)}
|
||||
to={url}
|
||||
>
|
||||
{translate({ message: 'Getting Start' })}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Home() {
|
||||
const context = useDocusaurusContext();
|
||||
const { siteConfig = {} } = context;
|
||||
|
||||
const title = translate({ message: 'Title' });
|
||||
const tagLine = translate({ message: 'TagLine' });
|
||||
const keywords = translate({ message: 'Keywords' });
|
||||
const description = translate({ message: 'Description' });
|
||||
const docsUrl = translate({ message: 'DocsUrl' });
|
||||
|
||||
return (
|
||||
<Layout title={tagLine} keywords={keywords} description={description}>
|
||||
<header className={clsx('hero hero--primary', styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<h1 className="hero__title">{title}</h1>
|
||||
<p className="hero__subtitle">{tagLine}</p>
|
||||
<div>
|
||||
<iframe
|
||||
className={styles.starIframe}
|
||||
src="https://ghbtns.com/github-btn.html?user=yinxin630&repo=fiora&type=star&count=true&size=large"
|
||||
width={160}
|
||||
height={30}
|
||||
title="GitHub Stars"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.buttons}>
|
||||
<Link
|
||||
className={clsx(
|
||||
'button button--outline button--secondary button--lg',
|
||||
styles.heroButton,
|
||||
)}
|
||||
to={siteConfig.url}
|
||||
>
|
||||
{translate({ message: 'Try It Now' })}
|
||||
</Link>
|
||||
<Link
|
||||
className={clsx(
|
||||
'button button--outline button--secondary button--lg',
|
||||
styles.heroButton,
|
||||
)}
|
||||
to={docsUrl}
|
||||
>
|
||||
{translate({ message: 'View Docs' })}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main>
|
||||
{features && features.length > 0 && (
|
||||
<section className={styles.features}>
|
||||
<div className="container">
|
||||
<div className="row">
|
||||
{features.map((props, idx) => (
|
||||
<Feature key={idx} {...props} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
{descriptions && descriptions.length > 0 && (
|
||||
<section className={styles.descriptions}>
|
||||
<div className={clsx('row', styles.descriptionRow)}>
|
||||
{descriptions.map((props, idx) => (
|
||||
<Description key={idx} {...props} index={idx} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
<section className={styles.descriptions}>
|
||||
<div className={clsx('row', styles.descriptionRow)}>
|
||||
<DeployByYourself url={`${siteConfig.baseUrl}docs/getting-start`} />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export default Home;
|
||||
@@ -0,0 +1,101 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
|
||||
/**
|
||||
* CSS files with the .module.css suffix will be treated as CSS modules
|
||||
* and scoped locally.
|
||||
*/
|
||||
|
||||
.heroBanner {
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 966px) {
|
||||
.heroBanner {
|
||||
padding: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.features {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.featureImage {
|
||||
height: 120px;
|
||||
width: 200px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.featureDescription {
|
||||
max-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.starIframe {
|
||||
border: none;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.descriptions {
|
||||
}
|
||||
|
||||
.descriptionRow {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.description {
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.descriptionContent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: var(--ifm-container-width);
|
||||
margin: 0 auto;
|
||||
padding: 0 var(--ifm-spacing-horizontal);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.descriptionImage {
|
||||
height: auto;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.lightBackground {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.rightImage {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.deployByYourself {
|
||||
width: 100%;
|
||||
min-height: 200px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.deployTitle {
|
||||
color: var(--ifm-color-primary);
|
||||
}
|
||||
|
||||
.heroButton {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 479 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 26 KiB |