Documentation ¶
Overview ¶
Package mal provides a client for accessing the MyAnimeList API: https://myanimelist.net/apiconfig/references/api/v2.
Installation ¶
This package can be installed using:
go get github.com/nstratos/go-myanimelist/mal
Usage ¶
Import the package using:
import "github.com/nstratos/go-myanimelist/mal"
First construct a new mal client:
c := mal.NewClient(nil)
Then use one of the client's services (User, Anime, Manga and Forum) to access the different MyAnimeList API methods.
Authentication ¶
When creating a new client, pass an `http.Client` that can handle authentication for you.
Accessing publicly available information ¶
To access public information, you need to add the ` X-MAL-CLIENT-ID` header in your requests. You can achieve this by creating an `http.Client` with a custom transport and use it as shown below:
type clientIDTransport struct { Transport http.RoundTripper ClientID string } func (c *clientIDTransport) RoundTrip(req *http.Request) (*http.Response, error) { if c.Transport == nil { c.Transport = http.DefaultTransport } req.Header.Add("X-MAL-CLIENT-ID", c.ClientID) return c.Transport.RoundTrip(req) } func main() { publicInfoClient := &http.Client{ // Create client ID from https://myanimelist.net/apiconfig. Transport: &clientIDTransport{ClientID: "<Your application client ID>"}, } c := mal.NewClient(publicInfoClient) // ... }
Authenticating using OAuth2 ¶
The recommended way is to use the golang.org/x/oauth2 package (https://github.com/golang/oauth2). After completing the OAuth2 flow, you will get an oauth2 token containing an access token, a refresh token and an expiration date. The oauth2 token can easily be stored in JSON format and used like this:
const storedToken = ` { "token_type": "Bearer", "access_token": "yourAccessToken", "refresh_token": "yourRefreshToken", "expiry": "2021-06-01T16:12:56.1319122Z" }` oauth2Token := new(oauth2.Token) _ = json.Unmarshal([]byte(storedToken), oauth2Token) // Create client ID and secret from https://myanimelist.net/apiconfig. // // Secret is currently optional if you choose App Type 'other'. oauth2Conf := &oauth2.Config{ ClientID: "<Enter your registered MyAnimeList.net application client ID>", ClientSecret: "<Enter your registered MyAnimeList.net application client secret>", Endpoint: oauth2.Endpoint{ AuthURL: "https://myanimelist.net/v1/oauth2/authorize", TokenURL: "https://myanimelist.net/v1/oauth2/token", AuthStyle: oauth2.AuthStyleInParams, }, } oauth2Client := oauth2Conf.Client(ctx, oauth2Token) // The oauth2Client will refresh the token if it expires. c := mal.NewClient(oauth2Client)
Note that all calls made by the client above will include the specified oauth2 token which is specific for an authenticated user. Therefore, authenticated clients should almost never be shared between different users.
Performing the OAuth2 flow involves registering a MAL API application and then asking for the user's consent to allow the application to access their data.
There is a detailed example of how to perform the Oauth2 flow and get an oauth2 token through the terminal under example/malauth. The only thing you need to run the example is a client ID and a client secret which you can acquire after registering your MAL API application. Here's how:
Navigate to https://myanimelist.net/apiconfig or go to your MyAnimeList profile, click Edit Profile and select the API tab on the far right.
Click Create ID and submit the form with your application details.
After registering your application, you can run the example and pass the client ID and client secret through flags:
cd example/malauth go run main.go democlient.go --client-id=... --client-secret=... or go install github.com/nstratos/go-myanimelist/example/malauth malauth --client-id=... --client-secret=...
After you perform a successful authentication once, the oauth2 token will be cached in a file under the same directory which makes it easier to run the example multiple times.
Official MAL API OAuth2 docs: https://myanimelist.net/apiconfig/references/authorization
List ¶
To search and get anime and manga data:
list, _, err := c.Anime.List(ctx, "hokuto no ken", mal.Fields{"rank", "popularity", "my_list_status"}, mal.Limit(5), ) // ... list, _, err := c.Manga.List(ctx, "hokuto no ken", mal.Fields{"rank", "popularity", "my_list_status"}, mal.Limit(5), ) // ...
You may get user specific data for a certain record by using the optional field "my_list_status".
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/anime_get
- https://myanimelist.net/apiconfig/references/api/v2#operation/manga_get
UserList ¶
To get the anime or manga list of a user:
// Get the authenticated user's anime list, filter only watching anime, sort by // last updated, include list status. anime, _, err := c.User.AnimeList(ctx, "@me", mal.Fields{"list_status"}, mal.AnimeStatusWatching, mal.SortAnimeListByListUpdatedAt, mal.Limit(5), ) // ... // Get the authenticated user's manga list's second page, sort by score, // include list status, comments and tags. manga, _, err := c.User.MangaList(ctx, "@me", mal.SortMangaListByListScore, mal.Fields{"list_status{comments, tags}"}, mal.Limit(5), mal.Offset(1), ) // ...
You may provide the username of the user or "@me" to get the authenticated user's list.
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/users_user_id_animelist_get
- https://myanimelist.net/apiconfig/references/api/v2#operation/users_user_id_mangalist_get
MyInfo ¶
To get information about the authenticated user:
user, _, err := c.User.MyInfo(ctx) // ...
This method can use the Fields option but the API doesn't seem to be able to send optional fields like "anime_statistics" at the time of writing.
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/users_user_id_get
Details ¶
To get details for a certain anime or manga:
a, _, err := c.Anime.Details(ctx, 967, mal.Fields{ "alternative_titles", "media_type", "num_episodes", "start_season", "source", "genres", "studios", "average_episode_duration", }, ) // ... m, _, err := c.Manga.Details(ctx, 401, mal.Fields{ "alternative_titles", "media_type", "num_volumes", "num_chapters", "authors{last_name, first_name}", "genres", "status", }, ) // ...
By default most fields are not populated so use the Fields option to request the fields you need.
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/anime_anime_id_get
- https://myanimelist.net/apiconfig/references/api/v2#operation/manga_manga_id_get
Ranking ¶
To get anime or manga based on a certain ranking:
anime, _, err := c.Anime.Ranking(ctx, mal.AnimeRankingAiring, mal.Fields{"rank", "popularity"}, mal.Limit(6), ) // ... manga, _, err := c.Manga.Ranking(ctx, mal.MangaRankingByPopularity, mal.Fields{"rank", "popularity"}, mal.Limit(6), ) // ...
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/anime_ranking_get
- https://myanimelist.net/apiconfig/references/api/v2#operation/manga_ranking_get
Add or Update List ¶
To add or update an entry in an authenticated user's list, provide the anime or manga ID and then options to specify the status, score, comments, tags etc.
_, _, err := c.Anime.UpdateMyListStatus(ctx, 967, mal.AnimeStatusWatching, mal.NumEpisodesWatched(73), mal.Score(8), mal.Comments("You wa shock!"), mal.StartDate(time.Date(2022, 02, 20, 0, 0, 0, 0, time.UTC)), mal.FinishDate(time.Time{}), // Remove an existing date. ) // ... _, _, err := c.Manga.UpdateMyListStatus(ctx, 401, mal.MangaStatusReading, mal.NumVolumesRead(1), mal.NumChaptersRead(5), mal.Comments("Migi"), mal.StartDate(time.Date(2022, 02, 20, 0, 0, 0, 0, time.UTC)), mal.FinishDate(time.Time{}), // Remove an existing date. ) // ...
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/anime_anime_id_my_list_status_put
- https://myanimelist.net/apiconfig/references/api/v2#operation/manga_manga_id_my_list_status_put
Delete ¶
To delete anime or manga from a user's list, simply provide their IDs:
_, err := c.Anime.DeleteMyListItem(ctx, 967) // ... _, err := c.Manga.DeleteMyListItem(ctx, 401) // ...
Official docs:
- https://myanimelist.net/apiconfig/references/api/v2#operation/anime_anime_id_my_list_status_delete
- https://myanimelist.net/apiconfig/references/api/v2#operation/manga_manga_id_my_list_status_delete
More Examples ¶
See package examples: https://pkg.go.dev/github.com/nstratos/go-myanimelist/mal#pkg-examples
Unit Testing ¶
To run all unit tests:
go test -cover
To see test coverage in your browser:
go test -covermode=count -coverprofile=count.out && go tool cover -html count.out
Integration Testing ¶
The integration tests will exercise the entire package against the live MyAnimeList API. As a result, these tests take much longer to run and there is also a much higher chance of false positives in test failures due to network issues etc.
These tests are meant to be run using a dedicated test account that contains empty anime and manga lists. A valid oauth2 token needs to be provided every time. Check the authentication section to learn how to get one.
By default the integration tests are skipped when an oauth2 token is not provided. To run all tests including the integration tests:
go test --client-id='<your app client ID>' --oauth2-token='<your oauth2 token>'
License ¶
MIT
Example (OAuth2) ¶
package main import ( "context" _ "embed" "encoding/json" "fmt" "net/http" "github.com/nstratos/go-myanimelist/mal" "golang.org/x/oauth2" ) func newOAuth2Client(ctx context.Context) *http.Client { // In order to create a client ID and secret for your application: // // 1. Navigate to https://myanimelist.net/apiconfig or go to your MyAnimeList // profile, click Edit Profile and select the API tab on the far right. // 2. Click Create ID and submit the form with your application details. oauth2Conf := &oauth2.Config{ ClientID: "<Enter your MyAnimeList.net application client ID>", ClientSecret: "<Enter your MyAnimeList.net application client secret>", // Optional if you chose App Type 'other'. Endpoint: oauth2.Endpoint{ AuthURL: "https://myanimelist.net/v1/oauth2/authorize", TokenURL: "https://myanimelist.net/v1/oauth2/token", AuthStyle: oauth2.AuthStyleInParams, }, } // To get your first token you need to complete the oauth2 flow. There is a // detailed example that uses the terminal under `example/malauth` which you // should adjust for your application. // // Here we assume we have already received our first valid token and stored // it somewhere in JSON format. const storedToken = ` { "token_type": "Bearer", "access_token": "yourAccessToken", "refresh_token": "yourRefreshToken", "expiry": "2021-06-01T16:12:56.1319122Z" }` // Decode stored token to oauth2.Token struct. oauth2Token := new(oauth2.Token) _ = json.Unmarshal([]byte(storedToken), oauth2Token) // The oauth2 client returned here with the above configuration and valid // token will refresh the token seamlessly when it expires. return oauth2Conf.Client(ctx, oauth2Token) } func main() { ctx := context.Background() oauth2Client := newOAuth2Client(ctx) c := mal.NewClient(oauth2Client) user, _, err := c.User.MyInfo(ctx) if err != nil { fmt.Printf("User.MyInfo error: %v", err) return } fmt.Printf("ID: %5d, Joined: %v, Username: %s\n", user.ID, user.JoinedAt.Format("Jan 2006"), user.Name) }
Output:
Index ¶
- Constants
- type Anime
- type AnimeListOption
- type AnimeListStatus
- type AnimeRanking
- type AnimeSeason
- type AnimeService
- func (s *AnimeService) DeleteMyListItem(ctx context.Context, animeID int) (*Response, error)
- func (s *AnimeService) Details(ctx context.Context, animeID int, options ...DetailsOption) (*Anime, *Response, error)
- func (s *AnimeService) List(ctx context.Context, search string, options ...Option) ([]Anime, *Response, error)
- func (s *AnimeService) Ranking(ctx context.Context, ranking AnimeRanking, options ...Option) ([]Anime, *Response, error)
- func (s *AnimeService) Seasonal(ctx context.Context, year int, season AnimeSeason, ...) ([]Anime, *Response, error)
- func (s *AnimeService) Suggested(ctx context.Context, options ...Option) ([]Anime, *Response, error)
- func (s *AnimeService) UpdateMyListStatus(ctx context.Context, animeID int, options ...UpdateMyAnimeListStatusOption) (*AnimeListStatus, *Response, error)
- type AnimeStatistics
- type AnimeStatus
- type Author
- type BoardID
- type Broadcast
- type Client
- type Comments
- type CreatedBy
- type DetailsOption
- type ErrorResponse
- type Fields
- type FinishDate
- type Forum
- type ForumBoard
- type ForumCategory
- type ForumService
- func (s *ForumService) Boards(ctx context.Context) (*Forum, *Response, error)
- func (s *ForumService) TopicDetails(ctx context.Context, topicID int, options ...PagingOption) (TopicDetails, *Response, error)
- func (s *ForumService) Topics(ctx context.Context, options ...TopicsOption) ([]Topic, *Response, error)
- type ForumSubboard
- type Genre
- type IsRereading
- type IsRewatching
- type Limit
- type Magazine
- type Manga
- type MangaListOption
- type MangaListStatus
- type MangaRanking
- type MangaService
- func (s *MangaService) DeleteMyListItem(ctx context.Context, mangaID int) (*Response, error)
- func (s *MangaService) Details(ctx context.Context, mangaID int, options ...DetailsOption) (*Manga, *Response, error)
- func (s *MangaService) List(ctx context.Context, search string, options ...Option) ([]Manga, *Response, error)
- func (s *MangaService) Ranking(ctx context.Context, ranking MangaRanking, options ...Option) ([]Manga, *Response, error)
- func (s *MangaService) UpdateMyListStatus(ctx context.Context, mangaID int, options ...UpdateMyMangaListStatusOption) (*MangaListStatus, *Response, error)
- type MangaStatus
- type MyInfoOption
- type NSFW
- type NumChaptersRead
- type NumEpisodesWatched
- type NumTimesReread
- type NumTimesRewatched
- type NumVolumesRead
- type Offset
- type Option
- type Paging
- type PagingOption
- type Person
- type Picture
- type Poll
- type PollOption
- type Post
- type Priority
- type Query
- type RecommendedAnime
- type RecommendedManga
- type RelatedAnime
- type RelatedManga
- type RereadValue
- type Response
- type RewatchValue
- type Score
- type SeasonalAnimeOption
- type Serialization
- type SortAnimeList
- type SortMangaList
- type SortSeasonalAnime
- type StartDate
- type StartSeason
- type Statistics
- type Status
- type Studio
- type SubboardID
- type Tags
- type Titles
- type Topic
- type TopicDetails
- type TopicUserName
- type TopicsOption
- type UpdateMyAnimeListStatusOption
- type UpdateMyMangaListStatusOption
- type User
- type UserAnime
- type UserManga
- type UserName
- type UserService
- func (s *UserService) AnimeList(ctx context.Context, username string, options ...AnimeListOption) ([]UserAnime, *Response, error)
- func (s *UserService) MangaList(ctx context.Context, username string, options ...MangaListOption) ([]UserManga, *Response, error)
- func (s *UserService) MyInfo(ctx context.Context, options ...MyInfoOption) (*User, *Response, error)
Examples ¶
- Package (OAuth2)
- AnimeService.DeleteMyListItem
- AnimeService.Details
- AnimeService.List
- AnimeService.Ranking
- AnimeService.Seasonal
- AnimeService.Suggested
- AnimeService.UpdateMyListStatus
- ForumService.Boards
- ForumService.TopicDetails
- ForumService.Topics
- MangaService.DeleteMyListItem
- MangaService.Details
- MangaService.List
- MangaService.Ranking
- MangaService.UpdateMyListStatus
- UserService.AnimeList
- UserService.MangaList
- UserService.MyInfo
Constants ¶
const SortTopicsRecent sortTopics = "recent"
SortTopicsRecent is the default and only sorting value for topics.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Anime ¶
type Anime struct { ID int `json:"id"` Title string `json:"title"` MainPicture Picture `json:"main_picture"` AlternativeTitles Titles `json:"alternative_titles"` StartDate string `json:"start_date"` EndDate string `json:"end_date"` Synopsis string `json:"synopsis"` Mean float64 `json:"mean"` Rank int `json:"rank"` Popularity int `json:"popularity"` NumListUsers int `json:"num_list_users"` NumScoringUsers int `json:"num_scoring_users"` NSFW string `json:"nsfw"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MediaType string `json:"media_type"` Status string `json:"status"` Genres []Genre `json:"genres"` MyListStatus AnimeListStatus `json:"my_list_status"` NumEpisodes int `json:"num_episodes"` StartSeason StartSeason `json:"start_season"` Broadcast Broadcast `json:"broadcast"` Source string `json:"source"` AverageEpisodeDuration int `json:"average_episode_duration"` Rating string `json:"rating"` Pictures []Picture `json:"pictures"` Background string `json:"background"` RelatedAnime []RelatedAnime `json:"related_anime"` RelatedManga []RelatedManga `json:"related_manga"` Recommendations []RecommendedAnime `json:"recommendations"` Studios []Studio `json:"studios"` Statistics Statistics `json:"statistics"` }
Anime represents a MyAnimeList anime.
type AnimeListOption ¶
type AnimeListOption interface {
// contains filtered or unexported methods
}
AnimeListOption are options specific to the UserService.AnimeList method.
type AnimeListStatus ¶
type AnimeListStatus struct { Status AnimeStatus `json:"status"` Score int `json:"score"` NumEpisodesWatched int `json:"num_episodes_watched"` IsRewatching bool `json:"is_rewatching"` UpdatedAt time.Time `json:"updated_at"` Priority int `json:"priority"` NumTimesRewatched int `json:"num_times_rewatched"` RewatchValue int `json:"rewatch_value"` Tags []string `json:"tags"` Comments string `json:"comments"` StartDate string `json:"start_date"` FinishDate string `json:"finish_date"` }
AnimeListStatus shows the status of each anime in a user's anime list.
type AnimeRanking ¶
type AnimeRanking string
AnimeRanking allows to choose how the anime will be ranked.
const ( // AnimeRankingAll returns the top anime series. AnimeRankingAll AnimeRanking = "all" // AnimeRankingAiring returns the top airing anime. AnimeRankingAiring AnimeRanking = "airing" // AnimeRankingUpcoming returns the top upcoming anime. AnimeRankingUpcoming AnimeRanking = "upcoming" // AnimeRankingTV returns the top Anime TV series. AnimeRankingTV AnimeRanking = "tv" // AnimeRankingOVA returns the top anime OVA series. AnimeRankingOVA AnimeRanking = "ova" // AnimeRankingMovie returns the top anime movies. AnimeRankingMovie AnimeRanking = "movie" // AnimeRankingSpecial returns the top anime specials. AnimeRankingSpecial AnimeRanking = "special" // AnimeRankingByPopularity returns the top anime by popularity. AnimeRankingByPopularity AnimeRanking = "bypopularity" // AnimeRankingFavorite returns the top favorite Anime. AnimeRankingFavorite AnimeRanking = "favorite" )
type AnimeSeason ¶
type AnimeSeason string
AnimeSeason is the airing season of the anime.
const ( // AnimeSeasonWinter is the winter season of January, February and March. AnimeSeasonWinter AnimeSeason = "winter" // AnimeSeasonSpring is the spring season of April, May and June. AnimeSeasonSpring AnimeSeason = "spring" // AnimeSeasonSummer is the summer season of July, August and September. AnimeSeasonSummer AnimeSeason = "summer" // AnimeSeasonFall is the fall season of October, November and December. AnimeSeasonFall AnimeSeason = "fall" )
type AnimeService ¶
type AnimeService struct {
// contains filtered or unexported fields
}
AnimeService handles communication with the anime related methods of the MyAnimeList API:
https://myanimelist.net/apiconfig/references/api/v2#tag/anime https://myanimelist.net/apiconfig/references/api/v2#tag/user-animelist
func (*AnimeService) DeleteMyListItem ¶
DeleteMyListItem deletes an anime from the user's list. If the anime does not exist in the user's list, 404 Not Found error is returned.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) resp, err := c.Anime.DeleteMyListItem(ctx, 967) if err != nil { fmt.Printf("Anime.DeleteMyListItem error: %v", err) return } fmt.Println(resp.Status)
Output: 200 OK
func (*AnimeService) Details ¶
func (s *AnimeService) Details(ctx context.Context, animeID int, options ...DetailsOption) (*Anime, *Response, error)
Details returns details about an anime. By default, few anime fields are populated. Use the Fields option to specify which fields should be included.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) a, _, err := c.Anime.Details(ctx, 967, mal.Fields{ "alternative_titles", "media_type", "num_episodes", "start_season", "source", "genres", "studios", "average_episode_duration", }, ) if err != nil { fmt.Printf("Anime.Details error: %v", err) return } fmt.Printf("%s\n", a.Title) fmt.Printf("ID: %d\n", a.ID) fmt.Printf("English: %s\n", a.AlternativeTitles.En) fmt.Printf("Type: %s\n", strings.ToUpper(a.MediaType)) fmt.Printf("Episodes: %d\n", a.NumEpisodes) fmt.Printf("Premiered: %s %d\n", strings.Title(a.StartSeason.Season), a.StartSeason.Year) fmt.Print("Studios: ") delim := "" for _, s := range a.Studios { fmt.Printf("%s%s", delim, s.Name) delim = " " } fmt.Println() fmt.Printf("Source: %s\n", strings.Title(a.Source)) fmt.Print("Genres: ") delim = "" for _, g := range a.Genres { fmt.Printf("%s%s", delim, g.Name) delim = " " } fmt.Println() fmt.Printf("Duration: %d min. per ep.\n", a.AverageEpisodeDuration/60)
Output: Hokuto no Ken ID: 967 English: Fist of the North Star Type: TV Episodes: 109 Premiered: Fall 1984 Studios: Toei Animation Source: Manga Genres: Action Drama Martial Arts Sci-Fi Shounen Duration: 25 min. per ep.
func (*AnimeService) List ¶
func (s *AnimeService) List(ctx context.Context, search string, options ...Option) ([]Anime, *Response, error)
List allows an authenticated user to search and list anime data. You may get user specific data by using the optional field "my_list_status".
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) anime, _, err := c.Anime.List(ctx, "hokuto no ken", mal.Fields{"rank", "popularity", "start_season"}, mal.Limit(5), mal.Offset(0), ) if err != nil { fmt.Printf("Anime.List error: %v", err) return } for _, a := range anime { fmt.Printf("ID: %5d, Rank: %5d, Popularity: %5d %s (%d)\n", a.ID, a.Rank, a.Popularity, a.Title, a.StartSeason.Year) }
Output: ID: 967, Rank: 556, Popularity: 1410 Hokuto no Ken (1984) ID: 1356, Rank: 1423, Popularity: 3367 Hokuto no Ken 2 (1987) ID: 1358, Rank: 2757, Popularity: 3964 Hokuto no Ken Movie (1986)
func (*AnimeService) Ranking ¶
func (s *AnimeService) Ranking(ctx context.Context, ranking AnimeRanking, options ...Option) ([]Anime, *Response, error)
Ranking allows an authenticated user to receive the top anime based on a certain ranking.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) anime, _, err := c.Anime.Ranking(ctx, mal.AnimeRankingAiring, mal.Fields{"rank", "popularity"}, mal.Limit(6), ) if err != nil { fmt.Printf("Anime.Ranking error: %v", err) return } for _, a := range anime { fmt.Printf("Rank: %5d, Popularity: %5d %s\n", a.Rank, a.Popularity, a.Title) }
Output: Rank: 2, Popularity: 104 Shingeki no Kyojin: The Final Season Rank: 59, Popularity: 371 Re:Zero kara Hajimeru Isekai Seikatsu 2nd Season Part 2 Rank: 67, Popularity: 1329 Yuru Camp△ Season 2 Rank: 69, Popularity: 109 Jujutsu Kaisen (TV) Rank: 83, Popularity: 3714 Holo no Graffiti Rank: 85, Popularity: 304 Horimiya
func (*AnimeService) Seasonal ¶
func (s *AnimeService) Seasonal(ctx context.Context, year int, season AnimeSeason, options ...SeasonalAnimeOption) ([]Anime, *Response, error)
Seasonal allows an authenticated user to receive the seasonal anime by providing the year and season. The results can be sorted using an option.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) anime, _, err := c.Anime.Seasonal(ctx, 2020, mal.AnimeSeasonFall, mal.Fields{"rank", "popularity"}, mal.SortSeasonalByAnimeNumListUsers, mal.Limit(3), mal.Offset(0), ) if err != nil { fmt.Printf("Anime.Seasonal error: %v", err) return } for _, a := range anime { fmt.Printf("Rank: %5d, Popularity: %5d %s\n", a.Rank, a.Popularity, a.Title) }
Output: Rank: 93, Popularity: 31 One Piece Rank: 1870, Popularity: 92 Black Clover Rank: 62, Popularity: 106 Jujutsu Kaisen (TV)
func (*AnimeService) Suggested ¶
func (s *AnimeService) Suggested(ctx context.Context, options ...Option) ([]Anime, *Response, error)
Suggested returns suggested anime for the authorized user. If the user is new comer, this endpoint returns an empty list.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) anime, _, err := c.Anime.Suggested(ctx, mal.Limit(10), mal.Fields{"rank", "popularity"}, ) if err != nil { fmt.Printf("Anime.Suggested error: %v", err) return } for _, a := range anime { fmt.Printf("Rank: %5d, Popularity: %5d %s\n", a.Rank, a.Popularity, a.Title) }
Output: Rank: 971, Popularity: 916 Kill la Kill Specials Rank: 726, Popularity: 4972 Osomatsu-san Movie Rank: 943, Popularity: 4595 Watashi no Ashinaga Ojisan
func (*AnimeService) UpdateMyListStatus ¶
func (s *AnimeService) UpdateMyListStatus(ctx context.Context, animeID int, options ...UpdateMyAnimeListStatusOption) (*AnimeListStatus, *Response, error)
UpdateMyListStatus adds the anime specified by animeID to the user's anime list with one or more options added to update the status. If the anime already exists in the list, only the status is updated.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) s, _, err := c.Anime.UpdateMyListStatus(ctx, 967, mal.AnimeStatusWatching, mal.NumEpisodesWatched(73), mal.Score(8), mal.Comments("You wa shock!"), mal.StartDate(time.Date(2022, 02, 20, 0, 0, 0, 0, time.UTC)), mal.FinishDate(time.Time{}), // Remove an existing date. ) if err != nil { fmt.Printf("Anime.UpdateMyListStatus error: %v", err) return } fmt.Printf("Status: %q, Score: %d, Episodes Watched: %d, Comments: %q, Start Date: %s\n", s.Status, s.Score, s.NumEpisodesWatched, s.Comments, s.StartDate)
Output: Status: "watching", Score: 8, Episodes Watched: 73, Comments: "You wa shock!", Start Date: 2022-02-20
type AnimeStatistics ¶
type AnimeStatistics struct { NumItemsWatching int `json:"num_items_watching"` NumItemsCompleted int `json:"num_items_completed"` NumItemsOnHold int `json:"num_items_on_hold"` NumItemsDropped int `json:"num_items_dropped"` NumItemsPlanToWatch int `json:"num_items_plan_to_watch"` NumItems int `json:"num_items"` NumDaysWatched float64 `json:"num_days_watched"` NumDaysWatching float64 `json:"num_days_watching"` NumDaysCompleted float64 `json:"num_days_completed"` NumDaysOnHold float64 `json:"num_days_on_hold"` NumDaysDropped float64 `json:"num_days_dropped"` NumDays float64 `json:"num_days"` NumEpisodes int `json:"num_episodes"` NumTimesRewatched int `json:"num_times_rewatched"` MeanScore float64 `json:"mean_score"` }
AnimeStatistics about the user.
type AnimeStatus ¶
type AnimeStatus string
AnimeStatus is an option that allows to filter the returned anime list by the specified status when using the UserService.AnimeList method. It can also be passed as an option when updating the anime list.
const ( // AnimeStatusWatching returns the anime with status 'watching' from a // user's list or sets the status of a list item as such. AnimeStatusWatching AnimeStatus = "watching" // AnimeStatusCompleted returns the anime with status 'completed' from a // user's list or sets the status of a list item as such. AnimeStatusCompleted AnimeStatus = "completed" // AnimeStatusOnHold returns the anime with status 'on hold' from a user's // list or sets the status of a list item as such. AnimeStatusOnHold AnimeStatus = "on_hold" // AnimeStatusDropped returns the anime with status 'dropped' from a user's // list or sets the status of a list item as such. AnimeStatusDropped AnimeStatus = "dropped" // AnimeStatusPlanToWatch returns the anime with status 'plan to watch' from // a user's list or sets the status of a list item as such. AnimeStatusPlanToWatch AnimeStatus = "plan_to_watch" )
type Broadcast ¶
type Broadcast struct { DayOfTheWeek string `json:"day_of_the_week"` StartTime string `json:"start_time"` }
Broadcast is the day and time that the show broadcasts.
type Client ¶
type Client struct { // Base URL for MyAnimeList API requests. BaseURL *url.URL Anime *AnimeService Manga *MangaService User *UserService Forum *ForumService // contains filtered or unexported fields }
Client manages communication with the MyAnimeList API.
func NewClient ¶
NewClient returns a new MyAnimeList API client. The httpClient parameter allows to specify the http.client that will be used for all API requests. If a nil httpClient is provided, a new http.Client will be used.
In the typical case, you will want to provide an http.Client that will perform the authentication for you. Such a client is provided by the golang.org/x/oauth2 package. Check out the example directory of the project for a full authentication example.
func (*Client) Do ¶
Do sends an API request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v. If v implements the io.Writer interface, the raw response body will be written to v, without attempting to first decode it.
If the provided ctx is nil then an error will be returned.
func (*Client) NewRequest ¶
func (c *Client) NewRequest(method, urlStr string, urlOptions ...func(v *url.Values)) (*http.Request, error)
NewRequest creates an API request. A relative URL can be provided in urlStr, in which case it is resolved relative to the BaseURL of the Client. Relative URLs should always be specified without a preceding slash. If data is passed as an argument then it will first be encoded in XML and then added to the request body as URL encoded value data=<xml>... This is how the MyAnimeList requires to receive the data when adding or updating entries.
MyAnimeList API docs: http://myanimelist.net/modules.php?go=api
type Comments ¶
type Comments string
Comments is an option that allows to update the comment of anime and manga in the user's list.
type CreatedBy ¶
type CreatedBy struct { ID int `json:"id"` Name string `json:"name"` ForumAvator string `json:"forum_avator"` }
CreatedBy shows the name of the user that created the post or topic.
type DetailsOption ¶
type DetailsOption interface {
// contains filtered or unexported methods
}
DetailsOption is an option specific for the anime and manga details methods.
type ErrorResponse ¶
type ErrorResponse struct { Response *http.Response // HTTP response that caused this error Message string `json:"message"` Err string `json:"error"` }
An ErrorResponse reports an error caused by an API request.
https://myanimelist.net/apiconfig/references/api/v2#section/Common-formats
func (*ErrorResponse) Error ¶
func (r *ErrorResponse) Error() string
type Fields ¶
type Fields []string
Fields is an option that allows to choose the fields that should be returned as by default, the API doesn't return all fields.
Example:
Fields{"synopsis", "my_list_status{priority,comments}"}
type FinishDate ¶ added in v0.9.5
FinishDate is an option that allows to update the finish date of anime and manga in the user's list.
type Forum ¶
type Forum struct {
Categories []ForumCategory `json:"categories"`
}
The Forum of MyAnimeList.
type ForumBoard ¶
type ForumBoard struct { ID int `json:"id"` Title string `json:"title"` Description string `json:"description"` Subboards []ForumSubboard `json:"subboards"` }
ForumBoard is a board of the forum.
type ForumCategory ¶
type ForumCategory struct { Title string `json:"title"` Boards []ForumBoard `json:"boards"` }
ForumCategory is a category of the forum.
type ForumService ¶
type ForumService struct {
// contains filtered or unexported fields
}
ForumService handles communication with the forum related methods of the MyAnimeList API:
https://myanimelist.net/apiconfig/references/api/v2#tag/forum
func (*ForumService) Boards ¶
Boards returns the forum boards.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) forum, _, err := c.Forum.Boards(ctx) if err != nil { fmt.Printf("Forum.Boards error: %v", err) return } for _, category := range forum.Categories { fmt.Printf("%s\n", category.Title) for _, b := range category.Boards { fmt.Printf("|-> %s\n", b.Title) for _, b := range b.Subboards { fmt.Printf(" |-> %s\n", b.Title) } } fmt.Println("---") }
Output: MyAnimeList |-> Updates & Announcements |-> MAL Guidelines & FAQ |-> DB Modification Requests |-> Anime DB |-> Character & People DB |-> Manga DB |-> Support |-> Suggestions |-> MAL Contests --- Anime & Manga |-> News Discussion |-> Anime & Manga Recommendations |-> Series Discussion |-> Anime Series |-> Manga Series |-> Anime Discussion |-> Manga Discussion --- General |-> Introductions |-> Games, Computers & Tech Support |-> Music & Entertainment |-> Current Events |-> Casual Discussion |-> Creative Corner |-> Forum Games ---
func (*ForumService) TopicDetails ¶
func (s *ForumService) TopicDetails(ctx context.Context, topicID int, options ...PagingOption) (TopicDetails, *Response, error)
TopicDetails returns details about the forum topic specified by topicID.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) topicDetails, _, err := c.Forum.TopicDetails(ctx, 1877721, mal.Limit(3), mal.Offset(0)) if err != nil { fmt.Printf("Forum.TopicDetails error: %v", err) return } fmt.Printf("Topic title: %q\n", topicDetails.Title) if topicDetails.Poll != nil { fmt.Printf("Poll: %q\n", topicDetails.Poll.Question) for _, o := range topicDetails.Poll.Options { fmt.Printf("- %-25s %2d\n", o.Text, o.Votes) } } for _, p := range topicDetails.Posts { fmt.Printf("Post: %2d created by %q\n", p.Number, p.CreatedBy.Name) }
Output: Topic title: "What is the best JoJo opening?" Poll: "What is the best JoJo opening?" - Sono Chi No Sadame 23 - Bloody Stream 61 - Stand Proud 12 - End Of The World 14 - Crazy Noisy Bizarre Town 22 - Chase 13 - Great Days 34 - Fighting Gold 15 - Traitor's Requiem 11 Post: 1 created by "Ringtomb" Post: 2 created by "Kenzolo-folk" Post: 3 created by "MechKingKillbot"
func (*ForumService) Topics ¶
func (s *ForumService) Topics(ctx context.Context, options ...TopicsOption) ([]Topic, *Response, error)
Topics returns the forum's topics. Make sure to pass at least the Query option or you will get an API error.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) topics, _, err := c.Forum.Topics(ctx, mal.Query("JoJo opening"), mal.SortTopicsRecent, mal.Limit(2), ) if err != nil { fmt.Printf("Forum.Topics error: %v", err) return } for _, t := range topics { fmt.Printf("ID: %5d, Title: %5q created by %q\n", t.ID, t.Title, t.CreatedBy.Name) }
Output: ID: 1877721, Title: "What is the best JoJo opening?" created by "Ringtomb" ID: 1851738, Title: "JoJo's Bizarre Adventures but its Yu Yu Hakusho Opening" created by "TinTin_29"
type ForumSubboard ¶
ForumSubboard is a subboard of the forum.
type IsRereading ¶
type IsRereading bool
IsRereading is an option that can update if a user is rereading a manga in their list.
type IsRewatching ¶
type IsRewatching bool
IsRewatching is an option that can update if a user is rewatching an anime in their list.
type Manga ¶
type Manga struct { ID int `json:"id"` Title string `json:"title"` MainPicture Picture `json:"main_picture"` AlternativeTitles Titles `json:"alternative_titles"` StartDate string `json:"start_date"` Synopsis string `json:"synopsis"` Mean float64 `json:"mean"` Rank int `json:"rank"` Popularity int `json:"popularity"` NumListUsers int `json:"num_list_users"` NumScoringUsers int `json:"num_scoring_users"` Nsfw string `json:"nsfw"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` MediaType string `json:"media_type"` Status string `json:"status"` Genres []Genre `json:"genres"` MyListStatus MangaListStatus `json:"my_list_status"` NumVolumes int `json:"num_volumes"` NumChapters int `json:"num_chapters"` Authors []Author `json:"authors"` Pictures []Picture `json:"pictures"` Background string `json:"background"` RelatedAnime []RelatedAnime `json:"related_anime"` RelatedManga []RelatedManga `json:"related_manga"` Recommendations []RecommendedManga `json:"recommendations"` Serialization []Serialization `json:"serialization"` }
Manga represents a MyAnimeList manga.
type MangaListOption ¶
type MangaListOption interface {
// contains filtered or unexported methods
}
MangaListOption are options specific to the UserService.MangaList method.
type MangaListStatus ¶
type MangaListStatus struct { Status MangaStatus `json:"status"` IsRereading bool `json:"is_rereading"` NumVolumesRead int `json:"num_volumes_read"` NumChaptersRead int `json:"num_chapters_read"` Score int `json:"score"` UpdatedAt time.Time `json:"updated_at"` Priority int `json:"priority"` NumTimesReread int `json:"num_times_reread"` RereadValue int `json:"reread_value"` Tags []string `json:"tags"` Comments string `json:"comments"` StartDate string `json:"start_date"` FinishDate string `json:"finish_date"` }
MangaListStatus shows the status of each manga in a user's manga list.
type MangaRanking ¶
type MangaRanking string
MangaRanking allows to choose how the manga will be ranked.
const ( // MangaRankingAll returns all types ranked. MangaRankingAll MangaRanking = "all" // MangaRankingManga returns the top manga. MangaRankingManga MangaRanking = "manga" // MangaRankingOneshots returns the top one-shots. MangaRankingOneshots MangaRanking = "oneshots" // MangaRankingDoujinshi returns the top doujinshi. MangaRankingDoujinshi MangaRanking = "doujin" // MangaRankingLightNovels returns the top light novels. MangaRankingLightNovels MangaRanking = "lightnovels" // MangaRankingNovels returns the top novels. MangaRankingNovels MangaRanking = "novels" // MangaRankingManhwa returns the top manhwa. MangaRankingManhwa MangaRanking = "manhwa" // MangaRankingManhua returns the top manhua. MangaRankingManhua MangaRanking = "manhua" // MangaRankingByPopularity returns the most popular entries. MangaRankingByPopularity MangaRanking = "bypopularity" // MangaRankingFavorite returns the most favorite entries. MangaRankingFavorite MangaRanking = "favorite" )
type MangaService ¶
type MangaService struct {
// contains filtered or unexported fields
}
MangaService handles communication with the manga related methods of the MyAnimeList API:
https://myanimelist.net/apiconfig/references/api/v2#tag/manga https://myanimelist.net/apiconfig/references/api/v2#tag/user-mangalist
func (*MangaService) DeleteMyListItem ¶
DeleteMyListItem deletes a manga from the user's list. If the manga does not exist in the user's list, 404 Not Found error is returned.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) resp, err := c.Manga.DeleteMyListItem(ctx, 401) if err != nil { fmt.Printf("Manga.DeleteMyListItem error: %v", err) return } fmt.Println(resp.Status)
Output: 200 OK
func (*MangaService) Details ¶
func (s *MangaService) Details(ctx context.Context, mangaID int, options ...DetailsOption) (*Manga, *Response, error)
Details returns details about a manga. By default, few manga fields are populated. Use the Fields option to specify which fields should be included.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) m, _, err := c.Manga.Details(ctx, 401, mal.Fields{ "alternative_titles", "media_type", "num_volumes", "num_chapters", "authors{last_name, first_name}", "genres", "status", }, ) if err != nil { fmt.Printf("Manga.Details error: %v", err) return } fmt.Printf("%s\n", m.Title) fmt.Printf("ID: %d\n", m.ID) fmt.Printf("English: %s\n", m.AlternativeTitles.En) fmt.Printf("Type: %s\n", strings.Title(m.MediaType)) fmt.Printf("Volumes: %d\n", m.NumVolumes) fmt.Printf("Chapters: %d\n", m.NumChapters) fmt.Print("Studios: ") delim := "" for _, s := range m.Authors { fmt.Printf("%s%s, %s (%s)", delim, s.Person.LastName, s.Person.FirstName, s.Role) delim = " " } fmt.Println() fmt.Print("Genres: ") delim = "" for _, g := range m.Genres { fmt.Printf("%s%s", delim, g.Name) delim = " " } fmt.Println() fmt.Printf("Status: %s\n", strings.Title(m.Status))
Output: Kiseijuu ID: 401 English: Parasyte Type: Manga Volumes: 10 Chapters: 64 Studios: Iwaaki, Hitoshi (Story & Art) Genres: Action Psychological Sci-Fi Drama Horror Seinen Status: Finished
func (*MangaService) List ¶
func (s *MangaService) List(ctx context.Context, search string, options ...Option) ([]Manga, *Response, error)
List allows an authenticated user to search and list manga data. You may get user specific data by using the optional field "my_list_status".
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) manga, _, err := c.Manga.List(ctx, "parasyte", mal.Fields{"num_volumes", "num_chapters", "alternative_titles"}, mal.Limit(3), mal.Offset(0), ) if err != nil { fmt.Printf("Manga.List error: %v", err) return } for _, m := range manga { fmt.Printf("ID: %5d, Volumes: %3d, Chapters: %3d %s (%s)\n", m.ID, m.NumVolumes, m.NumChapters, m.Title, m.AlternativeTitles.En) }
Output: ID: 401, Volumes: 10, Chapters: 64 Kiseijuu (Parasyte) ID: 78789, Volumes: 1, Chapters: 12 Neo Kiseijuu (Neo Parasyte m) ID: 80797, Volumes: 1, Chapters: 15 Neo Kiseijuu f (Neo Parasyte f)
func (*MangaService) Ranking ¶
func (s *MangaService) Ranking(ctx context.Context, ranking MangaRanking, options ...Option) ([]Manga, *Response, error)
Ranking allows an authenticated user to receive the top manga based on a certain ranking.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) manga, _, err := c.Manga.Ranking(ctx, mal.MangaRankingByPopularity, mal.Fields{"rank", "popularity"}, mal.Limit(6), ) if err != nil { fmt.Printf("Manga.Ranking error: %v", err) return } for _, m := range manga { fmt.Printf("Rank: %5d, Popularity: %5d %s\n", m.Rank, m.Popularity, m.Title) }
Output: Rank: 38, Popularity: 1 Shingeki no Kyojin Rank: 3, Popularity: 2 One Piece Rank: 1, Popularity: 3 Berserk Rank: 566, Popularity: 4 Naruto Rank: 106, Popularity: 5 Tokyo Ghoul Rank: 39, Popularity: 6 One Punch-Man
func (*MangaService) UpdateMyListStatus ¶
func (s *MangaService) UpdateMyListStatus(ctx context.Context, mangaID int, options ...UpdateMyMangaListStatusOption) (*MangaListStatus, *Response, error)
UpdateMyListStatus adds the manga specified by mangaID to the user's manga list with one or more options added to update the status. If the manga already exists in the list, only the status is updated.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) s, _, err := c.Manga.UpdateMyListStatus(ctx, 401, mal.MangaStatusReading, mal.NumVolumesRead(1), mal.NumChaptersRead(5), mal.Comments("Migi"), mal.StartDate(time.Date(2022, 02, 20, 0, 0, 0, 0, time.UTC)), mal.FinishDate(time.Time{}), // Remove an existing date. ) if err != nil { fmt.Printf("Manga.UpdateMyListStatus error: %v", err) return } fmt.Printf("Status: %q, Volumes Read: %d, Chapters Read: %d, Comments: %q, Start Date: %s\n", s.Status, s.NumVolumesRead, s.NumChaptersRead, s.Comments, s.StartDate)
Output: Status: "reading", Volumes Read: 1, Chapters Read: 5, Comments: "Migi", Start Date: 2022-02-20
type MangaStatus ¶
type MangaStatus string
MangaStatus is an option that allows to filter the returned manga list by the specified status when using the UserService.MangaList method. It can also be passed as an option when updating the manga list.
const ( // MangaStatusReading returns the manga with status 'reading' from a user's // list or sets the status of a list item as such. MangaStatusReading MangaStatus = "reading" // MangaStatusCompleted returns the manga with status 'completed' from a // user's list or sets the status of a list item as such. MangaStatusCompleted MangaStatus = "completed" // MangaStatusOnHold returns the manga with status 'on hold' from a user's // list or sets the status of a list item as such. MangaStatusOnHold MangaStatus = "on_hold" // MangaStatusDropped returns the manga with status 'dropped' from a user's // list or sets the status of a list item as such. MangaStatusDropped MangaStatus = "dropped" // MangaStatusPlanToRead returns the manga with status 'plan to read' from a // user's list or sets the status of a list item as such. MangaStatusPlanToRead MangaStatus = "plan_to_read" )
type MyInfoOption ¶
type MyInfoOption interface {
// contains filtered or unexported methods
}
MyInfoOption are options specific to the User.MyInfo method.
type NSFW ¶ added in v0.9.4
type NSFW bool
NSFW is an option which sets the NSFW query option. By default this is set to false.
type NumChaptersRead ¶
type NumChaptersRead int
NumChaptersRead is an option that can update the number of chapters read of a manga in the user's list.
type NumEpisodesWatched ¶
type NumEpisodesWatched int
NumEpisodesWatched is an option that can update the number of episodes watched of an anime in the user's list.
type NumTimesReread ¶
type NumTimesReread int
NumTimesReread is an option that can update the number of times the user has reread a manga in their list.
type NumTimesRewatched ¶
type NumTimesRewatched int
NumTimesRewatched is an option that can update the number of times the user has rewatched an anime in their list.
type NumVolumesRead ¶
type NumVolumesRead int
NumVolumesRead is an option that can update the number of volumes read of a manga in the user's list.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option is implemented by types that can be used as options in most methods such as Limit, Offset and Fields.
type Paging ¶
Paging provides access to the next and previous page URLs when there are pages of results.
type PagingOption ¶
type PagingOption interface {
// contains filtered or unexported methods
}
A PagingOption includes the Limit and Offset options which are used for controlling pagination in results.
type Person ¶
type Person struct { ID int `json:"id"` FirstName string `json:"first_name"` LastName string `json:"last_name"` }
Person is usually the creator of a manga.
type Poll ¶
type Poll struct { ID int `json:"id"` Question string `json:"question"` Closed bool `json:"closed"` Options []PollOption `json:"options"` }
Poll is an optional poll in a forum post.
type PollOption ¶
PollOption is one of the choices of a poll.
type Post ¶
type Post struct { ID int `json:"id"` Number int `json:"number"` CreatedAt time.Time `json:"created_at"` CreatedBy CreatedBy `json:"created_by"` Body string `json:"body"` Signature string `json:"signature"` }
Post is a forum post.
type Priority ¶
type Priority int
Priority is an option that allows to update the priority of an anime or manga in the user's list with values 0=Low, 1=Medium, 2=High.
type RecommendedAnime ¶
type RecommendedAnime struct { Node Anime `json:"node"` NumRecommendations int `json:"num_recommendations"` }
RecommendedAnime is a recommended anime.
type RecommendedManga ¶
type RecommendedManga struct { Node Manga `json:"node"` NumRecommendations int `json:"num_recommendations"` }
RecommendedManga is a manga recommended to the user.
type RelatedAnime ¶
type RelatedAnime struct { Node Anime `json:"node"` RelationType string `json:"relation_type"` RelationTypeFormatted string `json:"relation_type_formatted"` }
RelatedAnime contains a related anime.
type RelatedManga ¶
type RelatedManga struct { Node Manga `json:"node"` RelationType string `json:"relation_type"` RelationTypeFormatted string `json:"relation_type_formatted"` }
RelatedManga shows manga related with the returned entry.
type RereadValue ¶
type RereadValue int
RereadValue is an option that can update the reread value of a manga in the user's list with values:
0 = No value 1 = Very Low 2 = Low 3 = Medium 4 = High 5 = Very High
type Response ¶
Response wraps http.Response and is returned in all the library functions that communicate with the MyAnimeList API. Even if an error occurs the response will always be returned along with the actual error so that the caller can further inspect it if needed. For the same reason it also keeps a copy of the http.Response.Body that was read when the response was first received.
type RewatchValue ¶
type RewatchValue int
RewatchValue is an option that can update the rewatch value of an anime in the user's list with values:
0 = No value 1 = Very Low 2 = Low 3 = Medium 4 = High 5 = Very High
type Score ¶
type Score int
Score is an option that can update the anime and manga list scores with values 0-10.
type SeasonalAnimeOption ¶
type SeasonalAnimeOption interface {
// contains filtered or unexported methods
}
SeasonalAnimeOption are options specific to the AnimeService.Seasonal method.
type Serialization ¶
Serialization is a serialized manga series.
type SortAnimeList ¶
type SortAnimeList string
SortAnimeList is an option that sorts the results when getting the user's anime list.
const ( // SortAnimeListByListScore sorts results by the score of each item in the // list in descending order. SortAnimeListByListScore SortAnimeList = "list_score" // SortAnimeListByListUpdatedAt sorts results by the most updated entries in // the list in descending order. SortAnimeListByListUpdatedAt SortAnimeList = "list_updated_at" // SortAnimeListByAnimeTitle sorts results by the anime title in ascending // order. SortAnimeListByAnimeTitle SortAnimeList = "anime_title" // SortAnimeListByAnimeStartDate sorts results by the anime start date in // descending order. SortAnimeListByAnimeStartDate SortAnimeList = "anime_start_date" // SortAnimeListByAnimeID sorts results by the anime ID in ascending order. // Note: Currently under development. SortAnimeListByAnimeID SortAnimeList = "anime_id" )
type SortMangaList ¶
type SortMangaList string
SortMangaList is an option that sorts the results when getting the user's manga list.
const ( // SortMangaListByListScore sorts results by the score of each item in the // list in descending order. SortMangaListByListScore SortMangaList = "list_score" // SortMangaListByListUpdatedAt sorts results by the most updated entries in // the list in descending order. SortMangaListByListUpdatedAt SortMangaList = "list_updated_at" // SortMangaListByMangaTitle sorts results by the manga title in ascending // order. SortMangaListByMangaTitle SortMangaList = "manga_title" // SortMangaListByMangaStartDate sorts results by the manga start date in // descending order. SortMangaListByMangaStartDate SortMangaList = "manga_start_date" // SortMangaListByMangaID sorts results by the manga ID in ascending order. // Note: Currently under development. SortMangaListByMangaID SortMangaList = "manga_id" )
type SortSeasonalAnime ¶
type SortSeasonalAnime string
SortSeasonalAnime is an option that allows to sort the anime results.
const ( // SortSeasonalByAnimeScore sorts seasonal results by anime score in // descending order. SortSeasonalByAnimeScore SortSeasonalAnime = "anime_score" // SortSeasonalByAnimeNumListUsers sorts seasonal results by anime num list // users in descending order. SortSeasonalByAnimeNumListUsers SortSeasonalAnime = "anime_num_list_users" )
type StartDate ¶ added in v0.9.5
StartDate is an option that allows to update the start date of anime and manga in the user's list.
type StartSeason ¶
StartSeason is the season an anime starts.
type Statistics ¶
Statistics about the anime.
type Status ¶
type Status struct { Watching string `json:"watching"` Completed string `json:"completed"` OnHold string `json:"on_hold"` Dropped string `json:"dropped"` PlanToWatch string `json:"plan_to_watch"` }
Status of the user's anime list contained in statistics.
type SubboardID ¶
type SubboardID int
SubboardID is an option that filters topics based on the subboard ID.
type Tags ¶
type Tags []string
Tags is an option that allows to update the comma-separated tags of anime and manga in the user's list.
type Titles ¶
type Titles struct { Synonyms []string `json:"synonyms"` En string `json:"en"` Ja string `json:"ja"` }
Titles of the anime in English and Japanese.
type Topic ¶
type Topic struct { ID int `json:"id"` Title string `json:"title"` CreatedAt time.Time `json:"created_at"` CreatedBy CreatedBy `json:"created_by"` NumberOfPosts int `json:"number_of_posts"` LastPostCreatedAt time.Time `json:"last_post_created_at"` LastPostCreatedBy CreatedBy `json:"last_post_created_by"` IsLocked bool `json:"is_locked"` }
A Topic of the forum.
type TopicDetails ¶
type TopicDetails struct { Title string `json:"title"` Posts []Post `json:"posts"` Poll *Poll `json:"poll"` }
TopicDetails contain the posts of a forum topic and an optional poll.
type TopicUserName ¶
type TopicUserName string
TopicUserName is an option that filters topics based on the topic username.
type TopicsOption ¶
type TopicsOption interface {
// contains filtered or unexported methods
}
TopicsOption are options specific to the ForumService.Topics method.
type UpdateMyAnimeListStatusOption ¶
type UpdateMyAnimeListStatusOption interface {
// contains filtered or unexported methods
}
UpdateMyAnimeListStatusOption are options specific to the AnimeService.UpdateMyListStatus method.
type UpdateMyMangaListStatusOption ¶
type UpdateMyMangaListStatusOption interface {
// contains filtered or unexported methods
}
UpdateMyMangaListStatusOption are options specific to the MangaService.UpdateMyListStatus method.
type User ¶
type User struct { ID int64 `json:"id"` Name string `json:"name"` Picture string `json:"picture"` Gender string `json:"gender"` Birthday string `json:"birthday"` Location string `json:"location"` JoinedAt time.Time `json:"joined_at"` AnimeStatistics AnimeStatistics `json:"anime_statistics"` TimeZone string `json:"time_zone"` IsSupporter bool `json:"is_supporter"` }
User represents a MyAnimeList user.
type UserAnime ¶
type UserAnime struct { Anime Anime `json:"node"` Status AnimeListStatus `json:"list_status"` }
UserAnime contains an anime record along with its status on the user's list.
type UserManga ¶
type UserManga struct { Manga Manga `json:"node"` Status MangaListStatus `json:"list_status"` }
UserManga contains a manga record along with its status on the user's list.
type UserService ¶
type UserService struct {
// contains filtered or unexported fields
}
UserService handles communication with the user related methods of the MyAnimeList API:
https://myanimelist.net/apiconfig/references/api/v2#tag/user https://myanimelist.net/apiconfig/references/api/v2#operation/users_user_id_animelist_get https://myanimelist.net/apiconfig/references/api/v2#operation/users_user_id_mangalist_get
func (*UserService) AnimeList ¶
func (s *UserService) AnimeList(ctx context.Context, username string, options ...AnimeListOption) ([]UserAnime, *Response, error)
AnimeList gets the anime list of the user indicated by username (or use @me). The anime can be sorted and filtered using the AnimeStatus and SortAnimeList option functions respectively.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) anime, _, err := c.User.AnimeList(ctx, "@me", mal.Fields{"list_status"}, mal.SortAnimeListByListUpdatedAt, mal.Limit(5), ) if err != nil { fmt.Printf("User.AnimeList error: %v", err) return } for _, a := range anime { fmt.Printf("ID: %5d, Status: %15q, Episodes Watched: %3d %s\n", a.Anime.ID, a.Status.Status, a.Status.NumEpisodesWatched, a.Anime.Title) }
Output: ID: 967, Status: "watching", Episodes Watched: 73 Hokuto no Ken ID: 820, Status: "watching", Episodes Watched: 1 Ginga Eiyuu Densetsu ID: 42897, Status: "watching", Episodes Watched: 2 Horimiya ID: 1453, Status: "watching", Episodes Watched: 28 Maison Ikkoku ID: 37521, Status: "completed", Episodes Watched: 24 Vinland Saga
func (*UserService) MangaList ¶
func (s *UserService) MangaList(ctx context.Context, username string, options ...MangaListOption) ([]UserManga, *Response, error)
MangaList gets the manga list of the user indicated by username (or use @me). The manga can be sorted and filtered using the MangaStatus and SortMangaList option functions respectively.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) manga, _, err := c.User.MangaList(ctx, "@me", mal.Fields{"list_status"}, mal.SortMangaListByListUpdatedAt, mal.Limit(2), ) if err != nil { fmt.Printf("User.MangaList error: %v", err) return } for _, m := range manga { fmt.Printf("ID: %5d, Status: %15q, Volumes Read: %3d, Chapters Read: %3d %s\n", m.Manga.ID, m.Status.Status, m.Status.NumVolumesRead, m.Status.NumChaptersRead, m.Manga.Title) }
Output: ID: 21, Status: "completed", Volumes Read: 12, Chapters Read: 108 Death Note ID: 401, Status: "reading", Volumes Read: 1, Chapters Read: 5 Kiseijuu
func (*UserService) MyInfo ¶
func (s *UserService) MyInfo(ctx context.Context, options ...MyInfoOption) (*User, *Response, error)
MyInfo returns information about the authenticated user.
Example ¶
ctx := context.Background() c := mal.NewClient(nil) // Ignore the 3 following lines. A stub server is used instead of the real // API to produce testable examples. See: https://go.dev/blog/examples server := newStubServer() defer server.Close() c.BaseURL, _ = url.Parse(server.URL) user, _, err := c.User.MyInfo(ctx) if err != nil { fmt.Printf("User.MyInfo error: %v", err) return } fmt.Printf("ID: %5d, Joined: %v, Username: %s\n", user.ID, user.JoinedAt.Format("Jan 2006"), user.Name)
Output: ID: 4592783, Joined: May 2015, Username: nstratos