Created
October 6, 2024 20:41
-
-
Save ten4dinosaur/7b84f276729822df24a919cd7f92a427 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const unrestrictedSanitizer = (string) => string; | |
const unrestrictedPolicy = window.trustedTypes.createPolicy("po#html", { | |
createHTML: unrestrictedSanitizer, | |
createScript: unrestrictedSanitizer, | |
createScriptURL: unrestrictedSanitizer, | |
}); | |
const poRequest = async (endpoint, content) => { | |
const response = await fetch( | |
`https://jnn-pa.googleapis.com/$rpc/google.internal.waa.v1.Waa/${endpoint}`, | |
{ | |
method: "POST", | |
headers: { | |
"X-Goog-Api-Key": "AIzaSyDyT5W0Jh49F30Pqqtyfdf7pDLFKLJoAnw", | |
"Content-Type": "application/json+protobuf", | |
"X-User-Agent": "grpc-web-javascript/0.1", | |
}, | |
body: JSON.stringify(content), | |
} | |
); | |
return await response.json(); | |
}; | |
const requestChallenge = async (key, interpreterHash) => { | |
const body = interpreterHash === null ? [key] : [key, interpreterHash]; | |
const challenge = await poRequest("Create", body); | |
if (challenge.length) { | |
if (challenge.length > 1 && typeof challenge[1] === "string") { | |
const encoded = Uint8Array.from( | |
atob(challenge[1]), | |
(c) => c.charCodeAt(0) + 97 | |
); | |
return JSON.parse(new TextDecoder().decode(encoded)); | |
} else if (typeof challenge[0] === "object") { | |
return challenge[0]; | |
} | |
} | |
}; | |
const getChallenge = async (key, interpreterHash) => { | |
const challenge = await requestChallenge( | |
key, | |
typeof interpreterHash === "string" ? interpreterHash : null | |
); | |
return { | |
messageId: challenge[0], | |
interpreterJavascript: | |
challenge[1]?.length > 5 ? challenge[1][5] : null, | |
interpreterUrl: challenge[2]?.length > 3 ? challenge[2][3] : null, | |
interpreterHash: challenge[3], | |
program: challenge[4], | |
globalName: challenge[5], | |
clientExperimentsState: | |
challenge[7]?.length > 0 | |
? JSON.parse(challenge[7]) | |
: challenge[6]?.length >= 0 | |
? challenge[6] | |
: null, | |
}; | |
}; | |
const initVm = async (challenge) => { | |
const script = document.createElement("script"); | |
if (typeof challenge.interpreterJavascript === "string") { | |
script.textContent = unrestrictedPolicy.createScript( | |
challenge.interpreterJavascript | |
); | |
} else if (typeof challenge.interpreterUrl === "string") { | |
throw "Load via url / not implemented yet"; | |
} else throw "???"; | |
const documentScript = document.querySelector("script[nonce]"); | |
const documentNonce = | |
documentScript?.nonce || documentScript?.getAttribute("nonce") || ""; | |
documentNonce && script.setAttribute("nonce", documentNonce); | |
( | |
document.getElementsByTagName("head")[0] || document.documentElement | |
).appendChild(script); | |
script.parentNode && script.parentNode.removeChild(script); | |
const vm = window[challenge.globalName]; | |
delete window[challenge.globalName]; | |
return vm; | |
}; | |
const initBotguard = async (key, challenge, vm) => { | |
let functions = {}; | |
const setFunctions = (fn1, fn2, fn3, fn4) => | |
(functions = { fn1, fn2, fn3, fn4 }); | |
const state = [[], []]; // for now, in future should be generated based on clientExperimentsState | |
await vm.a( | |
challenge.program, | |
setFunctions, | |
true, | |
undefined, | |
() => {}, | |
state | |
); | |
let attestationResponse; | |
let processFunctions = []; | |
await functions.fn1( | |
(response) => (attestationResponse = response), | |
[undefined, undefined, processFunctions, undefined] | |
); | |
const time = Date.now(); | |
const response = await poRequest("GenerateIT", [key, attestationResponse]); | |
return { | |
expiresAt: time + response[1] * 1000, | |
refreshAt: time + (response[1] - response[2]) * 1000, | |
generateToken: processFunctions[0]( | |
Uint8Array.from(atob(response[0]), (c) => c.charCodeAt(0)) | |
), | |
}; | |
}; | |
const initTokenGenerator = async (isTv) => { | |
let challenge, vm, botguard; | |
const key = isTv === true ? "Z1elNkAKLpSR3oPOUMSN" : "O43z0dpjhgX20SCx4KAo"; | |
const hardRefresh = async () => { | |
challenge = await getChallenge(key); | |
vm = await initVm(challenge); | |
botguard = await initBotguard(key, challenge, vm); | |
}; | |
await hardRefresh(); | |
return { | |
expiresIn: () => Math.max(0, botguard.expiresAt - Date.now()), | |
refreshIn: () => Math.max(0, botguard.refreshAt - Date.now()), | |
generateToken: async (visitorData) => { | |
const poToken = await botguard.generateToken( | |
new TextEncoder().encode(visitorData) | |
); | |
return btoa(String.fromCharCode.apply(null, poToken)) | |
.replace(/\+/g, "-") | |
.replace(/\//g, "_"); | |
}, | |
refresh: async () => { | |
challenge = await getChallenge(key, challenge.interpreterHash); | |
botguard = await initBotguard(key, challenge, vm); | |
}, | |
hardRefresh: hardRefresh, | |
}; | |
}; | |
const generator = await initTokenGenerator(); | |
console.log( | |
await generator.generateToken( | |
ytInitialPlayerResponse.playerResponse.responseContext.visitorData | |
) | |
); | |
generator.refresh(); | |
console.log( | |
await generator.generateToken( | |
ytInitialPlayerResponse.playerResponse.responseContext.visitorData | |
) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment