Skip to content

Unofficial library to simplify API usage of MyAnimeList.com

License

Notifications You must be signed in to change notification settings

Camelva/myanimelist-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MyAnimeList-Go

PkgGoDev Build Status Go Report Card

MyAnimeList-Go is a small library to simplify your usage of MyAnimeList' API

According to official API documentation, current version of API labeled as Beta. Considering this, MyAnimeList-Go can't be called Stable too. But still, at this moment library fully covers all available methods of current API version (v2.0.0).

Table of contents

click to open

Installation

Library was tested to be working at v1.7+, but it is recommended to use v1.11+

import "github.com/camelva/myanimelist-go"  

Preparing

Before using API you need to obtain your MyAnimeList client's ID and Secret keys first. It can be achieved by creating new Application. For this, simply head to Settings => API. Or just use this link. Then, click on Create ID button and fill required fields.
After that, you can find Client ID and Client Secret fields inside your newly created app. Copy them to safe place - we will need them soon.

MyAnimeList Application info

Usage

Creating instance

To create new instance you just need to pass Config structure to myanimelist.New(). Example code below:

package main

import (
	"github.com/camelva/myanimelist-go"
	"log"
	"net/http"
	"time"
)

func main() {
	config := myanimelist.Config{
		ClientID: "clientid",
		ClientSecret: "clientsecret",
		RedirectURL: "https://example.com/anime/callback",
		// Optional
		// HTTPClient: *http.Client{Timeout: 5 * time.Second}
		// Logger: *log.Logger{}
	}
	mal, err := myanimelist.New(config)
	if err != nil {
		log.Fatal(err)
	}
	// do stuff
}

Here you use Client ID and Client Secret, obtained on previous step.
Also make sure you added your Redirect URL to MyAnimeList' application settings, otherwise it will not work.

Reference: New()


Authorization

Every method of API requires user's Access Token, so its good idea to auth as soon as possible.
MyAnimeList uses OAuth2, so whole process consist of 2 steps: heading user to MyAnimeList's Login page and exchanging received temporaty token for long-term access token.

Reference: Auth.LoginURL() | Auth.ExchangeToken()

Example code:

package main

import (
	"github.com/camelva/myanimelist-go"
	"log"
	"net/http"
)

// imagine we already made initialization
var mal = &myanimelist.MAL{}

func main() {
	http.HandleFunc("/login", loginHandler)
	http.HandleFunc("/callback", callbackHandler)
	http.HandleFunc("/app", appHandler)

	log.Fatal(http.ListenAndServe(":3000", nil))
}

// Step 1: Heading user to MyAnimeList login page
func loginHandler(w http.ResponseWriter, req *http.Request) {
	// creating authorization URL
	loginPageURL := mal.Auth.LoginURL()
	// and redirecting user there
	http.Redirect(w, req, loginPageURL, http.StatusFound)
}

// Step 2: Exchanging tokens
func callbackHandler(w http.ResponseWriter, req *http.Request) {
	// gathering temporary code from request query
	code := req.FormValue("code")
	// and exchange it for long-lasting access token
	userInfo, err := mal.Auth.ExchangeToken(code)
	if err != nil {
		// handle error
		return
	}
	// optionally you can store tokens in your db or anywhere else
	_, _, _ = userInfo.AccessToken, userInfo.ExpireAt, userInfo.RefreshToken
	http.Redirect(w, req, "/app", http.StatusFound)
}

func appHandler(w http.ResponseWriter, req *http.Request) {
	if mal.Auth.GetTokenInfo().AccessToken == "" {
		http.Redirect(w, req, "/login", http.StatusFound)
	}
	// do some stuff
}

Token expiration

Every user's access tokens have certain time they are valid. Standard, its 1 month (31 day) . You can always check when token will expire by reading ExpireAt field of UserCredentials.
If token already expired - you need to ask user to do authorization steps again. But if token still valid - you can request token update and receive new token with fresh duration without even user's interaction. For this, just call mal.Auth.RefreshToken():

newCredentials, err := mal.Auth.RefreshToken()  

Reference: Auth.RefreshToken()


Get tokens

You can get your current user's tokens by running:

mal.Auth.GetTokenInfo()

Reference: Auth.GetTokenInfo()


Set tokens manually

If you have your user's tokens saved somewhere and want to continue session without forcing user to log in again - you can set tokens manually.

mal.Auth.SetTokenInfo(accessToken string, refreshToken string, expireAt time.Time)

Reference: Auth.SetTokenInfo()


Search anime (manga)

Searching is simple - just use mal.Anime.Search or mal.Manga.Searchwith your query string and PagingSettings as parameters. These requests are multi-paged, so look at Multiple pages for additional info.

Reference: Anime.Search() | Manga.Search()


Details about certain anime (manga)

For retrieving detailed info there are mal.Anime.Details and mal.Manga.Details methods. Both accepts ID as first parameter, and, optionally, names of fields to gather. By default, these methods returns AnimeDetails (or MangaDetails) struct with fields ID, Title and MainPicture. To acquire more fields - you need to explicitly specify them by yourself. You can find list of all Shared, Anime-only and Manga-only fields at Constants

