df_st_api 0.3.0-development-1

Starting an API server for the DF Storyteller project.
Documentation
use crate::api_errors::{APIErrorNoContent, APIErrorNotModified};
use crate::api_objects::ApiObject;
use crate::pagination::{
    ApiCountPage, ApiCountPagination, ApiItem, ApiItemQuery, ApiPage, ApiPagination,
};
use crate::DfStDatabase;
use crate::ServerInfo;
use df_st_core::item_count::ItemCount;
use df_st_db::{id_filter, DBObject};
use rocket::{get, State};
use rocket_contrib::json::Json;
use df_rocket_okapi_codegen::openapi;

impl ApiObject for df_st_core::Region {
    fn get_type() -> String {
        "region".to_owned()
    }
    fn get_item_link(&self, base_url: &str) -> String {
        format!("{}/regions/{}", base_url, self.id)
    }
    fn get_page_link(base_url: &str) -> String {
        format!("{}/regions", base_url)
    }
    fn get_count_link(base_url: &str) -> String {
        format!("{}/regions/count", base_url)
    }
}

/// Request a `Region` by id.
///
/// ( Since = "0.1.0" )
#[openapi]
#[get("/regions/<region_id>?<item_query..>")]
pub fn get_region(
    conn: DfStDatabase,
    region_id: i32,
    item_query: ApiItemQuery,
    server_info: State<ServerInfo>,
) -> Result<Json<ApiItem<df_st_core::Region>>, APIErrorNoContent> {
    let mut api_page = ApiItem::<df_st_core::Region>::new(&server_info, &item_query);
    let item_search = df_st_db::Region::get_from_db(
        &*conn,
        id_filter!["id" => region_id, "world_id" => server_info.world_id],
        api_page.get_nested_items(),
    )?;
    if let Some(item) = item_search {
        api_page.wrap(item);
        return Ok(Json(api_page));
    }
    Err(APIErrorNoContent::new())
}

/// Request a list of all `Regions` in the world.
///
/// ( Since = "0.1.0" )
#[openapi]
#[get("/regions?<pagination..>")]
pub fn list_regions(
    conn: DfStDatabase,
    pagination: ApiPagination,
    server_info: State<ServerInfo>,
) -> Result<Json<ApiPage<df_st_core::Region>>, APIErrorNotModified> {
    let mut api_page = ApiPage::<df_st_core::Region>::new(&pagination, &server_info);
    api_page.match_fields::<df_st_db::Region, _, _>()?;

    api_page.total_item_count = df_st_db::Region::get_count_from_db(
        &*conn,
        api_page.add_int_filter(id_filter!["world_id" => server_info.world_id]),
        api_page.get_string_filter(),
        0,
        1,
        None,
        None,
    )?
    .get(0)
    .unwrap()
    .count;

    let result_list = df_st_db::Region::get_list_from_db(
        &*conn,
        api_page.add_int_filter(id_filter!["world_id" => server_info.world_id]),
        api_page.get_string_filter(),
        api_page.page_start,
        api_page.max_page_size,
        api_page.get_db_order(),
        api_page.order_by.clone(),
        None,
        api_page.get_nested_items(),
    )?;

    if api_page.wrap(result_list) {
        return Err(APIErrorNotModified::new());
    }
    Ok(Json(api_page))
}

/// Request a counts about `Region` grouped by a field.
///
/// ( Since = "0.1.0" )
#[openapi]
#[get("/regions/count?<group_by>&<pagination..>")]
pub fn get_region_count(
    conn: DfStDatabase,
    group_by: Option<String>,
    pagination: ApiCountPagination,
    server_info: State<ServerInfo>,
) -> Result<Json<ApiCountPage<ItemCount, df_st_core::Region>>, APIErrorNotModified> {
    let mut api_page =
        ApiCountPage::<ItemCount, df_st_core::Region>::new(&pagination, &server_info);
    api_page.group_by = group_by;
    api_page.match_fields::<df_st_db::Region, _, _>()?;

    api_page.total_item_count = df_st_db::Region::get_count_from_db(
        &*conn,
        api_page.add_int_filter(id_filter!["world_id" => server_info.world_id]),
        api_page.get_string_filter(),
        0,
        u32::MAX,
        api_page.group_by.clone(),
        None,
    )?
    .len() as u32;

    let result_list = df_st_db::Region::get_count_from_db(
        &*conn,
        api_page.add_int_filter(id_filter!["world_id" => server_info.world_id]),
        api_page.get_string_filter(),
        api_page.page_start,
        api_page.max_page_size,
        api_page.group_by.clone(),
        None,
    )?;

    if api_page.wrap(result_list) {
        return Err(APIErrorNotModified::new());
    }
    Ok(Json(api_page))
}