mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-23 23:32:05 +00:00
refactor(site): carry site_id on Fetched; unify cache-key site lookup
This commit is contained in:
@@ -299,6 +299,7 @@ impl From<Post> for Fetched {
|
||||
title: post.text.clone(),
|
||||
media: post.media,
|
||||
sensitive: post.sensitive,
|
||||
site_id: "bsky",
|
||||
render_data,
|
||||
_keep_alive: None,
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ pub struct Fetched {
|
||||
pub media: Vec<crate::media::Media>,
|
||||
/// Spoiler flag for all media of this post.
|
||||
pub sensitive: bool,
|
||||
/// Site id (`"twitter"` / `"bsky"` / `"pixiv"`): the single source of
|
||||
/// truth for site identity — caption-format lookup, cache-key prefix and
|
||||
/// the SetFormat whitelist all derive from it. Set by the producing site.
|
||||
pub site_id: &'static str,
|
||||
/// Raw values (pre-escaped) for user-customizable caption formats.
|
||||
pub(crate) render_data: Option<RenderData>,
|
||||
/// Keeps temp files (e.g. an encoded ugoira MP4) alive until the caller
|
||||
@@ -50,16 +54,10 @@ pub(crate) struct RenderData {
|
||||
|
||||
impl Fetched {
|
||||
/// The site this post came from (used for per-site format overrides).
|
||||
/// A thin alias over [`Fetched::site_id`] kept for callers that read the
|
||||
/// site off a fetched post.
|
||||
pub fn site_name(&self) -> &'static str {
|
||||
if self.source_url.contains("x.com") || self.source_url.contains("twitter.com") {
|
||||
"twitter"
|
||||
} else if self.source_url.contains("bsky.app") {
|
||||
"bsky"
|
||||
} else if self.source_url.contains("pixiv.net") {
|
||||
"pixiv"
|
||||
} else {
|
||||
"unknown"
|
||||
}
|
||||
self.site_id
|
||||
}
|
||||
|
||||
/// Renders a user-supplied caption format. The format string is
|
||||
@@ -177,6 +175,25 @@ pub fn cache_key(url: &str) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
/// The site id carried by a cache key (`"twitter:123"` → `"twitter"`).
|
||||
/// Unknown prefixes fall back to `"unknown"`. The bot uses this on the
|
||||
/// link-cache hit path, where no [`Fetched`] is available — the same value
|
||||
/// a fresh fetch would read from [`Fetched::site_id`].
|
||||
pub fn site_id_from_key(key: &str) -> &'static str {
|
||||
match key.split(':').next() {
|
||||
Some("twitter") => "twitter",
|
||||
Some("pixiv") => "pixiv",
|
||||
Some("bsky") => "bsky",
|
||||
_ => "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
/// Every supported site id, in dispatch order. The bot's SetFormat whitelist
|
||||
/// and per-site caption-format lookup derive from this list.
|
||||
pub fn site_ids() -> Vec<&'static str> {
|
||||
vec!["twitter", "bsky", "pixiv"]
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FetchError {
|
||||
Http(reqwest::Error),
|
||||
@@ -476,6 +493,15 @@ mod tests {
|
||||
assert_eq!(cache_key("https://example.com/not-a-post"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn site_id_from_key_parses_prefix() {
|
||||
assert_eq!(site_id_from_key("twitter:123"), "twitter");
|
||||
assert_eq!(site_id_from_key("pixiv:123"), "pixiv");
|
||||
assert_eq!(site_id_from_key("bsky:handle.example/3lorem"), "bsky");
|
||||
assert_eq!(site_id_from_key("unknown:1"), "unknown");
|
||||
assert_eq!(site_id_from_key("no-colon"), "unknown");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fetch_error_retryability_classification() {
|
||||
// Transient: network errors, explicit transient, pixiv 429/5xx.
|
||||
|
||||
@@ -142,6 +142,7 @@ impl From<Illustration> for Fetched {
|
||||
title: illustration.title.clone(),
|
||||
media: illustration.media,
|
||||
sensitive: illustration.nsfw,
|
||||
site_id: "pixiv",
|
||||
render_data,
|
||||
_keep_alive: illustration._keep_alive,
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ fn empty_fetched(url: &str) -> Fetched {
|
||||
title: String::new(),
|
||||
media: vec![],
|
||||
sensitive: true,
|
||||
site_id: "twitter",
|
||||
render_data: None,
|
||||
_keep_alive: None,
|
||||
}
|
||||
@@ -301,6 +302,7 @@ impl From<Tweet> for Fetched {
|
||||
title: tweet.text.clone(),
|
||||
media: tweet.media,
|
||||
sensitive: tweet.sensitive,
|
||||
site_id: "twitter",
|
||||
render_data,
|
||||
_keep_alive: None,
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ async fn execute_command(
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
if !["twitter", "bsky", "pixiv"].contains(&site) {
|
||||
if !x_media::site::site_ids().contains(&site) {
|
||||
reply(
|
||||
bot.clone(),
|
||||
message.clone(),
|
||||
@@ -636,7 +636,9 @@ async fn url_media(bot: Bot, message: &Message, url: &str) {
|
||||
{
|
||||
log::debug!("link cache hit for {key}");
|
||||
let chat_data = CHAT_STORE.get(chat_id).await;
|
||||
let site = key.split(':').next().unwrap_or("unknown");
|
||||
// Cache keys are prefixed with the site id ("twitter:…"), matching
|
||||
// the value a fresh fetch would read from Fetched::site_id.
|
||||
let site = x_media::site::site_id_from_key(&key);
|
||||
let format = chat_data
|
||||
.message_format
|
||||
.get(site)
|
||||
|
||||
Reference in New Issue
Block a user