mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-23 23:32:05 +00:00
refactor(site): move cache_key/is_retryable/media_headers into site modules
This commit is contained in:
@@ -49,6 +49,26 @@ pub async fn fetch_from_url(url: &str) -> Result<Fetched, FetchError> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cache key for a twitter URL: `"twitter:<id>"`. The prefix is the site id
|
||||
/// used for caption-format lookup and link-cache keys.
|
||||
pub fn cache_key(url: &str) -> Option<String> {
|
||||
PATTERN
|
||||
.captures(url)
|
||||
.map(|caps| format!("twitter:{}", &caps[1]))
|
||||
}
|
||||
|
||||
/// Twitter's fetch-retry policy: transient classes only. Not-found, blocked,
|
||||
/// sensitive (NSFW withholding) and parse failures are permanent — retrying
|
||||
/// them only wastes attempts against the syndication endpoint.
|
||||
pub fn is_retryable(err: &FetchError) -> bool {
|
||||
matches!(err, FetchError::Http(_) | FetchError::Transient(_))
|
||||
}
|
||||
|
||||
/// twimg URLs need no extra headers (no hotlink protection).
|
||||
pub fn media_headers(_url: &str) -> Option<Vec<(&'static str, String)>> {
|
||||
None
|
||||
}
|
||||
|
||||
/// A Fetched with no media for withheld tweets: the bot replies
|
||||
/// "No media found" and moves on instead of erroring.
|
||||
fn empty_fetched(url: &str) -> Fetched {
|
||||
@@ -354,6 +374,29 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cache_key_prefixes_tweet_id() {
|
||||
assert_eq!(
|
||||
cache_key("https://x.com/user/status/1234567890"),
|
||||
Some("twitter:1234567890".into())
|
||||
);
|
||||
assert_eq!(cache_key("https://example.com/1"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_retryable_classifies_transient_and_permanent() {
|
||||
// Transient: network errors and explicit transient statuses (the
|
||||
// `Http` arm shares this match arm with `Transient`).
|
||||
assert!(is_retryable(&FetchError::Transient("429".into())));
|
||||
// Permanent: gone, blocked, withheld, oversized, unparseable.
|
||||
assert!(!is_retryable(&FetchError::NotFound));
|
||||
assert!(!is_retryable(&FetchError::Blocked));
|
||||
assert!(!is_retryable(&FetchError::Sensitive));
|
||||
assert!(!is_retryable(&FetchError::TooLarge));
|
||||
let json_err = serde_json::from_str::<serde_json::Value>("x").unwrap_err();
|
||||
assert!(!is_retryable(&FetchError::Json(json_err)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syndication_json_converts_to_fetched() {
|
||||
let raw = fixture(serde_json::json!([
|
||||
|
||||
@@ -2,4 +2,6 @@ mod auth;
|
||||
mod interface;
|
||||
mod model;
|
||||
|
||||
pub use interface::{PATTERN, Tweet, enabled, fetch_from_url};
|
||||
pub use interface::{
|
||||
PATTERN, Tweet, cache_key, enabled, fetch_from_url, is_retryable, media_headers,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user