Vocabulary.com Answer Bot

The more questions you answer the smarter it will get. Features: spelling-assistance & auto - complete, definitions and examples, actively learning bot.

Install this script?
Author's suggested script

You may also like Quillbot Premium Unlocker.

Install this script
// ==UserScript==
// @name         Vocabulary.com Answer Bot
// @namespace    http://tampermonkey.net/
// @version      3.01
// @description  The more questions you answer the smarter it will get. Features: spelling-assistance & auto - complete, definitions and examples, actively learning bot.
// @author       longkidkoolstar
// @match        https://www.vocabulary.com/*
// @icon         https://cdn1.iconfinder.com/data/icons/network-and-comminications-flat-square-rounded-sha/120/content__blog__media__articles__news__management__edit-512.png
// @license      MIT
// @grant        none
// ==/UserScript==

let url = window.location.href,list=url.split("/")[4],words_defs,lists,learned=[],incorrect=[],inProgress=false;
if(localStorage.getItem("lists")!==null){lists = JSON.parse(localStorage.getItem("lists"))}
else{lists = []}if(localStorage.getItem("words&defs")!==null){words_defs = JSON.parse(localStorage.getItem("words&defs"))}
else{words_defs = []}if(localStorage.getItem("learned")!==null){learned = JSON.parse(localStorage.getItem("learned"))}
if(localStorage.getItem("wrong")!==null){incorrect = JSON.parse(localStorage.getItem("wrong"))}
let dictionary = "https://api.dictionaryapi.dev/api/v2/entries/en/";

//console.log(list,lists,partsOfList(list,"words"),partsOfList(list,"defs"))

if(!url.includes("/practice")){
    setInterval(function(){
        if(document.getElementsByClassName("activity practice")[0]!==undefined){
            let practice = document.getElementsByClassName("activity practice")[0];
            if(!lists.includes(list)){
                practice.addEventListener("click",function(){
                    let enteries = document.getElementsByClassName("entry");
                    for(let i=0;i<enteries.length;i++){
                        let word = enteries[i].children[0].innerText.trim();
                        let def = enteries[i].children[1].innerText.trim();
                        words_defs.push({"word":word,"def":def,"list":list});
                        if(enteries.length-1==i){
                            localStorage.setItem("words&defs",JSON.stringify(words_defs));
                            lists.push(list);
                            localStorage.setItem("lists",JSON.stringify(lists));
                        }
                    }
                })
            }
            if(list.trim().length>0){
                practice.click();
            }
        }
    },1000)
}
else if(url.includes("/practice")){
    setTimeout(function(){
        if(!lists.includes(list)){
            location.href=url.split("/practice")[0];
        }
        else{
            bot()
        }
    },250)
}

if(url.includes("/play/")){
    bot();
}

function bot(){
    let bot = setInterval(function(){
        if(document.getElementsByClassName("challenge-history")[0].children[1].children!==undefined&&inProgress!==true){
            let arr = document.getElementsByClassName("challenge-history")[0].children[1].children;
            let currQuest = getQuest(arr);
            if(currQuest!==false){
                let questIndx = Number(currQuest.innerText-1)
                let questBox = document.getElementsByClassName("question")[questIndx];
                let quest_Type = questType(questBox);
                let nxt = document.getElementsByClassName("next")[0];
                if(quest_Type!==false){
                    inProgress = true;
                    if(quest_Type=="spell"){
                        answerSpelling(questBox,questIndx);
                    }
                    if(quest_Type=="choice1"){
                        answerMultChoice(questBox);
                    }
                    if(quest_Type=="choice2"){
                        answerMultChoice(questBox,2);
                    }
                }
                else{
                    console.log("Question type doesn't exist 🤨");
                    inProgress=false;
                }
                nxt.addEventListener("click",function(){
                    inProgress=false;
                    //console.log("inProgress = false!")
                })
            }
        }
    },500)
    }

setInterval(()=>{
    makeRoom();
    if(document.getElementsByClassName("next active")[0]!==undefined){
        document.getElementsByClassName("next active")[0].click();
    }
},250)

function makeRoom(){
    if(document.getElementsByClassName("vcom-challenge resizable large started")[0]!==undefined){
        document.getElementsByClassName("vcom-challenge resizable large started")[0].style.minHeight="2500px";
    }
}

function questType(quest){
    let type=false;
    let children = quest.children;
    for(let i=0;i<children.length;i++){
        if(children[i].className=="spelltheword"){
            type = "spell"
        }
        if(children[i].className=="choices"){
            if(children[1].childElementCount>0){
                type= "choice1";
            }
            else if(children[1].childElementCount==0){
                type="choice2";
            }
        }
    }
    console.log(type)
    return type;
}

