use crate::cdn::aes_ecb;
use crate::cdn::cdn_upload::build_cdn_download_url;
use crate::error::{Error, Result};
use crate::types::CdnMedia;
pub fn resolve_cdn_download_url(cdn_base_url: &str, media: &CdnMedia) -> Option<String> {
if let Some(full) = &media.full_url {
let trimmed = full.trim();
if !trimmed.is_empty() {
return Some(trimmed.to_owned());
}
}
media
.encrypt_query_param
.as_deref()
.filter(|p| !p.is_empty())
.map(|p| build_cdn_download_url(cdn_base_url, p))
}
async fn fetch_bytes(url: &str) -> Result<Vec<u8>> {
let res = reqwest::get(url).await?;
if !res.status().is_success() {
let status = res.status();
let body = res.text().await.unwrap_or_default();
return Err(Error::CdnUpload(format!("CDN download {status}: {body}")));
}
Ok(res.bytes().await?.to_vec())
}
pub async fn download_and_decrypt(
cdn_base_url: &str,
media: &CdnMedia,
aes_key_base64: &str,
) -> Result<Vec<u8>> {
let key = aes_ecb::parse_aes_key(aes_key_base64)?;
let url = resolve_cdn_download_url(cdn_base_url, media)
.ok_or_else(|| Error::CdnUpload("no download URL available".into()))?;
tracing::debug!(url = %crate::util::redact::redact_url(&url), "CDN download+decrypt");
let encrypted = fetch_bytes(&url).await?;
aes_ecb::decrypt(&encrypted, &key)
}
pub async fn download_plain(cdn_base_url: &str, media: &CdnMedia) -> Result<Vec<u8>> {
let url = resolve_cdn_download_url(cdn_base_url, media)
.ok_or_else(|| Error::CdnUpload("no download URL available".into()))?;
tracing::debug!(url = %crate::util::redact::redact_url(&url), "CDN download plain");
fetch_bytes(&url).await
}