mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-07-22 01:15:14 +08:00
fix: harden official resource sync retries
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
//! Official JP download inventory extraction.
|
||||
|
||||
use super::yostar_jp::{verified_official_platforms, PatchPlatform, YostarJpResourceRoot};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet};
|
||||
|
||||
/// Download inventory extracted from the official JP catalog bytes.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -79,7 +79,7 @@ impl YostarJpPlatformDownloadInventory {
|
||||
platform_catalogs: Vec<YostarJpPlatformCatalogInventory>,
|
||||
) -> Self {
|
||||
Self {
|
||||
table_file_names: extract_file_names(table_catalog, &["db", "zip"]),
|
||||
table_file_names: extract_table_file_names(table_catalog),
|
||||
platform_catalogs: merge_platform_catalogs(platform_catalogs),
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ impl YostarJpDownloadInventory {
|
||||
) -> Self {
|
||||
Self {
|
||||
bundle_patch_pack_names: extract_full_patch_pack_names(bundle_packing_info),
|
||||
table_file_names: extract_file_names(table_catalog, &["db", "zip"]),
|
||||
table_file_names: extract_table_file_names(table_catalog),
|
||||
media_file_names: extract_file_names(
|
||||
media_catalog,
|
||||
&["zip", "mp4", "png", "ogg", "wav"],
|
||||
@@ -297,6 +297,24 @@ fn extract_full_patch_pack_names(data: &[u8]) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn extract_table_file_names(data: &[u8]) -> Vec<String> {
|
||||
let mut counts = BTreeMap::<String, usize>::new();
|
||||
|
||||
// Real TableCatalog bytes list top-level downloadable table files twice,
|
||||
// while package-internal stage/resource .zip names normally appear once
|
||||
// next to rawdata paths and are not direct TableBundles URLs.
|
||||
for string in extract_printable_strings(data, 4) {
|
||||
for name in candidate_file_names(&string, &["db", "zip"]) {
|
||||
*counts.entry(name).or_default() += 1;
|
||||
}
|
||||
}
|
||||
|
||||
counts
|
||||
.into_iter()
|
||||
.filter_map(|(name, count)| (count >= 2).then_some(name))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn extract_file_names(data: &[u8], extensions: &[&str]) -> Vec<String> {
|
||||
let mut names = BTreeSet::new();
|
||||
|
||||
@@ -422,7 +440,7 @@ mod tests {
|
||||
fn extracts_download_names_from_synthetic_bytes() {
|
||||
let inventory = YostarJpDownloadInventory::from_catalog_bytes(
|
||||
b"prefix FullPatch_000.zip noise FullPatch_114.zip suffix",
|
||||
b"GameData\\Table\\ExcelDB.db\0rawdata/table/excel/ignored.bytes\0Battle.zip8",
|
||||
b"GameData\\Table\\ExcelDB.db\0ExcelDB.db\0rawdata/table/excel/ignored.bytes\0Battle.zip\0Battle.zip8",
|
||||
b"audio/voc_jp/jp_airi/jp_airi\0GameData\\Audio\\VOC_JP\\JP_Airi.zip8\0JP_Akane.zip",
|
||||
);
|
||||
|
||||
@@ -443,11 +461,27 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extracts_only_top_level_table_files_from_table_catalog() {
|
||||
let inventory = YostarJpPlatformDownloadInventory::from_catalog_bytes(
|
||||
b"ExcelDB.db\0ExcelDB.db\0TablePatchPack_Prologue_GroundStage_1.zip\0TablePatchPack_Prologue_GroundStage_1.zip|1011101_01_s1_01_mainstreet_p01_d.zip\0rawdata/ground/stage/bytes/1011101_01_s1_01_mainstreet_p01_d.bytes",
|
||||
Vec::new(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
inventory.table_file_names,
|
||||
vec![
|
||||
"ExcelDB.db".to_string(),
|
||||
"TablePatchPack_Prologue_GroundStage_1.zip".to_string()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_direct_download_urls() {
|
||||
let inventory = YostarJpDownloadInventory::from_catalog_bytes(
|
||||
b"FullPatch_000.zip FullPatch_001.zip",
|
||||
b"ExcelDB.db Battle.zip",
|
||||
b"ExcelDB.db ExcelDB.db Battle.zip Battle.zip",
|
||||
b"JP_Airi.zip JP_Akane.zip",
|
||||
);
|
||||
let root = YostarJpResourceRoot::from_root_token(ROOT).unwrap();
|
||||
@@ -469,7 +503,7 @@ mod tests {
|
||||
fn builds_direct_download_urls_for_verified_platforms() {
|
||||
let inventory = YostarJpDownloadInventory::from_catalog_bytes(
|
||||
b"FullPatch_000.zip",
|
||||
b"ExcelDB.db",
|
||||
b"ExcelDB.db ExcelDB.db",
|
||||
b"JP_Airi.zip",
|
||||
);
|
||||
let root = YostarJpResourceRoot::from_root_token(ROOT).unwrap();
|
||||
@@ -499,7 +533,7 @@ mod tests {
|
||||
#[test]
|
||||
fn builds_platform_specific_download_urls_without_cross_mixing_catalogs() {
|
||||
let inventory = YostarJpPlatformDownloadInventory::from_catalog_bytes(
|
||||
b"ExcelDB.db",
|
||||
b"ExcelDB.db ExcelDB.db",
|
||||
vec![
|
||||
YostarJpPlatformCatalogInventory::from_catalog_bytes(
|
||||
PatchPlatform::Windows,
|
||||
@@ -556,7 +590,7 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_eq!(inventory.bundle_patch_pack_names.len(), 142);
|
||||
assert_eq!(inventory.table_file_names.len(), 6351);
|
||||
assert!(inventory.table_file_names.len() < 1000);
|
||||
assert_eq!(inventory.media_file_names.len(), 1887);
|
||||
assert!(inventory
|
||||
.bundle_patch_pack_names
|
||||
|
||||
Reference in New Issue
Block a user