Skip to content

Commit 78ee146

Browse files
committed
Meta data field customization #19
1 parent b4e40d2 commit 78ee146

File tree

8 files changed

+247
-11
lines changed

8 files changed

+247
-11
lines changed

src/api/apis/SteamAPI.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ export class SteamAPI extends APIModel {
8181

8282
let result;
8383
for (const [key, value] of Object.entries(await fetchData.json)) {
84-
if (key == id) {
84+
// console.log(typeof key, key)
85+
// console.log(typeof id, id)
86+
// after some testing I found out that id is somehow a number despite that it's defined as string...
87+
if (key === String(id)) {
8588
result = value.data;
8689
}
8790
}

src/main.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ import {WikipediaAPI} from './api/apis/WikipediaAPI';
1212
import {MusicBrainzAPI} from './api/apis/MusicBrainzAPI';
1313
import {MediaTypeManager} from './utils/MediaTypeManager';
1414
import {SteamAPI} from './api/apis/SteamAPI';
15+
import {ModelPropertyMapper} from './settings/ModelPropertyMapper';
16+
import {YAMLConverter} from './utils/YAMLConverter';
1517

1618
export default class MediaDbPlugin extends Plugin {
1719
settings: MediaDbPluginSettings;
1820
apiManager: APIManager;
1921
mediaTypeManager: MediaTypeManager;
22+
modelPropertyMapper: ModelPropertyMapper;
2023

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

7073
this.mediaTypeManager = new MediaTypeManager(this.settings);
74+
this.modelPropertyMapper = new ModelPropertyMapper(this.settings);
7175
}
7276

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

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

9296
if (this.settings.templates) {
9397
fileContent += await this.mediaTypeManager.getContent(mediaTypeModel, this.app);
@@ -144,13 +148,17 @@ export default class MediaDbPlugin extends Plugin {
144148
throw new Error('MDB | there is no active note');
145149
}
146150

147-
let metadata: FrontMatterCache = this.app.metadataCache.getFileCache(activeFile).frontmatter;
151+
let metadata: any = this.app.metadataCache.getFileCache(activeFile).frontmatter;
152+
delete metadata.position; // remove unnecessary data from the FrontMatterCache
153+
metadata = this.modelPropertyMapper.convertObjectBack(metadata);
154+
155+
console.log(metadata)
148156

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

153-
delete metadata.position; // remove unnecessary data from the FrontMatterCache
161+
154162
let oldMediaTypeModel = this.mediaTypeManager.createMediaTypeModelFromMediaType(metadata, metadata.type);
155163

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

172180
async saveSettings() {
173181
this.mediaTypeManager.updateTemplates(this.settings);
182+
this.modelPropertyMapper.updateConversionRules(this.settings);
183+
174184
await this.saveData(this.settings);
175185
}
176186
}

src/models/MediaTypeModel.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export abstract class MediaTypeModel {
1717

1818
abstract getTags(): string[];
1919

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

2424
getWithOutUserData(): object {

src/models/WikiModel.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class WikiModel extends MediaTypeModel {
1616
wikiUrl: string;
1717
lastUpdated: string;
1818
length: number;
19+
article: string;
1920

2021
userData: {};
2122

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

39+
override getWithOutUserData(): object {
40+
const copy = JSON.parse(JSON.stringify(this));
41+
delete copy.userData;
42+
delete copy.article;
43+
return copy;
44+
}
45+
3846
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {containsOnlyLettersAndUnderscores} from '../utils/Utils';
2+
3+
export class ModelPropertyConversionRule {
4+
property: string;
5+
newProperty: string;
6+
7+
constructor(conversionRule: string) {
8+
const conversionRuleParts = conversionRule.split('->');
9+
if (conversionRuleParts.length !== 2) {
10+
throw Error(`Conversion rule "${conversionRule}" may only have exactly one "->"`);
11+
}
12+
13+
let property = conversionRuleParts[0].trim();
14+
let newProperty = conversionRuleParts[1].trim();
15+
16+
if (!property || !containsOnlyLettersAndUnderscores(property)) {
17+
throw Error(`Error in conversion rule "${conversionRule}": property may not be empty and only contain letters and underscores.`);
18+
}
19+
20+
if (!newProperty || !containsOnlyLettersAndUnderscores(newProperty)) {
21+
throw Error(`Error in conversion rule "${conversionRule}": new property may not be empty and only contain letters and underscores.`);
22+
}
23+
24+
this.property = property;
25+
this.newProperty = newProperty;
26+
}
27+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import {MediaType} from '../utils/MediaType';
2+
import {MediaDbPluginSettings} from './Settings';
3+
import {ModelPropertyConversionRule} from './ModelPropertyConversionRule';
4+
5+
export class ModelPropertyMapper {
6+
conversionRulesMap: Map<MediaType, string>;
7+
8+
constructor(settings: MediaDbPluginSettings) {
9+
this.updateConversionRules(settings);
10+
}
11+
12+
updateConversionRules(settings: MediaDbPluginSettings) {
13+
this.conversionRulesMap = new Map<MediaType, string>();
14+
this.conversionRulesMap.set(MediaType.Movie, settings.moviePropertyConversionRules);
15+
this.conversionRulesMap.set(MediaType.Series, settings.seriesPropertyConversionRules);
16+
this.conversionRulesMap.set(MediaType.Game, settings.gamePropertyConversionRules);
17+
this.conversionRulesMap.set(MediaType.Wiki, settings.wikiPropertyConversionRules);
18+
this.conversionRulesMap.set(MediaType.MusicRelease, settings.musicReleasePropertyConversionRules);
19+
}
20+
21+
convertObject(obj: object): object {
22+
if (!obj.hasOwnProperty('type')) {
23+
return obj;
24+
}
25+
26+
// @ts-ignore
27+
const conversionRulesString: string = this.conversionRulesMap.get(obj['type']);
28+
if (!conversionRulesString) {
29+
return obj;
30+
}
31+
32+
const conversionRules: ModelPropertyConversionRule[] = []
33+
for (const conversionRuleString of conversionRulesString.split('\n')) {
34+
if (conversionRuleString) {
35+
conversionRules.push(new ModelPropertyConversionRule(conversionRuleString));
36+
}
37+
}
38+
39+
const newObj: object = {};
40+
41+
42+
for (const [key, value] of Object.entries(obj)) {
43+
if (key === 'type') {
44+
// @ts-ignore
45+
newObj[key] = value;
46+
continue;
47+
}
48+
49+
let hasConversionRule = false;
50+
for (const conversionRule of conversionRules) {
51+
if (conversionRule.property === key) {
52+
hasConversionRule = true;
53+
// @ts-ignore
54+
newObj[conversionRule.newProperty] = value;
55+
}
56+
}
57+
if (!hasConversionRule) {
58+
// @ts-ignore
59+
newObj[key] = value;
60+
}
61+
}
62+
63+
return newObj;
64+
}
65+
66+
convertObjectBack(obj: object): object {
67+
if (!obj.hasOwnProperty('type')) {
68+
return obj;
69+
}
70+
71+
// @ts-ignore
72+
const conversionRulesString: string = this.conversionRulesMap.get(obj['type']);
73+
if (!conversionRulesString) {
74+
return obj;
75+
}
76+
77+
const conversionRules: ModelPropertyConversionRule[] = []
78+
for (const conversionRuleString of conversionRulesString.split('\n')) {
79+
if (conversionRuleString) {
80+
conversionRules.push(new ModelPropertyConversionRule(conversionRuleString));
81+
}
82+
}
83+
84+
const originalObj: object = {};
85+
86+
for (const [key, value] of Object.entries(obj)) {
87+
if (key === 'type') {
88+
// @ts-ignore
89+
originalObj[key] = value;
90+
continue;
91+
}
92+
93+
let hasConversionRule = false;
94+
for (const conversionRule of conversionRules) {
95+
if (conversionRule.newProperty === key) {
96+
hasConversionRule = true;
97+
// @ts-ignore
98+
originalObj[conversionRule.property] = value;
99+
}
100+
}
101+
if (!hasConversionRule) {
102+
// @ts-ignore
103+
originalObj[key] = value;
104+
}
105+
}
106+
107+
return originalObj;
108+
}
109+
}

src/settings/Settings.ts

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ export interface MediaDbPluginSettings {
2222
wikiFileNameTemplate: string,
2323
musicReleaseFileNameTemplate: string,
2424

25+
moviePropertyConversionRules: string,
26+
seriesPropertyConversionRules: string,
27+
gamePropertyConversionRules: string,
28+
wikiPropertyConversionRules: string,
29+
musicReleasePropertyConversionRules: string,
30+
2531
templates: boolean,
2632
}
2733

@@ -42,6 +48,12 @@ export const DEFAULT_SETTINGS: MediaDbPluginSettings = {
4248
wikiFileNameTemplate: '{{ title }}',
4349
musicReleaseFileNameTemplate: '{{ title }} (by {{ ENUM:artists }} - {{ year }})',
4450

51+
moviePropertyConversionRules: '',
52+
seriesPropertyConversionRules: '',
53+
gamePropertyConversionRules: '',
54+
wikiPropertyConversionRules: '',
55+
musicReleasePropertyConversionRules: '',
56+
4557
templates: true,
4658
};
4759

@@ -181,7 +193,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
181193
new Setting(containerEl)
182194
.setName('Movie file name template')
183195
.setDesc('Template for the file name used when creating a new note for a movie.')
184-
.addSearch(cb => {
196+
.addText(cb => {
185197
cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.movieFileNameTemplate}`)
186198
.setValue(this.plugin.settings.movieFileNameTemplate)
187199
.onChange(data => {
@@ -193,7 +205,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
193205
new Setting(containerEl)
194206
.setName('Series file name template')
195207
.setDesc('Template for the file name used when creating a new note for a series.')
196-
.addSearch(cb => {
208+
.addText(cb => {
197209
cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.seriesFileNameTemplate}`)
198210
.setValue(this.plugin.settings.seriesFileNameTemplate)
199211
.onChange(data => {
@@ -205,7 +217,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
205217
new Setting(containerEl)
206218
.setName('Game file name template')
207219
.setDesc('Template for the file name used when creating a new note for a game.')
208-
.addSearch(cb => {
220+
.addText(cb => {
209221
cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.gameFileNameTemplate}`)
210222
.setValue(this.plugin.settings.gameFileNameTemplate)
211223
.onChange(data => {
@@ -217,7 +229,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
217229
new Setting(containerEl)
218230
.setName('Wiki file name template')
219231
.setDesc('Template for the file name used when creating a new note for a wiki entry.')
220-
.addSearch(cb => {
232+
.addText(cb => {
221233
cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.wikiFileNameTemplate}`)
222234
.setValue(this.plugin.settings.wikiFileNameTemplate)
223235
.onChange(data => {
@@ -229,7 +241,7 @@ export class MediaDbSettingTab extends PluginSettingTab {
229241
new Setting(containerEl)
230242
.setName('Music Release file name template')
231243
.setDesc('Template for the file name used when creating a new note for a music release.')
232-
.addSearch(cb => {
244+
.addText(cb => {
233245
cb.setPlaceholder(`Example: ${DEFAULT_SETTINGS.musicReleaseFileNameTemplate}`)
234246
.setValue(this.plugin.settings.musicReleaseFileNameTemplate)
235247
.onChange(data => {
@@ -239,6 +251,69 @@ export class MediaDbSettingTab extends PluginSettingTab {
239251
});
240252
// endregion
241253

254+
containerEl.createEl('h3', {text: 'Property Mappings'});
255+
// region Property Mappings
256+
new Setting(containerEl)
257+
.setName('Movie model property mappings')
258+
.setDesc('Mappings for the property names of a movie.')
259+
.addTextArea(cb => {
260+
cb.setPlaceholder(`Example: \ntitle -> name\nyear -> releaseYear`)
261+
.setValue(this.plugin.settings.moviePropertyConversionRules)
262+
.onChange(data => {
263+
this.plugin.settings.moviePropertyConversionRules = data;
264+
this.plugin.saveSettings();
265+
});
266+
});
267+
268+
new Setting(containerEl)
269+
.setName('Series model property mappings')
270+
.setDesc('Mappings for the property names of a series.')
271+
.addTextArea(cb => {
272+
cb.setPlaceholder(`Example: \ntitle -> name\nyear -> releaseYear`)
273+
.setValue(this.plugin.settings.seriesPropertyConversionRules)
274+
.onChange(data => {
275+
this.plugin.settings.seriesPropertyConversionRules = data;
276+
this.plugin.saveSettings();
277+
});
278+
});
279+
280+
new Setting(containerEl)
281+
.setName('Game model property mappings')
282+
.setDesc('Mappings for the property names of a game.')
283+
.addTextArea(cb => {
284+
cb.setPlaceholder(`Example: \ntitle -> name\nyear -> releaseYear`)
285+
.setValue(this.plugin.settings.gamePropertyConversionRules)
286+
.onChange(data => {
287+
this.plugin.settings.gamePropertyConversionRules = data;
288+
this.plugin.saveSettings();
289+
});
290+
});
291+
292+
new Setting(containerEl)
293+
.setName('Wiki model property mappings')
294+
.setDesc('Mappings for the property names of a wiki entry.')
295+
.addTextArea(cb => {
296+
cb.setPlaceholder(`Example: \ntitle -> name\nyear -> releaseYear`)
297+
.setValue(this.plugin.settings.wikiPropertyConversionRules)
298+
.onChange(data => {
299+
this.plugin.settings.wikiPropertyConversionRules = data;
300+
this.plugin.saveSettings();
301+
});
302+
});
303+
304+
new Setting(containerEl)
305+
.setName('Music Release model property mappings')
306+
.setDesc('Mappings for the property names of a music release.')
307+
.addTextArea(cb => {
308+
cb.setPlaceholder(`Example: \ntitle -> name\nyear -> releaseYear`)
309+
.setValue(this.plugin.settings.musicReleasePropertyConversionRules)
310+
.onChange(data => {
311+
this.plugin.settings.musicReleasePropertyConversionRules = data;
312+
this.plugin.saveSettings();
313+
});
314+
});
315+
// endregion
316+
242317
}
243318

244319
}

src/utils/Utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export function debugLog(o: any): void {
1717
}
1818
}
1919

20+
export function containsOnlyLettersAndUnderscores(str: string): boolean {
21+
return /^[a-zA-Z_]+$/.test(str);
22+
}
23+
2024
export function replaceIllegalFileNameCharactersInString(string: string): string {
2125
return string.replace(/[\\,#%&{}/*<>$"@.?]*/g, '').replace(/:+/g, ' -');
2226
}

0 commit comments

Comments
 (0)