vn-core 0.11.1

VNDB for Rust
Documentation
use super::request_json;
use crate::error::Result;
use crate::http::{Endpoint, JsonQueryBuilder as Query, UrlQueryParams};
use crate::make_request;
use crate::model::prelude::*;
use crate::vndb::{Token, Vndb};
use http::Method;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::sync::Weak;
use tokio::sync::Semaphore;
use tokio::time::Duration;

pub mod prelude {
  pub use super::{
    CharacterQuery, Post, ProducerQuery, ReleaseQuery, StaffQuery, TagQuery, TraitQuery,
    VisualNovelQuery,
  };
}

pub type CharacterQuery = Query<CharacterField, SortCharacterBy, Response<Character>>;
pub type ProducerQuery = Query<ProducerField, SortProducerBy, Response<Producer>>;
pub type ReleaseQuery = Query<ReleaseField, SortReleaseBy, Response<Release>>;
pub type StaffQuery = Query<StaffField, SortStaffBy, Response<Staff>>;
pub type TagQuery = Query<TagField, SortTagBy, Response<Tag>>;
pub type TraitQuery = Query<TraitField, SortTraitBy, Response<Trait>>;
pub type VisualNovelQuery = Query<VisualNovelField, SortVisualNovelBy, Response<VisualNovel>>;

pub struct Post {
  vndb: Weak<Vndb>,
}

macro_rules! post_request {
  ($self:expr, $kind:ident, $endpoint:ident) => {{
    let vndb = Weak::clone(&$self.vndb);
    $kind::new(Box::new(move |query| {
      Box::pin(async move {
        let vndb = Vndb::upgrade(&vndb)?;
        make_request!(vndb, post_json(Endpoint::$endpoint, &query))
      })
    }))
  }};
}

impl Post {
  pub fn new(vndb: Weak<Vndb>) -> Self {
    Self { vndb }
  }

  pub fn character(&self) -> CharacterQuery {
    post_request!(self, CharacterQuery, Character)
  }

  pub fn producer(&self) -> ProducerQuery {
    post_request!(self, ProducerQuery, Producer)
  }

  pub fn release(&self) -> ReleaseQuery {
    post_request!(self, ReleaseQuery, Release)
  }

  pub fn staff(&self) -> StaffQuery {
    post_request!(self, StaffQuery, Staff)
  }

  pub fn tag(&self) -> TagQuery {
    post_request!(self, TagQuery, Tag)
  }

  pub fn r#trait(&self) -> TraitQuery {
    post_request!(self, TraitQuery, Trait)
  }

  pub fn visual_novel(&self) -> VisualNovelQuery {
    post_request!(self, VisualNovelQuery, VisualNovel)
  }
}

impl Clone for Post {
  fn clone(&self) -> Self {
    Self { vndb: Weak::clone(&self.vndb) }
  }
}

#[bon::builder]
async fn post_json<Body, Json>(
  #[builder(start_fn)] endpoint: Endpoint,
  #[builder(start_fn)] body: &Body,
  query: Option<UrlQueryParams>,
  semaphore: Weak<Semaphore>,
  token: Option<&Token>,
  delay: Option<Duration>,
  timeout: Option<Duration>,
  user_agent: Option<&str>,
) -> Result<Json>
where
  Body: Serialize + ?Sized,
  Json: DeserializeOwned,
{
  request_json(endpoint)
    .method(Method::POST)
    .semaphore(semaphore)
    .body(body)
    .maybe_query(query)
    .maybe_token(token)
    .maybe_delay(delay)
    .maybe_timeout(timeout)
    .maybe_user_agent(user_agent)
    .call()
    .await
}