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).
click to open
- Installation
- Preparing
- Usage
Library was tested to be working at v1.7+
, but it is recommended to use v1.11+
import "github.com/camelva/myanimelist-go"
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.
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()
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
}
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()
You can get your current user's tokens by running:
mal.Auth.GetTokenInfo()
Reference: Auth.GetTokenInfo()
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()
Searching is simple - just use mal.Anime.Search
or mal.Manga.Search
with 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()
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()
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()
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()
Get anime suggestions for current user by running:
mal.Anime.Suggestions(setting PagingSettings)
For additional info about PagingSettings
see Multiple pages
Reference: Anime.Suggestions()
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()
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()
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
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()
mal.Forum.Boards()
Returns information about all forum categories, boards and sub-boards
Reference: Forum.Boards()
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
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()
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
}
- Fork it (https://github.com/Camelva/myanimelist-go/fork)
- Create your feature branch (
git checkout -b feature/fooBar
) - Commit your changes (
git commit -am 'Add some fooBar'
) - Push to the branch (
git push origin feature/fooBar
) - Create a new Pull Request