mirror of
https://github.com/Bluemangoo/sekai-unpacker.git
synced 2026-05-06 20:44:47 +08:00
exact single file bundle
This commit is contained in:
parent
83279e0253
commit
c015383f1d
@ -157,7 +157,7 @@ impl AssetExecutionContext {
|
|||||||
&self,
|
&self,
|
||||||
task: &DownloadTask,
|
task: &DownloadTask,
|
||||||
app_config: &AppConfig,
|
app_config: &AppConfig,
|
||||||
) -> Result<PathBuf, AssetExecutionError> {
|
) -> Result<(PathBuf, /*single file*/ bool), AssetExecutionError> {
|
||||||
let ctx = self.clone();
|
let ctx = self.clone();
|
||||||
ctx.download_and_export_bundle(app_config, task).await
|
ctx.download_and_export_bundle(app_config, task).await
|
||||||
}
|
}
|
||||||
@ -400,7 +400,7 @@ impl AssetExecutionContext {
|
|||||||
&self,
|
&self,
|
||||||
app_config: &AppConfig,
|
app_config: &AppConfig,
|
||||||
task: &DownloadTask,
|
task: &DownloadTask,
|
||||||
) -> Result<PathBuf, AssetExecutionError> {
|
) -> Result<(PathBuf, bool), AssetExecutionError> {
|
||||||
let bundle_url = self.render_bundle_url(task)?;
|
let bundle_url = self.render_bundle_url(task)?;
|
||||||
let body = self.get_with_retry(&bundle_url).await?;
|
let body = self.get_with_retry(&bundle_url).await?;
|
||||||
let deobfuscated = deobfuscate(&body);
|
let deobfuscated = deobfuscate(&body);
|
||||||
|
|||||||
@ -61,13 +61,13 @@ pub async fn extract_unity_asset_bundle(
|
|||||||
asset_bundle_file: &Path,
|
asset_bundle_file: &Path,
|
||||||
export_path: &str,
|
export_path: &str,
|
||||||
category: &str,
|
category: &str,
|
||||||
) -> Result<PathBuf, ExportPipelineError> {
|
) -> Result<(PathBuf, bool), ExportPipelineError> {
|
||||||
let output_dir = std::env::temp_dir()
|
let output_dir = std::env::temp_dir()
|
||||||
.join("sekai-updater")
|
.join("sekai-updater")
|
||||||
.join("extract")
|
.join("extract")
|
||||||
.join(&sync_context.region);
|
.join(&sync_context.region);
|
||||||
let Some(asset_studio_cli_path) = app_config.tools.asset_studio_cli_path.as_deref() else {
|
let Some(asset_studio_cli_path) = app_config.tools.asset_studio_cli_path.as_deref() else {
|
||||||
return Ok(asset_bundle_file.parent().unwrap().to_path_buf());
|
return Ok((asset_bundle_file.parent().unwrap().to_path_buf(), true));
|
||||||
};
|
};
|
||||||
|
|
||||||
let exclude_path_prefix = if sync_context.export.by_category {
|
let exclude_path_prefix = if sync_context.export.by_category {
|
||||||
@ -125,8 +125,11 @@ pub async fn extract_unity_asset_bundle(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let mut count = 0;
|
||||||
|
walk(&actual_export_path, &mut |_| count += 1)?;
|
||||||
|
|
||||||
post_process_exported_files(app_config, sync_context, region, &actual_export_path).await?;
|
post_process_exported_files(app_config, sync_context, region, &actual_export_path).await?;
|
||||||
Ok(actual_export_path)
|
Ok((actual_export_path, count <= 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn post_process_exported_files(
|
pub async fn post_process_exported_files(
|
||||||
|
|||||||
@ -4,24 +4,21 @@ use std::path::Path;
|
|||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt};
|
use tokio::io::{AsyncRead, AsyncReadExt};
|
||||||
|
|
||||||
pub async fn server_send_files<P: AsRef<Path>>(
|
pub async fn server_send_files<P: AsRef<Path>, S: AsRef<str>>(
|
||||||
mut send_stream: SendStream<Bytes>,
|
mut send_stream: SendStream<Bytes>,
|
||||||
base: P,
|
files: &[(P, S)],
|
||||||
files: &[P],
|
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut header = BytesMut::with_capacity(4);
|
let mut header = BytesMut::with_capacity(4);
|
||||||
header.put_u32(files.len() as u32);
|
header.put_u32(files.len() as u32);
|
||||||
send_stream.send_data(header.freeze(), false)?;
|
send_stream.send_data(header.freeze(), false)?;
|
||||||
|
|
||||||
for (i, path_ref) in files.iter().enumerate() {
|
for (i, path_ref) in files.iter().enumerate() {
|
||||||
let path = path_ref.as_ref();
|
let path = path_ref.0.as_ref();
|
||||||
let mut file = File::open(path).await?;
|
let mut file = File::open(path).await?;
|
||||||
let metadata = file.metadata().await?;
|
let metadata = file.metadata().await?;
|
||||||
|
|
||||||
let file_name = path
|
let file_name = &path_ref.1;
|
||||||
.strip_prefix(base.as_ref())
|
let name_bytes = file_name.as_ref().as_bytes();
|
||||||
.map(|n| n.to_string_lossy().to_string())?;
|
|
||||||
let name_bytes = file_name.as_bytes();
|
|
||||||
let file_size = metadata.len();
|
let file_size = metadata.len();
|
||||||
|
|
||||||
let mut meta_buf = BytesMut::with_capacity(2 + name_bytes.len() + 8);
|
let mut meta_buf = BytesMut::with_capacity(2 + name_bytes.len() + 8);
|
||||||
|
|||||||
@ -11,10 +11,10 @@ pub struct SyncContext {
|
|||||||
pub asset_version: Option<String>,
|
pub asset_version: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub asset_hash: Option<String>,
|
pub asset_hash: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub exact_single_file_bundle: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct RegionFiltersConfig {
|
pub struct RegionFiltersConfig {
|
||||||
|
|||||||
@ -13,11 +13,14 @@ profiles:
|
|||||||
cn:
|
cn:
|
||||||
region: cn
|
region: cn
|
||||||
# interval: 3 # seconds
|
# interval: 3 # seconds
|
||||||
|
concurrent: 50
|
||||||
filters:
|
filters:
|
||||||
start_app:
|
start_app:
|
||||||
- "thumbnail"
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
on_demand:
|
on_demand:
|
||||||
- "thumbnail"
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
skip: [ ]
|
skip: [ ]
|
||||||
file_ext: [ ]
|
file_ext: [ ]
|
||||||
export:
|
export:
|
||||||
@ -41,6 +44,7 @@ profiles:
|
|||||||
convert_to_mp3: false
|
convert_to_mp3: false
|
||||||
convert_to_flac: false
|
convert_to_flac: false
|
||||||
remove_wav: false
|
remove_wav: false
|
||||||
|
# exact_single_file_bundle: true
|
||||||
path: "./data/cn"
|
path: "./data/cn"
|
||||||
jp:
|
jp:
|
||||||
region: jp
|
region: jp
|
||||||
@ -48,8 +52,10 @@ profiles:
|
|||||||
filters:
|
filters:
|
||||||
start_app:
|
start_app:
|
||||||
- "thumbnail"
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
on_demand:
|
on_demand:
|
||||||
- "thumbnail"
|
- "thumbnail"
|
||||||
|
- "stamp"
|
||||||
skip: [ ]
|
skip: [ ]
|
||||||
file_ext: [ ]
|
file_ext: [ ]
|
||||||
asset_version: 6.4.0.30
|
asset_version: 6.4.0.30
|
||||||
@ -75,4 +81,5 @@ profiles:
|
|||||||
convert_to_mp3: false
|
convert_to_mp3: false
|
||||||
convert_to_flac: false
|
convert_to_flac: false
|
||||||
remove_wav: false
|
remove_wav: false
|
||||||
|
# exact_single_file_bundle: true
|
||||||
path: "./data/jp"
|
path: "./data/jp"
|
||||||
@ -41,7 +41,12 @@ pub async fn download(
|
|||||||
send_error(send_response, error.into());
|
send_error(send_response, error.into());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let dir = dir.unwrap();
|
let (dir, single_file) = dir.unwrap();
|
||||||
|
|
||||||
|
let dir_base = std::env::temp_dir()
|
||||||
|
.join("sekai-updater")
|
||||||
|
.join("extract")
|
||||||
|
.join(&context.sync_context.region);
|
||||||
|
|
||||||
let files = if !dir.is_dir() {
|
let files = if !dir.is_dir() {
|
||||||
if context.sync_context.filters.file_ext.is_empty()
|
if context.sync_context.filters.file_ext.is_empty()
|
||||||
@ -53,7 +58,13 @@ pub async fn download(
|
|||||||
.contains(&t.to_str().unwrap().to_lowercase())
|
.contains(&t.to_str().unwrap().to_lowercase())
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
vec![dir.clone()]
|
vec![(
|
||||||
|
dir.clone(),
|
||||||
|
dir.strip_prefix(&dir_base)
|
||||||
|
.unwrap()
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string(),
|
||||||
|
)]
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
@ -67,7 +78,22 @@ pub async fn download(
|
|||||||
send_error(send_response, error.into());
|
send_error(send_response, error.into());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
files.unwrap()
|
let base = dir.strip_prefix(&dir_base).unwrap();
|
||||||
|
let base_str = if single_file {
|
||||||
|
base.parent().unwrap().to_str().unwrap()
|
||||||
|
} else {
|
||||||
|
base.to_str().unwrap()
|
||||||
|
};
|
||||||
|
files
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|p| {
|
||||||
|
let raw = p.clone();
|
||||||
|
let name = p.strip_prefix(&dir).unwrap();
|
||||||
|
let path = format!("{}/{}", base_str, name.to_string_lossy());
|
||||||
|
(raw, path)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = Response::builder()
|
let response = Response::builder()
|
||||||
@ -76,13 +102,8 @@ pub async fn download(
|
|||||||
.body(())
|
.body(())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let dir_base = std::env::temp_dir()
|
|
||||||
.join("sekai-updater")
|
|
||||||
.join("extract")
|
|
||||||
.join(&context.sync_context.region);
|
|
||||||
|
|
||||||
if let Ok(send_stream) = send_response.send_response(response, false) {
|
if let Ok(send_stream) = send_response.send_response(response, false) {
|
||||||
let _ = server_send_files(send_stream, dir_base, &files).await;
|
let _ = server_send_files(send_stream, &files).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = std::fs::remove_file(dir);
|
let _ = std::fs::remove_file(dir);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user