forked from snxraven/LinkUp-P2P-Chat
handling user icons via HyperDrive
This commit is contained in:
parent
1c6cc9a82e
commit
db88b09ba5
20
app.js
20
app.js
@ -166,16 +166,23 @@ function setupEventListeners() {
|
||||
setupTalkButton();
|
||||
}
|
||||
}
|
||||
|
||||
function handleIncomingMessage(messageObj) {
|
||||
console.log('Received message:', messageObj); // Debugging log
|
||||
|
||||
if (messageObj.type === 'icon') {
|
||||
const username = messageObj.username;
|
||||
if (messageObj.avatar) {
|
||||
const avatarBuffer = b4a.from(messageObj.avatar, 'base64');
|
||||
drive.put(`/icons/${username}.png`, avatarBuffer);
|
||||
updateIcon(username, avatarBuffer);
|
||||
try {
|
||||
const avatarBuffer = b4a.from(messageObj.avatar, 'base64');
|
||||
drive.put(`/icons/${username}.png`, avatarBuffer).then(() => {
|
||||
console.log(`Icon stored for user: ${username}`); // Debugging log
|
||||
updateIcon(username, avatarBuffer);
|
||||
}).catch(error => {
|
||||
console.error(`Failed to store icon for user ${username}:`, error);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error processing avatar data:', error);
|
||||
}
|
||||
} else {
|
||||
console.error('Received icon message with missing avatar data:', messageObj);
|
||||
}
|
||||
@ -185,6 +192,8 @@ function handleIncomingMessage(messageObj) {
|
||||
drive.put(`/files/${messageObj.fileName}`, fileBuffer).then(() => {
|
||||
const fileUrl = `http://localhost:${servePort}/files/${messageObj.fileName}`;
|
||||
addFileMessage(messageObj.name, messageObj.fileName, updatePortInUrl(fileUrl), messageObj.fileType, updatePortInUrl(messageObj.avatar), messageObj.topic);
|
||||
}).catch(error => {
|
||||
console.error(`Failed to store file ${messageObj.fileName}:`, error);
|
||||
});
|
||||
} else {
|
||||
console.error('Received file message with missing file data or fileName:', messageObj);
|
||||
@ -197,12 +206,13 @@ function handleIncomingMessage(messageObj) {
|
||||
drive.put(filePath, audioBuffer).then(() => {
|
||||
const audioUrl = `http://localhost:${servePort}${filePath}`;
|
||||
addAudioMessage(messageObj.name, audioUrl, messageObj.avatar, messageObj.topic);
|
||||
}).catch(error => {
|
||||
console.error(`Failed to store audio message:`, error);
|
||||
});
|
||||
} else {
|
||||
console.error('Received unknown message type:', messageObj);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleConnection(connection, info) {
|
||||
console.log('New connection', info);
|
||||
|
||||
|
BIN
chatBot/assets/icon.png
Normal file
BIN
chatBot/assets/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
@ -52,7 +52,10 @@ loadCommands().then(commands => {
|
||||
|
||||
// If the command exists, execute its handler
|
||||
if (commandHandler && typeof commandHandler.handler === 'function') {
|
||||
console.log(`Executing command: ${command} with arguments: ${args}`);
|
||||
commandHandler.handler(bot, args, message);
|
||||
} else {
|
||||
console.warn(`Command not found: ${command}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -64,7 +67,9 @@ loadCommands().then(commands => {
|
||||
|
||||
bot.joinChatRoom(process.env.LINKUP_ROOM_ID);
|
||||
|
||||
bot.fetchAvatar(`https://avatar.iran.liara.run/username?username=${bot.botName}&background=f4d9b2&color=FF9800&size=40`); // Debugging avatar
|
||||
const iconPath = path.join(new URL('./assets/icon.png', import.meta.url).pathname);
|
||||
bot.fetchAvatar(iconPath); // Fetch the avatar from local file
|
||||
|
||||
}).catch(error => {
|
||||
console.error('Error loading commands:', error);
|
||||
});
|
@ -6,16 +6,29 @@ 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.botAvatar = "";
|
||||
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', () => {
|
||||
@ -25,35 +38,65 @@ class Client extends EventEmitter {
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('SIGTERM signal received. Shutting down HyperSwarm...');
|
||||
await this.destroy()
|
||||
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()
|
||||
await this.destroy();
|
||||
console.log('HyperSwarm was shut down. Exiting the process with exit code 0.');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
async fetchAvatar(url) {
|
||||
this.botAvatar = url;
|
||||
const web = await fetch(url);
|
||||
const img = await web.body.getReader().read();
|
||||
this.sendMessage(IconMessage.new(this, img.value));
|
||||
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', 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;
|
||||
const peerName = messageObj.userName; // Changed from name to userName
|
||||
const peerAvatar = messageObj.avatar;
|
||||
const timestamp = messageObj.timestamp;
|
||||
|
||||
@ -73,7 +116,7 @@ class Client extends EventEmitter {
|
||||
|
||||
peer.on('error', e => {
|
||||
this.emit('onError', e);
|
||||
console.error(`Connection error: ${e}`)
|
||||
console.error(`Connection error: ${e}`);
|
||||
});
|
||||
});
|
||||
|
||||
@ -97,17 +140,33 @@ class Client extends EventEmitter {
|
||||
}
|
||||
|
||||
sendTextMessage(message) {
|
||||
console.log(`Preparing to send text message: ${message}`);
|
||||
this.sendMessage(TextMessage.new(this, message));
|
||||
}
|
||||
|
||||
sendMessage(message) {
|
||||
if(!(message instanceof Message)) return console.log(`message does not extend Message class (TextMessage, FileMessage, AudioMessage).`, message);
|
||||
if (!(message instanceof Message)) {
|
||||
console.error(`message does not extend Message class (TextMessage, FileMessage, AudioMessage).`, message);
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log('Bot name:', this.botName);
|
||||
console.log("Sending message:", message);
|
||||
const data = message.toJsonString();
|
||||
const peers = [...this.swarm.connections];
|
||||
for (const peer of peers) peer.write(data);
|
||||
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() {
|
||||
|
@ -2,8 +2,8 @@ import Message from "./Message.js";
|
||||
import b4a from "b4a";
|
||||
|
||||
class IconMessage extends Message {
|
||||
constructor(peerName, peerAvatar, topic, timestamp) {
|
||||
super("icon", peerName, peerAvatar, topic, timestamp);
|
||||
constructor(peerName, peerAvatar, timestamp) {
|
||||
super("icon", peerName, peerAvatar, null, timestamp);
|
||||
}
|
||||
|
||||
toJsonString() {
|
||||
|
@ -10,7 +10,7 @@ class Message {
|
||||
toJson() {
|
||||
return {
|
||||
type: this.type,
|
||||
name: this.peerName,
|
||||
username: this.peerName,
|
||||
avatar: this.peerAvatar,
|
||||
topic: this.topic,
|
||||
timestamp: this.timestamp
|
||||
|
@ -1,21 +1,21 @@
|
||||
import Message from "./Message.js";
|
||||
|
||||
class TextMessage extends Message {
|
||||
constructor(peerName, peerAvatar, topic, timestamp, message) {
|
||||
super("message", peerName, peerAvatar, topic, timestamp);
|
||||
this.message = 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,
|
||||
});
|
||||
}
|
||||
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);
|
||||
}
|
||||
static new(bot, message) {
|
||||
return new TextMessage(bot.botName, bot.botAvatar, bot.currentTopic, Date.now(), message);
|
||||
}
|
||||
}
|
||||
|
||||
export default TextMessage;
|
||||
|
Loading…
Reference in New Issue
Block a user