mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-11-02 05:52:06 +00:00
fix(fetch): one status table — a persistent 4xx is permanent everywhere
status_error's catch-all called every unlisted status Transient, so a 400/405/418/451 got three retries per link before the same answer (twitter syndication's broken-token 400 being the live example), and download_status_error plus misskey's and bilibili's local fallbacks each carried their own copy of the table — bilibili and misskey classifying a 404 as Transient while the center classified it NotFound. The center now makes any client error except 408/429 a refusal (permanent), the media path delegates to it as status_error("media", ...) and its duplicated fn is deleted, and misskey/bilibili fall through to the center after their own special statuses (misskey's 400 body, bilibili's 412). A table test pins every class.
This commit is contained in:
@@ -105,7 +105,11 @@ fn download_stalled() -> FetchError {
|
||||
}
|
||||
|
||||
/// Sends a media-download request: the response head must arrive within the
|
||||
/// idle window, and a non-2xx status is classified by [`download_status_error`].
|
||||
/// idle window, and a non-2xx status is classified by
|
||||
/// [`super::status_error`] with `"media"` as the name — the same table the
|
||||
/// site adapters use, so a dead URL and a bad moment read the same everywhere.
|
||||
/// A transport error never reaches that table — it fails in `send()` and
|
||||
/// stays [`FetchError::Http`].
|
||||
async fn send_download(request: reqwest::RequestBuilder) -> Result<reqwest::Response, FetchError> {
|
||||
let response = match tokio::time::timeout(DOWNLOAD_IDLE_TIMEOUT, request.send()).await {
|
||||
Ok(Ok(response)) => response,
|
||||
@@ -115,7 +119,7 @@ async fn send_download(request: reqwest::RequestBuilder) -> Result<reqwest::Resp
|
||||
if response.status().is_success() {
|
||||
Ok(response)
|
||||
} else {
|
||||
Err(download_status_error(response.status()))
|
||||
Err(super::status_error("media", response.status()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,19 +225,6 @@ fn apply_media_headers(mut request: reqwest::RequestBuilder, url: &str) -> reqwe
|
||||
request
|
||||
}
|
||||
|
||||
/// Maps a media download's HTTP status onto the same classes the site
|
||||
/// adapters use, so callers can tell "try again" from "this URL is dead":
|
||||
/// 4xx is a property of the media (gone, refused by the host), while 429/5xx
|
||||
/// is a property of the moment. A transport error never reaches this — it
|
||||
/// fails in `send()` and stays [`FetchError::Http`].
|
||||
fn download_status_error(status: reqwest::StatusCode) -> FetchError {
|
||||
match status.as_u16() {
|
||||
401 | 403 => FetchError::Blocked,
|
||||
404 | 410 => FetchError::NotFound,
|
||||
_ => FetchError::Transient(format!("media status {status}")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Downloads a media file with a hard size cap: the body is streamed and the
|
||||
/// download aborts with [`FetchError::TooLarge`] the moment the cap is
|
||||
/// crossed (or when a declared Content-Length already exceeds it). Keeps the
|
||||
|
||||
Reference in New Issue
Block a user