Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stage 0.5.0, add blocking feature. #34

Merged
merged 6 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@
- `Released` type has been changed to a struct with an inner tuple value, though to get the regions, you use the functions:
- `Released::japan()`, `Released::global()`, and `Released::china()` for example.

## Fixes ⚒️
### Fixes ⚒️

- Applied a change to the `Student::position` function, was passing in the `Student::armor_type` for some reason... oops!

## 0.5.0 - 2024-04-01

### Additions ✨

Added the new `blocking` feature. It is not enabled by default, so you must require it if you wish to use it!

- This uses reqwest's `blocking` feature to handle all requests in a non-asynchronous way.

### Changes 📝

- Changed how some internal deserialization and hashing works in the crate.

### Fixes ⚒️
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "blue_archive"
version = "0.4.0"
version = "0.5.0"
edition = "2021"
license-file = "LICENSE"
description = "A Blue Archive api wrapper for Rust, based off of SchaleDB's data: https://github.com/lonqie/SchaleDB"
Expand Down Expand Up @@ -33,3 +33,11 @@ strum_macros = "0.26"

# futures = "0.3"
# chrono = { version = "0.4", features = ["serde"] }

[features]
blocking = ["reqwest/blocking"]

[[example]]
name = "get_all_students"
path = "examples/blocking/get_all_students.rs"
required-features = ["blocking"]
14 changes: 14 additions & 0 deletions examples/blocking/get_all_students.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use anyhow::Result;
use blue_archive::Language;

pub fn main() -> Result<()> {
// You can obtain the students in a blocking context now.
let students = blue_archive::blocking::get_all_students(Language::English)?;
println!("# of students: {}", students.len());
// You may also use filtering and the StudentFetcher as you would usually do, though with blocking you will have to use the `new_blocking` function.
let fetched = blue_archive::StudentFetcher::new_blocking(Language::Japanese)?;
if let Some(student) = fetched.get_random_student() {
println!("Randomized Student: [{student}]")
}
Ok(())
}
2 changes: 1 addition & 1 deletion examples/fetch_currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async fn main() -> anyhow::Result<()> {
println!("Pyroxenes");
println!("--------------------------");
println!(
"{:?}",
"{:#?}",
blue_archive::fetch_currency_by_name("Pyroxenes", Language::English)
.await?
.unwrap()
Expand Down
10 changes: 9 additions & 1 deletion examples/fetch_equipment.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
use blue_archive::Language;
use blue_archive::{types::equipment::EquipmentCategory, Language};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
for equipment in blue_archive::fetch_all_equipment(Language::English).await? {
println!("{}", equipment.name)
}

let hats = blue_archive::fetch_equipment_by_category(Language::English, EquipmentCategory::Hat)
.await?;

for hat in &hats {
println!("[{}] -> {}", hat.id, hat.name)
}

Ok(())
}
59 changes: 59 additions & 0 deletions src/api/blocking/currency.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use std::borrow::Borrow;

use crate::types::currency::Currency;

use crate::Language;

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client, Result,
};

/**
Fetches all existing **[`Currency`]** currently in the database.

# Examples
```
use blue_archive::Language;

fn main() -> anyhow::Result<()> {
println!(
"Total Currencies: [{}]",
blue_archive::blocking::get_all_currencies(Language::English).len()
);
Ok(())
}
```
*/
fn get_all_currencies(language: impl Borrow<Language>) -> Result<Vec<Currency>, BlueArchiveError> {
Ok(
get_response(&Endpoint::Currency, language.borrow(), &Client::new())?
.json::<Vec<Currency>>()?,
)
}

