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

0.3.94 #28

Merged
merged 3 commits into from
Feb 3, 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
.vscode/
Cargo.lock
Cargo.lock
.idea/
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "blue_archive"
version = "0.3.93"
version = "0.3.94"
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 All @@ -16,7 +16,6 @@ tokio = { version = "1", features = [
"rt-multi-thread",
] }
reqwest = { version = "0.11", features = ["json"] }
futures = "0.3"

serde = { version = "1", features = ["derive"] }
html-escape = "0.2"
Expand All @@ -29,4 +28,5 @@ thiserror = "1.0"
strum = "0.25"
strum_macros = "0.25"

# futures = "0.3"
# chrono = { version = "0.4", features = ["serde"] }
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ A Rust API wrapper of lonqie's SchaleDB that represents data from the game **Blu
- **Owner: <https://github.com/lonqie>**
- **Website: <https://schale.gg/>**

---

## Information

Something I wanted to make in Rust was a simple api wrapper, picked something and the rest was history.
Expand All @@ -21,8 +19,6 @@ Something I wanted to make in Rust was a simple api wrapper, picked something an

- **Repository: <https://github.com/MerryweatherLost/blue_archive_api-rs>**

---

## Contributing

If you wish to help out, you can. I am a beginner in Rust and I do not mind a few pointers.
7 changes: 7 additions & 0 deletions examples/fetch_students_under_clubs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,12 @@ async fn main() -> anyhow::Result<()> {
})
});

// Of course, you can just filter the students through the direct filter.
let maids = blue_archive::filter(&students)
.apply(Club::CleaningAndClearing)
.finish();
println!("{} Members : [{}]", Club::CleaningAndClearing, maids.len());
maids.iter().for_each(|student| println!("{student}"));

Ok(())
}
48 changes: 23 additions & 25 deletions src/api/student.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

use std::borrow::Borrow;

use crate::types::students::student::StudentImageData;