function getQuest(arr){
    let result=false;
    for(let i=0;i<arr.length;i++){
        if(arr[i].classList[0]=="enabled"&&arr[i].classList[1]=="selected"&&arr[i].classList.value=="enabled selected"){
            result = arr[i];
        }
    }
    return result;
}


function partsOfList(listId,part){
    let words = [];
    let defs = [];
    let examples = [];
    for(let i=0;i<words_defs.length;i++){
        if(words_defs[i].list==listId){
            if(!words.includes(words_defs[i].word)){
                words.push(words_defs[i].word)
            }
            defs.push(words_defs[i].def);
            if(!examples.includes(words_defs[i].example)){
                examples.push(words_defs[i].example)
            }
        }
        if(words_defs.length-1==i){
            if(part=="words"){
                return words;
            }
            if(part=="defs"){
                return defs;
            }
            if(part=="examples"){
                return examples;
            }
        }
    }
}

function getChoices(arr){
    let temp=[];
    for(let i=0;i<arr.length;i++){
        temp.push(arr[i].innerText);
    }
    return temp;
}

function learn(word,choice,def){
    let present=false;
    for(let i=0;i<learned.length;i++){
        if(learned[i].word==word&&learned[i].choice==choice){
            present=true;
            console.log(`${word} is known 💡`)
        }
    }
    if(!present){
        learned.push({"word":word,"choice":choice});
        if(choice.split(" ").length==1){
            learned.push({"word":choice,"choice":def});
        }
        localStorage.setItem("learned",JSON.stringify(learned))
        console.log(`Learned ${word} 🧠`)
    }
    inProgress=false;
}

function getDef(word){
    let def = false;
    let words = partsOfList(list,"words");
    let defs = partsOfList(list,"defs");
    for(let i=0;i<words.length;i++){
        if(words[i].includes(word)||word.includes(words[i])){
            def = defs[i];
        }
    }
    return def;
}

function defineChoices(word,arr){
    for(let i=0;i<arr.length;i++){
        if(arr[i].innerText.split(" ").length==1){
            let def = getDef(arr[i].innerText);
            if(def!==false){
                arr[i].innerText += `: ${getDef(arr[i].innerText)} - (answer?)`;
                arr[i].style.color = "orange";
                arr[i].innerText+=" 🧠"
                clean(word,arr)
            }
        }
    }
}

function answerMultChoice(questBox,clause){
    let word,choiceBox,choices;
    if(clause==2){
        let chil = questBox.children[2].children;
        if(chil.length>1){
            for(let i=0;i<chil.length;i++){
                if(chil[i].tagName=="STRONG"){
                    word = chil[i].innerText
                }
            }
        }
        else{
            word = questBox.children[2].children[0].innerText;
        }
    }
    else if(clause==undefined){
        word = questBox.children[1].children[0].children[0].innerText;
    }
    choiceBox = questBox.children[3].children;
    choices = getChoices(choiceBox);
    defineChoices(word,choiceBox)
    let instruct = questBox.children[2];
    let words = partsOfList(list,"words");
    let defs = partsOfList(list,"defs");
    let def=false;
    deepSearch(word,questBox);
    //deepDef(word,choices,choiceBox);
    def = getDef(word);
    defAllChoices(choices,choiceBox,def)
    maybe(choices,choiceBox)
    if(def!==false){
        let answr = false;
        for(let i=0;i<choices.length;i++){
            if(choices[i].includes(def)||def.includes(choices[i])){
                answr = i;
            }
        }
        if(answr!==false){
            choiceBox[answr].style.color="springgreen";
            choiceBox[answr].innerText+=" 🧠"
            clean(word,choiceBox)
        }
        else{
            answr=false;
            if(learned.length>0){
                for(let i=0;i<learned.length;i++){
                    for(let j=0;j<choiceBox.length;j++){
                        if(learned[i].word.includes(word)||choiceBox[j].innerText.includes(learned[i].choice)||learned[i].choice.includes(choiceBox[j].innerText)||word.includes(learned[i].word)){
                            answr = learned[i].choice;
                        }
                    }
                }
            }
            if(answr!==false){
                for(let i=0;i<choices.length;i++){
                    if(choices[i].includes(answr)||answr.includes(choices[i])){
                        choiceBox[i].style.color="springgreen";
                        choiceBox[i].innerText+=" 🧠"
                        clean(word,choiceBox)
                    }
                }
            }
            else{
                //console.log("No answer found - normal way");
            }
        }
    }
    for(let i=0;i<choiceBox.length;i++){
        choiceBox[i].addEventListener("click",function(){
            setTimeout(function(){
                grabChoice(word,choiceBox,def);
            },250)
        })
    }
}


