Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 216 additions & 53 deletions README.md

Large diffs are not rendered by default.

Binary file added docker/chat
Binary file not shown.
17 changes: 17 additions & 0 deletions docker/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM ubuntu:18.04
LABEL maintainer="https://github.com/OblivionTime"
LABEL version="1.0"
LABEL description="Chat docker 搭建平台"
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Shanghai
USER root
RUN apt-get update
RUN apt-get install mysql-server -y
RUN apt-get install libmysqlclient-dev -y
COPY . /chat
RUN chmod 777 /chat
RUN cd /chat && ./init.sh
EXPOSE 3306
EXPOSE 8888
WORKDIR /chat
CMD service mysql start && ./chat
5 changes: 5 additions & 0 deletions docker/execSql.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;
use mysql;
update user set Host="%" where User="root";
create database chat character set = utf8mb4;
4 changes: 4 additions & 0 deletions docker/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
cp -rf /chat/mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
service mysql start
mysql < /chat/execSql.sql
105 changes: 105 additions & 0 deletions docker/mysqld.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.

# Here is entries for some specific programs
# The following values assume you have at least 32M ram

[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0

[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 0.0.0.0
#
# * Fine Tuning
#
key_buffer_size = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover-options = BACKUP
#max_connections = 100
#table_open_cache = 64
#thread_concurrency = 10
#
# * Query Cache Configuration
#
query_cache_limit = 1M
query_cache_size = 16M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
#slow_query_log = 1
#slow_query_log_file = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#server-id = 1
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem
5 changes: 5 additions & 0 deletions server/app/routes/friend.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ module.exports = function () {
router.get('/list', authenticateToken, friend.List)
router.post('/add_friend', authenticateToken, friend.AddFriend)
router.get('/search', authenticateToken, friend.SearchUser)
router.get('/info', authenticateToken, friend.getFriendInfo)
router.get('/group_list', authenticateToken, friend.getFriendGroupList)
router.post('/create', authenticateToken, friend.createFriendGroup)
router.post('/update', authenticateToken, friend.updateFriendGroup)
router.post('/update_friend', authenticateToken, friend.updateFriendInfo)
return router
}
16 changes: 16 additions & 0 deletions server/app/routes/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,25 @@ function authenticateToken(req, res, next) {
});
}
module.exports = function () {
//群聊列表
router.get('/list', authenticateToken, group.List)
//获取群聊中所有群员
router.get('/members_list', authenticateToken, group.MembersList)
//创建群聊
router.post('/create_group', authenticateToken, upload.single('avatar'), group.CreateGroupChat)
//搜索群聊
router.get('/search', authenticateToken, group.SearchGroupChat)
//加入群聊
router.get('/join', authenticateToken, group.JoinGroupChat)
//群聊信息
router.get('/info', authenticateToken, group.GroupInfo)
//重命名
router.post('/rename', authenticateToken, group.RenameGroup)
//邀请群聊
router.post('/invitation', authenticateToken, group.invitedUsersToGroup)
//退出群聊
router.post('/exitGroupChat', authenticateToken, group.DeleteUserFromGroup)
//获取音视频房间的所有用户
router.get('/getRTCUser', authenticateToken, group.GetRTCUser)
return router
}
2 changes: 1 addition & 1 deletion server/app/routes/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ function authenticateToken(req, res, next) {
}
module.exports = function () {
router.get('/list', authenticateToken, message.List)
router.ws('/single',message.SingleConnect)
router.ws('/chat', message.ChatConnect)
return router
}
1 change: 1 addition & 0 deletions server/app/routes/rtc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ const rtc = require("../../container/rtc/index")

