Files
yourpart3/backend/services/chatService.js
Torsten Schulz (local) 19ee6ba0a1 Add password reset localization and chat configuration
- Implemented German and English localization for password reset functionality.
- Added WebSocket URL resolution logic in chat services to support various environments and configurations.
- Created centralized chat configuration for event keys and payload mappings.
- Developed RoomsView component for admin chat room management, including create, edit, and delete functionalities.
2025-08-18 07:44:56 +02:00

154 lines
5.0 KiB
JavaScript

import { v4 as uuidv4 } from 'uuid';
import amqp from 'amqplib/callback_api.js';
const RABBITMQ_URL = 'amqp://localhost';
const QUEUE = 'oneToOne_messages';
class ChatService {
constructor() {
this.messages = [];
this.searchQueue = [];
this.users = [];
this.randomChats = [];
this.oneToOneChats = [];
amqp.connect(RABBITMQ_URL, (err, connection) => {
if (err) throw err;
connection.createChannel((err, channel) => {
if (err) throw err;
this.channel = channel;
channel.assertQueue(QUEUE, { durable: false });
});
});
}
getMessages(toId, fromId) {
const userChats = this.randomChats.filter(chat => chat.includes(toId) && chat.includes(fromId));
if (userChats.length === 0) {
fromId = '';
}
const userMessages = this.messages.filter(message => message.to === toId && ["system", fromId].includes(message.from));
this.messages = this.messages.filter(message => message.to === toId && ["system", fromId].includes(message.from));
return userMessages;
}
async addMessage(from, to, text) {
const userChats = this.randomChats.filter(chat => chat.includes(from) && chat.includes(to));
if (userChats.length === 0) {
return;
}
this.messages.push({ from: from, to: to, text: text });
return { text: text };
}
findMatch(genders, age, id) {
const currentUsersChat = this.randomChats.filter(chat => chat.includes(id));
if (currentUsersChat.length > 0) {
return this.findUser(currentUsersChat[0][0] === id ? currentUsersChat[0][1] : currentUsersChat[0][0]);
}
let filteredSearchQueue = this.users.filter(user =>
this.searchQueue.some(sq => sq.id === user.id) && user.id !== id
&& this.randomChats.filter(chat => chat.includes(user.id)).length === 0
).sort(() => Math.random() - 0.5);
for (let i = 0; i < filteredSearchQueue.length; i++) {
const user = filteredSearchQueue[i];
const ageMatch = user.age >= age.min && user.age <= age.max;
const genderMatch = genders.includes(user.gender);
if (ageMatch && genderMatch) {
for (let j = this.searchQueue.length - 1; j >= 0; j--) {
if ([id, user.id].includes(this.searchQueue[j].id)) {
this.searchQueue.splice(j, 1);
}
}
this.randomChats.push([user.id, id]);
return user;
}
}
if (!this.searchQueue.find(user => user.id === id)) {
this.searchQueue.push({ id, genders, age });
}
return null;
}
findUser(id) {
return this.users.find(user => user.id === id);
}
async registerUser(gender, age) {
const id = uuidv4();
this.users.push({ gender, age, id });
return id;
}
async removeUser(id) {
this.searchQueue = this.searchQueue.filter(user => user.id !== id);
this.users = this.users.filter(user => user.id !== id);
this.randomChats = this.randomChats.filter(pair => pair[0] === id || pair[1] === id);
this.messages = this.messages.filter(message => message.from === id || message.to === id);
}
async endChat(userId) {
this.randomChats = this.randomChats.filter(chat => !chat.includes(userId));
this.messages.push({ to: userId, from: 'system', activity: 'otheruserleft' });
}
async initOneToOne(user1HashId, user2HashId) {
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
if (!chat) {
this.oneToOneChats.push({ user1Id: user1HashId, user2Id: user2HashId, history: [] });
}
}
async sendOneToOneMessage(user1HashId, user2HashId, message) {
const messageBundle = {
timestamp: Date.now(),
sender: user1HashId,
recipient: user2HashId,
message: message,
};
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
if (chat) {
chat.history.push(messageBundle);
} else {
this.oneToOneChats.push({
user1Id: user1HashId,
user2Id: user2HashId,
history: [messageBundle],
});
}
if (this.channel) {
this.channel.sendToQueue(QUEUE, Buffer.from(JSON.stringify(messageBundle)));
}
}
async getOneToOneMessageHistory(user1HashId, user2HashId) {
const chat = this.searchOneToOneChat(user1HashId, user2HashId);
return chat ? chat.history : [];
}
searchOneToOneChat(user1HashId, user2HashId) {
return this.oneToOneChats.find(chat =>
(chat.user1Id === user1HashId && chat.user2Id === user2HashId) ||
(chat.user1Id === user2HashId && chat.user2Id === user1HashId)
);
}
async getRoomList() {
// Nur öffentliche Räume, keine sensiblen Felder
const { default: Room } = await import('../models/chat/room.js');
const { default: RoomType } = await import('../models/chat/room_type.js');
return Room.findAll({
attributes: [
'id', 'title', 'roomTypeId', 'isPublic', 'genderRestrictionId',
'minAge', 'maxAge', 'friendsOfOwnerOnly', 'requiredUserRightId'
],
where: { isPublic: true },
include: [
{ model: RoomType, as: 'roomType' }
]
});
}
}
export default new ChatService();