done chat

This commit is contained in:
leca 2025-02-06 15:22:32 +03:00
parent 60e093f123
commit 37c170b265
9 changed files with 90 additions and 11 deletions

View File

@ -97,13 +97,14 @@ canvas {
}
.chat-container {
overflow: scroll;
border: black solid
}
.messages-container {
width: 100%;
height: 75%;
overflow: scroll;
overflow-wrap: anywhere;
border: gray solid;
}
@ -126,3 +127,10 @@ canvas {
margin: 0;
padding: 0
}
.chat-message {
margin-top: 8px;
margin-bottom: 8px;
margin-left: 8px;
margin-right: 16px;
}

View File

@ -4,21 +4,50 @@ function getCookie(name) {
if (parts.length === 2) return parts.pop().split(';').shift();
}
$(document).ready(() => {
//prod
// const socket = new WebSocket('wss://auth.foxarmy.org');
//dev
const socket = new WebSocket('ws://localhost:3000');
$(document).ready(async () => {
const wsConnectionString = (await fetch(`/api/websocketConnection`)).text()
const socket = new WebSocket(wsConnectionString);
let lastMessageNumber = 0;
let page = 20;
const fetchMoreMessages = async () => {
if (lastMessageNumber < 0 ) return [];
let messages = await (await fetch(`/api/getChatMessages/${lastMessageNumber}/${page}`)).json();
lastMessageNumber = messages.length < page? -1 : lastMessageNumber + messages.length
return messages
}
const appendMessageToChat = (author, content) => {
const messageDiv = document.createElement('div')//`<div class="chat-message" ><${message.author}> ${message.content}</div><br/>`
const messageDiv = document.createElement('div')
messageDiv.className = "chat-message"
messageDiv.textContent = `<${author}> ${content}`
document.getElementsByClassName("messages-container")[0].appendChild(messageDiv)
}
socket.onmessage = message => {
const prependMessageToChat = (author, content) => {
const messageDiv = document.createElement('div')
messageDiv.className = "chat-message"
messageDiv.textContent = `<${author}> ${content}`
const messageContainer = document.getElementsByClassName("messages-container")[0]
messageContainer.firstChild.insertAdjacentElement('afterend', messageDiv)
}
const onFetchMessageButtonClick = async () => {
let messages = await fetchMoreMessages(lastMessageNumber, page);
if (messages.length == 0) return;
messages.forEach(message => {
prependMessageToChat(message.author, message.content);
});
}
$("#fetch-messages-button").click(onFetchMessageButtonClick);
await onFetchMessageButtonClick();
socket.onmessage = message => {
try {
message = JSON.parse(message.data)
} catch(e) {
@ -40,6 +69,8 @@ $(document).ready(() => {
socket.send(JSON.stringify(message));
appendMessageToChat(message.author, message.content)
$("#chat-input").val("")
let messageContainer = $(".messages-container")
messageContainer.animate({ scrollTop: messageContainer.prop("scrollHeight")}, 1000);
}
$("#send-message-button").click(sendData);

View File

@ -7,3 +7,4 @@ DBPASS=GENERATE_A_STRONG_PASSWORD_HERE
PORT=3000
REQUIRE_TOKEN=false
DELETE_TOKEN_ON_USE=true
WS_CONNECTION_STRING=wss://auth.foxarmy.org

20
src/controllers/api.js Normal file
View File

@ -0,0 +1,20 @@
import ApiService from "../services/api.js";
import dotenv from 'dotenv';
dotenv.config({path: ".env"});
class ApiController {
async getChatMessages(req, res) {
const {limit, offset} = req.params;
const messages = await ApiService.getChatMessages(limit, offset);
return res.status(200).send(messages);
}
async getWebsocketConnection(req, res) {
return res.status(200).send(process.env.WS_CONNECTION_STRING)
}
}
export default new ApiController();

View File

@ -91,6 +91,8 @@ const startChat = async () => {
origin: "website"
})
}]
}).catch(e => {
console.log(e)
});
// we are not sending this message to all websockets right now, because plugin will emit
// a chat event once it'll catch this message from kafka, triggering a new message

View File

@ -26,7 +26,6 @@ const validateInviteToken = async (req, res, next) => {
let tokenValid = false;
inviteTokens.forEach((token) => {
console.log(`${token} == ${inviteToken}`)
if (token == inviteToken) tokenValid = true;
});

View File

@ -6,6 +6,7 @@ import auth from '../middlewares/auth.js';
import utils from '../utils.js';
import UserController from '../controllers/user.js';
import ApiController from '../controllers/api.js';
const ApiRouter = new Router();
@ -16,5 +17,7 @@ ApiRouter.post('/changepassword', auth.authenticate, existance.userExist, UserCo
ApiRouter.post('/uploadSkin', existance.userExist, auth.authenticate, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadSkin);
ApiRouter.post('/uploadCape', existance.userExist, auth.authenticate, auth.canHaveCloak, utils.upload.single('file'), requiredParameters.requireFile, UserController.uploadCape);
ApiRouter.get('/getUsername', existance.userExist, auth.authenticate, UserController.getUsername);
ApiRouter.get('/getChatMessages/:offset/:limit', auth.authenticate, ApiController.getChatMessages);
ApiRouter.get('/webSocketConnection', auth.authenticate, ApiController.getWebsocketConnection)
export default ApiRouter;

15
src/services/api.js Normal file
View File

@ -0,0 +1,15 @@
import db from '../db.js';
class ApiService {
async getChatMessages(limit, offset) {
try {
const messages = (await db.query("SELECT * FROM chat_messages ORDER BY ID DESC LIMIT $1 OFFSET $2", [limit, offset])).rows
return messages
} catch(e) {
console.log(e)
}
}
}
export default new ApiService();

View File

@ -15,7 +15,7 @@ html
h1 Чат
div(class="chat-container")
div(class="messages-container")
button(id="fetch-messages-button") Загрузить ещё
div(class="input-container")
input(type="text" id="chat-input")
button(id="send-message-button") Отправить