Expand description
mal-api
is an asynchronous, fully type-safe MyAnimeList API
§Table of Contents
§Overview
mal-api
library is a fully type-safe library
that provides asynchronous functionality for interacting with the MyAnimeList (MAL)
API.
With mal-api
, developers can confidently integrate MAL API
functionality into their applications, enabling them to retrieve, update,
and manage anime and manga data effortlessly. The library offers a comprehensive
set of API endpoints, allowing users to perform operations such as searching for
anime, retrieving detailed information about specific titles, managing user
lists, and more.
One of the key features of mal-api
is its type safety. By utilizing Rust’s
strong type system, the library provides compile-time guarantees that the API
requests and responses are correctly structured and formatted. This eliminates
the risk of runtime errors. Developers can leverage the library’s well-defined
structs and enums to easily construct API requests and handle the received
data in a type-safe manner.
§OAuth
mal-api
provides a method for obtaining MAL OAuth access tokens.
This token is necessary to access certain MAL API endpoints.
Depending on whether you obtain an OAuth token or just use your ClientId,
the mal-api
API client you create from either token will ensure you can only
access the endpoints your token is comptatible with.
§API Clients
There are four different API clients you can use:
- AnimeApiClient
- Implements all of the anime and user animelist MAL API endpoints
- Can be created from a MAL Oauth access token or a MAL ClientId
- MangaApiClient
- Implements all of the manga and user mangalist MAL API endpoints
- Can be created from a MAL Oauth access token or a MAL ClientId
- ForumApiClient
- Implements all of the forum MAL API endpoints
- Can be created from a MAL Oauth access token or a MAL ClientId
- UserApiClient
- Implements all of the user MAL API endpoints
- Can be created from a MAL Oauth access token
§Anime and Manga Fields
mal-api
provides utilities to ensure that the fields you want returned from the
anime and manga endpoints are valid fields.
use mal_api::prelude::*;
use mal_api::anime_common_fields;
// Specify which fields you want returned from the Anime endpoint
let fields = anime_common_fields!(
AnimeField::id,
AnimeField::num_episodes,
AnimeField::title,
);
// If you want all of the common fields:
let fields = mal_api::anime::all_common_fields();
// If you want all of the detailed fields:
let fields = mal_api::anime::all_detail_fields();
§Examples
§Using a ClientId
use dotenvy;
use mal_api::anime_common_fields;
use mal_api::oauth::MalClientId;
use mal_api::prelude::*;
#[tokio::main]
async fn main() {
dotenvy::dotenv().ok();
let client_id = MalClientId::try_from_env().unwrap();
// Anime API example
let api_client = AnimeApiClient::from(&client_id);
let fields = anime_common_fields!(
AnimeField::id,
AnimeField::num_episodes,
AnimeField::title,
);
// Example using builder pattern. The `builder(args...)` method will only require
// the required arguments for the specific API endpoint, while the
// other builder instance methods will build up the optional arguments.
let query = GetAnimeList::builder("One")
.fields(&fields)
.limit(5)
.build()
.unwrap();
let result = api_client.get_anime_list(&query).await.unwrap();
println!("Result: {}", &result);
// Example iterating through pages
let result = api_client.next(&result).await.unwrap();
println!("Next result: {}", &result);
let result = api_client.prev(&result).await.unwrap();
println!("Prev result: {}", &result);
// Manga API example
let api_client = MangaApiClient::from(&client_id);
let fields = mal_api::manga::all_common_fields();
// Example using `new` pattern. Not recommended, but available
let nsfw = false;
let limit = Some(5);
let query = GetMangaList::new("one".to_string(), nsfw, Some(&fields), limit, None).unwrap();
let result = api_client.get_manga_list(&query).await.unwrap();
println!("Result: {}", result);
}
§Creating an OAuth token
use dotenvy;
use mal_api::oauth::{OauthClient, RedirectResponse};
use std::io;
#[tokio::main]
async fn main() {
dotenvy::dotenv().ok();
let authenticated_client = OauthClient::load_from_config(".mal/config.toml");
match authenticated_client {
Ok(_) => {
println!("An existing authorized Oauth client already exists");
return;
}
Err(_) => println!("No existing Oauth client exists\n"),
}
let client_id = OauthClient::load_client_id_from_env().unwrap();
let client_secret = OauthClient::load_client_secret_from_env().unwrap();
let redirect_url = OauthClient::load_redirect_url_from_env().unwrap();
let mut oauth_client =
OauthClient::new(&client_id, Some(&client_secret), &redirect_url).unwrap();
println!("Visit this URL: {}\n", oauth_client.generate_auth_url());
println!("After authorizing, please enter the URL you were redirected to: ");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read user input");
let response = RedirectResponse::try_from(input).unwrap();
// Authentication process
let result = oauth_client.authenticate(response).await;
let authenticated_oauth_client = match result {
Ok(t) => {
println!("Got token: {:?}\n", t.get_access_token_secret());
let t = t.refresh().await.unwrap();
println!("Refreshed token: {:?}", t.get_access_token_secret());
t
}
Err(e) => panic!("Failed: {}", e),
};
// Save credentials to config to be re-used later
let _ = authenticated_oauth_client.save_to_config(".mal/config");
}
§Accessing data from responses
let query = GetAnimeList::builder("One Piece")
.fields(&common_fields)
.build()
.unwrap();
let response = api_client.get_anime_list(&query).await;
if let Ok(response) = response {
// Iterate through all of the anime entries, printing each anime's title and id
for entry in response.data.iter() {
println!("Anime Title: {} Anime ID: {}", entry.node.title, entry.node.id);
}
}
Modules§
- anime
- Module for interacting with the
anime
anduser animelist
endpoints - common
- Module containing common request/response fields, traits, and functions
- macros
- Module for ease-of-use macros
- manga
- Module for interacting with the
manga
anduser mangalist
endpoints - oauth
- Module for working through MAL OAuth2 flow
- prelude
- Module re-exports
Macros§
- anime_
common_ fields - Macro for creating a vector of valid AnimeCommonFields
- anime_
detail_ fields - Macro for creating a vector of valid AnimeDetailFields
- manga_
common_ fields - Macro for creating a vector of valid MangaCommonFields
- manga_
detail_ fields - Macro for creating a vector of valid MangaDetailFields