diff --git a/slader-limit-bypass/js/quizlet_bypass.js b/slader-limit-bypass/js/quizlet_bypass.js
index 9e11844..5363758 100644
--- a/slader-limit-bypass/js/quizlet_bypass.js
+++ b/slader-limit-bypass/js/quizlet_bypass.js
@@ -1,152 +1,74 @@
-// TODO: Sidestep race condition in a less patchwork manner
-setTimeout(function(){ renderBypass(); /* TODO: Check if it actually went through */ }, 1250);
+// Remove 'x' free solutions badge.
+if (document.querySelector('.b1if8dab')) { document.querySelector('.b1if8dab').style.display = "none"; }
+checkIfNewAccountNeeded();
-function renderBypass()
+function checkIfNewAccountNeeded()
{
- // Setup page elements
-
- //Get Katex CSS
- var katex_css = document.createElement('link');
- katex_css.setAttribute('rel','stylesheet');
- katex_css.setAttribute('href','https://cdn.jsdelivr.net/npm/katex@0.13.11/dist/katex.min.css ');
- document.head.appendChild(katex_css);
+ // Three cases: Almost out of solutions, not logged in at all, or out of solutions.
- // Get the webpage data, devoid of any headers or cookies. Acts as if the user is not logged in at all.
- doFetch(window.location).then(data => { processData(data); })
-
-}
-function processData(data){
- // Clear the "hidden explanation" out and replace it with a blank explanation area.
- // The innermost item is ".s1i7awl8"
- document.querySelector('main .mwhvwas').innerHTML = '
';
- var expArea = document.querySelector('.sladerBypass .s1i7awl8')
-
- // Render new stuff
-
- // Is this an abomination? Yes.
- // Does it work? Also yes.
- //
- // ...
- //
- // I don't want to talk about it.
- //
- var json = data.match(/(?<=window.Quizlet\["(questionDetailsPageData|textbookExercisePageData)"] = ).+?(?=; QLoad\("Quizlet.(questionDetailsPageData|textbookExercisePageData)")/gm);
- if (!json)
+ // Almost out of solutions
+ if (document.querySelector('.b1m16m5o') && document.querySelector('.b1m16m5o').textContent == "This is your last free explanation")
{
- // Display ratelimit message
- expArea.innerHTML = `You have been ratelimited by Quizlet
Try clearing your cookies for Quizlet and reloading this page, this usually fixes it.
— Slader Bypass.`;
+ signUpNewAccount(false);
}
+ // Not logged in
+ else if (document.querySelector('.t1qexa4p') && document.querySelector('.t1qexa4p').textContent == "Create a free account to see explanations")
+ {
+ signUpNewAccount(true);
+ }
+ // Out of solutions
+ else if (document.querySelector('.sukvi6d') && document.querySelector('.sukvi6d').textContent == "YOU'VE REACHED YOUR FREE LIMIT")
+ {
+ signUpNewAccount(true);
+ }
+}
- // Parse JSON data
- var qDetails = JSON.parse(json[0]);
- var solutions = (qDetails.question || qDetails.exercise).solutions;
- // Display JSON data as answer
- solutionNum = 0;
- solutions.forEach(solution => {
- solutionNum++;
- expArea.appendChild(document.createElement('hr'));
- var h1 = document.createElement('h1');
- h1.textContent = 'Solution ' + solutionNum + ":";
- expArea.appendChild(h1);
- const numSteps = solution.steps.length;
- solution.steps.forEach(step => {
- const stepNum = step.stepNumber;
- // Create card element
- var div = document.createElement('div');
- // Insert boilerplate card data
- div.innerHTML = '';
- // Step X: .s39tzu2
- div.querySelector('.s39tzu2').textContent = (numSteps === stepNum) ? "Result" : "Step " + stepNum;
- // x of x: .sb9ch1t
- div.querySelector('.sb9ch1t').textContent = stepNum + ' of ' + numSteps;
-
- // I'm not 100% on the structure of these, but I'll take a stab at it.
- // It seems that only one column is ever used. I'll iterate anyways, because I can't trust that.
- step.columns.forEach(column => {
- var columnDiv = document.createElement('div');
- // Insert inner text
- if (column.text)
- {
- var textDiv = document.createElement('div');
- textDiv.classList.add('sladerBypassKatexTextArea')
- textDiv.textContent = column.text.replaceAll('\n\n\n', '\n\n'); // The replace call is a bit funky but it works.
- columnDiv.appendChild(textDiv);
- }
- // Insert image, if applicable
- if (column.images.additional)
- {
- var image = document.createElement('img');
- image.setAttribute('src', column.images.additional.regular.srcUrl);
- columnDiv.appendChild(image);
- }
+function signUpNewAccount(doesReload)
+{
+ // We're just gonna assume this is a large enough characterspace for it to never matter.
+ var email = "sq_bypass_" + randomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
- // Append server-rendered image src url. Used in errorhandling. (See: handleKatexError())
- if (column.images.latex && column.images.latex.large)
- {
- div.querySelector('.sladerBypassKatex').setAttribute('katexsrc', column.images.latex.large.srcUrl);
- }
+ // Same thing ^
+ var username = "sq_bypass_" + randomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
- div.querySelector('.sladerBypassKatex').appendChild(columnDiv);
- });
-
- // Append card to explanation area.
- expArea.appendChild(div);
- });
- });
-
- // Render Katex for each card
- expArea.querySelectorAll('.sladerBypassKatex').forEach(textArea => {
- try {
- renderMathInElement(textArea, {
- delimiters: [
- {left: "$$", right: "$$", display: true},
- {left: "$", right: "$", display: false},
- {left: "\\(", right: "\\)", display: false},
- {left: "\\begin{equation}", right: "\\end{equation}", display: true},
- {left: "\\begin{align}", right: "\\end{align}", display: true},
- {left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
- {left: "\\begin{gather}", right: "\\end{gather}", display: true},
- {left: "\\begin{CD}", right: "\\end{CD}", display: true},
- {left: "\\[", right: "\\]", display: true}
- ],
- throwOnError : true,
- errorCallback : function(a, b){ handleKatexError(a, b, textArea); }
- });
- } catch (error) {
- console.error('Katex experienced an error. Attempting to load image replacement.');
+ var request = fetch("https://quizlet.com/webapi/3.2/direct-signup", {
+ "headers": {
+ "accept": "application/json",
+ "accept-language": "en-US,en;q=0.9",
+ "content-type": "application/json",
+ "cs-token": getToken(),
+ "sec-ch-ua": "\" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"91\", \"Chromium\";v=\"91\"",
+ "sec-ch-ua-mobile": "?0",
+ "sec-fetch-dest": "empty",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-site": "same-origin",
+ "x-requested-with": "XMLHttpRequest"
+ },
+ "referrer": "https://quizlet.com/goodbye",
+ "referrerPolicy": "origin-when-cross-origin",
+ "body": "{\"TOS\":false,\"birth_day\":\"5\",\"birth_month\":\"5\",\"birth_year\":\"2000\",\"email\":\"" + email + "@example.com\",\"is_free_teacher\":\"2\",\"is_parent\":false,\"password1\":\"SladerBypassPassword\",\"redir\":\"https://quizlet.com/goodbye\",\"signupOrigin\":\"global-header-link\",\"screenName\":\"Logout/logoutMobileSplash\",\"username\":\"" + username + "\",\"marketing_opt_out\":false}",
+ "method": "POST",
+ "mode": "cors",
+ "credentials": "include"
+ }).then(function()
+ {
+ if (doesReload)
+ {
+ location.reload();
}
});
+ return true;
};
-function handleKatexError(a, b, textArea)
-{
- // Display Katex error
- console.error(a);
- console.error(b);
+function randomString(length, chars) {
+ var result = '';
+ for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
+ return result;
+};
- // Remove broken Katex
- textArea.querySelector('.sladerBypassKatexTextArea').innerHTML = '';
-
- // Fallback to server-rendered katex (I'm assuming they have better error detection there.)
- var image = document.createElement('img');
- image.setAttribute('src', textArea.getAttribute('katexsrc'));
- textArea.appendChild(image);
-}
-
-async function doFetch(url)
-{
- const response = await fetch(url, {
- method: 'GET', // *GET, POST, PUT, DELETE, etc.
- mode: 'cors', // no-cors, *cors, same-origin
- cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
- credentials: 'omit', // include, *same-origin, omit
- headers: {
- },
- redirect: 'follow', // manual, *follow, error
- referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
- body: null // body data type must match "Content-Type" header
- });
- return response.text();
-}
\ No newline at end of file
+function getToken(){
+ token = document.cookie.match("(?:^|;)\\s*" + "qtkn".replace(/[\-\[\]{}()*+?.,\\^$|#\s]/g, "$&") + "=([^;]*)");
+ return decodeURIComponent(token[1]);
+};
\ No newline at end of file