@trap_stevo/filetide 0.0.28 → 0.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,10 @@ const {
11
11
  FileTransferManager
12
12
  } = require("./HUDManagers/FileTransferManager");
13
13
  class FileMessager {
14
- constructor(options = {}, transportOptions = {
14
+ constructor(options = {
15
+ pingTimeout: 3600000,
16
+ pingInterval: 60000
17
+ }, transportOptions = {
15
18
  parallelChunks: 3,
16
19
  maxRetries: 3
17
20
  }) {
@@ -71,14 +71,18 @@ class FileMessagerClient {
71
71
  * @param {string} destinationPath - The path to which the files should be sent.
72
72
  */
73
73
  sendDirectoryFiles(clientID, recipientId, filesData, baseDirectory, destinationPath) {
74
- const baseDirectoryName = path.basename(baseDirectory);
75
- const adjustedDestinationPath = FileUtilityManager.normalizePath(path.join(destinationPath, baseDirectoryName));
76
- const sendFilePromises = filesData.map((fileInfo, index) => {
77
- const relativeFilePath = path.dirname(path.relative(baseDirectory, fileInfo.filePath));
78
- const fileDestinationPath = FileUtilityManager.normalizePath(path.join(adjustedDestinationPath, relativeFilePath));
79
- return this.sendFile(clientID, recipientId, fileInfo.fileName, fileInfo.fileData, fileDestinationPath, fileInfo.size, adjustedDestinationPath, index);
80
- });
81
- Promise.all(sendFilePromises).then(() => console.log("\nAll files in directory transferred successfully!")).catch(error => console.error("Did not transfer files: ", error));
74
+ try {
75
+ const baseDirectoryName = path.basename(baseDirectory);
76
+ const adjustedDestinationPath = FileUtilityManager.normalizePath(path.join(destinationPath, baseDirectoryName));
77
+ const sendFilePromises = filesData.map((fileInfo, index) => {
78
+ const relativeFilePath = path.dirname(path.relative(baseDirectory, fileInfo.filePath));
79
+ const fileDestinationPath = FileUtilityManager.normalizePath(path.join(adjustedDestinationPath, relativeFilePath));
80
+ return this.sendFile(clientID, recipientId, fileInfo.fileName, fileInfo.fileData, fileDestinationPath, fileInfo.size, adjustedDestinationPath, index);
81
+ });
82
+ Promise.all(sendFilePromises).then(() => console.log("\nAll files in directory transferred successfully!")).catch(error => console.error("Did not transfer directory: ", error));
83
+ } catch (error) {
84
+ FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ Refused directory transfer: ${error}`, errorMessageColors);
85
+ }
82
86
  }
83
87
  sendFile(clientID, recipientId, fileName, file, filePath = process.cwd(), fileSize, directoryPath = null, index = 0) {
84
88
  if (!file) {
@@ -140,45 +144,8 @@ class FileMessagerClient {
140
144
  path: filePath,
141
145
  size: fileSize
142
146
  }
143
- }).then(() => FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ File ~ ${fileName} transfer complete!`, significantMessageColors)).catch(error => FileNetUtilityManager.outputGradient(`Refused file transfer: ${error}`, errorMessageColors));
147
+ }).then(() => FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ File ~ ${fileName} transfer complete!`, significantMessageColors)).catch(error => FileNetUtilityManager.outputGradient(`[FileTide ~ File Messager] ~ Refused file transfer: ${error}`, errorMessageColors));
144
148
  }
145
-
146
- /*onFileChunkReceived(userID)
147
- {
148
- this.clientTide.onEvent(userID, "transfer-progress", (data) => {
149
- console.log(`\n[FileTide ~ File Messager] ~ Receiving file chunk for client ~ ${userID}: `, data.fileChunk);
150
-
151
- console.log("\n[FileTide ~ File Messager] ~ Progress: ", data.progress);
152
-
153
- FileUtilityManager.saveChunk(userID, data.fileChunk, data.path, data.name);
154
- });
155
- }
156
-
157
- onFileTransferComplete(userID) {
158
- this.clientTide.onEvent(userID, "transfer-complete", (data) => {
159
- console.log(`\n[FileTide ~ File Messager] ~ File transfer completed for user ${userID}.`);
160
-
161
- FileUtilityManager.assembleFile(userID);
162
- });
163
- }
164
-
165
- handleIncomingFile(userID)
166
- {
167
- this.clientTide.onEvent(userID, "incoming-file", (data) => {
168
- console.log(`\n[FileTide ~ File Messager] ~ Received file for user ${userID}: ${data.fileName}.`);
169
-
170
- FileUtilityManager.saveFile(data.fileName, data.fileData, data.path, data.name);
171
- });
172
- }
173
-
174
- handleMultipleClientsTransfer()
175
- {
176
- this.clients.forEach((userID, roomData) => {
177
- this.onFileChunkReceived(userID);
178
-
179
- this.onFileTransferComplete(userID);
180
- });
181
- }*/
182
149
  }
183
150
  ;
184
151
  module.exports = FileMessagerClient;
@@ -33,6 +33,7 @@ class FileTide {
33
33
  this.progressBarManager = new ConsoleProgressBarManager([], {
34
34
  completionMessageColor: chalk.blue.bold
35
35
  });
36
+ this.clientShorePolicies = new Map();
36
37
  this.clients = new Map();
37
38
  this.currentUserID = "";
38
39
  return;
@@ -71,9 +72,7 @@ class FileTide {
71
72
  }
72
73
  const newClient = new FileMessagerClient(clientOptions);
73
74
  newClient.joinRoom(userID, roomName, connectionOptions);
74
-
75
- //newClient.handleMultipleClientsTransfer();
76
-
75
+ this.clientShorePolicies.set(userID, [FileUtilityManager.getTidePath(">CurrentUser"), FileUtilityManager.getTidePath(">Downloads"), FileUtilityManager.getTidePath(">Documents")]);
77
76
  this.clients.set(userID, newClient);
78
77
  FileTide.outputGradient(`[FileTide] ~ Messager launched successfully for client ~ ${userID}!`, significantMessageColors);
79
78
  _assertClassBrand(_FileTide_brand, this, _setupFileEventListeners).call(this, userID, newClient, onIncomingFile);
@@ -94,6 +93,29 @@ class FileTide {
94
93
  getTidePath(inputPath) {
95
94
  return FileUtilityManager.getTidePath(inputPath);
96
95
  }
96
+ clearShorePolicies(clientID, shores = []) {
97
+ let clientShorePolicies = this.clientShorePolicies.get(clientID);
98
+ if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
99
+ FileTide.outputGradient(`[FileTide] Did not clear from client ~ ${clientID} shore policies.`, ["#F94144", "#F3722C"]);
100
+ return false;
101
+ }
102
+ const shorePolicies = Array.from(clientShorePolicies.values());
103
+ const currentShores = new Set(clientShorePolicies);
104
+ this.clientShorePolicies.set(clientID, shorePolicies.filter(shorePolicy => !currentShores.has(shorePolicy)));
105
+ return true;
106
+ }
107
+ addShorePolicies(clientID, shores = []) {
108
+ const clientShorePolicies = this.clientShorePolicies.get(clientID);
109
+ if (!shores || shores.length <= 0 || !clientShorePolicies || !clientID) {
110
+ FileTide.outputGradient(`[FileTide] Did not add to client ~ ${clientID} shore policies.`, ["#F94144", "#F3722C"]);
111
+ return false;
112
+ }
113
+ this.clientShorePolicies.set(clientID, [...new Set([...clientShorePolicies, ...shores])]);
114
+ return true;
115
+ }
116
+ getShorePolicies(clientID) {
117
+ return this.clientShorePolicies.get(clientID);
118
+ }
97
119
 
98
120
  /**
99
121
  * Send files / directories directly to a device.
@@ -230,22 +252,26 @@ function _setupFileEventListeners(userID, client, onIncomingFile) {
230
252
  this.progressBarManager.listenForInput("Page Number:", "Press 'n' for next page, 'p' for previous page.", chalk.blue, chalk.magenta, chalk.yellow);
231
253
  });
232
254
  client.clientTide.onEvent(userID, "incoming-file", data => {
233
- console.log(`[${userID}] Preparing to receive file : ${data.fileName}`);
234
- activeTransfers.set(data.fileName, {
235
- receivedChunks: [],
236
- totalChunks: data.totalChunks,
237
- fileInfo: data
238
- });
239
- const saveDir = FileUtilityManager.getTidePath(data.path);
240
- this.progressBarManager.addTask({
241
- name: data.fileName,
242
- size: data.fileSize
243
- });
244
- if (data.senderID && data.senderID !== userID && !fs.existsSync(saveDir)) {
245
- fs.mkdirSync(saveDir, {
246
- recursive: true
255
+ try {
256
+ _FileTide.outputGradient(`[${userID}] Preparing to receive file : ${data.fileName}`, significantMessageColors);
257
+ activeTransfers.set(data.fileName, {
258
+ receivedChunks: [],
259
+ totalChunks: data.totalChunks,
260
+ fileInfo: data
247
261
  });
248
- _FileTide.outputGradient(`[${userID}] Created directory : ${saveDir}`, significantMessageColors);
262
+ const saveDir = FileUtilityManager.getTidePath(data.path);
263
+ if (data.senderID && data.senderID !== userID && !fs.existsSync(saveDir)) {
264
+ this.progressBarManager.addTask({
265
+ name: data.fileName,
266
+ size: data.fileSize
267
+ });
268
+ fs.mkdirSync(saveDir, {
269
+ recursive: true
270
+ });
271
+ _FileTide.outputGradient(`[${userID}] Created directory : ${saveDir}`, significantMessageColors);
272
+ }
273
+ } catch (error) {
274
+ _FileTide.outputGradient(`[${userID}] Halted file recieval preparation : ${data.fileName}\n${error}`, errorMessageColors);
249
275
  }
250
276
  });
251
277
  client.clientTide.onEvent(userID, "transfer-progress", data => {
@@ -256,30 +282,29 @@ function _setupFileEventListeners(userID, client, onIncomingFile) {
256
282
  if (!transferState) {
257
283
  return;
258
284
  }
259
-
260
- //console.log(`[${userID}] Receiving chunk ${data.chunkIndex + 1}/${transferState.totalChunks} for file : ${data.fileName}`);
261
-
262
285
  transferState.receivedChunks[data.chunkIndex] = Buffer.from(data.fileChunk);
263
286
  const progress = (data.chunkIndex + 1) / transferState.totalChunks * 100;
264
-
265
- //console.log(`[${userID}] Progress : ${progress.toFixed(2)}%`);
266
-
267
287
  this.progressBarManager.updateTaskProgress(data.fileName, 512 * 1024);
268
288
  if (onIncomingFile) {
269
289
  onIncomingFile(data);
270
290
  }
271
291
  });
272
292
  client.clientTide.onEvent(userID, "transfer-complete", data => {
273
- console.log(`[${userID}] File transfer complete : ${data.fileName}`);
274
- const transferState = activeTransfers.get(data.fileName);
275
- if (!transferState) {
276
- return;
293
+ try {
294
+ _FileTide.outputGradient(`[${userID}] File transfer complete : ${data.fileName}`, significantMessageColors);
295
+ const transferState = activeTransfers.get(data.fileName);
296
+ if (!transferState) {
297
+ return;
298
+ }
299
+ const savePath = FileUtilityManager.getTidePath(path.join(data.filePath, data.fileName));
300
+ const fullFile = Buffer.concat(transferState.receivedChunks);
301
+ fs.writeFileSync(savePath, fullFile);
302
+ _FileTide.outputGradient(`[${userID}] File saved at : ${savePath}`, significantMessageColors);
303
+ activeTransfers.delete(data.fileName);
304
+ } catch (error) {
305
+ _FileTide.outputGradient(`[${userID}] Did not save file at : ${savePath}\n${error}`, errorMessageColors);
306
+ activeTransfers.delete(data.fileName);
277
307
  }
278
- const savePath = FileUtilityManager.getTidePath(path.join(data.filePath, data.fileName));
279
- const fullFile = Buffer.concat(transferState.receivedChunks);
280
- fs.writeFileSync(savePath, fullFile);
281
- _FileTide.outputGradient(`[${userID}] File saved at : ${savePath}`, significantMessageColors);
282
- activeTransfers.delete(data.fileName);
283
308
  });
284
309
  client.clientTide.onEvent(userID, "transfer-requested", data => {
285
310
  _FileTide.outputGradient(`[${userID}] Transfer requested from: ${data.requesterID}`, significantMessageColors);
@@ -3,6 +3,8 @@
3
3
  class FileMessagerConfigManager {
4
4
  static getServerOptions({
5
5
  maxHttpBufferSize = 1e9,
6
+ pingTimeout = 3600000,
7
+ pingInterval = 60000,
6
8
  useHTTPS = false,
7
9
  corsOrigin = "*",
8
10
  useCors = true,
@@ -24,7 +26,7 @@ class FileMessagerConfigManager {
24
26
  };
25
27
  }
26
28
  static getClientOptions({
27
- serverUrl = 'http://localhost:3000'
29
+ serverUrl = "http://localhost:3000"
28
30
  } = {}) {
29
31
  return {
30
32
  url: serverUrl
@@ -24,15 +24,83 @@ class FileUtilityManager {
24
24
  });
25
25
  return totalSize;
26
26
  }
27
+
28
+ /**
29
+ * Function to filter files and directories.
30
+ * @param {string} dirPath - The directory path to scan
31
+ * @param {Array} filterContent - Array of paths (files, directories, extensions) to avoid (e.g., ['docs', 'example.txt', '.js'])
32
+ * @param {function} callback - A callback function to handle the results
33
+ */
34
+ static filterFilesAndDirectories(dirPath, filterContent = [], callback) {
35
+ fs.readdir(dirPath, {
36
+ withFileTypes: true
37
+ }, (error, items) => {
38
+ if (error) {
39
+ return callback(error);
40
+ }
41
+ const results = [];
42
+ items.forEach(item => {
43
+ const itemPath = path.join(dirPath, item.name);
44
+ const filtered = filterContent.some(filterEntry => {
45
+ const resolvedFilterEntry = path.resolve(filterEntry);
46
+ const fileExtension = filterEntry.startsWith(".");
47
+ return itemPath === resolvedFilterEntry || item.name === filterEntry || fileExtension && path.extname(item.name) === filterEntry;
48
+ });
49
+ if (!filtered) {
50
+ fs.stat(itemPath, (error, stats) => {
51
+ if (error) {
52
+ return callback(error);
53
+ }
54
+ results.push({
55
+ dateCreated: stats.birthtime,
56
+ type: item.isDirectory() ? "directory" : "file",
57
+ size: stats.size,
58
+ name: item.name,
59
+ path: itemPath
60
+ });
61
+ if (results.length === items.length) {
62
+ callback(null, results);
63
+ }
64
+ });
65
+ } else if (results.length === items.length) {
66
+ callback(null, results);
67
+ }
68
+ });
69
+ });
70
+ }
71
+
72
+ /**
73
+ * Function to check for a path or any of the path's subpaths inside the user's open shore (allowed drop-zone) policy.
74
+ * Supports a wildcard '*' which allows all paths.
75
+ * @param {string} shorePath - The file or directory path to check
76
+ * @param {Array} openShores - Array of paths or '*' to check against
77
+ * @returns {boolean} - Returns true if openShores found the itemPath or the itemPath's subpath.
78
+ */
79
+ static allowedShore(shorePath, openShores = []) {
80
+ const resolvedShorePath = path.resolve(shorePath);
81
+ if (openShores.includes("*")) {
82
+ return true;
83
+ }
84
+ return openShores.some(listedShore => {
85
+ const currentShore = path.resolve(listedShore);
86
+ return resolvedShorePath === currentShore || resolvedShorePath.startsWith(currentShore + path.sep);
87
+ });
88
+ }
27
89
  static getTidePath(inputPath) {
28
- const homeDir = os.homedir();
90
+ let homeDir = os.homedir();
29
91
  const platform = process.platform;
92
+ let currentUserDir = homeDir;
93
+ if (platform === "linux") {
94
+ const username = process.env.USER || process.env.LOGNAME;
95
+ homeDir = "/home";
96
+ currentUserDir = path.join(homeDir, username);
97
+ }
30
98
  const folderMappings = {
31
99
  ">Downloads": path.join(homeDir, "Downloads"),
32
100
  ">Documents": path.join(homeDir, "Documents"),
33
101
  ">Desktop": path.join(homeDir, "Desktop"),
34
102
  ">AppData": platform === "win32" ? path.join(homeDir, "AppData", "Roaming") : path.join(homeDir, ".config"),
35
- ">LocalAppData": platform === "win32" ? path.join(homeDir, "AppData", "Local") : "/var/local",
103
+ ">LocalAppData": platform === "win32" ? path.join(homeDir, "AppData", "Local") : path.join(homeDir, ".local", "share"),
36
104
  ">Music": path.join(homeDir, "Music"),
37
105
  ">Pictures": path.join(homeDir, "Pictures"),
38
106
  ">Videos": path.join(homeDir, "Videos"),
@@ -44,6 +112,7 @@ class FileUtilityManager {
44
112
  ">Cache": platform === "win32" ? path.join(homeDir, "AppData", "Local", "Cache") : path.join(homeDir, ".cache"),
45
113
  ">Config": platform === "win32" ? path.join(homeDir, "AppData", "Local", "Config") : "/etc",
46
114
  ">CurrentDirectory": process.cwd(),
115
+ ">CurrentUser": currentUserDir,
47
116
  ">Home": homeDir
48
117
  };
49
118
  let resolvedPath = inputPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trap_stevo/filetide",
3
- "version": "0.0.28",
3
+ "version": "0.0.31",
4
4
  "description": "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 with a tool designed for precision, efficiency, and effortless connectivity.",
5
5
  "main": "dist/cjs/FileTide.js",
6
6
  "scripts": {
@@ -29,7 +29,7 @@
29
29
  "author": "Steven Compton",
30
30
  "license": "ISC",
31
31
  "dependencies": {
32
- "@trap_stevo/iotide": "^0.0.36",
32
+ "@trap_stevo/iotide": "^0.0.37",
33
33
  "@trap_stevo/iotide-client": "^0.0.15",
34
34
  "@trap_stevo/legendarybuilderpronodejs-utilities": "^1.0.40",
35
35
  "chalk": "^4.1.2",