changes for plugin submission review

This commit is contained in:
mProjectsCode 2022-05-19 10:38:11 +02:00
parent 344c1ebf6c
commit a5d62ddc24
13 changed files with 134 additions and 237 deletions

View file

@ -1,6 +1,6 @@
## Obsidian Media DB Plugin ## Obsidian Media DB Plugin
A plugin that can query multiple APIs for movies, series, anime and games, and import them into your vault. A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.
### Features ### Features
#### Search by Title #### Search by Title
@ -10,23 +10,23 @@ Search a movie, series, anime or game by its name across multiple APIs.
Allows you to search by an ID that varies from API to API. Concrete info can be found in the description of the individual APIs. Allows you to search by an ID that varies from API to API. Concrete info can be found in the description of the individual APIs.
#### Templates #### Templates
The plugin allows you to set a template note that gets added to the end of any note created by this plugin. The plugin allows you to set a template note that gets added to the end of any note created by this plugin.
The plugin also offers simple "template tgs". E.g. if the template includes `{{ title }}`, it will be replaced by the title of the movie, show or game. The plugin also offers simple "template tgs". E.g. if the template includes `{{ title }}`, it will be replaced by the title of the movie, show or game.
Note that "template tags" are surrounded with two curly braces and that the spaces inside the curly braces are important. Note that "template tags" are surrounded with two curly braces and that the spaces inside the curly braces are important.
For arrays there are two special ways of displaying them. For arrays there are two special ways of displaying them.
- using `{{ LIST:variable_name }}` will result in - using `{{ LIST:variable_name }}` will result in
``` ```
- element 1 - element 1
- element 2 - element 2
- element 3 - element 3
- ... - ...
``` ```
- using `{{ ENUM:variable_name }}` will result in - using `{{ ENUM:variable_name }}` will result in
``` ```
element 1, element 2, element 3, ... element 1, element 2, element 3, ...
``` ```
I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates). I also published my own templates [here](https://github.com/mProjectsCode/obsidian-media-db-templates).
@ -34,48 +34,39 @@ I also published my own templates [here](https://github.com/mProjectsCode/obsidi
- movies (including specials) - movies (including specials)
- series (including OVAs) - series (including OVAs)
- games - games
- music releases
- wiki articles
### Currently supported APIs: ### Currently supported APIs:
- [Jikan](https://jikan.moe/), an API that uses [My Anime List](https://myanimelist.net) | Name | Description | Supported formats | Authentification | Rate limiting | SFW filter support |
- supported formats | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------- | ------------------------------ | ------------------ |
- series | [Jikan](https://jikan.moe/) | Jikan is an API that uses [My Anime List](https://myanimelist.net) and offers metadata for anime. | series, movies, specials, OVAs | No | 60 per minute and 3 per second | Yes |
- movies | [OMDb](https://www.omdbapi.com/) | OMDb is an API that offers metadata for movie, series and games. | series, movies, games | Yes, you can get a free key here [here](https://www.omdbapi.com/apikey.aspx) | 1000 per day | No |
- specials | [MusicBrainz](https://musicbrainz.org/) | MusicBrainz is an API that offers information about music releases. | music releases | No | 50 per second | No |
- OVAs | [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows acces to all Wikipedia articles. | wiki articles | No | None | No | | | | | | |
- authentication
- no authentication or API key needed #### Notes
- SFW filter support - [Jikan](https://jikan.moe/)
- yes - sometimes the api is very slow, this is normal
- Search by ID - you need to use the title the anime has on [My Anime List](https://myanimelist.net), which is in most cases the japanese title
- the ID you need is the ID of the anime on [My Anime List](https://myanimelist.net) - e.g. instead of "Demon Slayer" you have to search "Kimetsu no Yaiba"
- you can find this ID in the URL
- e.g. for "Beyond the Boundary" the URL looks like this `https://myanimelist.net/anime/18153/Kyoukai_no_Kanata` so the ID is `18153` #### Search by ID
- notes - [Jikan](https://jikan.moe/)
- sometimes the api is very slow, this is normal - the ID you need is the ID of the anime on [My Anime List](https://myanimelist.net)
- you need to use the title the anime has on [My Anime List](https://myanimelist.net), which is in most cases the japanese title - you can find this ID in the URL
- e.g. instead of "Demon Slayer" you have to search "Kimetsu no Yaiba" - e.g. for "Beyond the Boundary" the URL looks like this `https://myanimelist.net/anime/18153/Kyoukai_no_Kanata` so the ID is `18153`
- the API is rate limited to
- 60 requests per minute
- 3 requests per second
- [OMDb](https://www.omdbapi.com/) - [OMDb](https://www.omdbapi.com/)
- supported formats - the ID you need is the ID of the movie or show on [IMDb](https://www.imdb.com)
- series - you can find this ID in the URL
- movies - e.g. for "Rogue One" the URL looks like this `https://www.imdb.com/title/tt3748528/` so the ID is `tt3748528`
- games - [MusicBrainz](https://musicbrainz.org/)
- authentication - the id of a release is not easyly accessibe, you are better of just searching by title
- an API key is needed - [Wikipedia](https://en.wikipedia.org/wiki/Main_Page)
- you can get one [here](https://www.omdbapi.com/apikey.aspx) for free - [here](https://en.wikipedia.org/wiki/Wikipedia:Finding_a_Wikidata_ID) is a guide to finding the Wikipedia ID for an article
- SFW filter support
- no, but I haven't encountered any NSFW content while developing this plugin
- Search by ID
- the ID you need is the ID of the movie or show on [IMDb](https://www.imdb.com)
- you can find this ID in the URL
- e.g. for "Rogue One" the URL looks like this `https://www.imdb.com/title/tt3748528/` so the ID is `tt3748528`
- notes
- the api is rate limited to 1000 requests a day
### Contributions ### Contributions
Thank you for wanting to contribute to this project. Thank you for wanting to contribute to this project.
Contributions are always welcome. If you have an idea, feel free to open a feature request under the issue tab or even create a pull request. Contributions are always welcome. If you have an idea, feel free to open a feature request under the issue tab or even create a pull request.

View file

@ -3,7 +3,7 @@
"name": "Media DB Plugin", "name": "Media DB Plugin",
"version": "0.1.7", "version": "0.1.7",
"minAppVersion": "0.14.0", "minAppVersion": "0.14.0",
"description": "A plugin that can query multiple APIs for movies, series, anime and games, 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",
"authorUrl": "https://mprojectscode.github.io/", "authorUrl": "https://mprojectscode.github.io/",
"isDesktopOnly": false "isDesktopOnly": false

View file

@ -1,5 +1,6 @@
import {APIModel} from './APIModel'; import {APIModel} from './APIModel';
import {MediaTypeModel} from '../models/MediaTypeModel'; import {MediaTypeModel} from '../models/MediaTypeModel';
import {debugLog} from '../utils/Utils';
export class APIManager { export class APIManager {
apis: APIModel[]; apis: APIModel[];
@ -9,28 +10,17 @@ export class APIManager {
} }
async query(query: string, apisToQuery: any): Promise<MediaTypeModel[]> { async query(query: string, apisToQuery: any): Promise<MediaTypeModel[]> {
console.log('MDB | api manager queried'); debugLog(`MDB | api manager queried with "${query}"`);
let res: MediaTypeModel[] = []; let res: MediaTypeModel[] = [];
for (const api of this.apis) { for (const api of this.apis) {
if (Object.keys(apisToQuery).contains(api.apiName) && apisToQuery[api.apiName]) { if (Object.keys(apisToQuery).contains(api.apiName) && apisToQuery[api.apiName]) {
const apiRes = await api.searchByTitle(query); const apiRes = await api.searchByTitle(query);
// console.log(apiRes);
res = res.concat(apiRes); res = res.concat(apiRes);
} }
} }
/*
for (const api of this.apis) {
if (types.length === 0 || api.hasTypeOverlap(types)) {
const apiRes = await api.searchByTitle(query);
// console.log(apiRes);
res = res.concat(apiRes);
}
}
*/
return res; return res;
} }

View file

@ -19,6 +19,7 @@ export abstract class APIModel {
return this.types.contains(type); return this.types.contains(type);
} }
// for future use (https://github.com/mProjectsCode/obsidian-media-db-plugin/issues/5)
hasTypeOverlap(types: string[]): boolean { hasTypeOverlap(types: string[]): boolean {
for (const type of types) { for (const type of types) {
if (this.hasType(type)) { if (this.hasType(type)) {

View file

@ -1,6 +1,7 @@
import {APIModel} from '../APIModel'; import {APIModel} from '../APIModel';
import {MediaTypeModel} from '../../models/MediaTypeModel'; import {MediaTypeModel} from '../../models/MediaTypeModel';
import MediaDbPlugin from '../../main'; import MediaDbPlugin from '../../main';
import {debugLog} from '../../utils/Utils';
// WIP // WIP
export class LocGovAPI extends APIModel { export class LocGovAPI extends APIModel {
@ -20,63 +21,36 @@ export class LocGovAPI extends APIModel {
} }
async searchByTitle(title: string): Promise<MediaTypeModel[]> { async searchByTitle(title: string): Promise<MediaTypeModel[]> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by Title`);
const searchUrl = `https://www.loc.gov/search/?q=${encodeURIComponent(title)}&fo=json&c=20`; const searchUrl = `https://www.loc.gov/search/?q=${encodeURIComponent(title)}&fo=json&c=20`;
const fetchData = await fetch(searchUrl); const fetchData = await fetch(searchUrl);
console.log(fetchData); debugLog(fetchData);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
debugLog(data);
console.log(data);
let ret: MediaTypeModel[] = []; let ret: MediaTypeModel[] = [];
/* throw new Error('MDB | Under construction, API implementation not finished');
for (const result of data.data) {
const type = this.typeMappings.get(result.type.toLowerCase());
if (type === undefined) {
continue;
}
if (type === 'movie' || type === 'special') {
ret.push(new MovieModel({
type: type,
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));
} else if (type === 'series' || type === 'ova') {
ret.push(new SeriesModel({
type: type,
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 SeriesModel));
}
}
*/
return ret; // return ret;
} }
async getById(item: MediaTypeModel): Promise<MediaTypeModel> { async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `https://www.loc.gov/item/{item.id}/?fo=json`; const searchUrl = `https://www.loc.gov/item/${item.id}/?fo=json`;
const fetchData = await fetch(searchUrl); const fetchData = await fetch(searchUrl);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
console.log(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());
@ -84,63 +58,8 @@ export class LocGovAPI extends APIModel {
throw Error(`${result.type.toLowerCase()} is an unsupported type.`); throw Error(`${result.type.toLowerCase()} is an unsupported type.`);
} }
/* throw new Error('MDB | Under construction, API implementation not finished');
if (type === 'movie' || type === 'special') {
const model = new MovieModel({
type: type,
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) ?? [], // return;
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',
watched: false,
lastWatched: '',
personalRating: 0,
} as MovieModel);
return model;
} else if (type === 'series' || type === 'ova') {
const model = new SeriesModel({
type: type,
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) ?? [],
studios: result.studios?.map((x: any) => x.name) ?? [],
episodes: result.episodes,
duration: result.duration ?? 'unknown',
onlineRating: result.score ?? 0,
image: result.images?.jpg?.image_url ?? '',
released: true,
airedFrom: (new Date(result.aired?.from)).toLocaleDateString() ?? 'unknown',
airedTo: (new Date(result.aired?.to)).toLocaleDateString() ?? 'unknown',
airing: result.airing,
watched: false,
lastWatched: '',
personalRating: 0,
} as SeriesModel);
return model;
}
*/
return;
} }
} }

View file

@ -3,6 +3,7 @@ import {MediaTypeModel} from '../../models/MediaTypeModel';
import {MovieModel} from '../../models/MovieModel'; import {MovieModel} from '../../models/MovieModel';
import MediaDbPlugin from '../../main'; import MediaDbPlugin from '../../main';
import {SeriesModel} from '../../models/SeriesModel'; import {SeriesModel} from '../../models/SeriesModel';
import {debugLog} from '../../utils/Utils';
export class MALAPI extends APIModel { export class MALAPI extends APIModel {
plugin: MediaDbPlugin; plugin: MediaDbPlugin;
@ -24,18 +25,18 @@ export class MALAPI extends APIModel {
} }
async searchByTitle(title: string): Promise<MediaTypeModel[]> { async searchByTitle(title: string): Promise<MediaTypeModel[]> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by Title`);
const searchUrl = `https://api.jikan.moe/v4/anime?q=${encodeURIComponent(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); const fetchData = await fetch(searchUrl);
console.log(fetchData); debugLog(fetchData);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
console.log(data); debugLog(data);
let ret: MediaTypeModel[] = []; let ret: MediaTypeModel[] = [];
@ -69,16 +70,17 @@ export class MALAPI extends APIModel {
} }
async getById(item: MediaTypeModel): Promise<MediaTypeModel> { async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `https://api.jikan.moe/v4/anime/${item.id}`; const searchUrl = `https://api.jikan.moe/v4/anime/${item.id}`;
const fetchData = await fetch(searchUrl); const fetchData = await fetch(searchUrl);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
console.log(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());

View file

@ -3,10 +3,8 @@ import {MediaTypeModel} from '../../models/MediaTypeModel';
import MediaDbPlugin from '../../main'; import MediaDbPlugin from '../../main';
import {requestUrl} from 'obsidian'; import {requestUrl} from 'obsidian';
import {MusicReleaseModel} from '../../models/MusicReleaseModel'; import {MusicReleaseModel} from '../../models/MusicReleaseModel';
import {contactEmail, pluginName} from '../../utils/Utils'; import {contactEmail, debugLog, mediaDbVersion, pluginName} from '../../utils/Utils';
// import {MusicBrainzApi} from 'musicbrainz-api';
// WIP
export class MusicBrainzAPI extends APIModel { export class MusicBrainzAPI extends APIModel {
plugin: MediaDbPlugin; plugin: MediaDbPlugin;
@ -21,26 +19,25 @@ export class MusicBrainzAPI extends APIModel {
} }
async searchByTitle(title: string): Promise<MediaTypeModel[]> { async searchByTitle(title: string): Promise<MediaTypeModel[]> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by Title`);
const searchUrl = `https://musicbrainz.org/ws/2/release-group?query=${encodeURIComponent(title)}&limit=20&fmt=json`; const searchUrl = `https://musicbrainz.org/ws/2/release-group?query=${encodeURIComponent(title)}&limit=20&fmt=json`;
const fetchData = await requestUrl({ const fetchData = await requestUrl({
url: searchUrl, url: searchUrl,
headers: { headers: {
'User-Agent': `${pluginName}/0.1.7 (${contactEmail})`, 'User-Agent': `${pluginName}/${mediaDbVersion} (${contactEmail})`,
}, },
}); });
console.log(fetchData); debugLog(fetchData);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json; const data = await fetchData.json;
debugLog(data);
console.log(data);
let ret: MediaTypeModel[] = []; let ret: MediaTypeModel[] = [];
for (const result of data['release-groups']) { for (const result of data['release-groups']) {
@ -62,10 +59,9 @@ export class MusicBrainzAPI extends APIModel {
} }
async getById(item: MediaTypeModel): Promise<MediaTypeModel> { async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(item.id)}?inc=releases+artists+tags+ratings+genres&fmt=json`; const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(item.id)}?inc=releases+artists+tags+ratings+genres&fmt=json`;
const fetchData = await requestUrl({ const fetchData = await requestUrl({
url: searchUrl, url: searchUrl,
headers: { headers: {
@ -73,10 +69,12 @@ export class MusicBrainzAPI extends APIModel {
}, },
}); });
if (fetchData.status !== 200) {
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
}
const data = await fetchData.json; const data = await fetchData.json;
debugLog(data);
console.log(data);
const result = data; const result = data;
const model = new MusicReleaseModel({ const model = new MusicReleaseModel({

View file

@ -4,6 +4,7 @@ import {MovieModel} from '../../models/MovieModel';
import MediaDbPlugin from '../../main'; import MediaDbPlugin from '../../main';
import {SeriesModel} from '../../models/SeriesModel'; import {SeriesModel} from '../../models/SeriesModel';
import {GameModel} from '../../models/GameModel'; import {GameModel} from '../../models/GameModel';
import {debugLog} from '../../utils/Utils';
export class OMDbAPI extends APIModel { export class OMDbAPI extends APIModel {
plugin: MediaDbPlugin; plugin: MediaDbPlugin;
@ -24,29 +25,28 @@ export class OMDbAPI extends APIModel {
} }
async searchByTitle(title: string): Promise<MediaTypeModel[]> { async searchByTitle(title: string): Promise<MediaTypeModel[]> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by Title`);
const searchUrl = `http://www.omdbapi.com/?s=${encodeURIComponent(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); const fetchData = await fetch(searchUrl);
if (fetchData.status === 401) { if (fetchData.status === 401) {
throw Error(`Authentication for ${this.apiName} failed. Check the API key.`); throw Error(`MDB | Authentication for ${this.apiName} failed. Check the API key.`);
} }
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
if (data.Response === 'False') { if (data.Response === 'False') {
throw Error(`Received error from ${this.apiName}: ${data.Error}`); throw Error(`MDB | Received error from ${this.apiName}: ${data.Error}`);
} }
if (!data.Search) { if (!data.Search) {
return []; return [];
} }
console.log(data.Search); debugLog(data.Search);
let ret: MediaTypeModel[] = []; let ret: MediaTypeModel[] = [];
@ -89,23 +89,23 @@ export class OMDbAPI extends APIModel {
} }
async getById(item: MediaTypeModel): Promise<MediaTypeModel> { async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `http://www.omdbapi.com/?i=${item.id}&apikey=${this.plugin.settings.OMDbKey}`; const searchUrl = `http://www.omdbapi.com/?i=${item.id}&apikey=${this.plugin.settings.OMDbKey}`;
const fetchData = await fetch(searchUrl); const fetchData = await fetch(searchUrl);
if (fetchData.status === 401) { if (fetchData.status === 401) {
throw Error(`Authentication for ${this.apiName} failed. Check the API key.`); throw Error(`MDB | Authentication for ${this.apiName} failed. Check the API key.`);
} }
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const result = await fetchData.json(); const result = await fetchData.json();
debugLog(result);
console.log(result);
if (result.Response === 'False') { if (result.Response === 'False') {
throw Error(`Received error from ${this.apiName}: ${result.Error}`); throw Error(`MDB | Received error from ${this.apiName}: ${result.Error}`);
} }
const type = this.typeMappings.get(result.Type.toLowerCase()); const type = this.typeMappings.get(result.Type.toLowerCase());

View file

@ -2,6 +2,7 @@ import {APIModel} from '../APIModel';
import {MediaTypeModel} from '../../models/MediaTypeModel'; import {MediaTypeModel} from '../../models/MediaTypeModel';
import MediaDbPlugin from '../../main'; import MediaDbPlugin from '../../main';
import {WikiModel} from '../../models/WikiModel'; import {WikiModel} from '../../models/WikiModel';
import {debugLog} from '../../utils/Utils';
export class WikipediaAPI extends APIModel { export class WikipediaAPI extends APIModel {
plugin: MediaDbPlugin; plugin: MediaDbPlugin;
@ -17,22 +18,20 @@ export class WikipediaAPI extends APIModel {
} }
async searchByTitle(title: string): Promise<MediaTypeModel[]> { async searchByTitle(title: string): Promise<MediaTypeModel[]> {
console.log(`MDB | api "${this.apiName}" queried`); console.log(`MDB | api "${this.apiName}" queried by Title`);
const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(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); const fetchData = await fetch(searchUrl);
console.log(fetchData); debugLog(fetchData);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
debugLog(data);
console.log(data);
let ret: MediaTypeModel[] = []; let ret: MediaTypeModel[] = [];
for (const result of data.query.search) { for (const result of data.query.search) {
ret.push(new WikiModel({ ret.push(new WikiModel({
type: 'wiki', type: 'wiki',
@ -48,16 +47,17 @@ export class WikipediaAPI extends APIModel {
} }
async getById(item: MediaTypeModel): Promise<MediaTypeModel> { async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
console.log(`MDB | api "${this.apiName}" queried by ID`);
const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&prop=info&pageids=${item.id}&inprop=url&format=json&origin=*`; const searchUrl = `https://en.wikipedia.org/w/api.php?action=query&prop=info&pageids=${item.id}&inprop=url&format=json&origin=*`;
const fetchData = await fetch(searchUrl); const fetchData = await fetch(searchUrl);
if (fetchData.status !== 200) { if (fetchData.status !== 200) {
throw Error(`Received status code ${fetchData.status} from an API.`); throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
} }
const data = await fetchData.json(); const data = await fetchData.json();
console.log(data); debugLog(data);
const result = Object.entries(data?.query?.pages)[0][1]; const result = Object.entries(data?.query?.pages)[0][1];
const model = new WikiModel({ const model = new WikiModel({

View file

@ -57,9 +57,7 @@ export default class MediaDbPlugin extends Plugin {
data = await this.apiManager.queryDetailedInfo(data); data = await this.apiManager.queryDetailedInfo(data);
console.log(data); // console.log(data);
data.toMetaData();
let fileContent = `---\n${data.toMetaData()}---\n`; let fileContent = `---\n${data.toMetaData()}---\n`;
@ -78,7 +76,7 @@ export default class MediaDbPlugin extends Plugin {
} }
if (templateFile) { if (templateFile) {
let template = await this.app.vault.read(templateFile); let template = await this.app.vault.cachedRead(templateFile);
// console.log(template); // console.log(template);
if (this.settings.templates) { if (this.settings.templates) {
template = replaceTags(template, data); template = replaceTags(template, data);
@ -91,9 +89,9 @@ export default class MediaDbPlugin extends Plugin {
const targetFile = await this.app.vault.create(filePath, fileContent); const targetFile = await this.app.vault.create(filePath, fileContent);
// open file // open file
const activeLeaf = this.app.workspace.getLeaf(); const activeLeaf = this.app.workspace.getUnpinnedLeaf();
if (!activeLeaf) { if (!activeLeaf) {
console.warn('No active leaf'); console.warn('MDB | no active leaf, not opening media db note');
return; return;
} }
await activeLeaf.openFile(targetFile, {state: {mode: 'source'}}); await activeLeaf.openFile(targetFile, {state: {mode: 'source'}});

View file

@ -1,6 +1,7 @@
import {App, ButtonComponent, Component, Modal, Notice, Setting, TextComponent, ToggleComponent} from 'obsidian'; import {App, ButtonComponent, Component, Modal, Notice, Setting, TextComponent, ToggleComponent} from 'obsidian';
import {MediaTypeModel} from '../models/MediaTypeModel'; import {MediaTypeModel} from '../models/MediaTypeModel';
import {APIManager} from '../api/APIManager'; import {APIManager} from '../api/APIManager';
import {debugLog} from '../utils/Utils';
export class MediaDbAdvancedSearchModal extends Modal { export class MediaDbAdvancedSearchModal extends Modal {
query: string; query: string;
@ -28,10 +29,10 @@ export class MediaDbAdvancedSearchModal extends Modal {
async search(): Promise<MediaTypeModel[]> { async search(): Promise<MediaTypeModel[]> {
console.log(this.selectedApis); debugLog(this.selectedApis);
if (!this.query || this.query.length < 3) { if (!this.query || this.query.length < 3) {
new Notice('MDB: Query to short'); new Notice('MDB | Query to short');
return; return;
} }
@ -43,7 +44,7 @@ export class MediaDbAdvancedSearchModal extends Modal {
} }
if (selectedAPICount === 0) { if (selectedAPICount === 0) {
new Notice('MDB: No API selected'); new Notice('MDB | No API selected');
return; return;
} }
@ -53,12 +54,9 @@ export class MediaDbAdvancedSearchModal extends Modal {
this.searchBtn.setDisabled(false); this.searchBtn.setDisabled(false);
this.searchBtn.setButtonText('Searching...'); this.searchBtn.setButtonText('Searching...');
console.log('MDB | query started with ' + this.query); console.log(`MDB | query started with title ${this.query}`);
const res = await this.apiManager.query(this.query, this.selectedApis); const res = await this.apiManager.query(this.query, this.selectedApis);
// console.log(res)
this.onSubmit(null, res); this.onSubmit(null, res);
} catch (e) { } catch (e) {
this.onSubmit(e); this.onSubmit(e);

View file

@ -1,6 +1,7 @@
import {App, ButtonComponent, DropdownComponent, Modal, Notice, Setting, TextComponent} from 'obsidian'; import {App, ButtonComponent, DropdownComponent, Modal, Notice, Setting, TextComponent} from 'obsidian';
import {MediaTypeModel} from '../models/MediaTypeModel'; import {MediaTypeModel} from '../models/MediaTypeModel';
import {APIManager} from '../api/APIManager'; import {APIManager} from '../api/APIManager';
import {debugLog} from '../utils/Utils';
export class MediaDbIdSearchModal extends Modal { export class MediaDbIdSearchModal extends Modal {
query: string; query: string;
@ -25,15 +26,15 @@ export class MediaDbIdSearchModal extends Modal {
async search(): Promise<MediaTypeModel> { async search(): Promise<MediaTypeModel> {
console.log(this.selectedApi); debugLog(this.selectedApi);
if (!this.query) { if (!this.query) {
new Notice('MDB: no Id entered'); new Notice('MDB | no Id entered');
return; return;
} }
if (!this.selectedApi) { if (!this.selectedApi) {
new Notice('MDB: No API selected'); new Notice('MDB | No API selected');
return; return;
} }
@ -43,16 +44,13 @@ export class MediaDbIdSearchModal extends Modal {
this.searchBtn.setDisabled(false); this.searchBtn.setDisabled(false);
this.searchBtn.setButtonText('Searching...'); this.searchBtn.setButtonText('Searching...');
console.log('MDB | query started with id ' + this.query); console.log(`MDB | query started with id ${this.query}`);
const api = this.apiManager.getApiByName(this.selectedApi); const api = this.apiManager.getApiByName(this.selectedApi);
if (!api) { if (!api) {
this.onSubmit(new Error('the selected api does not exist')); this.onSubmit(new Error('the selected api does not exist'));
} }
const res = await api.getById({id: this.query} as MediaTypeModel); // TODO: fix jank const res = await api.getById({id: this.query} as MediaTypeModel); // TODO: fix jank
// console.log(res)
this.onSubmit(null, res); this.onSubmit(null, res);
} catch (e) { } catch (e) {
this.onSubmit(e); this.onSubmit(e);

View file

@ -1,18 +1,24 @@
import {MediaTypeModel} from '../models/MediaTypeModel'; import {MediaTypeModel} from '../models/MediaTypeModel';
export const pluginName: string = 'obsidian-media-db-plugin';
export const contactEmail: string = 'm.projects.code@gmail.com';
export const mediaDbTag: string = 'mediaDB';
export const mediaDbVersion: string = '0.1.7';
export const debug: boolean = false;
export function wrapAround(value: number, size: number): number { export function wrapAround(value: number, size: number): number {
return ((value % size) + size) % size; return ((value % size) + size) % size;
} }
export function sleep(ms: number) { export function debugLog(o: any): void {
return new Promise(resolve => setTimeout(resolve, ms)); if (debug) {
console.log(o);
}
} }
export function getFileName(item: MediaTypeModel) { export function replaceIllegalFileNameCharactersInString(string: string): string {
return replaceIllegalFileNameCharactersInString(item.year ? `${item.title} (${item.year})` : `${item.title}`);
}
export function replaceIllegalFileNameCharactersInString(string: string) {
return string.replace(/[\\,#%&{}/*<>$"@.?]*/g, '').replace(/:+/g, ' -'); return string.replace(/[\\,#%&{}/*<>$"@.?]*/g, '').replace(/:+/g, ' -');
} }
@ -79,7 +85,3 @@ function traverseMetaData(path: Array<string>, mediaTypeModel: MediaTypeModel):
return o; return o;
} }
export const pluginName = 'obsidian-media-db-plugin';
export const contactEmail = 'm.projects.code@gmail.com';
export const mediaDbTag = 'mediaDB';