UNPKG

@trap_stevo/legendarybuilderpronodejs-utilities

Version:

The legendary computational utility API that makes your application a legendary application. ~ Created by Steven Compton

1,820 lines (1,255 loc) 44.9 kB
/* Created by Hassan Steven Compton. March 2, 2024. */ const crypto = require("crypto"); const path = require("path"); const fs = require("fs"); const { addDays, addWeeks, addMonths, addYears } = require("date-fns"); async function getUniversalMultiDataContainingDesiredData(currentDB, collectionID, docAttributeID, input) { const desiredData = []; try { const collection = await currentDB.collection(collectionID); const snapshot = await collection.get(); const inputObject = typeof input === "object" && input !== null; const inputStr = inputObject ? JSON.stringify(input).toLowerCase() : String(input).toLowerCase(); for (const doc of snapshot.docs) { const data = doc.data(); const field = data[docAttributeID]; if (field == null) { continue; } let match = false; if (Array.isArray(field)) { match = field.includes(input); } else { const type = typeof field; switch (type) { case "string": match = field.toLowerCase().includes(inputStr); break; case "object": try { match = JSON.stringify(field).toLowerCase().includes(inputStr); } catch (e) { console.warn("Could not stringify object field", e); } break; case "number": case "boolean": match = field === input; break; } } if (match) { desiredData.push(data); } } return desiredData; } catch (error) { console.error(`Did not get documents in ${collectionID}: `, error); return []; } }; async function getUniversalMultiData(currentDB, collectionID) { try { const snapshot = await currentDB.collection(collectionID).get(); return snapshot.docs.map(doc => doc.data()); } catch (error) { console.error(`Did not get documents in ${collectionID}: `, error); return []; } }; async function getUniversalData(currentDB, collectionID, docAttributeID, input) { try { const collection = await currentDB.collection(collectionID); const snapshot = await collection.where(docAttributeID, '==', input).get(); for (const doc of snapshot.docs) { const data = doc.data(); if (data !== null && data !== undefined) { return data; } } return null; } catch (error) { return null; } }; async function getUniversalDataFromDocAttribute(currentDB, collectionID, docID, docAttributeID) { try { const docRef = await currentDB.collection(collectionID).doc(docID); const snapshot = await docRef.get(); const data = await snapshot.data(); return data[docAttributeID]; } catch (error) { return null; } }; async function getUniversalDataFromDoc(currentDB, collectionID, docID) { try { const docRef = await currentDB.collection(collectionID).doc(docID); const snapshot = await docRef.get(); const data = await snapshot.data(); return data; } catch (error) { return null; } }; async function checkForMatchingUniversalData(currentDB, collectionID, data, exclude = []) { try { let query = await currentDB.collection(collectionID); for (const [key, value] of Object.entries(data)) { if (!exclude.includes(key)) { query = query.where(key, '==', value); } } const snapshot = await query.get(); if (snapshot.empty) { console.log("Document not found"); return false; } return true; } catch (error) { console.error("Did not check documents....", error); return false; } }; async function getUniversalCollectionSize(currentDB, collectionID) { try { const snapshot = await currentDB.collection(collectionID).get(); return snapshot.size; } catch (error) { return 0; } }; async function getAvailableUniversalDocID(currentDB, collectionID) { try { const snapshot = await currentDB.collection(collectionID).get(); const docIDs = snapshot.docs.map(doc => parseInt(doc.id)).sort((a, b) => a - b); for (let i = 0; i < docIDs.length; i++) { if (docIDs[i] !== i) { return i; } } return docIDs.length; } catch (error) { console.error("Did not get the next available universal ID: ", error); return null; } }; async function addUniversalData(currentDB, collectionID, docIDAttributeName, docData) { try { const docID = await getAvailableUniversalDocID(currentDB, collectionID); if (docID === null) { throw new Error("Did not determine the next available universal ID."); } docData[docIDAttributeName] = docID; await currentDB.collection(collectionID).doc(docID.toString()).set(docData); console.log("Added document " + docID + " into " + collectionID); return docID; } catch (error) { console.log("Did not add document to " + collectionID, error); return null; } }; async function deleteUniversalData(currentDB, collectionID, docID) { try { await currentDB.collection(collectionID).doc(docID.toString()).delete(); console.log("Deleted document " + docID + " in " + collectionID); return true; } catch (error) { console.log("Did not delete document " + docID + " in " + collectionID + ": ", error); return false; } }; async function deleteUniversalDataField(currentDB, collectionID, docID, docIDAttributeName) { try { const docRef = await currentDB.collection(collectionID).doc(docID.toString()); await docRef.update({ [docIDAttributeName] : FieldValue.delete() }); console.log(`Field ${docIDAttributeName} successfully deleted!`); return true; } catch (error) { console.log(`Did not delete field ${docIDAttributeName} in ` + docID + ": ", error); return false; } }; function updateUniversalData(currentDB, collectionID, documentId, updateData, callback) { const docRef = currentDB.collection(collectionID).doc(documentId); docRef.get() .then(docSnapshot => { if (!docSnapshot.exists) { console.log(`Document ${documentId} in ${collectionID} not found.`); if (typeof callback === 'function') { callback(new Error(`Document ${documentId} in ${collectionID} not found.`), null); } return; } docRef.update(updateData) .then(() => { console.log(`Document ${documentId} in ${collectionID} updated successfully.`); if (typeof callback === 'function') { callback(null, `Document ${documentId} in ${collectionID} updated successfully.`); } }) .catch((error) => { console.error(`Did not update document ${documentId} in ${collectionID}: `, error); if (typeof callback === 'function') { callback(error, null); } }); }) .catch((error) => { console.error(`Did not get document ${documentId} in ${collectionID}: `, error); if (typeof callback === 'function') { callback(error, null); } }); }; function deepEqualData(currentData, comparedData) { if (currentData === comparedData) { return true; } if (typeof currentData !== 'object' || currentData === null || typeof comparedData !== 'object' || comparedData === null) { return false; } const keys = Object.keys(currentData); const comparedKeys = Object.keys(comparedData); if (keys.length !== comparedKeys.length) { return false; } for (const key of keys) { if (!comparedKeys.includes(key)) { return false; } if (typeof currentData[key] === 'object' && typeof comparedData[key] === 'object') { if (!deepEqualData(currentData[key], comparedData[key])) { return false; } } else if (currentData[key] !== comparedData[key]) { return false; } } return true; }; function desiredInnerUniversalData(data) { let dictionary = Object.values(data); return dictionary.length > 0 ? dictionary[0] : null }; // HUD Universal Functionality function convertUTCDateToDateDisplay(utcDouble, localTime = true, dateOffset = 1000) { const date = new Date(utcDouble * dateOffset); let month, day, year, hours, minutes, ampm, formattedHours; if (localTime) { month = date.getMonth() + 1; day = date.getDate(); year = date.getFullYear().toString().slice(-2); hours = date.getHours(); } else { month = date.getUTCMonth() + 1; day = date.getUTCDate(); year = date.getUTCFullYear().toString().slice(-2); hours = date.getUTCHours(); } const pad = (num) => (num < 10 ? `0${num}` : num); minutes = pad(date.getUTCMinutes()); ampm = hours >= 12 ? 'PM' : 'AM'; formattedHours = hours % 12 || 12; return `${month}/${day}/${year} ${formattedHours}:${minutes} ${ampm}`; }; function generateUTCDateDouble() { const utcDate = new Date(); const utcDouble = utcDate.getTime(); return utcDouble; }; function getNextUTCDate(startDate, interval) { const inputDate = new Date(startDate); var activators = { "day" : function() { return addDays(inputDate, 1); }, "two days" : function() { return addDays(inputDate, 2); }, "three days" : function() { return addDays(inputDate, 3); }, "four days" : function() { return addDays(inputDate, 4); }, "five days" : function() { return addDays(inputDate, 5); }, "week" : function() { return addWeeks(inputDate, 1); }, "two weeks" : function() { return addWeeks(inputDate, 2); }, "month" : function() { return addMonths(inputDate, 1); }, "two months" : function() { return addMonths(inputDate, 2); }, "three months" : function() { return addMonths(inputDate, 3); }, "six months" : function() { return addMonths(inputDate, 6); }, "year" : function() { return addYears(inputDate, 1); }, }; if (activators[interval] !== undefined) { return activators[interval]().getTime(); } return null; }; function generateDateToID(date, interval = "day") { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hour = String(date.getHours()).padStart(2, '0'); const minute = String(date.getMinutes()).padStart(2, '0'); return interval === "year" ? `${year}` : interval === "month" ? `${year}-${month}` : interval === "day" ? `${year}-${month}-${day}` : interval === "hour" ? `${year}-${month}-${day}-${hour}` : `${year}-${month}-${day}-${hour}-${minute}`; }; function convertNumberToMoneyFormat(n, showDecimals = true, minimumDecimals = 2, maximumDecimals = 2, moneyLocality = "en-US") { const number = parseFloat(n); const options = showDecimals ? { minimumFractionDigits : minimumDecimals, maximumFractionDigits : maximumDecimals } : { minimumFractionDigits : 0, maximumFractionDigits : 0 }; const moneyNumber = n.toLocaleString(moneyLocality, options); return moneyNumber; }; function displayLegalDocumentCurrentDate() { const date = new Date(); const month = date.toLocaleString("default", { month : "long" }); const year = date.getFullYear(); const day = date.getDate(); return `${month} ${day}, ${year}`; }; function convertNumberToWords(n) { const ones = ["Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"]; const tens = ["", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"]; if (n < 20) { return ones[n]; } if (n < 100) { return tens[Math.floor(n / 10)] + (n % 10 ? '-' + ones[n % 10] : ''); } if (n < 1000) { return ones[Math.floor(n / 100)] + ' Hundred' + (n % 100 ? ' ' + ConvertNumberToWords(n % 100) : ''); } const units = ["Thousand", "Million", "Billion", "Trillion", "Quadrillion", "Quintillion", "Sextillion", "Septillion", "Octillion", "Nonillion", "Decillion"]; let unitIndex = 0; let remainder = n; while (remainder >= 1000) { remainder /= 1000; unitIndex++; } remainder = Math.floor(remainder); let words = ConvertNumberToWords(remainder) + " " + units[unitIndex - 1]; let rest = n % (Math.pow(1000, unitIndex)); if (rest > 0) { words += " " + ConvertNumberToWords(rest); } return words; }; function convertDateTime(dateString, includeTimeZone = true, includeLeadingZeroHour = true, includeSeconds = true, shortDateFormat = false, includeLeadingZeroMonth = true) { const date = new Date(dateString); let formattedDate; if (shortDateFormat) { formattedDate = date.toLocaleDateString("en-US", { month : includeLeadingZeroMonth ? "2-digit" : "numeric", day : "2-digit", year : "numeric" }); } else { formattedDate = date.toLocaleDateString("en-US", { weekday : "short", month : "short", day : "numeric", year : "numeric" }); } const timeOptions = { hour : includeLeadingZeroHour ? "2-digit" : "numeric", minute : "2-digit", hour12 : true }; if (includeSeconds) { timeOptions.second = "2-digit"; } const formattedTime = date.toLocaleTimeString('en-US', timeOptions); let finalOutput = `${formattedDate} ${formattedTime}`; if (includeTimeZone) { const timeZone = date.toTimeString().match(/\(([^)]+)\)/)[1]; finalOutput += ` (${timeZone})`; } return finalOutput; }; function convertSecondsToETATime(seconds) { if (seconds === 0) return "0 s"; const units = [ { name : "y", seconds : 60 * 60 * 24 * 365 }, { name : "mo", seconds : 60 * 60 * 24 * 30 }, { name : "w", seconds : 60 * 60 * 24 * 7 }, { name : "d", seconds : 60 * 60 * 24 }, { name : "h", seconds : 60 * 60 }, { name : "m", seconds : 60 }, { name : "s", seconds : 1 } ]; let remainingSeconds = seconds; let result = ""; for (const unit of units) { const count = Math.floor(remainingSeconds / unit.seconds); if (count > 0) { result += `${count}${unit.name} `; remainingSeconds %= unit.seconds; } } return result.trim(); }; function convertToVideoTime(time, options = { showYears : false, showMonths : false, showDays : true, showHours : true, showMinutes : true, showSeconds : true, useLetters : false, leadingZero : true, showZero : true }) { const years = Math.floor(time / (365 * 24 * 60 * 60)); const months = Math.floor((time % (365 * 24 * 60 * 60)) / (30 * 24 * 60 * 60)); const days = Math.floor((time % (30 * 24 * 60 * 60)) / (24 * 60 * 60)); const hours = Math.floor((time % (24 * 60 * 60)) / (60 * 60)); const minutes = Math.floor((time % (60 * 60)) / 60); const seconds = Math.floor(time % 60); if (years > 0 && options.showYears) { return `${years}${options.useLetters ? "y:" : ":"}${months}${options.useLetters ? "m:" : ":"}${days}${options.useLetters ? "d:" : ":"}${hours < 10 && options.leadingZero ? "0" : ""}${hours}${options.useLetters ? "h:" : ":"}${minutes < 10 ? "0" : ""}${minutes}${options.useLetters ? "m:" : ":"}${seconds < 10 ? "0" : ""}${seconds}${options.useLetters ? "s" : ""}`; } if (months > 0 && options.showMonths) { return `${months}${options.useLetters ? "m:" : ":"}${days}${options.useLetters ? "d:" : ":"}${hours < 10 && options.leadingZero ? "0" : ""}${hours}${options.useLetters ? "h:" : ":"}${minutes < 10 ? "0" : ""}${minutes}${options.useLetters ? "m:" : ":"}${seconds < 10 ? "0" : ""}${seconds}${options.useLetters ? "s" : ""}`; } if (days > 0 && options.showDays) { return `${days}${options.useLetters ? "d:" : ":"}${hours < 10 && options.leadingZero ? "0" : ""}${hours}${options.useLetters ? "h:" : ":"}${minutes < 10 ? "0" : ""}${minutes}${options.useLetters ? "m:" : ":"}${seconds < 10 ? "0" : ""}${seconds}${options.useLetters ? "s" : ""}`; } if (hours > 0 && options.showHours) { return `${hours < 10 && options.leadingZero ? "0" : ""}${hours}${options.useLetters ? "h:" : ":"}${minutes < 10 ? "0" : ""}${minutes}${options.useLetters ? "m:" : ":"}${seconds < 10 ? "0" : ""}${seconds}${options.useLetters ? "s" : ""}`; } if (minutes > 0 || (options.showZero && options.showMinutes)) { return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`; } return `${seconds < 10 ? "0" : ""}${seconds}`; }; function convertDuration(duration) { const regex = /(\d+)\s*(ms|s|m|h|d|M|y|ns)/g; let totalMilliseconds = 0; let match; while ((match = regex.exec(duration)) !== null) { const value = parseInt(match[1]); const unit = match[2]; switch (unit) { case 'ms': totalMilliseconds += value; break; case 's': totalMilliseconds += value * 1000; break; case 'm': totalMilliseconds += value * 1000 * 60; break; case 'h': totalMilliseconds += value * 1000 * 60 * 60; break; case 'd': totalMilliseconds += value * 1000 * 60 * 60 * 24; break; case 'M': totalMilliseconds += value * 1000 * 60 * 60 * 24 * 30; break; case 'y': totalMilliseconds += value * 1000 * 60 * 60 * 24 * 365; break; case 'ns': totalMilliseconds += value / 1000000; break; default: throw new Error(`Unknown time unit: ${unit}`); } } return totalMilliseconds; }; function convertToReadableDuration(ms) { const years = Math.floor(ms / (1000 * 60 * 60 * 24 * 365)); ms %= 1000 * 60 * 60 * 24 * 365; const months = Math.floor(ms / (1000 * 60 * 60 * 24 * 30)); ms %= 1000 * 60 * 60 * 24 * 30; const days = Math.floor(ms / (1000 * 60 * 60 * 24)); ms %= 1000 * 60 * 60 * 24; const hours = Math.floor(ms / (1000 * 60 * 60)); ms %= 1000 * 60 * 60; const minutes = Math.floor(ms / (1000 * 60)); ms %= 1000 * 60; const seconds = Math.floor(ms / 1000); ms %= 1000; return { years, months, days, hours, minutes, seconds, milliseconds: ms }; }; function convertTextIntoParagraphs(text, maxSentences = 8, maxWords = null, maxParagraphLength = null, returnArray = false) { let words = text.split(/\s+/); let sentences = text.match(/[^.!?]+[.!?]+["')]*|.+/g) || []; let paragraphs = []; let currentParagraph = ""; let wordCount = 0; let sentenceCount = 0; words.forEach(word => { let exceedsCharLimit = maxParagraphLength && (currentParagraph.length + word.length + 1) > maxParagraphLength; let exceedsWordLimit = maxWords && (wordCount + 1) > maxWords; let exceedsSentenceLimit = maxSentences && (sentenceCount + 1) > maxSentences; if ((maxParagraphLength && exceedsCharLimit) || (maxWords && exceedsWordLimit) || (maxSentences && exceedsSentenceLimit)) { paragraphs.push(currentParagraph.trim()); currentParagraph = ""; wordCount = 0; sentenceCount = 0; } currentParagraph += word + " "; wordCount++; if (/[.!?]$/.test(word)) { sentenceCount++; } }); if (currentParagraph.trim().length > 0) { paragraphs.push(currentParagraph.trim()); } return returnArray ? paragraphs : paragraphs.join("\n\n"); }; function convertFileSizeToDisplay(bytes, decimalPoints = 2) { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(decimalPoints)) + " " + sizes[i]; }; function convertToSizeUnits(size) { const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return { current : size.toFixed(2), unit : units[unitIndex] }; }; function containsBlacklistedCharacters(input, whiteListedInput = "") { let blacklistedChars = ' \t\n\r!@#$%^&*()+=[]{};:\'",<>/?\\|`~'; for (let whiteListedChar of whiteListedInput) { blacklistedChars = blacklistedChars.replace(whiteListedChar, ""); } const blacklistedCharacters = new RegExp('[' + blacklistedChars.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&") + ']'); return blacklistedCharacters.test(input); }; function cleanData(data, options = { deep : false }) { if (typeof data !== "object" || data === null) { return {}; } const result = {}; for (const [key, value] of Object.entries(data)) { if (value === null || value === undefined) { continue; } if (options.deep && typeof value === "object" && !Array.isArray(value)) { const cleanedNested = cleanData(value, options); if (Object.keys(cleanedNested).length > 0) { result[key] = cleanedNested; } } else { result[key] = value; } } return result; }; function convertHexToRGB(hex) { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return [r, g, b]; }; async function generateChalk() { const chalk = await import("chalk"); return chalk.default; }; function generateLerp(a, b, t) { return a + (b - a) * t; }; function generateColorInterpolation(color1, color2, factor) { const result = color1.slice(); for (let i = 0; i < 3; i++) { result[i] = Math.round(generateLerp(color1[i], color2[i], factor)); } return result; }; function generateGradientColors(colors, steps) { let gradient = []; const sections = colors.length - 1; const stepsPerSection = Math.floor(steps / sections); for (let section = 0; section < sections; section++) { for (let step = 0; step < stepsPerSection; step++) { const color1 = convertHexToRGB(colors[section]); const color2 = convertHexToRGB(colors[section + 1]); const factor = step / stepsPerSection; gradient.push(generateColorInterpolation(color1, color2, factor)); } } gradient.push(convertHexToRGB(colors[colors.length - 1])); while (gradient.length < steps) { gradient.push(convertHexToRGB(colors[colors.length - 1])); } return gradient; }; async function outputMovingGradient(text, colors, interval = 100) { const chalk = await generateChalk(); let offset = 0; const updateText = () => { const gradientColors = generateGradientColors(colors, text.length); let coloredText = ''; for (let i = 0; i < text.length; i++) { const colorIndex = (i + offset) % gradientColors.length; const [r, g, b] = gradientColors[colorIndex]; coloredText += chalk.rgb(r, g, b)(text[i]); } console.clear(); console.log(coloredText); offset = (offset + 1) % text.length; }; setInterval(updateText, interval); }; async function outputGradient(text, colors) { const chalk = await generateChalk(); const gradient = generateGradientColors(colors, text.length); let coloredText = ''; for (let i = 0; i < text.length; i++) { const [r, g, b] = gradient[i]; coloredText += chalk.rgb(r, g, b)(text[i]); } console.log(coloredText); return; }; function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(async () => { try { await func.apply(this, args); } catch (error) { if (error.type !== "cancelation") { console.error("Error during debounce: ", error); } } }, wait); }; }; function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }; function incrementVersion(versionInfo, incrementID = "patch") { const versionP = versionInfo.split(".").map(Number); var id = incrementID; if (versionP[2] === 100) { id = "minor"; } if (versionP[1] === 100) { id = "major"; } if (versionP[0] === 100) { id = "patch"; } switch (id) { case 'major': versionP[0]++; versionP[1] = 0; versionP[2] = 0; break; case 'minor': versionP[1]++; versionP[2] = 0; break; case "patch": versionP[2]++; break; default: break; } const version = versionP.join("."); return version; }; function ifNightTime(date = new Date(), minT = 6, maxT = 18) { const hour = date.getHours(); return hour >= maxT || hour < minT; }; function outputPackageCreationTitle(displayDate = true, displayAuthor = true) { const date = displayDate ? convertUTCDateToDateDisplay(generateUTCDateDouble(), true, 1) : ""; const author = displayAuthor ? "~ Created by Steven Compton" : ""; outputGradient(date + "\n\n" + author, ["#F0C14B", "#FFF9DB", "#FFF9DB", "#B38600", "#FFF9DB", "#F7D9A0"]); return; } function outputPackageName() { outputGradient("LegendaryBuilderProNodeJS-Utilities", ["#800080", "#FF00FF"]); return; } function outputPackageLogo() { outputGradient(` ..::--=+- .::--==+++++++++ ::-================++. ------=============++: ----------=====-::.. :-:----------==. ... ..:--:--. .------=. ..::::.: :-:.. .-: -:-----: ::.. .:: ::. .:: -::::--: :: .:..:. :: :::::::- ... ::. .. :: .:...::- . . .... . .. . ....: . . . .:.. ... . ... . . . .. . : . . .. . . . . .. . .. . . .. . .. . .. . . . .. . . ... . .. . .. . .. . ... . .. . .. ... . .. . . . . `, ["#FF00FF", "#800080", "#FF00FF"]); return; } function outputPackageCredit(displayLogo = true, displayName = true, displayCreationTitle = true, displayDate = true, displayAuthor = true) { if (displayLogo) outputPackageLogo(); if (displayName) { outputPackageName(); console.log("\n"); } if (displayCreationTitle) outputPackageCreationTitle(displayDate, displayAuthor); return; } async function getDesiredData(currentDB, collectionID, docAttrID, inputData) { const desiredData = await getUniversalData(currentDB, collectionID, docAttrID, inputData); if (desiredData === null) { return null; } return desiredData; }; async function addDesiredData(currentDB, collectionID, iD, inputData) { await addUniversalData(currentDB, collectionID, iD, inputData); return; }; // Universal File Manager Functionality function validateSignedURL(req, res, baseFilePath, secretKey) { const { filePath, expires, signature, salt, ip } = req.query; if (!salt) { return res.status(400).json({ message : "Not authorized; missing credentials." }); } const currentTime = Math.floor(Date.now() / 1000); if (currentTime > expires) { return res.status(403).json({ message : "URL expired." }); } const clientIp = req.ip; if (ip && clientIp !== ip) { return res.status(403).json({ message : "Address not authorized." }); } const dataToSign = `${filePath}:${expires}:${ip || ""}`; const expectedSignature = crypto.createHmac("sha256", secretKey).update(dataToSign + salt).digest("hex"); if (signature !== expectedSignature) { return res.status(403).json({ message : "Invalid signature." }); } const fullFilePath = path.join(baseFilePath, filePath); res.download(fullFilePath); }; async function uploadFile(fileSystem, fileBytes, uploadPath, fileType = "pdf") { return new Promise((resolve, reject) => { let buffer; var currentFileBytes = fileBytes; if (typeof currentFileBytes !== "string" && Buffer.isBuffer(fileBytes)) { currentFileBytes = fileBytes.toString("base64"); } const matches = fileBytes.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/); if (matches && matches.length === 3) { buffer = Buffer.from(matches[2], "base64"); fileType = matches[1]; } else { buffer = Buffer.from(fileBytes, "base64"); } const file = fileSystem.file(uploadPath); const stream = file.createWriteStream({ metadata: { contentType : fileType.indexOf("/") !== -1 ? fileType : `application/${fileType}`, }, }); stream.on('error', (error) => reject(error)); stream.on('finish', async () => { await file.makePublic().catch(reject); const [url] = await file.getSignedUrl({ action : 'read', expires : '03-09-2491' }); resolve(url); }); stream.end(buffer); }); }; async function getFileDownloadUrl(fileSystem, filePath, urlExpiration = 60) { const file = fileSystem.file(filePath); const expires = Date.now() + urlExpiration * 60 * 1000; try { const [url] = await file.getSignedUrl({ action: "read", expires, }); console.log(`Generated signed URL: ${url}`); return url; } catch (error) { console.error("Did not generate signed URL: ", error); throw error; } }; function getSignedURL(filePath, secretKey, expiresIn = 60, domain = "https://your-domain.com", endpoint = "/download", userIP = "") { const expirationTime = Math.floor(Date.now() / 1000) + expiresIn; const dataToSign = `${filePath}:${expirationTime}:${userIP}`; const salt = crypto.randomBytes(16).toString("hex"); const signature = crypto.createHmac("sha256", secretKey).update(dataToSign + salt).digest("hex"); const signedURL = `${domain}${endpoint}?filePath=${encodeURIComponent(filePath)}&expires=${expirationTime}&signature=${signature}&salt=${salt}${userIP ? `&ip=${userIP}` : ''}`; return signedURL; }; async function getFileData(fileSystem, filePath) { const file = fileSystem.file(filePath); try { const buffer = await file.download(); console.log("File downloaded successfully."); return buffer[0]; } catch (error) { console.error("Did not download file: ", error); throw error; } }; async function getFile(fileSystem, filePath, req, ress, getType = "inline") { const file = fileSystem.file(filePath); try { const [metadata] = await file.getMetadata(); ress.setHeader("Content-Type", metadata.contentType || "application/octet-stream"); ress.setHeader("Content-Disposition", `${getType}; filename=\"` + encodeURIComponent(filePath.split("/").pop()) + '"'); const stream = file.createReadStream(); stream.on("error", (error) => { console.error("Did not stream the file: ", error); ress.status(327).json({ Message : "Did not download the file." }); }); stream.pipe(ress); } catch (error) { console.error("Did not fetch file metadata: ", error); ress.status(327).json({ Message : "Did not processing your request." }); } }; async function listAllFilesAndFolders(fileSystem) { try { const allFiles = await fileSystem.getFiles({ autoPaginate: true }); const files = allFiles[0]; const bucketStructure = {}; files.forEach(file => { const pathParts = file.name.split('/'); let currentLevel = bucketStructure; pathParts.forEach((part, index) => { if (index === pathParts.length - 1) { if (!currentLevel.files) currentLevel.files = []; currentLevel.files.push({ name: part, metadata: file.metadata }); } else { if (!currentLevel[part]) { currentLevel[part] = {}; } currentLevel = currentLevel[part]; } }); }); return bucketStructure; } catch (error) { return null; } } async function listFilesInFolder(fileSystem, folderPath) { try { const options = { prefix : folderPath, delimiter : "/" }; const response = await fileSystem.getFiles(options); const files = response[0] || []; const additionalResponseInfo = response[1] || {}; const fileMetadata = files.map(file => ({ name: file.name.replace(folderPath, ""), size: file.metadata.size, contentType: file.metadata.contentType, })); const mainFolderName = folderPath.split("/").filter(Boolean).pop() || folderPath; const subdirectoryNames = additionalResponseInfo.prefixes ? additionalResponseInfo.prefixes.map(prefix => { const cleanPrefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix; return cleanPrefix.split("/").pop(); }) : []; return { mainFolderName, subdirectoryNames, files : fileMetadata, }; } catch (error) { console.error("Did not list files in folder: ", error); return null; } }; async function deleteFolder(fileSystem, folderPath) { try { const [files] = await fileSystem.getFiles({ prefix: folderPath }); const deletePromises = files.map(file => file.delete()); await Promise.all(deletePromises); console.log(`Successfully deleted folder: ${folderPath.split("/")[0] ? folderPath.split("/")[0] : folderPath}.`); return true; } catch (error) { console.error("Error deleting folder contents: ", error); return false; } }; async function deleteFile(fileSystem, filePath) { try { await fileSystem.file(filePath).delete(); console.log(`File deleted from ${fileSystem.name}`); return true; } catch (error) { console.error("Did not delete file: ", error); return false; } }; // Map Functionality async function getAddressLocality(mapKey, address) { const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${mapKey}`; try { const fetch = (await import('node-fetch')).default; const response = await fetch(url); const localityData = await response.json(); if (localityData.status === 'OK') { const localityComponents = localityData.results[0].address_components; const country = localityComponents.find(c => c.types.includes('country'))?.long_name; const state = localityComponents.find(c => c.types.includes('administrative_area_level_1'))?.long_name; const county = localityComponents.find(c => c.types.includes('administrative_area_level_2'))?.long_name; const city = localityComponents.find(c => c.types.includes('locality'))?.long_name; return { country, state, county, city }; } return null; } catch (error) { console.error('Did not fetch locality components:', error); return null; } } async function getAddresses(mapKey, address) { const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(address)}&key=${mapKey}`; try { const fetch = (await import('node-fetch')).default; const response = await fetch(url); const data = await response.json(); if (data.status === 'OK') { return data.results.map(result => ({ formatted_address: result.formatted_address, address_components: result.address_components })); } return null; } catch (error) { console.error('Did not fetch addresses:', error); return null; } } module.exports = { outputPackageCreationTitle, outputPackageName, outputPackageLogo, outputPackageCredit, incrementVersion, ifNightTime, getDesiredData, addDesiredData, getAddressLocality, getAddresses, generateUTCDateDouble, generateDateToID, convertUTCDateToDateDisplay, convertNumberToMoneyFormat, convertNumberToWords, convertDateTime, convertSecondsToETATime, convertToVideoTime, convertDuration, convertToReadableDuration, convertFileSizeToDisplay, convertToSizeUnits, containsBlacklistedCharacters, cleanData, convertHexToRGB, generateLerp, generateColorInterpolation, generateGradientColors, outputMovingGradient, outputGradient, displayLegalDocumentCurrentDate, debounce, delay, checkForMatchingUniversalData, desiredInnerUniversalData, deepEqualData, uploadFile, deleteFolder, deleteFile, listAllFilesAndFolders, listFilesInFolder, getFileDownloadUrl, validateSignedURL, getSignedURL, getFileData, getFile, getUniversalMultiDataContainingDesiredData, getUniversalDataFromDocAttribute, getUniversalDataFromDoc, getUniversalMultiData, getUniversalData, getUniversalCollectionSize, getAvailableUniversalDocID, deleteUniversalDataField, deleteUniversalData, updateUniversalData, addUniversalData };