ptcg-tools/src/malie/client.rs
Felipe Contreras Salinas 7bd717e4db
download index
Signed-off-by: Felipe Contreras Salinas <felipe@bstr.cl>
2025-12-27 01:48:17 -03:00

86 lines
2.7 KiB
Rust

//! Client to download data from malie.io
use anyhow::{Context, Result, anyhow};
use camino::Utf8PathBuf;
use tokio::fs::File;
use tokio_stream::StreamExt;
use tokio_util::io::StreamReader;
use tracing::debug;
use super::models::Index;
use crate::directories::data_cache_directory;
/// Client to download data from mallie.io
pub struct Client {
client: reqwest::Client,
data_cache_directory: Utf8PathBuf,
}
const TCGL_BASE_URL: &str = "https://cdn.malie.io/file/malie-io/tcgl/export";
impl Client {
/// Create a new `Client`
pub async fn new() -> Result<Self> {
Ok(Self {
client: reqwest::Client::new(),
data_cache_directory: data_cache_directory().await?,
})
}
pub async fn download_all_data(&self) -> Result<()> {
self.download_tcgl_index_json().await?;
let index = self.load_tcgl_index().await?;
println!("{index:?}");
Ok(())
}
pub async fn download_tcgl_index_json(&self) -> Result<()> {
let file_path = self.data_cache_directory.join("tcgl_index.json");
let url = format!("{TCGL_BASE_URL}/index.json");
self.download_if_not_exists(file_path, &url).await?;
Ok(())
}
async fn load_tcgl_index(&self) -> Result<Index> {
let file_path = self.data_cache_directory.join("tcgl_index.json");
let index = tokio::fs::read_to_string(&file_path)
.await
.with_context(|| format!("Failed to read {file_path}"))?;
let index: Index =
serde_json::from_str(&index).with_context(|| format!("Couldn't parse {file_path}"))?;
Ok(index)
}
async fn download_if_not_exists(&self, file_path: Utf8PathBuf, url: &str) -> Result<()> {
if let Ok(true) = tokio::fs::try_exists(&file_path).await {
debug!("Found {}, skipping download", &file_path);
return Ok(());
}
let response = self.client.get(url).send().await?;
if !response.status().is_success() {
return Err(anyhow!(
"Error {} when downloading: {}",
response.status(),
url
));
}
let mut file = File::create_new(&file_path)
.await
.with_context(|| format!("Couldn't create file {file_path}"))?;
tokio::io::copy_buf(
&mut StreamReader::new(
response
.bytes_stream()
.map(|result| result.map_err(std::io::Error::other)),
),
&mut file,
)
.await
.with_context(|| format!("While writing to file {file_path}"))?;
file.sync_all().await?;
Ok(())
}
}