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();