diff --git a/.gitignore b/.gitignore index 853b0d74..fc2ad193 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ List/ Clash/ Modules/sukka_local_dns_mapping.sgmodule Modules/sukka_url_redirect.sgmodule +Mock/www-google-analytics-com_ga.js +Mock/www-googletagservices-com_gpt.js +Mock/www-google-analytics-com_analytics.js +Mock/www-googlesyndication-com_adsbygoogle.js diff --git a/Build/download-mock-assets.ts b/Build/download-mock-assets.ts new file mode 100644 index 00000000..435a9327 --- /dev/null +++ b/Build/download-mock-assets.ts @@ -0,0 +1,27 @@ +import picocolors from 'picocolors'; +import { task } from './lib/trace-runner'; +import path from 'path'; +import { fetchWithRetry } from './lib/fetch-retry'; + +const ASSETS_LIST = { + 'www-google-analytics-com_ga.js': 'https://unpkg.com/@adguard/scriptlets@1/dist/redirect-files/google-analytics-ga.js', + 'www-googletagservices-com_gpt.js': 'https://unpkg.com/@adguard/scriptlets@1/dist/redirect-files/googletagservices-gpt.js', + 'www-google-analytics-com_analytics.js': 'https://unpkg.com/@adguard/scriptlets@1/dist/redirect-files/google-analytics.js', + 'www-googlesyndication-com_adsbygoogle.js': 'https://unpkg.com/@adguard/scriptlets@1/dist/redirect-files/googlesyndication-adsbygoogle.js' +} as const; + +const mockDir = path.resolve(import.meta.dir, '../Mock'); + +export const downloadMockAssets = task(import.meta.path, () => Promise.all(Object.entries(ASSETS_LIST).map(async ([filename, url]) => { + const targetPath = path.join(mockDir, filename); + + const key = picocolors.gray(`Download ${filename}`); + console.time(key); + const res = await fetchWithRetry(url); + await Bun.write(targetPath, res as Response); + console.timeEnd(key); +}))); + +if (import.meta.main) { + downloadMockAssets(); +} diff --git a/Build/index.ts b/Build/index.ts index 2630c0ab..2e19e05b 100644 --- a/Build/index.ts +++ b/Build/index.ts @@ -17,6 +17,7 @@ import { validate } from './validate-domainset'; import { buildSSPanelUIMAppProfile } from './build-sspanel-appprofile'; import { buildPublic } from './build-public'; +import { downloadMockAssets } from './download-mock-assets'; // import type { TaskResult } from './lib/trace-runner'; (async () => { @@ -70,6 +71,8 @@ import { buildPublic } from './build-public'; downloadPreviousBuildPromise ]).then(() => buildSSPanelUIMAppProfile()); + const downloadMockAssetsPromise = downloadMockAssets(); + const stats = await Promise.all([ downloadPreviousBuildPromise, downloadPublicSuffixListPromise, @@ -87,7 +90,9 @@ import { buildPublic } from './build-public'; buildDomesticRulesetPromise, buildRedirectModulePromise, buildStreamServicePromise, - buildSSPanelUIMAppProfilePromise + buildSSPanelUIMAppProfilePromise, + + downloadMockAssetsPromise ]); await Promise.all([ diff --git a/Mock/www-google-analytics-com_analytics.js b/Mock/www-google-analytics-com_analytics.js deleted file mode 100644 index 9c796c7d..00000000 --- a/Mock/www-google-analytics-com_analytics.js +++ /dev/null @@ -1,89 +0,0 @@ -(function () { - 'use strict'; - - // https://developers.google.com/analytics/devguides/collection/analyticsjs/ - const noopfn = function () { - }; - // - const Tracker = function () { - }; - const p = Tracker.prototype; - p.get = noopfn; - p.set = noopfn; - p.send = noopfn; - // - const w = window; - const gaName = w.GoogleAnalyticsObject || 'ga'; - const gaQueue = w[gaName]; - const ga = function (...args) { - const len = args.length; - if (len === 0) { return; } - let fn; - const a = args[len - 1]; - if (typeof a === 'object' && typeof a.hitCallback === 'function') { - fn = a.hitCallback; - } else if (typeof a === 'function') { - fn = () => { a(ga.create()); }; - } else { - const pos = args.indexOf('hitCallback'); - if (pos !== -1 && typeof args[pos + 1] === 'function') { - fn = args[pos + 1]; - } - } - if (typeof fn !== 'function') { return; } - try { - fn(); - } catch { - } - }; - ga.create = function () { - return new Tracker(); - }; - ga.getByName = function () { - return new Tracker(); - }; - ga.getAll = function () { - return [new Tracker()]; - }; - ga.remove = noopfn; - // https://github.com/uBlockOrigin/uAssets/issues/2107 - ga.loaded = true; - w[gaName] = ga; - // https://github.com/gorhill/uBlock/issues/3075 - const dl = w.dataLayer; - if (typeof dl === 'object') { - if (typeof dl.hide === 'object' && typeof dl.hide.end === 'function') { - dl.hide.end(); - dl.hide.end = () => { }; - } - if (typeof dl.push === 'function') { - const doCallback = function (item) { - if (typeof item === 'object' === false) { return; } - if (typeof item.eventCallback !== 'function') { return; } - // eslint-disable-next-line sukka/prefer-timer-id -- deliberate use of setTimeout - setTimeout(item.eventCallback, 1); - item.eventCallback = () => { }; - }; - dl.push = new Proxy(dl.push, { - apply(target, thisArg, args) { - doCallback(args[0]); - return Reflect.apply(target, thisArg, args); - } - }); - if (Array.isArray(dl)) { - const q = dl.slice(); - for (const item of q) { - doCallback(item); - } - } - } - } - // empty ga queue - if (typeof gaQueue === 'function' && Array.isArray(gaQueue.q)) { - const q = gaQueue.q.slice(); - gaQueue.q.length = 0; - for (const entry of q) { - ga(...entry); - } - } -}()); diff --git a/Mock/www-google-analytics-com_ga.js b/Mock/www-google-analytics-com_ga.js deleted file mode 100644 index 845be868..00000000 --- a/Mock/www-google-analytics-com_ga.js +++ /dev/null @@ -1,109 +0,0 @@ -(function () { - 'use strict'; - - const noopfn = function () { - }; - // - const Gaq = function () { - }; - Gaq.prototype.Na = noopfn; - Gaq.prototype.O = noopfn; - Gaq.prototype.Sa = noopfn; - Gaq.prototype.Ta = noopfn; - Gaq.prototype.Va = noopfn; - Gaq.prototype._createAsyncTracker = noopfn; - Gaq.prototype._getAsyncTracker = noopfn; - Gaq.prototype._getPlugin = noopfn; - Gaq.prototype.push = function (a) { - if (typeof a === 'function') { - a(); return; - } - if (Array.isArray(a) === false) { return; } - // https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiDomainDirectory#_gat.GA_Tracker_._link - if ( - typeof a[0] === 'string' - && /(^|\.)_link$/.test(a[0]) - && typeof a[1] === 'string' - ) { - try { - window.location.assign(a[1]); - } catch { - } - } - if (a[0] === '_set' && a[1] === 'hitCallback' && typeof a[2] === 'function') { - a[2](); - } - }; - // - const tracker = (function () { - const out = {}; - const api = [ - '_addIgnoredOrganic _addIgnoredRef _addItem _addOrganic', - '_addTrans _clearIgnoredOrganic _clearIgnoredRef _clearOrganic', - '_cookiePathCopy _deleteCustomVar _getName _setAccount', - '_getAccount _getClientInfo _getDetectFlash _getDetectTitle', - '_getLinkerUrl _getLocalGifPath _getServiceMode _getVersion', - '_getVisitorCustomVar _initData _linkByPost', - '_setAllowAnchor _setAllowHash _setAllowLinker _setCampContentKey', - '_setCampMediumKey _setCampNameKey _setCampNOKey _setCampSourceKey', - '_setCampTermKey _setCampaignCookieTimeout _setCampaignTrack _setClientInfo', - '_setCookiePath _setCookiePersistence _setCookieTimeout _setCustomVar', - '_setDetectFlash _setDetectTitle _setDomainName _setLocalGifPath', - '_setLocalRemoteServerMode _setLocalServerMode _setReferrerOverride _setRemoteServerMode', - '_setSampleRate _setSessionTimeout _setSiteSpeedSampleRate _setSessionCookieTimeout', - '_setVar _setVisitorCookieTimeout _trackEvent _trackPageLoadTime', - '_trackPageview _trackSocial _trackTiming _trackTrans', - '_visitCode' - ].join(' ').split(/\s+/); - for (const method of api) { - out[method] = noopfn; - } - out._getLinkerUrl = function (a) { - return a; - }; - // https://github.com/AdguardTeam/Scriptlets/issues/154 - out._link = function (a) { - if (typeof a !== 'string') { return; } - try { - window.location.assign(a); - } catch { - } - }; - return out; - }()); - // - const Gat = function () { - }; - Gat.prototype._anonymizeIP = noopfn; - Gat.prototype._createTracker = noopfn; - Gat.prototype._forceSSL = noopfn; - Gat.prototype._getPlugin = noopfn; - Gat.prototype._getTracker = function () { - return tracker; - }; - Gat.prototype._getTrackerByName = function () { - return tracker; - }; - Gat.prototype._getTrackers = noopfn; - Gat.prototype.aa = noopfn; - Gat.prototype.ab = noopfn; - Gat.prototype.hb = noopfn; - Gat.prototype.la = noopfn; - Gat.prototype.oa = noopfn; - Gat.prototype.pa = noopfn; - Gat.prototype.u = noopfn; - const gat = new Gat(); - window._gat = gat; - // - const gaq = new Gaq(); - (function () { - const aa = window._gaq || []; - if (Array.isArray(aa)) { - while (aa[0]) { - gaq.push(aa.shift()); - } - } - }()); - gaq.qf = gaq; - window._gaq = gaq; -}()); diff --git a/Mock/www-googlesyndication-com_adsbygoogle.js b/Mock/www-googlesyndication-com_adsbygoogle.js deleted file mode 100644 index 8a025a5c..00000000 --- a/Mock/www-googlesyndication-com_adsbygoogle.js +++ /dev/null @@ -1,32 +0,0 @@ -(function () { - 'use strict'; - - const init = () => { - window.adsbygoogle = { - loaded: true, - push() { - } - }; - const phs = document.querySelectorAll('.adsbygoogle'); - const css = 'height:1px!important;max-height:1px!important;max-width:1px!important;width:1px!important;'; - for (let i = 0; i < phs.length; i++) { - const id = `aswift_${i}`; - if (document.querySelector(`iframe#${id}`) !== null) { continue; } - const fr = document.createElement('iframe'); - fr.id = id; - fr.style = css; - const cfr = document.createElement('iframe'); - cfr.id = `google_ads_frame${i}`; - fr.appendChild(cfr); - phs[i].appendChild(fr); - } - }; - if ( - document.querySelectorAll('.adsbygoogle').length === 0 - && document.readyState === 'loading' - ) { - window.addEventListener('DOMContentLoaded', init, { once: true }); - } else { - init(); - } -}()); diff --git a/Mock/www-googletagmanager-com_gtm.js b/Mock/www-googletagmanager-com_gtm.js deleted file mode 100644 index 539f5f51..00000000 --- a/Mock/www-googletagmanager-com_gtm.js +++ /dev/null @@ -1,24 +0,0 @@ -(function () { - 'use strict'; - - const noopfn = function () { - }; - const w = window; - w.ga = w.ga || noopfn; - const dl = w.dataLayer; - if (typeof dl !== 'object') { return; } - if (typeof dl.hide === 'object' && typeof dl.hide.end === 'function') { - dl.hide.end(); - } - if (typeof dl.push === 'function') { - dl.push = function (o) { - if ( - typeof o === 'object' - && typeof o.eventCallback === 'function' - ) { - // eslint-disable-next-line sukka/prefer-timer-id -- deliberately use setTimeout - setTimeout(o.eventCallback, 1); - } - }; - } -}()); diff --git a/Mock/www-googletagservices-com_gpt.js b/Mock/www-googletagservices-com_gpt.js deleted file mode 100644 index 8e6668bf..00000000 --- a/Mock/www-googletagservices-com_gpt.js +++ /dev/null @@ -1,133 +0,0 @@ -(function () { - 'use strict'; - - // https://developers.google.com/doubleclick-gpt/reference - const noopfn = function () { - }.bind(); - const noopthisfn = function () { - return this; - }; - const noopnullfn = function () { - return null; - }; - const nooparrayfn = function () { - return []; - }; - const noopstrfn = function () { - return ''; - }; - // - const companionAdsService = { - addEventListener: noopthisfn, - enableSyncLoading: noopfn, - setRefreshUnfilledSlots: noopfn - }; - const contentService = { - addEventListener: noopthisfn, - setContent: noopfn - }; - const PassbackSlot = function () { - }; - let p = PassbackSlot.prototype; - p.display = noopfn; - p.get = noopnullfn; - p.set = noopthisfn; - p.setClickUrl = noopthisfn; - p.setTagForChildDirectedTreatment = noopthisfn; - p.setTargeting = noopthisfn; - p.updateTargetingFromMap = noopthisfn; - const pubAdsService = { - addEventListener: noopthisfn, - clear: noopfn, - clearCategoryExclusions: noopthisfn, - clearTagForChildDirectedTreatment: noopthisfn, - clearTargeting: noopthisfn, - collapseEmptyDivs: noopfn, - defineOutOfPagePassback() { return new PassbackSlot(); }, - definePassback() { return new PassbackSlot(); }, - disableInitialLoad: noopfn, - display: noopfn, - enableAsyncRendering: noopfn, - enableSingleRequest: noopfn, - enableSyncRendering: noopfn, - enableVideoAds: noopfn, - get: noopnullfn, - getAttributeKeys: nooparrayfn, - getTargeting: noopfn, - getTargetingKeys: nooparrayfn, - getSlots: nooparrayfn, - refresh: noopfn, - removeEventListener: noopfn, - set: noopthisfn, - setCategoryExclusion: noopthisfn, - setCentering: noopfn, - setCookieOptions: noopthisfn, - setForceSafeFrame: noopthisfn, - setLocation: noopthisfn, - setPublisherProvidedId: noopthisfn, - setPrivacySettings: noopthisfn, - setRequestNonPersonalizedAds: noopthisfn, - setSafeFrameConfig: noopthisfn, - setTagForChildDirectedTreatment: noopthisfn, - setTargeting: noopthisfn, - setVideoContent: noopthisfn, - updateCorrelator: noopfn - }; - const SizeMappingBuilder = function () { - }; - p = SizeMappingBuilder.prototype; - p.addSize = noopthisfn; - p.build = noopnullfn; - const Slot = function () { - }; - p = Slot.prototype; - p.addService = noopthisfn; - p.clearCategoryExclusions = noopthisfn; - p.clearTargeting = noopthisfn; - p.defineSizeMapping = noopthisfn; - p.get = noopnullfn; - p.getAdUnitPath = nooparrayfn; - p.getAttributeKeys = nooparrayfn; - p.getCategoryExclusions = nooparrayfn; - p.getDomId = noopstrfn; - p.getResponseInformation = noopnullfn; - p.getSlotElementId = noopstrfn; - p.getSlotId = noopthisfn; - p.getTargeting = nooparrayfn; - p.getTargetingKeys = nooparrayfn; - p.set = noopthisfn; - p.setCategoryExclusion = noopthisfn; - p.setClickUrl = noopthisfn; - p.setCollapseEmptyDiv = noopthisfn; - p.setTargeting = noopthisfn; - p.updateTargetingFromMap = noopthisfn; - // - const gpt = window.googletag || {}; - const cmd = gpt.cmd || []; - gpt.apiReady = true; - gpt.cmd = []; - gpt.cmd.push = function (a) { - try { - a(); - } catch { - } - return 1; - }; - gpt.companionAds = function () { return companionAdsService; }; - gpt.content = function () { return contentService; }; - gpt.defineOutOfPageSlot = function () { return new Slot(); }; - gpt.defineSlot = function () { return new Slot(); }; - gpt.destroySlots = noopfn; - gpt.disablePublisherConsole = noopfn; - gpt.display = noopfn; - gpt.enableServices = noopfn; - gpt.getVersion = noopstrfn; - gpt.pubads = function () { return pubAdsService; }; - gpt.pubadsReady = true; - gpt.setAdIframeTitle = noopfn; - gpt.sizeMapping = function () { return new SizeMappingBuilder(); }; - window.googletag = gpt; - while (cmd.length !== 0) { - gpt.cmd.push(cmd.shift()); - } -}()); diff --git a/Modules/sukka_enhance_adblock.sgmodule b/Modules/sukka_enhance_adblock.sgmodule index 820b382b..08a98d4c 100644 --- a/Modules/sukka_enhance_adblock.sgmodule +++ b/Modules/sukka_enhance_adblock.sgmodule @@ -6,8 +6,8 @@ hostname = %APPEND% *.google-analytics.com, *.googletagmanager.com, *.googlesynd [URL Rewrite] ^https?://.*\.google-analytics\.com/analytics\.js https://ruleset.skk.moe/Mock/www-google-analytics-com_analytics.js 302 +^https?://.*\.googletagmanager\.com/gtm\.js https://ruleset.skk.moe/Mock/www-google-analytics-com_analytics.js 302 ^https?://.*\.google-analytics\.com/ga\.js https://ruleset.skk.moe/Mock/www-google-analytics-com_ga.js 302 -^https?://.*\.googletagmanager\.com/gtm\.js https://ruleset.skk.moe/Mock/www-googletagmanager-com_gtm.js 302 ^https?://.*\.google-analytics\.com/cx/api\.js https://ruleset.skk.moe/Mock/www-google-analytics-com_cx_api.js 302 ^https?://.*\.googlesyndication\.com/adsbygoogle\.js https://ruleset.skk.moe/Mock/www-googlesyndication-com_adsbygoogle.js 302 ^https?://.*\.googletagservices\.com/gpt\.js https://ruleset.skk.moe/Mock/www-googletagservices-com_gpt.js 302 diff --git a/bun.lockb b/bun.lockb index c90c6ab1..9bb22770 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 55ce43f8..e09d829f 100644 --- a/package.json +++ b/package.json @@ -21,25 +21,25 @@ "async-sema": "^3.1.1", "ci-info": "^4.0.0", "csv-parse": "^5.5.3", - "fast-cidr-tools": "^0.2.2", + "fast-cidr-tools": "^0.2.4", "mnemonist": "^0.39.6", "path-scurry": "^1.10.1", "picocolors": "^1.0.0", "punycode": "^2.3.1", "table": "^6.8.1", "tar-stream": "^3.1.6", - "tldts": "^6.0.22" + "tldts": "^6.1.1" }, "devDependencies": { "@eslint-sukka/node": "4.1.10-beta.2", "@eslint-sukka/ts": "4.1.10-beta.2", "@types/async-retry": "^1.4.8", "@types/tar-stream": "^3.1.3", - "bun-types": "^1.0.11", - "eslint": "^8.55.0", + "bun-types": "^1.0.18-1", + "eslint": "^8.56.0", "eslint-config-sukka": "4.1.10-beta.2", "eslint-formatter-sukka": "4.1.9", - "typescript": "^5.2.2" + "typescript": "^5.3.3" }, "resolutions": { "has": "npm:@nolyfill/has@latest"