function grabChoice(word,choices,def){
    let correct = false;
    for(let i=0;i<choices.length;i++){
        if(choices[i].className=="correct"){
            learn(word,choices[i].innerText,def);
            correct = true;
        }
        if(correct){
            if(choices[i].className!=="correct"){
                wrong(word,choices[i].innerText)
            }
        }
        else{
            if(choices[i].className=="incorrect"){
                wrong(word,choices[i].innerText);
            }
        }
    }
}


function clean(word,choices){
    for(let j=0;j<choices.length;j++){
        for(let i=0;i<incorrect.length;i++){
            if(incorrect[i].word==word&&incorrect[i].choice==choices[j].innerText){
                choices[j].style.color="red";
            }
        }
    }
}

function wrong(word,choice){
    let present=false;
    for(let i=0;i<incorrect.length;i++){
        if(incorrect[i].word==word&&incorrect[i].choice==choice){
            present=true;
            console.log(`${word}'s choice is known as incorrect ❌`);
        }
    }
    if(!present){
        incorrect.push({"word":word,"choice":choice});
        localStorage.setItem("wrong",JSON.stringify(incorrect))
        console.log(`Learned ${word}'s incorrect choice 🧠`)
    }
    inProgress=false;
}

async function deepSearch(word,questBox){
    try{
        let api=`https://vocabulary.now.sh/words/${word}`;
        let api2=`https://vocabulary.now.sh/word/${word}`;
        let result=await fetch(api).then(data => data.json()).then(data => data.data[0]);
        let example=await fetch(api2).then(data => data.json()).then(data => data.data);
        let def = await result.description;
        let choiceBox = questBox.children[3].children;
        let choices = getChoices(questBox.children[3].children);
        let instruct = questBox.children[2];
        let content = questBox.children[1];
        let answr=false;
        for(let i=0;i<choices.length;i++){
            if(choices[i].includes(example)||choices[i].includes(def)||def.includes(choices[i])||example.includes(choices[i])){
                answr=i;
            }
        }
        if(answr!==false){
            choiceBox[answr].style.color="springgreen";
            choiceBox[answr].innerText+=" 🧠"
        }
        else{
            //console.log("DeepSearch failed. Will add correct answer to dataSet when answered. 🤔");
        }
        if(getDef(word)!==false){
            let set = false;
            let rep = false;
            if(content.children.length>0){
                rep = content;
            }
            if(instruct.children.length>0){
                rep = instruct;
            }
            if(rep!==false){
                if(!set){
                    set = true;
                    rep.style.overflowY="auto";
                    rep.style.height="fit-content";
                    rep.innerHTML+=`<hr><div style="margin-top:50px;"><b style="color:black;">${word}</b> means: ${getDef(word)} 🧠 <br><br> <span style="font-size:18px; margin-bottom:10px;"><b style="color:black;">Example:</b> ${example}</span></div><br>`;
                    questBox.style.marginTop="-45px";

                }
            }
        }
        for(let i=0;i<choices.length;i++){
            if(similarity(choices[i],def)||similarity(choices[i],example)/*||similar(def,choices[i])||similar(example,choices[i])*/){
                choiceBox[i].style.color="springgreen";
                choiceBox[i].innerText+=" 🧠"
            }
        }
    }
    catch(e){
        return false;
    }
}

function maybe(choices,choiceBox){
    for(let i=0;i<choices.length;i++){
        for(let j=0;j<learned.length;j++){
            if(choices[i].toLowerCase().includes(learned[j].word.toLowerCase())||learned[j].word.toLowerCase().includes(choices[i].toLowerCase())){
                if(!choiceBox[i].innerText.includes(" - maybe this...")){
                    choiceBox[i].innerText+=" - maybe this...";
                    choiceBox[i].style.color="orange";
                }
            }
        }
    }
}

function cleanUp(choices){
    for(let i=0;i<choices.length;i++){
        choices[i].style.color="#36588e";
    }
}

