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/96] 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/96] 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/96] 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 9a521a174f0b65bcf5e2df94f561698c6ce7b7e0 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Wed, 5 Mar 2025 15:57:19 +0100
Subject: [PATCH 04/96] Added confirmation before overwriting an existing note
---
src/main.ts | 13 ++++++--
src/modals/ConfirmOverwriteModal.ts | 46 +++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 2 deletions(-)
create mode 100644 src/modals/ConfirmOverwriteModal.ts
diff --git a/src/main.ts b/src/main.ts
index bdb02bb..1846627 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -13,6 +13,7 @@ import { SteamAPI } from './api/apis/SteamAPI';
import { WikipediaAPI } from './api/apis/WikipediaAPI';
import { ComicVineAPI } from './api/apis/ComicVineAPI';
import { MediaDbFolderImportModal } from './modals/MediaDbFolderImportModal';
+import { ConfirmOverwriteModal } from './modals/ConfirmOverwriteModal';
import type { MediaTypeModel } from './models/MediaTypeModel';
import { PropertyMapper } from './settings/PropertyMapper';
import { PropertyMapping, PropertyMappingModel } from './settings/PropertyMapping';
@@ -508,9 +509,17 @@ export default class MediaDbPlugin extends Plugin {
fileName = replaceIllegalFileNameCharactersInString(fileName);
const filePath = `${folder.path}/${fileName}.md`;
- // find and delete file with the same name
+ // look if file already exists and ask if it should be overwritten
const file = this.app.vault.getAbstractFileByPath(filePath);
if (file) {
+ const shouldOverwrite = await new Promise(resolve => {
+ new ConfirmOverwriteModal(this.app, fileName, resolve).open();
+ });
+
+ if (!shouldOverwrite) {
+ throw new Error('MDB | file creation cancelled by user');
+ }
+
await this.app.vault.delete(file);
}
@@ -518,7 +527,7 @@ export default class MediaDbPlugin extends Plugin {
const targetFile = await this.app.vault.create(filePath, fileContent);
console.debug(`MDB | created new file at ${filePath}`);
- // open newly crated file
+ // open newly created file
if (options.openNote) {
const activeLeaf = this.app.workspace.getUnpinnedLeaf();
if (!activeLeaf) {
diff --git a/src/modals/ConfirmOverwriteModal.ts b/src/modals/ConfirmOverwriteModal.ts
new file mode 100644
index 0000000..501afea
--- /dev/null
+++ b/src/modals/ConfirmOverwriteModal.ts
@@ -0,0 +1,46 @@
+import type { App } from 'obsidian';
+import { Modal, Setting } from 'obsidian';
+
+export class ConfirmOverwriteModal extends Modal {
+ result: boolean = false;
+ onSubmit: (result: boolean) => void;
+ fileName: string;
+
+ constructor(app: App, fileName: string, onSubmit: (result: boolean) => void) {
+ super(app);
+ this.fileName = fileName;
+ this.onSubmit = onSubmit;
+ }
+
+ onOpen() {
+ const { contentEl } = this;
+ contentEl.createEl('h2', { text: 'File already exists' });
+ contentEl.createEl('p', { text: `The file "${this.fileName}" already exists. Do you want to overwrite it?` });
+
+ const buttonContainer = contentEl.createDiv({ cls: 'modal-button-container' });
+
+ new Setting(buttonContainer)
+ .addButton(btn => {
+ btn.setButtonText('Yes');
+ btn.onClick(() => {
+ this.result = true;
+ this.close();
+ });
+ btn.buttonEl.addClass('media-db-plugin-button');
+ })
+ .addButton(btn => {
+ btn.setButtonText('No');
+ btn.onClick(() => {
+ this.result = false;
+ this.close();
+ });
+ btn.buttonEl.addClass('media-db-plugin-button');
+ });
+ }
+
+ onClose() {
+ const { contentEl } = this;
+ contentEl.empty();
+ this.onSubmit(this.result);
+ }
+}
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 05/96] 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 06/96] 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 07/96] 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 08/96] 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 09/96] 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 10/96] 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 11/96] 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 46952218de42ab23a4a3338dfa2cb72af6d0ba59 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Wed, 5 Mar 2025 22:33:30 +0100
Subject: [PATCH 12/96] Changed overwrite confirmation to only appear on new
notes
Overwrite confirmation should only appear if a new note is created, not when updating the metadata for an existing note.
---
src/main.ts | 17 +++++++++--------
src/utils/Utils.ts | 1 +
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/main.ts b/src/main.ts
index 1846627..4803c09 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -512,14 +512,15 @@ export default class MediaDbPlugin extends Plugin {
// look if file already exists and ask if it should be overwritten
const file = this.app.vault.getAbstractFileByPath(filePath);
if (file) {
- const shouldOverwrite = await new Promise(resolve => {
- new ConfirmOverwriteModal(this.app, fileName, resolve).open();
- });
+ if (!options.isUpdating) {
+ const shouldOverwrite = await new Promise(resolve => {
+ new ConfirmOverwriteModal(this.app, fileName, resolve).open();
+ });
- if (!shouldOverwrite) {
- throw new Error('MDB | file creation cancelled by user');
+ if (!shouldOverwrite) {
+ throw new Error('MDB | file creation cancelled by user');
+ }
}
-
await this.app.vault.delete(file);
}
@@ -574,9 +575,9 @@ export default class MediaDbPlugin extends Plugin {
console.debug(`MDB | newMediaTypeModel after merge`, newMediaTypeModel);
if (onlyMetadata) {
- await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachFile: activeFile, folder: activeFile.parent ?? undefined, openNote: true });
+ await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachFile: activeFile, folder: activeFile.parent ?? undefined, openNote: true, isUpdating: true });
} else {
- await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachTemplate: true, folder: activeFile.parent ?? undefined, openNote: true });
+ await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachTemplate: true, folder: activeFile.parent ?? undefined, openNote: true, isUpdating: true });
}
}
diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts
index 7950b15..4e8b82f 100644
--- a/src/utils/Utils.ts
+++ b/src/utils/Utils.ts
@@ -193,6 +193,7 @@ export interface CreateNoteOptions {
attachFile?: TFile;
openNote?: boolean;
folder?: TFolder;
+ isUpdating?: boolean; // New property
}
export function migrateObject(object: T, oldData: any, defaultData: T): void {
From d24b2d727160eaffb237adc4a50cde0fd5bfa71f Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Wed, 5 Mar 2025 22:59:28 +0100
Subject: [PATCH 13/96] Revert "Changed overwrite confirmation to only appear
on new notes"
This reverts commit 46952218de42ab23a4a3338dfa2cb72af6d0ba59.
---
src/main.ts | 17 ++++++++---------
src/utils/Utils.ts | 1 -
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/src/main.ts b/src/main.ts
index 4803c09..1846627 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -512,15 +512,14 @@ export default class MediaDbPlugin extends Plugin {
// look if file already exists and ask if it should be overwritten
const file = this.app.vault.getAbstractFileByPath(filePath);
if (file) {
- if (!options.isUpdating) {
- const shouldOverwrite = await new Promise(resolve => {
- new ConfirmOverwriteModal(this.app, fileName, resolve).open();
- });
+ const shouldOverwrite = await new Promise(resolve => {
+ new ConfirmOverwriteModal(this.app, fileName, resolve).open();
+ });
- if (!shouldOverwrite) {
- throw new Error('MDB | file creation cancelled by user');
- }
+ if (!shouldOverwrite) {
+ throw new Error('MDB | file creation cancelled by user');
}
+
await this.app.vault.delete(file);
}
@@ -575,9 +574,9 @@ export default class MediaDbPlugin extends Plugin {
console.debug(`MDB | newMediaTypeModel after merge`, newMediaTypeModel);
if (onlyMetadata) {
- await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachFile: activeFile, folder: activeFile.parent ?? undefined, openNote: true, isUpdating: true });
+ await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachFile: activeFile, folder: activeFile.parent ?? undefined, openNote: true });
} else {
- await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachTemplate: true, folder: activeFile.parent ?? undefined, openNote: true, isUpdating: true });
+ await this.createMediaDbNoteFromModel(newMediaTypeModel, { attachTemplate: true, folder: activeFile.parent ?? undefined, openNote: true });
}
}
diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts
index 4e8b82f..7950b15 100644
--- a/src/utils/Utils.ts
+++ b/src/utils/Utils.ts
@@ -193,7 +193,6 @@ export interface CreateNoteOptions {
attachFile?: TFile;
openNote?: boolean;
folder?: TFolder;
- isUpdating?: boolean; // New property
}
export function migrateObject(object: T, oldData: any, defaultData: T): void {
From be7598d1011d75402d0ef24259b09176d4f4bc40 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Thu, 6 Mar 2025 13:45:18 +0100
Subject: [PATCH 14/96] Changed button setup for internal consistency
The buttons are now Cancel and Ok rather than Yes and No, they also have the correct order and color for the Ok button
---
src/modals/ConfirmOverwriteModal.ts | 32 ++++++++++++++---------------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/src/modals/ConfirmOverwriteModal.ts b/src/modals/ConfirmOverwriteModal.ts
index 501afea..bab0330 100644
--- a/src/modals/ConfirmOverwriteModal.ts
+++ b/src/modals/ConfirmOverwriteModal.ts
@@ -17,25 +17,23 @@ export class ConfirmOverwriteModal extends Modal {
contentEl.createEl('h2', { text: 'File already exists' });
contentEl.createEl('p', { text: `The file "${this.fileName}" already exists. Do you want to overwrite it?` });
- const buttonContainer = contentEl.createDiv({ cls: 'modal-button-container' });
+ contentEl.createDiv({ cls: 'media-db-plugin-spacer' });
- new Setting(buttonContainer)
- .addButton(btn => {
- btn.setButtonText('Yes');
- btn.onClick(() => {
- this.result = true;
- this.close();
- });
- btn.buttonEl.addClass('media-db-plugin-button');
- })
- .addButton(btn => {
- btn.setButtonText('No');
- btn.onClick(() => {
- this.result = false;
- this.close();
- });
- btn.buttonEl.addClass('media-db-plugin-button');
+ const bottomSettingRow = new Setting(contentEl);
+ bottomSettingRow.addButton(btn => {
+ btn.setButtonText('Cancel');
+ btn.onClick(() => this.close());
+ btn.buttonEl.addClass('media-db-plugin-button');
+ });
+ bottomSettingRow.addButton(btn => {
+ btn.setButtonText('Ok');
+ btn.setCta();
+ btn.onClick(() => {
+ this.result = true;
+ this.close();
});
+ btn.buttonEl.addClass('media-db-plugin-button');
+ });
}
onClose() {
From 9f37561396bcf29c2bb5f7f46d9322c324ce814b Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Fri, 7 Mar 2025 15:27:38 +0100
Subject: [PATCH 15/96] Changed back to No and Yes
---
src/modals/ConfirmOverwriteModal.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/modals/ConfirmOverwriteModal.ts b/src/modals/ConfirmOverwriteModal.ts
index bab0330..7da0c17 100644
--- a/src/modals/ConfirmOverwriteModal.ts
+++ b/src/modals/ConfirmOverwriteModal.ts
@@ -21,12 +21,12 @@ export class ConfirmOverwriteModal extends Modal {
const bottomSettingRow = new Setting(contentEl);
bottomSettingRow.addButton(btn => {
- btn.setButtonText('Cancel');
+ btn.setButtonText('No');
btn.onClick(() => this.close());
btn.buttonEl.addClass('media-db-plugin-button');
});
bottomSettingRow.addButton(btn => {
- btn.setButtonText('Ok');
+ btn.setButtonText('Yes');
btn.setCta();
btn.onClick(() => {
this.result = true;
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 16/96] 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 17/96] 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 18/96] 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 19/96] "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 20/96] 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 21/96] 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 22/96] 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 23/96] 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 24/96] 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) {
From db444c83f5154a3e46c4a2f0a3e4eaad9979f720 Mon Sep 17 00:00:00 2001
From: Moritz Jung
Date: Tue, 20 May 2025 12:11:35 +0200
Subject: [PATCH 25/96] refactor image download into method
---
src/main.ts | 61 +++++++++++++++++++++++++++++++----------------------
1 file changed, 36 insertions(+), 25 deletions(-)
diff --git a/src/main.ts b/src/main.ts
index 781ee1f..97344f1 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -316,31 +316,8 @@ 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);
- }
-
- 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) {
- console.warn('MDB | Failed to download image:', e);
- }
- } else {
- mediaTypeModel.image = mediaTypeModel.image;
- }
+ if (this.settings.imageDownload) {
+ await this.downloadImageForMediaModel(mediaTypeModel);
}
const fileContent = await this.generateMediaDbNoteContents(mediaTypeModel, options);
@@ -360,6 +337,40 @@ export default class MediaDbPlugin extends Plugin {
}
}
+ /**
+ * Tries to download the image for a media model.
+ *
+ * @param mediaTypeModel
+ * @returns true if the image was downloaded, false otherwise
+ */
+ private async downloadImageForMediaModel(mediaTypeModel: MediaTypeModel): Promise {
+ if (mediaTypeModel.image && typeof mediaTypeModel.image === 'string' && mediaTypeModel.image.startsWith('http')) {
+ 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);
+ }
+
+ 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}]]`;
+ return true;
+ } catch (e) {
+ console.warn('MDB | Failed to download image:', e);
+ }
+ }
+
+ return false;
+ }
+
generateMediaDbNoteFrontmatterPreview(mediaTypeModel: MediaTypeModel): string {
const fileMetadata = this.modelPropertyMapper.convertObject(mediaTypeModel.toMetaDataObject());
return stringifyYaml(fileMetadata);
From 8792fed9a3c1d60ffbdbee6fff77e260c4464510 Mon Sep 17 00:00:00 2001
From: Moritz Jung
Date: Sun, 15 Jun 2025 21:25:00 +0200
Subject: [PATCH 26/96] [auto] run release preconditions
---
src/main.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/main.ts b/src/main.ts
index 97344f1..4d7392e 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -339,8 +339,8 @@ export default class MediaDbPlugin extends Plugin {
/**
* Tries to download the image for a media model.
- *
- * @param mediaTypeModel
+ *
+ * @param mediaTypeModel
* @returns true if the image was downloaded, false otherwise
*/
private async downloadImageForMediaModel(mediaTypeModel: MediaTypeModel): Promise {
From 9518ede41c53c9f4866f2b483356fb0f954aa96c Mon Sep 17 00:00:00 2001
From: Moritz Jung
Date: Sun, 15 Jun 2025 21:25:05 +0200
Subject: [PATCH 27/96] [auto] bump version to `0.8.0-canary.20250615T192500`
---
manifest-beta.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/manifest-beta.json b/manifest-beta.json
index a8d101f..41961e9 100644
--- a/manifest-beta.json
+++ b/manifest-beta.json
@@ -1,7 +1,7 @@
{
"id": "obsidian-media-db-plugin",
"name": "Media DB",
- "version": "0.8.0",
+ "version": "0.8.0-canary.20250615T192500",
"minAppVersion": "1.5.0",
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.",
"author": "Moritz Jung",
From 8a392e5e4e274d28175cd78008b757e6709e40ce Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Fri, 27 Jun 2025 00:59:45 +0200
Subject: [PATCH 28/96] Improved openlibrary API + updated readme
Fixed missing ratings, page numbers and also added an option to add specific editions using search by ID, this method also enables you to search by isbn ID.
---
README.md | 6 ++++--
src/api/apis/OpenLibraryAPI.ts | 6 +++---
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index dd48ea0..0ffd6aa 100644
--- a/README.md
+++ b/README.md
@@ -162,9 +162,11 @@ Now you select the result you want and the plugin will cast it's magic and creat
- you can find this ID in the URL
- e.g. for "Factorio" the URL looks like this `https://store.steampowered.com/app/427520/Factorio/` so the ID is `427520`
- [Open Library](https://openlibrary.org)
- - The ID you need is the "work" ID and not the "book" ID, it needs to start with `/works/`. You can find this ID in the URL
- - e.g. for "Fantastic Mr. Fox" the URL looks like this `https://openlibrary.org/works/OL45804W` so the ID is `/works/OL45804W`
+ - The ID can either be the "/work/" ID, the "/book/" ID, or the "/isbn/" ID it needs to start with `/works/`. You can find this ID in the URL
+ - e.g. for "Fantastic Mr. Fox" the "/works/" URL looks like this `https://openlibrary.org/works/OL45804W` so the ID is `/works/OL45804W`
- This URL is located near the top of the page above the title, see `An edition of Fantastic Mr Fox (1970) `
+ - For a specific edition of "Fantastic Mr. Fox" the "/books/" URL looks like this `https://openlibrary.org/books/OL3567303M/` so the ID is `/books/OL3567303M`
+ - This URL is located in the editions section`
- [Moby Games](https://www.mobygames.com)
- you can find this ID in the URL
- e.g. for "Bioshock 2" the URL looks like this `https://www.mobygames.com/game/45089/bioshock-2/` so the ID is `45089`
diff --git a/src/api/apis/OpenLibraryAPI.ts b/src/api/apis/OpenLibraryAPI.ts
index 78eb301..45383f1 100644
--- a/src/api/apis/OpenLibraryAPI.ts
+++ b/src/api/apis/OpenLibraryAPI.ts
@@ -52,7 +52,7 @@ export class OpenLibraryAPI extends APIModel {
async getById(id: string): Promise {
console.log(`MDB | api "${this.apiName}" queried by ID`);
- const searchUrl = `https://openlibrary.org/search.json?q=key:${encodeURIComponent(id)}`;
+ const searchUrl = `https://openlibrary.org/search.json?q=${encodeURIComponent(id)}&fields=key,title,author_name,number_of_pages_median,first_publish_year,isbn,ratings_score,first_sentence,title_suggest,rating*,cover_edition_key`;
const fetchData = await fetch(searchUrl);
// console.debug(fetchData);
@@ -68,8 +68,8 @@ export class OpenLibraryAPI extends APIModel {
title: result.title,
year: result.first_publish_year,
dataSource: this.apiName,
- url: `https://openlibrary.org` + result.key,
- id: result.key,
+ url: `https://openlibrary.org` + data.q,
+ id: data.q,
isbn: (result.isbn ?? []).find((el: string | any[]) => el.length <= 10) ?? 'unknown',
isbn13: (result.isbn ?? []).find((el: string | any[]) => el.length == 13) ?? 'unknown',
englishTitle: result.title_english ?? result.title,
From f867f42793e7958b5ed101dafe52eddf1f71c828 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Fri, 27 Jun 2025 01:03:01 +0200
Subject: [PATCH 29/96] Update README.md
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 0ffd6aa..0bf4914 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
## Obsidian Media DB Plugin
-A plugin that can query multiple APIs for movies, series, anime, manga, books, games, music and wiki articles, and import them into your vault.
+A plugin that can query multiple APIs for movies, series, anime, manga, books, comics, games, music and wiki articles, and import them into your vault.
### Features
#### Search by Title
-Search a movie, series, anime, game, music release or wiki article by its name across multiple APIs.
+Search a movie, series, anime, manga, book, comic, game, music or wiki articles by its name across multiple APIs.
#### Search by ID
@@ -164,9 +164,9 @@ Now you select the result you want and the plugin will cast it's magic and creat
- [Open Library](https://openlibrary.org)
- The ID can either be the "/work/" ID, the "/book/" ID, or the "/isbn/" ID it needs to start with `/works/`. You can find this ID in the URL
- e.g. for "Fantastic Mr. Fox" the "/works/" URL looks like this `https://openlibrary.org/works/OL45804W` so the ID is `/works/OL45804W`
- - This URL is located near the top of the page above the title, see `An edition of Fantastic Mr Fox (1970) `
+ - This URL is located near the top of the page above the title, see `An edition of Fantastic Mr Fox (1970) `
- For a specific edition of "Fantastic Mr. Fox" the "/books/" URL looks like this `https://openlibrary.org/books/OL3567303M/` so the ID is `/books/OL3567303M`
- - This URL is located in the editions section`
+ - This URL is located in the editions section`
- [Moby Games](https://www.mobygames.com)
- you can find this ID in the URL
- e.g. for "Bioshock 2" the URL looks like this `https://www.mobygames.com/game/45089/bioshock-2/` so the ID is `45089`
From c3df1f582f3213f22385e654cf4db0f282602201 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Fri, 27 Jun 2025 01:14:10 +0200
Subject: [PATCH 30/96] Re-added music release
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0bf4914..536c900 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ A plugin that can query multiple APIs for movies, series, anime, manga, books, c
#### Search by Title
-Search a movie, series, anime, manga, book, comic, game, music or wiki articles by its name across multiple APIs.
+Search a movie, series, anime, manga, book, comic, game, music release or wiki articles by its name across multiple APIs.
#### Search by ID
From 74acf7f914ee9db502e46d1ad9cb86f93f47449b Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Fri, 27 Jun 2025 16:04:48 +0200
Subject: [PATCH 31/96] Small fix for musicbrainzapi
Added .jpg to the poster url so the posters can be downloaded by the plugin
---
src/api/apis/MusicBrainzAPI.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts
index 022d944..c67e820 100644
--- a/src/api/apis/MusicBrainzAPI.ts
+++ b/src/api/apis/MusicBrainzAPI.ts
@@ -51,7 +51,7 @@ export class MusicBrainzAPI extends APIModel {
dataSource: this.apiName,
url: 'https://musicbrainz.org/release-group/' + result.id,
id: result.id,
- image: 'https://coverartarchive.org/release-group/' + result.id + '/front',
+ image: 'https://coverartarchive.org/release-group/' + result.id + '/front.jpg',
artists: result['artist-credit'].map((a: any) => a.name),
subType: result['primary-type'],
@@ -87,7 +87,7 @@ export class MusicBrainzAPI extends APIModel {
dataSource: this.apiName,
url: 'https://musicbrainz.org/release-group/' + result.id,
id: result.id,
- image: 'https://coverartarchive.org/release-group/' + result.id + '/front',
+ image: 'https://coverartarchive.org/release-group/' + result.id + '/front.jpg',
artists: result['artist-credit'].map((a: any) => a.name),
genres: result.genres.map((g: any) => g.name),
From 12596573b3e72e187ba69fb19a6b8979c7f83dd4 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Tue, 1 Jul 2025 01:40:44 +0200
Subject: [PATCH 32/96] Added plot/description to openlibraryAPI when available
---
src/api/apis/OpenLibraryAPI.ts | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/api/apis/OpenLibraryAPI.ts b/src/api/apis/OpenLibraryAPI.ts
index 45383f1..7279206 100644
--- a/src/api/apis/OpenLibraryAPI.ts
+++ b/src/api/apis/OpenLibraryAPI.ts
@@ -3,6 +3,7 @@ import type MediaDbPlugin from '../../main';
import type { MediaTypeModel } from '../../models/MediaTypeModel';
import { MediaType } from '../../utils/MediaType';
import { APIModel } from '../APIModel';
+import { requestUrl } from 'obsidian';
export class OpenLibraryAPI extends APIModel {
plugin: MediaDbPlugin;
@@ -53,14 +54,24 @@ export class OpenLibraryAPI extends APIModel {
console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `https://openlibrary.org/search.json?q=${encodeURIComponent(id)}&fields=key,title,author_name,number_of_pages_median,first_publish_year,isbn,ratings_score,first_sentence,title_suggest,rating*,cover_edition_key`;
- const fetchData = await fetch(searchUrl);
+ const fetchData = await requestUrl({
+ url: searchUrl,
+ });
+ const descriptionUrl = `https://openlibrary.org/${encodeURIComponent(id)}.json`;
+ const fetchDescription = await requestUrl({
+ url: descriptionUrl,
+ });
// console.debug(fetchData);
if (fetchData.status !== 200) {
throw Error(`MDB | Received status code ${fetchData.status} from ${this.apiName}.`);
}
+ if (fetchDescription.status !== 200) {
+ throw Error(`MDB | Received status code ${fetchDescription.status} from ${this.apiName}.`);
+ }
- const data = await fetchData.json();
+ const data = await fetchData.json;
+ const resultdesc = await fetchDescription.json;
// console.debug(data);
const result = data.docs[0];
@@ -75,7 +86,7 @@ export class OpenLibraryAPI extends APIModel {
englishTitle: result.title_english ?? result.title,
author: result.author_name ?? 'unknown',
- plot: result.description ?? 'unknown',
+ plot: resultdesc.description?.value ?? 'unknown',
pages: result.number_of_pages_median ?? 'unknown',
onlineRating: Number.parseFloat(Number(result.ratings_average ?? 0).toFixed(2)),
image: `https://covers.openlibrary.org/b/OLID/` + result.cover_edition_key + `-L.jpg`,
From e17271b8e95fa6d307c058a54ab8db910f4f0922 Mon Sep 17 00:00:00 2001
From: ltctceplrm <14954927+ltctceplrm@users.noreply.github.com>
Date: Sat, 19 Jul 2025 14:27:58 +0200
Subject: [PATCH 33/96] Fix property mapping text box
---
.../PropertyMappingModelComponent.svelte | 16 ++++------------
.../PropertyMappingModelsComponent.svelte | 8 ++------
2 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/src/settings/PropertyMappingModelComponent.svelte b/src/settings/PropertyMappingModelComponent.svelte
index 0018d75..483854a 100644
--- a/src/settings/PropertyMappingModelComponent.svelte
+++ b/src/settings/PropertyMappingModelComponent.svelte
@@ -1,22 +1,14 @@