Skip to content

Commit

Permalink
save data to file
Browse files Browse the repository at this point in the history
Signed-off-by: Hoang Pham <hoangmaths96@gmail.com>
  • Loading branch information
hweihwang committed May 30, 2024
1 parent 4f3f454 commit 9f5a9fb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 29 deletions.
3 changes: 3 additions & 0 deletions src/collaboration/Portal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class Portal {

this.socket.on('joined-data', (data) => {
const remoteElements = JSON.parse(new TextDecoder().decode(data))

console.log(`JOINED DATA ${new TextDecoder().decode(data)}`)

const reconciledElements = this.collab._reconcileElements(remoteElements)
this.collab.handleRemoteSceneUpdate(reconciledElements)

Expand Down
119 changes: 90 additions & 29 deletions websocket_server/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import express from 'express';
import http from 'http';
import {Server as SocketIO} from 'socket.io';
import fetch from 'node-fetch';
import express from 'express'
import http from 'http'
import { Server as SocketIO } from 'socket.io'
import fetch from 'node-fetch'

const app = express();

Expand All @@ -26,43 +26,76 @@ try {
}, allowEIO3: true,
});

io.on('connection', (socket) => {
console.log('connection established!');
io.to(`${socket.id}`).emit('init-room');
io.on('connection', async (socket) => {
let roomDataStore = {};

socket.on('join-room', async (roomID) => {
console.log(`${socket.id} has joined ${roomID}`);
await socket.join(roomID);
const getRoomDataFromFile = async (roomID) => {
const response = await fetch(`http://nextcloud.local/index.php/apps/whiteboard/${roomID}`, {
headers: {
'Authorization': 'Basic ' + Buffer.from('admin:admin').toString('base64')
}
});

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
const roomData = data.data;

return JSON.stringify(roomData.elements);
};

const convertStringToArrayBuffer = (string) => {
return new TextEncoder().encode(string).buffer;
};

const convertArrayBufferToString = (arrayBuffer) => {
return new TextDecoder().decode(arrayBuffer);
};

const saveRoomDataToFile = async (roomID, data) => {
console.log(`Saving room data to file: ${roomID}`);

const body = JSON.stringify({ data: { elements: data }});

try {
const response = await fetch(`http://nextcloud.local/index.php/apps/whiteboard/${roomID}`, {
await fetch(`http://nextcloud.local/index.php/apps/whiteboard/${roomID}`, {
method: 'PUT',
headers: {
'Authorization': 'Basic ' + Buffer.from('admin:admin').toString('base64')
}
'Authorization': 'Basic ' + Buffer.from('admin:admin').toString('base64'),
'Content-Type': 'application/json'
},
body: body,
});
} catch (error) {
console.error(error);
}
};

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

const data = await response.json();
const roomData = data.data;
const saveAllRoomsData = async () => {
for (const roomID in roomDataStore) {
const roomData = roomDataStore[roomID];
await saveRoomDataToFile(roomID, roomData);
}
};

// Convert the room data to a JSON string
const jsonString = JSON.stringify(roomData.elements);
// const interval = setInterval(saveAllRoomsData, 10000);

// Use the TextEncoder API to convert the JSON string to a Uint8Array
const uint8Array = new TextEncoder().encode(jsonString);
io.to(`${socket.id}`).emit('init-room');

// Get the ArrayBuffer from the Uint8Array
const arrayBuffer = uint8Array.buffer;
socket.on('join-room', async (roomID) => {
console.log(`${socket.id} has joined ${roomID}`);
await socket.join(roomID);

socket.emit('joined-data', arrayBuffer, []);
} catch (error) {
console.error(`Failed to fetch data for room ${roomID}`, error);
if (!roomDataStore[roomID]) {
roomDataStore[roomID] = await getRoomDataFromFile(roomID);
}

socket.emit('joined-data', convertStringToArrayBuffer(roomDataStore[roomID]), []);

const sockets = await io.in(roomID).fetchSockets();

if (sockets.length <= 1) {
io.to(`${socket.id}`).emit('first-in-room');
} else {
Expand All @@ -74,11 +107,27 @@ try {
});

socket.on('server-broadcast', (roomID, encryptedData, iv) => {
console.log(`Broadcasting to room ${roomID}`);

socket.broadcast.to(roomID).emit('client-broadcast', encryptedData, iv);

const decryptedData = JSON.parse(convertArrayBufferToString(encryptedData));

setTimeout(() => {
roomDataStore[roomID] = decryptedData.payload.elements;
});
});

socket.on('server-volatile-broadcast', (roomID, encryptedData, iv) => {
console.log(`Volatile broadcasting to room ${roomID}`);

socket.volatile.broadcast.to(roomID).emit('client-broadcast', encryptedData, iv);

const decryptedData = JSON.parse(convertArrayBufferToString(encryptedData));

setTimeout(() => {
roomDataStore[roomID] = decryptedData.payload.elements;
});
});

socket.on('user-follow', async (payload) => {
Expand Down Expand Up @@ -111,7 +160,16 @@ try {

socket.on('disconnecting', async () => {
console.log(`${socket.id} has disconnected`);

for (const roomID of Array.from(socket.rooms)) {
if (roomID === socket.id) continue;

console.log(`${socket.id} has left ${roomID}`);

if (roomDataStore[roomID]) {
await saveRoomDataToFile(roomID, roomDataStore[roomID]);
}

const otherClients = (await io.in(roomID).fetchSockets()).filter((_socket) => _socket.id !== socket.id);

const isFollowRoom = roomID.startsWith('follow@');
Expand All @@ -127,9 +185,12 @@ try {
}
});

socket.on('disconnect', () => {
socket.on('disconnect', async () => {
socket.removeAllListeners();
socket.disconnect();
// clearInterval(interval);
// await saveAllRoomsData();
roomDataStore = {};
});
});
} catch (error) {
Expand Down

0 comments on commit 9f5a9fb

Please sign in to comment.