diff --git a/chatBot/includes/Client.js b/chatBot/includes/Client.js deleted file mode 100644 index 6a48679..0000000 --- a/chatBot/includes/Client.js +++ /dev/null @@ -1,211 +0,0 @@ -import path from 'path'; -import Hyperswarm from 'hyperswarm'; -import EventEmitter from 'node:events'; -import b4a from "b4a"; -import TextMessage from "./message/TextMessage.js"; -import FileMessage from "./message/FileMessage.js"; -import AudioMessage from "./message/AudioMessage.js"; -import Message from "./message/Message.js"; -import IconMessage from "./message/IconMessage.js"; -import Corestore from 'corestore'; -import Hyperdrive from 'hyperdrive'; -import fs from 'fs'; -import ServeDrive from 'serve-drive'; - -class Client extends EventEmitter { - constructor(botName) { - super(); - if (!botName) return console.error("Bot Name is not defined!"); - this.botName = botName; - this.swarm = new Hyperswarm(); - this.joinedRooms = new Set(); // Track the rooms the bot has joined - this.currentTopic = null; // Track the current topic - - // Initialize Corestore and Hyperdrive - this.storagePath = './storage/'; - this.store = new Corestore(this.storagePath); - this.drive = new Hyperdrive(this.store); - - // Initialize ServeDrive - this.servePort = null; - this.initializeServeDrive(); - - this.setupSwarm(); - - process.on('exit', () => { - console.log('EXIT signal received. Shutting down HyperSwarm...'); - this.destroy(); - }); - - process.on('SIGTERM', async () => { - console.log('SIGTERM signal received. Shutting down HyperSwarm...'); - await this.destroy(); - console.log('HyperSwarm was shut down. Exiting the process with exit code 0.'); - process.exit(0); - }); - - process.on('SIGINT', async () => { - console.log('SIGINT signal received. Shutting down HyperSwarm...'); - await this.destroy(); - console.log('HyperSwarm was shut down. Exiting the process with exit code 0.'); - process.exit(0); - }); - } - - async initializeServeDrive() { - try { - this.servePort = this.getRandomPort(); - const serve = new ServeDrive({ - port: this.servePort, - get: ({ key, filename, version }) => this.drive - }); - await serve.ready(); - console.log('ServeDrive listening on port:', this.servePort); - } catch (error) { - console.error('Error initializing ServeDrive:', error); - } - } - - getRandomPort() { - return Math.floor(Math.random() * (65535 - 49152 + 1)) + 49152; - } - - async fetchAvatar(filePath) { - try { - await this.drive.ready(); - const iconBuffer = fs.readFileSync(filePath); - await this.drive.put(`/icons/${this.botName}.png`, iconBuffer); - this.botAvatar = `http://localhost:${this.servePort}/icons/${this.botName}.png`; - - // Cache the icon message - this.iconMessage = IconMessage.new(this, iconBuffer); - } catch (error) { - console.error('Error fetching avatar:', error); - } - } - - setupSwarm() { - this.swarm.on('connection', (peer) => { - // Send the cached icon message to the new peer - if (this.iconMessage) { - peer.write(this.iconMessage.toJsonString()); - } - - peer.on('data', async message => { - const messageObj = JSON.parse(message.toString()); - if (this.joinedRooms.has(messageObj.topic)) { // Process message only if it is from a joined room - this.currentTopic = messageObj.topic; // Set the current topic from the incoming message - - const msgType = messageObj.type; - const peerName = messageObj.name; // Changed from name to userName - const peerAvatar = messageObj.avatar; - const timestamp = messageObj.timestamp; - - if (msgType === "message") - this.emit('onMessage', peer, new TextMessage(peerName, peerAvatar, this.currentTopic, timestamp, messageObj.message)); - - if (msgType === "file") { - const fileBuffer = await this.drive.get(`/files/${messageObj.fileName}`); - this.emit('onFile', peer, new FileMessage(peerName, peerAvatar, this.currentTopic, timestamp, messageObj.fileName, `http://localhost:${this.servePort}/files/${messageObj.fileName}`, messageObj.fileType, messageObj.fileData)); - } - - if (msgType === "icon") - this.emit('onIcon', peer, new IconMessage(peerName, peerAvatar, timestamp)); - - if (msgType === "audio") { - const audioBuffer = await this.drive.get(`/audio/${messageObj.audioName}`); - this.emit('onAudio', peer, new AudioMessage(peerName, peerAvatar, this.currentTopic, timestamp, `http://localhost:${this.servePort}/audio/${messageObj.audioName}`, messageObj.audioType, messageObj.audioData)); - } - } - }); - - peer.on('error', e => { - this.emit('onError', e); - console.error(`Connection error: ${e}`); - }); - }); - - this.swarm.on('update', () => { - console.log(`Connections count: ${this.swarm.connections.size} / Peers count: ${this.swarm.peers.size}`); - }); - } - - joinChatRoom(chatRoomID) { - if (!chatRoomID || typeof chatRoomID !== 'string') { - return console.error("Invalid chat room ID!"); - } - - this.joinedRooms.add(chatRoomID); // Add the room to the list of joined rooms - this.currentTopic = chatRoomID; // Store the current topic - this.discovery = this.swarm.join(Buffer.from(chatRoomID, 'hex'), { client: true, server: true }); - this.discovery.flushed().then(() => { - console.log(`Bot ${this.botName} joined the chat room.`); - this.emit('onBotJoinRoom'); - }); - } - - sendTextMessage(message) { - console.log(`Preparing to send text message: ${message}`); - this.sendMessage(TextMessage.new(this, message)); - } - - async sendFileMessage(filePath, fileType) { - try { - await this.drive.ready(); - const fileBuffer = fs.readFileSync(filePath); - const fileName = path.basename(filePath); - await this.drive.put(`/files/${fileName}`, fileBuffer); - const fileUrl = `http://localhost:${this.servePort}/files/${fileName}`; - const fileMessage = FileMessage.new(this, fileName, fileUrl, fileType, fileBuffer); // Pass fileBuffer to the new method - this.sendMessage(fileMessage); - } catch (error) { - console.error('Error sending file message:', error); - } - } - - async sendAudioMessage(filePath, audioType) { - try { - await this.drive.ready(); - const audioBuffer = fs.readFileSync(filePath); - const audioName = path.basename(filePath); - await this.drive.put(`/audio/${audioName}`, audioBuffer); - const audioUrl = `http://localhost:${this.servePort}/audio/${audioName}`; - const audioMessage = AudioMessage.new(this, audioUrl, audioType, audioBuffer); // Pass audioBuffer to the new method - this.sendMessage(audioMessage); - } catch (error) { - console.error('Error sending audio message:', error); - } - } - - sendMessage(message) { - if (!(message instanceof Message)) { - console.error(`message does not extend Message class (TextMessage, FileMessage, AudioMessage).`, message); - return; - } - - console.log("Sending message:", message); - const data = message.toJsonString(); - const peers = [...this.swarm.connections]; - if (peers.length === 0) { - console.warn("No active peer connections found."); - return; - } - - console.log(`Sending message to ${peers.length} peers.`); - for (const peer of peers) { - try { - peer.write(data); - console.log(`Message sent to peer: ${peer.remoteAddress}`); - } catch (error) { - console.error(`Failed to send message to peer: ${peer.remoteAddress}`, error); - } - } - } - - async destroy() { - await this.swarm.destroy(); - console.log(`Bot ${this.botName} disconnected.`); - } -} - -export default Client; diff --git a/chatBot/includes/message/AudioMessage.js b/chatBot/includes/message/AudioMessage.js deleted file mode 100644 index fd0dce6..0000000 --- a/chatBot/includes/message/AudioMessage.js +++ /dev/null @@ -1,27 +0,0 @@ -import Message from "./Message.js"; -import b4a from "b4a"; - -class AudioMessage extends Message { - constructor(peerName, peerAvatar, topic, timestamp, audioUrl, audioType, audioData) { - super("audio", peerName, peerAvatar, topic, timestamp); - this.audioUrl = audioUrl; - this.audioType = audioType; - this.audioData = audioData; // Add audio data property - } - - toJsonString() { - return JSON.stringify({ - ...this.toJson(), - audioUrl: this.audioUrl, - audioType: this.audioType, - audio: this.audioData // Include audio data in JSON - }); - } - - static new(bot, audioUrl, audioType, audioBuffer) { - const audioData = b4a.toString(audioBuffer, 'base64'); // Convert audio buffer to base64 - return new AudioMessage(bot.botName, bot.botAvatar, bot.currentTopic, Date.now(), audioUrl, audioType, audioData); - } -} - -export default AudioMessage; diff --git a/chatBot/includes/message/FileMessage.js b/chatBot/includes/message/FileMessage.js deleted file mode 100644 index a9be736..0000000 --- a/chatBot/includes/message/FileMessage.js +++ /dev/null @@ -1,29 +0,0 @@ -import Message from "./Message.js"; -import b4a from "b4a"; - -class FileMessage extends Message { - constructor(peerName, peerAvatar, topic, timestamp, fileName, fileUrl, fileType, fileData) { - super("file", peerName, peerAvatar, topic, timestamp); - this.fileName = fileName; - this.fileUrl = fileUrl; - this.fileType = fileType; - this.fileData = fileData; // Add file data property - } - - toJsonString() { - return JSON.stringify({ - ...this.toJson(), - fileName: this.fileName, - fileUrl: this.fileUrl, - fileType: this.fileType, - file: this.fileData // Include file data in JSON - }); - } - - static new(bot, fileName, fileUrl, fileType, fileBuffer) { - const fileData = b4a.toString(fileBuffer, 'base64'); // Convert file buffer to base64 - return new FileMessage(bot.botName, bot.botAvatar, bot.currentTopic, Date.now(), fileName, fileUrl, fileType, fileData); - } -} - -export default FileMessage; diff --git a/chatBot/includes/message/IconMessage.js b/chatBot/includes/message/IconMessage.js deleted file mode 100644 index f3e9bd5..0000000 --- a/chatBot/includes/message/IconMessage.js +++ /dev/null @@ -1,20 +0,0 @@ -import Message from "./Message.js"; -import b4a from "b4a"; - -class IconMessage extends Message { - constructor(peerName, peerAvatar, timestamp) { - super("icon", peerName, peerAvatar, null, timestamp); - } - - toJsonString() { - return JSON.stringify({ - ...this.toJson() - }); - } - - static new(bot, avatarBuffer) { - return new IconMessage(bot.botName, b4a.toString(avatarBuffer, 'base64'), Date.now()); - } -} - -export default IconMessage; diff --git a/chatBot/includes/message/Message.js b/chatBot/includes/message/Message.js deleted file mode 100644 index fbb2fff..0000000 --- a/chatBot/includes/message/Message.js +++ /dev/null @@ -1,21 +0,0 @@ -class Message { - constructor(messageType, peerName, peerAvatar, topic, timestamp) { - this.type = messageType; - this.peerName = peerName; - this.peerAvatar = peerAvatar; - this.topic = topic; - this.timestamp = timestamp; - } - - toJson() { - return { - type: this.type, - name: this.peerName, - avatar: this.peerAvatar, - topic: this.topic, - timestamp: this.timestamp - }; - } -} - -export default Message; diff --git a/chatBot/includes/message/TextMessage.js b/chatBot/includes/message/TextMessage.js deleted file mode 100644 index f4a68c0..0000000 --- a/chatBot/includes/message/TextMessage.js +++ /dev/null @@ -1,21 +0,0 @@ -import Message from "./Message.js"; - -class TextMessage extends Message { - constructor(peerName, peerAvatar, topic, timestamp, message) { - super("message", peerName, peerAvatar, topic, timestamp); - this.message = message; - } - - toJsonString() { - return JSON.stringify({ - ...this.toJson(), - message: this.message, - }); - } - - static new(bot, message) { - return new TextMessage(bot.botName, bot.botAvatar, bot.currentTopic, Date.now(), message); - } -} - -export default TextMessage;