Quizlet Learn Auto Answer

Automatically detects and answers every question in Quizlet Learn mode in real time. Highlights the correct answer in green for multiple choice questions and auto-fills and submits written questions instantly.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Quizlet Learn Auto Answer
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Automatically detects and answers every question in Quizlet Learn mode in real time. Highlights the correct answer in green for multiple choice questions and auto-fills and submits written questions instantly.
// @author       apzn
// @license      MIT
// @match        https://quizlet.com/*
// @grant        unsafeWindow
// @run-at       document-idle
// ==/UserScript==

const win = unsafeWindow;

const observer = new MutationObserver(() => {
    if (win.document.querySelector('article')) {
        observer.disconnect();
        setInterval(() => {
            try {
                const element = win.document.querySelector('article');
                if (!element) return;

                const fiberKey = Object.keys(element).find(k => k.startsWith('__reactFiber$'));
                if (!fiberKey) return;

                let node = element[fiberKey];
                let question = null;
                while (node) {
                    if (node.memoizedProps?.question?.type) {
                        question = node.memoizedProps.question;
                        break;
                    }
                    node = node.return;
                }
                if (!question) return;

                if (question.type === 'MultipleChoiceQuestion') {
                    const answerIndex = question.metadata.optionGenerationSource.findIndex(k => k === 'key');
                    const container = win.document.querySelector('[data-testid="MCQ Answers"]');
                    if (!container) return;

                    const wrapper = container.children[answerIndex];
                    if (!wrapper) return;

                    const answerText = wrapper.querySelector('section > :nth-child(2)');
                    if (answerText && answerText.style.color === 'lime') return;

                    [...container.children].forEach(child => {
                        const sec = child.querySelector('section > :nth-child(2)');
                        if (sec) sec.style.color = '';
                    });
                    if (answerText) answerText.style.color = 'lime';

                    const section = wrapper.querySelector('section') || wrapper;
                    if (section) {
                        const rect = section.getBoundingClientRect();
                        section.dispatchEvent(new PointerEvent('pointerdown', { bubbles: true, clientX: rect.x + 10, clientY: rect.y + 10 }));
                        section.dispatchEvent(new PointerEvent('pointerup', { bubbles: true, clientX: rect.x + 10, clientY: rect.y + 10 }));
                        section.dispatchEvent(new MouseEvent('click', { bubbles: true, clientX: rect.x + 10, clientY: rect.y + 10 }));
                    }

                } else if (question.type === 'WrittenQuestion') {
                    if (typeof win.__NEXT_DATA__ === 'undefined') return;
                    const allCards = win.__NEXT_DATA__.props.pageProps.studyModesCommon.studiableDocumentData.studiableItems;
                    const card = allCards.find(c => c.id === question.metadata.studiableItemId);
                    if (!card) return;
                    const otherSide = card.cardSides[question.metadata.answerSide === 'definition' ? 1 : 0];
                    const answer = otherSide.media[0].plainText;

                    const existing = win.document.querySelector('#x-answer');
                    if (existing) existing.innerText = `correct answer: ${answer}`;
                    else {
                        const form = win.document.querySelector('form');
                        if (form) form.parentElement.insertAdjacentHTML('afterbegin', `<p style="color:lime;padding-bottom:10px;" id="x-answer">correct answer: ${answer}</p>`);
                    }

                    const input = win.document.querySelector('form input, form textarea');
                    if (input && input.value !== answer) {
                        const setter = Object.getOwnPropertyDescriptor(win.HTMLInputElement.prototype, 'value')?.set
                            || Object.getOwnPropertyDescriptor(win.HTMLTextAreaElement.prototype, 'value')?.set;
                        setter.call(input, answer);
                        input.dispatchEvent(new Event('input', { bubbles: true }));
                        setTimeout(() => {
                            const form = win.document.querySelector('form');
                            if (form) form.dispatchEvent(new Event('submit', { bubbles: true }));
                            const btn = win.document.querySelector('form button[type="submit"], form button');
                            if (btn) btn.click();
                        }, 300);
                    }
                }
            } catch(e) { console.log('Script error:', e.message); }
        }, 100);
    }
});

observer.observe(win.document.body, { childList: true, subtree: true });