modde_sources/nexus/
mod.rs1pub mod api;
2pub mod auth;
3pub mod cdn;
4pub mod graphql;
5pub mod install;
6pub mod oauth;
7pub mod updates;
8
9pub use api::NexusApi;
10
11use std::collections::HashMap;
12use std::path::Path;
13
14use anyhow::Result;
15use reqwest::Client;
16use tracing::debug;
17
18use modde_core::manifest::wabbajack::DownloadDirective;
19
20use crate::common::simple_download;
21use crate::traits::{DownloadHandle, DownloadSource, ProgressCallback, VerifiedFile};
22
23pub struct NexusSource {
27 client: Client,
28 api_key: String,
29}
30
31impl NexusSource {
32 pub fn new(client: Client) -> Result<Self> {
34 let api_key = auth::load_api_key()?;
35 Ok(Self { client, api_key })
36 }
37
38 pub fn with_api_key(client: Client, api_key: String) -> Self {
40 Self { client, api_key }
41 }
42}
43
44impl DownloadSource for NexusSource {
45 fn can_handle(&self, directive: &DownloadDirective) -> bool {
46 matches!(directive, DownloadDirective::Nexus { .. })
47 }
48
49 async fn resolve(&self, directive: &DownloadDirective) -> Result<DownloadHandle> {
50 let DownloadDirective::Nexus {
51 game_id,
52 mod_id,
53 file_id,
54 hash,
55 } = directive
56 else {
57 anyhow::bail!("not a Nexus directive");
58 };
59
60 let download_url = cdn::generate_download_link(
61 &self.client,
62 &self.api_key,
63 game_id.as_str(),
64 *mod_id,
65 *file_id,
66 )
67 .await?;
68
69 debug!(url = %download_url, "resolved Nexus CDN download URL");
70
71 Ok(DownloadHandle {
72 url: download_url,
73 headers: HashMap::new(),
74 expected_hash: *hash,
75 size_hint: None,
76 })
77 }
78
79 async fn download_with_progress(
80 &self,
81 handle: DownloadHandle,
82 dest: &Path,
83 progress: ProgressCallback,
84 ) -> Result<VerifiedFile> {
85 simple_download(&self.client, &handle, dest, &progress).await
86 }
87}