@trap_stevo/filetide
Version:
Revolutionizing real-time file transfer with seamless, instant communication across any device. Deliver files instantly, regardless of platform, and experience unparalleled speed and control in managing transfers. Elevate your file-sharing capabilities wi
753 lines (744 loc) • 33.5 kB
JavaScript
var _FileTide;
function _classPrivateMethodInitSpec(e, a) { _checkPrivateRedeclaration(e, a), a.add(e); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
const {
HUDUtilityManager
} = require("@trap_stevo/legendarybuilderpronodejs-utilities");
const chalk = require("chalk");
const path = require("path");
const fs = require("fs");
const os = require("os");
const {
FileTideDebugUtilityManager,
significantMessageColors,
errorMessageColors
} = require("./HUDManagers/FileTideDebugUtilityManager.js");
const {
FileTransferTrackingManager
} = require("./HUDManagers/FileTransferTrackingManager.js");
const {
FileTransferReceiverManager
} = require("./HUDManagers/FileTransferReceiverManager.js");
const FileTransferRecoveryManager = require("./HUDManagers/FileTransferRecoveryManager.js");
const {
FileNetConfigManager
} = require("./HUDManagers/FileNetConfigManager.js");
const {
FileUtilityManager
} = require("./HUDManagers/FileUtilityManager.js");
const ConsoleProgressBarManager = require("./HUDComponents/ConsoleProgressBarManager");
const ChunkCapacitor = require("./HUDComponents/ChunkCapacitor.js");
const ConsoleTable = require("./HUDComponents/ConsoleTable.js");
const FileMessagerClient = require("./FileMessagerClient");
const FileMessager = require("./FileMessager");
var _FileTide_brand = /*#__PURE__*/new WeakSet();
class FileTide {
constructor(debugMode = true) {
/**
* Set up file transfer event listeners natively.
* Automatically checks and creates directories as needed.
*/
_classPrivateMethodInitSpec(this, _FileTide_brand);
this.progressBarManager = new ConsoleProgressBarManager([], {
completionMessageColor: chalk.blue.bold
});
this.clientShorePolicies = new Map();
this.transferBarrier = false;
this.clientDetails = new Map();
this.clients = new Map();
this.currentUserID = "";
this.runningOn = os.platform();
this.inDebugMode = debugMode;
FileTideDebugUtilityManager.setDebugMode(debugMode);
return;
}
static outputGradient(text, colors) {
FileTideDebugUtilityManager.outputGradient(text, colors);
return;
}
/**
* Initialize and start the server.
* @param {Object} serverOptions - Configuration for server (e.g., port, useCors, useHTTPS)
* @param {Function} onLaunch - Callback for when a file tide instance launches
* @param {...any} tideConfigurations - Additional configuration objects for customizing FileTide behavior
*/
launchFileTide(serverOptions = {}, onLaunch, ...tideConfigurations) {
this.fileNet = new FileMessager(serverOptions, ...tideConfigurations);
this.fileNet.start();
FileTide.outputGradient("[FileTide] ~ FileNet launched successfully!", significantMessageColors);
if (onLaunch) {
onLaunch(this.fileNet);
}
return;
}
/**
* Initialize and start a new client for each user.
* @param {Object} clientOptions - Configuration for client (e.g., serverUrl)
* @param {Object} connectionOptions - Configuration for the client connection
* @param {Object} transportOptions - Configuration for the file transporter
* @param {Object} messagerSettings - Configuration for the messager
* @param {String} roomName - The name of the room to join
* @param {String} userID - The ID of the client user
* @param {Function} onLaunch - Callback for when a file messager launches
* @param {Function} onIncomingFile - Callback for incoming files in transit
* @param {Function} onIncomingTransfer - Callback for incoming transfers
* @param {Function} onTransferBarrier - Callback for when an incoming transfer status updates
* @param {Function} onTransferProgress - Callback for when an current transfers progress
* @param {Boolean} [enableTransferBarrier=true] - Whether to enable the transfer barrier
* @param {Object} [options = {}] - Additional options
* @param {Object} [headers = {}] - Additional connection headers
* @param {Function} onConnect - Callback for when the client connects to the desired server
* @param {Function} onDisconnect - Callback for when the client disconnects from the desired server
* @param {String} authURL - The destination of the connection authentication functionality
* @param {Object} [authHeaders = {}] - Additional connection authentication headers
* @param {Boolean} [useAuthentication=true] - Whether to enable connection authentication
* @param {Boolean} [queryAuthToken=false] - Whether to enable connection authentication tokens
*/
launchMessager(clientOptions = {}, connectionOptions = {}, transportOptions = {
parallelChunks: 3,
maxRetries: 3
}, messagerSettings = {
maxReconnectionAttempts: 15,
reconnectionAttempts: 15,
maxReconnectionDelay: 10000
}, roomName, userID, onLaunch, onIncomingFile, onIncomingTransfer, onTransferBarrier, onTransferProgress, enableTransferBarrier = true, options = {}, headers = {}, onConnect = null, onDisconnect = null, authURL = "", authHeaders = {}, useAuthentication = false, queryAuthToken = false) {
if (this.clients.has(userID)) {
this.stopMessager(userID);
}
const currentClientDetails = this.clientDetails.get(userID);
if (currentClientDetails && currentClientDetails.unauthorized) {
const {
onCurrentClientUnauthorized
} = options;
FileTide.outputGradient(`[FileTide ~ FileNet] ~ Unauthorized access detected.`, errorMessageColors);
if (onCurrentClientUnauthorized) {
onCurrentClientUnauthorized({
...currentClientDetails,
userID
});
}
return;
}
const newClient = new FileMessagerClient(clientOptions, transportOptions, messagerSettings);
const enterRoom = newClient.joinRoom(userID, roomName, connectionOptions, headers, onConnect, onDisconnect, authURL, authHeaders, useAuthentication, queryAuthToken);
this.transferBarrier = enableTransferBarrier;
this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents"), FileUtilityManager.getTidePath(">Desktop"), FileUtilityManager.getTidePath(">Photos"), FileUtilityManager.getTidePath(">Videos"), FileUtilityManager.getTidePath(">Music")]);
this.clients.set(userID, newClient);
this.clientDetails.set(userID, {
unauthorized: false,
userID
});
FileTide.outputGradient(`[FileTide] ~ Messager launched successfully for client ~ ${userID}!`, significantMessageColors);
_assertClassBrand(_FileTide_brand, this, _setupFileEventListeners).call(this, userID, newClient, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options);
if (onLaunch) {
onLaunch(newClient, enterRoom);
}
return;
}
async getDirectoryData(directoryPath) {
return await FileUtilityManager.getDirectoryData(directoryPath);
}
getFileData(filePath) {
return FileUtilityManager.getFileData(filePath);
}
async getPathData(inputPath, filterContent = []) {
return await FileUtilityManager.getPathData(inputPath, filterContent);
}
getTidePath(inputPath) {
return FileUtilityManager.getTidePath(inputPath);
}
getTidingTransferStates() {
return FileTransferRecoveryManager.memoryStorage;
}
saveTransferStates() {
FileTransferRecoveryManager.flushToDisk();
}
filterFilesAndDirectories(dirPath, filterContent = [], callback) {
FileUtilityManager.filterFilesAndDirectories(dirPath, filterContent, (files, error) => {
if (callback) {
callback(files, error);
}
});
}
listFilesFromClient(recipientID, depth = 1) {
const clientID = this.currentUserID;
const clientMessager = this.clients.get(clientID);
if (!clientMessager) {
FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
return;
}
clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
clientID,
tideID: clientMessager.clientTide.sockets[clientID].tideID
});
clientMessager.listFiles(clientID, recipientID, depth);
}
async listFiles(directories, depth = 1, onDirectory) {
return await FileUtilityManager.listFiles(directories, depth, onDirectory);
}
clearShorePolicies(clientID, shores = []) {
let clientShorePolicies = this.clientShorePolicies.get(clientID);
if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, errorMessageColors);
return false;
}
const shorePolicies = Array.from(clientShorePolicies.values());
const currentShores = new Set(clientShorePolicies);
this.clientShorePolicies.set(clientID, shorePolicies.filter(shorePolicy => !currentShores.has(shorePolicy)));
return true;
}
addShorePolicies(clientID, shores = []) {
const clientShorePolicies = this.clientShorePolicies.get(clientID);
if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, errorMessageColors);
return false;
}
this.clientShorePolicies.set(clientID, [...new Set([...clientShorePolicies, ...shores])]);
return true;
}
getShorePolicies(clientID) {
return this.clientShorePolicies.get(clientID);
}
/**
* Send files / directories directly to a device.
* @param {String} recipientID - The ID of the client device to send the data to.
* @param {Buffer} fileData - The path of the data to send.
* @param {String} destinationPath - The destination path on the device.
* @param {Array} filterDirectoryContent - List of paths to filter.
* @param {Number} tideSize - The tide size in sending smaller to medium files (200).
* @param {Number} tidalSize - The tide size in sending large files (500).
* @param {Number} minTideSize - The minimum tide size in sending files (10).
* @param {Number} maxTideSize - The maximum tide size in sending files (2000).
* @param {Number} transferRequestExpirationTime - The maximum time until the transfer barrier times out the transfer request.
*/
async sendToDevice(recipientID, filePath, destinationPath, filterDirectoryContent = [], tideSize = 200, tidalSize = 500, minTideSize = 10, maxTideSize = 2000, transferRequestExpirationTime = 30000) {
const clientID = this.currentUserID;
const clientMessager = this.clients.get(clientID);
if (!clientMessager) {
FileTide.outputGradient(`[FileTide] Client ~ ${clientID} not found.`, errorMessageColors);
return false;
}
clientMessager.clientTide.emitEvent(clientID, "check-client-banned", {
clientID,
tideID: clientMessager.clientTide.sockets[clientID].tideID
});
const recipientOnline = await clientMessager.clientTide.emitEventWithResponse(clientID, "check-client-online", "retrieved-client-online", {
clientID: recipientID
}, 5000);
if (!recipientOnline || !recipientOnline.online) {
FileTide.outputGradient(`[FileTide] ${recipientID} currently not tiding.`, errorMessageColors);
return false;
}
const fileDetails = await this.getPathData(filePath, filterDirectoryContent);
if (!fileDetails) {
FileTide.outputGradient(`[${clientID}] File at path ${filePath} not found.`, errorMessageColors);
return false;
}
if (fileDetails.type === "file") {
if (fileDetails.largeFile) {
FileTide.outputGradient(`[${clientID}] Sending large file ~ ${fileDetails.fileName} to client ~ ${recipientID}...`, significantMessageColors);
await clientMessager.sendFile(clientID, recipientID, fileDetails.fileName, fileDetails.filePath, destinationPath, fileDetails.fileSize, tidalSize, minTideSize, maxTideSize, true, false, true, transferRequestExpirationTime);
return true;
}
FileTide.outputGradient(`[${clientID}] Sending file ~ ${fileDetails.content.fileName} to client ~ ${recipientID}...`, significantMessageColors);
await clientMessager.sendFile(clientID, recipientID, fileDetails.content.fileName, fileDetails.content.filePath, destinationPath, fileDetails.content.size, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
return true;
}
if (fileDetails.type === "directory") {
FileTide.outputGradient(`[${clientID}] Sending ${fileDetails.content.length} files in directory ~ ${path.basename(filePath)} to client ~ ${recipientID}...`, significantMessageColors);
await clientMessager.sendDirectoryFiles(clientID, recipientID, fileDetails.content, this.getTidePath(filePath), destinationPath, tideSize, minTideSize, maxTideSize, transferRequestExpirationTime);
return true;
}
FileTide.outputGradient(`[FileTide] ~ No active client ~ ${recipientID} found.`, errorMessageColors);
return false;
}
/**
* Check if running in server mode.
* @returns {Boolean} - True if running as a server
*/
fileTideOperational() {
return this.fileNet !== null;
}
/**
* Check if running in client mode.
* @returns {Boolean} - True if any client is active
*/
messagerOperational() {
return this.clients.size > 0;
}
/**
* Stop the server if running.
*/
stopFileTide() {
if (this.fileNet) {
FileTide.outputGradient("Stopping FileTide...", significantMessageColors);
this.fileNet.close();
this.fileNet = null;
FileTide.outputGradient("Stopped FileTide.", significantMessageColors);
}
return;
}
/**
* Stop a specific client.
* @param {String} userID - The ID of the client user to stop
* @param {Function} onBeforeDisconnect - Executes before messager disconnection
* @param {Function} onDisconnect - Executes upon messager disconnection
* @param {Function} onCompletion - Executes upon messager disconnection completion
*/
async stopMessager(userID, onBeforeDisconnect, onDisconnect, onCompletion) {
if (this.clients.has(userID)) {
FileTide.outputGradient(`Stopping messager for user ${userID}...`, significantMessageColors);
const connectionOrigin = this.clients.get(userID);
if (typeof onBeforeDisconnect === "function") {
await onBeforeDisconnect(this, userID, connectionOrigin);
}
if (connectionOrigin?.clientTide?.closeSocket) {
const result = connectionOrigin.clientTide.closeSocket(userID);
if (result instanceof Promise) {
try {
await result;
} catch (error) {
FileTide.outputGradient(`Did not disconnect ~ ${userID} ~ ${error.message}`, errorMessageColors);
}
}
if (typeof onDisconnect === "function") {
await onDisconnect(this, userID, connectionOrigin);
}
}
this.clients.delete(userID);
FileTide.outputGradient(`Stopped messager for user ${userID}.`, significantMessageColors);
if (typeof onCompletion === "function") {
await onCompletion(this, userID, connectionOrigin);
}
return;
}
FileTide.outputGradient(`No active messager found for user ${userID}.`, errorMessageColors);
return;
}
/**
* Stop all active clients.
* @param {Function} onBeforeClientDisconnect - Executes before each messager disconnection
* @param {Function} onClientDisconnect - Executes upon each messager disconnection
* @param {Function} onCompletion - Executes upon all messager disconnection
*/
async stopAllMessagers(onBeforeClientDisconnect, onClientDisconnect, onCompletion) {
FileTide.outputGradient("Stopping all messagers...", significantMessageColors);
const disconnectTasks = [];
for (let [userID, connectionOrigin] of this.clients.entries()) {
if (typeof onBeforeClientDisconnect === "function") {
await onBeforeClientDisconnect(this, userID, connectionOrigin);
}
if (connectionOrigin?.clientTide?.closeSocket) {
const task = async () => {
try {
const result = connectionOrigin.clientTide.closeSocket(userID);
if (result instanceof Promise) {
await result;
}
if (typeof onClientDisconnect === "function") {
await onClientDisconnect(this, userID, connectionOrigin);
}
FileTide.outputGradient(`Disconnected ~ ${userID}`, significantMessageColors);
} catch (error) {
FileTide.outputGradient(`Did not disconnect ~ ${userID} - ${error.message}`, errorMessageColors);
}
};
disconnectTasks.push(task());
}
}
await Promise.all(disconnectTasks);
this.clients.clear();
FileTide.outputGradient("All messagers stopped.", significantMessageColors);
if (typeof onCompletion === "function") {
await onCompletion(this);
}
return;
}
}
_FileTide = FileTide;
function _setupFileEventListeners(userID, client, onTransferProgress, onIncomingTransfer, onIncomingFile, onTransferBarrier, options = {}) {
const {
onTransferStart,
onTransferComplete,
onTransferRequested,
onTransferStatus,
onListFiles,
onFileListReceived,
onCurrentOnlineClients,
onClientTiding,
onCurrentClientIDAlreadyOnline,
onCurrentClientUnauthorized,
onBeforeCurrentClientUnauthorizedDisconnect,
onCurrentClientUnauthorizedDisconnect
} = options;
const cliTable = new ConsoleTable({
padding: 2,
headerAlign: "center",
cellAlign: "left",
borderStyle: "bold",
columnOrder: ["clientID", "originClientID", "connectedOnDisplay"],
columnNames: {
clientID: "Client Name",
originClientID: "Origin Name",
connectedOnDisplay: "Connected On"
},
title: "✨ Online ✨",
tableNumber: 1,
gradient: {
title: ["#00FFFF", "#1E90FF"],
header: ["#FFD700", "#FF8C00"],
border: ["#2e2f30", "#788e9e"],
cell: ["#00BFFF", "#1E90FF"]
},
cellColor: (content, column) => {
if (column === "clientID") {
return chalk.blue(content);
}
return content;
}
});
const fileTransferReceiver = new FileTransferReceiverManager();
client.clientTide.onEvent(userID, "current-online-clients", data => {
client.clientTide.emitEvent(userID, "check-client-banned", {
clientID: userID,
tideID: client.clientTide.sockets[userID].tideID
});
const currentClients = {};
Object.keys(data).forEach(key => {
if (key !== userID) {
if (data[key] && data[userID] && data[key].currentTideChannel === data[userID].currentTideChannel) {
let currentClient = data[key];
currentClient.connectedOnDisplay = HUDUtilityManager.convertUTCDateToDateDisplay(currentClient.connectedOn, true, 1);
currentClients[key] = currentClient;
}
}
});
if (Object.keys(currentClients).length <= 0) {
return;
}
cliTable.setTitle(`✨ Online >${Object.keys(currentClients).length}< ✨`, 1);
cliTable.setData(currentClients);
console.log(`\n[FileTide ~ FileNet]\n\n`, cliTable.render(), "\n");
if (onCurrentOnlineClients) {
onCurrentOnlineClients(currentClients, true);
}
});
client.clientTide.onEvent(userID, "current-client-tiding", data => {
if (onClientTiding) {
onClientTiding(data.message, significantMessageColors);
}
});
client.clientTide.onEvent(userID, "current-clients", data => {
const currentClients = {};
Object.keys(data).forEach(key => {
if (key !== userID) {
currentClients[key] = data[key];
}
});
if (Object.keys(currentClients).length <= 0) {
return;
}
_FileTide.outputGradient(`\n[FileTide ~ FileNet]\n\n✨ Current Clients >${Object.keys(currentClients).length}< ✨\n`, significantMessageColors);
if (onCurrentOnlineClients) {
onCurrentOnlineClients(currentClients, false);
}
});
client.clientTide.onEvent(userID, "current-client-id-already-online", clientID => {
if (userID === clientID) {
return;
}
_FileTide.outputGradient(`[FileTide ~ FileNet] ~ Client ~ ${userID} already online.`, significantMessageColors);
if (onCurrentClientIDAlreadyOnline) {
onCurrentClientIDAlreadyOnline(clientID);
}
return;
});
client.clientTide.onEvent(userID, "retrieved-client-banned", async bannedDetails => {
const clientID = bannedDetails.clientID;
if (userID !== clientID) {
return;
}
if (!bannedDetails.banned) {
return;
}
_FileTide.outputGradient(`[FileTide ~ FileNet] ~ Unauthorized access detected.`, errorMessageColors);
await this.stopAllMessagers(onBeforeCurrentClientUnauthorizedDisconnect, onCurrentClientUnauthorizedDisconnect, async () => {
if (onCurrentClientUnauthorized) {
onCurrentClientUnauthorized(bannedDetails);
}
});
return;
});
client.clientTide.onEvent(userID, "save-current-transfer-states", async data => {
this.saveTransferStates();
return;
});
client.clientTide.onEvent(userID, "current-transfer-state", async data => {
const {
senderID,
fileName,
filePath
} = data;
const currentTransferState = FileTransferRecoveryManager.getTransferState(userID, senderID, `${filePath}-${fileName}`);
client.clientTide.emitEvent(userID, "send-current-transfer-state", {
recipientID: userID,
senderID,
transferState: currentTransferState
});
return;
});
client.clientTide.onEvent(userID, "queue-incoming-transfer", async data => {
if (this.transferBarrier && onIncomingTransfer) {
onIncomingTransfer(data, status => {
client.clientTide.emitEvent(userID, "notify-transfer-barrier", {
accepted: status,
data
});
});
return;
} else if (!this.transferBarrier) {
client.clientTide.emitEvent(userID, "notify-transfer-barrier", {
accepted: true,
data
});
}
return;
});
client.clientTide.onEvent(userID, "incoming-transfer", async data => {
const {
currentSender
} = data;
if (currentSender && currentSender === userID) {
_FileTide.outputGradient(`[${userID}] Transfer successfully sent to ${data.recipientID}`, significantMessageColors);
this.progressBarManager.completionMessage = `Successfully sent to ${data.recipientID}!`;
this.progressBarManager.displayPage("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta);
this.progressBarManager.listenForInput("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta, chalk.yellow);
return;
}
_FileTide.outputGradient(`[${userID}] Preparing to receive transfer : ${FileUtilityManager.getTidePath(data.path)}`, significantMessageColors);
if (onTransferStart) {
onTransferStart(data);
}
this.progressBarManager.completionMessage = `Successfully received transfer from ${data.senderID}!`;
this.progressBarManager.displayPage("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta);
this.progressBarManager.listenForInput("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta, chalk.yellow);
});
client.clientTide.onEvent(userID, "incoming-file", async data => {
try {
_FileTide.outputGradient(`[${userID}] Preparing to receive file : ${data.fileName}`, significantMessageColors);
await fileTransferReceiver.initializeTransfer(data);
const saveDir = FileUtilityManager.getTidePath(data.path);
const verifiedSender = data.senderID && data.senderID !== userID;
if (verifiedSender) {
this.progressBarManager.addTask({
name: data.fileName,
size: data.fileSize
});
}
if (onIncomingFile) {
const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
onIncomingFile(verifiedSender, {
...data,
stats: taskBarStats
}, FileTransferTrackingManager.activeTransfers);
}
if (verifiedSender && !fs.existsSync(saveDir)) {
fs.mkdirSync(saveDir, {
recursive: true
});
_FileTide.outputGradient(`[${userID}] Created directory : ${saveDir}`, significantMessageColors);
}
} catch (error) {
_FileTide.outputGradient(`[${userID}] Halted file recieval preparation : ${data.fileName}\n${error}`, errorMessageColors);
}
});
client.clientTide.onEvent(userID, "accepted-transfer", async data => {
_FileTide.outputGradient(`[${userID}] Accepted ${data.clientID}'s transfer!`, significantMessageColors);
if (onTransferBarrier) {
onTransferBarrier(data);
}
});
client.clientTide.onEvent(userID, "denied-transfer", async data => {
_FileTide.outputGradient(`[${userID}] Denied ${data.clientID}'s transfer.`, errorMessageColors);
if (onTransferBarrier) {
onTransferBarrier(data);
}
});
client.clientTide.onEvent(userID, "transfer-progress", async data => {
if (!data || data.fileChunk === undefined || data.fileChunk === null) {
FileTideDebugUtilityManager.log("notice", true, `Received invalid data chunk from ~ ${data.senderName} in transfer progress ~ ${data.fileName}`);
FileTransferTrackingManager.outputCurrentTransfers();
return;
}
await fileTransferReceiver.handleTransferProgress(data);
this.progressBarManager.updateTaskProgress(data.fileName, data.chunkSize || 512 * 1024);
const currentTransferState = FileTransferRecoveryManager.getTransferState(userID, data.senderName, `${data.path}-${data.fileName}`) || {
transferredSize: 0
};
currentTransferState.transferredSize += data.chunkSize || 512 * 1024;
FileTransferRecoveryManager.saveTransferState(userID, data.senderName, `${data.path}-${data.fileName}`, data.chunkIndex, currentTransferState.transferredSize);
const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
client.clientTide.emitEvent(userID, "acknowledge-transfer-tide", {
fileName: data.fileName,
senderName: data.senderName,
recipientName: userID,
transferStateID: `${data.path}-${data.fileName}`,
path: data.path,
transferStats: taskBarStats
});
if (onTransferProgress) {
onTransferProgress({
...data,
stats: taskBarStats
});
}
});
client.clientTide.onEvent(userID, "transfer-status", data => {
const {
chunkIndex,
chunkSize,
fileName,
fileSize
} = data;
if (chunkIndex === 0) {
FileTransferTrackingManager.trackTransfer(data);
this.progressBarManager.addTask({
name: fileName,
size: fileSize
});
} else if (chunkIndex > 0) {
FileTransferTrackingManager.updateTransfer(data);
this.progressBarManager.updateTaskProgress(fileName, chunkSize);
}
if (onTransferStatus) {
const taskBarStats = this.progressBarManager.getTaskBar(fileName);
onTransferStatus({
...data,
stats: taskBarStats
});
}
return;
});
client.clientTide.onEvent(userID, "transfer-complete", data => {
const savePath = FileUtilityManager.getTidePath(path.join(data.filePath, data.fileName));
try {
_FileTide.outputGradient(`[${userID}] File transfer complete ~ ${data.fileName}`, significantMessageColors);
const transferState = FileTransferTrackingManager.getTransfer(data.fileName);
FileTideDebugUtilityManager.log("notice", true, `Transfer state ~ ${data.fileName} active | ${transferState !== null && transferState !== undefined ? true : false}`);
if (!transferState) {
return;
}
if (transferState.fileStream) {
fileTransferReceiver.completeTransfer(data, (transferData, transfers, success, error) => {
if (success) {
FileTransferRecoveryManager.clearTransferState(userID, data.senderID, `${data.filePath}-${data.fileName}`);
_FileTide.outputGradient(`[${userID}] File saved at ~ ${savePath}\n`, significantMessageColors);
} else if (!success) {
_FileTide.outputGradient(`[${userID}] Did not save file at ~ ${savePath}\n\t${error}\n`, errorMessageColors);
}
if (onTransferComplete) {
const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
onTransferComplete({
...data,
stats: taskBarStats
}, FileTransferTrackingManager.activeTransfers, success);
}
setTimeout(() => {
FileTransferTrackingManager.outputCurrentTransfers();
this.progressBarManager.clearTaskBar(data.fileName);
}, this.progressBarManager.completionTimeout);
});
return;
}
FileTransferRecoveryManager.clearTransferState(userID, data.senderID, `${data.filePath}-${data.fileName}`);
FileTransferTrackingManager.untrackTransfer(data.fileName);
_FileTide.outputGradient(`[${userID}] Transfer successfully sent to ~ ${data.recipientId} and saved at ~ ${path.join(data.filePath, data.fileName)}\n`, significantMessageColors);
if (onTransferComplete) {
const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
onTransferComplete({
...data,
stats: taskBarStats
}, FileTransferTrackingManager.activeTransfers, true);
}
setTimeout(() => {
FileTransferTrackingManager.outputCurrentTransfers();
this.progressBarManager.clearTaskBar(data.fileName);
}, this.progressBarManager.completionTimeout);
} catch (error) {
_FileTide.outputGradient(`[${userID}] Did not save file at ~ ${savePath}\n${error}`, errorMessageColors);
if (onTransferComplete) {
const taskBarStats = this.progressBarManager.getTaskBar(data.fileName);
onTransferComplete({
...data,
stats: taskBarStats
}, FileTransferTrackingManager.activeTransfers, false);
}
setTimeout(() => {
FileTransferTrackingManager.outputCurrentTransfers();
this.progressBarManager.clearTaskBar(data.fileName);
}, this.progressBarManager.completionTimeout);
}
});
client.clientTide.onEvent(userID, "transfer-requested", async data => {
_FileTide.outputGradient(`[${userID}] Transfer requested from: ${data.requesterID}`, significantMessageColors);
this.clients.get(userID).activeTransferTypes.set(data.destinationPath, data.type);
if (onTransferRequested) {
onTransferRequested(data);
}
await this.sendToDevice(data.requesterID, data.path, data.destinationPath, data.filterContent || []);
return;
});
client.clientTide.onEvent(userID, "list-files", async data => {
_FileTide.outputGradient(`[${userID}] Sending file list to ${data.senderID}...!`, significantMessageColors);
const currentClientShorePolicies = this.getShorePolicies(userID);
let totalFilesSent = 0;
const listedFiles = await this.listFiles(currentClientShorePolicies || [">Downloads"], data.depth || 1, (totalItems, directoryContents) => {
const capacitor = new ChunkCapacitor(directoryContents, 100);
const contents = capacitor.getAllChunks();
for (let files of contents) {
totalFilesSent += files.length;
client.clientTide.emitEvent(userID, "send-file-list-to-client", {
senderID: data.recipientID,
recipientID: data.senderID,
totalItems: files.length,
listedFiles: files,
runningOn: this.runningOn
});
}
});
setTimeout(() => {
_FileTide.outputGradient(`[${userID}] Sent file list to ${data.senderID}!`, significantMessageColors);
client.clientTide.emitEvent(userID, "sent-file-list-to-client", {
senderID: data.recipientID,
recipientID: data.senderID,
totalItemsSent: totalFilesSent,
runningOn: this.runningOn
});
}, 1000);
});
client.clientTide.onEvent(userID, "error", async error => {
_FileTide.outputGradient(`[${userID} | FileTide Error] ${error}`, errorMessageColors);
});
client.clientTide.onEvent(userID, "client-file-list-received", async data => {
_FileTide.outputGradient(`[${userID}] Successfully received all ${HUDUtilityManager.convertNumberToMoneyFormat(data.totalItemsSent, false)} contents in ${data.senderID}'s file list!`, significantMessageColors);
if (onFileListReceived) {
onFileListReceived(data);
}
});
client.clientTide.onEvent(userID, "client-file-list", async data => {
client.clientTide.emitEvent(userID, "check-client-banned", {
clientID: userID,
tideID: client.clientTide.sockets[userID].tideID
});
_FileTide.outputGradient(`[${userID}] Received ${HUDUtilityManager.convertNumberToMoneyFormat(data.totalItems, false)} directory contents from ${data.senderID}'s file list!`, significantMessageColors);
if (onListFiles) {
onListFiles(data);
}
});
this.currentUserID = userID;
return;
}
;
module.exports = FileTide;
;