use super::{
internal::{fetch_response, Endpoint},
BlueArchiveError, Client, IteratorRandom, Language, Result, Student, StudentFilterOptions,
Expand All @@ -16,12 +18,11 @@ pub async fn fetch_all_students(
.await?
.json::<Vec<Student>>()
.await?;
futures::future::join_all(
students
.iter_mut()
.map(|student| async { student.fetch_extra_data(&client).await }),
)
.await;

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

Ok(students)
}

Expand Down Expand Up @@ -55,27 +56,24 @@ pub async fn fetch_student_by_name(
language: impl Borrow<Language>,
) -> Result<Option<Student>, BlueArchiveError> {
let name: String = name.into();
let possible_student = fetch_all_students(language)
.await?
.into_iter()
.find(|student| {
[
&student.name,
&student.first_name(),
&student.last_name(),
&student.full_name_last(),
&student.full_name_first(),
]
.into_iter()
.any(|x| x.to_lowercase() == name.to_lowercase())
});
match possible_student {
Some(mut student) => {
student.fetch_extra_data(&Client::new()).await?;
Ok(Some(student))

let mut matched_student = None;

for student in fetch_all_students(language).await? {
let lowercased = name.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;
}
None => Ok(None),
}

Ok(matched_student)
}

/// Attempts to fetch a random **[`Student`]**.
Expand Down
28 changes: 17 additions & 11 deletions src/fetcher/student.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,23 @@ impl StudentFetcher {
*/
pub fn get_student_by_name(&self, name: impl Into<String>) -> Option<&Student> {
let name: String = name.into();
self.students.iter().find(|student| {
[
&student.name,
&student.first_name(),
&student.last_name(),
&student.full_name_last(),
&student.full_name_first(),
]
.into_iter()
.any(|x| x.to_lowercase() == name.to_lowercase())
})
let mut matched_student = None;

for student in &self.students {
let lowercased = name.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;
}
}

matched_student
}

/// Attempts to get a random **[`Student`]**.
Expand Down
1 change: 1 addition & 0 deletions src/types/raids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ impl Raid {
Released {
japan: self.is_released.0,
global: self.is_released.1,
china: self.is_released.2,
}
}

Expand Down
1 change: 1 addition & 0 deletions src/types/students/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl Display for Age {
pub struct Released {
pub japan: bool,
pub global: bool,
pub china: bool,
}

impl Display for Released {
Expand Down
76 changes: 25 additions & 51 deletions src/types/students/student.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

use std::str::FromStr;

use reqwest::Client;
use serde::{Deserialize, Serialize};

use crate::{
enums::*,
types::{Age, Effect, Released, SkillKind, ID},
BlueArchiveError, IMAGE_DATA_URI,
IMAGE_DATA_URI,
};

use anyhow::Result;

use super::Height;

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
Expand Down Expand Up @@ -165,6 +162,7 @@ impl Student {
Released {
japan: self.is_released.0,
global: self.is_released.1,
china: self.is_released.2,
}
}

Expand All @@ -191,59 +189,45 @@ impl Student {

/// Gets the **[`School`]** of the student.
pub fn school(&self) -> School {
School::from_str(&self.school).unwrap_or_else(|_| School::Unknown(self.school.clone()))
School::from_str(&self.school).unwrap_or(School::Unknown(self.school.clone()))
}

/// Gets the **[`TacticalRole`]** of the student.
pub fn tactical_role(&self) -> TacticalRole {
TacticalRole::from_str(&self.tactic_role)
.unwrap_or_else(|_| TacticalRole::Unknown(self.tactic_role.clone()))
.unwrap_or(TacticalRole::Unknown(self.tactic_role.clone()))
}

/// Gets the **[`Squad`]** of the student.
pub fn squad(&self) -> Squad {
Squad::from_str(&self.squad_type)
.unwrap_or_else(|_| Squad::Unknown(self.squad_type.clone()))
Squad::from_str(&self.squad_type).unwrap_or(Squad::Unknown(self.squad_type.clone()))
}

/// Gets the **[`Armor`]** of the student.
pub fn armor(&self) -> Armor {
Armor::from_str(&self.armor_type)
.unwrap_or_else(|_| Armor::Unknown(self.armor_type.clone()))
Armor::from_str(&self.armor_type).unwrap_or(Armor::Unknown(self.armor_type.clone()))
}

/// Gets the **[`Position`]** of the student.
pub fn position(&self) -> Position {
Position::from_str(&self.armor_type)
.unwrap_or_else(|_| Position::Unknown(self.armor_type.clone()))
Position::from_str(&self.armor_type).unwrap_or(Position::Unknown(self.armor_type.clone()))
}

/// Gets the **[`BulletType`]** of the student.
pub fn bullet_type(&self) -> BulletType {
BulletType::from_str(&self.bullet_type)
.unwrap_or_else(|_| BulletType::Unknown(self.bullet_type.clone()))
.unwrap_or(BulletType::Unknown(self.bullet_type.clone()))
}

/// Gets the **[`Club`]** of the student.
pub fn club(&self) -> Club {
Club::from_str(&self.club).unwrap_or_else(|_| Club::Unknown(self.club.clone()))
Club::from_str(&self.club).unwrap_or(Club::Unknown(self.club.clone()))
}

/// Gets the **[`WeaponType`]** of the student.
pub fn weapon_type(&self) -> WeaponType {
WeaponType::from_str(&self.weapon_type)
.unwrap_or_else(|_| WeaponType::Unknown(self.weapon_type.clone()))
}

/// Fetches extra data of this **[`Student`]**.
///
/// Has a possibility of failing when trying to use the [`Client`].
pub(crate) async fn fetch_extra_data(
&mut self,
client: &Client,
) -> Result<(), BlueArchiveError> {
self.image = StudentImageData::new(self, client).await?;
Ok(())
.unwrap_or(WeaponType::Unknown(self.weapon_type.clone()))
}
}

Expand Down Expand Up @@ -294,7 +278,7 @@ pub struct Summon {
#[serde(untagged)]
pub enum GearKind {
Present(Gear),
Empty(EmptyGear),
Empty(Empty),
}
impl GearKind {
/// Attempts to get a **[`Gear`]**, though if it gets an [`GearKind::Empty`], it will return [`None`].
Expand All @@ -309,7 +293,7 @@ impl GearKind {
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct Gear {
released: (bool, bool),
released: (bool, bool, bool),
pub stat_type: Vec<String>,
pub stat_value: Vec<Vec<u16>>,
pub name: String,
Expand All @@ -325,6 +309,7 @@ impl Gear {
Released {
japan: self.released.0,
global: self.released.1,
china: self.released.2,
}
}

Expand All @@ -334,10 +319,10 @@ impl Gear {
}
}
/// There is an issue where Gear in data is represented as `"gear": {}`, therefore this is a mitigation against that.
/// If you have a better implementation of handling this, as in allowing for me to represent the data as an `Option<Gear>`, please send a PR.
/// If you have a better implementation of handling this, as in allowing for me to represent the data as an `Option<...>`, please send a PR.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(rename_all = "PascalCase")]
pub struct EmptyGear {}
pub struct Empty {}

#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
#[serde(rename_all = "PascalCase")]
Expand Down Expand Up @@ -380,31 +365,20 @@ pub struct StudentImageData {
}

impl StudentImageData {
/// Creates itself from a given **[`Student`]** and **[`reqwest::Client`]**.
///
/// Will query for extra image data when constructed.
pub async fn new(student: &Student, client: &Client) -> Result<Self, BlueArchiveError> {
Ok(Self {
/// Creates itself from a given **[`Student`]**.
pub fn new(student: &Student) -> Self {
Self {
portrait: Portrait {
full_body_url: format!("{IMAGE_DATA_URI}/student/portrait/{}.webp", student.id.0),
icon_url: format!("{IMAGE_DATA_URI}/student/icon/{}.webp", student.id.0),
alternative_full_body_url: Self::fetch_image_with_url(
client,
format!("{IMAGE_DATA_URI}/student/portrait/{}_2.webp", student.id.0),
)
.await,
alternative_full_body_url: format!(
"{IMAGE_DATA_URI}/student/portrait/{}_2.webp",
student.id.0
),
bg_url: format!("{IMAGE_DATA_URI}/background/{}.jpg", student.collection_bg),
},
weapon_icon_url: format!("{IMAGE_DATA_URI}/weapon/{}.webp", student.weapon_img),
})
}

async fn fetch_image_with_url(client: &Client, url: impl Into<String>) -> Option<String> {
let url: String = url.into();
(client.get(&url).send().await).map_or(None, |response| match response.error_for_status() {
Ok(_) => Some(url),
Err(_) => None,
})
}
}
}

Expand All @@ -415,8 +389,8 @@ pub struct Portrait {
pub full_body_url: String,
/// The icon url associated with this **[`Student`]**.
pub icon_url: String,
/// If there is an alternative full-body image url associated with this **[`Student`]**.
pub alternative_full_body_url: Option<String>,
/// If there is an alternative full-body image url associated with this **[`Student`]**. There is a chance for this
pub alternative_full_body_url: String,
/// The background image url associated with this **[`Student`]**.
pub bg_url: String,
}
5 changes: 2 additions & 3 deletions src/types/summons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,12 @@ impl Summon {
/// Gets the **[`Bullet`]** type of the summon.
pub fn bullet_type(&self) -> BulletType {
BulletType::from_str(&self.bullet_type)
.unwrap_or_else(|_| BulletType::Unknown(self.bullet_type.clone()))
.unwrap_or(BulletType::Unknown(self.bullet_type.clone()))
}

/// Gets the **[`Armor`]** of the summon.
pub fn armor(&self) -> Armor {
Armor::from_str(&self.armor_type)
.unwrap_or_else(|_| Armor::Unknown(self.armor_type.clone()))
Armor::from_str(&self.armor_type).unwrap_or(Armor::Unknown(self.armor_type.clone()))
}
}

Expand Down
Loading