diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/README.md b/README.md index 299362a..23dc9e2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ +Dan Donato + # project_superchat Build a realtime multi-room chat application. Make it super. diff --git a/index.js b/index.js new file mode 100644 index 0000000..1d9b4d2 --- /dev/null +++ b/index.js @@ -0,0 +1,88 @@ +const express = require("express"); +const app = express(); +const bodyParser = require("body-parser"); +const hbs = require("express-handlebars"); +const server = require("http").createServer(app); +const io = require("socket.io")(server); +const cookieParser = require("cookie-parser"); +const redisTools = require("./lib/redis_tools"); + +// const { getUserIds, getUsername } = require("./lib/get_user_info"); +const { getUsernames } = require("./lib/get_user_info"); +const { getRoomNames } = require("./lib/room_info"); +const { generateUserInfo, generateRoomInfo } = require("./lib/redis_tools"); + +app.use(cookieParser()); +app.use(bodyParser.urlencoded({ extended: false })); +app.engine("handlebars", hbs({ defaultLayout: "main" })); +app.set("view engine", "handlebars"); +app.use(express.static(`${__dirname}/public`)); + +app.use( + "/socket.io", + express.static(`${__dirname}/node_modules/socket.io-client/dist/`) +); + +app.use(bodyParser.urlencoded({ extended: true })); + +io.on("connection", client => { + // send all current chats to rooms + getRoomNames().then(roomNames => { + client.emit("updateRooms", roomNames); + }); + + client.on("newChatRoom", newChatRoom => { + io.emit("newChatRoomFromServer", newChatRoom); + console.log(`newchatRoom: ${newChatRoom}`); + generateRoomInfo(newChatRoom).then(() => { + console.log("worked"); + }); + }); + + client.on("newMessage", newMessage => { + io.emit("newMessageFromServer", newMessage); + }); +}); + +app.get("/", (req, res) => { + console.log(req.cookies); + req.cookies.username ? res.redirect("/chatrooms") : res.render("loginScreen"); +}); + +app.post("/", (req, res) => { + console.log(req.body.name); + res.cookie("username", req.body.name); + + // Safety make sure we don't make 2 USER_IDS + getUsernames().then(usernames => { + console.log(usernames); + if (usernames.includes(req.body.name)) { + res.redirect("/"); + } else { + generateUserInfo(req.body.name).then(() => { + res.redirect("/"); + }); + } + }); +}); + +app.get("/chatrooms", (req, res) => { + res.render("chatLobby", { username: req.cookies.username }); +}); + +app.get("/chatrooms/:chatroom", (req, res) => { + let chatRoom = req.params.chatroom; + console.log(req.params.chatroom); + if (!req.cookies.username) { + res.redirect("/"); + } else { + res.render("chatScreen", { + roomName: chatRoom, + username: req.cookies.username + }); + } +}); + +server.listen(3000, () => { + console.log("Serving gormet lobster!"); +}); diff --git a/lib/get_message_helpers.js b/lib/get_message_helpers.js new file mode 100644 index 0000000..1d9cb72 --- /dev/null +++ b/lib/get_message_helpers.js @@ -0,0 +1,19 @@ +const redisClient = require("redis").createClient(); + +module.exports = { + getMessage: (messageId) => { + return new Promise((resolve, reject) => { + redisClient.hmget(messageId, (err, message) => { + (err) ? reject(err) : resolve(message); + }) + }) + }, + + getMessageIds: () => { + return new Promise((resolve, reject) => { + redisClient.lrange("MESSAGE_IDS", 0, -1, (err, messageIds) => { + (err) ? reject(err) : resolve(messageIds); + }) + }) + } +} diff --git a/lib/get_room_info_helpers.js b/lib/get_room_info_helpers.js new file mode 100644 index 0000000..c239420 --- /dev/null +++ b/lib/get_room_info_helpers.js @@ -0,0 +1,20 @@ + +const redisClient = require("redis").createClient(); + +module.exports = { + getRoomName: (roomId) => { + return new Promise((resolve, reject) => { + redisClient.get(roomId, (err, username) => { + (err) ? reject(err) : resolve(username); + }) + }) + }, + + getRoomIds: () => { + return new Promise((resolve, reject) => { + redisClient.lrange("ROOM_IDS", 0, -1, (err, roomIds) => { + (err) ? reject(err) : resolve(roomIds); + }) + }) + } +} diff --git a/lib/get_user_info.js b/lib/get_user_info.js new file mode 100644 index 0000000..05d7229 --- /dev/null +++ b/lib/get_user_info.js @@ -0,0 +1,32 @@ +const redisClient = require("redis").createClient(); +const { getUsername, getUserIds } = require("./get_user_info_helpers"); + +module.exports = { + storeUserId: userId => { + return new Promise((resolve, reject) => { + redisClient.lpush("USER_IDS", userId, (err, reply) => { + err ? reject(err) : resolve(userId); + }); + }); + }, + + storeUsername: (userId, username) => { + return new Promise((resolve, reject) => { + console.log(userId); + console.log(username); + redisClient.set(userId, username, (err, reply) => { + err ? reject(err) : resolve(); + }); + }); + }, + + getUsernames: () => { + return getUserIds().then(userIds => { + return Promise.all( + userIds.map(userId => { + return getUsername(userId); + }) + ); + }); + } +}; diff --git a/lib/get_user_info_helpers.js b/lib/get_user_info_helpers.js new file mode 100644 index 0000000..af3a6d4 --- /dev/null +++ b/lib/get_user_info_helpers.js @@ -0,0 +1,20 @@ +const redisClient = require("redis").createClient(); + +module.exports = { + getUsername: (userId) => { + return new Promise((resolve, reject) => { + redisClient.get(userId, (err, username) => { + // console.log(username); + (err) ? reject(err) : resolve(username); + }) + }) + }, + + getUserIds: () => { + return new Promise((resolve, reject) => { + redisClient.lrange("USER_IDS", 0, -1, (err, userIds) => { + (err) ? reject(err) : resolve(userIds); + }) + }) + } +} diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..45944f5 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,5 @@ +const redisTools = require("./redis_tools"); + +module.exports = { + redisTools +} diff --git a/lib/redis_messages.js b/lib/redis_messages.js new file mode 100644 index 0000000..c2c4287 --- /dev/null +++ b/lib/redis_messages.js @@ -0,0 +1,34 @@ +const redisClient = require("redis").createClient(); +const { getMessageIds, getMessage } = require("./get_message_helpers"); + +module.exports = { + storeMessageId: (messageId) => { + return new Promise((resolve, reject) => { + redisClient.lpush("MESSAGE",messageId, + (error,data) => {if(error) throw error; resolve();}); + }) + }, + + storeMessage: (messageId, message, username, roomName) => { + return new Promise((resolve, reject) => { + redisClient.hmset(messageId, { + message: message, + username: username, + roomName: roomName + }, (error,data) => { + if(error) throw error; + resolve(); + }) + }) + }, + + getMessages: () => { + return getMessageIds.then(messageIds => { + return Promise.all( + messagesIds.map(messageId => { + return getMessage(messageId); + }) + ) + }) + } +} diff --git a/lib/redis_tools.js b/lib/redis_tools.js new file mode 100644 index 0000000..9e6a94c --- /dev/null +++ b/lib/redis_tools.js @@ -0,0 +1,27 @@ +const usernameHelpers = require("./get_user_info"); +const chatroomHelpers = require("./room_info"); +const messageHelpers = require("./redis_messages"); +const shortid = require("shortid"); + +module.exports = { + generateUserInfo: username => { + const userId = shortid.generate(); + return usernameHelpers + .storeUserId(userId) + .then(userId => usernameHelpers.storeUsername(userId, username)); + }, + + generateRoomInfo: roomName => { + const roomId = shortid.generate(); + return chatroomHelpers + .storeRoomId(roomId) + .then(roomId => chatroomHelpers.storeRoomName(roomId, roomName)); + }, + + generateMessageInfo: (message, username, roomName) => { + const messageId = shortid.generate() + return messageHelpers + .storeMessageId(messageId) + .then(messageId => messageHelpers.storeMessage(messageId, message, username, roomName)); + } +}; diff --git a/lib/room_info.js b/lib/room_info.js new file mode 100644 index 0000000..71b5c0c --- /dev/null +++ b/lib/room_info.js @@ -0,0 +1,32 @@ +const redisClient = require("redis").createClient(); +const { getRoomName, getRoomIds } = require("./get_room_info_helpers"); + +module.exports = { + storeRoomId: (roomId) => { + return new Promise((resolve, reject) => { + redisClient.lpush("ROOM_IDS", roomId, (err, reply) => { + (err) + ? reject(err) + : resolve(roomId); + }) + }) + }, + + storeRoomName: (roomId, roomName) => { + return new Promise((resolve, reject) => { + redisClient.set(roomId, roomName, (err, reply) => { + (err) + ? reject(err) + : resolve(); + }); + }) + }, + + getRoomNames: () => { + return (getRoomIds().then((roomIds) => { + return Promise.all(roomIds.map((roomId) => { + return getRoomName(roomId); + })) + })) + } +} diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..9e8bcb3 --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,27 @@ +0 info it worked if it ends with ok +1 verbose cli [ '/home/alex/.nvm/versions/node/v6.0.0/bin/node', +1 verbose cli '/home/alex/.nvm/versions/node/v6.0.0/bin/npm', +1 verbose cli 'run', +1 verbose cli 'init' ] +2 info using npm@3.8.6 +3 info using node@v6.0.0 +4 verbose stack Error: missing script: init +4 verbose stack at run (/home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/lib/run-script.js:147:19) +4 verbose stack at /home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/lib/run-script.js:57:5 +4 verbose stack at /home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/read-package-json/read-json.js:345:5 +4 verbose stack at checkBinReferences_ (/home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/read-package-json/read-json.js:309:45) +4 verbose stack at final (/home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/read-package-json/read-json.js:343:3) +4 verbose stack at then (/home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/read-package-json/read-json.js:113:5) +4 verbose stack at /home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/read-package-json/read-json.js:300:12 +4 verbose stack at /home/alex/.nvm/versions/node/v6.0.0/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:78:16 +4 verbose stack at tryToString (fs.js:449:3) +4 verbose stack at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:436:12) +5 verbose cwd /home/alex/vcs/assignments_course/project_superchat +6 error Linux 4.10.0-27-generic +7 error argv "/home/alex/.nvm/versions/node/v6.0.0/bin/node" "/home/alex/.nvm/versions/node/v6.0.0/bin/npm" "run" "init" +8 error node v6.0.0 +9 error npm v3.8.6 +10 error missing script: init +11 error If you need help, you may report this error at: +11 error +12 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..2db9eaa --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "project_superchat", + "version": "1.0.0", + "description": "Dan Donato", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "nodemon index.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Alex-Willenbrink/project_superchat.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/Alex-Willenbrink/project_superchat/issues" + }, + "homepage": "https://github.com/Alex-Willenbrink/project_superchat#readme", + "dependencies": { + "body-parser": "^1.17.2", + "cookie-parser": "^1.4.3", + "express": "^4.15.3", + "express-handlebars": "^3.0.0", + "redis": "^2.7.1", + "shortid": "^2.2.8", + "socket.io": "^2.0.3" + } +} diff --git a/plan.txt b/plan.txt new file mode 100644 index 0000000..1aa19c0 --- /dev/null +++ b/plan.txt @@ -0,0 +1,20 @@ +Login screen: +message [rm# user: text] +counter when 10 +///later on save: move all the messages to external file + +message list push pop +[] of last n messages + + +ChatRoom: +{message: {user: +text: }} + Display previous n messages + display username next to messages + +redisserver. +rediserver.users if user exists append x +redisserver.rooms.messages[room:msg1,msg2] +>>>save user with cookie +jack: im the all thin::::::::king all seeing diff --git a/public/js/chat_room.js b/public/js/chat_room.js new file mode 100644 index 0000000..60e641c --- /dev/null +++ b/public/js/chat_room.js @@ -0,0 +1,25 @@ +const socket = io.connect("http://localhost:3000"); + +// $(".roomName").text(); +// $(".storedName").text(); +socket.on("newMessageFromServer", newChatMessage => { + let chatMessage = createNewMessage(newChatMessage); + $("#PostedMessages").prepend($(`${chatMessage}`)); +}); + +function createNewMessage(passedMessage) { + console.log(passedMessage); + return ` +