/**
Fetches a specific **[`Currency`]** that matches with a provided **`name`** argument.

# Examples
```
use blue_archive::Language;

fn main() -> anyhow::Result<()> {
let pyroxenes_now = blue_archive::blocking::get_currency_by_name("Pyroxenes", Language::English)
.unwrap();
println!("Pyroxenes");
println!("--------------------------");
println!("{:?}", pyroxenes_now);
Ok(())
}
```
*/
pub fn get_currency_by_name(
name: impl AsRef<str>,
language: impl Borrow<Language>,
) -> Result<Option<Currency>, BlueArchiveError> {
Ok(get_all_currencies(language)?
.into_iter()
.find(|currency| currency.name.to_lowercase() == name.as_ref().to_lowercase()))
}
32 changes: 32 additions & 0 deletions src/api/blocking/enemy.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::borrow::Borrow;

use crate::types::enemy::Enemy;

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client, Result,
};

use crate::Language;

/// Fetches all [`Enemy`]'s that are currently in the database.
pub fn get_all_enemies(language: impl Borrow<Language>) -> Result<Vec<Enemy>, BlueArchiveError> {
Ok(
get_response(&Endpoint::Enemies, language.borrow(), &Client::new())?
.json::<Vec<Enemy>>()?,
)
}

/**
Fetches a specific **[`Enemy`]** that matches with a provided **`name`** argument.


*/
pub fn get_enemy_by_name(
language: impl Borrow<Language>,
name: impl AsRef<str>,
) -> Result<Option<Enemy>, BlueArchiveError> {
Ok(get_all_enemies(language)?
.into_iter()
.find(|enemy| enemy.name.to_lowercase() == name.as_ref().to_lowercase()))
}
41 changes: 41 additions & 0 deletions src/api/blocking/equipment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::borrow::Borrow;

use crate::types::equipment::{Equipment, EquipmentCategory};

use crate::Language;

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client, Result,
};

/** Fetches all equipment in the database. */
pub fn get_all_equipment(
language: impl Borrow<Language>,
) -> Result<Vec<Equipment>, BlueArchiveError> {
Ok(
get_response(&Endpoint::Equipment, language.borrow(), &Client::new())?
.json::<Vec<Equipment>>()?,
)
}

/** Fetches all equipment that is equal to the given **`name`**. */
pub fn get_equipment_by_name(
language: impl Borrow<Language>,
name: impl AsRef<str>,
) -> Result<Option<Equipment>, BlueArchiveError> {
Ok(get_all_equipment(language)?
.into_iter()
.find(|equipment| equipment.name.to_lowercase() == name.as_ref().to_lowercase()))
}

/** Fetches all equipment that is equal to the given **[`EquipmentCategory`]**. */
pub fn get_equipment_by_category(
language: impl Borrow<Language>,
category: EquipmentCategory,
) -> Result<Vec<Equipment>, BlueArchiveError> {
Ok(get_all_equipment(language)?
.into_iter()
.filter(|equipment| equipment.category == category)
.collect::<Vec<_>>())
}
14 changes: 14 additions & 0 deletions src/api/blocking/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub mod currency;
pub mod enemy;
pub mod equipment;
pub mod raid;
pub mod student;
pub mod summon;

use anyhow::Result;

use super::internal;
use crate::BlueArchiveError;
use reqwest::blocking::Client;

pub use self::{currency::*, enemy::*, equipment::*, raid::*, student::*, summon::*};
17 changes: 17 additions & 0 deletions src/api/blocking/raid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//! Functions primarily for geting [`RaidData`].

use std::borrow::Borrow;

use anyhow::Result;

use crate::{types::RaidData, Language};

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client,
};

/// Fetches **[`RaidData`]**, which contains information related to raids in Blue Archive.
pub fn get_raid_data(language: impl Borrow<Language>) -> Result<RaidData, BlueArchiveError> {
Ok(get_response(&Endpoint::Raids, language.borrow(), &Client::new())?.json::<RaidData>()?)
}
106 changes: 106 additions & 0 deletions src/api/blocking/student.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//! Functions primarily for geting [`Student`] data.

use std::borrow::Borrow;

use rand::seq::IteratorRandom;

