Merge pull request #17 from EthanHarv/main

Auto-account.
This commit is contained in:
Alan Li 2021-08-03 11:04:29 +08:00 committed by GitHub
commit 4c5a71149a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 18252 deletions

View file

@ -7,6 +7,12 @@
- Firefox : 90.0 - Firefox : 90.0
- Test time : 2021/07/14 - Test time : 2021/07/14
# WARNING:
This extension logs you out of your normal quizlet account.
You can disable and re-enable it by going to `chrome://extensions/` on chrome and `about:addons` in firefox.
# Screenshot # Screenshot
## Before install ## Before install

View file

@ -1 +0,0 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={974:function(t){t.exports=e}},r={};function n(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(974),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n<t.length;){var o=t[n];if(a<=0&&t.slice(n,n+i)===e)return n;"\\"===o?n++:"{"===o?a++:"}"===o&&a--,n++}return-1},i=/^\\begin{/,o=function(e,t){for(var n,a=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i<n.length;i++)if("text"===n[i].type)a.appendChild(document.createTextNode(n[i].data));else{var l=document.createElement("span"),d=n[i].data;r.displayMode=n[i].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[i].data+"` with ",e),a.appendChild(document.createTextNode(n[i].rawData));continue}a.appendChild(l)}return a},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var a=t.childNodes[n];if(3===a.nodeType){var i=l(a.textContent,r);i&&(n+=i.childNodes.length-1,t.replaceChild(i,a))}else 1===a.nodeType&&function(){var t=" "+a.className+" ";-1===r.ignoredTags.indexOf(a.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(a,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),a=a.default}()}));

File diff suppressed because it is too large Load diff

View file

