-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
Start a New Chat
+
+
+
+
+
+
-
-
status
+
+
+
-
-
\ No newline at end of file
diff --git a/web/chat-server.js b/web/chat-server.js
index b50c3d7..e102945 100644
--- a/web/chat-server.js
+++ b/web/chat-server.js
@@ -11,6 +11,9 @@ const axios = require('axios');
const OpenAI = require('openai');
const Groq = require('groq-sdk');
+const { PrismaClient } = require('@prisma/client');
+const prisma = new PrismaClient();
+
// Load environment variables
dotenv.config({ path: `.env${process.env.NODE_ENV === 'development' ? '.development' :'.'+ process.env.NODE_ENV }` });
console.log(`loaded env file: ${process.env.NODE_ENV}`)
@@ -37,20 +40,36 @@ let queueCounter = 0;
const sessions = new Map();
const chats = new Map(); // Store chat rooms
-// Initialize storage and load initial values
-async function initStorage() {
- await storage.init();
- language = await storage.getItem('language') || language;
- storeRecordings = await storage.getItem('storeRecordings') || storeRecordings;
- const storedChats = await storage.getItem('chats') || [];
- storedChats.forEach(chat => chats.set(chat.id, chat));
- const storedSessions = await storage.getItem('sessions') || [];
- storedSessions.forEach(session => sessions.set(session.sessionId, session));
-}
+// User registration
+app.post('/register', async (req, res) => {
+ const { username, password } = req.body;
+ try {
+ const user = await prisma.user.create({
+ data: { username, password: hashPassword(password) },
+ });
+ res.status(201).json({ message: 'User registered successfully', userId: user.id });
+ } catch (error) {
+ res.status(400).json({ error: 'Username already exists' });
+ }
+ });
+
+ // User login
+ app.post('/login', async (req, res) => {
+ const { username, password } = req.body;
+ const user = await prisma.user.findUnique({ where: { username } });
+ if (user && verifyPassword(password, user.password)) {
+ const session = await prisma.session.create({
+ data: { userId: user.id, lastLogin: new Date() },
+ });
+ res.json({ sessionId: session.id, userId: user.id });
+ } else {
+ res.status(401).json({ error: 'Invalid credentials' });
+ }
+ });
+
-initStorage();
// WebSocket Server
const wss = new WebSocket.Server({ port: PORT_WS });
@@ -105,35 +124,57 @@ async function handleSessionId(ws) {
await storage.setItem('sessions', Array.from(sessions.values()));
}
-async function handleJoin(ws, { username, language }) {
- sessions.set(ws.sessionId, { username, sessionId: ws.sessionId, language });
- ws.send(JSON.stringify({ type: 'sessionId', sessionId: ws.sessionId, language, storeRecordings }));
-
- const userChats = Array.from(chats.values()).filter(chat => chat.participants.includes(ws.sessionId));
+// Modified handleJoin function
+async function handleJoin(ws, { username, language, sessionId }) {
+ const session = await prisma.session.update({
+ where: { id: sessionId },
+ data: { language },
+ include: { user: true },
+ });
+ ws.sessionId = sessionId;
+ ws.userId = session.userId;
+ ws.send(JSON.stringify({ type: 'sessionId', sessionId, language, storeRecordings }));
+
+ const userChats = await prisma.chat.findMany({
+ where: { participants: { some: { userId: session.userId } } },
+ include: { participants: true },
+ });
ws.send(JSON.stringify({ type: 'chats', chats: userChats }));
-
+
broadcastUserList();
-}
+ }
-async function handleStartChat(ws, { users }) {
+ async function handleStartChat(ws, { users }) {
const chatId = generateChatId();
- let participants = [ws.sessionId, ...users];
+ let participants = [ws.userId, ...users];
participants = [...new Set(participants)];
-
- chats.set(chatId, { participants, messages: [] });
- await storage.setItem('chats', Array.from(chats.values()));
-
+
+ const chat = await prisma.chat.create({
+ data: {
+ id: chatId,
+ participants: {
+ connect: participants.map(userId => ({ id: userId })),
+ },
+ },
+ include: { participants: true },
+ });
+
notifyParticipants(participants);
broadcastUserList();
-}
-
+ }
+
async function handleEnterChat(ws, { chatId }) {
- const enteredChat = chats.get(chatId);
- const currentSession = sessions.get(ws.sessionId);
- currentSession.currentChat = chatId;
- if (enteredChat && enteredChat.participants.includes(ws.sessionId)) {
- ws.send(JSON.stringify({ type: 'chat', chat: enteredChat }));
- }
+ const enteredChat = await prisma.chat.findUnique({
+ where: { id: chatId },
+ include: { participants: true, messages: true },
+ });
+ if (enteredChat && enteredChat.participants.some(p => p.id === ws.userId)) {
+ await prisma.session.update({
+ where: { id: ws.sessionId },
+ data: { currentChatId: chatId },
+ });
+ ws.send(JSON.stringify({ type: 'chat', chat: enteredChat }));
+ }
}
async function handleReconnect(ws, { sessionId }) {
@@ -158,21 +199,24 @@ function generateChatId() {
return Math.random().toString(36).substring(2);
}
-function broadcastUserList() {
- const userList = Array.from(sessions.values()).map(user => ({
- username: user.username,
- sessionId: user.sessionId,
- currentChat: user.currentChat,
- language: user.language
- }));
-
- wss.clients.forEach(client => {
- if (client.readyState === WebSocket.OPEN) {
- client.send(JSON.stringify({ type: 'userList', users: userList }));
- }
+async function broadcastUserList() {
+ const users = await prisma.session.findMany({
+ include: { user: true },
});
-}
-
+ const userList = users.map(session => ({
+ username: session.user.username,
+ sessionId: session.id,
+ currentChat: session.currentChatId,
+ language: session.language,
+ }));
+
+ wss.clients.forEach(client => {
+ if (client.readyState === WebSocket.OPEN) {
+ client.send(JSON.stringify({ type: 'userList', users: userList }));
+ }
+ });
+ }
+
function notifyParticipants(participants) {
participants.forEach(sessionId => {
const participantSocket = Array.from(wss.clients).find(client => client.sessionId === sessionId);
diff --git a/web/prisma/schema.prisma b/web/prisma/schema.prisma
new file mode 100644
index 0000000..1d549b3
--- /dev/null
+++ b/web/prisma/schema.prisma
@@ -0,0 +1,40 @@
+datasource db {
+ provider = "sqlite"
+ url = "file:./dev.db"
+}
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+model User {
+ id String @id @default(uuid())
+ username String @unique
+ password String
+ sessions Session[]
+ chats Chat[]
+}
+
+model Session {
+ id String @id @default(uuid())
+ userId String
+ user User @relation(fields: [userId], references: [id])
+ language String?
+ lastLogin DateTime
+ currentChatId String?
+}
+
+model Chat {
+ id String @id
+ participants User[]
+ messages Message[]
+}
+
+model Message {
+ id String @id @default(uuid())
+ chatId String
+ chat Chat @relation(fields: [chatId], references: [id])
+ senderId String
+ content String
+ timestamp DateTime @default(now())
+}
\ No newline at end of file