rangement/utils/finder.ts

322 lines
11 KiB
TypeScript

/**
* 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<string> = []
// 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<any> = []
let tagsToRemove: Array<any> = []
// 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]
}
}