Skip to content

klawingco/mal-management-JS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MAL Management JS

License Downloads

At first with the roll out of new MAL v2 api, I just want to play around th api itself however I find it inconvenient to do different call to each of items I needed off the api.

This library is heavily inspired from contentful-management.js, and actually created because I want to manage my anime using a globally installed CLI . But in order to create a cli, a good wrapper that is easy to use, fluent, developer friendly and removes the pain staking part of api call creation is needed, hence the project is born.

Current Features available

  • Public Anime
  • Public Manga
  • Public Forum
  • User Profile (Authenticated)

In flight

  • Update User Manga and Anime Entries

Installation

Yarn

yarn add mal-management-js

Npm

npm install mal-management-js

Usage

  1. Instantiating the Client
  2. Anime List
  3. Anime Detail
  4. Anime Ranking List
  5. Seasonal Anime List
  6. Manga List
  7. Manga Detail
  8. Manga Ranking List
  9. Forum Boards List
  10. Forum Topics List
  11. Forum Topic Detail
  12. User Profile
  13. Logging
  14. Field Cheatsheet
  15. Gotchas
  16. Future Plans

Instantiating the Client

For accessing public data only

import mal from 'mal-management-js'
...
const client = mal.createClient({
  clientId: CLIENT_ID
})

If you need to use user authenticated endpoints.

import mal from 'mal-management-js'
// import {createClient} from 'mal-management-js'
...
const client = mal.createClient({
  accessToken: ACCESS_TOKEN,
})

CommonJS

const mal = require('mal-management-js')
...
const client = mal.createClient({
  clientId: CLIENT_ID
})

NSFW

By default NSFW are automatically filtered out, if you want to include nsfw entries, you could instantiate the createClient with .allowNSFW() extension. This setting will affect all of subsequent request and is useful for setting general NSFW rule.

const client = mal.createClient({
  clientId: CLIENT_ID
}).allowNSFW()

Alternatively, you could also give it to CreateClientOptions as a nsfw option

const client = mal.createClient({
  clientId: CLIENT_ID,
  nsfw: true
})

Client Extension functions

Function Description
.allowNSFW() Allows showing of nsfw entries ( ͡° ͜ʖ ͡°)
.setRequestLogger(request=> void) Add a custom request logger (See logging)
.setResponseLogger(request=> void) Add a custom response logger (See logging)

Getting Anime List

Using async await

const animes: Anime[] = await client
  .getAnime({ q: 'Jujutsu Kaisen', fields:[...] })

Using Promise

client.getAnime({ q: 'Jujutsu Kaisen' })
  .then(animes => console.log(animes))

Both of approach mentioned can be chained with .catch for error busting and such.

Full Configuration Options (AnimeListOptions)

Options Description
q Search String
fields (optional) Use to add additional fields the api should return. See field cheatsheet
nsfw (optional) If global allowNSFW() is not present, you could use this option to explicitly allow nsfw for the current request
limit (optional) Pagination
offset (optional) Pagination


Getting Anime Detail

For example you just want to get the detail of the first result from getAnime().

const animes = await client
  .getAnime({ q: 'Jujutsu Kaisen' })
const anime = await animes[0].getDetail()    

You could also configure the fields you want to show using fields options

const animes = await client
  .getAnime({ q: 'Jujutsu Kaisen' })
const anime = await animes[0].getDetail({fields: [...]})

Alternatively If you have the id of the anime, you could directly get the anime details using client

const animeDetail = await client
.getAnimeDetail({
    id: 30276,
    // Using TS Enums
    fields: [AnimeFields.alternative_titles, AnimeFields.start_date], 
    // Or using string
    // fields:  ['alternative_titles', 'start_date']
})
Full Configuration Options (AnimeDetailOptions)

Options Description
id anime id
fields (optional) Use to add additional fields the api should return. See field cheatsheet


Getting Anime Ranking List

const animeRanking = await client
  .getAnimeRanking({
    ranking_type: 'airing', 
    fields: [AnimeFields.alternative_titles, AnimeFields.start_date],
  })

