Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/api-request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: API request
about: Suggest a new API to be added to this plugin.
title: ''
labels: API request
assignees: ''

---

**Name**
Name of the API you would like to be added to the plugin

**Link**
A link to their API documentation

**What does the API do/offer**
A short description of what data the API offers


- [ ] Is the API free to use
- [ ] Does the API require authentication
40 changes: 40 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

- [ ] The Plugin is up to date
- [ ] Obsidian is up to date

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Occurs on**
- [ ] Windows
- [ ] macOS
- [ ] Linux
- [ ] Android
- [ ] iOS

**Plugin version**
x.x.x

**Additional context**
Add any other context about the problem here.
17 changes: 17 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature request
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Additional context**
Add any other context or screenshots about the feature request here.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ Available variables that can be used in template tags are the same variables fro

I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates).

#### Metadata field customization
Allows you to rename the metadata fields this plugin generates through mappings.

A mapping has to follow this syntax `[origional property name] -> [new property name]`.
Multiple mappings are separated by a new line.
So e.g.:
```
title -> name
year -> releaseYear
```

### How to install
**The plugin is now released, so it can be installed directly through obsidian's plugin installer.**

Expand All @@ -46,8 +57,7 @@ The folder structure should look like this:
|_ main.js
|_ manifest.json
|_ styles.css
```

```


### How to use
Expand Down Expand Up @@ -102,6 +112,11 @@ Now you select the result you want and the plugin will cast it's magic and creat
### 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).

### Changelog
#### 0.2.0
- Added the option to rename metadata fields through property mappings
- fixed note creation falling, when the folder set in the settings did not exist

