Merge branch 'master' into release
This commit is contained in:
commit
317b43016b
10 changed files with 144 additions and 45 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "obsidian-media-db-plugin",
|
"id": "obsidian-media-db-plugin",
|
||||||
"name": "Media DB Plugin",
|
"name": "Media DB Plugin",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"minAppVersion": "0.14.0",
|
"minAppVersion": "0.14.0",
|
||||||
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.",
|
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.",
|
||||||
"author": "Moritz Jung",
|
"author": "Moritz Jung",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "obsidian-media-db-plugin",
|
"name": "obsidian-media-db-plugin",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.",
|
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,20 @@ export class MALAPI extends APIModel {
|
||||||
let ret: MediaTypeModel[] = [];
|
let ret: MediaTypeModel[] = [];
|
||||||
|
|
||||||
for (const result of data.data) {
|
for (const result of data.data) {
|
||||||
const type = this.typeMappings.get(result.type.toLowerCase());
|
const type = this.typeMappings.get(result.type?.toLowerCase());
|
||||||
if (type === undefined) {
|
if (type === undefined) {
|
||||||
continue;
|
ret.push(new MovieModel({
|
||||||
|
subType: '',
|
||||||
|
title: result.title,
|
||||||
|
englishTitle: result.title_english ?? result.title,
|
||||||
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
dataSource: this.apiName,
|
||||||
|
id: result.mal_id,
|
||||||
|
} as MovieModel));
|
||||||
}
|
}
|
||||||
if (type === 'movie' || type === 'special') {
|
if (type === 'movie' || type === 'special') {
|
||||||
ret.push(new MovieModel({
|
ret.push(new MovieModel({
|
||||||
type: type,
|
subType: type,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
englishTitle: result.title_english ?? result.title,
|
englishTitle: result.title_english ?? result.title,
|
||||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
|
@ -56,7 +63,7 @@ export class MALAPI extends APIModel {
|
||||||
} as MovieModel));
|
} as MovieModel));
|
||||||
} else if (type === 'series' || type === 'ova') {
|
} else if (type === 'series' || type === 'ova') {
|
||||||
ret.push(new SeriesModel({
|
ret.push(new SeriesModel({
|
||||||
type: type,
|
subType: type,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
englishTitle: result.title_english ?? result.title,
|
englishTitle: result.title_english ?? result.title,
|
||||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
|
@ -83,14 +90,39 @@ export class MALAPI extends APIModel {
|
||||||
debugLog(data);
|
debugLog(data);
|
||||||
const result = data.data;
|
const result = data.data;
|
||||||
|
|
||||||
const type = this.typeMappings.get(result.type.toLowerCase());
|
const type = this.typeMappings.get(result.type?.toLowerCase());
|
||||||
if (type === undefined) {
|
if (type === undefined) {
|
||||||
throw Error(`${result.type.toLowerCase()} is an unsupported type.`);
|
const model = new MovieModel({
|
||||||
|
subType: '',
|
||||||
|
title: result.title,
|
||||||
|
englishTitle: result.title_english ?? result.title,
|
||||||
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
dataSource: this.apiName,
|
||||||
|
url: result.url,
|
||||||
|
id: result.mal_id,
|
||||||
|
|
||||||
|
genres: result.genres?.map((x: any) => x.name) ?? [],
|
||||||
|
producer: result.studios?.map((x: any) => x.name).join(', ') ?? 'unknown',
|
||||||
|
duration: result.duration ?? 'unknown',
|
||||||
|
onlineRating: result.score ?? 0,
|
||||||
|
image: result.images?.jpg?.image_url ?? '',
|
||||||
|
|
||||||
|
released: true,
|
||||||
|
premiere: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown',
|
||||||
|
|
||||||
|
userData: {
|
||||||
|
watched: false,
|
||||||
|
lastWatched: '',
|
||||||
|
personalRating: 0,
|
||||||
|
},
|
||||||
|
} as MovieModel);
|
||||||
|
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'movie' || type === 'special') {
|
if (type === 'movie' || type === 'special') {
|
||||||
const model = new MovieModel({
|
const model = new MovieModel({
|
||||||
type: type,
|
subType: type,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
englishTitle: result.title_english ?? result.title,
|
englishTitle: result.title_english ?? result.title,
|
||||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
|
@ -117,7 +149,7 @@ export class MALAPI extends APIModel {
|
||||||
return model;
|
return model;
|
||||||
} else if (type === 'series' || type === 'ova') {
|
} else if (type === 'series' || type === 'ova') {
|
||||||
const model = new SeriesModel({
|
const model = new SeriesModel({
|
||||||
type: type,
|
subType: type,
|
||||||
title: result.title,
|
title: result.title,
|
||||||
englishTitle: result.title_english ?? result.title,
|
englishTitle: result.title_english ?? result.title,
|
||||||
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
year: result.year ?? result.aired?.prop?.from?.year ?? '',
|
||||||
|
|
|
||||||
93
src/main.ts
93
src/main.ts
|
|
@ -1,4 +1,4 @@
|
||||||
import {Notice, Plugin, TFile, TFolder} from 'obsidian';
|
import {Notice, parseYaml, Plugin, stringifyYaml, TFile, TFolder} from 'obsidian';
|
||||||
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings';
|
import {DEFAULT_SETTINGS, MediaDbPluginSettings, MediaDbSettingTab} from './settings/Settings';
|
||||||
import {APIManager} from './api/APIManager';
|
import {APIManager} from './api/APIManager';
|
||||||
import {MediaTypeModel} from './models/MediaTypeModel';
|
import {MediaTypeModel} from './models/MediaTypeModel';
|
||||||
|
|
@ -109,33 +109,13 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
console.log('MDB | Creating new note...');
|
console.log('MDB | Creating new note...');
|
||||||
// console.log(mediaTypeModel);
|
// console.log(mediaTypeModel);
|
||||||
|
|
||||||
let metadata = this.modelPropertyMapper.convertObject(mediaTypeModel.toMetaDataObject());
|
let fileMetadata = this.modelPropertyMapper.convertObject(mediaTypeModel.toMetaDataObject());
|
||||||
if (attachFile) {
|
let fileContent = '';
|
||||||
let attachFileMetadata: any = this.app.metadataCache.getFileCache(attachFile).frontmatter;
|
|
||||||
if (attachFileMetadata) {
|
|
||||||
attachFileMetadata = JSON.parse(JSON.stringify(attachFileMetadata)); // deep copy
|
|
||||||
delete attachFileMetadata.position;
|
|
||||||
} else {
|
|
||||||
attachFileMetadata = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata = Object.assign(attachFileMetadata, metadata);
|
({fileMetadata, fileContent} = await this.attachFile(fileMetadata, fileContent, attachFile));
|
||||||
}
|
({fileMetadata, fileContent} = await this.attachTemplate(fileMetadata, fileContent, await this.mediaTypeManager.getTemplate(mediaTypeModel, this.app)));
|
||||||
|
|
||||||
debugLog(metadata);
|
fileContent = `---\n${this.settings.useCustomYamlStringifier ? YAMLConverter.toYaml(fileMetadata) : stringifyYaml(fileMetadata)}---\n` + fileContent;
|
||||||
|
|
||||||
let fileContent = `---\n${YAMLConverter.toYaml(metadata)}---\n`;
|
|
||||||
|
|
||||||
if (this.settings.templates) {
|
|
||||||
fileContent += await this.mediaTypeManager.getContent(mediaTypeModel, this.app);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attachFile) {
|
|
||||||
let attachFileContent: string = await this.app.vault.read(attachFile);
|
|
||||||
const regExp = new RegExp('^(---)\\n[\\s\\S]*\\n---');
|
|
||||||
attachFileContent = attachFileContent.replace(regExp, '');
|
|
||||||
fileContent += '\n\n' + attachFileContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.createNote(this.mediaTypeManager.getFileName(mediaTypeModel), fileContent);
|
await this.createNote(this.mediaTypeManager.getFileName(mediaTypeModel), fileContent);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -144,6 +124,67 @@ export default class MediaDbPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async attachFile(fileMetadata: any, fileContent: string, fileToAttach?: TFile): Promise<{ fileMetadata: any, fileContent: string }> {
|
||||||
|
if (!fileToAttach) {
|
||||||
|
return {fileMetadata: fileMetadata, fileContent: fileContent};
|
||||||
|
}
|
||||||
|
|
||||||
|
let attachFileMetadata: any = this.app.metadataCache.getFileCache(fileToAttach).frontmatter;
|
||||||
|
if (attachFileMetadata) {
|
||||||
|
attachFileMetadata = JSON.parse(JSON.stringify(attachFileMetadata)); // deep copy
|
||||||
|
delete attachFileMetadata.position;
|
||||||
|
} else {
|
||||||
|
attachFileMetadata = {};
|
||||||
|
}
|
||||||
|
fileMetadata = Object.assign(attachFileMetadata, fileMetadata);
|
||||||
|
|
||||||
|
let attachFileContent: string = await this.app.vault.read(fileToAttach);
|
||||||
|
const regExp = new RegExp('^(---)\\n[\\s\\S]*\\n---');
|
||||||
|
attachFileContent = attachFileContent.replace(regExp, '');
|
||||||
|
fileContent += '\n' + attachFileContent;
|
||||||
|
|
||||||
|
return {fileMetadata: fileMetadata, fileContent: fileContent};
|
||||||
|
}
|
||||||
|
|
||||||
|
async attachTemplate(fileMetadata: any, fileContent: string, template: string): Promise<{ fileMetadata: any, fileContent: string }> {
|
||||||
|
if (!template) {
|
||||||
|
return {fileMetadata: fileMetadata, fileContent: fileContent};
|
||||||
|
}
|
||||||
|
|
||||||
|
let templateMetadata: any = this.getMetaDataFromFileContent(template);
|
||||||
|
fileMetadata = Object.assign(templateMetadata, fileMetadata);
|
||||||
|
|
||||||
|
const regExp = new RegExp('^(---)\\n[\\s\\S]*\\n---');
|
||||||
|
const attachFileContent = template.replace(regExp, '');
|
||||||
|
fileContent += '\n' + attachFileContent;
|
||||||
|
|
||||||
|
return {fileMetadata: fileMetadata, fileContent: fileContent};
|
||||||
|
}
|
||||||
|
|
||||||
|
getMetaDataFromFileContent(fileContent: string): any {
|
||||||
|
let metadata: any;
|
||||||
|
|
||||||
|
const regExp = new RegExp('^(---)\\n[\\s\\S]*\\n---');
|
||||||
|
const frontMatterRegExpResult = regExp.exec(fileContent);
|
||||||
|
if (!frontMatterRegExpResult) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
let frontMatter = frontMatterRegExpResult[0];
|
||||||
|
if (!frontMatter) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
frontMatter = frontMatter.substring(4);
|
||||||
|
frontMatter = frontMatter.substring(0, frontMatter.length - 3);
|
||||||
|
|
||||||
|
metadata = parseYaml(frontMatter);
|
||||||
|
|
||||||
|
if (!metadata) {
|
||||||
|
metadata = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
async createNote(fileName: string, fileContent: string, openFile: boolean = false) {
|
async createNote(fileName: string, fileContent: string, openFile: boolean = false) {
|
||||||
fileName = replaceIllegalFileNameCharactersInString(fileName);
|
fileName = replaceIllegalFileNameCharactersInString(fileName);
|
||||||
const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`;
|
const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`;
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export class MediaDbFolderImportModal extends Modal {
|
||||||
|
|
||||||
|
|
||||||
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
|
contentEl.createDiv({cls: 'media-db-plugin-spacer'});
|
||||||
contentEl.createEl('h3', {text: 'The name of the mata data field that should be used as the title to query'});
|
contentEl.createEl('h3', {text: 'The name of the metadata field that should be used as the title to query.'});
|
||||||
|
|
||||||
const placeholder = 'title';
|
const placeholder = 'title';
|
||||||
const titleFieldNameComponent = new TextComponent(contentEl);
|
const titleFieldNameComponent = new TextComponent(contentEl);
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,13 @@ export abstract class SelectModal<T> extends Modal {
|
||||||
contentEl.createEl('h2', {text: this.title});
|
contentEl.createEl('h2', {text: this.title});
|
||||||
contentEl.createEl('p', {text: this.description});
|
contentEl.createEl('p', {text: this.description});
|
||||||
|
|
||||||
|
contentEl.addClass('media-db-plugin-select-modal');
|
||||||
|
|
||||||
const elementWrapper = contentEl.createDiv({cls: 'media-db-plugin-select-wrapper'});
|
const elementWrapper = contentEl.createDiv({cls: 'media-db-plugin-select-wrapper'});
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const element of this.elements) {
|
for (const element of this.elements) {
|
||||||
const selectModalElement = new SelectModalElement(element, contentEl, i, this, false);
|
const selectModalElement = new SelectModalElement(element, elementWrapper, i, this, false);
|
||||||
|
|
||||||
this.selectModalElements.push(selectModalElement);
|
this.selectModalElements.push(selectModalElement);
|
||||||
|
|
||||||
|
|
@ -85,6 +87,8 @@ export abstract class SelectModal<T> extends Modal {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.selectModalElements.first()?.element.scrollIntoView();
|
||||||
|
|
||||||
const bottomSetting = new Setting(contentEl);
|
const bottomSetting = new Setting(contentEl);
|
||||||
bottomSetting.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()));
|
bottomSetting.addButton(btn => btn.setButtonText('Cancel').onClick(() => this.close()));
|
||||||
if (this.skipButton) {
|
if (this.skipButton) {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,11 @@ import {FileSuggest} from './suggesters/FileSuggest';
|
||||||
|
|
||||||
export interface MediaDbPluginSettings {
|
export interface MediaDbPluginSettings {
|
||||||
folder: string,
|
folder: string,
|
||||||
sfwFilter: boolean,
|
|
||||||
OMDbKey: string,
|
OMDbKey: string,
|
||||||
|
sfwFilter: boolean,
|
||||||
|
useCustomYamlStringifier: boolean;
|
||||||
|
templates: boolean,
|
||||||
|
|
||||||
|
|
||||||
movieTemplate: string,
|
movieTemplate: string,
|
||||||
seriesTemplate: string,
|
seriesTemplate: string,
|
||||||
|
|
@ -28,13 +31,14 @@ export interface MediaDbPluginSettings {
|
||||||
wikiPropertyConversionRules: string,
|
wikiPropertyConversionRules: string,
|
||||||
musicReleasePropertyConversionRules: string,
|
musicReleasePropertyConversionRules: string,
|
||||||
|
|
||||||
templates: boolean,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
export const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||||
folder: 'Media DB',
|
folder: 'Media DB',
|
||||||
sfwFilter: true,
|
|
||||||
OMDbKey: '',
|
OMDbKey: '',
|
||||||
|
sfwFilter: true,
|
||||||
|
useCustomYamlStringifier: true,
|
||||||
|
templates: true,
|
||||||
|
|
||||||
movieTemplate: '',
|
movieTemplate: '',
|
||||||
seriesTemplate: '',
|
seriesTemplate: '',
|
||||||
|
|
@ -54,7 +58,7 @@ export const DEFAULT_SETTINGS: MediaDbPluginSettings = {
|
||||||
wikiPropertyConversionRules: '',
|
wikiPropertyConversionRules: '',
|
||||||
musicReleasePropertyConversionRules: '',
|
musicReleasePropertyConversionRules: '',
|
||||||
|
|
||||||
templates: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class MediaDbSettingTab extends PluginSettingTab {
|
export class MediaDbSettingTab extends PluginSettingTab {
|
||||||
|
|
@ -108,6 +112,17 @@ export class MediaDbSettingTab extends PluginSettingTab {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName('YAML formatter')
|
||||||
|
.setDesc('Add optional quotation marks around strings in the metadata block.')
|
||||||
|
.addToggle(cb => {
|
||||||
|
cb.setValue(this.plugin.settings.useCustomYamlStringifier)
|
||||||
|
.onChange(data => {
|
||||||
|
this.plugin.settings.useCustomYamlStringifier = data;
|
||||||
|
this.plugin.saveSettings();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName('Resolve {{ tags }} in templates')
|
.setName('Resolve {{ tags }} in templates')
|
||||||
.setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.')
|
.setDesc('Whether to resolve {{ tags }} in templates. The spaces inside the curly braces are important.')
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ export class MediaTypeManager {
|
||||||
return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType()), mediaTypeModel);
|
return replaceTags(this.mediaFileNameTemplateMap.get(mediaTypeModel.getMediaType()), mediaTypeModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getContent(mediaTypeModel: MediaTypeModel, app: App) {
|
async getTemplate(mediaTypeModel: MediaTypeModel, app: App) {
|
||||||
const templateFileName = this.mediaTemplateMap.get(mediaTypeModel.getMediaType());
|
const templateFileName = this.mediaTemplateMap.get(mediaTypeModel.getMediaType());
|
||||||
|
|
||||||
if (!templateFileName) {
|
if (!templateFileName) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import {MediaTypeModel} from '../models/MediaTypeModel';
|
||||||
export const pluginName: string = 'obsidian-media-db-plugin';
|
export const pluginName: string = 'obsidian-media-db-plugin';
|
||||||
export const contactEmail: string = 'm.projects.code@gmail.com';
|
export const contactEmail: string = 'm.projects.code@gmail.com';
|
||||||
export const mediaDbTag: string = 'mediaDB';
|
export const mediaDbTag: string = 'mediaDB';
|
||||||
export const mediaDbVersion: string = '0.3.0';
|
export const mediaDbVersion: string = '0.3.1';
|
||||||
export const debug: boolean = false;
|
export const debug: boolean = false;
|
||||||
|
|
||||||
export function wrapAround(value: number, size: number): number {
|
export function wrapAround(value: number, size: number): number {
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,15 @@ small.media-db-plugin-list-text{
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.media-db-plugin-select-modal {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.media-db-plugin-select-wrapper {
|
.media-db-plugin-select-wrapper {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-db-plugin-select-element {
|
.media-db-plugin-select-element {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue