Skip to content

Commit a5bb7a4

Browse files
committed
implement my own adblock cause npm modules are worthless
1 parent 99f7534 commit a5bb7a4

12 files changed

Lines changed: 308 additions & 81 deletions

File tree

bun.lock

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
"@aws-sdk/client-s3": "^3.883.0",
5959
"@aws-sdk/credential-provider-cognito-identity": "^3.883.0",
6060
"@aws-sdk/util-dynamodb": "^3.883.0",
61-
"@sveltejs/adapter-static": "^3.0.9",
62-
"just-detect-adblock": "^1.1.0"
61+
"@sveltejs/adapter-static": "^3.0.9"
6362
}
6463
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import detectDomAdblocker from "./detectDomAdblock.js";
2+
import { createBaitRequest } from "./helpers.js";
3+
4+
/**
5+
* Detect if any known ad blocker mechanism is detected
6+
* @return Promise
7+
*/
8+
export default async function detectAnyAdblocker(): Promise<boolean> {
9+
// check dom adblockers first
10+
if (detectDomAdblocker()) {
11+
return true;
12+
}
13+
try {
14+
const responseOk = await createBaitRequest();
15+
if (!responseOk) {
16+
return true;
17+
}
18+
} catch {
19+
return true;
20+
}
21+
return false;
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createBaitElement, doesElementIsBlocked } from "./helpers.js";
2+
3+
/**
4+
* Detect if an ad blocker is blocking ads in the DOM itself
5+
* @return Boolean
6+
*/
7+
export default function detectDomAdblocker(){
8+
// that's a legacy Ad Block Plus check I suppose ?
9+
// I don't think this attribute is set anymore, but I am keeping it anyway
10+
if(window.document.body.getAttribute('abp') !== null) {
11+
return true;
12+
}
13+
14+
// try to lure adblockers into a trap
15+
var bait = createBaitElement();
16+
window.document.body.appendChild(bait);
17+
var detected = doesElementIsBlocked(bait);
18+
window.document.body.removeChild(bait);
19+
20+
return detected;
21+
};

