use std::sync::LazyLock;
pub static ADBLOCK_PATTERNS: LazyLock<Vec<&'static str>> = LazyLock::new(|| {
vec![
"-advertisement.",
"-advertisement-icon.",
"-advertisement-management/",
"-advertisement/script.",
"-ads.",
"-ads/script.",
"-ad.",
"ads.js",
"gtm.js?",
"googletagmanager.com",
"ssl.google-analytics.com",
"-tracking.",
"-tracking/script.",
".tracking",
".snowplowanalytics.snowplow",
".mountain.com",
"tracking.js",
"track.js",
"/upi/jslogger",
"otBannerSdk.js",
"analytics.js",
"analytics.min.js",
"ob.cityrobotflower.com",
"siteintercept.qualtrics.com",
"iesnare.com",
"iovation.com",
"googletagmanager.com",
"forter.com",
"/first.iovation.com",
"/simpleads/impression",
"googlesyndication.com",
".googlesyndication.com/safeframe/",
"adsafeprotected.com",
"cxense.com/",
".sharethis.com",
"amazon-adsystem.com",
"g.doubleclick.net",
"privacy-notice.js",
"insight.min.js",
]
});
#[cfg(feature = "adblock")]
pub mod engine {
use std::sync::Arc;
pub struct FilterListUrls;
impl FilterListUrls {
pub const EASYLIST: &'static str = "https://easylist.to/easylist/easylist.txt";
pub const EASYPRIVACY: &'static str = "https://easylist.to/easylist/easyprivacy.txt";
}
pub struct AdblockEngine {
inner: adblock::Engine,
}
impl AdblockEngine {
pub fn from_engine(engine: adblock::Engine) -> Self {
Self { inner: engine }
}
pub fn from_rules<I, S>(rules: I, debug: bool) -> Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let mut filter_set = adblock::lists::FilterSet::new(debug);
filter_set.add_filters(rules, adblock::lists::ParseOptions::default());
let engine = adblock::Engine::from_filter_set(filter_set, true);
Self { inner: engine }
}
pub fn from_filter_list_content(content: &str, debug: bool) -> Self {
let rules: Vec<&str> = content.lines().collect();
Self::from_rules(rules, debug)
}
pub fn should_block(&self, url: &str, source_url: &str, request_type: &str) -> bool {
match adblock::request::Request::new(url, source_url, request_type) {
Ok(request) => self.inner.check_network_request(&request).matched,
Err(_) => false,
}
}
pub fn check_request(
&self,
url: &str,
source_url: &str,
request_type: &str,
) -> Option<adblock::blocker::BlockerResult> {
adblock::request::Request::new(url, source_url, request_type)
.ok()
.map(|req| self.inner.check_network_request(&req))
}
pub fn serialize(&self) -> Vec<u8> {
self.inner.serialize()
}
pub fn deserialize(data: &[u8]) -> Option<Self> {
let mut engine = adblock::Engine::default();
if engine.deserialize(data).is_ok() {
Some(Self { inner: engine })
} else {
None
}
}
pub fn into_shared(self) -> Arc<Self> {
Arc::new(self)
}
}
}
#[cfg(feature = "adblock_easylist")]
pub mod easylist_engine {
use std::sync::LazyLock;
static EASYLIST: &str = include_str!(concat!(env!("OUT_DIR"), "/easylist.txt"));
static EASYPRIVACY: &str = include_str!(concat!(env!("OUT_DIR"), "/easyprivacy.txt"));
pub static ADBLOCK_ENGINE: LazyLock<super::engine::AdblockEngine> = LazyLock::new(|| {
use adblock::lists::{FilterSet, ParseOptions, RuleTypes};
let mut filter_set = FilterSet::new(false);
let mut opts = ParseOptions::default();
opts.rule_types = RuleTypes::All;
filter_set.add_filters(&*super::ADBLOCK_PATTERNS, opts.clone());
if !EASYLIST.is_empty() {
filter_set.add_filter_list(EASYLIST, opts.clone());
}
if !EASYPRIVACY.is_empty() {
filter_set.add_filter_list(EASYPRIVACY, opts);
}
let engine = adblock::Engine::from_filter_set(filter_set, true);
super::engine::AdblockEngine::from_engine(engine)
});
}