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:
parent
1ade743f82
commit
c3f4679c4b
6 changed files with 88 additions and 91 deletions
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
44
src/lib.rs
44
src/lib.rs
|
@ -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;
|
||||
}
|
||||
|
|
107
src/parser.rs
107
src/parser.rs
|
@ -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}") {
|
||||
|
|
|
@ -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(),
|
||||
|
|
Loading…
Add table
Reference in a new issue