src/lib/adblock/helpers.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Check if Brave is the current browser
3+
* @return Boolean
4+
*/
5+
export function isBraveBrowser() {
6+
return typeof (navigator as any).brave !== 'undefined' && typeof (navigator as any).brave.isBrave !== 'undefined';
7+
};
8+
9+
/**
10+
* Check if Opera is the current browser
11+
* @return Boolean
12+
*/
13+
export function isOperaBrowser() {
14+
return typeof navigator.userAgent === 'string' && navigator.userAgent.match(/Opera|OPR\//);
15+
};
16+
17+
/**
18+
* Create a DOM element that should be seen as an ad by adblockers
19+
* @return DOM element
20+
*/
21+
export function createBaitElement() {
22+
var bait = document.createElement('div');
23+
24+
bait.setAttribute('class', 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links ad-text adSense adBlock adContent adBanner');
25+
bait.setAttribute('style', 'width: 1px !important; height: 1px !important; position: absolute !important; left: -10000px !important; top: -1000px !important;');
26+
27+
return bait;
28+
};
29+
30+
/**
31+
* Check if a DOM element seems to be blocked by an adblocker or not
32+
* @return Boolean
33+
*/
34+
export function doesElementIsBlocked(elem: HTMLElement) {
35+
if (elem.offsetParent === null
36+
|| elem.offsetHeight == 0
37+
|| elem.offsetLeft == 0
38+
|| elem.offsetTop == 0
39+
|| elem.offsetWidth == 0
40+
|| elem.clientHeight == 0
41+
|| elem.clientWidth == 0) {
42+
return true;
43+
} else if (window.getComputedStyle !== undefined) {
44+
var elemCS = window.getComputedStyle(elem, null);
45+
if (elemCS && (elemCS.getPropertyValue('display') == 'none' || elemCS.getPropertyValue('visibility') == 'hidden')) {
46+
return true;
47+
}
48+
}
49+
50+
return false;
51+
};
52+
53+
/**
54+
* Create and execute an XMLHttpRequest that should be blocked by an adblocker
55+
* @return Promise
56+
*/
57+
export async function createBaitRequest() {
58+
try {
59+
const response = await fetch('https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', { method: 'GET' });
60+
return response.ok;
61+
} catch {
62+
return false;
63+
}
64+
}

src/lib/components/CardGrid.svelte

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@
169169
}
170170
171171
const searchRegex = /[a-z0-9]/i;
172-
onMount(() => {
172+
onMount(async () => {
173173
document.addEventListener("keydown", (e) => {
174174
if (!searchInput) return;
175175
// Ignore keyboard shortcuts, special keys, non a-z0-9, or backspace, enter, delete, etc.
@@ -216,47 +216,39 @@
216216
217217
if (SessionState.ssr) return;
218218
219-
(async () => {
220-
const enabled = !detectAdBlockEnabled() && State.isAHost();
221-
if (enabled) {
222-
const host = browser ? window.location.hostname : "<SSR_HOST>";
223-
if (host in adSlotConfig) {
224-
adSlots = adSlotConfig[host as keyof typeof adSlotConfig];
225-
}
219+
await detectAdBlockEnabled();
220+
console.log("AdBlock Enabled:", SessionState.adBlockEnabled);
221+
adsEnabled = SessionState.adsEnabled;
222+
if (adsEnabled) {
223+
const host = browser ? window.location.hostname : "<SSR_HOST>";
224+
if (host in adSlotConfig) {
225+
adSlots = adSlotConfig[host as keyof typeof adSlotConfig];
226+
}
227+
(async () => {
226228
const aHosts = await findAHosts();
227229
if (!aHosts) {
228230
adsEnabled = false;
231+
SessionState.adsEnabled = false;
229232
return;
230233
}
231234
232235
const aHostData = aHosts.find((h) => h.hostname === host);
233236
if (aHostData && aHostData.acode) {
237+
const scriptId = `ad-script-${aHostData.acode}`;
238+
if (document.getElementById(scriptId)) return;
239+
234240
const script = document.createElement("script");
241+
script.id = scriptId;
235242
script.src = `//monu.delivery/site/${aHostData.acode}`;
236243
script.setAttribute("data-cfasync", "false");
237244
script.defer = true;
238245
document.head.appendChild(script);
239-
adsEnabled = true;
240246
} else {
241-
if (!SessionState.devMode) {
242-
adsEnabled = false;
243-
} else {
244-
const script = document.createElement("script");
245-
script.src = `//monu.delivery/site/${aHosts[0].acode}`;
246-
script.setAttribute("data-cfasync", "false");
247-
script.defer = true;
248-
document.head.appendChild(script);
249-
adsEnabled = true;
250-
if (!adSlots) {
251-
adSlots =
252-
adSlotConfig[
253-
aHosts[0].hostname as keyof typeof adSlotConfig
254-
];
255-
}
256-
}
247+
adsEnabled = false;
248+
SessionState.adsEnabled = false;
257249
}
258-
}
259-
})();
250+
})();
251+
}
260252
});
261253
262254
$effect(() => {

src/lib/helpers.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { ReturnValue, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
22
import type { Game } from "./types/game.js";
33
import { SessionState, State } from "./state.js";
4-
import detection from 'just-detect-adblock'
4+
import detectAnyAdBlocker from "./adblock/detectAnyAdblock.js";
55
import { browser } from "$app/environment";
6-
const { detectAnyAdblocker } = detection;
76
export function decamelize(string: string): string {
87
// HelloWorld -> Hello World
98
return string.replace(/([a-z])([A-Z])/g, '$1 $2');
@@ -69,8 +68,15 @@ export async function importJSON(path: string): Promise<any> {
6968

7069
export async function detectAdBlockEnabled() {
7170
if (!browser) return false; // Only run in browser
72-
const detected = await detectAnyAdblocker();
73-
return detected;
71+
try {
72+
const detected = await detectAnyAdBlocker();
73+
SessionState.adBlockEnabled = detected;
74+
SessionState.adsEnabled = !detected && State.isAHost();
75+
return detected;
76+
} catch (e) {
77+
console.error("Adblock detection failed", e);
78+
return true; // Assume adblock is enabled if detection fails
79+
}
7480
}
7581

7682
export function getTimeBetween(date1: Date, date2: Date): string {

src/lib/just-detect-adblock.d.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/lib/state.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ export const SessionState = {
1111
awsReady: false,
1212
ssr: !browser,
1313
adBlockEnabled: false,
14+
adsEnabled: false,
1415
credentials: null as CognitoIdentityCredentials | null,
1516
dynamoDBClient: null as DynamoDBClient | null,
1617
s3Client: null as S3Client | null,
1718
devMode: (browser && window.location.hostname === "localhost"),
18-
plays: 0
19+
plays: 0,
20+
user: null as null | { name: string; email: string; tokens: any } | undefined,
21+
loggedIn: false
1922
}
2023

2124

2225
type StateType = {
2326
version: string;
24-
loggedIn: boolean;
2527
servers: typeof Servers;
2628
aHosts: typeof AHosts;
2729
currentServer: Server;
@@ -53,7 +55,6 @@ function createState(initial: StateType): StateType {
5355

5456
export const State = createState({
5557
version: "1.0.0",
56-
loggedIn: false,
5758
servers: Servers,
5859
aHosts: AHosts,
5960
currentServer: Servers[0],
@@ -76,6 +77,8 @@ export async function initializeTooling() {
7677
}
7778
const adBlock = await detectAdBlockEnabled();
7879
SessionState.adBlockEnabled = adBlock;
80+
SessionState.adsEnabled = !adBlock && State.isAHost();
81+
7982
const credentials = await initializeUnathenticated();
8083
const dynamoDBClient = new DynamoDBClient({
8184
region: "us-west-2",
@@ -130,3 +133,4 @@ async function initializeUnathenticated() {
130133
SessionState.awsReady = true;
131134
return credentials;
132135
}
136+

src/routes/+page.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313
const { games } = data;
1414
let isAHost = $state(State.isAHost());
1515
let devMode = $state(true);
16+
let adblockEnabled = $state(SessionState.adBlockEnabled);
17+
let adsEnabled = $state(SessionState.adsEnabled);
1618
onMount(async () => {
1719
await initializeTooling();
1820
isAHost = State.isAHost();
1921
devMode = SessionState.devMode;
22+
adblockEnabled = SessionState.adBlockEnabled;
23+
adsEnabled = SessionState.adsEnabled;
2024
});
2125
</script>
2226

@@ -68,7 +72,8 @@
6872
Browser: {browser ? navigator.userAgent : "<SSR_HOST>"}<br />
6973
Host: {browser ? window.location.hostname : "<SSR_HOST>"}<br />
7074
DevMode: {SessionState.devMode}<br />
71-
AdBlock: {SessionState.adBlockEnabled}<br />
75+
AdBlock Enabled: {adblockEnabled}<br />
76+
Ads Enabled: {adsEnabled}<br />
7277
Current Server: {State.currentServer.name} (Loaded {State.servers
7378
.length})<br />
7479
AHost: {State.isAHost()} (Loaded {State.aHosts.length})<br />
@@ -77,7 +82,7 @@
7782
Games Loaded: {games.length} ({State.pinnedGames.length} pinned) - rendered
7883
{State.homeView}<br />
7984
Version: {State.version}<br />
80-
Logged In: {State.loggedIn}<br />
85+
Logged In: {SessionState.loggedIn}<br />
8186
SSR: {SessionState.ssr}<br />
8287
AWS Ready: {SessionState.awsReady}<br />
8388
AWS Acting: {SessionState.credentials?.identityId} | {SessionState

0 commit comments

Comments
 (0)