| Crates.io | shikicrate |
| lib.rs | shikicrate |
| version | 0.2.1 |
| created_at | 2026-01-03 21:09:51.901814+00 |
| updated_at | 2026-01-04 07:42:00.495012+00 |
| description | Rust client for Shikimori GraphQL API |
| homepage | |
| repository | https://github.com/KidTheFelon/shikicrate |
| max_upload_size | |
| id | 2020793 |
| size | 191,801 |
Rust клиент для Shikimori GraphQL API. Потому что парсить JSON руками — это прошлый век.
Нужен доступ к аниме, манге, персонажам и прочей японской культуре через Shikimori? Не хочешь писать GraphQL запросы вручную? Добро пожаловать. Клиент сам разберется с retry-логикой, rate limiting и прочими радостями жизни.
Кидай в Cargo.toml:
[dependencies]
shikicrate = "<актуальная версия>"
Или для локальной разработки (если хочешь поковырять код):
[dependencies]
shikicrate = { path = "../shikicrate" }
use shikicrate::{ShikicrateClient, queries::*};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ShikicrateClient::new()?;
// Ищем Наруто (или что там тебе нужно)
let params = AnimeSearchParams {
search: Some("naruto".to_string()),
limit: Some(10),
kind: None,
};
let animes = client.animes(params).await?;
for anime in animes {
println!("{} (ID: {})", anime.name, anime.id);
}
Ok(())
}
let params = AnimeSearchParams {
limit: Some(10),
search: Some("naruto".to_string()),
kind: None,
};
let animes = client.animes(params).await?;
let params = MangaSearchParams {
limit: Some(5),
search: Some("one piece".to_string()),
kind: None,
};
let mangas = client.mangas(params).await?;
Можно искать по странице, можно по ID — как удобнее:
// По странице
let params = CharacterSearchParams {
page: Some(1),
limit: Some(20),
ids: None,
};
let characters = client.characters(params).await?;
// Или по ID (если знаешь, кого ищешь)
let params = CharacterSearchParams {
page: None,
limit: None,
ids: Some(vec!["1".to_string(), "2".to_string()]),
};
let characters = client.characters(params).await?;
let params = PeopleSearchParams {
limit: Some(10),
search: Some("miyazaki".to_string()),
};
let people = client.people(params).await?;
let params = UserRateSearchParams {
page: Some(1),
limit: Some(20),
target_type: Some("Anime".to_string()),
order_field: Some("updated_at".to_string()),
order: Some("desc".to_string()),
};
let user_rates = client.user_rates(params).await?;
use shikicrate::ShikicrateClientBuilder;
use std::time::Duration;
let client = ShikicrateClientBuilder::new()
.timeout(Duration::from_secs(60))
.base_url("https://shikimori.one/api/graphql".to_string())
.build()?;
use shikicrate::ShikicrateClient;
// Дефолтные настройки (30 секунд таймаут)
let client = ShikicrateClient::new()?;
// С кастомным таймаутом
let client = ShikicrateClient::with_timeout(Duration::from_secs(60))?;
// С кастомным URL (если у тебя свой инстанс)
let client = ShikicrateClient::with_base_url("https://api.example.com/graphql".to_string())?;
Клиент сам разбирается с:
Retry-After и повторяет запросuse shikicrate::{ShikicrateError, Result};
match client.animes(params).await {
Err(ShikicrateError::RateLimit { retry_after, .. }) => {
println!("Rate limit, retry after: {:?} seconds", retry_after);
}
Err(ShikicrateError::Validation(msg)) => {
println!("Validation error: {}", msg);
}
Ok(animes) => println!("Found {} animes", animes.len()),
Err(e) => eprintln!("Error: {}", e),
}
Запусти пример, чтобы посмотреть, как это работает:
cargo run --example test_client
Там показывается:
src/client.rs — HTTP клиент, который делает всю грязную работуsrc/error.rs — типы ошибок (чтобы знать, что пошло не так)src/types.rs — типы данных (Anime, Manga, Character, Person и т.д.)src/queries.rs — методы для выполнения запросовanimes, mangas, characters, people, userrates — GraphQL запросыcargo test
MIT OR Apache-2.0 — используй как хочешь.