Pro-tip: If you are on typescript There's a exposed Typescript Type called AnimeRankingType

type AnimeRankingType = 'all' | 'airing' |'upcoming' |'tv' |'ova' |'movie' | 'special' |'bypopularity' |'favorite'
Full Configuration Options (AnimeRankingListOptions)

Options Description
ranking_type Specifying the ranking criteria See AnimeRankingType
fields (optional) Use to add additional fields the api should return. See field cheatsheet
nsfw (optional) If global allowNSFW() is not present, you could use this option to explicitly allow nsfw for the current request
limit (optional) Pagination
offset (optional) Pagination


Getting Seasonal Anime List

const animeSeasonal = await client
  .getAnimeSeasonal({
    year: 2020,
    season: 'fall',
    sort: 'anime_score',
    fields: [AnimeFields.alternative_titles, AnimeFields.start_date],
  })

Pro-tip: If you are on typescript There's a exposed Typescript Type called AnimeSeason and AnimeSortType

type AnimeSeason = 'winter' | 'spring' | 'summer' | 'fall'

type AnimeSortType = 'anime_score' | 'anime_num_list_users'
Full Configuration Options (AnimeSeasonalListOptions)

Options Description
year target year
season Specify what airing season See AnimeSeason
sort Specify what sort criteria. See AnimeSortType
fields (optional) Use to add additional fields the api should return. See field cheatsheet
nsfw (optional) If global allowNSFW() is not present, you could use this option to explicitly allow nsfw for the current request
limit (optional) Pagination
offset (optional) Pagination


Getting Manga List

Using async await

const mangas: Manga[] = await client
  .getManga({ q: 'Jujutsu Kaisen' })

Using Promise

client.getManga({ q: 'Jujutsu Kaisen' }).then(mangas => console.log(mangas))

Both of approach mentioned can be chained with .catch for error busting and such. Specifiying Fields are also available.

Full Configuration Options (MangaListOptions)

Options Description
q Search String
fields (optional) Use to add additional fields the api should return. See field cheatsheet
nsfw (optional) If global allowNSFW() is not present, you could use this option to explicitly allow nsfw for the current request
limit (optional) Pagination
offset (optional) Pagination


Getting Manga Detail

For example you just want to get the detail of the first result from getManga(). You could chain it like this

const mangas = await client
  .getManga({ q: 'Jujutsu Kaisen' })
const manga = mangas[0].getDetail()

You could also configure the fields you want to show using fields options

const mangas = await client
  .getManga({ q: 'Jujutsu Kaisen' })
const manga =  await mangas[0].getDetail({fields: [...]})

Alternatively If you have the id of the anime, you could directly get the anime details using client

const mangaDetail = await client
.getMangaDetail({
    id: 30276,
    // Using TS Enums
    fields: [MangaFields.mean,
        MangaFields.num_chapters,
        MangaFields.media_type], 
    // Or using string
    // fields:  ['alternative_titles', 'start_date']
})
Full Configuration Options (MangaDetailOptions)

Options Description
id manga id
fields (optional) Use to add additional fields the api should return. See field cheatsheet


Getting Manga Ranking List

const mangaRanking = await client
  .getMangaRanking({
    ranking_type: 'all', 
    fields: [...],
  })

Pro-tip: If you are on typescript There's a exposed Typescript Type called MangaRankingType

export type MangaRankingType = 'all' | 'manga' | 'novels' | 'oneshots' |'doujin' | 'manhwa' | 'manhua' | 'bypopularity'| 'favorite'
Full Configuration Options (MangaRankingListOptions)

Options Description
ranking_type Specifying the ranking criteria See MangaRankingType
fields (optional) Use to add additional fields the api should return. See field cheatsheet
nsfw (optional) If global allowNSFW() is not present, you could use this option to explicitly allow nsfw for the current request
limit (optional) Pagination
offset (optional) Pagination


Getting Main Forum Boards

This will return all of Main Forum Boards Categories

const forumBoards: ForumBoardCategory[] = await client.getForumBoard();