### Contributions
Thank you for wanting to contribute to this project.

Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-media-db-plugin",
"name": "Media DB Plugin",
"version": "0.1.11",
"version": "0.2.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. ",
"author": "Moritz Jung",
Expand Down
5 changes: 4 additions & 1 deletion src/api/apis/SteamAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ export class SteamAPI extends APIModel {

let result;
for (const [key, value] of Object.entries(await fetchData.json)) {
if (key == id) {
// console.log(typeof key, key)
// console.log(typeof id, id)
// after some testing I found out that id is somehow a number despite that it's defined as string...
if (key === String(id)) {
result = value.data;
}
}
Expand Down
21 changes: 18 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import {WikipediaAPI} from './api/apis/WikipediaAPI';
import {MusicBrainzAPI} from './api/apis/MusicBrainzAPI';
import {MediaTypeManager} from './utils/MediaTypeManager';
import {SteamAPI} from './api/apis/SteamAPI';
import {ModelPropertyMapper} from './settings/ModelPropertyMapper';
import {YAMLConverter} from './utils/YAMLConverter';

export default class MediaDbPlugin extends Plugin {
settings: MediaDbPluginSettings;
apiManager: APIManager;
mediaTypeManager: MediaTypeManager;
modelPropertyMapper: ModelPropertyMapper;

async onload() {
await this.loadSettings();
Expand Down Expand Up @@ -68,6 +71,7 @@ export default class MediaDbPlugin extends Plugin {
// this.apiManager.registerAPI(new LocGovAPI(this)); // TODO: parse data

this.mediaTypeManager = new MediaTypeManager(this.settings);
this.modelPropertyMapper = new ModelPropertyMapper(this.settings);
}

async createMediaDbNote(modal: () => Promise<MediaTypeModel>): Promise<void> {
Expand All @@ -87,7 +91,7 @@ export default class MediaDbPlugin extends Plugin {
console.log('MDB | Creating new note...');
// console.log(mediaTypeModel);

let fileContent = `---\n${mediaTypeModel.toMetaData()}---\n`;
let fileContent = `---\n${YAMLConverter.toYaml(this.modelPropertyMapper.convertObject(mediaTypeModel.toMetaDataObject()))}---\n`;

if (this.settings.templates) {
fileContent += await this.mediaTypeManager.getContent(mediaTypeModel, this.app);
Expand All @@ -96,6 +100,11 @@ export default class MediaDbPlugin extends Plugin {
const fileName = replaceIllegalFileNameCharactersInString(this.mediaTypeManager.getFileName(mediaTypeModel));
const filePath = `${this.settings.folder.replace(/\/$/, '')}/${fileName}.md`;

const folder = this.app.vault.getAbstractFileByPath(this.settings.folder);
if (!folder) {
await this.app.vault.createFolder(this.settings.folder.replace(/\/$/, ''));
}

const file = this.app.vault.getAbstractFileByPath(filePath);
if (file) {
await this.app.vault.delete(file);
Expand Down Expand Up @@ -144,13 +153,17 @@ export default class MediaDbPlugin extends Plugin {
throw new Error('MDB | there is no active note');
}

let metadata: FrontMatterCache = this.app.metadataCache.getFileCache(activeFile).frontmatter;
let metadata: any = this.app.metadataCache.getFileCache(activeFile).frontmatter;
delete metadata.position; // remove unnecessary data from the FrontMatterCache
metadata = this.modelPropertyMapper.convertObjectBack(metadata);

console.log(metadata)

if (!metadata?.type || !metadata?.dataSource || !metadata?.id) {
throw new Error('MDB | active note is not a Media DB entry or is missing metadata');
}

delete metadata.position; // remove unnecessary data from the FrontMatterCache

let oldMediaTypeModel = this.mediaTypeManager.createMediaTypeModelFromMediaType(metadata, metadata.type);

let newMediaTypeModel = await this.apiManager.queryDetailedInfoById(metadata.id, metadata.dataSource);
Expand All @@ -171,6 +184,8 @@ export default class MediaDbPlugin extends Plugin {

async saveSettings() {
this.mediaTypeManager.updateTemplates(this.settings);
this.modelPropertyMapper.updateConversionRules(this.settings);

await this.saveData(this.settings);
}
}
4 changes: 2 additions & 2 deletions src/models/MediaTypeModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export abstract class MediaTypeModel {

abstract getTags(): string[];

toMetaData(): string {
return YAMLConverter.toYaml({...this.getWithOutUserData(), ...this.userData, tags: '#' + this.getTags().join('/')});
toMetaDataObject(): object {
return {...this.getWithOutUserData(), ...this.userData, tags: '#' + this.getTags().join('/')};
}

getWithOutUserData(): object {
Expand Down
8 changes: 8 additions & 0 deletions src/models/WikiModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class WikiModel extends MediaTypeModel {
wikiUrl: string;
lastUpdated: string;
length: number;
article: string;

userData: {};

Expand All @@ -35,4 +36,11 @@ export class WikiModel extends MediaTypeModel {
return MediaType.Wiki;
}

override getWithOutUserData(): object {
const copy = JSON.parse(JSON.stringify(this));
delete copy.userData;
delete copy.article;
return copy;
}

}
27 changes: 27 additions & 0 deletions src/settings/ModelPropertyConversionRule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {containsOnlyLettersAndUnderscores} from '../utils/Utils';

export class ModelPropertyConversionRule {
property: string;
newProperty: string;

constructor(conversionRule: string) {
const conversionRuleParts = conversionRule.split('->');
if (conversionRuleParts.length !== 2) {
throw Error(`Conversion rule "${conversionRule}" may only have exactly one "->"`);
}

let property = conversionRuleParts[0].trim();
let newProperty = conversionRuleParts[1].trim();

if (!property || !containsOnlyLettersAndUnderscores(property)) {
throw Error(`Error in conversion rule "${conversionRule}": property may not be empty and only contain letters and underscores.`);
}

if (!newProperty || !containsOnlyLettersAndUnderscores(newProperty)) {
throw Error(`Error in conversion rule "${conversionRule}": new property may not be empty and only contain letters and underscores.`);
}

this.property = property;
this.newProperty = newProperty;
}
}
109 changes: 109 additions & 0 deletions src/settings/ModelPropertyMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {MediaType} from '../utils/MediaType';
import {MediaDbPluginSettings} from './Settings';
import {ModelPropertyConversionRule} from './ModelPropertyConversionRule';

export class ModelPropertyMapper {
conversionRulesMap: Map<MediaType, string>;

constructor(settings: MediaDbPluginSettings) {
this.updateConversionRules(settings);
}

updateConversionRules(settings: MediaDbPluginSettings) {
this.conversionRulesMap = new Map<MediaType, string>();
this.conversionRulesMap.set(MediaType.Movie, settings.moviePropertyConversionRules);
this.conversionRulesMap.set(MediaType.Series, settings.seriesPropertyConversionRules);
this.conversionRulesMap.set(MediaType.Game, settings.gamePropertyConversionRules);
this.conversionRulesMap.set(MediaType.Wiki, settings.wikiPropertyConversionRules);
this.conversionRulesMap.set(MediaType.MusicRelease, settings.musicReleasePropertyConversionRules);
}

convertObject(obj: object): object {
if (!obj.hasOwnProperty('type')) {
return obj;
}

// @ts-ignore
const conversionRulesString: string = this.conversionRulesMap.get(obj['type']);
if (!conversionRulesString) {
return obj;
}

const conversionRules: ModelPropertyConversionRule[] = []
for (const conversionRuleString of conversionRulesString.split('\n')) {
if (conversionRuleString) {
conversionRules.push(new ModelPropertyConversionRule(conversionRuleString));
}
}

const newObj: object = {};


for (const [key, value] of Object.entries(obj)) {
if (key === 'type') {
// @ts-ignore
newObj[key] = value;
continue;
}

let hasConversionRule = false;
for (const conversionRule of conversionRules) {
if (conversionRule.property === key) {
hasConversionRule = true;
// @ts-ignore
newObj[conversionRule.newProperty] = value;
}
}
if (!hasConversionRule) {
// @ts-ignore
newObj[key] = value;
}
}

return newObj;
}

convertObjectBack(obj: object): object {
if (!obj.hasOwnProperty('type')) {
return obj;
}

// @ts-ignore
const conversionRulesString: string = this.conversionRulesMap.get(obj['type']);
if (!conversionRulesString) {
return obj;
}

const conversionRules: ModelPropertyConversionRule[] = []
for (const conversionRuleString of conversionRulesString.split('\n')) {
if (conversionRuleString) {
conversionRules.push(new ModelPropertyConversionRule(conversionRuleString));
}
}

const originalObj: object = {};

for (const [key, value] of Object.entries(obj)) {
if (key === 'type') {
// @ts-ignore
originalObj[key] = value;
continue;
}

let hasConversionRule = false;
for (const conversionRule of conversionRules) {
if (conversionRule.newProperty === key) {
hasConversionRule = true;
// @ts-ignore
originalObj[conversionRule.property] = value;
}
}
if (!hasConversionRule) {
// @ts-ignore
originalObj[key] = value;
}
}

return originalObj;
}
}
Loading