Files
Modrinth-plus/theseus/src/data/meta.rs

108 lines
3.1 KiB
Rust
Raw Normal View History

2022-02-20 22:47:44 +08:00
use crate::{data::DataError, LAUNCHER_WORK_DIR};
use once_cell::sync;
2021-12-15 22:24:08 -07:00
use serde::{Deserialize, Serialize};
use tokio::sync::{RwLock, RwLockReadGuard};
2021-12-15 22:24:08 -07:00
const META_FILE: &str = "meta.json";
const META_URL: &str = "https://meta.modrinth.com/gamedata";
2021-12-15 22:24:08 -07:00
static METADATA: sync::OnceCell<RwLock<Metadata>> = sync::OnceCell::new();
2021-12-15 22:24:08 -07:00
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Metadata {
pub minecraft: daedalus::minecraft::VersionManifest,
pub forge: daedalus::modded::Manifest,
pub fabric: daedalus::modded::Manifest,
}
impl Metadata {
pub async fn init() -> Result<(), DataError> {
let meta_path = LAUNCHER_WORK_DIR.join(META_FILE);
2021-12-15 22:24:08 -07:00
if meta_path.exists() {
let meta_data = tokio::fs::read_to_string(meta_path)
.await
.ok()
.and_then(|it| serde_json::from_str::<Metadata>(&it).ok());
2021-12-15 22:24:08 -07:00
if let Some(metadata) = meta_data {
METADATA.get_or_init(|| RwLock::new(metadata));
}
}
let future = async {
for attempt in 0..=3 {
let res = async {
let new = Self::fetch().await?;
std::fs::write(
LAUNCHER_WORK_DIR.join(META_FILE),
2022-02-20 22:47:44 +08:00
&serde_json::to_string(&new)?,
2021-12-15 22:24:08 -07:00
)?;
if let Some(metadata) = METADATA.get() {
*metadata.write().await = new;
} else {
METADATA.get_or_init(|| RwLock::new(new));
}
Ok::<(), DataError>(())
2021-12-15 22:24:08 -07:00
}
.await;
match res {
Ok(_) => {
break;
}
Err(_) if attempt <= 3 => continue,
Err(err) => {
log::warn!("Unable to fetch launcher metadata: {}", err)
}
};
2021-12-15 22:24:08 -07:00
}
};
if METADATA.get().is_some() {
tokio::task::spawn(future);
} else {
future.await;
}
Ok(())
}
pub async fn fetch() -> Result<Self, DataError> {
2021-12-15 22:24:08 -07:00
let (game, forge, fabric) = futures::future::join3(
daedalus::minecraft::fetch_version_manifest(Some(&format!(
2021-12-15 22:24:08 -07:00
"{}/minecraft/v0/manifest.json",
META_URL
))),
daedalus::modded::fetch_manifest(&format!(
"{}/forge/v0/manifest.json",
META_URL
)),
daedalus::modded::fetch_manifest(&format!(
"{}/fabric/v0/manifest.json",
META_URL
)),
2021-12-15 22:24:08 -07:00
)
.await;
Ok(Self {
minecraft: game?,
forge: forge?,
fabric: fabric?,
})
}
pub async fn get<'a>() -> Result<RwLockReadGuard<'a, Self>, DataError> {
let res = METADATA
2021-12-15 22:24:08 -07:00
.get()
.ok_or_else(|| DataError::InitializedError("metadata".to_string()))?
2021-12-15 22:24:08 -07:00
.read()
.await;
Ok(res)
2021-12-15 22:24:08 -07:00
}
}