function answerSpelling(questBox,indx){
    let inp = questBox.children[1].children[1].children[1];
    let submit = questBox.children[1].children[2].children[0];
    let surrender = questBox.children[1].children[2].children[1];
    let status = document.getElementsByClassName("status")[indx];
    let speak = questBox.children[1].children[1].children[0];
    let label = questBox.children[1].children[0];
    let words = partsOfList(list,"words");
    speak.click();
    function auto(matches){
        inp.value=matches[0];
        inp.blur();
        setTimeout(function(){
            submit.click();
            inProgress = false;
        },350)
    }
    inp.addEventListener("keyup",function(evt){
        if(inp.value.trim().length>0){
            label.innerText = "Spell the word:";
            let input = inp.value;
            let matches=[];
            for(let i=0;i<words.length;i++){
                if(words[i].toLowerCase().includes(input.toLowerCase())||input.toLowerCase().includes(words[i].toLowerCase())){
                    matches.push(words[i]);
                }
            }
            if(matches.length>0){
                label.innerText = "Matches 😉:"
                let newLabel = document.createElement("div");
                label.append(newLabel);
                let max = 5;
                if(matches.length<5){
                    max = matches.length;
                }
                for(let i=0;i<max;i++){
                    newLabel.style="width:100%;height:fit-content;display:flex;align-items:center;justify-content:center;flex-direction:row;overflow:hidden;"
                    newLabel.innerHTML+=` <p style="cursor:pointer;margin:5px;" class = "spellGuess">${matches[i]}</p>`;
                    let guesses = document.getElementsByClassName("spellGuess");
                    for(let i=0;i<guesses.length;i++){
                        guesses[i].addEventListener("click",()=>{
                            inp.value = guesses[i].innerText;
                            setTimeout(()=>{
                                submit.click();
                                inProgress = false;
                            },350)
                        })
                    }
                }
                if(matches.length==1){
                    let auto_do = true;
                    if(status.children.length>0){
                        if(status.children[0].innerText.includes("again")){
                            auto_do = false;
                        }
                    }
                    if(auto_do){
                        auto(matches);
                    }
                }
            }
            else{
                label.innerText = "No matches 😟";
            }
        }
        else{
            label.innerText = "Spell the word:";
        }
    })
    inp.addEventListener("keydown",function(evt){
        if(evt.keyCode==13){
            if(inp.value.trim().length>0){
                inProgress=false;
            }
        }
    })
    submit.addEventListener("click",function(){
        inProgress=false;
    })
}



function similarity(s1, s2) {
    var longer = s1;
    var shorter = s2;
    if (s1.length < s2.length) {
        longer = s2;
        shorter = s1;
    }
    var longerLength = longer.length;
    if (longerLength == 0) {
        return 1.0;
    }
    if((longerLength - editDistance(longer, shorter)) / parseFloat(longerLength)>0.5){
        return true;
    }
}
function editDistance(s1, s2) {
    s1 = s1.toLowerCase();
    s2 = s2.toLowerCase();

    var costs = new Array();
    for (var i = 0; i <= s1.length; i++) {
        var lastValue = i;
        for (var j = 0; j <= s2.length; j++) {
            if (i == 0)
                costs[j] = j;
            else {
                if (j > 0) {
                    var newValue = costs[j - 1];
                    if (s1.charAt(i - 1) != s2.charAt(j - 1))
                        newValue = Math.min(Math.min(newValue, lastValue),
                                            costs[j]) + 1;
                    costs[j - 1] = lastValue;
                    lastValue = newValue;
                }
            }
        }
        if (i > 0)
            costs[s2.length] = lastValue;
    }
    return costs[s2.length];
}

function similar(phrase,choice){
    let simScore1 = 0;
    let simScore2 = 0;
    phrase = cleanPunc(phrase).split(" ");
    choice = cleanPunc(choice).split(" ");
    for(let i=0;i<phrase.length;i++){
        for(let j=0;j<choice.length;j++){
            if(phrase[i].includes(choice[j])||choice[j].includes(phrase[i])){
                return true;
            }
        }
    }
    return false;
}

function cleanPunc(string){
    return string.replace(/[^A-Za-z0-9\s]/g,"").replace(/\s{2,}/g, " ");
}

/*
async function deepDef(word,choices,choiceBox){
    try{
        let api = dictionary+word;
        let dets = await fetch(api).then(data => data.json()).then(data=>data[0].meanings[0].definitions[0]);
        let synms = dets.synonyms;
        let antms = dets.antonyms;
        let def = dets.definition;
        for(let i=0;i<choices.length;i++){
            for(let j=0;j<synms.length;j++){
                if(choices[i].includes(synms[j])||synms[j].includes(choices[i])){
                    choiceBox[i].style.color="springgreen";
                    choiceBox[i].innerText+=" 🧠"
                }
            }
        }
    }
    catch(error){
        console.log("Can't find synonyms for this one. Not a big problem, I have other ways of dealing with this 😊")
    }
}
*/

async function defAllChoices(choices,choiceBox,def){
    for(let i=0;i<choices.length;i++){
        if(choices[i].split(" ").length==1){
            let api = dictionary+choices[i];
            let defs = await fetch(api).then(data => data.json()).then(data=>data[0].meanings[0].definitions);
            let temp=[];
            for(let j=0;j<defs.length;j++){
                if(defs[j]!==undefined){
                    temp.push(defs[j].definition);
                }
            }
            for(let x=0;x<temp.length;x++){
                choiceBox[i].innerText+=` - ${temp[x]}`;
            }
        }
    }
}