mirror of
https://github.com/redstrate/Auracite.git
synced 2025-04-24 21:47:45 +00:00
Move character archiving to the library
So this can eventually be called by JavaScript.
This commit is contained in:
parent
6ac3f5ced7
commit
0acea2646e
4 changed files with 150 additions and 85 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -103,6 +103,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"touche",
|
"touche",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1688,9 +1689,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
|
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -1699,9 +1700,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
|
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
|
@ -1726,9 +1727,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
|
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
@ -1736,9 +1737,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
|
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1749,9 +1750,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.93"
|
version = "0.2.95"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
|
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
|
|
|
@ -30,6 +30,9 @@ minijinja = "2.0"
|
||||||
# TODO: upstream this or poke upstream to add this
|
# TODO: upstream this or poke upstream to add this
|
||||||
touche = { git = "https://github.com/redstrate/touche" }
|
touche = { git = "https://github.com/redstrate/touche" }
|
||||||
|
|
||||||
|
# Used to generate the WebAssembly version
|
||||||
|
wasm-bindgen = "0.2.95"
|
||||||
|
|
||||||
# Not used directly by us, but to disable the "std" feature and is used by the scraper crate.
|
# Not used directly by us, but to disable the "std" feature and is used by the scraper crate.
|
||||||
ahash = { version = "0.8.0", default-features = false }
|
ahash = { version = "0.8.0", default-features = false }
|
||||||
|
|
||||||
|
|
132
src/lib.rs
132
src/lib.rs
|
@ -2,3 +2,135 @@ pub mod data;
|
||||||
pub mod downloader;
|
pub mod downloader;
|
||||||
pub mod html;
|
pub mod html;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::convert::Infallible;
|
||||||
|
use std::fs::{read, write};
|
||||||
|
use std::path::Path;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use touche::server::Service;
|
||||||
|
use touche::{Body, HttpBody, Request, Response, Server, StatusCode};
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
use crate::downloader::download;
|
||||||
|
use crate::html::write_html;
|
||||||
|
use crate::parser::parse_search;
|
||||||
|
|
||||||
|
const LODESTONE_HOST: &str = "https://na.finalfantasyxiv.com";
|
||||||
|
|
||||||
|
#[derive(Default, Deserialize, Clone)]
|
||||||
|
struct Package {
|
||||||
|
playtime: String,
|
||||||
|
height: i32,
|
||||||
|
bust_size: i32,
|
||||||
|
gil: u32,
|
||||||
|
is_battle_mentor: bool,
|
||||||
|
is_trade_mentor: bool,
|
||||||
|
is_novice: bool,
|
||||||
|
is_returner: bool,
|
||||||
|
player_commendations: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct PackageService<'a> {
|
||||||
|
wants_stop: Arc<Mutex<bool>>, // TODO: THIS IS TERRIBLE STOP STOP STOP
|
||||||
|
package: &'a Arc<Mutex<Package>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Service for PackageService<'_> {
|
||||||
|
type Body = &'static str;
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn call(&self, req: Request<Body>) -> Result<Response<Self::Body>, Self::Error> {
|
||||||
|
*self.package.lock().unwrap() = serde_json::from_str(&String::from_utf8(req.into_body().into_bytes().unwrap()).unwrap()).unwrap();
|
||||||
|
|
||||||
|
*self.wants_stop.lock().unwrap() = true;
|
||||||
|
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.body("")
|
||||||
|
.unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: NO NO NO NO
|
||||||
|
fn wants_stop(&self) -> bool {
|
||||||
|
*self.wants_stop.lock().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub extern fn archive_character(character_name: &str, use_dalamud: bool) {
|
||||||
|
let search_page_path = Path::new("/tmp/search.html");
|
||||||
|
download(
|
||||||
|
&format!("{LODESTONE_HOST}/lodestone/character/?q={}", character_name),
|
||||||
|
search_page_path,
|
||||||
|
)
|
||||||
|
.expect("Failed to download the search page from the Lodestone.");
|
||||||
|
|
||||||
|
let href = parse_search(&String::from_utf8(read(search_page_path).unwrap()).unwrap());
|
||||||
|
if href.is_empty() {
|
||||||
|
println!("Unable to find character!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let char_page_path = Path::new("/tmp/character.html");
|
||||||
|
download(&format!("{LODESTONE_HOST}{}", href), char_page_path)
|
||||||
|
.expect("Failed to download the character page from the Lodestone.");
|
||||||
|
|
||||||
|
let mut char_data = crate::parser::parse_lodestone(&String::from_utf8(read(char_page_path).unwrap()).unwrap());
|
||||||
|
|
||||||
|
let character_folder = Path::new(&character_name);
|
||||||
|
if !character_folder.exists() {
|
||||||
|
std::fs::create_dir(character_folder).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !char_data.portrait_url.is_empty() {
|
||||||
|
download(
|
||||||
|
&char_data.portrait_url,
|
||||||
|
&character_folder.join("portrait.jpg"),
|
||||||
|
)
|
||||||
|
.expect("Failed to download the character portrait image.");
|
||||||
|
}
|
||||||
|
if !char_data.face_url.is_empty() {
|
||||||
|
download(&char_data.face_url, &character_folder.join("face.jpg"))
|
||||||
|
.expect("Failed to download the character face image.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if use_dalamud {
|
||||||
|
println!("Now waiting for the Dalamud plugin. Type /auracite begin in chat.");
|
||||||
|
|
||||||
|
let package = Arc::new(Mutex::new(Package::default()));
|
||||||
|
|
||||||
|
Server::bind("0.0.0.0:8000").serve_single_thread(PackageService { wants_stop: Arc::new(Mutex::new(false)), package: &package }).unwrap();
|
||||||
|
|
||||||
|
let package = &*package.lock().unwrap();
|
||||||
|
|
||||||
|
char_data.playtime = package.playtime.parse().unwrap();
|
||||||
|
char_data.appearance.height = package.height;
|
||||||
|
char_data.appearance.bust_size = package.bust_size;
|
||||||
|
char_data.currencies.gil = package.gil; // TODO: also fetch from the lodestone
|
||||||
|
char_data.is_battle_mentor = package.is_battle_mentor;
|
||||||
|
char_data.is_trade_mentor = package.is_trade_mentor;
|
||||||
|
char_data.is_novice = package.is_novice;
|
||||||
|
char_data.is_returner = package.is_returner;
|
||||||
|
char_data.player_commendations = package.player_commendations; // TODO: fetch from the lodestone?
|
||||||
|
}
|
||||||
|
|
||||||
|
let serialized = serde_json::to_string(&char_data).unwrap();
|
||||||
|
write(character_folder.join("character.json"), serialized)
|
||||||
|
.expect("Failed to write the character JSON file.");
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Download complete! The archive is located at: {}",
|
||||||
|
character_folder.file_name().unwrap().to_str().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
write_html(
|
||||||
|
&char_data,
|
||||||
|
&character_folder
|
||||||
|
.join("character.html")
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.expect("Failed to write the character HTML file.");
|
||||||
|
}
|
||||||
|
|
75
src/main.rs
75
src/main.rs
|
@ -9,6 +9,7 @@ use std::path::Path;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use touche::server::Service;
|
use touche::server::Service;
|
||||||
use touche::{Body, HttpBody, Request, Response, Server, StatusCode};
|
use touche::{Body, HttpBody, Request, Response, Server, StatusCode};
|
||||||
|
use auracite::archive_character;
|
||||||
|
|
||||||
const LODESTONE_HOST: &str = "https://na.finalfantasyxiv.com";
|
const LODESTONE_HOST: &str = "https://na.finalfantasyxiv.com";
|
||||||
|
|
||||||
|
@ -67,77 +68,5 @@ fn main() {
|
||||||
|
|
||||||
println!("Downloading character data for {}...", args.name);
|
println!("Downloading character data for {}...", args.name);
|
||||||
|
|
||||||
let search_page_path = Path::new("/tmp/search.html");
|
archive_character(&args.name, args.dalamud);
|
||||||
download(
|
|
||||||
&format!("{LODESTONE_HOST}/lodestone/character/?q={}", args.name),
|
|
||||||
search_page_path,
|
|
||||||
)
|
|
||||||
.expect("Failed to download the search page from the Lodestone.");
|
|
||||||
|
|
||||||
let href = parse_search(&String::from_utf8(read(search_page_path).unwrap()).unwrap());
|
|
||||||
if href.is_empty() {
|
|
||||||
println!("Unable to find character!");
|
|
||||||
}
|
|
||||||
|
|
||||||
let char_page_path = Path::new("/tmp/character.html");
|
|
||||||
download(&format!("{LODESTONE_HOST}{}", href), char_page_path)
|
|
||||||
.expect("Failed to download the character page from the Lodestone.");
|
|
||||||
|
|
||||||
let mut char_data = parse_lodestone(&String::from_utf8(read(char_page_path).unwrap()).unwrap());
|
|
||||||
|
|
||||||
let character_folder = Path::new(&args.name);
|
|
||||||
if !character_folder.exists() {
|
|
||||||
std::fs::create_dir(character_folder).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if !char_data.portrait_url.is_empty() {
|
|
||||||
download(
|
|
||||||
&char_data.portrait_url,
|
|
||||||
&character_folder.join("portrait.jpg"),
|
|
||||||
)
|
|
||||||
.expect("Failed to download the character portrait image.");
|
|
||||||
}
|
|
||||||
if !char_data.face_url.is_empty() {
|
|
||||||
download(&char_data.face_url, &character_folder.join("face.jpg"))
|
|
||||||
.expect("Failed to download the character face image.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.dalamud {
|
|
||||||
println!("Now waiting for the Dalamud plugin. Type /auracite begin in chat.");
|
|
||||||
|
|
||||||
let package = Arc::new(Mutex::new(Package::default()));
|
|
||||||
|
|
||||||
Server::bind("0.0.0.0:8000").serve_single_thread(PackageService { wants_stop: Arc::new(Mutex::new(false)), package: &package }).unwrap();
|
|
||||||
|
|
||||||
let package = &*package.lock().unwrap();
|
|
||||||
|
|
||||||
char_data.playtime = package.playtime.parse().unwrap();
|
|
||||||
char_data.appearance.height = package.height;
|
|
||||||
char_data.appearance.bust_size = package.bust_size;
|
|
||||||
char_data.currencies.gil = package.gil; // TODO: also fetch from the lodestone
|
|
||||||
char_data.is_battle_mentor = package.is_battle_mentor;
|
|
||||||
char_data.is_trade_mentor = package.is_trade_mentor;
|
|
||||||
char_data.is_novice = package.is_novice;
|
|
||||||
char_data.is_returner = package.is_returner;
|
|
||||||
char_data.player_commendations = package.player_commendations; // TODO: fetch from the lodestone?
|
|
||||||
}
|
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&char_data).unwrap();
|
|
||||||
write(character_folder.join("character.json"), serialized)
|
|
||||||
.expect("Failed to write the character JSON file.");
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Download complete! The archive is located at: {}",
|
|
||||||
character_folder.file_name().unwrap().to_str().unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
write_html(
|
|
||||||
&char_data,
|
|
||||||
&character_folder
|
|
||||||
.join("character.html")
|
|
||||||
.into_os_string()
|
|
||||||
.into_string()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
.expect("Failed to write the character HTML file.");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue