mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-28 00:02:12 +00:00
refactor(site): match the site pattern once, then check enabled
find_site walked the registry with "enabled && matches" and disabled_site walked it again with "!enabled && matches" — two passes re-running the same regexes to answer one question. matching_site finds the first match and the fetch decides what a disabled site means; the patterns are disjoint (one domain each), so "first enabled match" and "first match, then check" never disagree.
This commit is contained in:
@@ -385,25 +385,16 @@ pub(crate) static SITES: LazyLock<Vec<Box<dyn Site>>> = LazyLock::new(|| {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The first enabled site whose pattern matches `url`, in dispatch order.
|
/// The first site whose pattern matches `url`, in dispatch order — enabled
|
||||||
fn find_site(url: &str) -> Option<&'static dyn Site> {
|
/// or not. The caller decides what a disabled match means; no match at all is
|
||||||
|
/// the "unsupported link" case.
|
||||||
|
fn matching_site(url: &str) -> Option<&'static dyn Site> {
|
||||||
SITES
|
SITES
|
||||||
.iter()
|
.iter()
|
||||||
.find(|site| site.enabled() && site.pattern().is_match(url))
|
.find(|site| site.pattern().is_match(url))
|
||||||
.map(|site| site.as_ref())
|
.map(|site| site.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The site whose pattern matches `url` but which is disabled right now.
|
|
||||||
/// `None` when no site matches the URL at all, or when the matching site is
|
|
||||||
/// enabled. Lets the dispatcher tell "unsupported link" (silently ignored)
|
|
||||||
/// apart from "this bot has that site switched off" (reported to the user).
|
|
||||||
fn disabled_site(url: &str) -> Option<&'static str> {
|
|
||||||
SITES
|
|
||||||
.iter()
|
|
||||||
.find(|site| !site.enabled() && site.pattern().is_match(url))
|
|
||||||
.map(|site| site.id())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Every supported site id, in dispatch order. The bot's SetFormat whitelist
|
/// Every supported site id, in dispatch order. The bot's SetFormat whitelist
|
||||||
/// derives from this list.
|
/// derives from this list.
|
||||||
pub fn site_ids() -> Vec<&'static str> {
|
pub fn site_ids() -> Vec<&'static str> {
|
||||||
@@ -467,17 +458,18 @@ async fn fetch_with_attempts(url: &str, attempts: u32) -> Result<Option<Fetched>
|
|||||||
// Wall time of the whole fetch, retry backoff included: the ugoira encode
|
// Wall time of the whole fetch, retry backoff included: the ugoira encode
|
||||||
// and the HLS remux live inside it, so this is where a slow fetch shows.
|
// and the HLS remux live inside it, so this is where a slow fetch shows.
|
||||||
let started = std::time::Instant::now();
|
let started = std::time::Instant::now();
|
||||||
let Some(site) = find_site(url) else {
|
let Some(site) = matching_site(url) else {
|
||||||
// A registered-but-disabled site (pixiv without a token) is not an
|
return Ok(None); // unsupported link: silently ignored
|
||||||
// unsupported link: report it, so the bot answers the user instead of
|
|
||||||
// ignoring the message.
|
|
||||||
return match disabled_site(url) {
|
|
||||||
Some(site) => Err(FetchError::Disabled { site }),
|
|
||||||
None => Ok(None),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
// Unsupported and disabled links answer above without touching the gate;
|
// A registered-but-disabled site (pixiv without a token) is not an
|
||||||
// from here on every attempt counts against FETCH_SLOTS (see above).
|
// unsupported link: report it, so the bot answers the user instead of
|
||||||
|
// ignoring the message. One match is the whole lookup — the site patterns
|
||||||
|
// are disjoint (one domain each), so "first enabled match" and "first
|
||||||
|
// match, then check" never disagree.
|
||||||
|
if !site.enabled() {
|
||||||
|
return Err(FetchError::Disabled { site: site.id() });
|
||||||
|
}
|
||||||
|
// Gate every network attempt process-wide (see FETCH_SLOTS).
|
||||||
let _permit = FETCH_SLOTS.acquire().await.expect("fetch gate closed");
|
let _permit = FETCH_SLOTS.acquire().await.expect("fetch gate closed");
|
||||||
for attempt in 0..attempts.max(1) {
|
for attempt in 0..attempts.max(1) {
|
||||||
match site.fetch_from_url(url).await {
|
match site.fetch_from_url(url).await {
|
||||||
@@ -584,11 +576,11 @@ mod tests {
|
|||||||
site_ids(),
|
site_ids(),
|
||||||
vec!["twitter", "bsky", "misskey", "pixiv", "bilibili"]
|
vec!["twitter", "bsky", "misskey", "pixiv", "bilibili"]
|
||||||
);
|
);
|
||||||
// Enabled sites dispatch; unsupported URLs never match.
|
// Patterns dispatch; unsupported URLs never match.
|
||||||
assert!(find_site("https://x.com/u/status/1").is_some());
|
assert!(matching_site("https://x.com/u/status/1").is_some());
|
||||||
assert!(find_site("https://misskey.io/notes/abc").is_some());
|
assert!(matching_site("https://misskey.io/notes/abc").is_some());
|
||||||
assert!(find_site("https://t.bilibili.com/1245284537985925159").is_some());
|
assert!(matching_site("https://t.bilibili.com/1245284537985925159").is_some());
|
||||||
assert!(find_site("https://example.com/x").is_none());
|
assert!(matching_site("https://example.com/x").is_none());
|
||||||
// Cache keys are pattern-driven, independent of the enabled() gate
|
// Cache keys are pattern-driven, independent of the enabled() gate
|
||||||
// (pixiv is disabled in tests without PIXIV_REFRESH_TOKEN).
|
// (pixiv is disabled in tests without PIXIV_REFRESH_TOKEN).
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|||||||
Reference in New Issue
Block a user