module.exports = function () {
router.ws('/single',rtc.SingleRTCConnect)
router.ws('/group',rtc.groupRTCConnect)
return router
}
98 changes: 78 additions & 20 deletions server/container/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module.exports = {
};
const jwt = require('jsonwebtoken');
const secretKey = 'xWbiNA3FqnK77MnVCj5CAcfA-VlXj7xoQLd1QaAme6l_t0Yp1TdHbSw';
let rooms = {}
let codeRooms = {}
let { RespUserOrPassErr, RespParamErr, RespServerErr, RespUserExitErr, RespUpdateErr, RespUserNotExitErr } = require('../../model/error');
const { RespData, RespSuccess } = require('../../model/resp');
const { Query } = require('../../db/query');
Expand Down Expand Up @@ -189,18 +189,18 @@ function LoginCode(ws, req) {
let room = params.get("room")
let name = params.get("name")
if (name == 'device') {
rooms[room] = {}
rooms[room][name] = ws
} else if (rooms[room] && name == 'user') {
rooms[room][name] = ws
codeRooms[room] = {}
codeRooms[room][name] = ws
} else if (codeRooms[room] && name == 'user') {
codeRooms[room][name] = ws
} else {
ws.close()
}
ws.on('message', function (Resp_data) {
let data = JSON.parse(Resp_data)
if (name == 'user') {
if (data.operation == "connect") {
rooms[room]['device'].send(JSON.stringify(data))
codeRooms[room]['device'].send(JSON.stringify(data))
} else if (data.operation == "login") {
let username = data.username
const sql = 'select * from user where username=?'
Expand All @@ -224,26 +224,26 @@ function LoginCode(ws, req) {
phone: results[0].phone,
}
}
rooms[room]['device'].send(JSON.stringify(data))
codeRooms[room]['device'].send(JSON.stringify(data))
} else {
ws.send(JSON.stringify({ operation: "error", error: "登录失败" }))
}
})
}
} else {
rooms[room]['user'].send(Resp_data)
codeRooms[room]['user'].send(Resp_data)
}
});
ws.on('close', function () {
if (name == 'device') {
delete rooms[room][name]
for (const key in rooms[room]) {
rooms[room][key].close()
delete codeRooms[room][name]
for (const key in codeRooms[room]) {
codeRooms[room][key].close()
}
delete rooms[room]
delete codeRooms[room]
} else {
if (rooms[room]) {
delete rooms[room][name]
if (codeRooms[room]) {
delete codeRooms[room][name]
}
}
})
Expand Down Expand Up @@ -276,18 +276,76 @@ function initUserNotification(ws, req) {
let params = new URLSearchParams(url)
let username = params.get("username")
//如果用户已经登录则强制退出当前用户
if (LoginRooms[username]) {
ws.close()
// if (LoginRooms[username]) {
// LoginRooms[username].send(JSON.stringify({ name: "logout" }))
// LoginRooms[username].close()
// }
LoginRooms[username] = {
ws: ws,
status: false,
}
LoginRooms[username] = ws
ws.on('message', function (Resp_data) {
ws.on('message', async (Resp_data) => {
let data = JSON.parse(Resp_data)
//接收者
let receiver_username = data.receiver_username
if (data.name == 'audio' || data.name == 'video') {
if (!LoginRooms[receiver_username]) {
ws.send(JSON.stringify({ name: "reject", message: "对方当前不在线!!!" }))
return
}
if (LoginRooms[receiver_username].status) {
ws.send(JSON.stringify({ name: "reject", message: "对方正在通话中!!!" }))
return
}
//当用户已经在音视频通话了则需要告知发送方
if (LoginRooms[username].status) {
ws.send(JSON.stringify({ name: "reject", message: "你正在通话中,请勿发送其他通话请求...." }))
return
}
LoginRooms[username].status = true
//对方在线
if (LoginRooms[receiver_username]) {
LoginRooms[receiver_username].ws.send(Resp_data)
data.method = data.name
data.name = 'peer'
ws.send(JSON.stringify(data))
return
}
} else if (data.name == 'group_audio' || data.name == 'group_video') {
if (LoginRooms[username].status || (group_rooms[data.room] && Object.keys(group_rooms[data.room]).length != 0)) {
ws.send(JSON.stringify({ name: "reject", message: "无法创建群音视频...." }))
return
}
/**
* 群视频逻辑处理
*
*/
group_rooms[data.room] = {}
group_rooms[data.room][username] = ""
LoginRooms[username].status = true
for (const user of data.userList) {
if (user == data.sender_name) {
continue
}
//对方在线且并未通话
if (LoginRooms[user] && !LoginRooms[user].status) {
group_rooms[data.room][user] = ""
LoginRooms[user].ws.send(Resp_data)
}
}
data.method = data.name
data.name = 'group_peer'
ws.send(JSON.stringify(data))
return
}
//拒绝通话
if (data.name == 'reject') {
LoginRooms[username].status = false
return
}
//对方在线
if (LoginRooms[receiver_username]) {
LoginRooms[receiver_username].send(Resp_data)

LoginRooms[receiver_username].ws.send(Resp_data)
}
});
ws.on('close', function () {
Expand Down
13 changes: 8 additions & 5 deletions server/container/bing/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ let { RespUserOrPassErr, RespParamErr, RespServerErr, RespUserExitErr, RespUpdat
const { Query } = require('../../db/query');
const { getConversation } = require('../../utils/newBing');
const { v4: uuidv4 } = require('uuid');
let rooms = {}
let bing_rooms = {}
/**
* 生成Conversation
* 1.获取当前登录的用户名,并获取到前端传来的代理服务器地址
Expand All @@ -13,6 +13,9 @@ let rooms = {}
*/
//生成密钥对
async function generateConversation(req, res) {
if (os.platform() !== 'win32') {
return RespError(res, RespServerErr)
}
//获取当前登录的用户名
let username = req.user.username
const { proxy } = req.query
Expand Down Expand Up @@ -62,7 +65,7 @@ async function getConversationInfo(req, res) {
let sql = "update ai_conversation set count=0 where username=? and TIMESTAMPDIFF(hour, updated_at, NOW()) >= 6"
await Query(sql, [username])
//获取到可聊天总数和已用次数
sql = "select count(*) as total,SUM(count) as us_count,room from ai_conversation where username=?"
sql = "select count(*) as total,SUM(count) as us_count,room from ai_conversation where username=? GROUP BY room"
let { err, results } = await Query(sql, [username])
// 查询数据失败
if (err) return RespError(res, RespServerErr)
Expand Down Expand Up @@ -104,7 +107,7 @@ async function BingConnect(ws, req) {
let url = req.url.split("?")[1];
let params = new URLSearchParams(url)
let room = params.get("room")
rooms[room] = ws
bing_rooms[room] = ws
//获取所有聊天记录
let sql = 'SELECT m.*,u.avatar FROM (SELECT sender_id, receiver_id, content, room, link_list,ai_message.created_at,invocation_id FROM ai_message WHERE `room` =? ORDER BY created_at ASC) AS m LEFT JOIN user as u ON u.`id`=m.`sender_id`'
let { err, results } = await Query(sql, [room])
Expand Down Expand Up @@ -133,8 +136,8 @@ async function BingConnect(ws, req) {
sql = `update ai_conversation set count=? where conversation_id=? and conversation_signature=?`
await Query(sql, [message.numUserMessagesInConversation, message.conversation_id, message.conversation_signature])
if (message.numUserMessagesInConversation == 20) {
if (rooms[room]) {
rooms[room].send(JSON.stringify({ "name": "reset" }))
if (bing_rooms[room]) {
bing_rooms[room].send(JSON.stringify({ "name": "reset" }))
}
}
return
Expand Down
Loading