1
Fork 0
mirror of https://github.com/redstrate/Auracite.git synced 2025-06-30 17:47:45 +00:00

Fix the outstanding warnings

This commit is contained in:
Joshua Goins 2025-06-29 19:59:41 -04:00
parent 1ade743f82
commit c3f4679c4b
6 changed files with 88 additions and 91 deletions

View file

@ -27,7 +27,7 @@ serde = { version = "1.0", features = ["derive"], default-features = false }
regex = { version = "1.11", default-features = false, features = ["unicode-perl"] }
# Used to generate the HTML page to easily preview your exported data
minijinja = { version = "2.11", default-features = false }
minijinja = { version = "2.11", features = ["serde"], default-features = false }
# Download files
reqwest = { version = "0.12" }
@ -38,7 +38,7 @@ zip = { version = "4.2", default-features = false }
# Exporting propietary game data
physis = { git = "https://github.com/redstrate/Physis" }
# Encoding the character archive to base64 so the browser can download it and decoding the base64 images from the c lient
# Encoding the character archive to base64 so the browser can download it and decoding the base64 images from the client
base64 = { version = "0.22", default-features = false }
# Not used directly by us, but to disable the "std" feature and is used by the scraper crate.

View file

@ -51,7 +51,7 @@ pub struct BackendRust {}
impl bridge::Backend {
pub fn archive_character_by_name(
mut self: Pin<&mut Self>,
self: Pin<&mut Self>,
character_name: &QString,
use_dalamud: bool,
filename: &QString,
@ -83,7 +83,7 @@ impl bridge::Backend {
}
pub fn archive_character_by_id(
mut self: Pin<&mut Self>,
self: Pin<&mut Self>,
character_id: &QString,
use_dalamud: bool,
filename: &QString,

View file

@ -66,7 +66,7 @@ fn main() {
&QUrl::from(&QString::from("https://redstrate.com/rss-image.png")),
));
KAboutData::set_application_data(&*about_data);
KAboutData::set_application_data(&about_data);
QGuiApplication::set_desktop_file_name(&QString::from("zone.xiv.auracite"));
let mut command_line_parser = QCommandLineParser::default();
@ -91,7 +91,7 @@ fn main() {
command_line_parser.add_option(&dalamud_option);
command_line_parser.process(&QStringList::from(&QList::from(
&args().map(|x| QString::from(x)).collect::<Vec<QString>>(),
&args().map(QString::from).collect::<Vec<QString>>(),
)));
about_data
.as_mut()
@ -102,15 +102,16 @@ fn main() {
.value(&QString::from("name"))
.to_string();
println!("Downloading character data for {}...", character_name);
println!("Downloading character data for {character_name}...");
let id = search_character_blocking(&character_name).expect("Couldn't find character!");
archive_character_blocking(
id,
command_line_parser.is_set(&QString::from("dalamud")),
&format!("{}.zip", character_name),
);
&format!("{character_name}.zip"),
)
.expect("Failed to archive the requested character!");
return;
}
@ -122,13 +123,14 @@ fn main() {
.parse()
.expect("Not a valid ID!");
println!("Downloading character data for {}...", id);
println!("Downloading character data for {id}...");
archive_character_blocking(
id,
command_line_parser.is_set(&QString::from("dalamud")),
&format!("{}.zip", id), // TODO: give it the character's name
);
&format!("{id}.zip"), // TODO: give it the character's name
)
.expect("Failed to archive the requested character!");
return;
}

View file

@ -10,12 +10,11 @@ use crate::downloader::download;
use crate::html::{create_character_html, create_plate_html};
use crate::parser::parse_search;
use base64::prelude::*;
use data::{Appearance, Currencies};
use data::Appearance;
use package::Package;
use physis::savedata::chardat;
use regex::Regex;
use reqwest::Url;
use serde::Deserialize;
use std::io::Write;
use std::time::{SystemTime, UNIX_EPOCH};
#[cfg(target_family = "wasm")]
@ -124,7 +123,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
LODESTONE_HOST
};
let char_page_url = Url::parse(&format!("{lodestone_host}/lodestone/character/{}/", id))
let char_page_url = Url::parse(&format!("{lodestone_host}/lodestone/character/{id}/"))
.map_err(|_| ArchiveError::UnknownError)?;
let char_page = download(&char_page_url)
.await
@ -135,8 +134,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
parser::parse_profile(&char_page, &mut char_data);
let classjob_page_url = Url::parse(&format!(
"{lodestone_host}/lodestone/character/{}/class_job/",
id
"{lodestone_host}/lodestone/character/{id}/class_job/"
))
.map_err(|_| ArchiveError::UnknownError)?;
let classjob_page = download(&classjob_page_url)
@ -160,14 +158,14 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
} else {
&char_data.portrait_url
};
let portrait_url = Url::parse(&portrait_url).map_err(|_| ArchiveError::UnknownError)?;
let portrait_url = Url::parse(portrait_url).map_err(|_| ArchiveError::UnknownError)?;
let portrait = download(&portrait_url)
.await
.map_err(|_| ArchiveError::DownloadFailed(portrait_url.to_string()))?;
zip.start_file("portrait.jpg", options)?;
zip.write_all(&*portrait)?;
zip.write_all(&portrait)?;
}
if !char_data.face_url.is_empty() {
let face_url = if cfg!(target_family = "wasm") {
@ -175,26 +173,26 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
} else {
&char_data.face_url
};
let face_url = Url::parse(&face_url).map_err(|_| ArchiveError::UnknownError)?;
let face_url = Url::parse(face_url).map_err(|_| ArchiveError::UnknownError)?;
let face = download(&face_url)
.await
.map_err(|_| ArchiveError::DownloadFailed(face_url.to_string()))?;
zip.start_file("face.jpg", options)?;
zip.write_all(&*face)?;
zip.write_all(&face)?;
}
if use_dalamud {
let dalamud_url = Url::parse(&"http://localhost:42072/package")
.map_err(|_| ArchiveError::UnknownError)?;
let dalamud_url =
Url::parse("http://localhost:42072/package").map_err(|_| ArchiveError::UnknownError)?;
let package = download(&dalamud_url)
.await
.map_err(|_| ArchiveError::CouldNotConnectToDalamud)?;
let package = String::from_utf8(package).map_err(|_| ArchiveError::ParsingError)?;
// Remove BOM at the start
let package = package.trim_start_matches("\u{feff}");
let package: Package = serde_json::from_str(&package.trim_start()).unwrap();
let package: Package = serde_json::from_str(package.trim_start()).unwrap();
// appearance data
char_data.appearance = Some(Appearance {
@ -264,7 +262,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
zip.start_file("plate-portrait.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(
package
.portrait
@ -276,7 +274,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(base_plate) = package.base_plate {
zip.start_file("base-plate.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(base_plate.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -285,7 +283,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(pattern_overlay) = package.pattern_overlay {
zip.start_file("pattern-overlay.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(pattern_overlay.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -294,7 +292,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(backing) = package.backing {
zip.start_file("backing.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(backing.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -303,7 +301,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(top_border) = package.top_border {
zip.start_file("top-border.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(top_border.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -312,7 +310,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(bottom_border) = package.bottom_border {
zip.start_file("bottom-border.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(bottom_border.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -321,7 +319,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(portrait_frame) = package.portrait_frame {
zip.start_file("portrait-frame.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(portrait_frame.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -330,7 +328,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(plate_frame) = package.plate_frame {
zip.start_file("plate-frame.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(plate_frame.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -339,7 +337,7 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
if let Some(accent) = package.accent {
zip.start_file("accent.png", options)?;
zip.write_all(
&*BASE64_STANDARD
&BASE64_STANDARD
.decode(accent.trim_start_matches("data:image/png;base64,"))
.unwrap(),
)?;
@ -388,11 +386,11 @@ pub async fn archive_character(id: u64, use_dalamud: bool) -> Result<Vec<u8>, Ar
};
zip.start_file("FFXIV_CHARA_01.dat", options)?;
zip.write_all(&*char_dat.write_to_buffer().unwrap())?;
zip.write_all(&char_dat.write_to_buffer().unwrap())?;
// Stop the HTTP server
let stop_url =
Url::parse(&"http://localhost:42072/stop").map_err(|_| ArchiveError::UnknownError)?;
Url::parse("http://localhost:42072/stop").map_err(|_| ArchiveError::UnknownError)?;
// I'm intentionally ignoring the message because it doesn't matter if it fails - and it usually does
let _ = download(&stop_url).await;
}

View file

@ -17,16 +17,14 @@ pub fn parse_search(data: &str) -> String {
let mut href = String::new();
for element in document.select(&Selector::parse(ENTRY_SELECTOR).unwrap()) {
if let Some(block_name) = element
if let Some(_) = element
.select(&Selector::parse(ENTRY_NAME_SELECTOR).unwrap())
.nth(0)
{
if let Some(block_name) = element
.next()
&& let Some(block_name) = element
.select(&Selector::parse("a.entry__link").unwrap())
.nth(0)
{
href = block_name.attr("href").unwrap().parse().unwrap();
}
.next()
{
href = block_name.attr("href").unwrap().parse().unwrap();
}
}
@ -54,34 +52,35 @@ pub fn parse_profile(data: &str, char_data: &mut CharacterData) {
if let Some(title) = document
.select(&Selector::parse(TITLE_SELECTOR).unwrap())
.nth(0)
.next()
{
char_data.title = Some(title.inner_html().as_str().to_string());
}
let world_re = Regex::new(r"(\w+)\s\[(\w+)\]").unwrap();
for element in document.select(&Selector::parse(WORLD_DATA_CENTER_SELECTOR).unwrap()) {
let re = Regex::new(r"(\w+)\s\[(\w+)\]").unwrap();
let inner_html = element.inner_html();
let captures = re.captures(&inner_html).unwrap();
let captures = world_re.captures(&inner_html).unwrap();
// TODO: use error
char_data.world = WorldValue::try_from(captures.get(1).unwrap().as_str()).unwrap();
char_data.data_center = captures.get(2).unwrap().as_str().to_owned();
}
let block_re = Regex::new(r"([^<]+)<br>([^\/]+)\s\/\s(\W)").unwrap();
let grand_re = Regex::new(r"([^\/]+)\s\/\s([^\/]+)").unwrap();
for element in document.select(&Selector::parse(CHARACTER_BLOCK_SELECTOR).unwrap()) {
if let Some(block_title) = element
.select(&Selector::parse(CHARACTER_BLOCK_TITLE_SELECTOR).unwrap())
.nth(0)
.next()
{
let name = block_title.inner_html();
if name == "Race/Clan/Gender" {
if let Some(block_name) = element
.select(&Selector::parse(CHARACTER_BLOCK_NAME_SELECTOR).unwrap())
.nth(0)
.next()
{
let re = Regex::new(r"([^<]+)<br>([^\/]+)\s\/\s(\W)").unwrap();
let inner_html = block_name.inner_html();
let captures = re.captures(&inner_html).unwrap();
let captures = block_re.captures(&inner_html).unwrap();
char_data.race =
RaceValue::try_from(captures.get(1).unwrap().as_str()).unwrap();
@ -93,7 +92,7 @@ pub fn parse_profile(data: &str, char_data: &mut CharacterData) {
} else if name == "City-state" {
if let Some(block_name) = element
.select(&Selector::parse(CHARACTER_BLOCK_NAME_SELECTOR).unwrap())
.nth(0)
.next()
{
char_data.city_state =
CityStateValue::try_from(block_name.inner_html().as_str()).unwrap();
@ -106,29 +105,27 @@ pub fn parse_profile(data: &str, char_data: &mut CharacterData) {
if let Some(block_name) = element
.select(&Selector::parse(CHARACTER_BLOCK_NAME_SELECTOR).unwrap())
.nth(0)
.next()
{
char_data.guardian =
GuardianValue::try_from(block_name.inner_html().as_str()).unwrap();
}
} else if name == "Grand Company" {
if let Some(block_name) = element
} else if name == "Grand Company"
&& let Some(block_name) = element
.select(&Selector::parse(CHARACTER_BLOCK_NAME_SELECTOR).unwrap())
.nth(0)
{
let re = Regex::new(r"([^\/]+)\s\/\s([^\/]+)").unwrap();
let inner_html = block_name.inner_html();
let captures = re.captures(&inner_html).unwrap();
.next()
{
let inner_html = block_name.inner_html();
let captures = grand_re.captures(&inner_html).unwrap();
char_data.grand_company.name = captures.get(1).unwrap().as_str().to_string();
char_data.grand_company.rank = captures.get(2).unwrap().as_str().to_string();
}
char_data.grand_company.name = captures.get(1).unwrap().as_str().to_string();
char_data.grand_company.rank = captures.get(2).unwrap().as_str().to_string();
}
}
if let Some(free_company) = element
.select(&Selector::parse(FREE_COMPANY_SELECTOR).unwrap())
.nth(0)
.next()
{
char_data.free_company = Some(free_company.inner_html().as_str().to_string());
}
@ -138,9 +135,9 @@ pub fn parse_profile(data: &str, char_data: &mut CharacterData) {
char_data.face_url = element.attr("src").unwrap().parse().unwrap();
}
for element in document
if let Some(element) = document
.select(&Selector::parse(PORTRAIT_IMG_SELECTOR).unwrap())
.nth(0)
.next()
{
char_data.portrait_url = element.attr("src").unwrap().parse().unwrap();
}
@ -163,28 +160,28 @@ pub fn parse_profile(data: &str, char_data: &mut CharacterData) {
];
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!"),
};
if let Some(slot) = document.select(&Selector::parse(selector).unwrap()).next()
&& let Some(item) = slot.select(&Selector::parse(".db-tooltip").unwrap()).next()
{
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;
}
*slot = parsed_item;
}
}
}
@ -201,15 +198,15 @@ pub fn parse_classjob(data: &str, char_data: &mut CharacterData) {
for element in document.select(&Selector::parse(CLASSJOB_SELECTOR).unwrap()) {
let level = element
.select(&Selector::parse(CLASSJOB_LEVEL_SELECTOR).unwrap())
.nth(0)
.next()
.unwrap();
let name = element
.select(&Selector::parse(CLASSJOB_NAME_SELECTOR).unwrap())
.nth(0)
.next()
.unwrap();
let exp_element = element
.select(&Selector::parse(CLASSJOB_EXP_SELECTOR).unwrap())
.nth(0)
.next()
.unwrap();
let mut exp = None;
@ -234,7 +231,7 @@ pub fn parse_classjob(data: &str, char_data: &mut CharacterData) {
fn parse_item_tooltip(element: &scraper::ElementRef<'_>) -> Option<ItemValue> {
if let Some(slot) = element
.select(&Selector::parse(".db-tooltip__item__name").unwrap())
.nth(0)
.next()
{
let mut text: String = slot.text().collect();
if text.contains("\u{e03c}") {

View file

@ -283,7 +283,7 @@ impl TryFrom<&str> for NamedayValue {
fn try_from(value: &str) -> Result<Self, ArchiveError> {
let re = Regex::new(r"(\d{1,2})[^\d]+(\d{1,2})").unwrap();
let captures = re.captures(&value).unwrap();
let captures = re.captures(value).unwrap();
Ok(Self {
value: value.to_string(),