Note that at the moment MAL only return Main Boards. Hence reason that Subboards is not yet available.


Getting Forum Topics

This will query against all Board Topics

const forumTopics = await client.getForumTopics({
  q: "love"
})

If you want to specify a board or a subboard

const forumTopics = await client.getForumTopics({
  board_id: 2,
  subboard_id: 3,
  q: "love"
})
Full Configuration Options (ForumTopicOptions)

Options Description
board_id Id of the board topic you want to search against
subboard_id Id of the subboard topic you want to search against
sort MAL only has recent available at the moment
q Search String
topic_user_name Use to filter using topic_user_name
user_name Use to filter using user_name that participated
limit Pagination
offset Pagination


Getting Forum Topic Detail

This gives details about all of posts, poll and title related to the topic

Similar to Anime and Manga, you could also get a injected getDetail() to each of instances of Forum Topic

const forumTopics = await client.getForumTopics({
  q: "love"
})
const oregairu = await forumTopics[0].getDetail()

Or if you have the topic id

  const forumDetail = await client.getForumTopicDetail({
    id: 614681, //topic id
    limit: 10,
  })
  console.log('OreGairu ', forumDetail)  
Full Configuration Options (ForumTopicDetailOptions)

Options Description
id Id of the topic.
limit Pagination
offset Pagination


Getting User Profile

AUTHENTICATION NEEDED ! Client must be instantiated with accessToken option.

This will get the user's profile.

const userProfile = await client.getUserProfile()

Or if you want to specify additional user fields

const userProfile = await client.getUserProfile({
  // Using TS enums
  fields: [UserFields.anime_statistics, UserFields.is_supporter, UserFields.time_zone]
  // Works also using string
  // fields: ['anime_statistics', 'is_supporter', 'time_zone']
})

Note: Only the current Authenticated user are allowed to get profile. No official endpoint yet are available for public profile.


Logging

mal-management-js offers a way to logged both of request and response using a extension function which is you can chain to client. This is useful for apps that is running on backend that needs robusts logging. You could implement a file logging by hooking into this.

Sample Request logging

const client = mal.createClient({
  accessToken: ACCESS_TOKEN,
}).setRequestLogger(request => {
  console.log('REQUEST URL', request.url)
  console.log('REQUEST QUERIES', request.params)
})

Field Cheatsheet

Common Fields (Applies to Both Anime and Manga)

  • alternative_titles
  • start_date
  • end_date
  • synopsis
  • mean
  • rank
  • popularity
  • num_list_users
  • num_scoring_users
  • nsfw
  • created_at
  • media_type
  • status
  • genres
  • pictures
  • background
  • related_anime
  • related_manga
  • recommendations
  • statistics
  • my_list_status

Anime Only Fields

  • num_episodes
  • start_season
  • broadcast
  • source
  • average_episode_duration
  • rating
  • studios

Manga Only Cheatsheat

  • num_volumes
  • num_chapters
  • 'authors{first_name,last_name}'
  • 'serialization{name}'

Gotchas

About fields field

Fields are way to control what fields are going to be responsed by MAL API.

At default id, title, main_picture will always be present regardless if you put it at fields or not.

Another thing is some of the field options are only available to details endpoint examples of such are

  • picture
  • background
  • related_anime
  • related_manga
  • recommendations
  • statistics

User Fields

There are also default Fields for User Profile that will always be present irregardless if you added it at fields options, namely.

  • id
  • name
  • picture
  • gender
  • birthday
  • joined_at
  • location

Future Plans

Although currently APIs that MAL offers is very limited.

The aim of this library is to be Backend and Scripts First, while technically you can use this at Front end space. The rationale was to create a wrapper tool to navigate and manage MyAnimeList via scripts and also to ease the backend integration.

For example, if in FUTURE MAL officially release an api for a Anime's characters.

This wrapper could end with api of

const anime = client.getAnimeDetail({id: 30276})
const characters = anime.getCharacters()

LICENSE

MIT

About

A Yet Another JS Wrapper for MyAnimelist API, but this time aimed more for Scripting and Backend

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •