144 lines
4.5 KiB
Rust
144 lines
4.5 KiB
Rust
use crate::data::{FetchResult, FetchResultCard, State};
|
|
use crate::download::Downloader;
|
|
use crate::github::{fetch_last_hash, sync_data};
|
|
use crate::{CONFIG, PROVIDE, STATE, STORE, ending_point};
|
|
use anyhow::anyhow;
|
|
use assets_updater::core::export_pipeline::find_files;
|
|
use futures::StreamExt;
|
|
use futures::stream::FuturesUnordered;
|
|
use log::{debug, info};
|
|
use std::fs;
|
|
|
|
pub async fn main() -> anyhow::Result<()> {
|
|
let current_hash = fetch_last_hash().await?;
|
|
ending_point!(ok);
|
|
let old_state = {
|
|
let mut l = STATE.read();
|
|
if l.is_err() {
|
|
STATE.clear_poison();
|
|
drop(l);
|
|
let mut s = STATE.write().map_err(|e| anyhow!("{}", e))?;
|
|
*s = State::new();
|
|
let _ = s.init();
|
|
drop(s);
|
|
l = STATE.read();
|
|
}
|
|
if let Ok(state) = l {
|
|
state.clone()
|
|
} else {
|
|
State::new()
|
|
}
|
|
};
|
|
if let Some(old_hash) = &old_state.git_hash
|
|
&& old_hash == ¤t_hash
|
|
{
|
|
return Ok(());
|
|
}
|
|
// hash updated
|
|
|
|
ending_point!(ok);
|
|
sync_data().await?;
|
|
ending_point!(ok);
|
|
let store = STORE.read().map_err(|e| anyhow!("{}", e))?;
|
|
let event = store.find_last_event();
|
|
if event
|
|
.as_ref()
|
|
.zip(old_state.event_id.as_ref())
|
|
.is_none_or(|(e, id)| &e.event_id == id)
|
|
{
|
|
let mut state = STATE.write().map_err(|e| anyhow!("{}", e))?;
|
|
state.git_hash = Some(current_hash);
|
|
if let Some(event) = event {
|
|
state.event_id = Some(event.event_id);
|
|
}
|
|
state.save();
|
|
return Ok(());
|
|
}
|
|
let event = event.unwrap();
|
|
// event updated
|
|
|
|
info!("Event updated to {}", event.event_id);
|
|
let cards = store.find_cards_by_event(event.event_id);
|
|
drop(store);
|
|
ending_point!(ok);
|
|
let downloader = Downloader::new().await?;
|
|
ending_point!(ok);
|
|
let cache_dir = CONFIG.get().unwrap().cache_dir();
|
|
let mut futures = FuturesUnordered::new();
|
|
for card in &cards {
|
|
futures.push(async {
|
|
ending_point!(ok);
|
|
debug!(
|
|
"Pulling card {} from bundle {}",
|
|
card.id, card.assetbundle_name
|
|
);
|
|
let dir = downloader
|
|
.pull(&format!("character/member/{}", card.assetbundle_name))
|
|
.await?;
|
|
ending_point!(ok_with {
|
|
fs::remove_dir_all(dir.0)?;
|
|
});
|
|
let files = find_files(&dir.0)?;
|
|
let mut local_images = Vec::new();
|
|
for file in files {
|
|
ending_point!(ok_with {
|
|
fs::remove_dir_all(dir.0)?;
|
|
});
|
|
if file.is_file() && file.extension().map(|ext| ext == "png").unwrap_or(false) {
|
|
let new_filename = format!(
|
|
"{}_{}",
|
|
card.assetbundle_name,
|
|
file.file_name().unwrap().to_str().unwrap()
|
|
);
|
|
let new_file = cache_dir.join(new_filename);
|
|
fs::copy(&file, &new_file)?;
|
|
fs::remove_file(&file)?;
|
|
local_images.push(new_file);
|
|
}
|
|
}
|
|
fs::remove_dir_all(dir.0)?;
|
|
Ok::<_, anyhow::Error>((card.clone(), local_images))
|
|
});
|
|
}
|
|
let mut images = Vec::new();
|
|
while let Some(res) = futures.next().await {
|
|
images.push(res?);
|
|
}
|
|
images.sort_by(|a, b| a.0.id.cmp(&b.0.id)); // 小在前
|
|
let images: Vec<_> = images
|
|
.into_iter()
|
|
.map(|(card, path)| FetchResultCard {
|
|
text: format!(
|
|
"#{id} {attr}{rarity} {skill} [{prefix}]{name}",
|
|
id = card.id,
|
|
attr = card.attr_short_text(),
|
|
rarity = card.rarity_short_text(),
|
|
skill = card
|
|
.skill_id_short().map(|s| format!("({})", s))
|
|
.unwrap_or_default(),
|
|
prefix = card.prefix,
|
|
name = card.character_name()
|
|
),
|
|
path,
|
|
})
|
|
.collect();
|
|
|
|
info!(
|
|
"In event {} collected {} cards",
|
|
event.event_id,
|
|
images.len()
|
|
);
|
|
let result = FetchResult {
|
|
event_id: event.event_id,
|
|
cards: images,
|
|
};
|
|
debug!("Providing result: {:?}", result);
|
|
*PROVIDE.write().map_err(|e| anyhow!("{}", e))? = Some(result);
|
|
let mut state = STATE.write().map_err(|e| anyhow!("{}", e))?;
|
|
state.git_hash = Some(current_hash);
|
|
state.event_id = Some(event.event_id);
|
|
state.save();
|
|
|
|
Ok(())
|
|
}
|