1
Fork 0
mirror of https://github.com/redstrate/Auracite.git synced 2025-05-01 16:37:45 +00:00

Extract currently equipped item names

This commit is contained in:
Joshua Goins 2025-04-28 16:33:24 -04:00
parent 2c7cea378b
commit 0e1662e86e
3 changed files with 99 additions and 4 deletions

View file

@ -1,8 +1,8 @@
use serde::Serialize; use serde::Serialize;
use crate::value::{ use crate::value::{
CityStateValue, ClassJobValue, GenderValue, GrandCompanyValue, GuardianValue, NamedayValue, CityStateValue, ClassJobValue, GenderValue, GrandCompanyValue, GuardianValue, ItemValue,
RaceValue, TribeValue, WorldValue, NamedayValue, RaceValue, TribeValue, WorldValue,
}; };
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
@ -40,6 +40,36 @@ pub struct Appearance {
pub facepaint_color: i32, pub facepaint_color: i32,
} }
#[derive(Default, Serialize)]
pub struct EquippedItems {
#[serde(skip_serializing_if = "Option::is_none")]
pub main_hand: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub off_hand: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub head: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hands: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub legs: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub feet: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub earrings: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub necklace: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bracelets: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub left_ring: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub right_ring: Option<ItemValue>,
#[serde(skip_serializing_if = "Option::is_none")]
pub soul_crystal: Option<ItemValue>,
}
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
pub struct CharacterData { pub struct CharacterData {
pub name: String, pub name: String,
@ -57,6 +87,7 @@ pub struct CharacterData {
pub free_company: Option<String>, pub free_company: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>, pub title: Option<String>,
pub equipped: EquippedItems,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub currencies: Option<Currencies>, pub currencies: Option<Currencies>,

View file

@ -1,8 +1,8 @@
use crate::{ use crate::{
data::CharacterData, data::CharacterData,
value::{ value::{
CityStateValue, ClassJobValue, GenderValue, GuardianValue, NamedayValue, RaceValue, CityStateValue, ClassJobValue, GenderValue, GuardianValue, ItemValue, NamedayValue,
TribeValue, WorldValue, RaceValue, TribeValue, WorldValue,
}, },
}; };
use regex::Regex; use regex::Regex;
@ -173,5 +173,63 @@ pub fn parse_lodestone(data: &str) -> CharacterData {
} }
} }
// TODO: support facewear
let item_slot_selectors = [
".icon-c--0", // Main Hand
".icon-c--1", // Off hand
".icon-c--2", // Head
".icon-c--3", // Body
".icon-c--4", // Hands
".icon-c--6", // Legs
".icon-c--7", // Feet
".icon-c--8", // Earrings
".icon-c--9", // Necklace
".icon-c--10", // Bracelets
".icon-c--11", // Left Ring
".icon-c--12", // Right Ring
".icon-c--13", // Soul Crystal
];
for (i, selector) in item_slot_selectors.iter().enumerate() {
if let Some(slot) = document.select(&Selector::parse(selector).unwrap()).nth(0) {
if let Some(item) = slot.select(&Selector::parse(".db-tooltip").unwrap()).nth(0) {
let parsed_item = parse_item_tooltip(&item);
let slot = match i {
0 => &mut char_data.equipped.main_hand,
1 => &mut char_data.equipped.off_hand,
2 => &mut char_data.equipped.head,
3 => &mut char_data.equipped.body,
4 => &mut char_data.equipped.hands,
5 => &mut char_data.equipped.legs,
6 => &mut char_data.equipped.feet,
7 => &mut char_data.equipped.earrings,
8 => &mut char_data.equipped.necklace,
9 => &mut char_data.equipped.bracelets,
10 => &mut char_data.equipped.left_ring,
11 => &mut char_data.equipped.right_ring,
12 => &mut char_data.equipped.soul_crystal,
_ => panic!("Unexpected slot!"),
};
*slot = parsed_item;
}
}
}
char_data char_data
} }
fn parse_item_tooltip(element: &scraper::ElementRef<'_>) -> Option<ItemValue> {
if let Some(slot) = element
.select(&Selector::parse(".db-tooltip__item__name").unwrap())
.nth(0)
{
let text: String = slot.text().collect();
let item_name = text.strip_suffix("\u{e03c}").unwrap();
return Some(ItemValue {
name: item_name.to_string(),
});
}
None
}

View file

@ -308,3 +308,9 @@ pub struct GrandCompanyValue {
/// Name of your rank in the grand company. /// Name of your rank in the grand company.
pub rank: String, pub rank: String,
} }
#[derive(Default, Serialize)]
pub struct ItemValue {
/// Name of the item.
pub name: String,
}