use crate::{
filter::student::StudentFilterOptions,
types::{students::student::StudentImageData, Student},
Language,
};

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client, Result,
};

/// Fetches all students with extra data, which includes the images of the **[`Students`][`Student`]** among other things.
pub fn get_all_students(language: impl Borrow<Language>) -> Result<Vec<Student>, BlueArchiveError> {
let client = Client::new();
let mut students =
get_response(&Endpoint::Students, language.borrow(), &client)?.json::<Vec<Student>>()?;

students
.iter_mut()
.for_each(|student| student.image = StudentImageData::new(student));

Ok(students)
}

/**
Fetches a **[`Student`]** by a `name` from a set of names.

## Different Methods
- Searching with an associated tag, such as **`Iori (Swimsuit)`**
- It is recommended to use the last name and an associated tag if you are looking for a **[`Student`]** with a different appearance.
- Searching via. the **last name (`surname`)**.
- Searching via. the **first name**.
- Searching via. the **first name and last name together**, and vise versa (e.g. Asuna Ichinose/Ichinose Asuna).

# Examples
```
use anyhow::Result;

use blue_archive::Language;

fn main() -> Result<()> {
// Fetching asuna is relatively simple...
let asuna = blue_archive::blocking::get_student_by_name("Asuna", Language::English)?.unwrap();
println!("{}", asuna);
Ok(())
}
```
*/
pub fn get_student_by_name(
name: impl AsRef<str>,
language: impl Borrow<Language>,
) -> Result<Option<Student>, BlueArchiveError> {
let mut matched_student = None;

for student in get_all_students(language)? {
let lowercased = name.as_ref().to_lowercase();
let maybe_student = (lowercased == student.name.to_lowercase()
|| lowercased == student.first_name.to_lowercase()
|| lowercased == student.last_name.to_lowercase()
|| lowercased == student.full_name_last().to_lowercase()
|| lowercased == student.full_name_first().to_lowercase())
.then_some(student);
if let Some(student) = maybe_student {
matched_student = Some(student);
break;
}
}

Ok(matched_student)
}

/// Attempts to get a random **[`Student`]**.
///
/// If geting the data fails, then it will return a [`BlueArchiveError`], as the data would not have any **[`Students`][`Student`]**.
pub fn get_random_student(
language: impl Borrow<Language>,
) -> Result<Option<Student>, BlueArchiveError> {
Ok(get_all_students(language)?
.into_iter()
.choose(&mut rand::thread_rng()))
}

/// Attempts to get a random amount of **[`Students`][`Student`]** depending on the specified **`amount`**.
///
/// Depending on the **`amount`** inserted, if it exceeds the total length of **[`Students`][`Student`]** from the data, it will just return everything.
///
/// If geting the data fails, then it will return a [`BlueArchiveError`], as the data would not have any **[`Students`][`Student`]**.
pub fn get_random_students(
language: impl Borrow<Language>,
amount: usize,
) -> Result<Vec<Student>, BlueArchiveError> {
Ok(get_all_students(language)?
.into_iter()
.choose_multiple(&mut rand::thread_rng(), amount))
}

/// Returns **[`StudentFilterOptions`]** to be used with the provided **[`Vec<Student>`]** for filtering.
pub fn filter(students: &Vec<Student>) -> StudentFilterOptions {
StudentFilterOptions::new(students)
}
18 changes: 18 additions & 0 deletions src/api/blocking/summon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! Functions primarily for geting [`Summon`] data.

use std::borrow::Borrow;

use crate::{types::Summon, Language};

use super::{
internal::{get_response, Endpoint},
BlueArchiveError, Client,
};

/// Fetches all **[`Summons`][`Summon`]** from the data.
pub fn get_all_summons(language: impl Borrow<Language>) -> Result<Vec<Summon>, BlueArchiveError> {
Ok(
get_response(&Endpoint::Summons, language.borrow(), &Client::new())?
.json::<Vec<Summon>>()?,
)
}
Loading
Loading