@ -1,161 +1,115 @@
// TODO: Sidestep race condition in a less patchwork manner // Remove 'x' free solutions badge and "verify your email" badge.
setTimeout(function(){ renderBypass(); /* TODO: Check if it actually went through */ }, 1250); if (document.querySelector('.BannerWrapper')) { document.querySelector('.BannerWrapper').style.display = "none"; }
if (document.querySelector('.UINotification')) { document.querySelector('.UINotification').style.display = "none"; }
checkIfNewAccountNeeded();
function renderBypass() function checkIfNewAccountNeeded()
{ {
// Setup page elements // Three cases: Almost out of solutions, not logged in at all, or out of solutions.
//Get Katex CSS // Almost out of solutions
var katex_css = document.createElement('link'); if (pageContains("This is your last free explanation"))
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);
// 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 = '<div class="c18oith1 sladerBypass"><div class="s1oluvjw"><h4 class="h1cwp1lk">Explanation</h4><div class="as7m9cv snqbbas"><div data-testid="ExplanationsSolution" class="e1sw891e"><div class="s1i7awl8"></div></div></div></div></div>';
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)
{ {
// Display ratelimit message // Don't reload, not actually out of solutions yet.
expArea.innerHTML = `<div style="color: red;"><h1>You have been ratelimited by Quizlet</h1><br>Try clearing your cookies for Quizlet and reloading this page, this usually fixes it.<br>— Slader Bypass.</div>`; signUpNewAccount(false);
}
// Not logged in
else if (pageContains("Create a free account to see explanations"))
{
signUpNewAccount(true);
}
// Out of solutions
else if (pageContains("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; // Catchall for logged out entirely.
solution.steps.forEach(step => { else if (!isLoggedIn())
const stepNum = step.stepNumber; {
// Create card element signUpNewAccount(true);
var div = document.createElement('div'); }
// Insert boilerplate card data // Catchall for out of solutions
div.innerHTML = '<div class="r8gl7vf" data-testid="ExplanationsSolutionStep" style="padding-top: 0.8rem;"><div class="AssemblyCard AssemblyMediumCard"><div class="ExplanationsSolutionCard c5ngj6s"><div class="h1ejaztj"><h4 class="s39tzu2"></h4><span class="sb9ch1t"></span></div><div class="s1wwu7g8"><div class="s1x7f4sz"><div class=""><div class="s1xkd811"><div class="mi4ni5d sladerBypassKatex" style="white-space: pre-wrap;"></div></div></div></div></div></div></div></div>'; else if (pageContains('source=explanations_meter_exceeded'))
// Step X: .s39tzu2 {
div.querySelector('.s39tzu2').textContent = (numSteps === stepNum) ? "Result" : "Step " + stepNum; signUpNewAccount(true);
// 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. function signUpNewAccount(doesReload)
// It seems that only one column is ever used. I'll iterate anyways, because I can't trust that. {
step.columns.forEach(column => { // We're just gonna assume this is a large enough characterspace for it to never matter.
var columnDiv = document.createElement('div'); var name = "sq_bypass_" + randomString(10, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
// 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);
}
// 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);
}
// handle hasInvalidKatex var request = fetch("https://quizlet.com/webapi/3.2/direct-signup", {
if(column.hasInvalidKatex) "headers": {
div.querySelector('.sladerBypassKatex').setAttribute('InvalidKatex', "true"); "accept": "application/json",
"accept-language": "en-US,en;q=0.9",
div.querySelector('.sladerBypassKatex').appendChild(columnDiv); "content-type": "application/json",
}); "cs-token": getToken(),
"sec-ch-ua": "\" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"91\", \"Chromium\";v=\"91\"",
// Append card to explanation area. "sec-ch-ua-mobile": "?0",
expArea.appendChild(div); "sec-fetch-dest": "empty",
}); "sec-fetch-mode": "cors",
}); "sec-fetch-site": "same-origin",
"x-requested-with": "XMLHttpRequest"
// Render Katex for each card },
expArea.querySelectorAll('.sladerBypassKatex').forEach(textArea => { "referrer": "https://quizlet.com/goodbye",
try { "referrerPolicy": "origin-when-cross-origin",
if(!textArea.hasAttribute("InvalidKatex")){ "body": "{\"TOS\":false,\"birth_day\":\"5\",\"birth_month\":\"5\",\"birth_year\":\"2000\",\"email\":\"" + name + "@example.com\",\"is_free_teacher\":\"2\",\"is_parent\":false,\"password1\":\"SladerBypassPassword\",\"redir\":\"https://quizlet.com/goodbye\",\"signupOrigin\":\"global-header-link\",\"screenName\":\"Logout/logoutMobileSplash\",\"username\":\"" + name + "\",\"marketing_opt_out\":false}",
renderMathInElement(textArea, { "method": "POST",
delimiters: [ "mode": "cors",
{left: "$$", right: "$$", display: true}, "credentials": "include"
{left: "$", right: "$", display: false}, }).then(function()
{left: "\\(", right: "\\)", display: false}, {
{left: "\\begin{equation}", right: "\\end{equation}", display: true}, if (doesReload)
{left: "\\begin{align}", right: "\\end{align}", display: true}, {
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true}, location.reload();
{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); }
});
}
else{
// sometimes even hasInvalidKatex, textArea still can render without error
handleKatexError("hasInvalidKatex","hasInvalidKatex", textArea);
}
} catch (error) {
console.error('Katex experienced an error. Attempting to load image replacement.');
} }
}); });
return true;
}; };
function handleKatexError(a, b, textArea) function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
};
function getToken(){
token = document.cookie.match("(?:^|;)\\s*" + "qtkn".replace(/[\-\[\]{}()*+?.,\\^$|#\s]/g, "$&") + "=([^;]*)");
return decodeURIComponent(token[1]);
};
function pageContains(str)
{ {
// Display Katex error if (document.body.innerHTML.match(str))
console.error(a); {
console.error(b); return true;
}
// Remove broken Katex else
textArea.querySelector('.sladerBypassKatexTextArea').innerHTML = ''; {
return false;
// 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) function isLoggedIn()
{ {
const response = await fetch(url, { // Looks for `{"LOGGED_IN":false,` in the header.
method: 'GET', // *GET, POST, PUT, DELETE, etc. var li = document.head.innerHTML.match(/(?<="LOGGED_IN":)\w[^,]*/)[0];
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached if (li === "false")
credentials: 'omit', // include, *same-origin, omit {
headers: { return false;
}, }
redirect: 'follow', // manual, *follow, error else if (li === "true")
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 true;
}); }
return response.text(); else
{
return true; // Return true on possible error to prevent explosion of accounts. Effectively assumes logged in on error.
}
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "slader bypass", "name": "slader bypass",
"version": "0.8", "version": "0.10",
"author":"Alan Li & Ethan Harvey", "author":"Alan Li & Ethan Harvey",
"description": "Slader/Quizlet 5 solutions limit bypass", "description": "Slader/Quizlet 5 solutions limit bypass",
"permissions": [ "permissions": [
@ -21,7 +21,7 @@
}, },
{ {
"matches": ["*://quizlet.com/explanations/questions/*", "*://quizlet.com/explanations/textbook-solutions/*/*"], "matches": ["*://quizlet.com/explanations/questions/*", "*://quizlet.com/explanations/textbook-solutions/*/*"],
"js": ["js/katex/katex.js", "js/katex/autorender.js", "js/quizlet_bypass.js"] "js": ["js/quizlet_bypass.js"]
} }
], ],
"manifest_version": 2 "manifest_version": 2

BIN
slader_bypass-0.10-fx.xpi Normal file

Binary file not shown.

Binary file not shown.