a lot of changes in back and front ;)
This commit is contained in:
parent
6cb2bea05b
commit
a500916712
373
src/index.js
373
src/index.js
|
@ -2,10 +2,10 @@ const express = require('express');
|
|||
const bcrypt = require('bcrypt');
|
||||
const cors = require("cors");
|
||||
const WebSocket = require('ws');
|
||||
const http = require('http')
|
||||
const http = require('http');
|
||||
const session = require('express-session');
|
||||
|
||||
clients = []; // websocket clients
|
||||
sessions = {}; // logged in clients, there are stored their tokens.
|
||||
sessions = {}; // logged in clients, there are stored objects like {"token": "some_token_here", "socket": here-is-websocket-object}
|
||||
|
||||
const middleware = require("./middleware");
|
||||
const utils = require("./utils")
|
||||
|
@ -20,21 +20,40 @@ const httpServer = http.createServer(app).listen(PORT, "0.0.0.0", () => {
|
|||
console.log("[LOG] Ready to use.");
|
||||
});
|
||||
|
||||
const ws = new WebSocket.Server({
|
||||
server: httpServer,
|
||||
host: "0.0.0.0"
|
||||
const wss = new WebSocket.WebSocketServer({ clientTracking: false, noServer: true });
|
||||
|
||||
const onSocketError = (err) => {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
httpServer.on('upgrade', (request, socket, head) => {
|
||||
socket.on('error', onSocketError);
|
||||
|
||||
sessionParser(request, {}, () => {
|
||||
if (!request.session.token) {
|
||||
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
socket.removeListener('error', onSocketError);
|
||||
|
||||
wss.handleUpgrade(request, socket, head, function (ws) {
|
||||
wss.emit('connection', ws, request);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
console.log("[LOG] Socket has been started");
|
||||
wss.on('connection', function (ws, request) {
|
||||
const token = request.session.token;
|
||||
|
||||
ws.on('connection', (wsclient) => {
|
||||
clients.push(wsclient)
|
||||
sessions[token].socket = ws;
|
||||
|
||||
ws.on('error', console.error);
|
||||
|
||||
/*
|
||||
Package structure:
|
||||
{
|
||||
"action": "...", // the request
|
||||
"token": "...", // the token that is the key for sessions dictionary
|
||||
"content": ..., // the rest content of an action.
|
||||
}
|
||||
|
||||
|
@ -42,51 +61,91 @@ ws.on('connection', (wsclient) => {
|
|||
message:
|
||||
{
|
||||
"action": "message",
|
||||
"token": "some_token_here",
|
||||
"content": {
|
||||
"chatId": 1,
|
||||
"text": "Hello!"
|
||||
}
|
||||
}
|
||||
*/
|
||||
ws.on('message', async (message) => {
|
||||
message = JSON.parse(message);
|
||||
switch (message.action) {
|
||||
case "message": {
|
||||
let chatId = message.content.chatId;
|
||||
let text = message.content.text;
|
||||
let userId = sessions[token].userId
|
||||
|
||||
wsclient.on('message', async (msg) => {
|
||||
try {
|
||||
let jsonMsg = JSON.parse(msg)
|
||||
switch (jsonMsg.action) {
|
||||
case "message":{
|
||||
let userId = sessions[jsonMsg.token];
|
||||
console.log(`${userId} has sent a message: ${jsonMsg.content.text} to ${jsonMsg.content.chatId}`);
|
||||
let r = await client.query("SELECT ID FROM Chats WHERE ID = $1", [chatId]);
|
||||
if (r.rowCount == 0) { // no such chat exist
|
||||
sessions[token].socket.send(`No chat with ID ${chatId} exist.`);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((await client.query("SELECT ID FROM Users WHERE ID = $1 AND $2 = ANY(chats)", [userId, chatId])).rowCount == 0) {
|
||||
ws.send("You are not a member of this chat.");
|
||||
}
|
||||
|
||||
default:
|
||||
console.log(`Package cannot be understood: ${msg}`)
|
||||
//Inserting a message into database.
|
||||
let messageId = (await client.query("INSERT INTO Messages (author_id, time_sent, content) VALUES($1, NOW(), $2) RETURNING ID", [userId, text])).rows[0].id;
|
||||
await client.query("UPDATE Chats SET messages = ARRAY_APPEND(messages, $1) WHERE ID = $2", [messageId, chatId])
|
||||
// sessions[token].socket.send("successful");
|
||||
|
||||
//Sending a message to everyone who is in the group.
|
||||
|
||||
let membersIds = (await client.query("SELECT ID FROM Users WHERE $1 = ANY(chats)", [chatId])).rows
|
||||
let Ids = [];
|
||||
for (let mId of membersIds) {
|
||||
Ids.push(mId.id)
|
||||
}
|
||||
|
||||
// find all sessions by IDs and send to their sockets
|
||||
for (const [key, value] of Object.entries(sessions)) {
|
||||
let session = value;
|
||||
if (session == undefined) continue
|
||||
if (session.userId == userId) continue; // Skip the sender of the message
|
||||
if (Ids.includes(session.userId)) {
|
||||
session.socket.send(JSON.stringify({
|
||||
action: "message",
|
||||
content: {
|
||||
chatId: chatId,
|
||||
authorId: userId,
|
||||
text: text
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.log(`[ERROR] Package cannot be understood: ${JSON.stringify(message)}`);
|
||||
sessions[token].socket.send("Package cannot be understood.")
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in receiving message by websocket: ${e}`)
|
||||
}
|
||||
});
|
||||
|
||||
wsclient.on('close', () => {
|
||||
clients = clients.filter(c => c !== wsclient)
|
||||
})
|
||||
})
|
||||
ws.on('close', function () {
|
||||
// sessions[token].socket = undefined
|
||||
});
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(require('express-session')({
|
||||
console.log("[LOG] Socket has been started");
|
||||
|
||||
|
||||
const sessionParser = session({
|
||||
name: 'smk_chat',
|
||||
secret: 'PLEASE!!GENERATE!!A!!STRONG!!ONE!!',
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
});
|
||||
|
||||
}));
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(sessionParser);
|
||||
app.use('/js', express.static(__dirname + "/js"));
|
||||
|
||||
|
||||
//======================frontend===========================
|
||||
app.get('/', middleware.requireToBeLoggedIn, (req, res) => {
|
||||
res.sendFile('views/index.html', { root: __dirname });
|
||||
});
|
||||
|
@ -99,41 +158,124 @@ app.get('/login', middleware.requireToBeNotLoggedIn, (req, res) => {
|
|||
res.sendFile('views/login.html', { root: __dirname });
|
||||
});
|
||||
|
||||
app.get('/chat/:chatId', middleware.requireToBeLoggedIn, (req, res) => {
|
||||
res.sendFile('views/chat.html', { root: __dirname })
|
||||
});
|
||||
|
||||
//======================backend===========================
|
||||
|
||||
|
||||
//IN: userId (in route)
|
||||
//OUT: lastname, firstname, middlename
|
||||
//Return credentials of the user whose id is userId.
|
||||
//Return -1 if no such user exist.
|
||||
//Requires client to be logged in.
|
||||
app.get('/api/getCredentialsById/:id', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const userId = req.params.id;
|
||||
let user = (await client.query("SELECT lastname, firstname, middlename FROM Users WHERE ID = $1", [userId])).rows[0];
|
||||
if (user == undefined) return res.send("-1").status(400).end();
|
||||
return res.send(user).status(200).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getCredentialsById/${req.params.id}}: ${e}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//IN: lastname, firstname, middlename
|
||||
//OUT: UserID
|
||||
//Returns an ID of the user, whose lastname, firstname and middlename were passed.
|
||||
//Returns -1 if user does not exist.
|
||||
//Requires client to be logged in.
|
||||
app.get('/api/getIdByCredentials', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
const { lastname, firstname, middlename } = req.body;
|
||||
|
||||
return res.send(await utils.getIdByCredentials(lastname, firstname, middlename)).end();
|
||||
app.get('/api/getIdByCredentials', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const { lastname, firstname, middlename } = req.body;
|
||||
|
||||
return res.send(await utils.getIdByCredentials(lastname, firstname, middlename)).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getIdByCredentials: ${e}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//IN: chatId, amount
|
||||
//OUT: array of objects that represent a message, like {"author_id": ..., time_sent: ..., content: ...}
|
||||
//Returns an array of last ${amount} ordered by date of described objects if everything is okay
|
||||
//Returns HTTP/1.1 400 "Chat with id ${ID} does not exist." if no chat with supplied id does not exist.
|
||||
//Returns HTTP/1.1 403 "You are not a member of this chat" if the statement is true ;)
|
||||
//Requires client to be logged in.
|
||||
app.post('/api/getMessagesFromChat/by-amount', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const userId = sessions[req.session.token].userId;
|
||||
|
||||
const { chatId, amount } = req.body;
|
||||
let messages = []
|
||||
|
||||
if ((await client.query("SELECT ID FROM Users WHERE ID = $1 AND $2 = ANY(Chats)", [userId, chatId]).rowCount == 0)) {
|
||||
return res.status(403).send("You are not a member of this chat");
|
||||
}
|
||||
|
||||
if ((await client.query("SELECT ID FROM Chats WHERE ID = $1", [chatId])).rowCount == 0) {
|
||||
return res.status(400).send(`Chat with id ${chatId} does not exist.`).end()
|
||||
}
|
||||
|
||||
let result = await client.query("SELECT messages FROM Chats WHERE ID = $1 LIMIT $2", [chatId, amount])
|
||||
|
||||
let messagesIds = result.rows[0].messages;
|
||||
|
||||
if (messagesIds == null || messagesIds == undefined) return res.send("").status(200).end();
|
||||
|
||||
|
||||
let selectedMessagesIds = messagesIds.slice(-amount);
|
||||
|
||||
if (selectedMessagesIds == null || selectedMessagesIds == undefined) return res.send("").status(200).end();
|
||||
for (let id of selectedMessagesIds) {
|
||||
let message = (await client.query("SELECT * FROM messages WHERE ID = $1 ORDER BY time_sent DESC LIMIT $2", [id, amount])).rows[0];
|
||||
messages.push(message)
|
||||
}
|
||||
return res.send(messages).status(200).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getMessagesFromChat/by-amount: ${e}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//IN: chatId, fromTimestamp, toTimestamp
|
||||
//OUT: array of objects that represent a message, like {"author_id": ..., time_sent: ..., content: ...}
|
||||
//fromTimestamp must be lower that toTimestamp, otherwise it might return nothing.
|
||||
//Returns an array of described objects.
|
||||
//Return "Chat with id ${ID} does not exist." if no chat with supplied id does not exist.
|
||||
//Returns an array of described objects if everything is okay
|
||||
//Returns HTTP/1.1 400 "Chat with id ${ID} does not exist." if no chat with supplied id does not exist.
|
||||
//Returns HTTP/1.1 200 and an empty string if no messages in chat are found /shrug.
|
||||
//Requires client to be logged in.
|
||||
app.post('/api/getMessagesFromChat', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
const userId = sessions[req.session.token];
|
||||
app.post('/api/getMessagesFromChat/by-time', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const userId = sessions[req.session.token].userId;
|
||||
|
||||
const { chatId, fromTimestamp, toTimestamp } = req.body;
|
||||
let messages = []
|
||||
const { chatId, fromTimestamp, toTimestamp } = req.body;
|
||||
let messages = []
|
||||
|
||||
if ((await client.query("SELECT ID FROM Chats WHERE ID = $1", [chatId])).rowCount == 0) {
|
||||
return res.status(400).send(`Chat with id ${chatId} does not exist.`).end()
|
||||
if ((await client.query("SELECT ID FROM Chats WHERE ID = $1", [chatId])).rowCount == 0) {
|
||||
return res.status(400).send(`Chat with id ${chatId} does not exist.`).end()
|
||||
}
|
||||
|
||||
let result = await client.query("SELECT messages FROM Chats WHERE ID = $1", [chatId])
|
||||
|
||||
let messagesIds = result.rows[0].messages;
|
||||
if (messagesIds == null) return res.send("").status(200).end();
|
||||
for (let id of messagesIds) {
|
||||
let message = (await client.query("SELECT * FROM messages WHERE ID = $1 AND time_sent <= $2::TIMESTAMP AND time_sent >= $3::TIMESTAMP", [id, toTimestamp, fromTimestamp])).rows[0];
|
||||
if (message == undefined) continue
|
||||
messages.push(message)
|
||||
}
|
||||
return res.send(messages).status(200).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getMessagesFromChat/by-time: ${e}`);
|
||||
res.status(500).send();
|
||||
}
|
||||
|
||||
let messagesIds = (await client.query("SELECT messages FROM Chats WHERE ID = $1", [chatId])).rows[0].messages;
|
||||
for (let id of messagesIds) {
|
||||
let message = (await client.query("SELECT * FROM messages WHERE ID = $1 AND time_sent <= $2::TIMESTAMP AND time_sent >= $3::TIMESTAMP", [id, toTimestamp, fromTimestamp])).rows[0];
|
||||
messages.push(message)
|
||||
}
|
||||
return res.send(messages).status(200).end();
|
||||
});
|
||||
|
||||
|
||||
|
@ -142,45 +284,101 @@ app.post('/api/getMessagesFromChat', middleware.requireToBeLoggedIn, async (req,
|
|||
//Returs ids of chats which user with passed ID is member in.
|
||||
//Return empty string if user has no membership in any chat.
|
||||
app.get('/api/getChats', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const userId = sessions[req.session.token].userId
|
||||
|
||||
const userId = sessions[req.session.token]
|
||||
let chats = (await client.query("SELECT chats FROM Users WHERE ID = $1", [userId])).rows[0].chats
|
||||
return res.send(chats).status(200).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getChats: ${e}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
|
||||
let chats = (await client.query("SELECT chats FROM Users WHERE ID = $1", [userId])).rows[0].chats
|
||||
return res.send(chats).status(200).end();
|
||||
//IN: chatId (in route)
|
||||
//OUT: JSON describes a chat with id:
|
||||
//{name: ..., admins: ..., members: ...}
|
||||
//Note: JSON does not include messages. You have to use /api/getMessagesFromChat to query messages.
|
||||
//Returns aforementioned json if the chat exists and user is a member of this chat.
|
||||
//Returns -1 if chat does not exist
|
||||
//Return -2 if user is not a member of the chat
|
||||
app.get('/api/getChatInfo/:chatId', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
try {
|
||||
const chatId = req.params.chatId;
|
||||
|
||||
if (Number(chatId) != chatId) return res.send("-1").status(400).end();
|
||||
|
||||
let chatRequest = await client.query("SELECT name, admins FROM Chats WHERE ID = $1::INT", [chatId]);
|
||||
if (chatRequest.rowCount == 0) return res.send("-1").status(400).end();
|
||||
|
||||
|
||||
let membersRequest = await client.query("SELECT ID FROM Users WHERE $1 = ANY(chats)", [chatId]);
|
||||
|
||||
let members = [];
|
||||
|
||||
membersRequest.rows.forEach((member, index, membersRequest) => {
|
||||
members.push(member.id)
|
||||
});
|
||||
// console.log(members)
|
||||
// console.log(sessions[req.session.token])
|
||||
if (!members.includes(sessions[req.session.token].userId)) {
|
||||
return res.send("-2").status(403).end();
|
||||
}
|
||||
|
||||
let chatInfo = {
|
||||
name: chatRequest.rows[0].name,
|
||||
admins: chatRequest.rows[0].admins,
|
||||
members: members
|
||||
};
|
||||
|
||||
return res.send(JSON.stringify(chatInfo)).status(200).end();
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/getChatInfo/${req.params.chatId}: ${e}`);
|
||||
res.status(500).send();
|
||||
}
|
||||
});
|
||||
|
||||
//IN: UserId, array of UserIDs that are to be invited.
|
||||
//OUT: "Ok" if succsessful, "User with id ${MEMBERID} does not exist."
|
||||
//OUT: "Ok" if successful, "User with id ${MEMBERID} does not exist."
|
||||
//Return -1 if amout of users to invite is 0.
|
||||
//Requires to be logged in
|
||||
app.post('/api/createChat', middleware.requireToBeLoggedIn, async (req, res) => {
|
||||
const userId = sessions[req.session.token]
|
||||
let { toInviteIds } = req.body;
|
||||
try {
|
||||
const userId = sessions[req.session.token].userId
|
||||
let { toInviteIds } = req.body;
|
||||
if (toInviteIds == "" || toInviteIds == undefined || toInviteIds == null) return res.send("-1").status(400).end();
|
||||
|
||||
toInviteIds = toInviteIds.split(" ");
|
||||
toInviteIds = toInviteIds.split(" ");
|
||||
|
||||
toInviteIds.forEach(async (id, index, toInviteIds) => {
|
||||
if ((await client.query("SELECT ID FROM Users WHERE ID = $1", [id])).rowCount == 0) {
|
||||
return res.send(`User with id ${id} does not exist.`)
|
||||
toInviteIds.forEach(async (id, index, toInviteIds) => {
|
||||
if ((await client.query("SELECT ID FROM Users WHERE ID = $1", [id])).rowCount == 0) {
|
||||
return res.send(`User with id ${id} does not exist.`).end();
|
||||
}
|
||||
});
|
||||
|
||||
let chatName
|
||||
if (toInviteIds.length == 1) {
|
||||
let invitedFullname = (await client.query("SELECT lastname, firstname, middlename FROM Users WHERE ID = $1;", [toInviteIds[0]])).rows[0]
|
||||
let invitorFullname = (await client.query("SELECT lastname, firstname, middlename FROM Users WHERE ID = $1;", [userId])).rows[0]
|
||||
chatName = invitedFullname.lastname + " " + invitedFullname.firstname + " " + invitedFullname.middlename + " и " + invitorFullname.lastname + " " + invitorFullname.firstname + " " + invitorFullname.middlename
|
||||
} else {
|
||||
chatName = "Новая группа"
|
||||
}
|
||||
});
|
||||
|
||||
let chatName
|
||||
if (toInviteIds.length == 1) {
|
||||
let invitedFullname = (await client.query("SELECT lastname, firstname, middlename FROM Users WHERE ID = $1;", [toInviteIds[0]])).rows[0]
|
||||
let invitorFullname = (await client.query("SELECT lastname, firstname, middlename FROM Users WHERE ID = $1;", [userId])).rows[0]
|
||||
chatName = invitedFullname.lastname + " " + invitedFullname.firstname + " " + invitedFullname.middlename + " и " + invitorFullname.lastname + " " + invitorFullname.firstname + " " + invitorFullname.middlename
|
||||
} else {
|
||||
chatName = "Новая группа"
|
||||
let chatId = (await client.query("INSERT INTO Chats (name) VALUES ($1) RETURNING ID;", [chatName])).rows[0].id
|
||||
|
||||
await client.query("UPDATE Chats SET admins = ARRAY_APPEND(admins, $1) WHERE ID = $2", [userId, chatId]);
|
||||
|
||||
toInviteIds.push(userId); // we need to invite the admin, too :)
|
||||
toInviteIds.forEach(async (id, index, toInviteIds) => {
|
||||
await client.query("UPDATE Users SET chats = ARRAY_APPEND(chats, $1) WHERE ID = $2;", [chatId, id]);
|
||||
});
|
||||
|
||||
return res.send("Ok");
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/createChat: ${e}`);
|
||||
res.status(500).send();
|
||||
}
|
||||
|
||||
let chatId = (await client.query("INSERT INTO Chats (name) VALUES ($1) RETURNING ID;", [chatName])).rows[0].id
|
||||
|
||||
await client.query("UPDATE Chats SET admins = ARRAY_APPEND(admins, $1) WHERE ID = $2", [userId, chatId]);
|
||||
|
||||
toInviteIds.forEach(async (id, index, toInviteIds) => {
|
||||
await client.query("UPDATE Users SET chats = ARRAY_APPEND(chats, $1) WHERE ID = $2;", [chatId, id]);
|
||||
});
|
||||
return res.send("Ok")
|
||||
});
|
||||
|
||||
//IN: none.
|
||||
|
@ -188,9 +386,15 @@ app.post('/api/createChat', middleware.requireToBeLoggedIn, async (req, res) =>
|
|||
//Removes client's session, thus unlogging a user.
|
||||
//Requires to be logged in.
|
||||
app.get('/api/logout', middleware.requireToBeLoggedIn, (req, res) => {
|
||||
sessions[req.session.token] = undefined;
|
||||
req.session.token = undefined;
|
||||
res.redirect('/login');
|
||||
try {
|
||||
sessions[req.session.token] = undefined;
|
||||
req.session.token = undefined;
|
||||
res.redirect('/login');
|
||||
} catch (e) {
|
||||
console.log(`[ERROR] in /api/logout: ${e}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//IN: lastname, firstname, middlename, password.
|
||||
|
@ -214,7 +418,10 @@ app.post('/api/register', middleware.requireToBeNotLoggedIn, async (req, res) =>
|
|||
[lastname, firstname, middlename, hash]
|
||||
)).rows[0].id;
|
||||
req.session.token = utils.generateRandomString();
|
||||
sessions[req.session.token] = id;
|
||||
sessions[req.session.token] = {
|
||||
userId: id,
|
||||
socket: undefined
|
||||
};
|
||||
res.redirect('/');
|
||||
} catch (err) {
|
||||
console.log(`[ERROR] in /api/register: ${err}`)
|
||||
|
@ -240,7 +447,10 @@ app.post('/api/login', middleware.requireToBeNotLoggedIn, async (req, res) => {
|
|||
|
||||
if (bcrypt.compareSync(password, stored_password)) {
|
||||
req.session.token = utils.generateRandomString()
|
||||
sessions[req.session.token] = ID;
|
||||
sessions[req.session.token] = {
|
||||
userId: ID,
|
||||
socket: undefined
|
||||
};
|
||||
return res.redirect('/');
|
||||
} else {
|
||||
return res.status(400).send("Wrong password").end();
|
||||
|
@ -249,5 +459,4 @@ app.post('/api/login', middleware.requireToBeNotLoggedIn, async (req, res) => {
|
|||
console.log(`[ERROR] in /api/login: ${err}`)
|
||||
res.status(500).send();
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
const sendMessage = (event) => {
|
||||
if (event.key == "Enter") {
|
||||
console.log(event);
|
||||
}
|
||||
}
|
||||
|
||||
const createMessageElement = async (message) => {
|
||||
|
||||
let author = JSON.parse(await fetch(`/api/getCredentialsById/${message.author_id}`).then(response => response.text()).then((response) => { return response; }))
|
||||
|
||||
|
||||
let messageDiv = document.createElement("div");
|
||||
messageDiv.id = `message-${message.id}`;
|
||||
messageDiv.style = "background-color: gray; box-shadow: 1px 1px; margin: 10px; padding: 5px"
|
||||
|
||||
let authorName = document.createElement("b");
|
||||
authorName.innerText = `${author.firstname}:`;
|
||||
|
||||
let messageContent = document.createElement("p");
|
||||
messageContent.innerText = message.content;
|
||||
messageContent.id = "content";
|
||||
|
||||
let messageTime = document.createElement("i");
|
||||
messageTime.innerText = `@ ${message.time_sent.toString()}`;
|
||||
messageTime.id = "time_sent";
|
||||
|
||||
messageDiv.appendChild(authorName);
|
||||
messageDiv.appendChild(messageContent);
|
||||
messageDiv.appendChild(messageTime);
|
||||
|
||||
return messageDiv
|
||||
}
|
||||
|
||||
|
||||
window.addEventListener('load', async function () {
|
||||
let location = window.location.href.split("/")
|
||||
const chatId = location[location.length - 1];
|
||||
|
||||
let chatInfo = JSON.parse(
|
||||
await fetch(`/api/getChatInfo/${chatId}`).then(response => response.text()).then(response => { return response })
|
||||
);
|
||||
console.log(chatInfo)
|
||||
let header = document.getElementById('header-text');
|
||||
header.innerText = chatInfo.name;
|
||||
let content = document.getElementById('content-div')
|
||||
|
||||
|
||||
let today = new Date();
|
||||
let yesterday = new Date();
|
||||
yesterday.setUTCDate(today.getUTCDate() - 10);
|
||||
console.log(today.toISOString(), yesterday.toISOString())
|
||||
// fetching messages from yesterday to today
|
||||
let messages = await fetch("/api/getMessagesFromChat/by-time", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
chatId: chatId,
|
||||
fromTimestamp: yesterday.toISOString(),
|
||||
toTimestamp: today.toISOString()
|
||||
})
|
||||
}).then(response => response.text()).then((response) => { return response; })
|
||||
messages = eval(messages)
|
||||
for (let message of messages) {
|
||||
content.appendChild(await createMessageElement(message));
|
||||
}
|
||||
console.log(messages)
|
||||
});
|
|
@ -1,35 +0,0 @@
|
|||
let socket
|
||||
|
||||
function getCookie(name) {
|
||||
const value = `; ${document.cookie}`;
|
||||
const parts = value.split(`; ${name}=`);
|
||||
if (parts.length === 2) return parts.pop().split(';').shift();
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
let connectionString = location.protocol == "https:" ? `wss://${window.location.hostname}:${window.location.port}` : `ws://${window.location.hostname}:${window.location.port}`
|
||||
socket = new WebSocket(connectionString)
|
||||
console.log(getCookie("token"))
|
||||
socket.addEventListener('open', (e) => {
|
||||
socket.send(JSON.stringify(
|
||||
{
|
||||
"action": "message",
|
||||
"token": getCookie("token"),
|
||||
"content": {
|
||||
"chatId": 1,
|
||||
"text": "test"
|
||||
}
|
||||
}
|
||||
));
|
||||
})
|
||||
|
||||
fetch("/api/getMessagesFromChat", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ chatId: 1, fromTimestamp: '2012.01.01 00:00:00.000000', toTimestamp: '2026.01.01 00:00:00.000000' })
|
||||
}).then(response => response.text())
|
||||
.then((response => console.log(response)))
|
||||
})
|
|
@ -0,0 +1,84 @@
|
|||
let socket
|
||||
|
||||
window.addEventListener('load', async function () {
|
||||
let connectionString = location.protocol == "https:" ? `wss://${window.location.hostname}:${window.location.port}` : `ws://${window.location.hostname}:${window.location.port}`
|
||||
socket = new WebSocket(connectionString)
|
||||
socket.addEventListener('open', (e) => {
|
||||
socket.send(JSON.stringify(
|
||||
{
|
||||
"action": "message",
|
||||
"content": {
|
||||
"chatId": 1,
|
||||
"text": "test"
|
||||
}
|
||||
}
|
||||
));
|
||||
})
|
||||
|
||||
socket.addEventListener('message', (m) => {
|
||||
if (m.data == "successful") return;
|
||||
const data = JSON.parse(m.data)
|
||||
switch (data.action) {
|
||||
case "message": {
|
||||
console.log(`New message in chat ${data.content.chatId} from ${data.content.authorId}, which says '${data.content.text}'`)
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let chatsIds = await fetch("/api/getChats").then(response => response.text()).then((response) => {
|
||||
return response
|
||||
})
|
||||
let chats = []; // chats with their info
|
||||
chatsIds = eval(chatsIds)
|
||||
for (let chat of chatsIds) {
|
||||
let chatInfo = await fetch(`/api/getChatInfo/${chat}`).then(response => response.text()).then(response => { return response });
|
||||
chatInfo = JSON.parse(chatInfo)
|
||||
chatInfo.id = chat
|
||||
let lastMessage = await fetch(`/api/getMessagesFromChat/by-amount`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ chatId: chat, amount: 1 })
|
||||
}).then(response => response.text()).then((response) => { return response });
|
||||
|
||||
if (lastMessage == undefined || lastMessage == "") {
|
||||
chatInfo.lastMessage = {
|
||||
id: "",
|
||||
author_id: "",
|
||||
time_sent: "",
|
||||
content: ""
|
||||
}
|
||||
chats.push(chatInfo)
|
||||
continue
|
||||
}
|
||||
|
||||
chatInfo.lastMessage = JSON.parse(lastMessage)[0]
|
||||
chats.push(chatInfo);
|
||||
}
|
||||
|
||||
|
||||
let chatsContainer = this.document.getElementById('chats');
|
||||
for (let chat of chats) {
|
||||
let chatHTML = `
|
||||
<div class=\"chat-entry\" name=\"${chat.name}\">
|
||||
<p>
|
||||
<a href=\"/chat/${chat.id}\">${chat.name}</a> | ${chat.lastMessage.author_id}: ${chat.lastMessage.content} ${chat.lastMessage.time_sent}
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
chatsContainer.innerHTML += chatHTML;
|
||||
}
|
||||
|
||||
fetch("/api/getMessagesFromChat/by-time", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ chatId: 1, fromTimestamp: '2012.01.01 00:00:00.000000', toTimestamp: '2026.01.01 00:00:00.000000' })
|
||||
}).then(response => response.text())
|
||||
// .then((response => console.log(response)))
|
||||
})
|
|
@ -6,7 +6,8 @@ const { Client } = pg;
|
|||
client = new Client({
|
||||
user: "smk",
|
||||
password: "CHANGEME", // do not forget to change it in docker-compose.yml in db section.
|
||||
host: "10.5.0.6", //defined in docker-compose.yml.
|
||||
// host: "10.5.0.6", //defined in docker-compose.yml.
|
||||
host: 'localhost',
|
||||
port: 5432,
|
||||
database: "chat"
|
||||
});
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Chat</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="header-div">
|
||||
<b id="header-text"></b>
|
||||
</div>
|
||||
<div id="content-div"></div>
|
||||
<div id="typefield-div">
|
||||
<input type="text" onkeypress="sendMessage(event)">
|
||||
</div>
|
||||
</body>
|
||||
<script src="/js/chat.js"></script>
|
||||
|
||||
</html>
|
|
@ -5,6 +5,9 @@
|
|||
<title>index</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="chats" name="chats" id="chats">
|
||||
|
||||
</div>
|
||||
<form action="/api/createChat" method="POST">
|
||||
<label for="toInviteIds">ID пользователей для приглашения через пробел</label><br/>
|
||||
<input type="text" id="toInviteIds" name="toInviteIds"><br/>
|
||||
|
@ -13,5 +16,5 @@
|
|||
</form>
|
||||
<a href="/api/logout">Выйти</a>
|
||||
</body>
|
||||
<script src="/js/frontend.js"></script>
|
||||
<script src="/js/index.js"></script>
|
||||
</html>
|
Loading…
Reference in New Issue