Skip to content

Commit abab2cd

Browse files
Merge pull request #6 from mProjectsCode/master
merge master into release for 0.1.8
2 parents e138b19 + 41ca791 commit abab2cd

21 files changed

+479
-149
lines changed

README.md

Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Obsidian Media DB Plugin
22

3-
A plugin that can query multiple APIs for movies, series, anime and games, and import them into your vault.
3+
A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault.
44

55
### Features
66
#### Search by Title
@@ -10,72 +10,63 @@ Search a movie, series, anime or game by its name across multiple APIs.
1010
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.
1111

1212
#### Templates
13-
The plugin allows you to set a template note that gets added to the end of any note created by this plugin.
14-
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.
13+
The plugin allows you to set a template note that gets added to the end of any note created by this plugin.
14+
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.
1515
Note that "template tags" are surrounded with two curly braces and that the spaces inside the curly braces are important.
1616

1717
For arrays there are two special ways of displaying them.
1818
- using `{{ LIST:variable_name }}` will result in
19-
```
20-
- element 1
21-
- element 2
22-
- element 3
23-
- ...
24-
```
19+
```
20+
- element 1
21+
- element 2
22+
- element 3
23+
- ...
24+
```
2525
- using `{{ ENUM:variable_name }}` will result in
26-
```
27-
element 1, element 2, element 3, ...
28-
```
29-
26+
```
27+
element 1, element 2, element 3, ...
28+
```
29+
3030

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

3333
### Currently supported media types
3434
- movies (including specials)
3535
- series (including OVAs)
3636
- games
37+
- music releases
38+
- wiki articles
3739

