Initial comit ver2
This commit is contained in:
commit
69b3aa215d
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
src/utils/roomsIDs.json
|
||||
src/utils/roomsIDs.json
|
BIN
Kacper-Maj-Karta-projekt.pdf
Normal file
BIN
Kacper-Maj-Karta-projekt.pdf
Normal file
Binary file not shown.
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# Watch With Friends
|
||||
**Watch with friends** to projekt, który ma za zadanie umożliwić „spotkanie” się znajomych na wspólnym oglądaniu filmów w dobie pandemii. Postawiłem sobie za zadanie umożliwić połączenie możliwie wielu przyjaciół jednocześnie w jednym, generowanym losowo pokoju do którego dostęp otrzymują osoby, które dostaną unikatowy link. W pokoju tym użytkownicy poproszeni zostaną o ustawienie swojej nazwy a następnie mogą zarządzać puszczanym aktualnie filmem z YouTube, wkleić link do wybranego przez siebie filmu, dowolnie zatrzymywać i puszczać film. Jako dodatkowy element pokoju dodany zostanie chat, który będzie pozwalał na komunikację pomiędzy użytkownikami serwisu w czasie rzeczywistym.
|
1526
package-lock.json
generated
Normal file
1526
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
package.json
Normal file
21
package.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "chat-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node src/index.js",
|
||||
"dev": "nodemon src/index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"bad-words": "^3.0.4",
|
||||
"express": "^4.17.1",
|
||||
"socket.io": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.7"
|
||||
}
|
||||
}
|
42
public/chat.html
Normal file
42
public/chat.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Chat</title>
|
||||
<link rel="icon" href="/img/favicon.png">
|
||||
<link rel="stylesheet" href="/css/styles.min.css">
|
||||
<link rel="stylesheet" href="/css/styles.css">
|
||||
<meta name="description" content="Chat">
|
||||
<meta name="author" content="SitePoint">
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.1/mustache.min.js"></script>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.6.0/qs.min.js"></script>
|
||||
<script defer src="/socket.io/socket.io.js"></script>
|
||||
<script defer src="/js/chat.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="chat">
|
||||
<div class="chat__sidebar">
|
||||
|
||||
</div>
|
||||
<div class="chat__main">
|
||||
<div id="messages-container" class="chat__messages"> </div>
|
||||
|
||||
<div class="compose">
|
||||
<form action="POST" id="sendMessForm">
|
||||
<input placeholder="Write your message">
|
||||
<button type="submit" id="formButton">Send</button>
|
||||
</form>
|
||||
<button id="sendLocation">Send location!</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
public/css/.DS_Store
vendored
Normal file
BIN
public/css/.DS_Store
vendored
Normal file
Binary file not shown.
196
public/css/styles.css
Normal file
196
public/css/styles.css
Normal file
@ -0,0 +1,196 @@
|
||||
/* General Styles */
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height: 1.4;
|
||||
color: #333333;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid #eeeeee;
|
||||
padding: 12px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
padding: 12px;
|
||||
background: #7c5cbf;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: #6b47b8;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
cursor: default;
|
||||
background: #7c5cbf94;
|
||||
}
|
||||
|
||||
/* Join Page Styles */
|
||||
|
||||
.centered-form {
|
||||
background: #333744;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.centered-form__box {
|
||||
box-shadow: 0px 0px 17px 1px #1d1f26;
|
||||
background: #f7f7fa;
|
||||
padding: 24px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.centered-form button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.centered-form input {
|
||||
margin-bottom: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Chat Page Layout */
|
||||
|
||||
.chat {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chat__sidebar {
|
||||
height: 100vh;
|
||||
color: rgb(223, 223, 223);
|
||||
background: #333744;
|
||||
width: 225px;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Chat styles */
|
||||
|
||||
.chat__main {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.chat__messages {
|
||||
flex-grow: 1;
|
||||
padding: 24px 24px 0 24px;
|
||||
overflow-y: scroll;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Message Styles */
|
||||
|
||||
.message {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.message__name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.message__meta {
|
||||
color: #777;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.message a {
|
||||
color: #0070cc;
|
||||
}
|
||||
|
||||
/* Message Composition Styles */
|
||||
|
||||
.compose {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
margin-top: 16px;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.compose form {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.compose input {
|
||||
border: 1px solid #eeeeee;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
margin: 0 16px 0 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.compose button {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Chat Sidebar Styles */
|
||||
|
||||
.room-title {
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
background: #2c2f3a;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.list-title {
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
margin-bottom: 4px;
|
||||
padding: 12px 24px 0 24px;
|
||||
}
|
||||
|
||||
.users {
|
||||
text-align: center;
|
||||
list-style-type: none;
|
||||
font-weight: 100;
|
||||
font-style: italic;
|
||||
padding: 12px 24px 0 24px;
|
||||
}
|
||||
|
||||
.welcome-mess {
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
color: #333333;
|
||||
}
|
147
public/css/styles.min.css
vendored
Normal file
147
public/css/styles.min.css
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
body {
|
||||
line-height: 1.4;
|
||||
color: #333;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
}
|
||||
h1 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
label {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
margin-bottom: 8px;
|
||||
color: #777;
|
||||
}
|
||||
input {
|
||||
border: 1px solid #eee;
|
||||
padding: 12px;
|
||||
outline: none;
|
||||
}
|
||||
button {
|
||||
cursor: pointer;
|
||||
padding: 12px;
|
||||
background: #7c5cbf;
|
||||
border: none;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
button:hover {
|
||||
background: #6b47b8;
|
||||
}
|
||||
button:disabled {
|
||||
cursor: default;
|
||||
background: #7c5cbf94;
|
||||
}
|
||||
.centered-form {
|
||||
background: #333744;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.centered-form__box {
|
||||
box-shadow: 0 0 17px 1px #1d1f26;
|
||||
background: #f7f7fa;
|
||||
padding: 24px;
|
||||
width: 250px;
|
||||
}
|
||||
.centered-form button {
|
||||
width: 100%;
|
||||
}
|
||||
.centered-form input {
|
||||
margin-bottom: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
.chat {
|
||||
display: flex;
|
||||
}
|
||||
.chat__sidebar {
|
||||
height: 100vh;
|
||||
color: #fff;
|
||||
background: #333744;
|
||||
width: 225px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.chat__main {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 100vh;
|
||||
}
|
||||
.chat__messages {
|
||||
flex-grow: 1;
|
||||
padding: 24px 24px 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.message {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.message__name {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.message__meta {
|
||||
color: #777;
|
||||
font-size: 14px;
|
||||
}
|
||||
.message a {
|
||||
color: #0070cc;
|
||||
}
|
||||
.compose {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
margin-top: 16px;
|
||||
padding: 24px;
|
||||
}
|
||||
.compose form {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
margin-right: 16px;
|
||||
}
|
||||
.compose input {
|
||||
border: 1px solid #eee;
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
margin: 0 16px 0 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.compose button {
|
||||
font-size: 14px;
|
||||
}
|
||||
.room-title {
|
||||
font-weight: 400;
|
||||
font-size: 22px;
|
||||
background: #2c2f3a;
|
||||
padding: 24px;
|
||||
}
|
||||
.list-title {
|
||||
font-weight: 500;
|
||||
font-size: 18px;
|
||||
margin-bottom: 4px;
|
||||
padding: 12px 24px 0;
|
||||
}
|
||||
.users {
|
||||
list-style-type: none;
|
||||
font-weight: 300;
|
||||
padding: 12px 24px 0;
|
||||
}
|
||||
.myPar {
|
||||
text-align: center;
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
}
|
BIN
public/img/favicon.png
Normal file
BIN
public/img/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
33
public/index.html
Normal file
33
public/index.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Chat</title>
|
||||
<link rel="icon" href="/img/favicon.png">
|
||||
<link rel="stylesheet" href="/css/styles.min.css">
|
||||
<meta name="description" content="Chat">
|
||||
<meta name="author" content="SitePoint">
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="centered-form">
|
||||
<div class="centered-form__box">
|
||||
<h1>Join</h1>
|
||||
<form action="/chat.html">
|
||||
<label>Display name</label>
|
||||
<input type="text" name="username" placeholder="Display name" required>
|
||||
<label>Room</label>
|
||||
<input type="text" name="room" placeholder="Room" required>
|
||||
<button type="submit">Join</button>
|
||||
</form>
|
||||
<p class="myPar">or</p>
|
||||
<button type="submit">Generate room</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
152
public/js/chat.js
Normal file
152
public/js/chat.js
Normal file
@ -0,0 +1,152 @@
|
||||
'use strict';
|
||||
const socket = io();
|
||||
const buttonLocation = document.querySelector('#sendLocation');
|
||||
const form = document.querySelector('#sendMessForm');
|
||||
const formButton = document.querySelector('#formButton');
|
||||
const input = form.childNodes[1];
|
||||
const button = form.childNodes[3];
|
||||
const messageContainer = document.querySelector('#messages-container');
|
||||
const sidebarContainer = document.querySelector('.chat__sidebar');
|
||||
|
||||
// TEMPLATES
|
||||
const sidebarTemplate = `<h2 class="room-title">{{room}}</h2>
|
||||
<h3 class="list-title">Users</h3>
|
||||
<ul class="users">
|
||||
{{#users}}
|
||||
<li>{{username}}</li>
|
||||
{{/users}}
|
||||
</ul>`;
|
||||
|
||||
const htmlTemplate = [
|
||||
`<div class="message">
|
||||
<p>
|
||||
<span class="message__name"> {{user}} </span>
|
||||
<span class="message__meta"> {{createdAt}} </span>
|
||||
</p>
|
||||
<p>{{string}}</p>
|
||||
</div>`,
|
||||
`<div class="message">
|
||||
<p>
|
||||
<span class="message__name"> {{user}} </span>
|
||||
<span class="message__meta"> {{createdAt}} </span>
|
||||
</p>
|
||||
<p><a href="{{string}}">Link</a></p>
|
||||
</div>`,
|
||||
`<div class="message">
|
||||
<p class="welcome-mess">{{string}}</p>
|
||||
</div>`,
|
||||
];
|
||||
|
||||
let message = '';
|
||||
// let user = window.prompt('Please state your username', 'User');
|
||||
|
||||
const autoscroll = () => {
|
||||
// New message elemnt
|
||||
const newMessage = messageContainer.lastElementChild;
|
||||
|
||||
// Height of the new message
|
||||
const newMessageStyles = getComputedStyle(newMessage);
|
||||
const newMessageMargin = parseInt(newMessageStyles.marginBottom);
|
||||
const newMessageHeight = newMessage.offsetHeight + newMessageMargin;
|
||||
|
||||
// Visible height
|
||||
const visibleHeight = messageContainer.offsetHeight;
|
||||
|
||||
// Height of messages container
|
||||
const containerHeight = messageContainer.scrollHeight;
|
||||
|
||||
// scrolloffset
|
||||
const scrolloffset = messageContainer.scrollTop + visibleHeight + 15;
|
||||
|
||||
if (containerHeight - newMessageHeight <= scrolloffset) {
|
||||
console.log('should scroll down');
|
||||
messageContainer.scrollTop = messageContainer.scrollHeight;
|
||||
}
|
||||
};
|
||||
|
||||
const { username, room } = Qs.parse(location.search, {
|
||||
ignoreQueryPrefix: true,
|
||||
});
|
||||
console.log(username, room);
|
||||
|
||||
socket.on('message', (object) => {
|
||||
console.log(object);
|
||||
const string = object.text;
|
||||
const user = object.username;
|
||||
const createdAt = moment(object.createdAt).format('HH:mm:ss');
|
||||
|
||||
if (string.includes('https') || string.includes('http')) {
|
||||
const html = Mustache.render(htmlTemplate[1], {
|
||||
user,
|
||||
string,
|
||||
createdAt,
|
||||
});
|
||||
messageContainer.insertAdjacentHTML('beforeend', html);
|
||||
autoscroll();
|
||||
|
||||
console.log('not includes');
|
||||
} else if (string.includes('Welcome to the server')) {
|
||||
const html = Mustache.render(htmlTemplate[2], {
|
||||
string,
|
||||
});
|
||||
messageContainer.insertAdjacentHTML('beforeend', html);
|
||||
autoscroll();
|
||||
} else {
|
||||
const html = Mustache.render(htmlTemplate[0], {
|
||||
string,
|
||||
user,
|
||||
createdAt,
|
||||
});
|
||||
messageContainer.insertAdjacentHTML('beforeend', html);
|
||||
autoscroll();
|
||||
}
|
||||
});
|
||||
|
||||
form.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
input.focus();
|
||||
|
||||
// Disable form
|
||||
|
||||
if (input.value === '') return;
|
||||
button.setAttribute('disabled', 'disabled');
|
||||
|
||||
socket.emit('message', input.value, (error) => {
|
||||
// Re-enable form
|
||||
button.removeAttribute('disabled');
|
||||
if (error) return console.log(error);
|
||||
console.log('Message delivered');
|
||||
input.value = '';
|
||||
input.focus();
|
||||
});
|
||||
});
|
||||
|
||||
// Send location
|
||||
buttonLocation.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!navigator.geolocation) return alert('No geolocation');
|
||||
buttonLocation.setAttribute('disabled', 'disabled');
|
||||
|
||||
navigator.geolocation.getCurrentPosition((position) => {
|
||||
const { latitude, longitude } = position.coords;
|
||||
const coordsObj = `https://www.google.com/maps/?q=${latitude},${longitude}`;
|
||||
|
||||
socket.emit('message', coordsObj, () => {
|
||||
console.log('Location delivered');
|
||||
buttonLocation.removeAttribute('disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('roomData', ({ room, users }) => {
|
||||
const html = Mustache.render(sidebarTemplate, { room, users });
|
||||
sidebarContainer.innerHTML = html;
|
||||
});
|
||||
|
||||
socket.emit('join', { username, room }, (error) => {
|
||||
if (error) {
|
||||
alert(error);
|
||||
location.href = '/';
|
||||
}
|
||||
});
|
86
src/index.js
Normal file
86
src/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
const express = require('express');
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const socketio = require('socket.io');
|
||||
const Filter = require('bad-words');
|
||||
const { generateMessage } = require('./utils/messages');
|
||||
const {
|
||||
addUser,
|
||||
removeUser,
|
||||
getUser,
|
||||
getUsersInRoom,
|
||||
} = require('./utils/users');
|
||||
|
||||
const app = express();
|
||||
const server = http.createServer(app);
|
||||
const io = socketio(server);
|
||||
|
||||
const port = process.env.PORT || 3000;
|
||||
const publicDirectoryPath = path.join(__dirname, '../public');
|
||||
|
||||
app.use(express.static(publicDirectoryPath));
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
// Welcome message
|
||||
|
||||
socket.on('join', ({ username, room }, callback) => {
|
||||
const { error, user } = addUser({ id: socket.id, username, room });
|
||||
if (error) return callback(error);
|
||||
|
||||
socket.join(user.room); //Join the room
|
||||
|
||||
// emit the message to() specific room
|
||||
socket.emit(
|
||||
'message',
|
||||
generateMessage(`Welcome to the server, ${username}!`)
|
||||
);
|
||||
socket.broadcast
|
||||
.to(user.room)
|
||||
.emit('message', generateMessage(`${user.username} has joined`));
|
||||
io.to(user.room).emit('roomData', {
|
||||
room: user.room,
|
||||
users: getUsersInRoom(user.room),
|
||||
});
|
||||
callback();
|
||||
});
|
||||
|
||||
// On recv message
|
||||
socket.on('message', (message, callback) => {
|
||||
const user = getUser(socket.id);
|
||||
const filter = new Filter();
|
||||
|
||||
if (filter.isProfane(message)) message = filter.clean(message);
|
||||
//callback('Profanity is not allowed');
|
||||
console.log(user);
|
||||
try {
|
||||
io.to(user.room).emit(
|
||||
'message',
|
||||
generateMessage(message, user.username)
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
callback();
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
const user = removeUser(socket.id);
|
||||
if (user)
|
||||
io.to(user.room).emit(
|
||||
'message',
|
||||
generateMessage(`${user.username} has left!`)
|
||||
);
|
||||
io.to(user.room).emit('roomData', {
|
||||
room: user.room,
|
||||
users: getUsersInRoom(user.room),
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('sendLocation', (object, callback) => {
|
||||
callback('Location shared');
|
||||
socket.broadcast.emit('recvObject', generateMessage(object));
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(port, () => console.log(`Server is listening at ${port}`));
|
11
src/utils/messages.js
Normal file
11
src/utils/messages.js
Normal file
@ -0,0 +1,11 @@
|
||||
const generateMessage = (text, username) => {
|
||||
return {
|
||||
text,
|
||||
username,
|
||||
createdAt: new Date().getTime(),
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
generateMessage,
|
||||
};
|
54
src/utils/users.js
Normal file
54
src/utils/users.js
Normal file
@ -0,0 +1,54 @@
|
||||
const users = [];
|
||||
|
||||
// addUser, removeUser, getUser, getUsersInRoom
|
||||
|
||||
const addUser = ({ id, username, room }) => {
|
||||
// Clean the data
|
||||
// username = username.trim().toLowerCase();
|
||||
// room = room.trim().toLowerCase();
|
||||
if (!room || !username)
|
||||
return {
|
||||
error: 'Username and room are required',
|
||||
};
|
||||
// Check for existing user
|
||||
const existingUser = users.find((user) => {
|
||||
return user.room === room && user.username === username;
|
||||
});
|
||||
// Validate username
|
||||
if (existingUser)
|
||||
return {
|
||||
error: 'Username is in use!',
|
||||
};
|
||||
|
||||
// Store user
|
||||
const user = { id, username, room };
|
||||
users.push(user);
|
||||
return { user };
|
||||
};
|
||||
|
||||
const removeUser = (id) => {
|
||||
const index = users.findIndex((user) => user.id === id);
|
||||
if (index !== -1) {
|
||||
// console.log(users[id])
|
||||
return users.splice(index, 1)[0];
|
||||
}
|
||||
};
|
||||
|
||||
const getUser = (id) => {
|
||||
const foundUser = users.find((user) => user.id === id);
|
||||
if (!foundUser) return undefined;
|
||||
return foundUser;
|
||||
};
|
||||
|
||||
const getUsersInRoom = (room) => {
|
||||
const usersInRoom = users.filter((user) => user.room === room);
|
||||
if (!usersInRoom) return [];
|
||||
return usersInRoom;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
addUser,
|
||||
removeUser,
|
||||
getUser,
|
||||
getUsersInRoom,
|
||||
};
|
Loading…
Reference in New Issue
Block a user