diff --git a/src/api/apis/LocGovAPI.ts b/src/api/apis/LocGovAPI.ts index 8e8fa42..9788bb4 100644 --- a/src/api/apis/LocGovAPI.ts +++ b/src/api/apis/LocGovAPI.ts @@ -2,6 +2,7 @@ import {APIModel} from '../APIModel'; import {MediaTypeModel} from '../../models/MediaTypeModel'; import MediaDbPlugin from '../../main'; +// WIP export class LocGovAPI extends APIModel { plugin: MediaDbPlugin; typeMappings: Map; @@ -21,7 +22,7 @@ export class LocGovAPI extends APIModel { async searchByTitle(title: string): Promise { console.log(`MDB | api "${this.apiName}" queried`); - const searchUrl = `https://www.loc.gov/search/?q=${title}&fo=json&c=20`; + const searchUrl = `https://www.loc.gov/search/?q=${encodeURIComponent(title)}&fo=json&c=20`; const fetchData = await fetch(searchUrl); console.log(fetchData); diff --git a/src/api/apis/MALAPI.ts b/src/api/apis/MALAPI.ts index 8057ab7..48cc850 100644 --- a/src/api/apis/MALAPI.ts +++ b/src/api/apis/MALAPI.ts @@ -26,7 +26,7 @@ export class MALAPI extends APIModel { async searchByTitle(title: string): Promise { console.log(`MDB | api "${this.apiName}" queried`); - const searchUrl = `https://api.jikan.moe/v4/anime?q=${title}&limit=20${this.plugin.settings.sfwFilter ? '&sfw' : ''}`; + const searchUrl = `https://api.jikan.moe/v4/anime?q=${encodeURIComponent(title)}&limit=20${this.plugin.settings.sfwFilter ? '&sfw' : ''}`; const fetchData = await fetch(searchUrl); console.log(fetchData); diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts new file mode 100644 index 0000000..0cd899c --- /dev/null +++ b/src/api/apis/MusicBrainzAPI.ts @@ -0,0 +1,98 @@ +import {APIModel} from '../APIModel'; +import {MediaTypeModel} from '../../models/MediaTypeModel'; +import MediaDbPlugin from '../../main'; +import {requestUrl} from 'obsidian'; +import {MusicReleaseModel} from '../../models/MusicReleaseModel'; +// import {MusicBrainzApi} from 'musicbrainz-api'; + +// WIP +export class MusicBrainzAPI extends APIModel { + plugin: MediaDbPlugin; + + constructor(plugin: MediaDbPlugin) { + super(); + + this.plugin = plugin; + this.apiName = 'MusicBrainz API'; + this.apiDescription = 'Free API for music albums.'; + this.apiUrl = 'https://musicbrainz.org/'; + this.types = ['music']; + } + + async searchByTitle(title: string): Promise { + console.log(`MDB | api "${this.apiName}" queried`); + + const searchUrl = `https://musicbrainz.org/ws/2/release-group?query=${encodeURIComponent(title)}&limit=20&fmt=json`; + + const fetchData = await requestUrl({ + url: searchUrl, + headers: { + 'User-Agent': 'obsidian-media-db-plugin/0.1.7 ( m.projects.code@gmail.com )', + }, + }); + + console.log(fetchData); + + if (fetchData.status !== 200) { + throw Error(`Received status code ${fetchData.status} from an API.`); + } + const data = await fetchData.json; + + console.log(data); + + let ret: MediaTypeModel[] = []; + + for (const result of data['release-groups']) { + ret.push(new MusicReleaseModel({ + type: 'musicRelease', + title: result.title, + englishTitle: result.title, + year: (new Date(result['first-release-date'])).getFullYear().toString(), + dataSource: this.apiName, + url: '', + id: result.id, + + artists: result['artist-credit'].map((a: any) => a.name), + subType: result['primary-type'], + } as MusicReleaseModel)); + } + + return ret; + } + + async getById(item: MediaTypeModel): Promise { + console.log(`MDB | api "${this.apiName}" queried`); + + const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(item.id)}?inc=releases+artists+tags+ratings+genres&fmt=json`; + + const fetchData = await requestUrl({ + url: searchUrl, + headers: { + 'User-Agent': 'MyAwesomeTagger/1.2.0 ( me@example.com )', + }, + }); + + const data = await fetchData.json; + + console.log(data); + + const result = data; + + const model = new MusicReleaseModel({ + type: 'musicRelease', + title: result.title, + englishTitle: result.title, + year: (new Date(result['first-release-date'])).getFullYear().toString(), + dataSource: this.apiName, + url: '', + id: result.id, + + artists: result['artist-credit'].map((a: any) => a.name), + genres: result.genres.map((g: any) => g.name), + subType: result['primary-type'], + rating: result.rating.value * 2, + } as MusicReleaseModel); + + return model; + } +} diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index e3531db..d5797f4 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -26,7 +26,7 @@ export class OMDbAPI extends APIModel { async searchByTitle(title: string): Promise { console.log(`MDB | api "${this.apiName}" queried`); - const searchUrl = `http://www.omdbapi.com/?s=${title}&apikey=${this.plugin.settings.OMDbKey}`; + const searchUrl = `http://www.omdbapi.com/?s=${encodeURIComponent(title)}&apikey=${this.plugin.settings.OMDbKey}`; const fetchData = await fetch(searchUrl); diff --git a/src/api/apis/TestAPI.ts b/src/api/apis/TestAPI.ts deleted file mode 100644 index cdba595..0000000 --- a/src/api/apis/TestAPI.ts +++ /dev/null @@ -1,26 +0,0 @@ -import {APIModel} from '../APIModel'; -import {MediaTypeModel} from '../../models/MediaTypeModel'; -import {MovieModel} from '../../models/MovieModel'; - -export class TestAPI extends APIModel { - constructor() { - super(); - this.apiName = 'testAPI'; - this.apiDescription = 'The test API used during development.'; - this.apiUrl = 'www.test.api'; - this.types = ['test']; - } - - async searchByTitle(title: string): Promise { - console.log(`MDB | api "${this.apiName}" queried`); - - return [ - new MovieModel({title: 'test_1', type: this.types[0], dataSource: this.apiName}), - new MovieModel({title: 'test_2', type: this.types[0], dataSource: this.apiName, producer: 'Max Musterman'}), - ]; - } - - async getById(item: MediaTypeModel): Promise { - return item; - } -} diff --git a/src/api/apis/WikipediaAPI.ts b/src/api/apis/WikipediaAPI.ts index 5e141e2..db17d40 100644 --- a/src/api/apis/WikipediaAPI.ts +++ b/src/api/apis/WikipediaAPI.ts @@ -19,7 +19,7 @@ export class WikipediaAPI extends APIModel { async searchByTitle(title: string): Promise { console.log(`MDB | api "${this.apiName}" queried`); - const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${title}&srlimit=20&utf8=&format=json&origin=*`; + const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(title)}&srlimit=20&utf8=&format=json&origin=*`; const fetchData = await fetch(searchUrl); console.log(fetchData); diff --git a/src/main.ts b/src/main.ts index 880d086..0a8ab3a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,6 @@ import {Notice, Plugin, TFile} from 'obsidian'; import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings'; import {APIManager} from './api/APIManager'; -import {TestAPI} from './api/apis/TestAPI'; import {MediaTypeModel} from './models/MediaTypeModel'; import {replaceIllegalFileNameCharactersInString, replaceTags} from './utils/Utils'; import {OMDbAPI} from './api/apis/OMDbAPI'; @@ -10,6 +9,7 @@ import {MediaDbSearchResultModal} from './modals/MediaDbSearchResultModal'; import {MALAPI} from './api/apis/MALAPI'; import {MediaDbIdSearchModal} from './modals/MediaDbIdSearchModal'; import {WikipediaAPI} from './api/apis/WikipediaAPI'; +import {MusicBrainzAPI} from './api/apis/MusicBrainzAPI'; export default class MediaDbPlugin extends Plugin { settings: MediaDbPluginSettings; @@ -43,10 +43,10 @@ export default class MediaDbPlugin extends Plugin { this.apiManager = new APIManager(); // register APIs - this.apiManager.registerAPI(new TestAPI()); this.apiManager.registerAPI(new OMDbAPI(this)); this.apiManager.registerAPI(new MALAPI(this)); this.apiManager.registerAPI(new WikipediaAPI(this)); + this.apiManager.registerAPI(new MusicBrainzAPI(this)); // this.apiManager.registerAPI(new LocGovAPI(this)); // TODO: parse data } @@ -71,6 +71,10 @@ export default class MediaDbPlugin extends Plugin { 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 (templateFile) { diff --git a/src/modals/MediaDbAdvancedSearchModal.ts b/src/modals/MediaDbAdvancedSearchModal.ts index 08da542..0664620 100644 --- a/src/modals/MediaDbAdvancedSearchModal.ts +++ b/src/modals/MediaDbAdvancedSearchModal.ts @@ -30,7 +30,7 @@ export class MediaDbAdvancedSearchModal extends Modal { console.log(this.selectedApis); - if (!this.query || this.query.length < 5) { + if (!this.query || this.query.length < 3) { new Notice('MDB: Query to short'); return; } diff --git a/src/models/MusicReleaseModel.ts b/src/models/MusicReleaseModel.ts new file mode 100644 index 0000000..46a2505 --- /dev/null +++ b/src/models/MusicReleaseModel.ts @@ -0,0 +1,35 @@ +import {MediaTypeModel} from './MediaTypeModel'; +import {stringifyYaml} from 'obsidian'; + + +export class MusicReleaseModel extends MediaTypeModel { + type: string; + title: string; + englishTitle: string; + year: string; + dataSource: string; + url: string; + id: string; + + genres: string[]; + artists: string[]; + subType: string; + rating: number; + + personalRating: number; + + constructor(obj: any = {}) { + super(); + + Object.assign(this, obj); + } + + toMetaData(): string { + return stringifyYaml(this); + } + + getFileName(): string { + return this.title + ' (' + this.artists.join(', ') + ' - ' + this.year + ' - ' + this.subType + ')'; + } + +} diff --git a/src/models/SeriesModel.ts b/src/models/SeriesModel.ts index d6ab109..7fc4a17 100644 --- a/src/models/SeriesModel.ts +++ b/src/models/SeriesModel.ts @@ -39,7 +39,7 @@ export class SeriesModel extends MediaTypeModel { } getFileName(): string { - return this.title; + return this.title + ' (' + this.year + ')'; } } diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 8b85f32..cc8a967 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -12,6 +12,8 @@ export interface MediaDbPluginSettings { movieTemplate: string, seriesTemplate: string, gameTemplate: string, + wikiTemplate: string, + musicReleaseTemplate: string, templates: boolean, } @@ -22,6 +24,8 @@ export const DEFAULT_SETTINGS: MediaDbPluginSettings = { movieTemplate: '', seriesTemplate: '', gameTemplate: '', + wikiTemplate: '', + musicReleaseTemplate: '', templates: true, }; @@ -103,6 +107,32 @@ export class MediaDbSettingTab extends PluginSettingTab { }); }); + 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; + 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; + this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) .setName('OMDb API key') .setDesc('API key for "www.omdbapi.com".') diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index aa385df..45b66c4 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -35,7 +35,7 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel): string { let obj = traverseMetaData(path, mediaTypeModel); if (obj === undefined) { - return '{{ INVALID TEMPLATE TAG }}'; + return '{{ INVALID TEMPLATE TAG - object undefined }}'; } return obj; @@ -47,7 +47,7 @@ function replaceTag(match: string, mediaTypeModel: MediaTypeModel): string { let obj = traverseMetaData(path, mediaTypeModel); if (obj === undefined) { - return '{{ INVALID TEMPLATE TAG }}'; + return '{{ INVALID TEMPLATE TAG - object undefined }}'; } if (operator === 'LIST') {