diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index ee02b6c..1fd318f 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -17,6 +17,7 @@ - dtmm: reset dtkit-patch installations - sdk: implement decompiling Lua files - dtmm: fetch cover image for Nexus mods +- dtmm: fetch file version for Nexus mods === Fixed diff --git a/crates/dtmm/src/controller/import.rs b/crates/dtmm/src/controller/import.rs index 5ca4068..cef7ee4 100644 --- a/crates/dtmm/src/controller/import.rs +++ b/crates/dtmm/src/controller/import.rs @@ -411,7 +411,7 @@ pub(crate) async fn import_mod(state: ActionState, info: FileInfo) -> Result Result version, + Err(err) => { + let err = Report::new(err); + tracing::warn!( + "Failed to fetch version for Nexus download. \ + Falling back to file name:\n{:?}", + err + ); + version + } + }; + + let info = NexusInfo::from(mod_info); + tracing::debug!(version, ?info); + Some((info, version)) } else { None diff --git a/lib/nexusmods/src/lib.rs b/lib/nexusmods/src/lib.rs index 1407fca..5fb08e2 100644 --- a/lib/nexusmods/src/lib.rs +++ b/lib/nexusmods/src/lib.rs @@ -39,6 +39,8 @@ pub enum Error { Infallible(#[from] Infallible), #[error("invalid NXM URL '{}': {0}", .1.as_str())] InvalidNXM(&'static str, Url), + #[error("{0}")] + Custom(String), } pub type Result = std::result::Result; @@ -102,6 +104,28 @@ impl Api { self.send(req).await } + #[tracing::instrument(skip(self))] + pub async fn file_version(&self, id: u64, timestamp: T) -> Result + where + T: std::fmt::Debug, + OffsetDateTime: PartialEq, + { + let url = BASE_URL_GAME.join(&format!("mods/{id}/files.json"))?; + let req = self.client.get(url); + let files: FileList = self.send(req).await?; + + let Some(file) = files + .files + .into_iter() + .find(|file| file.uploaded_timestamp == timestamp) + else { + let err = Error::Custom("Timestamp does not match any file".into()); + return Err(err); + }; + + Ok(file.version) + } + #[tracing::instrument(skip(self))] pub async fn picture(&self, url: impl IntoUrl + std::fmt::Debug) -> Result> { let res = self.client.get(url).send().await?.error_for_status()?; diff --git a/lib/nexusmods/src/types.rs b/lib/nexusmods/src/types.rs index b0dffd5..db0f624 100644 --- a/lib/nexusmods/src/types.rs +++ b/lib/nexusmods/src/types.rs @@ -64,6 +64,35 @@ pub struct Mod { // pub contains_adult_content: bool, } +#[derive(Debug, Deserialize)] +pub struct File { + pub id: Vec, + pub uid: u64, + pub file_id: u64, + pub name: String, + pub version: String, + pub category_id: u64, + pub category_name: String, + pub is_primary: bool, + pub size: u64, + pub file_name: String, + #[serde(with = "time::serde::timestamp")] + pub uploaded_timestamp: OffsetDateTime, + pub mod_version: String, + pub external_virus_scan_url: String, + pub description: String, + pub size_kb: u64, + pub size_in_bytes: u64, + pub changelog_html: Option, + pub content_preview_link: String, +} + +#[derive(Debug, Deserialize)] +pub struct FileList { + pub files: Vec, + // pub file_updates: Vec, +} + #[derive(Debug, Deserialize)] pub struct DownloadLink { pub name: String,