mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-23 23:32:05 +00:00
send: stream media downloads with hard size caps
download_to_temp now uses download_media_limited: non-photos abort the moment the 10 MiB upload cap is crossed mid-stream (no more full-body buffering before the size check), photos cap at the 512 MiB decode budget, and the ugoira frame zip gets a 512 MiB cap. MediaTooLarge routes to the existing smaller-URL fallback.
This commit is contained in:
@@ -222,7 +222,7 @@ impl PixivAPI {
|
|||||||
let Some(zip_url) = zip_url else {
|
let Some(zip_url) = zip_url else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
let zip_bytes = crate::site::download_media(&zip_url)
|
let zip_bytes = crate::site::download_media_limited(&zip_url, 512 * 1024 * 1024)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| match e {
|
.map_err(|e| match e {
|
||||||
FetchError::Http(e) => PixivError::Http(e),
|
FetchError::Http(e) => PixivError::Http(e),
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ pub const PHOTO_TARGET_DIMENSION_SUM: u32 = 9900;
|
|||||||
/// to a smaller media URL instead.
|
/// to a smaller media URL instead.
|
||||||
pub const MAX_UPLOAD_BYTES: u64 = 10 * 1024 * 1024;
|
pub const MAX_UPLOAD_BYTES: u64 = 10 * 1024 * 1024;
|
||||||
/// Decode budget (bytes): a larger intermediate buffer is not worth the peak
|
/// Decode budget (bytes): a larger intermediate buffer is not worth the peak
|
||||||
/// memory; the photo degrades to the smaller URL instead.
|
/// memory; the photo degrades to the smaller URL instead. Also the cap for
|
||||||
const MAX_DECODE_BYTES: u64 = 512 * 1024 * 1024;
|
/// downloading photos in the send fallback (they must be downloaded whole).
|
||||||
|
pub(crate) const MAX_DECODE_BYTES: u64 = 512 * 1024 * 1024;
|
||||||
/// JPEG output quality (1-100).
|
/// JPEG output quality (1-100).
|
||||||
const JPEG_QUALITY: u8 = 90;
|
const JPEG_QUALITY: u8 = 90;
|
||||||
|
|
||||||
|
|||||||
@@ -472,24 +472,30 @@ async fn download_to_temp(item: &MediaItemPayload) -> Result<NamedTempFile, Fall
|
|||||||
| MediaItemPayload::Video { media, .. }
|
| MediaItemPayload::Video { media, .. }
|
||||||
| MediaItemPayload::Animation { media, .. } => media,
|
| MediaItemPayload::Animation { media, .. } => media,
|
||||||
};
|
};
|
||||||
let bytes = match x_media::site::download_media(media_url).await {
|
// Photos are downloaded even over the upload cap so `prepare_photo` can
|
||||||
|
// downscale / transcode them (cap = decode budget); videos/animations
|
||||||
|
// abort as soon as the upload cap is crossed mid-stream.
|
||||||
|
let limit = if matches!(item, MediaItemPayload::Photo { .. }) {
|
||||||
|
photo::MAX_DECODE_BYTES
|
||||||
|
} else {
|
||||||
|
MAX_UPLOAD_BYTES + 1
|
||||||
|
};
|
||||||
|
let bytes = match x_media::site::download_media_limited(media_url, limit).await {
|
||||||
Ok(bytes) => bytes,
|
Ok(bytes) => bytes,
|
||||||
Err(FetchError::Http(_)) => {
|
Err(FetchError::Http(_)) => {
|
||||||
return Err(FallbackError::Retryable {
|
return Err(FallbackError::Retryable {
|
||||||
delay_seconds: retry_delay_seconds(0),
|
delay_seconds: retry_delay_seconds(0),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Err(FetchError::TooLarge) => {
|
||||||
|
return Err(FallbackError::MediaTooLarge);
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(FallbackError::Permanent {
|
return Err(FallbackError::Permanent {
|
||||||
message: format!("download failed: {e}"),
|
message: format!("download failed: {e}"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Photos are downloaded even over the cap so `prepare_photo` can
|
|
||||||
// downscale / transcode them; only videos/animations short-circuit.
|
|
||||||
if !matches!(item, MediaItemPayload::Photo { .. }) && bytes.len() as u64 > MAX_UPLOAD_BYTES {
|
|
||||||
return Err(FallbackError::MediaTooLarge);
|
|
||||||
}
|
|
||||||
let ext = sniff_ext(&bytes);
|
let ext = sniff_ext(&bytes);
|
||||||
let mut file = tempfile::Builder::new()
|
let mut file = tempfile::Builder::new()
|
||||||
.suffix(&format!(".{ext}"))
|
.suffix(&format!(".{ext}"))
|
||||||
|
|||||||
Reference in New Issue
Block a user