mirror of
https://github.com/redstrate/Auracite.git
synced 2025-05-01 16:37:45 +00:00
Improve the error handling from character_archive
This commit is contained in:
parent
eb14e13311
commit
489084cb51
2 changed files with 49 additions and 22 deletions
|
@ -14,7 +14,7 @@ fn archive_character_blocking(character_name: &String, use_dalamud: bool) {
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let inner = rt.block_on(archive_character(&character_name.to_string(), use_dalamud));
|
let inner = rt.block_on(archive_character(&character_name.to_string(), use_dalamud)).unwrap();
|
||||||
write("/home/josh/test.zip", inner);
|
write("/home/josh/test.zip", inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
src/lib.rs
75
src/lib.rs
|
@ -10,6 +10,7 @@ use std::sync::{Arc, Mutex};
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
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 zip::result::ZipError;
|
||||||
use zip::write::SimpleFileOptions;
|
use zip::write::SimpleFileOptions;
|
||||||
use zip::ZipWriter;
|
use zip::ZipWriter;
|
||||||
use crate::downloader::download;
|
use crate::downloader::download;
|
||||||
|
@ -62,50 +63,76 @@ impl Service for PackageService<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Archives the character named `character_name` and gives a ZIP file as bytes that can be written to disk.
|
#[derive(Debug)]
|
||||||
pub async fn archive_character(character_name: &str, use_dalamud: bool) -> Vec<u8> {
|
pub enum ArchiveError {
|
||||||
let search_page = download(&Url::parse_with_params(&format!("{LODESTONE_HOST}/lodestone/character?"), &[("q", character_name)]).unwrap())
|
DownloadFailed(String),
|
||||||
.await
|
CharacterNotFound,
|
||||||
.expect("Failed to download the search page from the Lodestone.");
|
ParsingError,
|
||||||
|
UnknownError
|
||||||
let href = parse_search(&String::from_utf8(search_page).unwrap());
|
|
||||||
if href.is_empty() {
|
|
||||||
println!("Unable to find character!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let char_page = download(&Url::parse(&format!("{LODESTONE_HOST}{}", href)).unwrap())
|
impl From<ZipError> for ArchiveError {
|
||||||
.await
|
fn from(_: ZipError) -> Self {
|
||||||
.expect("Failed to download the character page from the Lodestone.");
|
ArchiveError::UnknownError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut char_data = crate::parser::parse_lodestone(&String::from_utf8(char_page).unwrap());
|
impl From<std::io::Error> for ArchiveError {
|
||||||
|
fn from(_: std::io::Error) -> Self {
|
||||||
|
ArchiveError::UnknownError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Archives the character named `character_name` and gives a ZIP file as bytes that can be written to disk.
|
||||||
|
pub async fn archive_character(character_name: &str, use_dalamud: bool) -> Result<Vec<u8>, ArchiveError> {
|
||||||
|
let search_url = Url::parse_with_params(&format!("{LODESTONE_HOST}/lodestone/character?"), &[("q", character_name)]).map_err(|_| ArchiveError::UnknownError)?;
|
||||||
|
let search_page = download(&search_url)
|
||||||
|
.await
|
||||||
|
.map_err(|_| ArchiveError::DownloadFailed(search_url.to_string()))?;
|
||||||
|
let search_page = String::from_utf8(search_page).map_err(|_| ArchiveError::ParsingError)?;
|
||||||
|
|
||||||
|
let href = parse_search(&search_page);
|
||||||
|
if href.is_empty() {
|
||||||
|
return Err(ArchiveError::CharacterNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
let char_page_url = Url::parse(&format!("{LODESTONE_HOST}{}", href)).map_err(|_| ArchiveError::UnknownError)?;
|
||||||
|
let char_page = download(&char_page_url)
|
||||||
|
.await
|
||||||
|
.map_err(|_| ArchiveError::DownloadFailed(char_page_url.to_string()))?;
|
||||||
|
let char_page = String::from_utf8(char_page).map_err(|_| ArchiveError::ParsingError)?;
|
||||||
|
|
||||||
|
let mut char_data = parser::parse_lodestone(&char_page);
|
||||||
|
|
||||||
// 2 MiB, for one JSON and two images
|
// 2 MiB, for one JSON and two images
|
||||||
let mut buf = vec![0; 2097152];
|
let mut buf = vec![0; 2097152];
|
||||||
let mut zip = ZipWriter::new(std::io::Cursor::new(&mut buf[..]));
|
let mut zip = ZipWriter::new(std::io::Cursor::new(&mut buf[..]));
|
||||||
|
|
||||||
let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
|
||||||
zip.start_file("character.json", options);
|
zip.start_file("character.json", options)?;
|
||||||
zip.write_all(serde_json::to_string(&char_data).unwrap().as_ref());
|
zip.write_all(serde_json::to_string(&char_data).unwrap().as_ref())?;
|
||||||
|
|
||||||
if !char_data.portrait_url.is_empty() {
|
if !char_data.portrait_url.is_empty() {
|
||||||
let portrait_url = char_data.portrait_url.replace("img2.finalfantasyxiv.com", "img-tunnel.ryne.moe");
|
let portrait_url = char_data.portrait_url.replace("img2.finalfantasyxiv.com", "img-tunnel.ryne.moe");
|
||||||
|
let portrait_url = Url::parse(&portrait_url).map_err(|_| ArchiveError::UnknownError)?;
|
||||||
|
|
||||||
let portrait = download(&Url::parse(&portrait_url).unwrap())
|
let portrait = download(&portrait_url)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to download the character portrait image.");
|
.map_err(|_| ArchiveError::DownloadFailed(portrait_url.to_string()))?;
|
||||||
|
|
||||||
zip.start_file("portrait.jpg", options);
|
zip.start_file("portrait.jpg", options)?;
|
||||||
zip.write_all(&*portrait);
|
zip.write_all(&*portrait)?;
|
||||||
}
|
}
|
||||||
if !char_data.face_url.is_empty() {
|
if !char_data.face_url.is_empty() {
|
||||||
let face_url = char_data.face_url.replace("img2.finalfantasyxiv.com", "img-tunnel.ryne.moe");
|
let face_url = char_data.face_url.replace("img2.finalfantasyxiv.com", "img-tunnel.ryne.moe");
|
||||||
|
let face_url = Url::parse(&face_url).map_err(|_| ArchiveError::UnknownError)?;
|
||||||
|
|
||||||
let face = download(&Url::parse(&face_url).unwrap())
|
let face = download(&face_url)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to download the character face image.");
|
.map_err(|_| ArchiveError::DownloadFailed(face_url.to_string()))?;
|
||||||
|
|
||||||
zip.start_file("face.jpg", options);
|
zip.start_file("face.jpg", options)?;
|
||||||
zip.write_all(&*face);
|
zip.write_all(&*face)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if use_dalamud {
|
if use_dalamud {
|
||||||
|
@ -137,7 +164,7 @@ pub async fn archive_character(character_name: &str, use_dalamud: bool) -> Vec<u
|
||||||
|
|
||||||
zip.finish();
|
zip.finish();
|
||||||
|
|
||||||
return buf;
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Archives the character named `character_name` and converts the ZIP file to Base64. Useful for downloading via data URIs.
|
/// Archives the character named `character_name` and converts the ZIP file to Base64. Useful for downloading via data URIs.
|
||||||
|
|
Loading…
Add table
Reference in a new issue