From 16299fecedc14afd68af4eb7626ac752899f4972 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Thu, 19 May 2022 22:59:01 +0200 Subject: [PATCH 1/8] Update entry command --- src/main.ts | 42 +++++++++++++++++++++++++++++++-- src/models/GameModel.ts | 3 +++ src/models/MediaTypeModel.ts | 2 ++ src/models/MovieModel.ts | 3 +++ src/models/MusicReleaseModel.ts | 4 +++- src/models/SeriesModel.ts | 3 +++ src/models/WikiModel.ts | 3 +++ src/utils/Utils.ts | 5 ++++ 8 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 69c713b..b5ddbfd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -37,6 +37,12 @@ export default class MediaDbPlugin extends Plugin { callback: () => this.createMediaDbNote(this.openMediaDbIdSearchModal.bind(this)), }); + this.addCommand({ + id: 'update-media-db-note', + name: 'Update the open note, if it is a Media DB entry.', + callback: () => this.updateActiveNote(), + }); + // register the settings tab this.addSettingTab(new MediaDbSettingTab(this.app, this)); @@ -53,10 +59,18 @@ export default class MediaDbPlugin extends Plugin { async createMediaDbNote(modal: () => Promise): Promise { try { let data: MediaTypeModel = await modal(); - console.log('MDB | Creating new note...'); - data = await this.apiManager.queryDetailedInfo(data); + await this.createMediaDbNoteFromModel(data); + } catch (e) { + console.warn(e); + new Notice(e.toString()); + } + } + + async createMediaDbNoteFromModel(data: MediaTypeModel): Promise { + try { + console.log('MDB | Creating new note...'); // console.log(data); let fileContent = `---\n${data.toMetaData()}---\n`; @@ -86,6 +100,8 @@ export default class MediaDbPlugin extends Plugin { const fileName = replaceIllegalFileNameCharactersInString(data.getFileName()); const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`; + + await this.app.vault.delete(this.app.vault.getAbstractFileByPath(filePath)); const targetFile = await this.app.vault.create(filePath, fileContent); // open file @@ -95,6 +111,7 @@ export default class MediaDbPlugin extends Plugin { return; } await activeLeaf.openFile(targetFile, {state: {mode: 'source'}}); + } catch (e) { console.warn(e); new Notice(e.toString()); @@ -122,6 +139,27 @@ export default class MediaDbPlugin extends Plugin { })); } + async updateActiveNote() { + const activeLeaf: TFile = this.app.workspace.getActiveFile(); + if (!activeLeaf.name) return; + + let metadata = this.app.metadataCache.getFileCache(activeLeaf).frontmatter; + + if (!metadata.type || !metadata.dataSource || !metadata.id) { + throw new Error('MDB | active note is not a Media DB entry or is missing metadata'); + } + + const newMetadata = await this.apiManager.queryDetailedInfo({dataSource: metadata.dataSource, id: metadata.id} as MediaTypeModel); + + if (!newMetadata) { + return; + } + + console.log('MDB | deleting old entry'); + await this.app.vault.delete(activeLeaf); + await this.createMediaDbNoteFromModel(newMetadata); + } + async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); } diff --git a/src/models/GameModel.ts b/src/models/GameModel.ts index 8a807ba..47f8c91 100644 --- a/src/models/GameModel.ts +++ b/src/models/GameModel.ts @@ -5,6 +5,7 @@ import {mediaDbTag} from '../utils/Utils'; export class GameModel extends MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -27,6 +28,8 @@ export class GameModel extends MediaTypeModel { super(); Object.assign(this, obj); + + this.type = 'game'; } toMetaData(): string { diff --git a/src/models/MediaTypeModel.ts b/src/models/MediaTypeModel.ts index 4963fb5..12490b0 100644 --- a/src/models/MediaTypeModel.ts +++ b/src/models/MediaTypeModel.ts @@ -1,5 +1,6 @@ export abstract class MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -12,4 +13,5 @@ export abstract class MediaTypeModel { abstract getFileName(): string; abstract getTags(): string[]; + } diff --git a/src/models/MovieModel.ts b/src/models/MovieModel.ts index e0ff845..777ff1f 100644 --- a/src/models/MovieModel.ts +++ b/src/models/MovieModel.ts @@ -5,6 +5,7 @@ import {mediaDbTag} from '../utils/Utils'; export class MovieModel extends MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -30,6 +31,8 @@ export class MovieModel extends MediaTypeModel { super(); Object.assign(this, obj); + + this.type = 'movie'; } toMetaData(): string { diff --git a/src/models/MusicReleaseModel.ts b/src/models/MusicReleaseModel.ts index 2561cf0..eb0dec4 100644 --- a/src/models/MusicReleaseModel.ts +++ b/src/models/MusicReleaseModel.ts @@ -5,6 +5,7 @@ import {mediaDbTag} from '../utils/Utils'; export class MusicReleaseModel extends MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -14,7 +15,6 @@ export class MusicReleaseModel extends MediaTypeModel { genres: string[]; artists: string[]; - subType: string; rating: number; personalRating: number; @@ -23,6 +23,8 @@ export class MusicReleaseModel extends MediaTypeModel { super(); Object.assign(this, obj); + + this.type = 'musicRelease'; } toMetaData(): string { diff --git a/src/models/SeriesModel.ts b/src/models/SeriesModel.ts index 205d51a..4d10829 100644 --- a/src/models/SeriesModel.ts +++ b/src/models/SeriesModel.ts @@ -5,6 +5,7 @@ import {mediaDbTag} from '../utils/Utils'; export class SeriesModel extends MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -33,6 +34,8 @@ export class SeriesModel extends MediaTypeModel { super(); Object.assign(this, obj); + + this.type = 'series'; } toMetaData(): string { diff --git a/src/models/WikiModel.ts b/src/models/WikiModel.ts index cf5dea5..9ee6508 100644 --- a/src/models/WikiModel.ts +++ b/src/models/WikiModel.ts @@ -5,6 +5,7 @@ import {mediaDbTag} from '../utils/Utils'; export class WikiModel extends MediaTypeModel { type: string; + subType: string; title: string; englishTitle: string; year: string; @@ -21,6 +22,8 @@ export class WikiModel extends MediaTypeModel { super(); Object.assign(this, obj); + + this.type = 'wiki'; } toMetaData(): string { diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 12927db..e93764c 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,4 +1,5 @@ import {MediaTypeModel} from '../models/MediaTypeModel'; +import {TFile} from 'obsidian'; export const pluginName: string = 'obsidian-media-db-plugin'; @@ -85,3 +86,7 @@ function traverseMetaData(path: Array, mediaTypeModel: MediaTypeModel): return o; } + +export function updateNote(file: TFile) { + +} From 2c570943323466fe535e5f9b5d2144ef73c46653 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Sun, 22 May 2022 12:59:14 +0200 Subject: [PATCH 2/8] Templates for file names #8 --- src/main.ts | 44 +++------ src/modals/MediaDbAdvancedSearchModal.ts | 14 +-- src/modals/MediaDbIdSearchModal.ts | 12 +-- src/modals/MediaDbSearchResultModal.ts | 9 +- src/models/GameModel.ts | 16 ++-- src/models/MediaTypeModel.ts | 11 ++- src/models/MovieModel.ts | 16 ++-- src/models/MusicReleaseModel.ts | 16 ++-- src/models/SeriesModel.ts | 16 ++-- src/models/WikiModel.ts | 16 ++-- src/settings/Settings.ts | 111 ++++++++++++++++++++--- src/utils/MediaType.ts | 7 ++ src/utils/MediaTypeManager.ts | 52 +++++++++++ src/utils/Utils.ts | 6 -- 14 files changed, 231 insertions(+), 115 deletions(-) create mode 100644 src/utils/MediaType.ts create mode 100644 src/utils/MediaTypeManager.ts diff --git a/src/main.ts b/src/main.ts index b5ddbfd..e5795eb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ import {Notice, Plugin, TFile} from 'obsidian'; import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings'; import {APIManager} from './api/APIManager'; import {MediaTypeModel} from './models/MediaTypeModel'; -import {replaceIllegalFileNameCharactersInString, replaceTags} from './utils/Utils'; +import {replaceIllegalFileNameCharactersInString} from './utils/Utils'; import {OMDbAPI} from './api/apis/OMDbAPI'; import {MediaDbAdvancedSearchModal} from './modals/MediaDbAdvancedSearchModal'; import {MediaDbSearchResultModal} from './modals/MediaDbSearchResultModal'; @@ -10,10 +10,12 @@ import {MALAPI} from './api/apis/MALAPI'; import {MediaDbIdSearchModal} from './modals/MediaDbIdSearchModal'; import {WikipediaAPI} from './api/apis/WikipediaAPI'; import {MusicBrainzAPI} from './api/apis/MusicBrainzAPI'; +import {MediaTypeManager} from './utils/MediaTypeManager'; export default class MediaDbPlugin extends Plugin { settings: MediaDbPluginSettings; apiManager: APIManager; + mediaTypeManager: MediaTypeManager; async onload() { await this.loadSettings(); @@ -54,6 +56,8 @@ export default class MediaDbPlugin extends Plugin { this.apiManager.registerAPI(new WikipediaAPI(this)); this.apiManager.registerAPI(new MusicBrainzAPI(this)); // this.apiManager.registerAPI(new LocGovAPI(this)); // TODO: parse data + + this.mediaTypeManager = new MediaTypeManager(this.settings); } async createMediaDbNote(modal: () => Promise): Promise { @@ -68,37 +72,18 @@ export default class MediaDbPlugin extends Plugin { } } - async createMediaDbNoteFromModel(data: MediaTypeModel): Promise { + async createMediaDbNoteFromModel(mediaTypeModel: MediaTypeModel): Promise { try { console.log('MDB | Creating new note...'); - // console.log(data); + // console.log(mediaTypeModel); - let fileContent = `---\n${data.toMetaData()}---\n`; + let fileContent = `---\n${mediaTypeModel.toMetaData()}---\n`; - let templateFile: TFile = null; - - if (data.type === 'movie' && this.settings.movieTemplate) { - templateFile = this.app.vault.getFiles().filter((f: TFile) => f.name === this.settings.movieTemplate).first(); - } else if (data.type === 'series' && this.settings.seriesTemplate) { - templateFile = this.app.vault.getFiles().filter((f: TFile) => f.name === this.settings.seriesTemplate).first(); - } else if (data.type === 'game' && this.settings.gameTemplate) { - templateFile = this.app.vault.getFiles().filter((f: TFile) => f.name === this.settings.gameTemplate).first(); - } else if (data.type === 'wiki' && this.settings.wikiTemplate) { - templateFile = this.app.vault.getFiles().filter((f: TFile) => f.name === this.settings.wikiTemplate).first(); - } else if (data.type === 'musicRelease' && this.settings.musicReleaseTemplate) { - templateFile = this.app.vault.getFiles().filter((f: TFile) => f.name === this.settings.musicReleaseTemplate).first(); + if (this.settings.templates) { + fileContent += await this.mediaTypeManager.getContent(mediaTypeModel, this.app); } - if (templateFile) { - let template = await this.app.vault.cachedRead(templateFile); - // console.log(template); - if (this.settings.templates) { - template = replaceTags(template, data); - } - fileContent += template; - } - - const fileName = replaceIllegalFileNameCharactersInString(data.getFileName()); + const fileName = replaceIllegalFileNameCharactersInString(this.mediaTypeManager.getFileName(mediaTypeModel)); const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`; await this.app.vault.delete(this.app.vault.getAbstractFileByPath(filePath)); @@ -120,9 +105,9 @@ export default class MediaDbPlugin extends Plugin { async openMediaDbSearchModal(): Promise { return new Promise(((resolve, reject) => { - new MediaDbAdvancedSearchModal(this.app, this.apiManager, (err, results) => { + new MediaDbAdvancedSearchModal(this.app, this, (err, results) => { if (err) return reject(err); - new MediaDbSearchResultModal(this.app, results, (err2, res) => { + new MediaDbSearchResultModal(this.app, this, results, (err2, res) => { if (err2) return reject(err2); resolve(res); }).open(); @@ -132,7 +117,7 @@ export default class MediaDbPlugin extends Plugin { async openMediaDbIdSearchModal(): Promise { return new Promise(((resolve, reject) => { - new MediaDbIdSearchModal(this.app, this.apiManager, (err, res) => { + new MediaDbIdSearchModal(this.app, this, (err, res) => { if (err) return reject(err); resolve(res); }).open(); @@ -165,6 +150,7 @@ export default class MediaDbPlugin extends Plugin { } async saveSettings() { + this.mediaTypeManager.updateTemplates(this.settings); await this.saveData(this.settings); } } diff --git a/src/modals/MediaDbAdvancedSearchModal.ts b/src/modals/MediaDbAdvancedSearchModal.ts index 1472f7d..c878e61 100644 --- a/src/modals/MediaDbAdvancedSearchModal.ts +++ b/src/modals/MediaDbAdvancedSearchModal.ts @@ -1,22 +1,22 @@ import {App, ButtonComponent, Component, Modal, Notice, Setting, TextComponent, ToggleComponent} from 'obsidian'; import {MediaTypeModel} from '../models/MediaTypeModel'; -import {APIManager} from '../api/APIManager'; import {debugLog} from '../utils/Utils'; +import MediaDbPlugin from '../main'; export class MediaDbAdvancedSearchModal extends Modal { query: string; isBusy: boolean; - apiManager: APIManager; + plugin: MediaDbPlugin; searchBtn: ButtonComponent; selectedApis: any; onSubmit: (err: Error, result?: MediaTypeModel[]) => void; - constructor(app: App, apiManager: APIManager, onSubmit?: (err: Error, result?: MediaTypeModel[]) => void) { + constructor(app: App, plugin: MediaDbPlugin, onSubmit?: (err: Error, result?: MediaTypeModel[]) => void) { super(app); - this.apiManager = apiManager; + this.plugin = plugin; this.onSubmit = onSubmit; this.selectedApis = []; - for (const api of this.apiManager.apis) { + for (const api of this.plugin.apiManager.apis) { this.selectedApis[api.apiName] = false; } } @@ -56,7 +56,7 @@ export class MediaDbAdvancedSearchModal extends Modal { console.log(`MDB | query started with title ${this.query}`); - const res = await this.apiManager.query(this.query, this.selectedApis); + const res = await this.plugin.apiManager.query(this.query, this.selectedApis); this.onSubmit(null, res); } catch (e) { this.onSubmit(e); @@ -84,7 +84,7 @@ export class MediaDbAdvancedSearchModal extends Modal { contentEl.createEl('h3', {text: 'APIs to search'}); const apiToggleComponents: Component[] = []; - for (const api of this.apiManager.apis) { + for (const api of this.plugin.apiManager.apis) { const apiToggleListElementWrapper = contentEl.createEl('div', {cls: 'media-db-plugin-list-wrapper'}); const apiToggleTextWrapper = apiToggleListElementWrapper.createEl('div', {cls: 'media-db-plugin-list-text-wrapper'}); diff --git a/src/modals/MediaDbIdSearchModal.ts b/src/modals/MediaDbIdSearchModal.ts index 0216746..d7dc4cb 100644 --- a/src/modals/MediaDbIdSearchModal.ts +++ b/src/modals/MediaDbIdSearchModal.ts @@ -1,19 +1,19 @@ import {App, ButtonComponent, DropdownComponent, Modal, Notice, Setting, TextComponent} from 'obsidian'; import {MediaTypeModel} from '../models/MediaTypeModel'; -import {APIManager} from '../api/APIManager'; import {debugLog} from '../utils/Utils'; +import MediaDbPlugin from '../main'; export class MediaDbIdSearchModal extends Modal { query: string; isBusy: boolean; - apiManager: APIManager; + plugin: MediaDbPlugin; searchBtn: ButtonComponent; selectedApi: string; onSubmit: (err: Error, result?: MediaTypeModel) => void; - constructor(app: App, apiManager: APIManager, onSubmit?: (err: Error, result?: MediaTypeModel) => void) { + constructor(app: App, plugin: MediaDbPlugin, onSubmit?: (err: Error, result?: MediaTypeModel) => void) { super(app); - this.apiManager = apiManager; + this.plugin = plugin; this.onSubmit = onSubmit; this.selectedApi = ''; } @@ -46,7 +46,7 @@ export class MediaDbIdSearchModal extends Modal { console.log(`MDB | query started with id ${this.query}`); - const api = this.apiManager.getApiByName(this.selectedApi); + const api = this.plugin.apiManager.getApiByName(this.selectedApi); if (!api) { this.onSubmit(new Error('the selected api does not exist')); } @@ -83,7 +83,7 @@ export class MediaDbIdSearchModal extends Modal { apiSelectorComponent.onChange((value: string) => { this.selectedApi = value; }); - for (const api of this.apiManager.apis) { + for (const api of this.plugin.apiManager.apis) { apiSelectorComponent.addOption(api.apiName, api.apiName); } apiSelectorWrapper.appendChild(apiSelectorComponent.selectEl); diff --git a/src/modals/MediaDbSearchResultModal.ts b/src/modals/MediaDbSearchResultModal.ts index 40f5dca..7cab85f 100644 --- a/src/modals/MediaDbSearchResultModal.ts +++ b/src/modals/MediaDbSearchResultModal.ts @@ -1,12 +1,15 @@ import {App, SuggestModal} from 'obsidian'; import {MediaTypeModel} from '../models/MediaTypeModel'; +import MediaDbPlugin from '../main'; export class MediaDbSearchResultModal extends SuggestModal { suggestion: MediaTypeModel[]; + plugin: MediaDbPlugin; onChoose: (error: Error, result?: MediaTypeModel) => void; - constructor(app: App, suggestion: MediaTypeModel[], onChoose: (error: Error, result?: MediaTypeModel) => void) { + constructor(app: App, plugin: MediaDbPlugin, suggestion: MediaTypeModel[], onChoose: (error: Error, result?: MediaTypeModel) => void) { super(app); + this.plugin = plugin; this.suggestion = suggestion; this.onChoose = onChoose; } @@ -20,9 +23,9 @@ export class MediaDbSearchResultModal extends SuggestModal { // Renders each suggestion item. renderSuggestion(item: MediaTypeModel, el: HTMLElement) { - el.createEl('div', {text: item.getFileName()}); + el.createEl('div', {text: this.plugin.mediaTypeManager.getFileName(item)}); el.createEl('small', {text: `${item.englishTitle}\n`}); - el.createEl('small', {text: `${item.type.toUpperCase()} from ${item.dataSource}`}); + el.createEl('small', {text: `${item.type.toUpperCase() + (item.subType ? ` (${item.subType})` : '')} from ${item.dataSource}`}); } // Perform action on the selected suggestion. diff --git a/src/models/GameModel.ts b/src/models/GameModel.ts index 47f8c91..96bca40 100644 --- a/src/models/GameModel.ts +++ b/src/models/GameModel.ts @@ -1,6 +1,6 @@ import {MediaTypeModel} from './MediaTypeModel'; -import {stringifyYaml} from 'obsidian'; import {mediaDbTag} from '../utils/Utils'; +import {MediaType} from '../utils/MediaType'; export class GameModel extends MediaTypeModel { @@ -29,19 +29,15 @@ export class GameModel extends MediaTypeModel { Object.assign(this, obj); - this.type = 'game'; - } - - toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); - } - - getFileName(): string { - return this.title + (this.year ? ` (${this.year})` : ''); + this.type = this.getMediaType(); } getTags(): string[] { return [mediaDbTag, 'game']; } + getMediaType(): MediaType { + return MediaType.Game; + } + } diff --git a/src/models/MediaTypeModel.ts b/src/models/MediaTypeModel.ts index 12490b0..c73a588 100644 --- a/src/models/MediaTypeModel.ts +++ b/src/models/MediaTypeModel.ts @@ -1,3 +1,6 @@ +import {MediaType} from '../utils/MediaType'; +import {stringifyYaml} from 'obsidian'; + export abstract class MediaTypeModel { type: string; subType: string; @@ -8,10 +11,12 @@ export abstract class MediaTypeModel { url: string; id: string; - abstract toMetaData(): string; - - abstract getFileName(): string; + abstract getMediaType(): MediaType; abstract getTags(): string[]; + toMetaData(): string { + return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); + } + } diff --git a/src/models/MovieModel.ts b/src/models/MovieModel.ts index 777ff1f..c4fe66b 100644 --- a/src/models/MovieModel.ts +++ b/src/models/MovieModel.ts @@ -1,6 +1,6 @@ import {MediaTypeModel} from './MediaTypeModel'; -import {stringifyYaml} from 'obsidian'; import {mediaDbTag} from '../utils/Utils'; +import {MediaType} from '../utils/MediaType'; export class MovieModel extends MediaTypeModel { @@ -32,19 +32,15 @@ export class MovieModel extends MediaTypeModel { Object.assign(this, obj); - this.type = 'movie'; - } - - toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); - } - - getFileName(): string { - return this.title + (this.year ? ` (${this.year})` : ''); + this.type = this.getMediaType(); } getTags(): string[] { return [mediaDbTag, 'tv', 'movie']; } + getMediaType(): MediaType { + return MediaType.Movie; + } + } diff --git a/src/models/MusicReleaseModel.ts b/src/models/MusicReleaseModel.ts index eb0dec4..5edefdc 100644 --- a/src/models/MusicReleaseModel.ts +++ b/src/models/MusicReleaseModel.ts @@ -1,6 +1,6 @@ import {MediaTypeModel} from './MediaTypeModel'; -import {stringifyYaml} from 'obsidian'; import {mediaDbTag} from '../utils/Utils'; +import {MediaType} from '../utils/MediaType'; export class MusicReleaseModel extends MediaTypeModel { @@ -24,19 +24,15 @@ export class MusicReleaseModel extends MediaTypeModel { Object.assign(this, obj); - this.type = 'musicRelease'; - } - - toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); - } - - getFileName(): string { - return this.title + ' (' + this.artists.join(', ') + ' - ' + this.year + ' - ' + this.subType + ')'; + this.type = this.getMediaType(); } getTags(): string[] { return [mediaDbTag, 'music', 'album']; } + getMediaType(): MediaType { + return MediaType.MusicRelease; + } + } diff --git a/src/models/SeriesModel.ts b/src/models/SeriesModel.ts index 4d10829..54afc78 100644 --- a/src/models/SeriesModel.ts +++ b/src/models/SeriesModel.ts @@ -1,6 +1,6 @@ import {MediaTypeModel} from './MediaTypeModel'; -import {stringifyYaml} from 'obsidian'; import {mediaDbTag} from '../utils/Utils'; +import {MediaType} from '../utils/MediaType'; export class SeriesModel extends MediaTypeModel { @@ -35,19 +35,15 @@ export class SeriesModel extends MediaTypeModel { Object.assign(this, obj); - this.type = 'series'; - } - - toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); - } - - getFileName(): string { - return this.title + ' (' + this.year + ')'; + this.type = this.getMediaType(); } getTags(): string[] { return [mediaDbTag, 'tv', 'series']; } + getMediaType(): MediaType { + return MediaType.Series; + } + } diff --git a/src/models/WikiModel.ts b/src/models/WikiModel.ts index 9ee6508..a5dd1b7 100644 --- a/src/models/WikiModel.ts +++ b/src/models/WikiModel.ts @@ -1,6 +1,6 @@ import {MediaTypeModel} from './MediaTypeModel'; -import {stringifyYaml} from 'obsidian'; import {mediaDbTag} from '../utils/Utils'; +import {MediaType} from '../utils/MediaType'; export class WikiModel extends MediaTypeModel { @@ -23,19 +23,15 @@ export class WikiModel extends MediaTypeModel { Object.assign(this, obj); - this.type = 'wiki'; - } - - toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); - } - - getFileName(): string { - return this.title; + this.type = this.getMediaType(); } getTags(): string[] { return [mediaDbTag, 'wiki']; } + getMediaType(): MediaType { + return MediaType.Wiki; + } + } diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index cc8a967..4673dc6 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -9,11 +9,19 @@ export interface MediaDbPluginSettings { folder: string, sfwFilter: boolean, OMDbKey: string, + movieTemplate: string, seriesTemplate: string, gameTemplate: string, wikiTemplate: string, musicReleaseTemplate: string, + + movieFileNameTemplate: string, + seriesFileNameTemplate: string, + gameFileNameTemplate: string, + wikiFileNameTemplate: string, + musicReleaseFileNameTemplate: string, + templates: boolean, } @@ -21,11 +29,19 @@ export const DEFAULT_SETTINGS: MediaDbPluginSettings = { folder: '', sfwFilter: true, OMDbKey: '', + movieTemplate: '', seriesTemplate: '', gameTemplate: '', wikiTemplate: '', musicReleaseTemplate: '', + + movieFileNameTemplate: '{{ title }} ({{ year }})', + seriesFileNameTemplate: '{{ title }} ({{ year }})', + gameFileNameTemplate: '{{ title }} ({{ year }})', + wikiFileNameTemplate: '{{ title }}', + musicReleaseFileNameTemplate: '{{ title }} (by {{ artists.0 }} - {{ year }})', + templates: true, }; @@ -57,6 +73,29 @@ export class MediaDbSettingTab extends PluginSettingTab { }); }); + 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; + 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; + 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.') @@ -68,6 +107,9 @@ export class MediaDbSettingTab extends PluginSettingTab { }); }); + + containerEl.createEl('h3', {text: 'Template Settings'}); + // region templates new Setting(containerEl) .setName('Movie template') .setDesc('Template file to be used when creating a new note for a movie.') @@ -132,29 +174,76 @@ export class MediaDbSettingTab extends PluginSettingTab { this.plugin.saveSettings(); }); }); + // endregion + containerEl.createEl('h3', {text: 'File Name Settings'}); + // region file name templates 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) + .setName('Movie file name template') + .setDesc('Template for the file name used when creating a new note for a movie.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) + .setValue(this.plugin.settings.movieFileNameTemplate) .onChange(data => { - this.plugin.settings.OMDbKey = data; + this.plugin.settings.movieFileNameTemplate = data; 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) + .setName('Series file name template') + .setDesc('Template for the file name used when creating a new note for a series.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) + .setValue(this.plugin.settings.seriesFileNameTemplate) .onChange(data => { - this.plugin.settings.sfwFilter = data; + this.plugin.settings.seriesFileNameTemplate = data; 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.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) + .setValue(this.plugin.settings.gameFileNameTemplate) + .onChange(data => { + this.plugin.settings.gameFileNameTemplate = data; + 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.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) + .setValue(this.plugin.settings.wikiFileNameTemplate) + .onChange(data => { + this.plugin.settings.wikiFileNameTemplate = data; + 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.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) + .setValue(this.plugin.settings.musicReleaseFileNameTemplate) + .onChange(data => { + this.plugin.settings.musicReleaseFileNameTemplate = data; + this.plugin.saveSettings(); + }); + }); + // endregion + } } diff --git a/src/utils/MediaType.ts b/src/utils/MediaType.ts new file mode 100644 index 0000000..c4f1076 --- /dev/null +++ b/src/utils/MediaType.ts @@ -0,0 +1,7 @@ +export enum MediaType { + Movie = 'movie', + Series = 'series', + Game = 'game', + MusicRelease = 'musicRelease', + Wiki = 'wiki', +} diff --git a/src/utils/MediaTypeManager.ts b/src/utils/MediaTypeManager.ts new file mode 100644 index 0000000..d85f14d --- /dev/null +++ b/src/utils/MediaTypeManager.ts @@ -0,0 +1,52 @@ +import {MediaDbPluginSettings} from '../settings/Settings'; +import {MediaType} from './MediaType'; +import {MediaTypeModel} from '../models/MediaTypeModel'; +import {replaceTags} from './Utils'; +import {App, TFile} from 'obsidian'; + +export class MediaTypeManager { + mediaFileNameTemplateMap: Map; + mediaTemplateMap: Map; + + constructor(settings: MediaDbPluginSettings) { + this.updateTemplates(settings); + } + + updateTemplates(settings: MediaDbPluginSettings) { + this.mediaFileNameTemplateMap = new Map(); + this.mediaFileNameTemplateMap.set(MediaType.Movie, settings.movieFileNameTemplate); + this.mediaFileNameTemplateMap.set(MediaType.Series, settings.seriesFileNameTemplate); + this.mediaFileNameTemplateMap.set(MediaType.Game, settings.gameFileNameTemplate); + this.mediaFileNameTemplateMap.set(MediaType.Wiki, settings.wikiFileNameTemplate); + this.mediaFileNameTemplateMap.set(MediaType.MusicRelease, settings.musicReleaseFileNameTemplate); + + this.mediaTemplateMap = new Map(); + this.mediaTemplateMap.set(MediaType.Movie, settings.movieTemplate); + this.mediaTemplateMap.set(MediaType.Series, settings.seriesTemplate); + this.mediaTemplateMap.set(MediaType.Game, settings.gameTemplate); + this.mediaTemplateMap.set(MediaType.Wiki, settings.wikiTemplate); + this.mediaTemplateMap.set(MediaType.MusicRelease, settings.musicReleaseTemplate); + } + + getFileName(mediaTypeModel: MediaTypeModel): string { + return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType()), mediaTypeModel); + } + + async getContent(mediaTypeModel: MediaTypeModel, app: App) { + const templateFileName = this.mediaTemplateMap.get(mediaTypeModel.getMediaType()); + + if (!templateFileName) { + return ''; + } + + const templateFile: TFile = app.vault.getFiles().filter((f: TFile) => f.name === templateFileName).first(); + + if (!templateFile) { + return ''; + } + + const template = await app.vault.cachedRead(templateFile); + // console.log(template); + return replaceTags(template, mediaTypeModel); + } +} diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index e93764c..7c76315 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,5 +1,4 @@ import {MediaTypeModel} from '../models/MediaTypeModel'; -import {TFile} from 'obsidian'; export const pluginName: string = 'obsidian-media-db-plugin'; @@ -8,7 +7,6 @@ export const mediaDbTag: string = 'mediaDB'; export const mediaDbVersion: string = '0.1.8'; export const debug: boolean = false; - export function wrapAround(value: number, size: number): number { return ((value % size) + size) % size; } @@ -86,7 +84,3 @@ function traverseMetaData(path: Array, mediaTypeModel: MediaTypeModel): return o; } - -export function updateNote(file: TFile) { - -} From 3b1e500317f7e4c4b21b6db4211f966e632ec6b5 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Sun, 22 May 2022 23:59:57 +0200 Subject: [PATCH 3/8] Fix file suggest on title template setting --- src/models/MusicReleaseModel.ts | 2 +- src/settings/Settings.ts | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/models/MusicReleaseModel.ts b/src/models/MusicReleaseModel.ts index 5edefdc..10153cc 100644 --- a/src/models/MusicReleaseModel.ts +++ b/src/models/MusicReleaseModel.ts @@ -28,7 +28,7 @@ export class MusicReleaseModel extends MediaTypeModel { } getTags(): string[] { - return [mediaDbTag, 'music', 'album']; + return [mediaDbTag, 'music', this.subType]; } getMediaType(): MediaType { diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 4673dc6..4fb9e95 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -26,7 +26,7 @@ export interface MediaDbPluginSettings { } export const DEFAULT_SETTINGS: MediaDbPluginSettings = { - folder: '', + folder: 'Media DB', sfwFilter: true, OMDbKey: '', @@ -40,7 +40,7 @@ export const DEFAULT_SETTINGS: MediaDbPluginSettings = { seriesFileNameTemplate: '{{ title }} ({{ year }})', gameFileNameTemplate: '{{ title }} ({{ year }})', wikiFileNameTemplate: '{{ title }}', - musicReleaseFileNameTemplate: '{{ title }} (by {{ artists.0 }} - {{ year }})', + musicReleaseFileNameTemplate: '{{ title }} (by {{ ENUM:artists }} - {{ year }})', templates: true, }; @@ -182,7 +182,6 @@ export class MediaDbSettingTab extends PluginSettingTab { .setName('Movie file name template') .setDesc('Template for the file name used when creating a new note for a movie.') .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`) .setValue(this.plugin.settings.movieFileNameTemplate) .onChange(data => { @@ -195,7 +194,6 @@ export class MediaDbSettingTab extends PluginSettingTab { .setName('Series file name template') .setDesc('Template for the file name used when creating a new note for a series.') .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`) .setValue(this.plugin.settings.seriesFileNameTemplate) .onChange(data => { @@ -208,7 +206,6 @@ export class MediaDbSettingTab extends PluginSettingTab { .setName('Game file name template') .setDesc('Template for the file name used when creating a new note for a game.') .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`) .setValue(this.plugin.settings.gameFileNameTemplate) .onChange(data => { @@ -221,7 +218,6 @@ export class MediaDbSettingTab extends PluginSettingTab { .setName('Wiki file name template') .setDesc('Template for the file name used when creating a new note for a wiki entry.') .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`) .setValue(this.plugin.settings.wikiFileNameTemplate) .onChange(data => { @@ -234,7 +230,6 @@ export class MediaDbSettingTab extends PluginSettingTab { .setName('Music Release file name template') .setDesc('Template for the file name used when creating a new note for a music release.') .addSearch(cb => { - new FileSuggest(this.app, cb.inputEl); cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`) .setValue(this.plugin.settings.musicReleaseFileNameTemplate) .onChange(data => { From f6825bbadcaec59a4ec0b5700edc3af505876c49 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Thu, 26 May 2022 20:20:00 +0200 Subject: [PATCH 4/8] Return of the test API and update readme --- README.md | 39 +++++++++++++++++++++++++++++++++++---- src/main.ts | 8 ++++---- src/tests/TestAPI.ts | 27 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 src/tests/TestAPI.ts diff --git a/README.md b/README.md index a37387d..3b49cc3 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ A plugin that can query multiple APIs for movies, series, anime, games, music an ### Features #### Search by Title -Search a movie, series, anime or game by its name across multiple APIs. +Search a movie, series, anime, game, music release or wiki article by its name across multiple APIs. #### Search by ID -Allows you to search by an ID that varies from API to API. Concrete info can be found in the description of the individual APIs. +Allows you to search by an ID that varies from API to API. Concrete information on this feature can be found in the description of the individual APIs. #### Templates The plugin allows you to set a template note that gets added to the end of any note created by this plugin. @@ -27,9 +27,37 @@ For arrays there are two special ways of displaying them. element 1, element 2, element 3, ... ``` +Available variables that can be used in template tags are the same variables from the metadata of the note. I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates). +### How to install +Currently, you have to manually download the zip archive from the latest release here on GitHub. +After downloading, extract the archive into the `.obsidian/plugins` folder in your vault. + +The folder structure should look like this: +``` +[path to your vault] +|_ .obsidian + |_ plugins + |_ obsidian-media-db-plugin + |_ main.js + |_ manifest.json + |_ styles.css +``` + +Once the plugin submission goes through, the plugin will also be installable directly through obsidian's plugin installer. + +### How to use +(pictures are coming) + +Once you have installed this plugin, you will find a database icon in the left ribbon. +When using this or the `Add new Media DB entry` command, a popup will open. +Here you can enter the title of what you want to search for and then select in which APIs to search. + +After clicking search, a new popup will open prompting you to select from the search results. +Now you select the result you want and the plugin will cast it's magic and create a new note in your vault, that contains the metadata of the selected search result. + ### Currently supported media types - movies (including specials) - series (including OVAs) @@ -39,11 +67,11 @@ I also published my own templates [here](https://github.com/mProjectsCode/obsidi ### 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 | No | 60 per minute and 3 per second | Yes | | [OMDb](https://www.omdbapi.com/) | OMDb is an API that offers metadata for movie, series and games. | series, movies, games | Yes, you can get a free key here [here](https://www.omdbapi.com/apikey.aspx) | 1000 per day | No | | [MusicBrainz](https://musicbrainz.org/) | MusicBrainz is an API that offers information about music releases. | music releases | No | 50 per second | No | -| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows acces to all Wikipedia articles. | wiki articles | No | None | No | | | | | | | +| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows acces to all Wikipedia articles. | wiki articles | No | None | No | #### Notes - [Jikan](https://jikan.moe/) @@ -65,6 +93,9 @@ I also published my own templates [here](https://github.com/mProjectsCode/obsidi - [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 +### Problems, unexpected behavior or improvement suggestions? +You are more than welcome to open an issue on [GitHub](https://github.com/mProjectsCode/obsidian-media-db-plugin/issues). + ### Contributions Thank you for wanting to contribute to this project. diff --git a/src/main.ts b/src/main.ts index e5795eb..7240135 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,7 +22,7 @@ export default class MediaDbPlugin extends Plugin { // add icon to the left ribbon const ribbonIconEl = this.addRibbonIcon('database', 'Add new Media DB entry', (evt: MouseEvent) => - this.createMediaDbNote(this.openMediaDbSearchModal.bind(this)), + this.createMediaDbNote(this.openMediaDbAdvancedSearchModal.bind(this)), ); ribbonIconEl.addClass('obsidian-media-db-plugin-ribbon-class'); @@ -30,7 +30,7 @@ export default class MediaDbPlugin extends Plugin { this.addCommand({ id: 'open-media-db-search-modal', name: 'Add new Media DB entry', - callback: () => this.createMediaDbNote(this.openMediaDbSearchModal.bind(this)), + callback: () => this.createMediaDbNote(this.openMediaDbAdvancedSearchModal.bind(this)), }); // register command to open id search modal this.addCommand({ @@ -38,7 +38,7 @@ export default class MediaDbPlugin extends Plugin { name: 'Add new Media DB entry by id', callback: () => this.createMediaDbNote(this.openMediaDbIdSearchModal.bind(this)), }); - + // register command to update the open note this.addCommand({ id: 'update-media-db-note', name: 'Update the open note, if it is a Media DB entry.', @@ -103,7 +103,7 @@ export default class MediaDbPlugin extends Plugin { } } - async openMediaDbSearchModal(): Promise { + async openMediaDbAdvancedSearchModal(): Promise { return new Promise(((resolve, reject) => { new MediaDbAdvancedSearchModal(this.app, this, (err, results) => { if (err) return reject(err); diff --git a/src/tests/TestAPI.ts b/src/tests/TestAPI.ts new file mode 100644 index 0000000..324765b --- /dev/null +++ b/src/tests/TestAPI.ts @@ -0,0 +1,27 @@ +import {APIModel} from '../api/APIModel'; +import {MediaTypeModel} from '../models/MediaTypeModel'; +import MediaDbPlugin from '../main'; + +export class TestAPI extends APIModel { + plugin: MediaDbPlugin; + + + constructor(plugin: MediaDbPlugin) { + super(); + + this.plugin = plugin; + this.apiName = 'TestAPI'; + this.apiDescription = 'A test API for automated testing.'; + this.apiUrl = ''; + this.types = []; + } + + + async getById(item: MediaTypeModel): Promise { + return undefined; + } + + async searchByTitle(title: string): Promise { + return [] as MediaTypeModel[]; + } +} From 5916ed66eb9f35f7424e7bcb742ba4b85af0d6e4 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Sun, 29 May 2022 20:01:33 +0200 Subject: [PATCH 5/8] Steam API --- README.md | 58 +++++++++++---------- src/api/apis/SteamAPI.ts | 109 +++++++++++++++++++++++++++++++++++++++ src/main.ts | 2 + 3 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 src/api/apis/SteamAPI.ts diff --git a/README.md b/README.md index 3b49cc3..c334bf5 100644 --- a/README.md +++ b/README.md @@ -10,52 +10,52 @@ Search a movie, series, anime, game, music release or wiki article by its name a Allows you to search by an ID that varies from API to API. Concrete information on this feature can be found in the description of the individual APIs. #### Templates -The plugin allows you to set a template note that gets added to the end of any note created by this plugin. -The plugin also offers simple "template tgs". E.g. if the template includes `{{ title }}`, it will be replaced by the title of the movie, show or game. +The plugin allows you to set a template note that gets added to the end of any note created by this plugin. +The plugin also offers simple "template tgs". E.g. if the template includes `{{ title }}`, it will be replaced by the title of the movie, show or game. Note that "template tags" are surrounded with two curly braces and that the spaces inside the curly braces are important. For arrays there are two special ways of displaying them. - using `{{ LIST:variable_name }}` will result in - ``` - - element 1 - - element 2 - - element 3 - - ... - ``` + ``` + - element 1 + - element 2 + - element 3 + - ... + ``` - using `{{ ENUM:variable_name }}` will result in - ``` - element 1, element 2, element 3, ... - ``` + ``` + element 1, element 2, element 3, ... + ``` Available variables that can be used in template tags are the same variables from the metadata of the note. I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates). ### How to install -Currently, you have to manually download the zip archive from the latest release here on GitHub. +Currently, you have to manually download the zip archive from the latest release here on GitHub. After downloading, extract the archive into the `.obsidian/plugins` folder in your vault. The folder structure should look like this: -``` -[path to your vault] -|_ .obsidian - |_ plugins - |_ obsidian-media-db-plugin - |_ main.js - |_ manifest.json - |_ styles.css -``` +``` +[path to your vault] +|_ .obsidian + |_ plugins + |_ obsidian-media-db-plugin + |_ main.js + |_ manifest.json + |_ styles.css +``` -Once the plugin submission goes through, the plugin will also be installable directly through obsidian's plugin installer. +Once the plugin submission goes through, the plugin will also be installable directly through obsidian's plugin installer. ### How to use (pictures are coming) -Once you have installed this plugin, you will find a database icon in the left ribbon. -When using this or the `Add new Media DB entry` command, a popup will open. +Once you have installed this plugin, you will find a database icon in the left ribbon. +When using this or the `Add new Media DB entry` command, a popup will open. Here you can enter the title of what you want to search for and then select in which APIs to search. -After clicking search, a new popup will open prompting you to select from the search results. +After clicking search, a new popup will open prompting you to select from the search results. Now you select the result you want and the plugin will cast it's magic and create a new note in your vault, that contains the metadata of the selected search result. ### Currently supported media types @@ -71,7 +71,8 @@ Now you select the result you want and the plugin will cast it's magic and creat | [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 | No | 60 per minute and 3 per second | Yes | | [OMDb](https://www.omdbapi.com/) | OMDb is an API that offers metadata for movie, series and games. | series, movies, games | Yes, you can get a free key here [here](https://www.omdbapi.com/apikey.aspx) | 1000 per day | No | | [MusicBrainz](https://musicbrainz.org/) | MusicBrainz is an API that offers information about music releases. | music releases | No | 50 per second | No | -| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows acces to all Wikipedia articles. | wiki articles | No | None | No | +| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows access to all Wikipedia articles. | wiki articles | No | None | No | +| [Steam](https://store.steampowered.com/) | The Steam API offers information on all steam games. | games | No | 10000 per day | No | #### Notes - [Jikan](https://jikan.moe/) @@ -89,9 +90,12 @@ 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 "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 accessibe, you are better of just searching by title + - the id of a release is not easily accessible, you are better off just searching by title - [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/) + - 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` ### Problems, unexpected behavior or improvement suggestions? You are more than welcome to open an issue on [GitHub](https://github.com/mProjectsCode/obsidian-media-db-plugin/issues). diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts new file mode 100644 index 0000000..5e27fb9 --- /dev/null +++ b/src/api/apis/SteamAPI.ts @@ -0,0 +1,109 @@ +import {APIModel} from '../APIModel'; +import {MediaTypeModel} from '../../models/MediaTypeModel'; +import {MovieModel} from '../../models/MovieModel'; +import MediaDbPlugin from '../../main'; +import {SeriesModel} from '../../models/SeriesModel'; +import {GameModel} from '../../models/GameModel'; +import {contactEmail, debugLog, pluginName} from '../../utils/Utils'; +import {requestUrl} from 'obsidian'; +import {MediaType} from '../../utils/MediaType'; + +export class SteamAPI extends APIModel { + plugin: MediaDbPlugin; + typeMappings: Map; + + constructor(plugin: MediaDbPlugin) { + super(); + + this.plugin = plugin; + this.apiName = 'SteamAPI'; + this.apiDescription = 'A free API for all Steam games.'; + this.apiUrl = 'http://www.steampowered.com/'; + this.types = ['games']; + this.typeMappings = new Map(); + this.typeMappings.set('game', 'game'); + } + + async searchByTitle(title: string): Promise { + console.log(`MDB | api "${this.apiName}" queried by Title`); + + const searchUrl = `http://api.steampowered.com/ISteamApps/GetAppList/v0002/?format=json`; + const fetchData = await requestUrl({ + url: searchUrl, + }); + + if (fetchData.status !== 200) { + throw Error(`MDB | Received status code ${fetchData.status} from an API.`); + } + + const data = await fetchData.json; + + debugLog(data); + + let filteredData = []; + + for (const app of data.applist.apps) { + if (app.name.toLowerCase().includes(title.toLowerCase())) { + filteredData.push(app); + } + if (filteredData.length > 20) { + break; + } + } + + let ret: MediaTypeModel[] = []; + + for (const result of filteredData) { + ret.push(new GameModel({ + type: MediaType.Game, + title: result.name, + englishTitle: result.name, + year: '', + dataSource: this.apiName, + id: result.appid, + } as GameModel)); + } + + return ret; + } + + async getById(item: MediaTypeModel): Promise { + console.log(`MDB | api "${this.apiName}" queried by ID`); + + const searchUrl = `http://store.steampowered.com/api/appdetails?appids=${item.id}`; + const fetchData = await requestUrl({ + url: searchUrl, + }); + + if (fetchData.status !== 200) { + throw Error(`MDB | Received status code ${fetchData.status} from an API.`); + } + + const result = (await fetchData.json)[item.id].data; + + debugLog(result); + + const model = new GameModel({ + type: MediaType.Game, + title: result.name, + englishTitle: result.name, + year: (new Date(result.release_date.date)).getFullYear().toString(), + dataSource: this.apiName, + url: `https://store.steampowered.com/app/${result.id}`, + id: result.steam_appid, + + genres: result.genres?.map((x: any) => x.description) ?? [], + onlineRating: Number.parseFloat(result.metacritic?.score ?? 0), + image: result.header_image ?? '', + + released: !result.release_date?.comming_soon, + releaseDate: (new Date(result.release_date?.date)).toLocaleDateString() ?? 'unknown', + + played: false, + personalRating: 0, + } as GameModel); + + return model; + + } +} diff --git a/src/main.ts b/src/main.ts index 7240135..aa747dd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -11,6 +11,7 @@ import {MediaDbIdSearchModal} from './modals/MediaDbIdSearchModal'; import {WikipediaAPI} from './api/apis/WikipediaAPI'; import {MusicBrainzAPI} from './api/apis/MusicBrainzAPI'; import {MediaTypeManager} from './utils/MediaTypeManager'; +import {SteamAPI} from './api/apis/SteamAPI'; export default class MediaDbPlugin extends Plugin { settings: MediaDbPluginSettings; @@ -55,6 +56,7 @@ export default class MediaDbPlugin extends Plugin { this.apiManager.registerAPI(new MALAPI(this)); this.apiManager.registerAPI(new WikipediaAPI(this)); this.apiManager.registerAPI(new MusicBrainzAPI(this)); + this.apiManager.registerAPI(new SteamAPI(this)); // this.apiManager.registerAPI(new LocGovAPI(this)); // TODO: parse data this.mediaTypeManager = new MediaTypeManager(this.settings); From 0298270b031d259865bd5b7b92d48de69d55d357 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Tue, 31 May 2022 22:26:45 +0200 Subject: [PATCH 6/8] Own YAML Converter and update note won't override user data anymore --- src/api/apis/MALAPI.ts | 16 +++++++++------ src/api/apis/MusicBrainzAPI.ts | 4 ++++ src/api/apis/OMDbAPI.ts | 22 +++++++++++++-------- src/api/apis/SteamAPI.ts | 10 +++++----- src/api/apis/WikipediaAPI.ts | 2 ++ src/main.ts | 16 +++++++++------ src/models/GameModel.ts | 6 ++++-- src/models/MediaTypeModel.ts | 12 +++++++++-- src/models/MovieModel.ts | 9 +++++---- src/models/MusicReleaseModel.ts | 4 +++- src/models/SeriesModel.ts | 9 +++++---- src/models/WikiModel.ts | 1 + src/utils/MediaTypeManager.ts | 21 ++++++++++++++++++++ src/utils/YAMLConverter.ts | 35 +++++++++++++++++++++++++++++++++ 14 files changed, 129 insertions(+), 38 deletions(-) create mode 100644 src/utils/YAMLConverter.ts diff --git a/src/api/apis/MALAPI.ts b/src/api/apis/MALAPI.ts index 67c5790..a60e349 100644 --- a/src/api/apis/MALAPI.ts +++ b/src/api/apis/MALAPI.ts @@ -107,9 +107,11 @@ export class MALAPI extends APIModel { released: true, premiere: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown', - watched: false, - lastWatched: '', - personalRating: 0, + userData: { + watched: false, + lastWatched: '', + personalRating: 0, + }, } as MovieModel); return model; @@ -135,9 +137,11 @@ export class MALAPI extends APIModel { airedTo: (new Date(result.aired?.to)).toLocaleDateString() ?? 'unknown', airing: result.airing, - watched: false, - lastWatched: '', - personalRating: 0, + userData: { + watched: false, + lastWatched: '', + personalRating: 0, + }, } as SeriesModel); return model; diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts index 87ea855..53936cc 100644 --- a/src/api/apis/MusicBrainzAPI.ts +++ b/src/api/apis/MusicBrainzAPI.ts @@ -90,6 +90,10 @@ export class MusicBrainzAPI extends APIModel { genres: result.genres.map((g: any) => g.name), subType: result['primary-type'], rating: result.rating.value * 2, + + userData: { + personalRating: 0, + }, } as MusicReleaseModel); return model; diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index 4ae38f4..e4c2bee 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -132,9 +132,11 @@ export class OMDbAPI extends APIModel { released: true, premiere: (new Date(result.Released)).toLocaleDateString() ?? 'unknown', - watched: false, - lastWatched: '', - personalRating: 0, + userData: { + watched: false, + lastWatched: '', + personalRating: 0, + }, } as MovieModel); return model; @@ -160,9 +162,11 @@ export class OMDbAPI extends APIModel { airedFrom: (new Date(result.Released)).toLocaleDateString() ?? 'unknown', airedTo: 'unknown', - watched: false, - lastWatched: '', - personalRating: 0, + userData: { + watched: false, + lastWatched: '', + personalRating: 0, + }, } as SeriesModel); return model; @@ -183,8 +187,10 @@ export class OMDbAPI extends APIModel { released: true, releaseDate: (new Date(result.Released)).toLocaleDateString() ?? 'unknown', - played: false, - personalRating: 0, + userData: { + played: false, + personalRating: 0, + }, } as GameModel); return model; diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts index 5e27fb9..92cb1dd 100644 --- a/src/api/apis/SteamAPI.ts +++ b/src/api/apis/SteamAPI.ts @@ -1,10 +1,8 @@ import {APIModel} from '../APIModel'; import {MediaTypeModel} from '../../models/MediaTypeModel'; -import {MovieModel} from '../../models/MovieModel'; import MediaDbPlugin from '../../main'; -import {SeriesModel} from '../../models/SeriesModel'; import {GameModel} from '../../models/GameModel'; -import {contactEmail, debugLog, pluginName} from '../../utils/Utils'; +import {debugLog} from '../../utils/Utils'; import {requestUrl} from 'obsidian'; import {MediaType} from '../../utils/MediaType'; @@ -99,8 +97,10 @@ export class SteamAPI extends APIModel { released: !result.release_date?.comming_soon, releaseDate: (new Date(result.release_date?.date)).toLocaleDateString() ?? 'unknown', - played: false, - personalRating: 0, + userData: { + played: false, + personalRating: 0, + }, } as GameModel); return model; diff --git a/src/api/apis/WikipediaAPI.ts b/src/api/apis/WikipediaAPI.ts index 1387b65..096d1d4 100644 --- a/src/api/apis/WikipediaAPI.ts +++ b/src/api/apis/WikipediaAPI.ts @@ -71,6 +71,8 @@ export class WikipediaAPI extends APIModel { wikiUrl: result.fullurl, lastUpdated: (new Date(result.touched)).toLocaleDateString() ?? 'unknown', length: result.length, + + userData: {}, } as WikiModel); return model; diff --git a/src/main.ts b/src/main.ts index aa747dd..a93a63c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import {Notice, Plugin, TFile} from 'obsidian'; +import {FrontMatterCache, Notice, Plugin, TFile} from 'obsidian'; import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings'; import {APIManager} from './api/APIManager'; import {MediaTypeModel} from './models/MediaTypeModel'; @@ -130,21 +130,25 @@ export default class MediaDbPlugin extends Plugin { const activeLeaf: TFile = this.app.workspace.getActiveFile(); if (!activeLeaf.name) return; - let metadata = this.app.metadataCache.getFileCache(activeLeaf).frontmatter; + let metadata: FrontMatterCache = this.app.metadataCache.getFileCache(activeLeaf).frontmatter; - if (!metadata.type || !metadata.dataSource || !metadata.id) { + if (!metadata?.type || !metadata?.dataSource || !metadata?.id) { throw new Error('MDB | active note is not a Media DB entry or is missing metadata'); } - const newMetadata = await this.apiManager.queryDetailedInfo({dataSource: metadata.dataSource, id: metadata.id} as MediaTypeModel); + delete metadata.position; // remove unnecessary data from the FrontMatterCache + let oldMediaTypeModel = this.mediaTypeManager.createMediaTypeModelFromMediaType(metadata, metadata.type); - if (!newMetadata) { + let newMediaTypeModel = await this.apiManager.queryDetailedInfo({dataSource: metadata.dataSource, id: metadata.id} as MediaTypeModel); + if (!newMediaTypeModel) { return; } + newMediaTypeModel = Object.assign(oldMediaTypeModel, newMediaTypeModel.getWithOutUserData()); + console.log('MDB | deleting old entry'); await this.app.vault.delete(activeLeaf); - await this.createMediaDbNoteFromModel(newMetadata); + await this.createMediaDbNoteFromModel(newMediaTypeModel); } async loadSettings() { diff --git a/src/models/GameModel.ts b/src/models/GameModel.ts index 96bca40..d19dc2e 100644 --- a/src/models/GameModel.ts +++ b/src/models/GameModel.ts @@ -20,8 +20,10 @@ export class GameModel extends MediaTypeModel { released: boolean; releaseDate: string; - played: boolean; - personalRating: number; + userData: { + played: boolean; + personalRating: number; + }; constructor(obj: any = {}) { diff --git a/src/models/MediaTypeModel.ts b/src/models/MediaTypeModel.ts index c73a588..9c52813 100644 --- a/src/models/MediaTypeModel.ts +++ b/src/models/MediaTypeModel.ts @@ -1,5 +1,5 @@ import {MediaType} from '../utils/MediaType'; -import {stringifyYaml} from 'obsidian'; +import {YAMLConverter} from '../utils/YAMLConverter'; export abstract class MediaTypeModel { type: string; @@ -11,12 +11,20 @@ export abstract class MediaTypeModel { url: string; id: string; + userData: object; + abstract getMediaType(): MediaType; abstract getTags(): string[]; toMetaData(): string { - return stringifyYaml({...this, tags: '#' + this.getTags().join('/')}); + return YAMLConverter.toYaml({...this.getWithOutUserData(), ...this.userData, tags: '#' + this.getTags().join('/')}); + } + + getWithOutUserData(): object { + const copy = JSON.parse(JSON.stringify(this)); + delete copy.userData; + return copy; } } diff --git a/src/models/MovieModel.ts b/src/models/MovieModel.ts index c4fe66b..a761908 100644 --- a/src/models/MovieModel.ts +++ b/src/models/MovieModel.ts @@ -22,10 +22,11 @@ export class MovieModel extends MediaTypeModel { released: boolean; premiere: string; - watched: boolean; - lastWatched: string; - personalRating: number; - + userData: { + watched: boolean; + lastWatched: string; + personalRating: number; + }; constructor(obj: any = {}) { super(); diff --git a/src/models/MusicReleaseModel.ts b/src/models/MusicReleaseModel.ts index 10153cc..4094927 100644 --- a/src/models/MusicReleaseModel.ts +++ b/src/models/MusicReleaseModel.ts @@ -17,7 +17,9 @@ export class MusicReleaseModel extends MediaTypeModel { artists: string[]; rating: number; - personalRating: number; + userData: { + personalRating: number; + }; constructor(obj: any = {}) { super(); diff --git a/src/models/SeriesModel.ts b/src/models/SeriesModel.ts index 54afc78..5e49a59 100644 --- a/src/models/SeriesModel.ts +++ b/src/models/SeriesModel.ts @@ -25,10 +25,11 @@ export class SeriesModel extends MediaTypeModel { airedFrom: string; airedTo: string; - watched: boolean; - lastWatched: string; - personalRating: number; - + userData: { + watched: boolean; + lastWatched: string; + personalRating: number; + }; constructor(obj: any = {}) { super(); diff --git a/src/models/WikiModel.ts b/src/models/WikiModel.ts index a5dd1b7..6c067e9 100644 --- a/src/models/WikiModel.ts +++ b/src/models/WikiModel.ts @@ -17,6 +17,7 @@ export class WikiModel extends MediaTypeModel { lastUpdated: string; length: number; + userData: {}; constructor(obj: any = {}) { super(); diff --git a/src/utils/MediaTypeManager.ts b/src/utils/MediaTypeManager.ts index d85f14d..bd47d84 100644 --- a/src/utils/MediaTypeManager.ts +++ b/src/utils/MediaTypeManager.ts @@ -3,6 +3,11 @@ import {MediaType} from './MediaType'; import {MediaTypeModel} from '../models/MediaTypeModel'; import {replaceTags} from './Utils'; import {App, TFile} from 'obsidian'; +import {MovieModel} from '../models/MovieModel'; +import {SeriesModel} from '../models/SeriesModel'; +import {GameModel} from '../models/GameModel'; +import {WikiModel} from '../models/WikiModel'; +import {MusicReleaseModel} from '../models/MusicReleaseModel'; export class MediaTypeManager { mediaFileNameTemplateMap: Map; @@ -49,4 +54,20 @@ export class MediaTypeManager { // console.log(template); return replaceTags(template, mediaTypeModel); } + + createMediaTypeModelFromMediaType(obj: any, mediaType: MediaType): MediaTypeModel { + if (mediaType === MediaType.Movie) { + return new MovieModel(obj); + } else if (mediaType === MediaType.Series) { + return new SeriesModel(obj); + } else if (mediaType === MediaType.Game) { + return new GameModel(obj); + } else if (mediaType === MediaType.Wiki) { + return new WikiModel(obj); + } else if (mediaType === MediaType.MusicRelease) { + return new MusicReleaseModel(obj); + } + + return undefined; + } } diff --git a/src/utils/YAMLConverter.ts b/src/utils/YAMLConverter.ts new file mode 100644 index 0000000..a59d411 --- /dev/null +++ b/src/utils/YAMLConverter.ts @@ -0,0 +1,35 @@ +export class YAMLConverter { + static toYaml(obj: any): string { + let output = ''; + + for (const [key, value] of Object.entries(obj)) { + output += `${key}: ${YAMLConverter.toYamlString(value)}\n`; + } + + return output; + } + + private static toYamlString(value: any): string { + if (typeof value === 'boolean') { + return value ? 'true' : 'false'; + } else if (typeof value === 'number') { + return value.toString(); + } else if (typeof value === 'string') { + return '"' + value + '"'; + } else if (typeof value === 'object') { + let output = ''; + + if (Array.isArray(value)) { + for (const valueElement of value) { + output += `\n - ${YAMLConverter.toYamlString(valueElement)}`; + } + } else { + for (const [objKey, objValue] of Object.entries(value)) { + output += `\n ${objKey}: ${YAMLConverter.toYamlString(objValue)}`; + } + } + + return output; + } + } +} From 8b4a50647db02a5278de8ab7520ba1136f096be2 Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Tue, 31 May 2022 23:17:37 +0200 Subject: [PATCH 7/8] YAML converter indentation fix --- src/utils/YAMLConverter.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/utils/YAMLConverter.ts b/src/utils/YAMLConverter.ts index a59d411..7cec238 100644 --- a/src/utils/YAMLConverter.ts +++ b/src/utils/YAMLConverter.ts @@ -3,13 +3,13 @@ export class YAMLConverter { let output = ''; for (const [key, value] of Object.entries(obj)) { - output += `${key}: ${YAMLConverter.toYamlString(value)}\n`; + output += `${key}: ${YAMLConverter.toYamlString(value, 0)}\n`; } return output; } - private static toYamlString(value: any): string { + private static toYamlString(value: any, indentation: number): string { if (typeof value === 'boolean') { return value ? 'true' : 'false'; } else if (typeof value === 'number') { @@ -21,15 +21,19 @@ export class YAMLConverter { if (Array.isArray(value)) { for (const valueElement of value) { - output += `\n - ${YAMLConverter.toYamlString(valueElement)}`; + output += `\n${YAMLConverter.calculateSpacing(indentation)} - ${YAMLConverter.toYamlString(valueElement, indentation + 1)}`; } } else { for (const [objKey, objValue] of Object.entries(value)) { - output += `\n ${objKey}: ${YAMLConverter.toYamlString(objValue)}`; + output += `\n${YAMLConverter.calculateSpacing(indentation)} ${objKey}: ${YAMLConverter.toYamlString(objValue, indentation + 1)}`; } } return output; } } + + private static calculateSpacing(indentation: number): string { + return ' '.repeat(indentation * 4); + } } From 889d51712e5b27be6a891ffa453fc4a1b44fc8ba Mon Sep 17 00:00:00 2001 From: mProjectsCode Date: Wed, 1 Jun 2022 13:50:26 +0200 Subject: [PATCH 8/8] Plugin review changes round 2 --- src/api/APIManager.ts | 8 ++++++-- src/api/APIModel.ts | 2 +- src/api/apis/LocGovAPI.ts | 4 ++-- src/api/apis/MALAPI.ts | 4 ++-- src/api/apis/MusicBrainzAPI.ts | 6 +++--- src/api/apis/OMDbAPI.ts | 4 ++-- src/api/apis/SteamAPI.ts | 16 +++++++++++++--- src/api/apis/WikipediaAPI.ts | 4 ++-- src/main.ts | 28 +++++++++++++++++++++------- 9 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/api/APIManager.ts b/src/api/APIManager.ts index c20c677..cca4a41 100644 --- a/src/api/APIManager.ts +++ b/src/api/APIManager.ts @@ -25,9 +25,13 @@ export class APIManager { } async queryDetailedInfo(item: MediaTypeModel): Promise { + return await this.queryDetailedInfoById(item.id, item.dataSource); + } + + async queryDetailedInfoById(id: string, dataSource: string): Promise { for (const api of this.apis) { - if (api.apiName === item.dataSource) { - return api.getById(item); + if (api.apiName === dataSource) { + return api.getById(id); } } } diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index 0cbf5fa..9d2dd78 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -13,7 +13,7 @@ export abstract class APIModel { */ abstract searchByTitle(title: string): Promise; - abstract getById(item: MediaTypeModel): Promise; + abstract getById(id: string): Promise; hasType(type: string): boolean { return this.types.contains(type); diff --git a/src/api/apis/LocGovAPI.ts b/src/api/apis/LocGovAPI.ts index fd0b2d5..c90cdd0 100644 --- a/src/api/apis/LocGovAPI.ts +++ b/src/api/apis/LocGovAPI.ts @@ -40,10 +40,10 @@ export class LocGovAPI extends APIModel { // return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `https://www.loc.gov/item/${item.id}/?fo=json`; + const searchUrl = `https://www.loc.gov/item/${encodeURIComponent(id)}/?fo=json`; const fetchData = await fetch(searchUrl); if (fetchData.status !== 200) { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); diff --git a/src/api/apis/MALAPI.ts b/src/api/apis/MALAPI.ts index a60e349..5507a10 100644 --- a/src/api/apis/MALAPI.ts +++ b/src/api/apis/MALAPI.ts @@ -69,10 +69,10 @@ export class MALAPI extends APIModel { return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `https://api.jikan.moe/v4/anime/${item.id}`; + const searchUrl = `https://api.jikan.moe/v4/anime/${encodeURIComponent(id)}`; const fetchData = await fetch(searchUrl); if (fetchData.status !== 200) { diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts index 53936cc..1bcd84b 100644 --- a/src/api/apis/MusicBrainzAPI.ts +++ b/src/api/apis/MusicBrainzAPI.ts @@ -58,14 +58,14 @@ export class MusicBrainzAPI extends APIModel { return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(item.id)}?inc=releases+artists+tags+ratings+genres&fmt=json`; + const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(id)}?inc=releases+artists+tags+ratings+genres&fmt=json`; const fetchData = await requestUrl({ url: searchUrl, headers: { - 'User-Agent': `${pluginName}/0.1.7 (${contactEmail})`, + 'User-Agent': `${pluginName}/${mediaDbVersion} (${contactEmail})`, }, }); diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index e4c2bee..2c8bafb 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -88,10 +88,10 @@ export class OMDbAPI extends APIModel { return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `http://www.omdbapi.com/?i=${item.id}&apikey=${this.plugin.settings.OMDbKey}`; + const searchUrl = `http://www.omdbapi.com/?i=${encodeURIComponent(id)}&apikey=${this.plugin.settings.OMDbKey}`; const fetchData = await fetch(searchUrl); if (fetchData.status === 401) { diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts index 92cb1dd..c523609 100644 --- a/src/api/apis/SteamAPI.ts +++ b/src/api/apis/SteamAPI.ts @@ -65,10 +65,10 @@ export class SteamAPI extends APIModel { return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `http://store.steampowered.com/api/appdetails?appids=${item.id}`; + const searchUrl = `http://store.steampowered.com/api/appdetails?appids=${encodeURIComponent(id)}`; const fetchData = await requestUrl({ url: searchUrl, }); @@ -77,7 +77,17 @@ export class SteamAPI extends APIModel { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } - const result = (await fetchData.json)[item.id].data; + debugLog(await fetchData.json); + + let result; + for (const [key, value] of Object.entries(await fetchData.json)) { + if (key == id) { + result = value.data; + } + } + if (!result) { + throw Error(`MDB | API returned invalid data.`); + } debugLog(result); diff --git a/src/api/apis/WikipediaAPI.ts b/src/api/apis/WikipediaAPI.ts index 096d1d4..b0796b2 100644 --- a/src/api/apis/WikipediaAPI.ts +++ b/src/api/apis/WikipediaAPI.ts @@ -46,10 +46,10 @@ export class WikipediaAPI extends APIModel { return ret; } - async getById(item: MediaTypeModel): Promise { + async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&prop=info&pageids=${item.id}&inprop=url&format=json&origin=*`; + const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&prop=info&pageids=${encodeURIComponent(id)}&inprop=url&format=json&origin=*`; const fetchData = await fetch(searchUrl); if (fetchData.status !== 200) { diff --git a/src/main.ts b/src/main.ts index a93a63c..a08be41 100644 --- a/src/main.ts +++ b/src/main.ts @@ -43,7 +43,15 @@ export default class MediaDbPlugin extends Plugin { this.addCommand({ id: 'update-media-db-note', name: 'Update the open note, if it is a Media DB entry.', - callback: () => this.updateActiveNote(), + checkCallback: (checking: boolean) => { + if (!this.app.workspace.getActiveFile()) { + return false; + } + if (!checking) { + this.updateActiveNote() + } + return true; + }, }); // register the settings tab @@ -88,7 +96,11 @@ export default class MediaDbPlugin extends Plugin { const fileName = replaceIllegalFileNameCharactersInString(this.mediaTypeManager.getFileName(mediaTypeModel)); const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`; - await this.app.vault.delete(this.app.vault.getAbstractFileByPath(filePath)); + const file = this.app.vault.getAbstractFileByPath(filePath); + if (file) { + await this.app.vault.delete(file); + } + const targetFile = await this.app.vault.create(filePath, fileContent); // open file @@ -127,10 +139,12 @@ export default class MediaDbPlugin extends Plugin { } async updateActiveNote() { - const activeLeaf: TFile = this.app.workspace.getActiveFile(); - if (!activeLeaf.name) return; + const activeFile: TFile = this.app.workspace.getActiveFile(); + if (!activeFile) { + throw new Error('MDB | there is no active note'); + } - let metadata: FrontMatterCache = this.app.metadataCache.getFileCache(activeLeaf).frontmatter; + let metadata: FrontMatterCache = this.app.metadataCache.getFileCache(activeFile).frontmatter; if (!metadata?.type || !metadata?.dataSource || !metadata?.id) { throw new Error('MDB | active note is not a Media DB entry or is missing metadata'); @@ -139,7 +153,7 @@ export default class MediaDbPlugin extends Plugin { delete metadata.position; // remove unnecessary data from the FrontMatterCache let oldMediaTypeModel = this.mediaTypeManager.createMediaTypeModelFromMediaType(metadata, metadata.type); - let newMediaTypeModel = await this.apiManager.queryDetailedInfo({dataSource: metadata.dataSource, id: metadata.id} as MediaTypeModel); + let newMediaTypeModel = await this.apiManager.queryDetailedInfoById(metadata.id, metadata.dataSource); if (!newMediaTypeModel) { return; } @@ -147,7 +161,7 @@ export default class MediaDbPlugin extends Plugin { newMediaTypeModel = Object.assign(oldMediaTypeModel, newMediaTypeModel.getWithOutUserData()); console.log('MDB | deleting old entry'); - await this.app.vault.delete(activeLeaf); + await this.app.vault.delete(activeFile); await this.createMediaDbNoteFromModel(newMediaTypeModel); }