diff --git a/README.md b/README.md index 01bcfaa..e5f32be 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,6 @@ # ReactBlog -a blog system based on React+Node +node_chat分支 -以[NodeBlog](https://github.com/BetaMee/NodeBlog)为基础,开发一个React+Node的blog系统,简单可易用的系统。 +以[NodeBlog](https://github.com/BetaMee/NodeBlog)为基础,开发一个React+Node的实时通信系统,使用WebSocket和Socket.io为包,后期准备独立出来,前期放在ReactBlog下。也学习下github分支管理。 -需求: - -1. 完善的api接口,返回的是json数据,前端使用fetch获取数据。 -2. 后期使用electron开发桌面应用,用于本地写博客。(或许我可以写一个像hexo那样的可以部署到github上的桌面应用) -3. 以我喜爱的material ui开发,后期设计自己的主题 -4. 有用户权限 -5. 留言系统就不自己做了 -6. post模型和user模型 -7. 正式部署到服务器上 - -未来计划: - -1. electron桌面应用 -2. 设计自己的主题风格 -3. 开发部署工具,部署到github上,静态博客 - -步骤: -1. 先以NodeBlog为基础完善后台api设计. -2. 开发react的web页面,react-router作路由,前后端协作。 diff --git a/index.js b/index.js index e69de29..06944ad 100644 --- a/index.js +++ b/index.js @@ -0,0 +1,60 @@ +var http = require('http'); +var fs = require('fs'); +var path = require('path'); +var mime = require('mime'); +var cache = {}; + +function send404(response) { + response.writeHead(404, {'Content-Type': 'text/plain'}); + response.write('Error 404: resource not found.'); + response.end(); +} + +function sendFile(response, filePath, fileContents) { + response.writeHead( + 200, + {"content-type": mime.lookup(path.basename(filePath))} + ); + response.end(fileContents); +} + +function serveStatic(response, cache, absPath) { + if (cache[absPath]) { + sendFile(response, absPath, cache[absPath]); + } else { + fs.exists(absPath, function(exists) { + if (exists) { + fs.readFile(absPath, function(err, data) { + if (err) { + send404(response); + } else { + cache[absPath] = data; + sendFile(response, absPath, data); + } + }); + } else { + send404(response); + } + }); + } +} + +var server = http.createServer(function(request, response) { + var filePath = false; + + if (request.url == '/') { + filePath = 'public/index.html'; + } else { + filePath = 'public' + request.url; + } + + var absPath = './' + filePath; + serveStatic(response, cache, absPath); +}); + +server.listen(3000, function() { + console.log("Server listening on port 3000."); +}); + +var chatServer = require('./lib/chat_server'); +chatServer.listen(server); diff --git a/lib/chat_server.js b/lib/chat_server.js new file mode 100644 index 0000000..aa42a57 --- /dev/null +++ b/lib/chat_server.js @@ -0,0 +1,112 @@ +var socketio = require('socket.io'); +var io; +var guestNumber = 1; +var nickNames = {}; +var namesUsed = []; +var currentRoom = {}; + +exports.listen = function(server) { + io = socketio.listen(server); + io.set('log level', 1); + io.sockets.on('connection', function (socket) { + guestNumber = assignGuestName(socket, guestNumber, nickNames, namesUsed); + joinRoom(socket, 'Lobby'); + handleMessageBroadcasting(socket, nickNames); + handleNameChangeAttempts(socket, nickNames, namesUsed); + handleRoomJoining(socket); + socket.on('rooms', function() { + socket.emit('rooms', io.sockets.manager.rooms); + }); + handleClientDisconnection(socket, nickNames, namesUsed); + }); +}; + +function assignGuestName(socket, guestNumber, nickNames, namesUsed) { + var name = 'Guest' + guestNumber; + nickNames[socket.id] = name; + socket.emit('nameResult', { + success: true, + name: name + }); + namesUsed.push(name); + return guestNumber + 1; +} + +function joinRoom(socket, room) { + socket.join(room); + currentRoom[socket.id] = room; + socket.emit('joinResult', {room: room}); + socket.broadcast.to(room).emit('message', { + text: nickNames[socket.id] + ' has joined ' + room + '.' + }); + + var usersInRoom = io.sockets.clients(room); + if (usersInRoom.length > 1) { + var usersInRoomSummary = 'Users currently in ' + room + ': '; + for (var index in usersInRoom) { + var userSocketId = usersInRoom[index].id; + if (userSocketId != socket.id) { + if (index > 0) { + usersInRoomSummary += ', '; + } + usersInRoomSummary += nickNames[userSocketId]; + } + } + usersInRoomSummary += '.'; + socket.emit('message', {text: usersInRoomSummary}); + } +} + +function handleNameChangeAttempts(socket, nickNames, namesUsed) { + socket.on('nameAttempt', function(name) { + if (name.indexOf('Guest') == 0) { + socket.emit('nameResult', { + success: false, + message: 'Names cannot begin with "Guest".' + }); + } else { + if (namesUsed.indexOf(name) == -1) { + var previousName = nickNames[socket.id]; + var previousNameIndex = namesUsed.indexOf(previousName); + namesUsed.push(name); + nickNames[socket.id] = name; + delete namesUsed[previousNameIndex]; + socket.emit('nameResult', { + success: true, + name: name + }); + socket.broadcast.to(currentRoom[socket.id]).emit('message', { + text: previousName + ' is now known as ' + name + '.' + }); + } else { + socket.emit('nameResult', { + success: false, + message: 'That name is already in use.' + }); + } + } + }); +} + +function handleMessageBroadcasting(socket) { + socket.on('message', function (message) { + socket.broadcast.to(message.room).emit('message', { + text: nickNames[socket.id] + ': ' + message.text + }); + }); +} + +function handleRoomJoining(socket) { + socket.on('join', function(room) { + socket.leave(currentRoom[socket.id]); + joinRoom(socket, room.newRoom); + }); +} + +function handleClientDisconnection(socket) { + socket.on('disconnect', function() { + var nameIndex = namesUsed.indexOf(nickNames[socket.id]); + delete namesUsed[nameIndex]; + delete nickNames[socket.id]; + }); +} diff --git a/package.json b/package.json index ac744f5..3f52a08 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,8 @@ "homepage": "https://github.com/BetaMee/ReactBlog#readme", "dependencies": { "express": "^4.14.1", - "express-session": "^1.15.1" + "express-session": "^1.15.1", + "mime": "^1.3.4", + "socket.io": "^1.7.2" } } diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..9e4a7c5 --- /dev/null +++ b/public/css/style.css @@ -0,0 +1,53 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} + +#content { + width: 800px; + margin-left: auto; + margin-right: auto; +} + +#room { + background-color: #ddd; + margin-bottom: 1em; +} + +#messages { + width: 690px; + height: 300px; + overflow: auto; + background-color: #eee; + margin-bottom: 1em; + margin-right: 10px; +} + +#room-list { + float: right; + width: 100px; + height: 300px; + overflow: auto; +} + +#room-list div { + border-bottom: 1px solid #eee; +} + +#room-list div:hover { + background-color: #ddd; +} + +#send-message { + width: 700px; + margin-bottom: 1em; + margin-right: 1em; +} + +#help { + font: 10px "Lucida Grande", Helvetica, Arial, sans-serif; +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..dedf230 --- /dev/null +++ b/public/index.html @@ -0,0 +1,34 @@ + + + +
+