Reference: Anime.Details() | Manga.Details()


Top anime (manga)

Use mal.Anime.Top or mal.Manga.Top. First parameter is RankingType, second - PagingSettings (for more info about paged results see Multiple pages). There are a couple of different ranks at MyAnimeList, you can find all of them at the official documentation - Anime ranks and Manga ranks or at library's documentation constants section.

Reference: Anime.Top() | Manga.Top()


Seasonal anime

You can get anime list of certain year's season by running

mal.Anime.Seasonal(year int, season string, sort string, settings PagingSettings)

Only year and season parameters are required, rest are optional. For season use one of these constants: SeasonWinter, SeasonSpring, SeasonSummer or SeasonFall. By passing non-zero sort parameter, you can sort result by score or number of users, added anime to their list. For this, use either SortByScore or SortByUsersLists constants. For additional info about PagingSettings see Multiple pages

Reference: Anime.Seasonal()


Anime suggestions

Get anime suggestions for current user by running:

mal.Anime.Suggestions(setting PagingSettings)

For additional info about PagingSettings see Multiple pages

Reference: Anime.Suggestions()


User information

At the moment, you can acquire information only about current user (but seems like this API method will support different usernames too)

mal.User.Info(settings PagingSetting)

For additional info about PagingSettings see Multiple pages

Reference: User.Info()


User anime (manga) list

mal.Anime.List.User(username string, status string, sort string, settings PagingSettings)
mal.Manga.List.User(username string, status string, sort string, settings PagingSettings)

Here you can use any username to request their anime/manga list. To get current user - pass empty string. By passing status you can filter response to contain only entries with same status. You can look at library documentation's constants section to find all Shared Statuses, Anime-only and Manga-only Also you can sort result by passing corresponding parameter. List of all available sort constants can also be found at documentation For additional info about PagingSettings see Multiple pages.

Reference: AnimeList.User() | MangaList.User()


Update anime (manga) status

To add entry to your list or update their statuses you should use corresponding methods:

mal.Anime.List.Update(config AnimeConfig)
mal.Manga.List.Update(config MangaConfig)

Reference: AnimeList.Update() | MangaList.Update()

Both of them require appropriate config struct. It's recommended to create them by running NewAnimeConfig(id int) (NewMangaConfig(id int)). These config structures have a bunch of helper methods to set values you want to change. Such as SetScore, SetStatus and so on. For list of all available methods see documentation reference.

Reference: AnimeConfig | MangaConfig


Remove entry from list

To remove anime from your list use mal.Anime.List.Remove(id int) or mal.Manga.List.Remove(id int) for manga. If there is no entry with such id in your list - call still considered as successful and returns no error.

Reference: AnimeList.Remove() | MangaList.Remove()


Forum

Forum boards

mal.Forum.Boards()

Returns information about all forum categories, boards and sub-boards

Reference: Forum.Boards()


Forum search

Forum search provided by

mal.Forum.Search(searchOpts ForumSearchSettings, settings PagingSettings)

ForumSearchSettings contain all your search parameters. There is no required fields, but you need to fill at least one of them. See documentation for additional info. For additional info about PagingSettings see Multiple pages.

Reference: Forum.Search() | ForumSearchSettings


Forum topic information

To acquire information about certain topic use:

mal.Forum.Topic(id int, settings PagingSettings)

For additional info about PagingSettings see Multiple pages

Reference: Forum.Topic()

Multiple pages

Some requests (such as Anime.Top()) returns a lot of data, so result split into multiple pages.
You can detect such functions by having a special input parameter - struct PagingSettings with two fields: limit and offset (of course you can specify only field you need, or even leave both at zero).
These functions' returned value (let's call it PagedResult) is always struct with, among other things, field Paging. This field contains URLs to next and previous pages accordingly. So, for simplified usage, every of such PagedResult structures have Next and Prev methods. Which optionally accepts new limit value as parameters.

Example usage:

package main

import (
	"github.com/camelva/myanimelist-go"
)

// imagine we already made initialization
var mal = &myanimelist.MAL{}

func main() {
	// lets request 10 top anime, ranked by popularity
	popularAnime, err := mal.Anime.Top(
		myanimelist.RankByPopularity,
		myanimelist.PagingSettings{Limit: 10})
	if err != nil {
		panic(err) // example error handling
	}
    // showed result to user or something else
    // but now we want to get another 10 top anime
    morePopularAnime, err := popularAnime.Next()
    if err != nil {
    	panic(err) // example error handling
    }
    // and now we want more, but only 5
    anotherPopularAnime, err := morePopularAnime.Next(5)
    if err != nil {
    	panic(err) // example error handling
    }
    _ = anotherPopularAnime // do something with result
}  

Contributing

  1. Fork it (https://github.com/Camelva/myanimelist-go/fork)
  2. Create your feature branch (git checkout -b feature/fooBar)
  3. Commit your changes (git commit -am 'Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

References

About

Unofficial library to simplify API usage of MyAnimeList.com

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages