sneedium/ad-blocker.js

187 lines
No EOL
5.7 KiB
JavaScript

/**
* Ad Blocker Module
*
* Handles ad blocking and web request filtering for Sneedium browser:
* - Sets up ad blocking with the Ghostery adblocker
* - Configures web request rules
* - Prevents access to local resources from remote sites
*/
const { ElectronBlocker } = require('@ghostery/adblocker-electron');
const fetch = require("cross-fetch");
// Blocklist for ad filtering
const toBlock = [
"*://*.doubleclick.*",
"*://s.innovid.com/*",
"*://partner.googleadservices.com/*",
"*://*.googlesyndication.com/*",
"*://*.google-analytics.com/*",
"*://*.creative.ak.fbcdn.net/*",
"*://*.adbrite.com/*",
"*://*.exponential.com/*",
"*://*.quantserve.com/*",
"*://*.scorecardresearch.com/*",
"*://*.zedo.com/*",
"*://*.a-ads.com/*",
"*://*.777partner.com/*",
"*://*.77tracking.com/*",
"*://*.abc-ads.com/*",
"*://*.aaxads.com/*",
"*://*.adizio.com/*",
"*://*.adjix.com/*",
"*://*.adjug.com/*",
"*://*.adjuggler.com/*",
"*://*.trafficjunky.net/*",
"*://*.trafficleader.com/*",
"*://*.trafficrouter.io/*",
"*://*.monerominer.rocks/*",
"*://*.2mdn.net/*",
"*.exe",
"*.vbs",
"*://*.googlesyndication.*",
"*pixels*",
"*telemetry*",
"*analytics*",
"*://ads.*.com*",
"*ae/us/audience*",
"*/api/v*/science*",
"*/api/v*/typing*"
];
// Regex patterns for additional blocking
const regexPatterns = [
"r[0-100]+---sn-.*\\.googlevideo\\.com$/g",
"r[0-100]+-sn-.*\\.googlevideo\\.com$/g"
];
// Local domain tokens for security filtering
const locals = [
'0.0.0.0', '127.0.0.1', '192.168', '.local', '.example', '.staging', 'fe80::', '::1'
];
/**
* Initialize ad blocker and web request filtering
* @param {Object} session - Electron session to apply blocking to
* @returns {Object} Functions to control ad blocker
*/
function initAdBlocker(session) {
let blocker = undefined;
return {
enableAdBlocking: () => enableGoodies(session),
setupWebRequestFilters: () => setupWebRequestFilters(session),
isLocal
};
}
/**
* Enable ad blocking for a session
* @param {Object} s - Electron session to enable blocking for
*/
async function enableGoodies(s) {
try {
if (!s) {
console.log("No session provided to enableGoodies, using default session");
return;
}
const blocker = await ElectronBlocker.fromLists(fetch, [
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/ubol-filters.txt",
'https://easylist.to/easylist/easylist.txt',
'https://secure.fanboy.co.nz/fanboy-annoyance.txt',
'https://easylist.to/easylist/easyprivacy.txt',
'https://easylist-downloads.adblockplus.org/antiadblockfilters.txt',
'https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt',
'https://cdn.jsdelivr.net/gh/hagezi/dns-blocklists@latest/adblock/pro.plus.txt',
"https://github.com/yokoffing/filterlists/raw/refs/heads/main/youtube_clear_view.txt",
"https://pgl.yoyo.org/as/serverlist.php?showintro=0;hostformat=adblock",
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/unbreak.txt",
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/quick-fixes.txt",
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/privacy.txt",
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/badware.txt",
"https://github.com/uBlockOrigin/uAssets/raw/refs/heads/master/filters/filters.txt"
]);
blocker.enableBlockingInSession(s);
console.log("AD blocking enabled successfully");
return blocker;
} catch (error) {
console.error("Error enabling AD blocking:", error);
return null;
}
}
/**
* Check if a URL is for a local resource
* @param {string} url - URL to check
* @returns {boolean} Whether URL is for a local resource
*/
function isLocal(url) {
return locals.some(local => url.includes(local));
}
/**
* Check if a URL should be blocked by our custom rules
* @param {string} url - URL to check
* @returns {boolean} Whether URL should be blocked
*/
function containsAD(url) {
// Check against simple pattern list
for (let i = 0; i < toBlock.length; i++) {
let regex = toBlock[i].replace(/\*/g, "[^ ]*");
if (url.match(regex)) {
return true;
}
}
// Check against regex patterns
for (let i = 0; i < regexPatterns.length; i++) {
let regex = regexPatterns[i];
if (url.match(regex)) {
return true;
}
}
return false;
}
/**
* Set up web request filters for ad blocking and security
* @param {Object} session - Electron session to set up filters for
*/
function setupWebRequestFilters(session) {
// Set up web request filter
session.webRequest.onBeforeRequest((details, callback) => {
// Block ads
if (containsAD(details.url)) {
return callback({cancel: true});
}
try {
const url = new URL(details.url);
const hostname = url.hostname;
const isLocalDomain = isLocal(hostname);
// Check if the request is to a local domain
if (isLocalDomain) {
// Check if the request is initiated by a remote domain
const initiator = details.initiator ? new URL(details.initiator).hostname : '';
const isInitiatorLocal = isLocal(initiator);
if (initiator && !isInitiatorLocal) {
console.log(`[W] Local domain is being accessed by external source (${initiator}), don't allow!`);
callback({ cancel: true }); // Block request to local domains from remote sources
return;
}
}
callback({ cancel: false }); // Allow request
} catch (error) {
console.error("Error in web request filter:", error);
callback({ cancel: false }); // Allow on error
}
});
}
module.exports = initAdBlocker;