I think it’s possibly a little broken again
1 Like
Try this:
// ==UserScript==
// @name WK Auto Commit (09.01.25)
// @namespace WKAUTOCOMMIT
// @version 0.4.8-fixed-fast-2
// @description Auto submits on exact accepted answer match (incl. user synonyms) and advances ASAP.
// @author Johannes Mikulasch (original) + patch
// @match https://www.wanikani.com/subjects/*
// @match https://www.wanikani.com/subject-lessons/*
// @match https://www.wanikani.com/review/*
// @match https://www.wanikani.com/lesson/*
// @match https://www.wanikani.com/lessons/*
// @match https://www.wanikani.com/reviews/*
// @match https://www.wanikani.com/*
// @grant none
// @run-at document-end
// ==/UserScript==
'use strict';
let activated = true, expected = [], synonyms = {}, bound = false, nextTimer = null;
const q = (s) => document.querySelector(s);
const input = () => q('#user-response');
const btn = () => q('.quiz-input__submit-button');
const lightning = () => !!q('.doublecheck-active');
const s = (v) => (v == null ? '' : String(v).replace(/\s/g, '').toLowerCase());
const toggle = () => {
const b = q('#WKAUTOCOMMIT_button'); if (!b) return;
activated = !activated;
b.style.opacity = activated ? 1 : 0.5;
b.textContent = activated ? 'Auto Commit is on' : 'Auto Commit is off';
b.title = activated ? 'Switch auto commit off' : 'Switch auto commit on';
};
const addBtn = () => {
if (q('#WKAUTOCOMMIT_button')) return;
const f = q('.quiz-footer'); if (!f) return;
const d = document.createElement('div');
d.id = 'WKAUTOCOMMIT_button';
d.textContent = 'Auto Commit is on';
d.title = 'Toggle Auto Commit Mode';
d.onclick = toggle;
Object.assign(d.style, {
backgroundColor: '#C55', opacity: 1, display: 'inline-block', fontSize: '0.8125em',
color: '#FFF', cursor: 'pointer', padding: '10px', marginLeft: '10px', verticalAlign: 'bottom'
});
f.appendChild(d);
};
const loadSyn = () => {
if (loadSyn.loaded) return;
const t = q('script[data-quiz-user-synonyms-target]'); if (!t) return;
try { synonyms = JSON.parse(t.innerHTML); loadSyn.loaded = true; } catch {}
};
window.addEventListener('didUpdateUserSynonyms', (e) => {
if (e?.detail) synonyms[e.detail.subjectId] = e.detail.synonyms;
});
const isAdvanceReady = (b) => {
if (!b) return false;
if (b.disabled || b.getAttribute('aria-disabled') === 'true') return false;
const t = (b.textContent || '').trim().toLowerCase();
if (t.includes('next') || t.includes('continue')) return true;
if (t && (t.includes('submit') || t.includes('answer') || t.includes('check'))) return false;
return true;
};
const clickNextASAP = () => {
if (nextTimer) return;
const start = performance.now(), maxWait = 700, interval = 10;
nextTimer = setInterval(() => {
const b = btn(); if (!b) return;
if (isAdvanceReady(b) || performance.now() - start > maxWait) {
clearInterval(nextTimer); nextTimer = null; b.click();
}
}, interval);
};
const commit = () => {
if (!commit.usable) return;
const b = btn(); if (!b) return;
commit.usable = false;
b.click();
if (!lightning()) clickNextASAP();
};
const check = () => {
const i = input(); if (!i) return;
const cur = s(i.value);
for (let k = 0; k < expected.length; k++) if (cur === s(expected[k])) { commit(); break; }
};
const bind = () => {
const i = input(); if (!i || bound) return;
i.addEventListener('keyup', () => { if (activated) check(); }, { capture: true });
bound = true;
};
window.addEventListener('willShowNextQuestion', (e) => {
bound = false;
if (nextTimer) { clearInterval(nextTimer); nextTimer = null; }
bind(); addBtn(); loadSyn();
expected = [];
const item = e?.detail, subj = item?.subject;
if (!subj) { commit.usable = true; return; }
const ok = ['alternative', 'primary', 'allowed'];
if (item.questionType === 'meaning') {
if (Array.isArray(subj.meanings)) expected = expected.concat(subj.meanings.filter(x => x && ok.includes(x.kind)).map(x => x.text));
const syn = (subj.id in synonyms) ? synonyms[subj.id] : [];
if (Array.isArray(syn)) expected = expected.concat(syn);
} else if (item.questionType === 'reading') {
if (Array.isArray(subj.readings)) expected = expected.concat(
subj.readings
.filter(x => x && ok.includes(x.kind) && (String(subj.type).toLowerCase() !== 'kanji' || subj.primary_reading_type === x.type))
.map(x => x.text)
);
}
commit.usable = true;
});
(() => console.log('WK Auto Commit: Initialized'))();
1 Like