Author: ${passedMessage.username}

+

Message: ${passedMessage.message}

+ `; +} + +$("#submitPost").on("click", e => { + console.log("fjfjf"); + e.preventDefault(); + socket.emit("newMessage", { + username: $(".storedName").text(), + message: $(".message").val() + }); +}); diff --git a/public/js/lobby.js b/public/js/lobby.js new file mode 100644 index 0000000..27a9da5 --- /dev/null +++ b/public/js/lobby.js @@ -0,0 +1,33 @@ +const socket = io.connect("http://localhost:3000"); + +$("#createRoom").on("click", e => { + e.preventDefault(); + socket.emit("newChatRoom", $(".roomName").val()); +}); + +// Will add button of new chat room +socket.on("newChatRoomFromServer", newChatRoom => { + console.log("working Here"); + let chatButton = createRoom(newChatRoom); + $("#ChatRoomList").append(chatButton); +}); + +socket.on("updateRooms", roomNames => { + console.log(roomNames); + console.log("Wow, so many rooms"); + roomNames.forEach(roomName => { + let chatButton = createRoom(roomName); + console.log(chatButton); + $("#ChatRoomList").append($(`${chatButton}`)); + }); +}); + +function createRoom(roomName) { + return ` +
+
+ +
+
+ `; +} diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..2c2fb24 --- /dev/null +++ b/styles.css @@ -0,0 +1,3 @@ +li { + border: 3px solid #73ad21; +} diff --git a/views/chatLobby.handlebars b/views/chatLobby.handlebars new file mode 100644 index 0000000..25d657b --- /dev/null +++ b/views/chatLobby.handlebars @@ -0,0 +1,14 @@ +Welcome +
{{username}}
+ +============================= +
+ + +
+============================= +
+
+ + + diff --git a/views/chatScreen.handlebars b/views/chatScreen.handlebars new file mode 100644 index 0000000..c6192d6 --- /dev/null +++ b/views/chatScreen.handlebars @@ -0,0 +1,16 @@ +

{{roomName}}

+
{{username}}
+ +============================= +
+ + +
+ +============================= + +
+ + + diff --git a/views/index.handlebars b/views/index.handlebars new file mode 100644 index 0000000..c0c3420 --- /dev/null +++ b/views/index.handlebars @@ -0,0 +1,26 @@ +
+ + +
+ +
+ {{#each chats as |chatText|}} +
+ {{chatText.name}} +

{{chatText}}

+
+ {{/each}} +
+ diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars new file mode 100644 index 0000000..8babb37 --- /dev/null +++ b/views/layouts/main.handlebars @@ -0,0 +1,11 @@ + + + + + + Chat Room + + + {{{body}}} + + diff --git a/views/loginScreen.handlebars b/views/loginScreen.handlebars new file mode 100644 index 0000000..3699ae2 --- /dev/null +++ b/views/loginScreen.handlebars @@ -0,0 +1,4 @@ +
+ + +
diff --git a/views/rooms_display.handlebars b/views/rooms_display.handlebars new file mode 100644 index 0000000..ee3b064 --- /dev/null +++ b/views/rooms_display.handlebars @@ -0,0 +1,15 @@ + +

Chat Lobby

+
{{username}}
+ +
+ + +
+ + +
+ +
+ +