3840
### Currently supported APIs:
39-
- [Jikan](https://jikan.moe/), an API that uses [My Anime List](https://myanimelist.net)
40-
- supported formats
41-
- series
42-
- movies
43-
- specials
44-
- OVAs
45-
- authentication
46-
- no authentication or API key needed
47-
- SFW filter support
48-
- yes
49-
- Search by ID
50-
- the ID you need is the ID of the anime on [My Anime List](https://myanimelist.net)
51-
- you can find this ID in the URL
52-
- e.g. for "Beyond the Boundary" the URL looks like this `https://myanimelist.net/anime/18153/Kyoukai_no_Kanata` so the ID is `18153`
53-
- notes
54-
- sometimes the api is very slow, this is normal
55-
- you need to use the title the anime has on [My Anime List](https://myanimelist.net), which is in most cases the japanese title
56-
- e.g. instead of "Demon Slayer" you have to search "Kimetsu no Yaiba"
57-
- the API is rate limited to
58-
- 60 requests per minute
59-
- 3 requests per second
41+
| Name | Description | Supported formats | Authentification | Rate limiting | SFW filter support |
42+
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------- | ------------------------------ | ------------------ |
43+
| [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 |
44+
| [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 |
45+
| [MusicBrainz](https://musicbrainz.org/) | MusicBrainz is an API that offers information about music releases. | music releases | No | 50 per second | No |
46+
| [Wikipedia](https://en.wikipedia.org/wiki/Main_Page) | The Wikipedia API allows acces to all Wikipedia articles. | wiki articles | No | None | No | | | | | | |
47+
48+
#### Notes
49+
- [Jikan](https://jikan.moe/)
50+
- sometimes the api is very slow, this is normal
51+
- you need to use the title the anime has on [My Anime List](https://myanimelist.net), which is in most cases the japanese title
52+
- e.g. instead of "Demon Slayer" you have to search "Kimetsu no Yaiba"
53+
54+
#### Search by ID
55+
- [Jikan](https://jikan.moe/)
56+
- the ID you need is the ID of the anime on [My Anime List](https://myanimelist.net)
57+
- you can find this ID in the URL
58+
- e.g. for "Beyond the Boundary" the URL looks like this `https://myanimelist.net/anime/18153/Kyoukai_no_Kanata` so the ID is `18153`
6059
- [OMDb](https://www.omdbapi.com/)
61-
- supported formats
62-
- series
63-
- movies
64-
- games
65-
- authentication
66-
- an API key is needed
67-
- you can get one [here](https://www.omdbapi.com/apikey.aspx) for free
68-
- SFW filter support
69-
- no, but I haven't encountered any NSFW content while developing this plugin
70-
- Search by ID
71-
- the ID you need is the ID of the movie or show on [IMDb](https://www.imdb.com)
72-
- you can find this ID in the URL
73-
- e.g. for "Rogue One" the URL looks like this `https://www.imdb.com/title/tt3748528/` so the ID is `tt3748528`
74-
- notes
75-
- the api is rate limited to 1000 requests a day
76-
60+
- the ID you need is the ID of the movie or show on [IMDb](https://www.imdb.com)
61+
- you can find this ID in the URL
62+
- e.g. for "Rogue One" the URL looks like this `https://www.imdb.com/title/tt3748528/` so the ID is `tt3748528`
63+
- [MusicBrainz](https://musicbrainz.org/)
64+
- the id of a release is not easyly accessibe, you are better of just searching by title
65+
- [Wikipedia](https://en.wikipedia.org/wiki/Main_Page)
66+
- [here](https://en.wikipedia.org/wiki/Wikipedia:Finding_a_Wikidata_ID) is a guide to finding the Wikipedia ID for an article
67+
7768
### Contributions
78-
Thank you for wanting to contribute to this project.
69+
Thank you for wanting to contribute to this project.
7970

8071
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.
8172

manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"id": "obsidian-media-db-plugin",
33
"name": "Media DB Plugin",
4-
"version": "0.1.7",
4+
"version": "0.1.8",
55
"minAppVersion": "0.14.0",
6-
"description": "A plugin that can query multiple APIs for movies, series, anime and games, and import them into your vault.",
6+
"description": "A plugin that can query multiple APIs for movies, series, anime, games, music and wiki articles, and import them into your vault. ",
77
"author": "Moritz Jung",
88
"authorUrl": "https://mprojectscode.github.io/",
99
"isDesktopOnly": false

src/api/APIManager.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {APIModel} from './APIModel';
22
import {MediaTypeModel} from '../models/MediaTypeModel';
3+
import {debugLog} from '../utils/Utils';
34

45
export class APIManager {
56
apis: APIModel[];
@@ -9,28 +10,17 @@ export class APIManager {
910
}
1011

1112
async query(query: string, apisToQuery: any): Promise<MediaTypeModel[]> {
12-
console.log('MDB | api manager queried');
13+
debugLog(`MDB | api manager queried with "${query}"`);
1314

1415
let res: MediaTypeModel[] = [];
1516

1617
for (const api of this.apis) {
1718
if (Object.keys(apisToQuery).contains(api.apiName) && apisToQuery[api.apiName]) {
1819
const apiRes = await api.searchByTitle(query);
19-
// console.log(apiRes);
2020
res = res.concat(apiRes);
2121
}
2222
}
2323

24-
/*
25-
for (const api of this.apis) {
26-
if (types.length === 0 || api.hasTypeOverlap(types)) {
27-
const apiRes = await api.searchByTitle(query);
28-
// console.log(apiRes);
29-
res = res.concat(apiRes);
30-
}
31-
}
32-
*/
33-
3424
return res;
3525
}
3626

src/api/APIModel.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export abstract class APIModel {
1919
return this.types.contains(type);
2020
}
2121

22+
// for future use (https://github.com/mProjectsCode/obsidian-media-db-plugin/issues/5)
2223
hasTypeOverlap(types: string[]): boolean {
2324
for (const type of types) {
2425
if (this.hasType(type)) {

src/api/apis/LocGovAPI.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import {APIModel} from '../APIModel';
2+
import {MediaTypeModel} from '../../models/MediaTypeModel';
3+
import MediaDbPlugin from '../../main';
4+
import {debugLog} from '../../utils/Utils';
5+
6+
// WIP
7+
export class LocGovAPI extends APIModel {
8+
plugin: MediaDbPlugin;
9+
typeMappings: Map<string, string>;
10+
11+
constructor(plugin: MediaDbPlugin) {
12+
super();
13+
14+
this.plugin = plugin;
15+
this.apiName = 'loc.gov API';
16+
this.apiDescription = 'A free API for the Library of Congress collections.';
17+
this.apiUrl = 'https://libraryofcongress.github.io/data-exploration/index.html';
18+
this.types = [];
19+
this.typeMappings = new Map<string, string>();
20+
// this.typeMappings.set('movie', 'movie');
21+
}
22+
23+
async searchByTitle(title: string): Promise<MediaTypeModel[]> {
24+
console.log(`MDB | api "${this.apiName}" queried by Title`);
25+
26+
const searchUrl = `https://www.loc.gov/search/?q=${encodeURIComponent(title)}&fo=json&c=20`;
27+
const fetchData = await fetch(searchUrl);
28+
debugLog(fetchData);
29+
30+
if (fetchData.status !== 200) {
31+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
32+
}
33+
34+
const data = await fetchData.json();
35+
debugLog(data);
36+
let ret: MediaTypeModel[] = [];
37+
38+
throw new Error('MDB | Under construction, API implementation not finished');
39+
40+
// return ret;
41+
}
42+
43+
async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
44+
console.log(`MDB | api "${this.apiName}" queried by ID`);
45+
46+
const searchUrl = `https://www.loc.gov/item/${item.id}/?fo=json`;
47+
const fetchData = await fetch(searchUrl);
48+
if (fetchData.status !== 200) {
49+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
50+
}
51+
52+
const data = await fetchData.json();
53+
debugLog(data);
54+
const result = data.data;
55+
56+
const type = this.typeMappings.get(result.type.toLowerCase());
57+
if (type === undefined) {
58+
throw Error(`${result.type.toLowerCase()} is an unsupported type.`);
59+
}
60+
61+
throw new Error('MDB | Under construction, API implementation not finished');
62+
63+
// return;
64+
}
65+
}

src/api/apis/MALAPI.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {MediaTypeModel} from '../../models/MediaTypeModel';
33
import {MovieModel} from '../../models/MovieModel';
44
import MediaDbPlugin from '../../main';
55
import {SeriesModel} from '../../models/SeriesModel';
6+
import {debugLog} from '../../utils/Utils';
67

78
export class MALAPI extends APIModel {
89
plugin: MediaDbPlugin;
@@ -24,18 +25,18 @@ export class MALAPI extends APIModel {
2425
}
2526

2627
async searchByTitle(title: string): Promise<MediaTypeModel[]> {
27-
console.log(`MDB | api "${this.apiName}" queried`);
28+
console.log(`MDB | api "${this.apiName}" queried by Title`);
2829

29-
const searchUrl = `https://api.jikan.moe/v4/anime?q=${title}&limit=20${this.plugin.settings.sfwFilter ? '&sfw' : ''}`;
30+
const searchUrl = `https://api.jikan.moe/v4/anime?q=${encodeURIComponent(title)}&limit=20${this.plugin.settings.sfwFilter ? '&sfw' : ''}`;
3031

3132
const fetchData = await fetch(searchUrl);
32-
console.log(fetchData);
33+
debugLog(fetchData);
3334
if (fetchData.status !== 200) {
34-
throw Error(`Received status code ${fetchData.status} from an API.`);
35+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
3536
}
3637
const data = await fetchData.json();
3738

38-
console.log(data);
39+
debugLog(data);
3940

4041
let ret: MediaTypeModel[] = [];
4142

@@ -69,16 +70,17 @@ export class MALAPI extends APIModel {
6970
}
7071

7172
async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
73+
console.log(`MDB | api "${this.apiName}" queried by ID`);
7274

7375
const searchUrl = `https://api.jikan.moe/v4/anime/${item.id}`;
74-
7576
const fetchData = await fetch(searchUrl);
77+
7678
if (fetchData.status !== 200) {
77-
throw Error(`Received status code ${fetchData.status} from an API.`);
79+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
7880
}
7981

8082
const data = await fetchData.json();
81-
console.log(data);
83+
debugLog(data);
8284
const result = data.data;
8385

8486
const type = this.typeMappings.get(result.type.toLowerCase());

src/api/apis/MusicBrainzAPI.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import {APIModel} from '../APIModel';
2+
import {MediaTypeModel} from '../../models/MediaTypeModel';
3+
import MediaDbPlugin from '../../main';
4+
import {requestUrl} from 'obsidian';
5+
import {MusicReleaseModel} from '../../models/MusicReleaseModel';
6+
import {contactEmail, debugLog, mediaDbVersion, pluginName} from '../../utils/Utils';
7+
8+
export class MusicBrainzAPI extends APIModel {
9+
plugin: MediaDbPlugin;
10+
11+
constructor(plugin: MediaDbPlugin) {
12+
super();
13+
14+
this.plugin = plugin;
15+
this.apiName = 'MusicBrainz API';
16+
this.apiDescription = 'Free API for music albums.';
17+
this.apiUrl = 'https://musicbrainz.org/';
18+
this.types = ['music'];
19+
}
20+
21+
async searchByTitle(title: string): Promise<MediaTypeModel[]> {
22+
console.log(`MDB | api "${this.apiName}" queried by Title`);
23+
24+
const searchUrl = `https://musicbrainz.org/ws/2/release-group?query=${encodeURIComponent(title)}&limit=20&fmt=json`;
25+
26+
const fetchData = await requestUrl({
27+
url: searchUrl,
28+
headers: {
29+
'User-Agent': `${pluginName}/${mediaDbVersion} (${contactEmail})`,
30+
},
31+
});
32+
33+
debugLog(fetchData);
34+
35+
if (fetchData.status !== 200) {
36+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
37+
}
38+
39+
const data = await fetchData.json;
40+
debugLog(data);
41+
let ret: MediaTypeModel[] = [];
42+
43+
for (const result of data['release-groups']) {
44+
ret.push(new MusicReleaseModel({
45+
type: 'musicRelease',
46+
title: result.title,
47+
englishTitle: result.title,
48+
year: (new Date(result['first-release-date'])).getFullYear().toString(),
49+
dataSource: this.apiName,
50+
url: '',
51+
id: result.id,
52+
53+
artists: result['artist-credit'].map((a: any) => a.name),
54+
subType: result['primary-type'],
55+
} as MusicReleaseModel));
56+
}
57+
58+
return ret;
59+
}
60+
61+
async getById(item: MediaTypeModel): Promise<MediaTypeModel> {
62+
console.log(`MDB | api "${this.apiName}" queried by ID`);
63+
64+
const searchUrl = `https://musicbrainz.org/ws/2/release-group/${encodeURIComponent(item.id)}?inc=releases+artists+tags+ratings+genres&fmt=json`;
65+
const fetchData = await requestUrl({
66+
url: searchUrl,
67+
headers: {
68+
'User-Agent': `${pluginName}/0.1.7 (${contactEmail})`,
69+
},
70+
});
71+
72+
if (fetchData.status !== 200) {
73+
throw Error(`MDB | Received status code ${fetchData.status} from an API.`);
74+
}
75+
76+
const data = await fetchData.json;
77+
debugLog(data);
78+
const result = data;
79+
80+
const model = new MusicReleaseModel({
81+
type: 'musicRelease',
82+
title: result.title,
83+
englishTitle: result.title,
84+
year: (new Date(result['first-release-date'])).getFullYear().toString(),
85+
dataSource: this.apiName,
86+
url: '',
87+
id: result.id,
88+
89+
artists: result['artist-credit'].map((a: any) => a.name),
90+
genres: result.genres.map((g: any) => g.name),
91+
subType: result['primary-type'],
92+
rating: result.rating.value * 2,
93+
} as MusicReleaseModel);
94+
95+
return model;
96+
}
97+
}

0 commit comments

Comments
 (0)