Compare commits

..

2 Commits

Author SHA1 Message Date
Raven Scott
cd5edfc9aa current 2024-06-03 20:04:32 -04:00
Raven Scott
2d199493ac current 2024-06-03 20:04:15 -04:00
4 changed files with 41 additions and 71 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules node_modules
package-lock.json package-lock.json
shared-storage shared-storage
storage

111
app.js
View File

@ -3,20 +3,21 @@ import crypto from 'hypercore-crypto';
import b4a from 'b4a'; import b4a from 'b4a';
import ServeDrive from 'serve-drive'; import ServeDrive from 'serve-drive';
import Localdrive from 'localdrive'; import Localdrive from 'localdrive';
import fs from 'fs';
const sharedDrive = new Localdrive('./shared-storage'); const drive = new Localdrive('./storage');
let swarm; let swarm;
let userName = 'Anonymous'; let userName = 'Anonymous';
let userAvatar = ''; let userAvatar = '';
let registeredUsers = JSON.parse(localStorage.getItem('registeredUsers')) || {};
let peerCount = 0; let peerCount = 0;
async function initialize() { async function initialize() {
swarm = new Hyperswarm(); swarm = new Hyperswarm();
await sharedDrive.ready(); await drive.ready();
const servePort = 1337; const servePort = 1337;
const serve = new ServeDrive({ port: servePort, get: ({ key, filename, version }) => sharedDrive }); const serve = new ServeDrive({ port: servePort, get: ({ key, filename, version }) => drive });
await serve.ready(); await serve.ready();
console.log('Listening on http://localhost:' + serve.address().port); console.log('Listening on http://localhost:' + serve.address().port);
@ -44,38 +45,6 @@ async function initialize() {
messageForm.addEventListener('submit', sendMessage); messageForm.addEventListener('submit', sendMessage);
} }
swarm.on('connection', (connection, info) => {
peerCount++;
updatePeerCount();
connection.on('data', async (data) => {
const messageObj = JSON.parse(data.toString());
if (messageObj.type === 'avatarRequest') {
const avatarBuffer = await getAvatar(messageObj.username);
if (avatarBuffer) {
connection.write(avatarBuffer);
}
} else if (messageObj.type === 'fileUpdate') {
await processFileUpdate(messageObj);
} else {
onMessageAdded(messageObj.name, messageObj.message, messageObj.avatar);
}
});
connection.on('close', () => {
peerCount--;
updatePeerCount();
});
});
swarm.on('error', (err) => {
console.error('Swarm error:', err);
});
swarm.on('close', () => {
console.log('Swarm closed.');
});
const savedUser = localStorage.getItem('currentUser'); const savedUser = localStorage.getItem('currentUser');
if (savedUser) { if (savedUser) {
const user = JSON.parse(savedUser); const user = JSON.parse(savedUser);
@ -92,8 +61,33 @@ async function initialize() {
} }
} }
const randomTopic = crypto.randomBytes(32); swarm.on('connection', (connection, info) => {
document.querySelector('#chat-room-topic').innerText = b4a.toString(randomTopic, 'hex'); peerCount++;
updatePeerCount();
connection.on('data', async (data) => {
const messageObj = JSON.parse(data.toString());
if (messageObj.type === 'icon') {
// Save icon to local directory
const username = messageObj.username;
const avatarBuffer = Buffer.from(messageObj.avatar, 'base64');
await drive.put(`/icons/${username}.png`, avatarBuffer);
} else {
onMessageAdded(messageObj.name, messageObj.message, messageObj.avatar);
}
});
connection.on('close', () => {
peerCount--;
updatePeerCount();
});
});
swarm.on('error', (err) => {
console.error('Swarm error:', err);
});
swarm.on('close', () => {
console.log('Swarm closed.');
});
} }
function updatePeerCount() { function updatePeerCount() {
@ -103,17 +97,6 @@ function updatePeerCount() {
} }
} }
async function getAvatar(username) {
try {
const avatarPath = `./shared-storage/icons/${username}.png`;
const avatarBuffer = await sharedDrive.get(avatarPath);
return avatarBuffer;
} catch (error) {
console.error('Error getting avatar:', error);
return null;
}
}
async function registerUser(e) { async function registerUser(e) {
e.preventDefault(); e.preventDefault();
@ -142,8 +125,9 @@ async function registerUser(e) {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = async () => { reader.onload = async () => {
const fileBuffer = Buffer.from(reader.result); const fileBuffer = Buffer.from(reader.result);
await sharedDrive.put(`/icons/${regUsername}-${file.name}`, fileBuffer); await drive.put(`/icons/${regUsername}.png`, fileBuffer);
userAvatar = `http://localhost:1337/icons/${regUsername}-${file.name}`; userAvatar = `http://localhost:1337/icons/${regUsername}.png`;
// Save avatar URL to localStorage
localStorage.setItem('avatarURL', userAvatar); localStorage.setItem('avatarURL', userAvatar);
}; };
reader.readAsArrayBuffer(file); reader.readAsArrayBuffer(file);
@ -173,6 +157,7 @@ async function continueRegistration(regUsername) {
} }
async function createChatRoom() { async function createChatRoom() {
// Generate a new random topic (32 byte string)
const topicBuffer = crypto.randomBytes(32); const topicBuffer = crypto.randomBytes(32);
joinSwarm(topicBuffer); joinSwarm(topicBuffer);
} }
@ -188,6 +173,7 @@ async function joinSwarm(topicBuffer) {
document.querySelector('#setup').classList.add('hidden'); document.querySelector('#setup').classList.add('hidden');
document.querySelector('#loading').classList.remove('hidden'); document.querySelector('#loading').classList.remove('hidden');
// Join the swarm with the topic. Setting both client/server to true means that this app can act as both.
const discovery = swarm.join(topicBuffer, { client: true, server: true }); const discovery = swarm.join(topicBuffer, { client: true, server: true });
await discovery.flushed(); await discovery.flushed();
@ -204,8 +190,7 @@ function sendMessage(e) {
onMessageAdded(userName, message, userAvatar); onMessageAdded(userName, message, userAvatar);
onMessageAdded(userName, message, userAvatar); // Send the message to all peers (that you are connected to)
const messageObj = JSON.stringify({ const messageObj = JSON.stringify({
type: 'message', type: 'message',
name: userName, name: userName,
@ -220,23 +205,7 @@ function sendMessage(e) {
} }
} }
async function processFileUpdate(messageObj) { // appends element to #messages element with content set to sender and message
try {
const filePath = messageObj.filePath;
const fileBuffer = await downloadFileFromPeer(messageObj.peerId, filePath);
await sharedDrive.put(filePath, fileBuffer);
console.log(`File ${filePath} updated successfully.`);
} catch (error) {
console.error('Error processing file update:', error);
}
}
async function downloadFileFromPeer(peerId, filePath) {
// Implement logic to download file from peer using Hyperswarm or other P2P mechanisms
}
function onMessageAdded(from, message, avatar) { function onMessageAdded(from, message, avatar) {
const $div = document.createElement('div'); const $div = document.createElement('div');
$div.classList.add('message'); $div.classList.add('message');
@ -262,4 +231,4 @@ function onMessageAdded(from, message, avatar) {
document.querySelector('#messages').appendChild($div); document.querySelector('#messages').appendChild($div);
} }
initialize(); initialize();

BIN
storage/icons/Raven.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
storage/icons/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB