Fix includes

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 2 years ago
parent 46d7bd52f7
commit a2924614e0
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

2
Cargo.lock generated

@ -4,7 +4,7 @@ version = 3
[[package]]
name = "animethemes-rs"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"reqwest",
"serde",

@ -1,8 +1,8 @@
[package]
name = "animethemes-rs"
version = "0.3.0"
version = "0.4.0"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
edition = "2021"
readme = "README.md"
repository = "https://github.com/trivernis/animethemes-rs"
license = "Apache-2.0"

@ -1,4 +1,5 @@
use crate::error::ApiResult;
use crate::includes::*;
use crate::models::{
Anime, AnimeSynonym, Artist, Image, Resource, SearchResponse, Series, Song, Theme, ThemeEntry,
Video,
@ -15,7 +16,7 @@ pub static DEFAULT_VIDEO_ENDPOINT: &str = "https://animethemes.moe/video/";
#[derive(Clone, Debug)]
pub struct AnimeThemesClient {
api_endpoint: String,
video_endpoint: String,
pub video_endpoint: String,
client: reqwest::Client,
}
@ -47,10 +48,11 @@ impl AnimeThemesClient {
/// ```
/// # use animethemes_rs::error::ApiResult;
/// use animethemes_rs::client::AnimeThemesClient;
/// use animethemes_rs::includes::SearchIncludes;
///
/// # async fn a() -> ApiResult<()> {
/// let client = AnimeThemesClient::default();
/// let response = client.search("Attack on Titan", &[], &[]).await?;
/// let response = client.search("Attack on Titan", &[], SearchIncludes::default()).await?;
///
/// assert!(response.anime.is_some());
/// assert!(response.songs.is_some());
@ -60,12 +62,13 @@ impl AnimeThemesClient {
&self,
query: &str,
fields: &[&str],
include: &[&str],
include: SearchIncludes,
) -> ApiResult<SearchResponse> {
let mut query = vec![("q", query.to_string()), ("include", include.join(","))];
let mut query = vec![("q".to_string(), query.to_string())];
query.append(&mut include.indo_includes());
if !fields.is_empty() {
query.push(("fields[search]", fields.join(",")));
query.push(("fields[search]".to_string(), fields.join(",")));
}
let mut response: HashMap<String, SearchResponse> =
self.api_get("/search", &query[..]).await?.json().await?;
@ -74,56 +77,62 @@ impl AnimeThemesClient {
}
/// Returns an anime by a given slug string
pub async fn anime(&self, slug: &str, include: &[&str]) -> ApiResult<Anime> {
self.entry_by_id_with_include("anime", slug, include).await
pub async fn anime(&self, slug: &str, include: AnimeInclude) -> ApiResult<Anime> {
self.entry_by_id_with_include("anime", slug, include.includes())
.await
}
/// Returns an artist by a given slug string
pub async fn artist(&self, slug: &str, include: &[&str]) -> ApiResult<Artist> {
self.entry_by_id_with_include("artist", slug, include).await
pub async fn artist(&self, slug: &str, include: ArtistInclude) -> ApiResult<Artist> {
self.entry_by_id_with_include("artist", slug, include.includes())
.await
}
/// Returns an entry by a given id
pub async fn entry(&self, id: u32, include: &[&str]) -> ApiResult<ThemeEntry> {
self.entry_by_id_with_include("animethemeentry", id, include)
pub async fn entry(&self, id: u32, include: ThemeEntryInclude) -> ApiResult<ThemeEntry> {
self.entry_by_id_with_include("animethemeentry", id, include.includes())
.await
}
/// Returns an image by id
pub async fn image(&self, id: u32, include: &[&str]) -> ApiResult<Image> {
self.entry_by_id_with_include("image", id, include).await
pub async fn image(&self, id: u32, include: ImageInclude) -> ApiResult<Image> {
self.entry_by_id_with_include("image", id, include.includes())
.await
}
/// Returns a resource by id
pub async fn resource(&self, id: u32, include: &[&str]) -> ApiResult<Resource> {
self.entry_by_id_with_include("resource", id, include).await
pub async fn resource(&self, id: u32, include: ResourceInclude) -> ApiResult<Resource> {
self.entry_by_id_with_include("resource", id, include.includes())
.await
}
/// Returns a series by slug
pub async fn series(&self, slug: &str, include: &[&str]) -> ApiResult<Series> {
self.entry_by_id_with_include("series", slug, include).await
pub async fn series(&self, slug: &str, include: SeriesInclude) -> ApiResult<Series> {
self.entry_by_id_with_include("series", slug, include.includes())
.await
}
/// Returns a song by id
pub async fn song(&self, id: u32, include: &[&str]) -> ApiResult<Song> {
self.entry_by_id_with_include("song", id, include).await
pub async fn song(&self, id: u32, include: SongInclude) -> ApiResult<Song> {
self.entry_by_id_with_include("song", id, include.includes())
.await
}
/// Returns a synonym by id
pub async fn synonym(&self, id: u32, include: &[&str]) -> ApiResult<AnimeSynonym> {
self.entry_by_id_with_include("animesynonym", id, include)
pub async fn synonym(&self, id: u32, include: SynonymInclude) -> ApiResult<AnimeSynonym> {
self.entry_by_id_with_include("animesynonym", id, include.includes())
.await
}
/// Returns a theme by id
pub async fn theme(&self, id: u32, include: &[&str]) -> ApiResult<Theme> {
self.entry_by_id_with_include("animetheme", id, include)
pub async fn theme(&self, id: u32, include: ThemeInclude) -> ApiResult<Theme> {
self.entry_by_id_with_include("animetheme", id, include.includes())
.await
}
/// Returns a video by basename
pub async fn video(&self, basename: &str, include: &[&str]) -> ApiResult<Video> {
self.entry_by_id_with_include("video", basename, include)
pub async fn video(&self, basename: &str, include: VideoInclude) -> ApiResult<Video> {
self.entry_by_id_with_include("video", basename, include.includes())
.await
}
@ -132,7 +141,7 @@ impl AnimeThemesClient {
&self,
endpoint: &str,
id: I,
include: &[&str],
include: Vec<String>,
) -> ApiResult<T> {
let mut response: HashMap<String, T> = self
.api_get(

@ -1,10 +1,208 @@
pub static THEMES: &str = "animethemes";
pub static THEME: &str = "animetheme";
pub static THEME_ENTRIES: &str = "animethemeentries";
pub static SYNONYMS: &str = "animesynonyms";
pub static RESOURCES: &str = "resources";
pub static IMAGES: &str = "images";
pub static SERIES: &str = "series";
pub static SONGS: &str = "songs";
pub static VIDEOS: &str = "videos";
pub static ANIME: &str = "anime";
macro_rules! theme_include {
(
pub struct $name: ident ($include_type:literal) {
$($field: ident: $field_name: literal),+
}
) => {
#[derive(Clone, Copy, Default, Debug)]
pub struct $name {
$($field: bool),+
}
impl $name {
$(pub fn $field(mut self) -> Self {
self.$field = true;
self
}
)+
}
impl Includes for $name {
fn include_type() -> &'static str {
$include_type
}
fn includes(&self) -> Vec<String> {
let mut includes = Vec::new();
$(
if self.$field {
includes.push($field_name.into());
}
)+
includes
}
}
}
}
pub trait Includes {
fn include_type() -> &'static str;
fn includes(&self) -> Vec<String>;
}
theme_include!(
pub struct AnimeInclude ("anime") {
synonyms: "animesynonyms",
themes: "animethemes",
themes_entries: "animethemes.animethemeentries",
themes_entries_videos: "animethemes.animethemeentries.videos",
themes_song: "animethemes.song",
themes_song_artists: "animethemes.song.artists",
images: "images",
resources: "resources",
series: "series",
studios: "studios"
}
);
theme_include!(
pub struct AnimeImageInclude ("animeimage") {
anime: "anime",
image: "image"
}
);
theme_include!(
pub struct SynonymInclude ("animesynonym") {
anime: "anime"
}
);
theme_include!(
pub struct ThemeInclude ("animetheme") {
anime: "anime",
anime_images: "anime.images",
entries: "animethemeentries",
entries_videos: "animethemeentries.videos",
song: "song",
song_artists: "song.artists"
}
);
theme_include!(
pub struct ThemeEntryInclude ("animethemeentry") {
theme: "animetheme",
theme_anime: "animetheme.anime",
videos: "videos"
}
);
theme_include!(
pub struct ArtistInclude ("artist") {
groups: "groups",
members: "members",
resources: "resources",
songs: "songs",
songs_themes: "songs.animethemes",
songs_themes_anime: "songs.animethemes.anime"
}
);
theme_include!(
pub struct ImageInclude ("image") {
anime: "anime",
artists: "artists",
studios: "studios"
}
);
theme_include!(
pub struct ResourceInclude ("resource") {
anime: "anime",
artists: "artists",
studios: "studios"
}
);
theme_include!(
pub struct SeriesInclude ("series") {
anime: "anime"
}
);
theme_include!(
pub struct SongInclude ("song") {
themes: "animethemes",
themes_anime: "animethemes.anime",
artists: "artists"
}
);
theme_include!(
pub struct Studio ("studio") {
anime: "anime",
images: "images",
resources: "resources"
}
);
theme_include!(
pub struct VideoInclude ("video") {
entries: "animethemeentries",
entries_theme: "animethemeentries.animetheme",
entries_theme_anime: "animethemeentries.animetheme.anime"
}
);
#[derive(Clone, Copy, Default, Debug)]
pub struct SearchIncludes {
pub anime: AnimeInclude,
pub animethemes: ThemeInclude,
pub artists: ArtistInclude,
pub series: SeriesInclude,
pub songs: SongInclude,
pub videos: VideoInclude,
}
impl SearchIncludes {
pub fn indo_includes(self) -> Vec<(String, String)> {
let mut includes = Vec::new();
let anime_includes = self.anime.includes();
let animetheme_includes = self.animethemes.includes();
let artist_includes = self.artists.includes();
let series_includes = self.series.includes();
let song_includes = self.songs.includes();
let video_includes = self.videos.includes();
if !anime_includes.is_empty() {
includes.push((
format!("includes[{}]", AnimeInclude::include_type()),
anime_includes.join(","),
));
}
if !animetheme_includes.is_empty() {
includes.push((
format!("includes[{}]", ThemeInclude::include_type()),
animetheme_includes.join(","),
));
}
if !artist_includes.is_empty() {
includes.push((
format!("includes[{}]", ArtistInclude::include_type()),
artist_includes.join(","),
));
}
if !series_includes.is_empty() {
includes.push((
format!("includes[{}]", SeriesInclude::include_type()),
series_includes.join(","),
));
}
if !song_includes.is_empty() {
includes.push((
format!("includes[{}]", SongInclude::include_type()),
song_includes.join(","),
));
}
if !video_includes.is_empty() {
includes.push((
format!("includes[{}]", VideoInclude::include_type()),
video_includes.join(","),
));
}
includes
}
}

@ -4,10 +4,11 @@
//! ```
//! # use animethemes_rs::error::ApiResult;
//! use animethemes_rs::client::AnimeThemesClient;
//! use animethemes_rs::includes::SearchIncludes;
//!
//! # async fn a() -> ApiResult<()> {
//! let client = AnimeThemesClient::default();
//! let response = client.search("Vivy", &[], &[]).await?;
//! let response = client.search("Vivy", &[], SearchIncludes::default()).await?;
//!
//! assert!(response.anime.is_some());
//! assert!(response.videos.is_some());

@ -1,10 +1,20 @@
use crate::client::AnimeThemesClient;
use crate::includes::{ANIME, SONGS, THEME, THEMES, THEME_ENTRIES, VIDEOS};
use crate::includes::*;
#[tokio::test]
async fn it_searches() {
let client = AnimeThemesClient::default();
let result = client.search("Vivy", &[], &[]).await.unwrap();
let result = client
.search(
"vivy",
&[],
SearchIncludes {
anime: AnimeInclude::default().images().series(),
..Default::default()
},
)
.await
.unwrap();
assert!(result.artists.is_some());
assert!(result.songs.is_some());
assert!(result.anime.is_some());
@ -17,7 +27,7 @@ async fn it_searches() {
async fn it_returns_anime_by_slug() {
let client = AnimeThemesClient::default();
let result = client
.anime("vivy_fluorite_eyes_song", &[THEMES])
.anime("vivy_fluorite_eyes_song", AnimeInclude::default().themes())
.await
.unwrap();
@ -27,7 +37,10 @@ async fn it_returns_anime_by_slug() {
#[tokio::test]
async fn it_returns_artists_by_slug() {
let client = AnimeThemesClient::default();
let result = client.artist("lisa", &[SONGS]).await.unwrap();
let result = client
.artist("lisa", ArtistInclude::default().songs())
.await
.unwrap();
assert!(result.songs.is_some());
}
@ -35,7 +48,10 @@ async fn it_returns_artists_by_slug() {
#[tokio::test]
async fn it_returns_entries_by_id() {
let client = AnimeThemesClient::default();
let result = client.entry(11948, &[VIDEOS, THEME]).await.unwrap();
let result = client
.entry(11948, ThemeEntryInclude::default().theme().videos())
.await
.unwrap();
assert!(result.videos.is_some());
assert!(result.theme.is_some());
@ -44,7 +60,10 @@ async fn it_returns_entries_by_id() {
#[tokio::test]
async fn it_returns_images_by_id() {
let client = AnimeThemesClient::default();
let result = client.image(7247, &[ANIME]).await.unwrap();
let result = client
.image(7247, ImageInclude::default().anime())
.await
.unwrap();
assert!(result.anime.is_some())
}
@ -52,7 +71,10 @@ async fn it_returns_images_by_id() {
#[tokio::test]
async fn it_returns_resources_by_id() {
let client = AnimeThemesClient::default();
let result = client.resource(3588, &[ANIME]).await.unwrap();
let result = client
.resource(3588, ResourceInclude::default().anime())
.await
.unwrap();
assert!(result.anime.is_some())
}
@ -60,7 +82,10 @@ async fn it_returns_resources_by_id() {
#[tokio::test]
async fn it_returns_series_by_slug() {
let client = AnimeThemesClient::default();
let result = client.series("shingeki_no_kyojin", &[ANIME]).await.unwrap();
let result = client
.series("shingeki_no_kyojin", SeriesInclude::default().anime())
.await
.unwrap();
assert!(result.anime.is_some())
}
@ -68,7 +93,10 @@ async fn it_returns_series_by_slug() {
#[tokio::test]
async fn it_returns_synonyms_by_id() {
let client = AnimeThemesClient::default();
let result = client.synonym(2462, &[ANIME]).await.unwrap();
let result = client
.synonym(2462, SynonymInclude::default().anime())
.await
.unwrap();
assert!(result.anime.is_some())
}
@ -76,7 +104,10 @@ async fn it_returns_synonyms_by_id() {
#[tokio::test]
async fn it_returns_songs_by_id() {
let client = AnimeThemesClient::default();
let result = client.song(8188, &[THEMES]).await.unwrap();
let result = client
.song(8188, SongInclude::default().themes())
.await
.unwrap();
assert!(result.themes.is_some())
}
@ -84,7 +115,10 @@ async fn it_returns_songs_by_id() {
#[tokio::test]
async fn it_returns_themes_by_id() {
let client = AnimeThemesClient::default();
let result = client.theme(8187, &[THEME_ENTRIES]).await.unwrap();
let result = client
.theme(8187, ThemeInclude::default().entries())
.await
.unwrap();
assert!(result.entries.is_some())
}
@ -93,7 +127,7 @@ async fn it_returns_themes_by_id() {
async fn it_returns_videos_by_basename() {
let client = AnimeThemesClient::default();
let result = client
.video("KimiUso-OP2.webm", &[THEME_ENTRIES])
.video("KimiUso-OP2.webm", VideoInclude::default().entries())
.await
.unwrap();

Loading…
Cancel
Save