diff --git a/.vscode/launch.json b/.vscode/launch.json index 69228d9..5eb672a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,7 +1,4 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { @@ -19,7 +16,14 @@ "id": "command", "type": "pickString", "description": "Which command do you want to run?", - "options": ["smart", "relocate", "import-ext", "help"], + "options": [ + // + "import-ext", + "relocate", + "smart", + "strip-accents", + "help" + ], "default": "smart" } ] diff --git a/src/commands/strip-accents.ts b/src/commands/strip-accents.ts new file mode 100644 index 0000000..bf49925 --- /dev/null +++ b/src/commands/strip-accents.ts @@ -0,0 +1,106 @@ +import chalk from 'chalk'; +import pluralize from 'pluralize'; + +import { BaseEngineCommand } from '../base-commands'; +import * as engine from '../engine'; +import { isLicensed } from '../licensing'; +import { spinner } from '../utils'; + +export default class StripAccents extends BaseEngineCommand { + async run() { + if (!this.checkLicense()) { + return; + } + + this.warnBlock( + `This will NOT update tags in your files. It will only update tags in the Engine DB.`, + ); + + await this.connectToEngine(); + + const accentedTracks = await spinner({ + text: 'Find accented tracks', + run: async ctx => { + const accented = await this.findTracksWithAccents(); + const length = accented.length; + + const msgSuffix = `${pluralize( + 'track', + length, + )} with accents in their filename or tags`; + + if (length) { + ctx.succeed(chalk`Found {yellow ${length.toString()}} ${msgSuffix}`); + } else { + ctx.warn(`Didn't find any ${msgSuffix}`); + } + + return accented; + }, + }); + this.logTracks(accentedTracks); + } + + private checkLicense(): boolean { + if (!isLicensed()) { + this.warnBlock( + chalk`The {cyan ${StripAccents.id}} command isn't included in the free version.`, + ); + return false; + } + + return true; + } + + private async findTracksWithAccents(): Promise { + const tracks = await this.engineDb.getTracks(); + + return tracks.filter(track => + ACCENTS_REGEX.test( + [ + track.album, + track.artist, + track.comment, + track.composer, + track.filename, + track.genre, + track.label, + track.remixer, + track.title, + ].join(''), + ), + ); + } +} + +// spell-checker: disable +const ACCENT_MAP = { + ÀÁÂÃÄÅ: 'A', + àáâãäå: 'a', + ÈÉÊË: 'E', + èéêë: 'e', + ÌÍÎÏ: 'I', + ìíîï: 'i', + ÒÓÔÕÖØ: 'O', + òóôõöø: 'o', + ÙÚÛÜ: 'U', + ùúûüµ: 'u', + Ææ: 'AE', + Œœ: 'OE', + Ðð: 'DH', + Þþ: 'TH', + Çç: 'C', + ß: 'S', + '¢£€¤¥': '$', + '©': '©', + '«»': '"', + // '·': '.', + '¡': '!', + '¿': '?', + '×': '*', + '÷': '/', +} as const; +// spell-checker: enable + +const ALL_ACCENTS = Object.keys(ACCENT_MAP).join(''); +const ACCENTS_REGEX = new RegExp(`[${ALL_ACCENTS}]`); diff --git a/webpack.config.js b/webpack.config.js index b8f9356..e325bce 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -35,6 +35,7 @@ module.exports = { ...commandEntry('import-ext'), ...commandEntry('relocate'), ...commandEntry('smart'), + ...commandEntry('strip-accents'), ...hookEntry('init', 'conf'), ...hookEntry('prerun', 'engine-library'), },