From 91a56e0ff7fea43fd99fe44bc0a328e7da34fabd Mon Sep 17 00:00:00 2001 From: xtrullor73 Date: Mon, 27 May 2024 16:06:51 -0700 Subject: [PATCH] fix(validation): prevent overwriting files with same artist and title by generating unique filenames - Implement generateUniqueFilename to ensure each file is saved with a unique name These changes address the issue when two or more different songs by the same artist and with the same title overwrite each other --- src/utils/generateUniqueFileName.js | 28 ++++++++++++++++++++++++++++ src/utils/renameAudioFileTitle.js | 9 ++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 src/utils/generateUniqueFileName.js diff --git a/src/utils/generateUniqueFileName.js b/src/utils/generateUniqueFileName.js new file mode 100644 index 0000000..d0d1cf0 --- /dev/null +++ b/src/utils/generateUniqueFileName.js @@ -0,0 +1,28 @@ +import fs from 'fs/promises'; +import path from 'path'; + +/** + * Generates a unique filename based on the original filename, ensuring it doesn't overwrite existing files. + * @param {string} directory - The directory to save the downloaded image. + * @param {string} filename - The original filename. + * @returns {Promise} - A promise that resolves to a unique filename. + */ +const generateUniqueFilename = async (directory, filename) => { + const extension = path.extname(filename); + const basename = path.basename(filename, extension); + let counter = 1; + + let uniqueFilename = filename; + let filePath = path.join(directory, uniqueFilename); + + // Check if the file exists and append a counter to make it unique + while (await fs.stat(filePath).catch(() => false)) { + uniqueFilename = `${basename} (${counter})${extension}`; + filePath = path.join(directory, uniqueFilename); + counter += 1; + } + + return filePath; +}; + +export default generateUniqueFilename; diff --git a/src/utils/renameAudioFileTitle.js b/src/utils/renameAudioFileTitle.js index 5663042..7325a8b 100644 --- a/src/utils/renameAudioFileTitle.js +++ b/src/utils/renameAudioFileTitle.js @@ -1,5 +1,6 @@ import path from 'path'; import fs from 'fs/promises'; +import generateUniqueFilename from '../utils/generateUniqueFilename.js'; /** * Renames an audio file by its metadata properties: artist and title. @@ -13,13 +14,15 @@ import fs from 'fs/promises'; export default async function renameFile(artist, title, filePath) { // Ensure file path, artist, and title are provided if (!filePath || !artist || !title) { - throw new Error('File path, artist, and title must be provided.'); + throw new Error('File path, artist, and title must be provided when renaming file.'); } const ext = path.extname(filePath); const dir = path.dirname(filePath); - const newFileName = `${artist} - ${title}${ext}`; - const newFilePath = path.join(dir, newFileName); + const proposedFileName = `${artist} - ${title}${ext}`; + + // Generate a unique filename to avoid overwriting + const newFilePath = await generateUniqueFilename(dir, proposedFileName); try { await fs.rename(filePath, newFilePath);