Skip to content

Commit 04f3fab

Browse files
committed
feat: 1.0.0
1 parent cd0e6b9 commit 04f3fab

1 file changed

Lines changed: 78 additions & 1 deletion

File tree

userscript/source/index.ts

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,81 @@ type unsafeWindow = typeof window
1313
declare const unsafeWindow: unsafeWindow
1414

1515
const Win = typeof unsafeWindow !== 'undefined' ? unsafeWindow : window
16-
const UserscriptName = 'newtoki-cracker'
16+
const UserscriptName = 'newtoki-cracker'
17+
18+
const OriginalMapSet = Win.Map.prototype.set
19+
const OriginalFunctionToString = Function.prototype.toString
20+
Win.Map.prototype.set = new Proxy(OriginalMapSet, {
21+
apply(Target: typeof OriginalMapSet, ThisArg: Map<unknown, unknown>, Args: [unknown, unknown]) {
22+
if (typeof Args[0] === 'number' && typeof Args[1] === 'function') {
23+
let FuncStr = Reflect.apply(OriginalFunctionToString, Args[1], [])
24+
const Keywords: RegExp[][] = [[/getBoundingClientRect\(\)/], [/\) *return *void */]]
25+
if (Keywords.filter(KeywordGroup => KeywordGroup.every(Keyword => Keyword.test(FuncStr))).length > 0) {
26+
return
27+
}
28+
}
29+
return Reflect.apply(Target, ThisArg, Args)
30+
}
31+
})
32+
33+
const OriginalFetch = Win.fetch
34+
Win.fetch = new Proxy(OriginalFetch, {
35+
apply(Target: typeof OriginalFetch, ThisArg: Window, Args: Parameters<typeof fetch>) {
36+
if (typeof Args[1] !== 'undefined' && Args[1] !== null && 'body' in Args[1] && Args[1].body && typeof Args[1].body === 'string'
37+
&& /{ *("|')reason("|') *: *("|')[A-Za-z0-9_-]+("|') *,.+("|')adblock/.test(Args[1].body)
38+
) {
39+
return new Promise(() => {})
40+
}
41+
return Reflect.apply(Target, ThisArg, Args)
42+
}
43+
})
44+
45+
const ElementAttachShadow = Element.prototype.attachShadow
46+
Element.prototype.attachShadow = new Proxy(ElementAttachShadow, {
47+
apply(Target: typeof ElementAttachShadow, ThisArg: Element, Args: [ShadowRootInit]) {
48+
if (ThisArg instanceof HTMLElement && Args[0].mode === 'closed' && ThisArg.outerHTML.length > 100
49+
&& document.body.style.overflow === 'hidden' && document.documentElement.style.overflow === 'hidden') {
50+
document.body.style.overflow = ''
51+
document.documentElement.style.overflow = ''
52+
throw new Error()
53+
}
54+
return Reflect.apply(Target, ThisArg, Args)
55+
}
56+
})
57+
58+
const OriginalDocumentQuerySelectorAll = Document.prototype.querySelectorAll
59+
Document.prototype.querySelectorAll = new Proxy(OriginalDocumentQuerySelectorAll, {
60+
apply(Target: typeof OriginalDocumentQuerySelectorAll, ThisArg: Document, Args: [string]) {
61+
if (Args[0].includes('[data-br="')) {
62+
return []
63+
}
64+
return Reflect.apply(Target, ThisArg, Args)
65+
}
66+
})
67+
68+
// novel
69+
document.addEventListener('DOMContentLoaded', () => {
70+
const CurrentAdvertContainerCount = [...document.querySelectorAll('[data-br] img')].length + 1
71+
const HTMLScriptElementHasTokenNonces = [...document.body.querySelectorAll('script')].filter(Script => {
72+
const InnerHTML = Script.innerHTML
73+
return InnerHTML.includes('challenge') && InnerHTML.includes('token') && InnerHTML.includes('slotNonces')
74+
})
75+
const Token = HTMLScriptElementHasTokenNonces[0]!.innerHTML.match(/(?<=, *{ *(\\)*('|")challenge(\\)*('|") *: *{ *(\\)*('|")token(\\)*('|") *: *(\\)*('|"))eyJ2[A-Za-z0-9._-]+/g)?.[0] ?? ''
76+
const SlotNonces = HTMLScriptElementHasTokenNonces[0]!.innerHTML.match(/(?<=, *(\\)*('|")slotNonces(\\)*('|") *: *)\[ *(\\)*('|")[a-zA-Z0-9-_]+(\\)*('|") *, *(\\)*('|")[a-zA-Z0-9-_]+(\\)*('|") *, *(\\)*('|")[a-zA-Z0-9-_]+(\\)*('|") *, *(\\)*('|")[a-zA-Z0-9-_]+(\\)*('|") *\]/g)?.[0] ?? ''
77+
console.debug(`[${UserscriptName}]`, 'Token:', Token , 'SlotNonces:', SlotNonces, 'CurrentAdvertContainerCount:', CurrentAdvertContainerCount)
78+
Reflect.apply(OriginalFetch, Win, [new URL(`https://${location.hostname}/api/ad/ack`), {
79+
body: JSON.stringify({
80+
challengeToken: Token,
81+
total: CurrentAdvertContainerCount,
82+
visible: CurrentAdvertContainerCount,
83+
path: location.pathname,
84+
slotNonces: JSON.parse(SlotNonces.replaceAll('\\', ''))
85+
}),
86+
method: 'POST',
87+
headers: {
88+
'Content-Type': 'application/json'
89+
},
90+
credentials: 'include',
91+
keepalive: true
92+
}])
93+
})

0 commit comments

Comments
 (0)