diff --git a/src/api/APIModel.ts b/src/api/APIModel.ts index c44589c..c424508 100644 --- a/src/api/APIModel.ts +++ b/src/api/APIModel.ts @@ -1,10 +1,11 @@ import { MediaTypeModel } from '../models/MediaTypeModel'; +import { MediaType } from '../utils/MediaType'; export abstract class APIModel { apiName: string; apiUrl: string; apiDescription: string; - types: string[]; + types: MediaType[]; /** * This function should query the api and return a list of matches. The matches should be caped at 20. @@ -15,12 +16,11 @@ export abstract class APIModel { abstract getById(id: string): Promise; - hasType(type: string): boolean { + hasType(type: MediaType): boolean { return this.types.contains(type); } - // for future use (https://github.com/mProjectsCode/obsidian-media-db-plugin/issues/5) - hasTypeOverlap(types: string[]): boolean { + hasTypeOverlap(types: MediaType[]): boolean { for (const type of types) { if (this.hasType(type)) { return true; diff --git a/src/api/apis/BoardGameGeekAPI.ts b/src/api/apis/BoardGameGeekAPI.ts index f49955f..9f3ea20 100644 --- a/src/api/apis/BoardGameGeekAPI.ts +++ b/src/api/apis/BoardGameGeekAPI.ts @@ -2,8 +2,8 @@ import { APIModel } from '../APIModel'; import { MediaTypeModel } from '../../models/MediaTypeModel'; import MediaDbPlugin from '../../main'; import { BoardGameModel } from 'src/models/BoardGameModel'; -import { debugLog } from '../../utils/Utils'; import { requestUrl } from 'obsidian'; +import { MediaType } from '../../utils/MediaType'; export class BoardGameGeekAPI extends APIModel { plugin: MediaDbPlugin; @@ -15,7 +15,7 @@ export class BoardGameGeekAPI extends APIModel { this.apiName = 'BoardGameGeekAPI'; this.apiDescription = 'A free API for BoardGameGeek things.'; this.apiUrl = 'https://api.geekdo.com/xmlapi'; - this.types = ['boardgames']; + this.types = [MediaType.BoardGame]; } async searchByTitle(title: string): Promise { @@ -33,13 +33,13 @@ export class BoardGameGeekAPI extends APIModel { const data = fetchData.text; const response = new window.DOMParser().parseFromString(data, 'text/xml'); - debugLog(response); + console.debug(response); let ret: MediaTypeModel[] = []; for (const boardgame of Array.from(response.querySelectorAll('boardgame'))) { const id = boardgame.attributes.getNamedItem('objectid')!.value; - const title = boardgame.querySelector('name')!.textContent!; + const title = boardgame.querySelector('name[primary=true]')?.textContent ?? boardgame.querySelector('name')!.textContent!; const year = boardgame.querySelector('yearpublished')?.textContent ?? ''; ret.push( @@ -70,17 +70,22 @@ export class BoardGameGeekAPI extends APIModel { const data = fetchData.text; const response = new window.DOMParser().parseFromString(data, 'text/xml'); - debugLog(response); + console.debug(response); const boardgame = response.querySelector('boardgame')!; - const title = boardgame.querySelector('name')!.textContent!; + const title = boardgame.querySelector('name[primary=true]')!.textContent!; const year = boardgame.querySelector('yearpublished')?.textContent ?? ''; const image = boardgame.querySelector('image')?.textContent ?? undefined; - const onlineRating = Number.parseFloat(boardgame.querySelector('statistics ratings average')?.textContent ?? ''); + const onlineRating = Number.parseFloat(boardgame.querySelector('statistics ratings average')?.textContent ?? '0'); const genres = Array.from(boardgame.querySelectorAll('boardgamecategory')).map(n => n!.textContent!); + const complexityRating = Number.parseFloat(boardgame.querySelector('averageweight')?.textContent ?? '0'); + const minPlayers = Number.parseFloat(boardgame.querySelector('minplayers')?.textContent ?? '0'); + const maxPlayers = Number.parseFloat(boardgame.querySelector('maxplayers')?.textContent ?? '0'); + const playtime = (boardgame.querySelector('playingtime')?.textContent ?? 'unknown') + ' minutes'; + const publishers = Array.from(boardgame.querySelectorAll('boardgamepublisher')).map(n => n!.textContent!); const model = new BoardGameModel({ - title, + title: title, englishTitle: title, year: year === '0' ? '' : year, dataSource: this.apiName, @@ -89,7 +94,13 @@ export class BoardGameGeekAPI extends APIModel { genres: genres, onlineRating: onlineRating, + complexityRating: complexityRating, + minPlayers: minPlayers, + maxPlayers: maxPlayers, + playtime: playtime, + publishers: publishers, image: image, + released: true, userData: { diff --git a/src/api/apis/LocGovAPI.ts b/src/api/apis/LocGovAPI.ts index b7f843a..9e45bb2 100644 --- a/src/api/apis/LocGovAPI.ts +++ b/src/api/apis/LocGovAPI.ts @@ -25,14 +25,14 @@ export class LocGovAPI extends APIModel { const searchUrl = `https://www.loc.gov/search/?q=${encodeURIComponent(title)}&fo=json&c=20`; const fetchData = await fetch(searchUrl); - debugLog(fetchData); + console.debug(fetchData); if (fetchData.status !== 200) { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } const data = await fetchData.json(); - debugLog(data); + console.debug(data); let ret: MediaTypeModel[] = []; throw new Error('MDB | Under construction, API implementation not finished'); @@ -50,7 +50,7 @@ export class LocGovAPI extends APIModel { } const data = await fetchData.json(); - debugLog(data); + console.debug(data); const result = data.data; const type = this.typeMappings.get(result.type.toLowerCase()); diff --git a/src/api/apis/MALAPI.ts b/src/api/apis/MALAPI.ts index 880e008..50667ba 100644 --- a/src/api/apis/MALAPI.ts +++ b/src/api/apis/MALAPI.ts @@ -3,7 +3,7 @@ import { MediaTypeModel } from '../../models/MediaTypeModel'; import { MovieModel } from '../../models/MovieModel'; import MediaDbPlugin from '../../main'; import { SeriesModel } from '../../models/SeriesModel'; -import { debugLog } from '../../utils/Utils'; +import { MediaType } from '../../utils/MediaType'; export class MALAPI extends APIModel { plugin: MediaDbPlugin; @@ -16,7 +16,7 @@ export class MALAPI extends APIModel { this.apiName = 'MALAPI'; this.apiDescription = 'A free API for Anime. Some results may take a long time to load.'; this.apiUrl = 'https://jikan.moe/'; - this.types = ['movie', 'series', 'anime']; + this.types = [MediaType.Movie, MediaType.Series]; this.typeMappings = new Map(); this.typeMappings.set('movie', 'movie'); this.typeMappings.set('special', 'special'); @@ -30,13 +30,13 @@ export class MALAPI extends APIModel { const searchUrl = `https://api.jikan.moe/v4/anime?q=${encodeURIComponent(title)}&limit=20${this.plugin.settings.sfwFilter ? '&sfw' : ''}`; const fetchData = await fetch(searchUrl); - debugLog(fetchData); + console.debug(fetchData); if (fetchData.status !== 200) { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } const data = await fetchData.json(); - debugLog(data); + console.debug(data); let ret: MediaTypeModel[] = []; @@ -85,7 +85,7 @@ export class MALAPI extends APIModel { async getById(id: string): Promise { console.log(`MDB | api "${this.apiName}" queried by ID`); - const searchUrl = `https://api.jikan.moe/v4/anime/${encodeURIComponent(id)}`; + const searchUrl = `https://api.jikan.moe/v4/anime/${encodeURIComponent(id)}/full`; const fetchData = await fetch(searchUrl); if (fetchData.status !== 200) { @@ -93,7 +93,7 @@ export class MALAPI extends APIModel { } const data = await fetchData.json(); - debugLog(data); + console.debug(data); const result = data.data; const type = this.typeMappings.get(result.type?.toLowerCase()); @@ -111,10 +111,12 @@ export class MALAPI extends APIModel { producer: result.studios?.map((x: any) => x.name).join(', ') ?? 'unknown', duration: result.duration ?? 'unknown', onlineRating: result.score ?? 0, + actors: [], image: result.images?.jpg?.image_url ?? '', released: true, premiere: new Date(result.aired?.from).toLocaleDateString() ?? 'unknown', + streamingServices: result.streaming?.map((x: any) => x.name) ?? [], userData: { watched: false, @@ -140,10 +142,12 @@ export class MALAPI extends APIModel { producer: result.studios?.map((x: any) => x.name).join(', ') ?? 'unknown', duration: result.duration ?? 'unknown', onlineRating: result.score ?? 0, + actors: [], image: result.images?.jpg?.image_url ?? '', released: true, premiere: new Date(result.aired?.from).toLocaleDateString() ?? 'unknown', + streamingServices: result.streaming?.map((x: any) => x.name) ?? [], userData: { watched: false, @@ -168,6 +172,7 @@ export class MALAPI extends APIModel { episodes: result.episodes, duration: result.duration ?? 'unknown', onlineRating: result.score ?? 0, + streamingServices: result.streaming?.map((x: any) => x.name) ?? [], image: result.images?.jpg?.image_url ?? '', released: true, diff --git a/src/api/apis/MusicBrainzAPI.ts b/src/api/apis/MusicBrainzAPI.ts index 0b85b17..484566e 100644 --- a/src/api/apis/MusicBrainzAPI.ts +++ b/src/api/apis/MusicBrainzAPI.ts @@ -3,7 +3,8 @@ import { MediaTypeModel } from '../../models/MediaTypeModel'; import MediaDbPlugin from '../../main'; import { requestUrl } from 'obsidian'; import { MusicReleaseModel } from '../../models/MusicReleaseModel'; -import { contactEmail, debugLog, mediaDbVersion, pluginName } from '../../utils/Utils'; +import { contactEmail, mediaDbVersion, pluginName } from '../../utils/Utils'; +import { MediaType } from '../../utils/MediaType'; export class MusicBrainzAPI extends APIModel { plugin: MediaDbPlugin; @@ -15,7 +16,7 @@ export class MusicBrainzAPI extends APIModel { this.apiName = 'MusicBrainz API'; this.apiDescription = 'Free API for music albums.'; this.apiUrl = 'https://musicbrainz.org/'; - this.types = ['music']; + this.types = [MediaType.MusicRelease]; } async searchByTitle(title: string): Promise { @@ -30,14 +31,14 @@ export class MusicBrainzAPI extends APIModel { }, }); - debugLog(fetchData); + console.debug(fetchData); if (fetchData.status !== 200) { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } const data = await fetchData.json; - debugLog(data); + console.debug(data); let ret: MediaTypeModel[] = []; for (const result of data['release-groups']) { @@ -76,7 +77,7 @@ export class MusicBrainzAPI extends APIModel { } const data = await fetchData.json; - debugLog(data); + console.debug(data); const result = data; const model = new MusicReleaseModel({ diff --git a/src/api/apis/OMDbAPI.ts b/src/api/apis/OMDbAPI.ts index 0a7af61..34d5bee 100644 --- a/src/api/apis/OMDbAPI.ts +++ b/src/api/apis/OMDbAPI.ts @@ -4,7 +4,7 @@ import { MovieModel } from '../../models/MovieModel'; import MediaDbPlugin from '../../main'; import { SeriesModel } from '../../models/SeriesModel'; import { GameModel } from '../../models/GameModel'; -import { debugLog } from '../../utils/Utils'; +import { MediaType } from '../../utils/MediaType'; export class OMDbAPI extends APIModel { plugin: MediaDbPlugin; @@ -17,7 +17,7 @@ export class OMDbAPI extends APIModel { this.apiName = 'OMDbAPI'; this.apiDescription = 'A free API for Movies, Series and Games.'; this.apiUrl = 'http://www.omdbapi.com/'; - this.types = ['movie', 'series']; + this.types = [MediaType.Movie, MediaType.Series, MediaType.Game]; this.typeMappings = new Map(); this.typeMappings.set('movie', 'movie'); this.typeMappings.set('series', 'series'); @@ -46,7 +46,7 @@ export class OMDbAPI extends APIModel { return []; } - debugLog(data.Search); + console.debug(data.Search); let ret: MediaTypeModel[] = []; @@ -108,7 +108,7 @@ export class OMDbAPI extends APIModel { } const result = await fetchData.json(); - debugLog(result); + console.debug(result); if (result.Response === 'False') { throw Error(`MDB | Received error from ${this.apiName}: ${result.Error}`); @@ -133,9 +133,11 @@ export class OMDbAPI extends APIModel { producer: result.Director ?? 'unknown', duration: result.Runtime ?? 'unknown', onlineRating: Number.parseFloat(result.imdbRating ?? 0), + actors: result.Actors?.split(', ') ?? [], image: result.Poster ?? '', released: true, + streamingServices: [], premiere: new Date(result.Released).toLocaleDateString() ?? 'unknown', userData: { @@ -161,9 +163,11 @@ export class OMDbAPI extends APIModel { episodes: 0, duration: result.Runtime ?? 'unknown', onlineRating: Number.parseFloat(result.imdbRating ?? 0), + actors: result.Actors?.split(', ') ?? [], image: result.Poster ?? '', released: true, + streamingServices: [], airing: false, airedFrom: new Date(result.Released).toLocaleDateString() ?? 'unknown', airedTo: 'unknown', diff --git a/src/api/apis/SteamAPI.ts b/src/api/apis/SteamAPI.ts index 4cea1be..3a02663 100644 --- a/src/api/apis/SteamAPI.ts +++ b/src/api/apis/SteamAPI.ts @@ -2,7 +2,6 @@ import { APIModel } from '../APIModel'; import { MediaTypeModel } from '../../models/MediaTypeModel'; import MediaDbPlugin from '../../main'; import { GameModel } from '../../models/GameModel'; -import { debugLog } from '../../utils/Utils'; import { requestUrl } from 'obsidian'; import { MediaType } from '../../utils/MediaType'; @@ -17,7 +16,7 @@ export class SteamAPI extends APIModel { this.apiName = 'SteamAPI'; this.apiDescription = 'A free API for all Steam games.'; this.apiUrl = 'http://www.steampowered.com/'; - this.types = ['games']; + this.types = [MediaType.Game]; this.typeMappings = new Map(); this.typeMappings.set('game', 'game'); } @@ -36,7 +35,7 @@ export class SteamAPI extends APIModel { const data = await fetchData.json; - debugLog(data); + console.debug(data); let filteredData = []; @@ -79,7 +78,7 @@ export class SteamAPI extends APIModel { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } - debugLog(await fetchData.json); + console.debug(await fetchData.json); let result: any; for (const [key, value] of Object.entries(await fetchData.json)) { @@ -94,7 +93,7 @@ export class SteamAPI extends APIModel { throw Error(`MDB | API returned invalid data.`); } - debugLog(result); + console.debug(result); const model = new GameModel({ type: MediaType.Game, diff --git a/src/api/apis/WikipediaAPI.ts b/src/api/apis/WikipediaAPI.ts index d51dd69..6947612 100644 --- a/src/api/apis/WikipediaAPI.ts +++ b/src/api/apis/WikipediaAPI.ts @@ -2,7 +2,7 @@ import { APIModel } from '../APIModel'; import { MediaTypeModel } from '../../models/MediaTypeModel'; import MediaDbPlugin from '../../main'; import { WikiModel } from '../../models/WikiModel'; -import { debugLog } from '../../utils/Utils'; +import { MediaType } from '../../utils/MediaType'; export class WikipediaAPI extends APIModel { plugin: MediaDbPlugin; @@ -14,7 +14,7 @@ export class WikipediaAPI extends APIModel { this.apiName = 'Wikipedia API'; this.apiDescription = 'The API behind Wikipedia'; this.apiUrl = 'https://www.wikipedia.com'; - this.types = ['wiki']; + this.types = [MediaType.Wiki]; } async searchByTitle(title: string): Promise { @@ -22,14 +22,14 @@ export class WikipediaAPI extends APIModel { 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); - debugLog(fetchData); + console.debug(fetchData); if (fetchData.status !== 200) { throw Error(`MDB | Received status code ${fetchData.status} from an API.`); } const data = await fetchData.json(); - debugLog(data); + console.debug(data); let ret: MediaTypeModel[] = []; for (const result of data.query.search) { @@ -59,7 +59,7 @@ export class WikipediaAPI extends APIModel { } const data = await fetchData.json(); - debugLog(data); + console.debug(data); const result: any = Object.entries(data?.query?.pages)[0][1]; const model = new WikiModel({ diff --git a/src/main.ts b/src/main.ts index acff744..ded9ce2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -45,6 +45,7 @@ export default class MediaDbPlugin extends Plugin { this.addSettingTab(new MediaDbSettingTab(this.app, this)); this.mediaTypeManager.updateTemplates(this.settings); + this.mediaTypeManager.updateFolders(this.settings); // add icon to the left ribbon const ribbonIconEl = this.addRibbonIcon('database', 'Add new Media DB entry', (evt: MouseEvent) => this.createEntryWithAdvancedSearchModal()); @@ -271,6 +272,10 @@ export default class MediaDbPlugin extends Plugin { let fileContent = await this.generateMediaDbNoteContents(mediaTypeModel, options); + if (!options.folder) { + options.folder = await this.mediaTypeManager.getFolder(mediaTypeModel, this.app); + } + await this.createNote(this.mediaTypeManager.getFileName(mediaTypeModel), fileContent, options); } catch (e) { console.warn(e); @@ -368,10 +373,7 @@ export default class MediaDbPlugin extends Plugin { */ async createNote(fileName: string, fileContent: string, options: CreateNoteOptions) { // find and possibly create the folder set in settings or passed in folder - const folder = options.folder ?? this.app.vault.getAbstractFileByPath(this.settings.folder); - if (!folder) { - await this.app.vault.createFolder(this.settings.folder); - } + const folder = options.folder ?? this.app.vault.getAbstractFileByPath('/'); fileName = replaceIllegalFileNameCharactersInString(fileName); const filePath = `${folder.path}/${fileName}.md`; @@ -513,8 +515,8 @@ export default class MediaDbPlugin extends Plugin { } async createErroredFilesReport(erroredFiles: { filePath: string; error: string }[]): Promise { - const title = `bulk import error report ${dateTimeToString(new Date())}`; - const filePath = `${this.settings.folder.replace(/\/$/, '')}/${title}.md`; + const title = `MDB - bulk import error report ${dateTimeToString(new Date())}`; + const filePath = `${title}.md`; const table = [['file', 'error']].concat(erroredFiles.map(x => [x.filePath, x.error])); @@ -561,6 +563,7 @@ export default class MediaDbPlugin extends Plugin { async saveSettings() { this.mediaTypeManager.updateTemplates(this.settings); + this.mediaTypeManager.updateFolders(this.settings); await this.saveData(this.settings); } diff --git a/src/models/BoardGameModel.ts b/src/models/BoardGameModel.ts index cb53a25..70b86e5 100644 --- a/src/models/BoardGameModel.ts +++ b/src/models/BoardGameModel.ts @@ -5,6 +5,11 @@ import { MediaType } from '../utils/MediaType'; export class BoardGameModel extends MediaTypeModel { genres: string[]; onlineRating: number; + complexityRating: number; + minPlayers: number; + maxPlayers: number; + playtime: string; + publishers: string[]; image?: string; released: boolean; @@ -19,8 +24,15 @@ export class BoardGameModel extends MediaTypeModel { this.genres = undefined; this.onlineRating = undefined; + this.minPlayers = undefined; + this.maxPlayers = undefined; + this.playtime = undefined; + this.publishers = undefined; + this.complexityRating = undefined; this.image = undefined; + this.released = undefined; + this.userData = { played: undefined, personalRating: undefined, diff --git a/src/models/MovieModel.ts b/src/models/MovieModel.ts index 5c99863..83d874f 100644 --- a/src/models/MovieModel.ts +++ b/src/models/MovieModel.ts @@ -7,9 +7,11 @@ export class MovieModel extends MediaTypeModel { producer: string; duration: string; onlineRating: number; + actors: string[]; image: string; released: boolean; + streamingServices: string[]; premiere: string; userData: { @@ -25,9 +27,13 @@ export class MovieModel extends MediaTypeModel { this.producer = undefined; this.duration = undefined; this.onlineRating = undefined; + this.actors = undefined; this.image = undefined; + this.released = undefined; + this.streamingServices = undefined; this.premiere = undefined; + this.userData = { watched: undefined, lastWatched: undefined, diff --git a/src/models/SeriesModel.ts b/src/models/SeriesModel.ts index 8df01cc..5132f1e 100644 --- a/src/models/SeriesModel.ts +++ b/src/models/SeriesModel.ts @@ -17,9 +17,11 @@ export class SeriesModel extends MediaTypeModel { episodes: number; duration: string; onlineRating: number; + actors: string[]; image: string; released: boolean; + streamingServices: string[]; airing: boolean; airedFrom: string; airedTo: string; @@ -38,11 +40,15 @@ export class SeriesModel extends MediaTypeModel { this.episodes = undefined; this.duration = undefined; this.onlineRating = undefined; + this.actors = undefined; this.image = undefined; + this.released = undefined; + this.streamingServices = undefined; this.airing = undefined; this.airedFrom = undefined; this.airedTo = undefined; + this.userData = { watched: undefined, lastWatched: undefined, diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 37f17af..caf0cc3 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -9,7 +9,6 @@ import { MEDIA_TYPES } from '../utils/MediaTypeManager'; import { MediaTypeModel } from '../models/MediaTypeModel'; export interface MediaDbPluginSettings { - folder: string; OMDbKey: string; sfwFilter: boolean; useCustomYamlStringifier: boolean; @@ -36,11 +35,17 @@ export interface MediaDbPluginSettings { musicReleasePropertyConversionRules: string; boardgamePropertyConversionRules: string; + movieFolder: string; + seriesFolder: string; + gameFolder: string; + wikiFolder: string; + musicReleaseFolder: string; + boardgameFolder: string; + propertyMappingModels: PropertyMappingModel[]; } const DEFAULT_SETTINGS: MediaDbPluginSettings = { - folder: 'Media DB', OMDbKey: '', sfwFilter: true, useCustomYamlStringifier: true, @@ -67,6 +72,13 @@ const DEFAULT_SETTINGS: MediaDbPluginSettings = { musicReleasePropertyConversionRules: '', boardgamePropertyConversionRules: '', + movieFolder: 'Media DB/movies', + seriesFolder: 'Media DB/series', + gameFolder: 'Media DB/games', + wikiFolder: 'Media DB/wiki', + musicReleaseFolder: 'Media DB/music', + boardgameFolder: 'Media DB/boardgames', + propertyMappingModels: [], }; @@ -111,19 +123,6 @@ export class MediaDbSettingTab extends PluginSettingTab { containerEl.createEl('h2', { text: 'Media DB Plugin Settings' }); - new Setting(containerEl) - .setName('New file location') - .setDesc('New media db entries will be placed here.') - .addSearch(cb => { - new FolderSuggest(this.app, cb.inputEl); - cb.setPlaceholder('Example: folder1/folder2') - .setValue(this.plugin.settings.folder) - .onChange(data => { - this.plugin.settings.folder = data; - this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) .setName('OMDb API key') .setDesc('API key for "www.omdbapi.com".') @@ -166,6 +165,87 @@ export class MediaDbSettingTab extends PluginSettingTab { }); }); + containerEl.createEl('h3', { text: 'New File Location' }); + // region new file location + new Setting(containerEl) + .setName('Movie Folder') + .setDesc('Where newly imported movies should be places.') + .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; + this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Series Folder') + .setDesc('Where newly imported series should be places.') + .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; + this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Game Folder') + .setDesc('Where newly imported games should be places.') + .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; + this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Wiki Folder') + .setDesc('Where newly imported wiki articles should be places.') + .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; + this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Music Folder') + .setDesc('Where newly imported music should be places.') + .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; + this.plugin.saveSettings(); + }); + }); + + new Setting(containerEl) + .setName('Board Game Folder') + .setDesc('Where newly imported board games should be places.') + .addSearch(cb => { + new FileSuggest(this.app, cb.inputEl); + cb.setPlaceholder(DEFAULT_SETTINGS.boardgameFolder) + .setValue(this.plugin.settings.boardgameFolder) + .onChange(data => { + this.plugin.settings.boardgameFolder = data; + this.plugin.saveSettings(); + }); + }); + // endregion + containerEl.createEl('h3', { text: 'Template Settings' }); // region templates new Setting(containerEl) diff --git a/src/utils/MediaTypeManager.ts b/src/utils/MediaTypeManager.ts index 22f5140..1d7bc12 100644 --- a/src/utils/MediaTypeManager.ts +++ b/src/utils/MediaTypeManager.ts @@ -2,19 +2,21 @@ import { MediaDbPluginSettings } from '../settings/Settings'; import { MediaType } from './MediaType'; import { MediaTypeModel } from '../models/MediaTypeModel'; import { replaceTags } from './Utils'; -import { App, TFile } from 'obsidian'; +import { App, TAbstractFile, TFile, TFolder } 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'; import { BoardGameModel } from '../models/BoardGameModel'; +import { awaitExpression } from '@babel/types'; export const MEDIA_TYPES: MediaType[] = [MediaType.Movie, MediaType.Series, MediaType.Game, MediaType.Wiki, MediaType.MusicRelease, MediaType.BoardGame]; export class MediaTypeManager { mediaFileNameTemplateMap: Map; mediaTemplateMap: Map; + mediaFolderMap: Map; constructor() {} @@ -36,6 +38,16 @@ export class MediaTypeManager { this.mediaTemplateMap.set(MediaType.BoardGame, settings.boardgameTemplate); } + updateFolders(settings: MediaDbPluginSettings) { + this.mediaFolderMap = new Map(); + this.mediaFolderMap.set(MediaType.Movie, settings.movieFolder); + this.mediaFolderMap.set(MediaType.Series, settings.seriesFolder); + this.mediaFolderMap.set(MediaType.Game, settings.gameFolder); + this.mediaFolderMap.set(MediaType.Wiki, settings.wikiFolder); + this.mediaFolderMap.set(MediaType.MusicRelease, settings.musicReleaseFolder); + this.mediaFolderMap.set(MediaType.BoardGame, settings.boardgameFolder); + } + getFileName(mediaTypeModel: MediaTypeModel): string { return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType()), mediaTypeModel); } @@ -61,6 +73,26 @@ export class MediaTypeManager { return replaceTags(template, mediaTypeModel); } + async getFolder(mediaTypeModel: MediaTypeModel, app: App): Promise { + let folderPath = this.mediaFolderMap.get(mediaTypeModel.getMediaType()); + + if (!folderPath) { + folderPath = `/`; + } + console.log(folderPath); + + if (!(await app.vault.adapter.exists(folderPath))) { + await app.vault.createFolder(folderPath); + } + let folder: TAbstractFile = app.vault.getAbstractFileByPath(folderPath); + + if (!(folder instanceof TFolder)) { + throw Error(`Expected ${folder} to be instance of TFolder`); + } + + return folder; + } + /** * Takes an object and a MediaType and turns the object into an instance of a MediaTypeModel corresponding to the MediaType passed in. * diff --git a/src/utils/ModalHelper.ts b/src/utils/ModalHelper.ts index 24e7217..d8b6f2e 100644 --- a/src/utils/ModalHelper.ts +++ b/src/utils/ModalHelper.ts @@ -7,6 +7,7 @@ import MediaDbPlugin from '../main'; import { MediaDbPreviewModal } from 'src/modals/MediaDbPreviewModal'; import { CreateNoteOptions } from './Utils'; import { MediaDbSearchModal } from '../modals/MediaDbSearchModal'; +import { MediaType } from './MediaType'; export enum ModalResultCode { SUCCESS, @@ -77,7 +78,7 @@ export interface PreviewModalResult { */ export interface SearchModalData { query: string; - types: string[]; + types: MediaType[]; } /** @@ -124,7 +125,7 @@ export interface PreviewModalData { */ export interface SearchModalOptions { modalTitle?: string; - preselectedTypes?: string[]; + preselectedTypes?: MediaType[]; prefilledSearchString?: string; } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 6220759..186abf2 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -202,6 +202,7 @@ export class PropertyMappingNameConflictError extends Error { * - attachTemplate: whether to attach the template (DEFAULT: false) * - attachFie: a file to attach (DEFAULT: undefined) * - openNote: whether to open the note after creation (DEFAULT: false) + * - folder: folder to put the note in */ export interface CreateNoteOptions { attachTemplate?: boolean;