diff --git a/src/configuration.ts b/src/configuration.ts index 66a02bb1..8dc9803e 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -194,6 +194,13 @@ function parseKibibytesToBytes( return bytes; } +function parseRegExp( + environmentVariable: string, + defaultValue?: RegExp, +): RegExp | undefined { + return environmentVariable ? RegExp(environmentVariable) : defaultValue; +} + function safeHash(value: string | undefined): string | null { if (!value) { return null; @@ -325,6 +332,12 @@ const configuration = { resolveEnv("GAMES_SEARCH_RECURSIVE"), true, ), + SEARCH_EXCLUDE_FILE_REGEX: parseRegExp( + resolveEnv("GAMES_SEARCH_EXCLUDE_FILE_REGEX"), + ), + SEARCH_EXCLUDE_DIR_REGEX: parseRegExp( + resolveEnv("GAMES_SEARCH_EXCLUDE_DIR_REGEX"), + ), INDEX_CONCURRENCY: parseNumber(resolveEnv("GAMES_INDEX_CONCURRENCY"), 1), DEFAULT_ARCHIVE_PASSWORD: resolveEnv("GAMES_DEFAULT_ARCHIVE_PASSWORD") || "Anything", diff --git a/src/modules/games/files.service.ts b/src/modules/games/files.service.ts index 102a1eec..b13c5ef7 100644 --- a/src/modules/games/files.service.ts +++ b/src/modules/games/files.service.ts @@ -724,6 +724,34 @@ export class FilesService implements OnApplicationBootstrap { return checkedGames; } + /** Checks whether a given filename should be included by the indexer. */ + private shouldIncludeFile(filename: string): boolean { + const shouldExclude = + configuration.GAMES.SEARCH_EXCLUDE_FILE_REGEX?.test(filename); + if (shouldExclude) { + this.logger.debug({ + message: `Indexer ignoring filename due to exclusion settings.`, + reason: "Excluded by configuration.", + filename, + }); + } + return !shouldExclude && this.isValidFilePath(filename); + } + + /** Checks whether a given dirname should be included by the indexer. */ + private shouldIncludeDirectory(dirname: string): boolean { + const shouldExclude = + configuration.GAMES.SEARCH_EXCLUDE_DIR_REGEX?.test(dirname); + if (shouldExclude) { + this.logger.debug({ + message: `Indexer ignoring dirname due to exclusion settings.`, + reason: "Excluded by configuration.", + dirname, + }); + } + return !shouldExclude; + } + /** * This method retrieves an array of objects representing game files in the * file system. @@ -737,7 +765,8 @@ export class FilesService implements OnApplicationBootstrap { const stream = readdirp(configuration.VOLUMES.FILES, { type: "files", depth: configuration.GAMES.SEARCH_RECURSIVE ? undefined : 0, - fileFilter: (entry) => this.isValidFilePath(entry.basename), + fileFilter: (entry) => this.shouldIncludeFile(entry.basename), + directoryFilter: (entry) => this.shouldIncludeDirectory(entry.basename), alwaysStat: true, // ensure size is available for integrity checks });