/** * la classe qui repère des patterns */ import exifr from 'exifr' import moment from 'moment' import log from 'loglevel' import rangement_instance from '../conf/configs' log.setLevel(rangement_instance.log_level) interface fileDestructuration { fullPath: string folderPath: string fileNameOriginal: string dateStampInFileNameOriginal: string dateStampExif: string, freeText: string, tags: string[], extension: string, } /** * finds patterns for file name */ export default class finder { static statistics = { filesModified: 0, filesNotModified: 0, } static reportStatistics() { log.info('\n --------- statistics', this.statistics) } static findScreenshot(inputString: string) { return inputString.match(/screenshot/i) || inputString.match(/capture d'écran/i) } static findFormattedDate(filepath: string) { let match = filepath.match(/\d{4}-\d{2}-\d{2}T\d{2}\.\d{2}\.\d{2}/ig) log.debug(' finder - match findFormattedDate', match) let result = '' if (match && match[0]) { result = match[0] } return result } static findFileExtension(inputString: string): string { let result = inputString.match(/\.\w{3,4}$/i) if (result && result.length) { return result[0] } return '' } /** * find the section of file name which contains the free text to describe the picture * @param fileName * @returns {*|string} */ static findFileNameFreeTextPart(fileName: string) { fileName = fileName.replace(this.findFileExtension(fileName), '') let boom = fileName.split(rangement_instance.tagSectionSeparator) if (boom.length) { let freeTextPart = boom[0].trim() // remove date let foundDate = this.findFormattedDate(freeTextPart) if (foundDate) { freeTextPart = freeTextPart.replace(foundDate, '').trim() } log.debug(' finder - freeTextPart:', freeTextPart) return freeTextPart } return fileName.trim() } /** * find an array of tags * @param inputString * @returns {[]} */ static findTagSectionInString(inputString: string) { let listOfTags: Array = [] // remove extension let extensionFile = finder.findFileExtension(inputString) if (extensionFile) { inputString = inputString.replace(extensionFile, '') } else { log.debug(' finder - no extensionFile', extensionFile, inputString) extensionFile = '' } inputString = inputString.replace(extensionFile, '') log.debug(' finder - extensionFile', extensionFile) if (inputString.includes(rangement_instance.tagSectionSeparator)) { log.debug(' finder - inputString', inputString) if (inputString.length) { let boom = inputString.split(rangement_instance.tagSectionSeparator) log.debug(' finder - boom', boom) if (boom.length) { listOfTags = [...boom[1].trim().split(rangement_instance.tagSeparator)] log.debug(' finder - listOfTags', listOfTags) } else { log.debug(' finder - no boom', boom) } } } return listOfTags } static removeTagInProperties(properties: fileDestructuration, tagName: string) { let foundTagNameIndex = properties.tags.indexOf(tagName) if (foundTagNameIndex) { delete properties.tags[foundTagNameIndex] } return properties } static cleanSpaces(inputString: string) { return inputString.trim().replace(/ *g/, ' ').replace(/ /, ' ') } static searchAndReplaceInFileName(searchString: string, replaceString: string, fileName: string): string { return this.cleanSpaces(fileName.replace(searchString, replaceString)) } /** * search screenshot clues and rename */ static searchAndRenameScreenshots(fileName: string) { if (finder.findScreenshot(fileName)) { let tags = this.findTagSectionInString(fileName) log.debug(' finder - tags', tags) if (!tags.includes('screenshot')) { fileName = this.addTagInFileName('screenshot', fileName) fileName = this.searchAndReplaceInFileName('Screenshot', '', fileName) log.debug(' finder - screenShotMockFileName:', fileName) return this.cleanSpaces(fileName) } log.debug(' finder - is a screenshot, remove screenshot in name, and add tag screenshot') } else { return null } } /** * determines if we must add or remove new tags * @param tagCommand * @returns {{tagsToAdd: [], tagCommand: *, tagsToRemove: []}} */ static addOrRemoveTagsParsing(tagCommand: string): any { let tagsToAdd: Array = [] let tagsToRemove: Array = [] // split all tags let listOfTags = tagCommand.split(' ') listOfTags.forEach(elem => { // remove when a minus is present* if (elem.indexOf('-')) { tagsToRemove.push(elem) } else { // add tag otherwise tagsToAdd.push(elem) } }) return {tagCommand, tagsToAdd, tagsToRemove} } static applyTagChangesOnProperties(tagChange: any, properties: fileDestructuration) { properties.tags = [...properties.tags, tagChange.tagsToAdd] properties.tags.filter(elem => { return tagChange.tagsToRemove.includes(elem) }) return properties } /** * add a tag and gives new filename with extension * @param tagName * @param fileName * @returns {*} */ static addTagInFileName(tagName:string, fileName:string) { let tags:any = this.findTagSectionInString(fileName) let firstPart = this.findFileNameFreeTextPart(fileName) tags.push(tagName) // @ts-ignore let uniqueArray = [...new Set(tags)] let newFileName = firstPart + ' ' + rangement_instance.tagSectionSeparator + ' ' + uniqueArray.join(rangement_instance.tagSeparator) newFileName = newFileName.replace(/ {*}/, '') + this.findFileExtension(fileName) return this.cleanSpaces(newFileName) } /** * convertit un nom de fichier en une structure décrivant plusieurs parties correspondant au pattern d'archivage * @param fullPath * @returns {{extension: *, dateStamp: string, freeText: (*|string), tags: *[]}} */ static destructurateFileName(fullPath:string) { let [folderPath, fileNameOriginal] = this.findFolderPath(fullPath) let dateStampInFileNameOriginal = this.findFormattedDate(fileNameOriginal) return { fullPath, folderPath, fileNameOriginal, dateStampInFileNameOriginal, dateStampExif: '', freeText: this.findFileNameFreeTextPart(fileNameOriginal), tags: this.findTagSectionInString(fileNameOriginal), extension: this.findFileExtension(fileNameOriginal), } } /** * finds the earliest part in several exif date info * @param exifData * @returns {string} */ static findEarliestDateInExifData(exifData:any) { log.debug(' finder - findEarliestDateInExifData') if (exifData) { let moments = [] log.debug(' finder - exif data : ', exifData) // Do something with your data! if (exifData.DateTimeOriginal) { log.debug(' finder - image créée le : DateTimeOriginal : ', exifData.DateTimeOriginal) // Do something with your data! moments.push(exifData.DateTimeOriginal) } if (exifData.ModificationDateTime) { log.debug(' finder - image créée le : ModificationDateTime : ', exifData.ModificationDateTime) // Do something with your data! moments.push(exifData.ModificationDateTime) } if (exifData.ModifyDate) { log.debug(' finder - image créée le : ModifyDate : ', exifData.ModifyDate) // Do something with your data! moments.push(exifData.ModifyDate) } if (exifData.FileAccessDateTime) { moments.push(exifData.FileAccessDateTime) } if (exifData.FileInodeChangeDateTime) { moments.push(exifData.FileInodeChangeDateTime) } if (exifData.FileModificationDateTime) { log.debug(' finder - image créée le : FileModificationDateTime : ', exifData.FileModificationDateTime) // Do something with your data! moments.push(exifData.FileModificationDateTime) } if (exifData.CreateDate) { log.debug(' finder - image créée le : CreateDate : ', exifData.CreateDate) // Do something with your data! moments.push(exifData.CreateDate) } moments = moments.map(d => { let newdate = moment(d) return newdate }) let minDate = moment.min(moments) log.debug(' finder - minDate :::::::::', minDate) log.info(' finder - minDate :::::::::', minDate.format(rangement_instance.iso_date_format)) return minDate.format(rangement_instance.iso_date_format) } else { log.debug(' finder - /!\\ pas de exif data') return '' } } static appendFileName(fileProperties:fileDestructuration, newText:string) { fileProperties.freeText = finder.cleanSpaces(fileProperties.freeText + ' ' + newText) return fileProperties } static prependFileName(fileProperties:fileDestructuration, newText:string) { fileProperties.freeText = finder.cleanSpaces(newText + ' ' + fileProperties.freeText) return fileProperties } /** * examine plusieurs propriétés exif de date et retourne la plus ancienne * @param filepath */ static async findExifCreationDate(filepath:string) { log.debug(' finder - filepath', filepath) let dateAlreadyInFileName = finder.findFormattedDate(filepath) if (dateAlreadyInFileName) { log.debug(' finder - ------ dateAlreadyInFileName', dateAlreadyInFileName) } return await exifr.parse(filepath) } static findFolderPath(filePath:string) { let folders:any = filePath.split('/') let fileName:any = folders.pop() folders = filePath.replace(fileName, '') log.debug(' finder - \n - folders', folders) log.debug(' finder - - fileName', fileName, '\n') return [folders, fileName] } }