From 4de707f29eb7aba9c062fa84d4bad884a3d094f6 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Tue, 4 Mar 2025 23:01:44 +0100 Subject: [PATCH 01/19] Restored and updated api toggle The settings screen where you can toggle each API per media type is now fully automatic and works for each media type that has more than 1 API. --- src/api/APIModel.ts | 14 +- src/settings/Settings.ts | 1085 +++++++++++++++++++------------------- 2 files changed, 540 insertions(+), 559 deletions(-) diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index d23f2a5..ecd2f43 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -19,13 +19,13 @@ export abstract class APIModel { abstract getById(id: string): Promise; hasType(type: MediaType): boolean { - // if ( - // this.types.contains(type) && - // (Boolean((this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type]) === true || (this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type] === undefined) - // ) { - // return true; - // } - return this.types.contains(type); + if ( + this.types.contains(type) && + (Boolean((this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type]) === true || (this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type] === undefined) + ) { + return true; + } + return false; } hasTypeOverlap(types: MediaType[]): boolean { diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index f880a35..3601efc 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -4,7 +4,7 @@ import { mount } from 'svelte'; import type MediaDbPlugin from '../main'; import type { MediaTypeModel } from '../models/MediaTypeModel'; import { MEDIA_TYPES } from '../utils/MediaTypeManager'; -import { fragWithHTML } from '../utils/Utils'; +import { fragWithHTML, unCamelCase } from '../utils/Utils'; import { PropertyMapping, PropertyMappingModel, PropertyMappingOption } from './PropertyMapping'; import PropertyMappingModelsComponent from './PropertyMappingModelsComponent.svelte'; import { FileSuggest } from './suggesters/FileSuggest'; @@ -21,24 +21,35 @@ export interface MediaDbPluginSettings { openNoteInNewTab: boolean; useDefaultFrontMatter: boolean; enableTemplaterIntegration: boolean; - // TODO: disabled for now, as i currently don't have the time to fix this from the original PR that introduced it (#133) - // apiToggle: { - // OMDbAPI: { - // movie: boolean; - // series: boolean; - // game: boolean; - // }; - // MALAPI: { - // movie: boolean; - // series: boolean; - // }; - // SteamAPI: { - // game: boolean; - // }; - // MobyGamesAPI: { - // game: boolean; - // }; - // }; + apiToggle: { + OMDbAPI: { + movie: boolean; + series: boolean; + game: boolean; + }; + MALAPI: { + movie: boolean; + series: boolean; + }; + MALAPIManga: { + comicManga: boolean; + }; + ComicVineAPI: { + comicManga: boolean; + }; + SteamAPI: { + game: boolean; + }; + MobyGamesAPI: { + game: boolean; + }; + GiantBombAPI: { + game: boolean; + }; + VNDBAPI: { + game: boolean; + }; + }; movieTemplate: string; seriesTemplate: string; mangaTemplate: string; @@ -89,23 +100,35 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { openNoteInNewTab: true, useDefaultFrontMatter: true, enableTemplaterIntegration: false, - // apiToggle: { - // OMDbAPI: { - // movie: true, - // series: true, - // game: true, - // }, - // MALAPI: { - // movie: true, - // series: true, - // }, - // SteamAPI: { - // game: true, - // }, - // MobyGamesAPI: { - // game: true, - // }, - // }, + apiToggle: { + OMDbAPI: { + movie: true, + series: true, + game: true, + }, + MALAPI: { + movie: true, + series: true, + }, + MALAPIManga: { + comicManga: true + }, + ComicVineAPI: { + comicManga: true + }, + SteamAPI: { + game: true, + }, + MobyGamesAPI: { + game: true, + }, + GiantBombAPI: { + game: true, + }, + VNDBAPI: { + game: true, + }, + }, movieTemplate: '', seriesTemplate: '', mangaTemplate: '', @@ -172,541 +195,499 @@ export function getDefaultSettings(plugin: MediaDbPlugin): MediaDbPluginSettings } export class MediaDbSettingTab extends PluginSettingTab { - plugin: MediaDbPlugin; + plugin: MediaDbPlugin; - constructor(app: App, plugin: MediaDbPlugin) { - super(app, plugin); - this.plugin = plugin; - } + constructor(app: App, plugin: MediaDbPlugin) { + super(app, plugin); + this.plugin = plugin; + } - display(): void { - const { containerEl } = this; + display(): void { + const { containerEl } = this; - containerEl.empty(); + containerEl.empty(); - new Setting(containerEl) - .setName('OMDb API key') - .setDesc('API key for "www.omdbapi.com".') + new Setting(containerEl) + .setName('OMDb API key') + .setDesc('API key for "www.omdbapi.com".') .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.OMDbKey) - .onChange(data => { - this.plugin.settings.OMDbKey = data; - void this.plugin.saveSettings(); - }); - }); + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.OMDbKey) + .onChange(data => { + this.plugin.settings.OMDbKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Moby Games key') - .setDesc('API key for "www.mobygames.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.MobyGamesKey) - .onChange(data => { - this.plugin.settings.MobyGamesKey = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Moby Games key') + .setDesc('API key for "www.mobygames.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.MobyGamesKey) + .onChange(data => { + this.plugin.settings.MobyGamesKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Giant Bomb Key') - .setDesc('API key for "www.giantbomb.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.GiantBombKey) - .onChange(data => { - this.plugin.settings.GiantBombKey = data; - void this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) - .setName('Comic Vine Key') - .setDesc('API key for "www.comicvine.gamespot.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.ComicVineKey) - .onChange(data => { - this.plugin.settings.ComicVineKey = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Giant Bomb Key') + .setDesc('API key for "www.giantbomb.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.GiantBombKey) + .onChange(data => { + this.plugin.settings.GiantBombKey = data; + void this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) + .setName('Comic Vine Key') + .setDesc('API key for "www.comicvine.gamespot.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.ComicVineKey) + .onChange(data => { + this.plugin.settings.ComicVineKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('SFW filter') - .setDesc('Only shows SFW results for APIs that offer filtering.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.sfwFilter).onChange(data => { - this.plugin.settings.sfwFilter = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('SFW filter') + .setDesc('Only shows SFW results for APIs that offer filtering.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.sfwFilter).onChange(data => { + this.plugin.settings.sfwFilter = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Resolve {{ tags }} in templates') - .setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.templates).onChange(data => { - this.plugin.settings.templates = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Resolve {{ tags }} in templates') + .setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.templates).onChange(data => { + this.plugin.settings.templates = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Date format') - .setDesc( - fragWithHTML( - "Your custom date format. Use 'YYYY-MM-DD' for example.
" + - "For more syntax, refer to format reference.
" + - "Your current syntax looks like this: " + - this.plugin.dateFormatter.getPreview() + - '', - ), - ) - .addText(cb => { - cb.setPlaceholder(DEFAULT_SETTINGS.customDateFormat) - .setValue(this.plugin.settings.customDateFormat === DEFAULT_SETTINGS.customDateFormat ? '' : this.plugin.settings.customDateFormat) - .onChange(data => { - const newDateFormat = data ? data : DEFAULT_SETTINGS.customDateFormat; - this.plugin.settings.customDateFormat = newDateFormat; - const previewEl = document.getElementById('media-db-dateformat-preview'); - if (previewEl) { - previewEl.textContent = this.plugin.dateFormatter.getPreview(newDateFormat); // update preview - } - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Date format') + .setDesc( + fragWithHTML( + "Your custom date format. Use 'YYYY-MM-DD' for example.
" + + "For more syntax, refer to format reference.
" + + "Your current syntax looks like this: " + + this.plugin.dateFormatter.getPreview() + + '', + ), + ) + .addText(cb => { + cb.setPlaceholder(DEFAULT_SETTINGS.customDateFormat) + .setValue(this.plugin.settings.customDateFormat === DEFAULT_SETTINGS.customDateFormat ? '' : this.plugin.settings.customDateFormat) + .onChange(data => { + const newDateFormat = data ? data : DEFAULT_SETTINGS.customDateFormat; + this.plugin.settings.customDateFormat = newDateFormat; + const previewEl = document.getElementById('media-db-dateformat-preview'); + if (previewEl) { + previewEl.textContent = this.plugin.dateFormatter.getPreview(newDateFormat); // update preview + } + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Open note in new tab') - .setDesc('Open the newly created note in a new tab.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.openNoteInNewTab).onChange(data => { - this.plugin.settings.openNoteInNewTab = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Open note in new tab') + .setDesc('Open the newly created note in a new tab.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.openNoteInNewTab).onChange(data => { + this.plugin.settings.openNoteInNewTab = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Use default front matter') - .setDesc('Whether to use the default front matter. If disabled, the front matter from the template will be used. Same as mapping everything to remove.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.useDefaultFrontMatter).onChange(data => { - this.plugin.settings.useDefaultFrontMatter = data; - void this.plugin.saveSettings(); - // Redraw settings to display/remove the property mappings - this.display(); - }); - }); + new Setting(containerEl) + .setName('Use default front matter') + .setDesc('Whether to use the default front matter. If disabled, the front matter from the template will be used. Same as mapping everything to remove.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.useDefaultFrontMatter).onChange(data => { + this.plugin.settings.useDefaultFrontMatter = data; + void this.plugin.saveSettings(); + // Redraw settings to display/remove the property mappings + this.display(); + }); + }); - new Setting(containerEl) - .setName('Enable Templater integration') - .setDesc( - 'Enable integration with the templater plugin, this also needs templater to be installed. Warning: Templater allows you to execute arbitrary JavaScript code and system commands.', - ) - .addToggle(cb => { - cb.setValue(this.plugin.settings.enableTemplaterIntegration).onChange(data => { - this.plugin.settings.enableTemplaterIntegration = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Enable Templater integration') + .setDesc( + 'Enable integration with the templater plugin, this also needs templater to be installed. Warning: Templater allows you to execute arbitrary JavaScript code and system commands.', + ) + .addToggle(cb => { + cb.setValue(this.plugin.settings.enableTemplaterIntegration).onChange(data => { + this.plugin.settings.enableTemplaterIntegration = data; + void this.plugin.saveSettings(); + }); + }); - // containerEl.createEl('h3', { text: 'APIs per media type' }); - // containerEl.createEl('h5', { text: 'Movies' }); - // new Setting(containerEl) - // .setName('OMDb API') - // .setDesc('Use OMDb API for movies.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.OMDbAPI.movie).onChange(data => { - // this.plugin.settings.apiToggle.OMDbAPI.movie = data; - // void this.plugin.saveSettings(); - // }); - // }); - // new Setting(containerEl) - // .setName('MAL API') - // .setDesc('Use MAL API for movies.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.MALAPI.movie).onChange(data => { - // this.plugin.settings.apiToggle.MALAPI.movie = data; - // void this.plugin.saveSettings(); - // }); - // }); - // containerEl.createEl('h5', { text: 'Series' }); - // new Setting(containerEl) - // .setName('OMDb API') - // .setDesc('Use OMDb API for series.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.OMDbAPI.series).onChange(data => { - // this.plugin.settings.apiToggle.OMDbAPI.series = data; - // void this.plugin.saveSettings(); - // }); - // }); - // new Setting(containerEl) - // .setName('MAL API') - // .setDesc('Use MAL API for series.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.MALAPI.series).onChange(data => { - // this.plugin.settings.apiToggle.MALAPI.series = data; - // void this.plugin.saveSettings(); - // }); - // }); - // containerEl.createEl('h5', { text: 'Games' }); - // new Setting(containerEl) - // .setName('OMDb API') - // .setDesc('Use OMDb API for games.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.OMDbAPI.game).onChange(data => { - // this.plugin.settings.apiToggle.OMDbAPI.game = data; - // void this.plugin.saveSettings(); - // }); - // }); - // new Setting(containerEl) - // .setName('Steam API') - // .setDesc('Use OMDb API for games.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.SteamAPI.game).onChange(data => { - // this.plugin.settings.apiToggle.SteamAPI.game = data; - // void this.plugin.saveSettings(); - // }); - // }); - // new Setting(containerEl) - // .setName('MobyGames API') - // .setDesc('Use MobyGames API for games.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.MobyGamesAPI.game).onChange(data => { - // this.plugin.settings.apiToggle.MobyGamesAPI.game = data; - // void this.plugin.saveSettings(); - // }); - // }); - // new Setting(containerEl) - // .setName('Giantbomb API') - // .setDesc('Use Giantbomb API for games.') - // .addToggle(cb => { - // cb.setValue(this.plugin.settings.apiToggle.GiantBombAPI.game).onChange(data => { - // this.plugin.settings.apiToggle.GiantBombAPI.game = data; - // void this.plugin.saveSettings(); - // }); - // }); - new Setting(containerEl).setName('New file location').setHeading(); - // region new file location - new Setting(containerEl) - .setName('Movie folder') - .setDesc('Where newly imported movies should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.movieFolder) - .setValue(this.plugin.settings.movieFolder) - .onChange(data => { - this.plugin.settings.movieFolder = data; - void this.plugin.saveSettings(); - }); - }); + // Create a map to store APIs for each media type + const mediaTypeApiMap = new Map(); - new Setting(containerEl) - .setName('Series folder') - .setDesc('Where newly imported series should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.seriesFolder) - .setValue(this.plugin.settings.seriesFolder) - .onChange(data => { - this.plugin.settings.seriesFolder = data; - void this.plugin.saveSettings(); - }); - }); + // Populate the map with APIs for each media type + Object.entries(this.plugin.settings.apiToggle).forEach(([apiName, api]) => { + Object.entries(api).forEach(([mediaType]) => { + if (!mediaTypeApiMap.has(mediaType)) { + mediaTypeApiMap.set(mediaType, []); + } + mediaTypeApiMap.get(mediaType)!.push(apiName); + }); + }); - new Setting(containerEl) - .setName('Comic and manga folder') - .setDesc('Where newly imported comics and manga should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.mangaFolder) - .setValue(this.plugin.settings.mangaFolder) - .onChange(data => { - this.plugin.settings.mangaFolder = data; - void this.plugin.saveSettings(); - }); - }); + // Filter out media types with only one API + const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); - new Setting(containerEl) - .setName('Game folder') - .setDesc('Where newly imported games should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.gameFolder) - .setValue(this.plugin.settings.gameFolder) - .onChange(data => { - this.plugin.settings.gameFolder = data; - void this.plugin.saveSettings(); - }); - }); + // Dynamically create settings based on the filtered media types and their APIs + filteredMediaTypes.forEach(([mediaType, apis]) => { + new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); + apis.forEach(apiName => { + const apiToggle = this.plugin.settings.apiToggle[apiName as keyof typeof this.plugin.settings.apiToggle]; + new Setting(containerEl) + .setName(apiName) + .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) + .addToggle(cb => { + cb.setValue((apiToggle as Record)[mediaType]) + .onChange(data => { + (apiToggle as Record)[mediaType] = data; + void this.plugin.saveSettings(); + }); + }); + }); + }); - new Setting(containerEl) - .setName('Wiki folder') - .setDesc('Where newly imported wiki articles should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.wikiFolder) - .setValue(this.plugin.settings.wikiFolder) - .onChange(data => { - this.plugin.settings.wikiFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('New file location').setHeading(); + // region new file location + new Setting(containerEl) + .setName('Movie folder') + .setDesc('Where newly imported movies should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.movieFolder) + .setValue(this.plugin.settings.movieFolder) + .onChange(data => { + this.plugin.settings.movieFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music folder') - .setDesc('Where newly imported music should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.musicReleaseFolder) - .setValue(this.plugin.settings.musicReleaseFolder) - .onChange(data => { - this.plugin.settings.musicReleaseFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series folder') + .setDesc('Where newly imported series should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.seriesFolder) + .setValue(this.plugin.settings.seriesFolder) + .onChange(data => { + this.plugin.settings.seriesFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game folder') - .setDesc('Where newly imported board games should be places.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.boardgameFolder) - .setValue(this.plugin.settings.boardgameFolder) - .onChange(data => { - this.plugin.settings.boardgameFolder = data; - void this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) - .setName('Book folder') - .setDesc('Where newly imported books should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.bookFolder) - .setValue(this.plugin.settings.bookFolder) - .onChange(data => { - this.plugin.settings.bookFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Comic and manga folder') + .setDesc('Where newly imported comics and manga should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.mangaFolder) + .setValue(this.plugin.settings.mangaFolder) + .onChange(data => { + this.plugin.settings.mangaFolder = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + new Setting(containerEl) + .setName('Game folder') + .setDesc('Where newly imported games should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.gameFolder) + .setValue(this.plugin.settings.gameFolder) + .onChange(data => { + this.plugin.settings.gameFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl).setName('Template settings').setHeading(); - // region templates - new Setting(containerEl) - .setName('Movie template') - .setDesc('Template file to be used when creating a new note for a movie.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: movieTemplate.md') - .setValue(this.plugin.settings.movieTemplate) - .onChange(data => { - this.plugin.settings.movieTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Wiki folder') + .setDesc('Where newly imported wiki articles should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.wikiFolder) + .setValue(this.plugin.settings.wikiFolder) + .onChange(data => { + this.plugin.settings.wikiFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Series template') - .setDesc('Template file to be used when creating a new note for a series.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: seriesTemplate.md') - .setValue(this.plugin.settings.seriesTemplate) - .onChange(data => { - this.plugin.settings.seriesTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Music folder') + .setDesc('Where newly imported music should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.musicReleaseFolder) + .setValue(this.plugin.settings.musicReleaseFolder) + .onChange(data => { + this.plugin.settings.musicReleaseFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Manga and Comics template') - .setDesc('Template file to be used when creating a new note for a manga or a comic.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: mangaTemplate.md') - .setValue(this.plugin.settings.mangaTemplate) - .onChange(data => { - this.plugin.settings.mangaTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Board game folder') + .setDesc('Where newly imported board games should be places.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.boardgameFolder) + .setValue(this.plugin.settings.boardgameFolder) + .onChange(data => { + this.plugin.settings.boardgameFolder = data; + void this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) + .setName('Book folder') + .setDesc('Where newly imported books should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.bookFolder) + .setValue(this.plugin.settings.bookFolder) + .onChange(data => { + this.plugin.settings.bookFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Game template') - .setDesc('Template file to be used when creating a new note for a game.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: gameTemplate.md') - .setValue(this.plugin.settings.gameTemplate) - .onChange(data => { - this.plugin.settings.gameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + // endregion - new Setting(containerEl) - .setName('Wiki template') - .setDesc('Template file to be used when creating a new note for a wiki entry.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: wikiTemplate.md') - .setValue(this.plugin.settings.wikiTemplate) - .onChange(data => { - this.plugin.settings.wikiTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('Template settings').setHeading(); + // region templates + new Setting(containerEl) + .setName('Movie template') + .setDesc('Template file to be used when creating a new note for a movie.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: movieTemplate.md') + .setValue(this.plugin.settings.movieTemplate) + .onChange(data => { + this.plugin.settings.movieTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music release template') - .setDesc('Template file to be used when creating a new note for a music release.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: musicReleaseTemplate.md') - .setValue(this.plugin.settings.musicReleaseTemplate) - .onChange(data => { - this.plugin.settings.musicReleaseTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series template') + .setDesc('Template file to be used when creating a new note for a series.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: seriesTemplate.md') + .setValue(this.plugin.settings.seriesTemplate) + .onChange(data => { + this.plugin.settings.seriesTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game template') - .setDesc('Template file to be used when creating a new note for a boardgame.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: boardgameTemplate.md') - .setValue(this.plugin.settings.boardgameTemplate) - .onChange(data => { - this.plugin.settings.boardgameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Manga and Comics template') + .setDesc('Template file to be used when creating a new note for a manga or a comic.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: mangaTemplate.md') + .setValue(this.plugin.settings.mangaTemplate) + .onChange(data => { + this.plugin.settings.mangaTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Book template') - .setDesc('Template file to be used when creating a new note for a book.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: bookTemplate.md') - .setValue(this.plugin.settings.bookTemplate) - .onChange(data => { - this.plugin.settings.bookTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Game template') + .setDesc('Template file to be used when creating a new note for a game.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: gameTemplate.md') + .setValue(this.plugin.settings.gameTemplate) + .onChange(data => { + this.plugin.settings.gameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + new Setting(containerEl) + .setName('Wiki template') + .setDesc('Template file to be used when creating a new note for a wiki entry.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: wikiTemplate.md') + .setValue(this.plugin.settings.wikiTemplate) + .onChange(data => { + this.plugin.settings.wikiTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl).setName('File name settings').setHeading(); - // region file name templates - new Setting(containerEl) - .setName('Movie file name template') - .setDesc('Template for the file name used when creating a new note for a movie.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) - .setValue(this.plugin.settings.movieFileNameTemplate) - .onChange(data => { - this.plugin.settings.movieFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Music release template') + .setDesc('Template file to be used when creating a new note for a music release.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: musicReleaseTemplate.md') + .setValue(this.plugin.settings.musicReleaseTemplate) + .onChange(data => { + this.plugin.settings.musicReleaseTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Series file name template') - .setDesc('Template for the file name used when creating a new note for a series.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) - .setValue(this.plugin.settings.seriesFileNameTemplate) - .onChange(data => { - this.plugin.settings.seriesFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Board game template') + .setDesc('Template file to be used when creating a new note for a boardgame.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: boardgameTemplate.md') + .setValue(this.plugin.settings.boardgameTemplate) + .onChange(data => { + this.plugin.settings.boardgameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Manga and comic file name template') - .setDesc('Template for the file name used when creating a new note for a manga or comic.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.mangaFileNameTemplate}`) - .setValue(this.plugin.settings.mangaFileNameTemplate) - .onChange(data => { - this.plugin.settings.mangaFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Book template') + .setDesc('Template file to be used when creating a new note for a book.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: bookTemplate.md') + .setValue(this.plugin.settings.bookTemplate) + .onChange(data => { + this.plugin.settings.bookTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Game file name template') - .setDesc('Template for the file name used when creating a new note for a game.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) - .setValue(this.plugin.settings.gameFileNameTemplate) - .onChange(data => { - this.plugin.settings.gameFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + // endregion - new Setting(containerEl) - .setName('Wiki file name template') - .setDesc('Template for the file name used when creating a new note for a wiki entry.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) - .setValue(this.plugin.settings.wikiFileNameTemplate) - .onChange(data => { - this.plugin.settings.wikiFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('File name settings').setHeading(); + // region file name templates + new Setting(containerEl) + .setName('Movie file name template') + .setDesc('Template for the file name used when creating a new note for a movie.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) + .setValue(this.plugin.settings.movieFileNameTemplate) + .onChange(data => { + this.plugin.settings.movieFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music release file name template') - .setDesc('Template for the file name used when creating a new note for a music release.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) - .setValue(this.plugin.settings.musicReleaseFileNameTemplate) - .onChange(data => { - this.plugin.settings.musicReleaseFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series file name template') + .setDesc('Template for the file name used when creating a new note for a series.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) + .setValue(this.plugin.settings.seriesFileNameTemplate) + .onChange(data => { + this.plugin.settings.seriesFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game file name template') - .setDesc('Template for the file name used when creating a new note for a boardgame.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.boardgameFileNameTemplate}`) - .setValue(this.plugin.settings.boardgameFileNameTemplate) - .onChange(data => { - this.plugin.settings.boardgameFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Manga and comic file name template') + .setDesc('Template for the file name used when creating a new note for a manga or comic.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.mangaFileNameTemplate}`) + .setValue(this.plugin.settings.mangaFileNameTemplate) + .onChange(data => { + this.plugin.settings.mangaFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Book file name template') - .setDesc('Template for the file name used when creating a new note for a book.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.bookFileNameTemplate}`) - .setValue(this.plugin.settings.bookFileNameTemplate) - .onChange(data => { - this.plugin.settings.bookFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Game file name template') + .setDesc('Template for the file name used when creating a new note for a game.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) + .setValue(this.plugin.settings.gameFileNameTemplate) + .onChange(data => { + this.plugin.settings.gameFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + new Setting(containerEl) + .setName('Wiki file name template') + .setDesc('Template for the file name used when creating a new note for a wiki entry.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) + .setValue(this.plugin.settings.wikiFileNameTemplate) + .onChange(data => { + this.plugin.settings.wikiFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - // region Property Mappings - if (this.plugin.settings.useDefaultFrontMatter) { - new Setting(containerEl).setName('Property mappings').setHeading(); + new Setting(containerEl) + .setName('Music release file name template') + .setDesc('Template for the file name used when creating a new note for a music release.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) + .setValue(this.plugin.settings.musicReleaseFileNameTemplate) + .onChange(data => { + this.plugin.settings.musicReleaseFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - const propertyMappingExplanation = containerEl.createEl('div'); - propertyMappingExplanation.innerHTML = ` + new Setting(containerEl) + .setName('Board game file name template') + .setDesc('Template for the file name used when creating a new note for a boardgame.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.boardgameFileNameTemplate}`) + .setValue(this.plugin.settings.boardgameFileNameTemplate) + .onChange(data => { + this.plugin.settings.boardgameFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Book file name template') + .setDesc('Template for the file name used when creating a new note for a book.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.bookFileNameTemplate}`) + .setValue(this.plugin.settings.bookFileNameTemplate) + .onChange(data => { + this.plugin.settings.bookFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); + + // endregion + + // region Property Mappings + if (this.plugin.settings.useDefaultFrontMatter) { + new Setting(containerEl).setName('Property mappings').setHeading(); + + const propertyMappingExplanation = containerEl.createEl('div'); + propertyMappingExplanation.innerHTML = `

Choose how metadata fields are mapped to property names. The options are:

  • default: keep the original name.
  • @@ -717,29 +698,29 @@ export class MediaDbSettingTab extends PluginSettingTab { Don't forget to save your changes using the save button for each individual category.

    `; - mount(PropertyMappingModelsComponent, { - target: this.containerEl, - props: { - models: this.plugin.settings.propertyMappingModels.map(x => x.copy()), - save: (model: PropertyMappingModel): void => { - const propertyMappingModels: PropertyMappingModel[] = []; + mount(PropertyMappingModelsComponent, { + target: this.containerEl, + props: { + models: this.plugin.settings.propertyMappingModels.map(x => x.copy()), + save: (model: PropertyMappingModel): void => { + const propertyMappingModels: PropertyMappingModel[] = []; - for (const model2 of this.plugin.settings.propertyMappingModels) { - if (model2.type === model.type) { - propertyMappingModels.push(model); - } else { - propertyMappingModels.push(model2); - } - } + for (const model2 of this.plugin.settings.propertyMappingModels) { + if (model2.type === model.type) { + propertyMappingModels.push(model); + } else { + propertyMappingModels.push(model2); + } + } - this.plugin.settings.propertyMappingModels = propertyMappingModels; - new Notice(`MDB: Property mappings for ${model.type} saved successfully.`); - void this.plugin.saveSettings(); - }, - }, - }); - } + this.plugin.settings.propertyMappingModels = propertyMappingModels; + new Notice(`MDB: Property mappings for ${model.type} saved successfully.`); + void this.plugin.saveSettings(); + }, + }, + }); + } - // endregion - } + // endregion + } } From 57b0532be8ef3f3eb7bc872e2b1468e134179777 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Tue, 4 Mar 2025 23:04:32 +0100 Subject: [PATCH 02/19] Ran prettier --- README.md | 3 +- src/settings/Settings.ts | 943 +++++++++++++++++++-------------------- 2 files changed, 472 insertions(+), 474 deletions(-) diff --git a/README.md b/README.md index 5ad2f49..e4c8805 100644 --- a/README.md +++ b/README.md @@ -113,7 +113,6 @@ Now you select the result you want and the plugin will cast it's magic and creat ### Currently supported APIs: - | Name | Description | Supported formats | Authentification | Rate limiting | SFW filter support | | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | | [Jikan](https://jikan.moe/) | Jikan is an API that uses [My Anime List](https://myanimelist.net) and offers metadata for anime. | series, movies, specials, OVAs, manga, manwha, novels | No | 60 per minute and 3 per second | Yes | @@ -124,7 +123,7 @@ Now you select the result you want and the plugin will cast it's magic and creat | [Open Library](https://openlibrary.org) | The OpenLibrary API offers metadata for books | books | No | Cover access is rate-limited when not using CoverID or OLID by max 100 requests/IP every 5 minutes. This plugin uses OLID so there shouldn't be a rate limit. | No | | [Moby Games](https://www.mobygames.com) | The Moby Games API offers metadata for games for all platforms | games | Yes, by making an account [here](https://www.mobygames.com/user/register/). NOTE: As of September 2024 the API key is no longer free so consider using Giant Bomb or steam instead | API requests are limited to 360 per hour (one every ten seconds). In addition, requests should be made no more frequently than one per second. | No | | [Giant Bomb](https://www.giantbomb.com) | The Giant Bomb API offers metadata for games for all platforms | games | Yes, by making an account [here](https://www.giantbomb.com/login-signup/) | API requests are limited to 200 requests per resource, per hour. In addition, they implement velocity detection to prevent malicious use. If too many requests are made per second, you may receive temporary blocks to resources. | No | -| Comic Vine | The Comic Vine API offers metadata for comic books | comicbooks | Yes, by making an account [here](https://comicvine.gamespot.com/login-signup/) and going to the [api section](https://comicvine.gamespot.com/api/) of the site | 200 requests per resource, per hour. There is also a velocity detection to prevent malicious use. If too many requests are made per second, you may receive temporary blocks to resources. | No +| Comic Vine | The Comic Vine API offers metadata for comic books | comicbooks | Yes, by making an account [here](https://comicvine.gamespot.com/login-signup/) and going to the [api section](https://comicvine.gamespot.com/api/) of the site | 200 requests per resource, per hour. There is also a velocity detection to prevent malicious use. If too many requests are made per second, you may receive temporary blocks to resources. | No | #### Notes diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 3601efc..2d4b7c4 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -111,10 +111,10 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { series: true, }, MALAPIManga: { - comicManga: true + comicManga: true, }, ComicVineAPI: { - comicManga: true + comicManga: true, }, SteamAPI: { game: true, @@ -195,499 +195,498 @@ export function getDefaultSettings(plugin: MediaDbPlugin): MediaDbPluginSettings } export class MediaDbSettingTab extends PluginSettingTab { - plugin: MediaDbPlugin; + plugin: MediaDbPlugin; - constructor(app: App, plugin: MediaDbPlugin) { - super(app, plugin); - this.plugin = plugin; - } + constructor(app: App, plugin: MediaDbPlugin) { + super(app, plugin); + this.plugin = plugin; + } - display(): void { - const { containerEl } = this; + display(): void { + const { containerEl } = this; - containerEl.empty(); + containerEl.empty(); - new Setting(containerEl) - .setName('OMDb API key') - .setDesc('API key for "www.omdbapi.com".') + new Setting(containerEl) + .setName('OMDb API key') + .setDesc('API key for "www.omdbapi.com".') .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.OMDbKey) - .onChange(data => { - this.plugin.settings.OMDbKey = data; - void this.plugin.saveSettings(); - }); - }); + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.OMDbKey) + .onChange(data => { + this.plugin.settings.OMDbKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Moby Games key') - .setDesc('API key for "www.mobygames.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.MobyGamesKey) - .onChange(data => { - this.plugin.settings.MobyGamesKey = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Moby Games key') + .setDesc('API key for "www.mobygames.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.MobyGamesKey) + .onChange(data => { + this.plugin.settings.MobyGamesKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Giant Bomb Key') - .setDesc('API key for "www.giantbomb.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.GiantBombKey) - .onChange(data => { - this.plugin.settings.GiantBombKey = data; - void this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) - .setName('Comic Vine Key') - .setDesc('API key for "www.comicvine.gamespot.com".') - .addText(cb => { - cb.setPlaceholder('API key') - .setValue(this.plugin.settings.ComicVineKey) - .onChange(data => { - this.plugin.settings.ComicVineKey = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Giant Bomb Key') + .setDesc('API key for "www.giantbomb.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.GiantBombKey) + .onChange(data => { + this.plugin.settings.GiantBombKey = data; + void this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) + .setName('Comic Vine Key') + .setDesc('API key for "www.comicvine.gamespot.com".') + .addText(cb => { + cb.setPlaceholder('API key') + .setValue(this.plugin.settings.ComicVineKey) + .onChange(data => { + this.plugin.settings.ComicVineKey = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('SFW filter') - .setDesc('Only shows SFW results for APIs that offer filtering.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.sfwFilter).onChange(data => { - this.plugin.settings.sfwFilter = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('SFW filter') + .setDesc('Only shows SFW results for APIs that offer filtering.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.sfwFilter).onChange(data => { + this.plugin.settings.sfwFilter = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Resolve {{ tags }} in templates') - .setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.templates).onChange(data => { - this.plugin.settings.templates = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Resolve {{ tags }} in templates') + .setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.templates).onChange(data => { + this.plugin.settings.templates = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Date format') - .setDesc( - fragWithHTML( - "Your custom date format. Use 'YYYY-MM-DD' for example.
    " + - "For more syntax, refer to format reference.
    " + - "Your current syntax looks like this: " + - this.plugin.dateFormatter.getPreview() + - '', - ), - ) - .addText(cb => { - cb.setPlaceholder(DEFAULT_SETTINGS.customDateFormat) - .setValue(this.plugin.settings.customDateFormat === DEFAULT_SETTINGS.customDateFormat ? '' : this.plugin.settings.customDateFormat) - .onChange(data => { - const newDateFormat = data ? data : DEFAULT_SETTINGS.customDateFormat; - this.plugin.settings.customDateFormat = newDateFormat; - const previewEl = document.getElementById('media-db-dateformat-preview'); - if (previewEl) { - previewEl.textContent = this.plugin.dateFormatter.getPreview(newDateFormat); // update preview - } - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Date format') + .setDesc( + fragWithHTML( + "Your custom date format. Use 'YYYY-MM-DD' for example.
    " + + "For more syntax, refer to format reference.
    " + + "Your current syntax looks like this: " + + this.plugin.dateFormatter.getPreview() + + '', + ), + ) + .addText(cb => { + cb.setPlaceholder(DEFAULT_SETTINGS.customDateFormat) + .setValue(this.plugin.settings.customDateFormat === DEFAULT_SETTINGS.customDateFormat ? '' : this.plugin.settings.customDateFormat) + .onChange(data => { + const newDateFormat = data ? data : DEFAULT_SETTINGS.customDateFormat; + this.plugin.settings.customDateFormat = newDateFormat; + const previewEl = document.getElementById('media-db-dateformat-preview'); + if (previewEl) { + previewEl.textContent = this.plugin.dateFormatter.getPreview(newDateFormat); // update preview + } + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Open note in new tab') - .setDesc('Open the newly created note in a new tab.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.openNoteInNewTab).onChange(data => { - this.plugin.settings.openNoteInNewTab = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Open note in new tab') + .setDesc('Open the newly created note in a new tab.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.openNoteInNewTab).onChange(data => { + this.plugin.settings.openNoteInNewTab = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Use default front matter') - .setDesc('Whether to use the default front matter. If disabled, the front matter from the template will be used. Same as mapping everything to remove.') - .addToggle(cb => { - cb.setValue(this.plugin.settings.useDefaultFrontMatter).onChange(data => { - this.plugin.settings.useDefaultFrontMatter = data; - void this.plugin.saveSettings(); - // Redraw settings to display/remove the property mappings - this.display(); - }); - }); + new Setting(containerEl) + .setName('Use default front matter') + .setDesc('Whether to use the default front matter. If disabled, the front matter from the template will be used. Same as mapping everything to remove.') + .addToggle(cb => { + cb.setValue(this.plugin.settings.useDefaultFrontMatter).onChange(data => { + this.plugin.settings.useDefaultFrontMatter = data; + void this.plugin.saveSettings(); + // Redraw settings to display/remove the property mappings + this.display(); + }); + }); - new Setting(containerEl) - .setName('Enable Templater integration') - .setDesc( - 'Enable integration with the templater plugin, this also needs templater to be installed. Warning: Templater allows you to execute arbitrary JavaScript code and system commands.', - ) - .addToggle(cb => { - cb.setValue(this.plugin.settings.enableTemplaterIntegration).onChange(data => { - this.plugin.settings.enableTemplaterIntegration = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Enable Templater integration') + .setDesc( + 'Enable integration with the templater plugin, this also needs templater to be installed. Warning: Templater allows you to execute arbitrary JavaScript code and system commands.', + ) + .addToggle(cb => { + cb.setValue(this.plugin.settings.enableTemplaterIntegration).onChange(data => { + this.plugin.settings.enableTemplaterIntegration = data; + void this.plugin.saveSettings(); + }); + }); - // Create a map to store APIs for each media type - const mediaTypeApiMap = new Map(); + // Create a map to store APIs for each media type + const mediaTypeApiMap = new Map(); - // Populate the map with APIs for each media type - Object.entries(this.plugin.settings.apiToggle).forEach(([apiName, api]) => { - Object.entries(api).forEach(([mediaType]) => { - if (!mediaTypeApiMap.has(mediaType)) { - mediaTypeApiMap.set(mediaType, []); - } - mediaTypeApiMap.get(mediaType)!.push(apiName); - }); - }); + // Populate the map with APIs for each media type + Object.entries(this.plugin.settings.apiToggle).forEach(([apiName, api]) => { + Object.entries(api).forEach(([mediaType]) => { + if (!mediaTypeApiMap.has(mediaType)) { + mediaTypeApiMap.set(mediaType, []); + } + mediaTypeApiMap.get(mediaType)!.push(apiName); + }); + }); - // Filter out media types with only one API - const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); + // Filter out media types with only one API + const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); - // Dynamically create settings based on the filtered media types and their APIs - filteredMediaTypes.forEach(([mediaType, apis]) => { - new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); - apis.forEach(apiName => { - const apiToggle = this.plugin.settings.apiToggle[apiName as keyof typeof this.plugin.settings.apiToggle]; - new Setting(containerEl) - .setName(apiName) - .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) - .addToggle(cb => { - cb.setValue((apiToggle as Record)[mediaType]) - .onChange(data => { - (apiToggle as Record)[mediaType] = data; - void this.plugin.saveSettings(); - }); - }); - }); - }); + // Dynamically create settings based on the filtered media types and their APIs + filteredMediaTypes.forEach(([mediaType, apis]) => { + new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); + apis.forEach(apiName => { + const apiToggle = this.plugin.settings.apiToggle[apiName as keyof typeof this.plugin.settings.apiToggle]; + new Setting(containerEl) + .setName(apiName) + .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) + .addToggle(cb => { + cb.setValue((apiToggle as Record)[mediaType]).onChange(data => { + (apiToggle as Record)[mediaType] = data; + void this.plugin.saveSettings(); + }); + }); + }); + }); - new Setting(containerEl).setName('New file location').setHeading(); - // region new file location - new Setting(containerEl) - .setName('Movie folder') - .setDesc('Where newly imported movies should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.movieFolder) - .setValue(this.plugin.settings.movieFolder) - .onChange(data => { - this.plugin.settings.movieFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('New file location').setHeading(); + // region new file location + new Setting(containerEl) + .setName('Movie folder') + .setDesc('Where newly imported movies should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.movieFolder) + .setValue(this.plugin.settings.movieFolder) + .onChange(data => { + this.plugin.settings.movieFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Series folder') - .setDesc('Where newly imported series should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.seriesFolder) - .setValue(this.plugin.settings.seriesFolder) - .onChange(data => { - this.plugin.settings.seriesFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series folder') + .setDesc('Where newly imported series should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.seriesFolder) + .setValue(this.plugin.settings.seriesFolder) + .onChange(data => { + this.plugin.settings.seriesFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Comic and manga folder') - .setDesc('Where newly imported comics and manga should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.mangaFolder) - .setValue(this.plugin.settings.mangaFolder) - .onChange(data => { - this.plugin.settings.mangaFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Comic and manga folder') + .setDesc('Where newly imported comics and manga should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.mangaFolder) + .setValue(this.plugin.settings.mangaFolder) + .onChange(data => { + this.plugin.settings.mangaFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Game folder') - .setDesc('Where newly imported games should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.gameFolder) - .setValue(this.plugin.settings.gameFolder) - .onChange(data => { - this.plugin.settings.gameFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Game folder') + .setDesc('Where newly imported games should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.gameFolder) + .setValue(this.plugin.settings.gameFolder) + .onChange(data => { + this.plugin.settings.gameFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Wiki folder') - .setDesc('Where newly imported wiki articles should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.wikiFolder) - .setValue(this.plugin.settings.wikiFolder) - .onChange(data => { - this.plugin.settings.wikiFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Wiki folder') + .setDesc('Where newly imported wiki articles should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.wikiFolder) + .setValue(this.plugin.settings.wikiFolder) + .onChange(data => { + this.plugin.settings.wikiFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music folder') - .setDesc('Where newly imported music should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.musicReleaseFolder) - .setValue(this.plugin.settings.musicReleaseFolder) - .onChange(data => { - this.plugin.settings.musicReleaseFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Music folder') + .setDesc('Where newly imported music should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.musicReleaseFolder) + .setValue(this.plugin.settings.musicReleaseFolder) + .onChange(data => { + this.plugin.settings.musicReleaseFolder = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game folder') - .setDesc('Where newly imported board games should be places.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.boardgameFolder) - .setValue(this.plugin.settings.boardgameFolder) - .onChange(data => { - this.plugin.settings.boardgameFolder = data; - void this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) - .setName('Book folder') - .setDesc('Where newly imported books should be placed.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder(DEFAULT_SETTINGS.bookFolder) - .setValue(this.plugin.settings.bookFolder) - .onChange(data => { - this.plugin.settings.bookFolder = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Board game folder') + .setDesc('Where newly imported board games should be places.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.boardgameFolder) + .setValue(this.plugin.settings.boardgameFolder) + .onChange(data => { + this.plugin.settings.boardgameFolder = data; + void this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) + .setName('Book folder') + .setDesc('Where newly imported books should be placed.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.bookFolder) + .setValue(this.plugin.settings.bookFolder) + .onChange(data => { + this.plugin.settings.bookFolder = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + // endregion - new Setting(containerEl).setName('Template settings').setHeading(); - // region templates - new Setting(containerEl) - .setName('Movie template') - .setDesc('Template file to be used when creating a new note for a movie.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: movieTemplate.md') - .setValue(this.plugin.settings.movieTemplate) - .onChange(data => { - this.plugin.settings.movieTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('Template settings').setHeading(); + // region templates + new Setting(containerEl) + .setName('Movie template') + .setDesc('Template file to be used when creating a new note for a movie.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: movieTemplate.md') + .setValue(this.plugin.settings.movieTemplate) + .onChange(data => { + this.plugin.settings.movieTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Series template') - .setDesc('Template file to be used when creating a new note for a series.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: seriesTemplate.md') - .setValue(this.plugin.settings.seriesTemplate) - .onChange(data => { - this.plugin.settings.seriesTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series template') + .setDesc('Template file to be used when creating a new note for a series.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: seriesTemplate.md') + .setValue(this.plugin.settings.seriesTemplate) + .onChange(data => { + this.plugin.settings.seriesTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Manga and Comics template') - .setDesc('Template file to be used when creating a new note for a manga or a comic.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: mangaTemplate.md') - .setValue(this.plugin.settings.mangaTemplate) - .onChange(data => { - this.plugin.settings.mangaTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Manga and Comics template') + .setDesc('Template file to be used when creating a new note for a manga or a comic.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: mangaTemplate.md') + .setValue(this.plugin.settings.mangaTemplate) + .onChange(data => { + this.plugin.settings.mangaTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Game template') - .setDesc('Template file to be used when creating a new note for a game.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: gameTemplate.md') - .setValue(this.plugin.settings.gameTemplate) - .onChange(data => { - this.plugin.settings.gameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Game template') + .setDesc('Template file to be used when creating a new note for a game.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: gameTemplate.md') + .setValue(this.plugin.settings.gameTemplate) + .onChange(data => { + this.plugin.settings.gameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Wiki template') - .setDesc('Template file to be used when creating a new note for a wiki entry.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: wikiTemplate.md') - .setValue(this.plugin.settings.wikiTemplate) - .onChange(data => { - this.plugin.settings.wikiTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Wiki template') + .setDesc('Template file to be used when creating a new note for a wiki entry.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: wikiTemplate.md') + .setValue(this.plugin.settings.wikiTemplate) + .onChange(data => { + this.plugin.settings.wikiTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music release template') - .setDesc('Template file to be used when creating a new note for a music release.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: musicReleaseTemplate.md') - .setValue(this.plugin.settings.musicReleaseTemplate) - .onChange(data => { - this.plugin.settings.musicReleaseTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Music release template') + .setDesc('Template file to be used when creating a new note for a music release.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: musicReleaseTemplate.md') + .setValue(this.plugin.settings.musicReleaseTemplate) + .onChange(data => { + this.plugin.settings.musicReleaseTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game template') - .setDesc('Template file to be used when creating a new note for a boardgame.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: boardgameTemplate.md') - .setValue(this.plugin.settings.boardgameTemplate) - .onChange(data => { - this.plugin.settings.boardgameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Board game template') + .setDesc('Template file to be used when creating a new note for a boardgame.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: boardgameTemplate.md') + .setValue(this.plugin.settings.boardgameTemplate) + .onChange(data => { + this.plugin.settings.boardgameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Book template') - .setDesc('Template file to be used when creating a new note for a book.') - .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: bookTemplate.md') - .setValue(this.plugin.settings.bookTemplate) - .onChange(data => { - this.plugin.settings.bookTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Book template') + .setDesc('Template file to be used when creating a new note for a book.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder('Example: bookTemplate.md') + .setValue(this.plugin.settings.bookTemplate) + .onChange(data => { + this.plugin.settings.bookTemplate = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + // endregion - new Setting(containerEl).setName('File name settings').setHeading(); - // region file name templates - new Setting(containerEl) - .setName('Movie file name template') - .setDesc('Template for the file name used when creating a new note for a movie.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) - .setValue(this.plugin.settings.movieFileNameTemplate) - .onChange(data => { - this.plugin.settings.movieFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl).setName('File name settings').setHeading(); + // region file name templates + new Setting(containerEl) + .setName('Movie file name template') + .setDesc('Template for the file name used when creating a new note for a movie.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) + .setValue(this.plugin.settings.movieFileNameTemplate) + .onChange(data => { + this.plugin.settings.movieFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Series file name template') - .setDesc('Template for the file name used when creating a new note for a series.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) - .setValue(this.plugin.settings.seriesFileNameTemplate) - .onChange(data => { - this.plugin.settings.seriesFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Series file name template') + .setDesc('Template for the file name used when creating a new note for a series.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) + .setValue(this.plugin.settings.seriesFileNameTemplate) + .onChange(data => { + this.plugin.settings.seriesFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Manga and comic file name template') - .setDesc('Template for the file name used when creating a new note for a manga or comic.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.mangaFileNameTemplate}`) - .setValue(this.plugin.settings.mangaFileNameTemplate) - .onChange(data => { - this.plugin.settings.mangaFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Manga and comic file name template') + .setDesc('Template for the file name used when creating a new note for a manga or comic.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.mangaFileNameTemplate}`) + .setValue(this.plugin.settings.mangaFileNameTemplate) + .onChange(data => { + this.plugin.settings.mangaFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Game file name template') - .setDesc('Template for the file name used when creating a new note for a game.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) - .setValue(this.plugin.settings.gameFileNameTemplate) - .onChange(data => { - this.plugin.settings.gameFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Game file name template') + .setDesc('Template for the file name used when creating a new note for a game.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) + .setValue(this.plugin.settings.gameFileNameTemplate) + .onChange(data => { + this.plugin.settings.gameFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Wiki file name template') - .setDesc('Template for the file name used when creating a new note for a wiki entry.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) - .setValue(this.plugin.settings.wikiFileNameTemplate) - .onChange(data => { - this.plugin.settings.wikiFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Wiki file name template') + .setDesc('Template for the file name used when creating a new note for a wiki entry.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) + .setValue(this.plugin.settings.wikiFileNameTemplate) + .onChange(data => { + this.plugin.settings.wikiFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Music release file name template') - .setDesc('Template for the file name used when creating a new note for a music release.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) - .setValue(this.plugin.settings.musicReleaseFileNameTemplate) - .onChange(data => { - this.plugin.settings.musicReleaseFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Music release file name template') + .setDesc('Template for the file name used when creating a new note for a music release.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) + .setValue(this.plugin.settings.musicReleaseFileNameTemplate) + .onChange(data => { + this.plugin.settings.musicReleaseFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Board game file name template') - .setDesc('Template for the file name used when creating a new note for a boardgame.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.boardgameFileNameTemplate}`) - .setValue(this.plugin.settings.boardgameFileNameTemplate) - .onChange(data => { - this.plugin.settings.boardgameFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Board game file name template') + .setDesc('Template for the file name used when creating a new note for a boardgame.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.boardgameFileNameTemplate}`) + .setValue(this.plugin.settings.boardgameFileNameTemplate) + .onChange(data => { + this.plugin.settings.boardgameFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - new Setting(containerEl) - .setName('Book file name template') - .setDesc('Template for the file name used when creating a new note for a book.') - .addText(cb => { - cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.bookFileNameTemplate}`) - .setValue(this.plugin.settings.bookFileNameTemplate) - .onChange(data => { - this.plugin.settings.bookFileNameTemplate = data; - void this.plugin.saveSettings(); - }); - }); + new Setting(containerEl) + .setName('Book file name template') + .setDesc('Template for the file name used when creating a new note for a book.') + .addText(cb => { + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.bookFileNameTemplate}`) + .setValue(this.plugin.settings.bookFileNameTemplate) + .onChange(data => { + this.plugin.settings.bookFileNameTemplate = data; + void this.plugin.saveSettings(); + }); + }); - // endregion + // endregion - // region Property Mappings - if (this.plugin.settings.useDefaultFrontMatter) { - new Setting(containerEl).setName('Property mappings').setHeading(); + // region Property Mappings + if (this.plugin.settings.useDefaultFrontMatter) { + new Setting(containerEl).setName('Property mappings').setHeading(); - const propertyMappingExplanation = containerEl.createEl('div'); - propertyMappingExplanation.innerHTML = ` + const propertyMappingExplanation = containerEl.createEl('div'); + propertyMappingExplanation.innerHTML = `

    Choose how metadata fields are mapped to property names. The options are:

    • default: keep the original name.
    • @@ -698,29 +697,29 @@ export class MediaDbSettingTab extends PluginSettingTab { Don't forget to save your changes using the save button for each individual category.

      `; - mount(PropertyMappingModelsComponent, { - target: this.containerEl, - props: { - models: this.plugin.settings.propertyMappingModels.map(x => x.copy()), - save: (model: PropertyMappingModel): void => { - const propertyMappingModels: PropertyMappingModel[] = []; + mount(PropertyMappingModelsComponent, { + target: this.containerEl, + props: { + models: this.plugin.settings.propertyMappingModels.map(x => x.copy()), + save: (model: PropertyMappingModel): void => { + const propertyMappingModels: PropertyMappingModel[] = []; - for (const model2 of this.plugin.settings.propertyMappingModels) { - if (model2.type === model.type) { - propertyMappingModels.push(model); - } else { - propertyMappingModels.push(model2); - } - } + for (const model2 of this.plugin.settings.propertyMappingModels) { + if (model2.type === model.type) { + propertyMappingModels.push(model); + } else { + propertyMappingModels.push(model2); + } + } - this.plugin.settings.propertyMappingModels = propertyMappingModels; - new Notice(`MDB: Property mappings for ${model.type} saved successfully.`); - void this.plugin.saveSettings(); - }, - }, - }); - } + this.plugin.settings.propertyMappingModels = propertyMappingModels; + new Notice(`MDB: Property mappings for ${model.type} saved successfully.`); + void this.plugin.saveSettings(); + }, + }, + }); + } - // endregion - } + // endregion + } } From 4995727fd37eb429b1dc22e5af4ccf6483da0fde Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 14:53:33 +0100 Subject: [PATCH 03/19] Removed VNDBAPI mentions --- src/settings/Settings.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 2d4b7c4..5d90080 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -46,9 +46,6 @@ export interface MediaDbPluginSettings { GiantBombAPI: { game: boolean; }; - VNDBAPI: { - game: boolean; - }; }; movieTemplate: string; seriesTemplate: string; @@ -125,9 +122,6 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { GiantBombAPI: { game: true, }, - VNDBAPI: { - game: true, - }, }, movieTemplate: '', seriesTemplate: '', From 7a0f8e03bbbc353cf9a76f4f403438f5ca8b8b31 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:24:50 +0100 Subject: [PATCH 04/19] Changed for.each loops to for loops --- src/settings/Settings.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 5d90080..1042802 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -331,22 +331,22 @@ export class MediaDbSettingTab extends PluginSettingTab { const mediaTypeApiMap = new Map(); // Populate the map with APIs for each media type - Object.entries(this.plugin.settings.apiToggle).forEach(([apiName, api]) => { - Object.entries(api).forEach(([mediaType]) => { + for (const [apiName, api] of Object.entries(this.plugin.settings.apiToggle)) { + for (const mediaType of Object.keys(api)) { if (!mediaTypeApiMap.has(mediaType)) { mediaTypeApiMap.set(mediaType, []); } mediaTypeApiMap.get(mediaType)!.push(apiName); - }); - }); + } + } // Filter out media types with only one API const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); // Dynamically create settings based on the filtered media types and their APIs - filteredMediaTypes.forEach(([mediaType, apis]) => { + for (const [mediaType, apis] of filteredMediaTypes) { new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); - apis.forEach(apiName => { + for (const apiName of apis) { const apiToggle = this.plugin.settings.apiToggle[apiName as keyof typeof this.plugin.settings.apiToggle]; new Setting(containerEl) .setName(apiName) @@ -357,8 +357,8 @@ export class MediaDbSettingTab extends PluginSettingTab { void this.plugin.saveSettings(); }); }); - }); - }); + } + } new Setting(containerEl).setName('New file location').setHeading(); // region new file location From daeefb9688c80f671b8989e455e80ffdbc198ade Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:16:47 +0100 Subject: [PATCH 05/19] Possible fix for the flat structured arrays --- src/api/APIModel.ts | 11 ++--- src/settings/Settings.ts | 100 ++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 66 deletions(-) diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index ecd2f43..94adbd3 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -10,7 +10,7 @@ export abstract class APIModel { plugin!: MediaDbPlugin; /** - * This function should query the api and return a list of matches. The matches should be caped at 20. + * This function should query the api and return a list of matches. The matches should be capped at 20. * * @param title the title to query for */ @@ -19,13 +19,8 @@ export abstract class APIModel { abstract getById(id: string): Promise; hasType(type: MediaType): boolean { - if ( - this.types.contains(type) && - (Boolean((this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type]) === true || (this.plugin.settings.apiToggle as any)?.[this.apiName]?.[type] === undefined) - ) { - return true; - } - return false; + const disabledMediaTypes = this.plugin.settings[`${this.apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]; + return this.types.includes(type) && !disabledMediaTypes.includes(type); } hasTypeOverlap(types: MediaType[]): boolean { diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 1042802..68b3c6e 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -21,32 +21,13 @@ export interface MediaDbPluginSettings { openNoteInNewTab: boolean; useDefaultFrontMatter: boolean; enableTemplaterIntegration: boolean; - apiToggle: { - OMDbAPI: { - movie: boolean; - series: boolean; - game: boolean; - }; - MALAPI: { - movie: boolean; - series: boolean; - }; - MALAPIManga: { - comicManga: boolean; - }; - ComicVineAPI: { - comicManga: boolean; - }; - SteamAPI: { - game: boolean; - }; - MobyGamesAPI: { - game: boolean; - }; - GiantBombAPI: { - game: boolean; - }; - }; + OMDbAPI_disabledMediaTypes: string[]; + MALAPI_disabledMediaTypes: string[]; + MALAPIManga_disabledMediaTypes: string[]; + ComicVineAPI_disabledMediaTypes: string[]; + SteamAPI_disabledMediaTypes: string[]; + MobyGamesAPI_disabledMediaTypes: string[]; + GiantBombAPI_disabledMediaTypes: string[]; movieTemplate: string; seriesTemplate: string; mangaTemplate: string; @@ -97,32 +78,13 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { openNoteInNewTab: true, useDefaultFrontMatter: true, enableTemplaterIntegration: false, - apiToggle: { - OMDbAPI: { - movie: true, - series: true, - game: true, - }, - MALAPI: { - movie: true, - series: true, - }, - MALAPIManga: { - comicManga: true, - }, - ComicVineAPI: { - comicManga: true, - }, - SteamAPI: { - game: true, - }, - MobyGamesAPI: { - game: true, - }, - GiantBombAPI: { - game: true, - }, - }, + OMDbAPI_disabledMediaTypes: [], + MALAPI_disabledMediaTypes: [], + MALAPIManga_disabledMediaTypes: [], + ComicVineAPI_disabledMediaTypes: [], + SteamAPI_disabledMediaTypes: [], + MobyGamesAPI_disabledMediaTypes: [], + GiantBombAPI_disabledMediaTypes: [], movieTemplate: '', seriesTemplate: '', mangaTemplate: '', @@ -329,31 +291,53 @@ export class MediaDbSettingTab extends PluginSettingTab { // Create a map to store APIs for each media type const mediaTypeApiMap = new Map(); + const apiMediaTypes = { + OMDbAPI: ['movie', 'series', 'game'], + MALAPI: ['movie', 'series'], + MALAPIManga: ['manga'], + ComicVineAPI: ['comic', 'manga'], + SteamAPI: ['game'], + MobyGamesAPI: ['game'], + GiantBombAPI: ['game'], + }; // Populate the map with APIs for each media type - for (const [apiName, api] of Object.entries(this.plugin.settings.apiToggle)) { - for (const mediaType of Object.keys(api)) { + for (const [api, mediaTypes] of Object.entries(apiMediaTypes)) { + for (const mediaType of mediaTypes) { if (!mediaTypeApiMap.has(mediaType)) { mediaTypeApiMap.set(mediaType, []); } - mediaTypeApiMap.get(mediaType)!.push(apiName); + mediaTypeApiMap.get(mediaType)!.push(api); } } + // Log the populated map to verify its contents + console.log('mediaTypeApiMap:', mediaTypeApiMap); + // Filter out media types with only one API const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); + // Log the filtered media types to verify the filtering + console.log('filteredMediaTypes:', filteredMediaTypes); + // Dynamically create settings based on the filtered media types and their APIs for (const [mediaType, apis] of filteredMediaTypes) { new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); for (const apiName of apis) { - const apiToggle = this.plugin.settings.apiToggle[apiName as keyof typeof this.plugin.settings.apiToggle]; + const disabledMediaTypes = this.plugin.settings[`${apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as string[]; new Setting(containerEl) .setName(apiName) .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) .addToggle(cb => { - cb.setValue((apiToggle as Record)[mediaType]).onChange(data => { - (apiToggle as Record)[mediaType] = data; + cb.setValue(!disabledMediaTypes.includes(mediaType)).onChange(data => { + if (data) { + const index = disabledMediaTypes.indexOf(mediaType); + if (index > -1) { + disabledMediaTypes.splice(index, 1); + } + } else { + disabledMediaTypes.push(mediaType); + } void this.plugin.saveSettings(); }); }); From e09737a09096c3716c7aee95ce7368bde709a44c Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 18:45:37 +0100 Subject: [PATCH 06/19] Removed logging and fixed error for comicmanga --- src/settings/Settings.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 68b3c6e..f7d721b 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -294,8 +294,8 @@ export class MediaDbSettingTab extends PluginSettingTab { const apiMediaTypes = { OMDbAPI: ['movie', 'series', 'game'], MALAPI: ['movie', 'series'], - MALAPIManga: ['manga'], - ComicVineAPI: ['comic', 'manga'], + MALAPIManga: ['comicManga'], + ComicVineAPI: ['comicManga'], SteamAPI: ['game'], MobyGamesAPI: ['game'], GiantBombAPI: ['game'], @@ -311,15 +311,9 @@ export class MediaDbSettingTab extends PluginSettingTab { } } - // Log the populated map to verify its contents - console.log('mediaTypeApiMap:', mediaTypeApiMap); - // Filter out media types with only one API const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); - // Log the filtered media types to verify the filtering - console.log('filteredMediaTypes:', filteredMediaTypes); - // Dynamically create settings based on the filtered media types and their APIs for (const [mediaType, apis] of filteredMediaTypes) { new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); From 98e96b15c70a6e6110a8cc7efdb74b3415da5a14 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 19:17:59 +0100 Subject: [PATCH 07/19] Added a fix for api's with spaces in their names --- src/api/APIModel.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index 94adbd3..6056a7d 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -19,8 +19,9 @@ export abstract class APIModel { abstract getById(id: string): Promise; hasType(type: MediaType): boolean { - const disabledMediaTypes = this.plugin.settings[`${this.apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]; - return this.types.includes(type) && !disabledMediaTypes.includes(type); + const sanitizedApiName = this.apiName.replace(/\s+/g, '_'); + const disabledMediaTypes = (this.plugin.settings[`${sanitizedApiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]) || []; + return (this.types || []).includes(type) && !disabledMediaTypes.includes(type); } hasTypeOverlap(types: MediaType[]): boolean { From af6009f1acf10d2bcaf475f1cde7ba6928178929 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 21:47:18 +0100 Subject: [PATCH 08/19] Revert "Added a fix for api's with spaces in their names" This reverts commit 98e96b15c70a6e6110a8cc7efdb74b3415da5a14. --- src/api/APIModel.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index 6056a7d..94adbd3 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -19,9 +19,8 @@ export abstract class APIModel { abstract getById(id: string): Promise; hasType(type: MediaType): boolean { - const sanitizedApiName = this.apiName.replace(/\s+/g, '_'); - const disabledMediaTypes = (this.plugin.settings[`${sanitizedApiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]) || []; - return (this.types || []).includes(type) && !disabledMediaTypes.includes(type); + const disabledMediaTypes = this.plugin.settings[`${this.apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]; + return this.types.includes(type) && !disabledMediaTypes.includes(type); } hasTypeOverlap(types: MediaType[]): boolean { From cc30e60d928f7291ddff2aed3cd1a3d430638055 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 21:50:29 +0100 Subject: [PATCH 09/19] Reverted change, spaces shouldn't be allowed in API names to ensure compatibility --- src/api/apis/MALAPIManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/apis/MALAPIManga.ts b/src/api/apis/MALAPIManga.ts index bd99476..77a8416 100644 --- a/src/api/apis/MALAPIManga.ts +++ b/src/api/apis/MALAPIManga.ts @@ -12,7 +12,7 @@ export class MALAPIManga extends APIModel { super(); this.plugin = plugin; - this.apiName = 'MALAPI Manga'; + this.apiName = 'MALAPIManga'; this.apiDescription = 'A free API for Manga. Some results may take a long time to load.'; this.apiUrl = 'https://jikan.moe/'; this.types = [MediaType.ComicManga]; From 266bb99a31ddc67dfe1ca6355190d8729a6a77df Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Wed, 5 Mar 2025 22:07:51 +0100 Subject: [PATCH 10/19] Added conversion from MALAPI Manga to MALAPIManga --- src/settings/PropertyMapper.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/settings/PropertyMapper.ts b/src/settings/PropertyMapper.ts index e3be2c5..9a46d27 100644 --- a/src/settings/PropertyMapper.ts +++ b/src/settings/PropertyMapper.ts @@ -66,6 +66,10 @@ export class PropertyMapper { obj.type = 'comicManga'; console.debug(`MDB | updated metadata type`, obj.type); } + if (obj.dataSource === 'MALAPI Manga') { + obj.dataSource = 'MALAPIManga'; + console.debug(`MDB | updated metadata dataSource`, obj.type); + } if (MEDIA_TYPES.contains(obj.type as any)) { return obj; } From 666ca1e93bc3d073e425afad1aea07948136a373 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sat, 8 Mar 2025 02:26:15 +0100 Subject: [PATCH 11/19] Reverted MALAPIManga rename --- src/api/apis/MALAPIManga.ts | 5 ++++- src/settings/PropertyMapper.ts | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/api/apis/MALAPIManga.ts b/src/api/apis/MALAPIManga.ts index 77a8416..138fc8d 100644 --- a/src/api/apis/MALAPIManga.ts +++ b/src/api/apis/MALAPIManga.ts @@ -12,7 +12,7 @@ export class MALAPIManga extends APIModel { super(); this.plugin = plugin; - this.apiName = 'MALAPIManga'; + this.apiName = 'MALAPI Manga'; this.apiDescription = 'A free API for Manga. Some results may take a long time to load.'; this.apiUrl = 'https://jikan.moe/'; this.types = [MediaType.ComicManga]; @@ -126,4 +126,7 @@ export class MALAPIManga extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.MALAPIManga_disabledMediaTypes as MediaType[]; + } } diff --git a/src/settings/PropertyMapper.ts b/src/settings/PropertyMapper.ts index 9a46d27..e3be2c5 100644 --- a/src/settings/PropertyMapper.ts +++ b/src/settings/PropertyMapper.ts @@ -66,10 +66,6 @@ export class PropertyMapper { obj.type = 'comicManga'; console.debug(`MDB | updated metadata type`, obj.type); } - if (obj.dataSource === 'MALAPI Manga') { - obj.dataSource = 'MALAPIManga'; - console.debug(`MDB | updated metadata dataSource`, obj.type); - } if (MEDIA_TYPES.contains(obj.type as any)) { return obj; } From 72198abd33ae6b596b3f45228a05778f358bfca5 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sat, 8 Mar 2025 02:35:09 +0100 Subject: [PATCH 12/19] Made several improvements - Replaced interpolated string to a new function getDisabledMediaTypes() - Added override for every API with the plugin settings for disabled media types - Added _disabledMediaTypes for API's even if they are the only provider of a media type - Replaced static apiMediaTypes to a dynamic version --- src/api/APIModel.ts | 4 +- src/api/apis/BoardGameGeekAPI.ts | 3 ++ src/api/apis/ComicVineAPI.ts | 3 ++ src/api/apis/GiantBombAPI.ts | 3 ++ src/api/apis/MALAPI.ts | 3 ++ src/api/apis/MobyGamesAPI.ts | 3 ++ src/api/apis/MusicBrainzAPI.ts | 3 ++ src/api/apis/OMDbAPI.ts | 4 ++ src/api/apis/OpenLibraryAPI.ts | 3 ++ src/api/apis/SteamAPI.ts | 3 ++ src/api/apis/WikipediaAPI.ts | 3 ++ src/settings/Settings.ts | 67 +++++++++++++++++--------------- 12 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index 94adbd3..0919db9 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -18,8 +18,10 @@ export abstract class APIModel { abstract getById(id: string): Promise; + abstract getDisabledMediaTypes(): MediaType[]; + hasType(type: MediaType): boolean { - const disabledMediaTypes = this.plugin.settings[`${this.apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as MediaType[]; + const disabledMediaTypes = this.getDisabledMediaTypes(); return this.types.includes(type) && !disabledMediaTypes.includes(type); } diff --git a/src/api/apis/BoardGameGeekAPI.ts b/src/api/apis/BoardGameGeekAPI.ts index 96ef76e..08c574f 100644 --- a/src/api/apis/BoardGameGeekAPI.ts +++ b/src/api/apis/BoardGameGeekAPI.ts @@ -117,4 +117,7 @@ export class BoardGameGeekAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.BoardgameGeekAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/ComicVineAPI.ts b/src/api/apis/ComicVineAPI.ts index 86c9bf8..65fd167 100644 --- a/src/api/apis/ComicVineAPI.ts +++ b/src/api/apis/ComicVineAPI.ts @@ -95,4 +95,7 @@ export class ComicVineAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.ComicVineAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/GiantBombAPI.ts b/src/api/apis/GiantBombAPI.ts index 60bf4e8..a60ccae 100644 --- a/src/api/apis/GiantBombAPI.ts +++ b/src/api/apis/GiantBombAPI.ts @@ -106,4 +106,7 @@ export class GiantBombAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.GiantBombAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/MALAPI.ts b/src/api/apis/MALAPI.ts index fa0d322..d85746c 100644 --- a/src/api/apis/MALAPI.ts +++ b/src/api/apis/MALAPI.ts @@ -195,4 +195,7 @@ export class MALAPI extends APIModel { throw new Error(`MDB | Unknown media type for id ${id}`); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.MALAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/MobyGamesAPI.ts b/src/api/apis/MobyGamesAPI.ts index 4c2922b..a8f0861 100644 --- a/src/api/apis/MobyGamesAPI.ts +++ b/src/api/apis/MobyGamesAPI.ts @@ -107,4 +107,7 @@ export class MobyGamesAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.MobyGamesAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts index 87349a1..022d944 100644 --- a/src/api/apis/MusicBrainzAPI.ts +++ b/src/api/apis/MusicBrainzAPI.ts @@ -99,4 +99,7 @@ export class MusicBrainzAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.MusicBrainzAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index 0dd54cc..fb6351d 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -223,4 +223,8 @@ export class OMDbAPI extends APIModel { throw new Error(`MDB | Unknown media type for id ${id}`); } + + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.OMDbAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/OpenLibraryAPI.ts b/src/api/apis/OpenLibraryAPI.ts index 4835afe..78eb301 100644 --- a/src/api/apis/OpenLibraryAPI.ts +++ b/src/api/apis/OpenLibraryAPI.ts @@ -89,4 +89,7 @@ export class OpenLibraryAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.OpenLibraryAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts index 1e52979..d3f7c8f 100644 --- a/src/api/apis/SteamAPI.ts +++ b/src/api/apis/SteamAPI.ts @@ -109,4 +109,7 @@ export class SteamAPI extends APIModel { }, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.SteamAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/api/apis/WikipediaAPI.ts b/src/api/apis/WikipediaAPI.ts index 110cd79..b73382d 100644 --- a/src/api/apis/WikipediaAPI.ts +++ b/src/api/apis/WikipediaAPI.ts @@ -79,4 +79,7 @@ export class WikipediaAPI extends APIModel { userData: {}, }); } + getDisabledMediaTypes(): MediaType[] { + return this.plugin.settings.WikipediaAPI_disabledMediaTypes as MediaType[]; + } } diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index f7d721b..da981d4 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -9,6 +9,7 @@ import { PropertyMapping, PropertyMappingModel, PropertyMappingOption } from './ import PropertyMappingModelsComponent from './PropertyMappingModelsComponent.svelte'; import { FileSuggest } from './suggesters/FileSuggest'; import { FolderSuggest } from './suggesters/FolderSuggest'; +import type { MediaType } from 'src/utils/MediaType'; export interface MediaDbPluginSettings { OMDbKey: string; @@ -28,6 +29,10 @@ export interface MediaDbPluginSettings { SteamAPI_disabledMediaTypes: string[]; MobyGamesAPI_disabledMediaTypes: string[]; GiantBombAPI_disabledMediaTypes: string[]; + WikipediaAPI_disabledMediaTypes: string[]; + BoardgameGeekAPI_disabledMediaTypes: string[]; + MusicBrainzAPI_disabledMediaTypes: string[]; + OpenLibraryAPI_disabledMediaTypes: string[]; movieTemplate: string; seriesTemplate: string; mangaTemplate: string; @@ -85,6 +90,10 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { SteamAPI_disabledMediaTypes: [], MobyGamesAPI_disabledMediaTypes: [], GiantBombAPI_disabledMediaTypes: [], + WikipediaAPI_disabledMediaTypes: [], + BoardgameGeekAPI_disabledMediaTypes: [], + MusicBrainzAPI_disabledMediaTypes: [], + OpenLibraryAPI_disabledMediaTypes: [], movieTemplate: '', seriesTemplate: '', mangaTemplate: '', @@ -291,23 +300,14 @@ export class MediaDbSettingTab extends PluginSettingTab { // Create a map to store APIs for each media type const mediaTypeApiMap = new Map(); - const apiMediaTypes = { - OMDbAPI: ['movie', 'series', 'game'], - MALAPI: ['movie', 'series'], - MALAPIManga: ['comicManga'], - ComicVineAPI: ['comicManga'], - SteamAPI: ['game'], - MobyGamesAPI: ['game'], - GiantBombAPI: ['game'], - }; - // Populate the map with APIs for each media type - for (const [api, mediaTypes] of Object.entries(apiMediaTypes)) { - for (const mediaType of mediaTypes) { - if (!mediaTypeApiMap.has(mediaType)) { - mediaTypeApiMap.set(mediaType, []); + // Populate the map with APIs for each media type dynamically + for (const api of this.plugin.apiManager.apis) { + for (const MediaType of api.types) { + if (!mediaTypeApiMap.has(MediaType)) { + mediaTypeApiMap.set(MediaType, []); } - mediaTypeApiMap.get(mediaType)!.push(api); + mediaTypeApiMap.get(MediaType)!.push(api.apiName); } } @@ -315,26 +315,29 @@ export class MediaDbSettingTab extends PluginSettingTab { const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); // Dynamically create settings based on the filtered media types and their APIs - for (const [mediaType, apis] of filteredMediaTypes) { - new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); + for (const [MediaType, apis] of filteredMediaTypes) { + new Setting(containerEl).setName(`Select APIs for ${unCamelCase(MediaType)}`).setHeading(); for (const apiName of apis) { - const disabledMediaTypes = this.plugin.settings[`${apiName}_disabledMediaTypes` as keyof typeof this.plugin.settings] as string[]; - new Setting(containerEl) - .setName(apiName) - .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) - .addToggle(cb => { - cb.setValue(!disabledMediaTypes.includes(mediaType)).onChange(data => { - if (data) { - const index = disabledMediaTypes.indexOf(mediaType); - if (index > -1) { - disabledMediaTypes.splice(index, 1); + const api = this.plugin.apiManager.apis.find(api => api.apiName === apiName); + if (api) { + const disabledMediaTypes = api.getDisabledMediaTypes(); + new Setting(containerEl) + .setName(apiName) + .setDesc(`Use ${apiName} API for ${unCamelCase(MediaType)}.`) + .addToggle(cb => { + cb.setValue(!disabledMediaTypes.includes(MediaType as MediaType)).onChange(data => { + if (data) { + const index = disabledMediaTypes.indexOf(MediaType as MediaType); + if (index > -1) { + disabledMediaTypes.splice(index, 1); + } + } else { + disabledMediaTypes.push(MediaType as MediaType); } - } else { - disabledMediaTypes.push(mediaType); - } - void this.plugin.saveSettings(); + void this.plugin.saveSettings(); + }); }); - }); + } } } From d5c760e72b96e14679444fc72a3a458428ff40bc Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sat, 8 Mar 2025 13:55:51 +0100 Subject: [PATCH 13/19] Applied fixes for review Use MediaType[] instead of string[], changed variables to lowercase --- src/settings/Settings.ts | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index da981d4..15c45af 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -22,17 +22,17 @@ export interface MediaDbPluginSettings { openNoteInNewTab: boolean; useDefaultFrontMatter: boolean; enableTemplaterIntegration: boolean; - OMDbAPI_disabledMediaTypes: string[]; - MALAPI_disabledMediaTypes: string[]; - MALAPIManga_disabledMediaTypes: string[]; - ComicVineAPI_disabledMediaTypes: string[]; - SteamAPI_disabledMediaTypes: string[]; - MobyGamesAPI_disabledMediaTypes: string[]; - GiantBombAPI_disabledMediaTypes: string[]; - WikipediaAPI_disabledMediaTypes: string[]; - BoardgameGeekAPI_disabledMediaTypes: string[]; - MusicBrainzAPI_disabledMediaTypes: string[]; - OpenLibraryAPI_disabledMediaTypes: string[]; + OMDbAPI_disabledMediaTypes: MediaType[]; + MALAPI_disabledMediaTypes: MediaType[]; + MALAPIManga_disabledMediaTypes: MediaType[]; + ComicVineAPI_disabledMediaTypes: MediaType[]; + SteamAPI_disabledMediaTypes: MediaType[]; + MobyGamesAPI_disabledMediaTypes: MediaType[]; + GiantBombAPI_disabledMediaTypes: MediaType[]; + WikipediaAPI_disabledMediaTypes: MediaType[]; + BoardgameGeekAPI_disabledMediaTypes: MediaType[]; + MusicBrainzAPI_disabledMediaTypes: MediaType[]; + OpenLibraryAPI_disabledMediaTypes: MediaType[]; movieTemplate: string; seriesTemplate: string; mangaTemplate: string; @@ -299,15 +299,15 @@ export class MediaDbSettingTab extends PluginSettingTab { }); // Create a map to store APIs for each media type - const mediaTypeApiMap = new Map(); + const mediaTypeApiMap = new Map(); // Populate the map with APIs for each media type dynamically for (const api of this.plugin.apiManager.apis) { - for (const MediaType of api.types) { - if (!mediaTypeApiMap.has(MediaType)) { - mediaTypeApiMap.set(MediaType, []); + for (const mediaType of api.types) { + if (!mediaTypeApiMap.has(mediaType)) { + mediaTypeApiMap.set(mediaType, []); } - mediaTypeApiMap.get(MediaType)!.push(api.apiName); + mediaTypeApiMap.get(mediaType)!.push(api.apiName); } } @@ -315,24 +315,24 @@ export class MediaDbSettingTab extends PluginSettingTab { const filteredMediaTypes = Array.from(mediaTypeApiMap.entries()).filter(([_, apis]) => apis.length > 1); // Dynamically create settings based on the filtered media types and their APIs - for (const [MediaType, apis] of filteredMediaTypes) { - new Setting(containerEl).setName(`Select APIs for ${unCamelCase(MediaType)}`).setHeading(); + for (const [mediaType, apis] of filteredMediaTypes) { + new Setting(containerEl).setName(`Select APIs for ${unCamelCase(mediaType)}`).setHeading(); for (const apiName of apis) { const api = this.plugin.apiManager.apis.find(api => api.apiName === apiName); if (api) { const disabledMediaTypes = api.getDisabledMediaTypes(); new Setting(containerEl) .setName(apiName) - .setDesc(`Use ${apiName} API for ${unCamelCase(MediaType)}.`) + .setDesc(`Use ${apiName} API for ${unCamelCase(mediaType)}.`) .addToggle(cb => { - cb.setValue(!disabledMediaTypes.includes(MediaType as MediaType)).onChange(data => { + cb.setValue(!disabledMediaTypes.includes(mediaType)).onChange(data => { if (data) { - const index = disabledMediaTypes.indexOf(MediaType as MediaType); + const index = disabledMediaTypes.indexOf(mediaType); if (index > -1) { disabledMediaTypes.splice(index, 1); } } else { - disabledMediaTypes.push(MediaType as MediaType); + disabledMediaTypes.push(mediaType); } void this.plugin.saveSettings(); }); From e42ba35697cfadb508718ecaca44954991c2de39 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Mon, 5 May 2025 15:52:16 +0200 Subject: [PATCH 14/19] "Cancel bug" fix #188 --- src/main.ts | 16 ++++++++++++---- src/utils/ModalHelper.ts | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main.ts b/src/main.ts index bdb02bb..c4f8562 100644 --- a/src/main.ts +++ b/src/main.ts @@ -218,13 +218,17 @@ export default class MediaDbPlugin extends Plugin { (await this.modalHelper.openSelectModal({ elements: apiSearchResults }, async selectModalData => { return await this.queryDetails(selectModalData.selected); })) ?? []; - if (!selectResults) { + if (!selectResults || selectResults.length < 1) { return; } - proceed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => { + const confirmed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => { return previewModalData.confirmed; }); + if (!confirmed) { + return; + } + break; } await this.createMediaDbNotes(selectResults!); @@ -248,13 +252,17 @@ export default class MediaDbPlugin extends Plugin { (await this.modalHelper.openSelectModal({ elements: apiSearchResults }, async selectModalData => { return await this.queryDetails(selectModalData.selected); })) ?? []; - if (!selectResults) { + if (!selectResults || selectResults.length < 1) { return; } - proceed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => { + const confirmed = await this.modalHelper.openPreviewModal({ elements: selectResults }, async previewModalData => { return previewModalData.confirmed; }); + if (!confirmed) { + return; + } + break; } await this.createMediaDbNotes(selectResults!); diff --git a/src/utils/ModalHelper.ts b/src/utils/ModalHelper.ts index eadf5a2..fce0f5c 100644 --- a/src/utils/ModalHelper.ts +++ b/src/utils/ModalHelper.ts @@ -505,12 +505,12 @@ export class ModalHelper { console.warn(previewModalResult.error); new Notice(previewModalResult.error.toString()); previewModal.close(); - return true; + return false; } if (previewModalResult.code === ModalResultCode.CLOSE) { // modal is already being closed - return true; + return false; } try { From 0a65fd8c8719347b6848eed41865975935037c93 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Mon, 5 May 2025 16:36:04 +0200 Subject: [PATCH 15/19] Updated readme for MusicBrainz To solve #186 --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e4c8805..b641bb9 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,10 @@ Now you select the result you want and the plugin will cast it's magic and creat - e.g. for "Rogue One" the URL looks like this `https://www.imdb.com/title/tt3748528/` so the ID is `tt3748528` - [MusicBrainz](https://musicbrainz.org/) - the id of a release is not easily accessible, you are better off just searching by title + - the search is generally for albums but you can have a more granular search like so: + - search for albums by a specific `artist:"Lady Gaga" AND primarytype:"album"` + - search for a specific album by a specific artist `artist:"Lady Gaga" AND primarytype:"album" AND releasegroup:"The Fame"` + - search for a specific entry (song or album) by a specific `artist:"Lady Gaga" AND releasegroup:"Poker face"` - [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) - [here](https://en.wikipedia.org/wiki/Wikipedia:Finding_a_Wikidata_ID) is a guide to finding the Wikipedia ID for an article - [Steam](https://store.steampowered.com/) From 657668dc7de898496ce0c40bb8ad35dbd2d9d8e1 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sun, 11 May 2025 17:26:12 +0200 Subject: [PATCH 16/19] Added download option for image urls --- src/main.ts | 26 ++++++++++++++++++++++++++ src/models/MediaTypeModel.ts | 3 +++ src/settings/Settings.ts | 27 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/src/main.ts b/src/main.ts index c4f8562..8240617 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,5 @@ import { MarkdownView, Notice, parseYaml, Plugin, stringifyYaml, TFile, TFolder } from 'obsidian'; +import { requestUrl, normalizePath } from 'obsidian'; // Add requestUrl import import type { MediaType } from 'src/utils/MediaType'; import { APIManager } from './api/APIManager'; import { BoardGameGeekAPI } from './api/apis/BoardGameGeekAPI'; @@ -314,6 +315,31 @@ export default class MediaDbPlugin extends Plugin { options.openNote = this.settings.openNoteInNewTab; + if (mediaTypeModel.image && typeof mediaTypeModel.image === 'string' && mediaTypeModel.image.startsWith('http')) { + if (this.settings.imageDownload) { + try { + const imageurl = mediaTypeModel.image; + const imageext = imageurl.split('.').pop()?.split(/\#|\?/)[0] || 'jpg'; + const imagefileName = `${replaceIllegalFileNameCharactersInString(`${mediaTypeModel.type}_${mediaTypeModel.title} (${mediaTypeModel.year})`)}.${imageext}`; + const imagepath = normalizePath(`${this.settings.imageFolder}/${imagefileName}`); + + if (!this.app.vault.getAbstractFileByPath(this.settings.imageFolder)) { + await this.app.vault.createFolder(this.settings.imageFolder); + } + + const response = await requestUrl({ url: imageurl, method: 'GET' }); + await this.app.vault.createBinary(imagepath, response.arrayBuffer); + + // Update model to use local image path + mediaTypeModel.image = `[[${imagepath}]]`; + } catch (e) { + console.warn('MDB | Failed to download image:', e); + } + } else { + mediaTypeModel.image = mediaTypeModel.image; + } + } + const fileContent = await this.generateMediaDbNoteContents(mediaTypeModel, options); if (!options.folder) { diff --git a/src/models/MediaTypeModel.ts b/src/models/MediaTypeModel.ts index 51c6378..e4d03a0 100644 --- a/src/models/MediaTypeModel.ts +++ b/src/models/MediaTypeModel.ts @@ -9,6 +9,7 @@ export abstract class MediaTypeModel { dataSource: string; url: string; id: string; + image?: string; userData: object; @@ -21,6 +22,8 @@ export abstract class MediaTypeModel { this.dataSource = ''; this.url = ''; this.id = ''; + this.image = ''; + this.userData = {}; } diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 15c45af..b48b82c 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -69,6 +69,8 @@ export interface MediaDbPluginSettings { boardgameFolder: string; bookFolder: string; + imageDownload: boolean; + imageFolder: string; propertyMappingModels: PropertyMappingModel[]; } @@ -130,6 +132,8 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { boardgameFolder: 'Media DB/boardgames', bookFolder: 'Media DB/books', + imageDownload: false, + imageFolder: 'Media DB/images', propertyMappingModels: [], }; @@ -298,6 +302,29 @@ export class MediaDbSettingTab extends PluginSettingTab { }); }); + new Setting(containerEl) + .setName('Download images') + .setDesc('Downloads images for new notes in the folder below') + .addToggle(cb => { + cb.setValue(this.plugin.settings.imageDownload).onChange(data => { + this.plugin.settings.imageDownload = data; + void this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Image folder') + .setDesc('Where downloaded images should be stored.') + .addSearch(cb => { + new FolderSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.imageFolder) + .setValue(this.plugin.settings.imageFolder) + .onChange(data => { + this.plugin.settings.imageFolder = data; + void this.plugin.saveSettings(); + }); + }); + // Create a map to store APIs for each media type const mediaTypeApiMap = new Map(); From a615e7f7680ee656e74c165780251edc0dec8ef3 Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sun, 11 May 2025 17:26:51 +0200 Subject: [PATCH 17/19] Updated image url for omdb and steam changed steam to a vertical poster to fit the other posters and upgraded the quality of omdb from SX300 to SX600 --- src/api/apis/OMDbAPI.ts | 6 +++--- src/api/apis/SteamAPI.ts | 13 ++++++++++++- src/utils/Utils.ts | 16 ++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index fb6351d..3afe47f 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -151,7 +151,7 @@ export class OMDbAPI extends APIModel { duration: result.Runtime ?? 'unknown', onlineRating: Number.parseFloat(result.imdbRating ?? 0), actors: result.Actors?.split(', ') ?? [], - image: result.Poster ?? '', + image: result.Poster ? result.Poster.replace('_SX300', '_SX600') : '', released: true, streamingServices: [], @@ -181,7 +181,7 @@ export class OMDbAPI extends APIModel { duration: result.Runtime ?? 'unknown', onlineRating: Number.parseFloat(result.imdbRating ?? 0), actors: result.Actors?.split(', ') ?? [], - image: result.Poster ?? '', + image: result.Poster ? result.Poster.replace('_SX300', '_SX600') : '', released: true, streamingServices: [], @@ -209,7 +209,7 @@ export class OMDbAPI extends APIModel { publishers: [], genres: result.Genre?.split(', ') ?? [], onlineRating: Number.parseFloat(result.imdbRating ?? 0), - image: result.Poster ?? '', + image: result.Poster ? result.Poster.replace('_SX300', '_SX600') : '', released: true, releaseDate: this.plugin.dateFormatter.format(result.Released, this.apiDateFormat) ?? 'unknown', diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts index d3f7c8f..504cc25 100644 --- a/src/api/apis/SteamAPI.ts +++ b/src/api/apis/SteamAPI.ts @@ -4,6 +4,7 @@ import { GameModel } from '../../models/GameModel'; import type { MediaTypeModel } from '../../models/MediaTypeModel'; import { MediaType } from '../../utils/MediaType'; import { APIModel } from '../APIModel'; +import { imageUrlExists } from '../../utils/Utils'; export class SteamAPI extends APIModel { plugin: MediaDbPlugin; @@ -85,6 +86,16 @@ export class SteamAPI extends APIModel { // console.debug(result); + // Check if a poster version of the image exists, else use the header image + const imageUrl = `https://steamcdn-a.akamaihd.net/steam/apps/${result.steam_appid}/library_600x900_2x.jpg`; + const exists = await imageUrlExists(imageUrl); + let finalimageurl; + if (exists) { + finalimageurl = imageUrl; + } else { + finalimageurl = result.header_image ?? ''; + } + return new GameModel({ type: MediaType.Game, title: result.name, @@ -98,7 +109,7 @@ export class SteamAPI extends APIModel { publishers: result.publishers, genres: result.genres?.map((x: any) => x.description) ?? [], onlineRating: Number.parseFloat(result.metacritic?.score ?? 0), - image: result.header_image ?? '', + image: finalimageurl ?? '', released: !result.release_date?.coming_soon, releaseDate: this.plugin.dateFormatter.format(result.release_date?.date, this.apiDateFormat) ?? 'unknown', diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 7950b15..8a28f04 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -234,3 +234,19 @@ export async function useTemplaterPluginInFile(app: App, file: TFile): Promise = { [K in keyof T as T[K] extends Function ? never : K]?: T[K]; }; + +// Checks if a given URL points to an existing image (status 200), or returns false for 404/other errors. + +export async function imageUrlExists(url: string): Promise { + try { + // @ts-ignore + const response = await requestUrl({ + url, + method: 'HEAD', + throw: false, + }); + return response.status === 200; + } catch { + return false; + } +} From 62e0f20634bb27cf6a7c8f65280e30a0b860a8ee Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Sun, 11 May 2025 17:32:57 +0200 Subject: [PATCH 18/19] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b641bb9..79dd6f8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Obsidian Media DB Plugin -A plugin that can query multiple APIs for movies, series, anime, manga, games, music and wiki articles, and import them into your vault. +A plugin that can query multiple APIs for movies, series, anime, manga, books, games, music and wiki articles, and import them into your vault. ### Features @@ -36,6 +36,9 @@ Available variables that can be used in template tags are the same variables fro I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates). +#### Download poster images +Allows you to automatically download the poster images for a new media, ensuring offline access. The images are saved as `type_title (year)` e.g. `movie_The Perfect Storm (2000)` with a user chosen save location. + #### Metadata field customization Allows you to rename the metadata fields this plugin generates through mappings. From 970432dcfb9d6727cd05c208ab9a2eed0c44814a Mon Sep 17 00:00:00 2001 From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com> Date: Mon, 12 May 2025 14:06:02 +0200 Subject: [PATCH 19/19] Reinstated check if file already exists Plugin will no longer download a poster if it already exists, to avoid unnecessary downloads and in case the user has modified the saved image themselves --- README.md | 1 + src/main.ts | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 79dd6f8..dd48ea0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ Available variables that can be used in template tags are the same variables fro I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates). #### Download poster images + Allows you to automatically download the poster images for a new media, ensuring offline access. The images are saved as `type_title (year)` e.g. `movie_The Perfect Storm (2000)` with a user chosen save location. #### Metadata field customization diff --git a/src/main.ts b/src/main.ts index 8240617..6128cd4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -327,9 +327,11 @@ export default class MediaDbPlugin extends Plugin { await this.app.vault.createFolder(this.settings.imageFolder); } - const response = await requestUrl({ url: imageurl, method: 'GET' }); - await this.app.vault.createBinary(imagepath, response.arrayBuffer); - + if (!this.app.vault.getAbstractFileByPath(imagepath)) { + const response = await requestUrl({ url: imageurl, method: 'GET' }); + await this.app.vault.createBinary(imagepath, response.arrayBuffer); + } + // Update model to use local image path mediaTypeModel.image = `[[${imagepath}]]`; } catch (e) {