// ==UserScript== // @name WordSleuth // @namespace https://greasyfork.org/en/users/1084087-kueldev // @version 0.3.1 // @description A script that helps you guess words in skribblio // @author kueldev // @match http*://www.skribbl.io/* // @match http*://skribbl.io/* // @icon https://www.google.com/s2/favicons?sz=64&domain=skribbl.io // @grant GM_setValue // @grant GM_getValue // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; let correctAnswers = GM_getValue('correctAnswers', []); const guessElem = createGuessElement(); let possibleWords = []; let wordList = []; // Initialize all wordlists fetchWords('https://raw.githubusercontent.com/arstgit/high-frequency-vocabulary/master/30k.txt').then(words => { words.forEach(word => { if (!wordList.includes(word)) { wordList.push(word); } }); observeHints(); observeInput(); }); fetchWords('https://raw.githubusercontent.com/kuel27/wordlist/main/wordlist.txt').then(words => { words.forEach(word => { if (!correctAnswers.includes(word)) { correctAnswers.push(word); } }); }); correctAnswers.forEach(answer => { if (!wordList.includes(answer)) { wordList.push(answer); } }); function fetchWords(url) { return fetch(url) .then(response => response.text()) .then(data => data.split('\n').map(word => word.trim())); } function observeHints() { const targetNodes = [ document.querySelector('.hints .container'), document.querySelector('.words'), document.querySelector('#game-word'), ]; const config = { childList: true, subtree: true }; const callback = function(mutationsList, observer) { const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]'); if (inputElem.value) return; for (let mutation of mutationsList) { if (mutation.type === 'childList') { checkIfAllHintsRevealed(); checkWordsElement(); generateGuesses(); } } }; const observer = new MutationObserver(callback); targetNodes.forEach(targetNode => { if (targetNode) { observer.observe(targetNode, config); } }); } function checkIfAllHintsRevealed() { const hintElems = Array.from(document.querySelectorAll('.hints .hint')); if (hintElems.every(elem => elem.classList.contains('uncover'))) { const correctAnswer = hintElems.map(elem => elem.textContent).join('').trim().toLowerCase(); if (!correctAnswer) { return; } if (!correctAnswers.includes(correctAnswer)) { correctAnswers.push(correctAnswer); GM_setValue('correctAnswers', correctAnswers); } if (!wordList.includes(correctAnswer)) { wordList.push(correctAnswer); } } } function checkWordsElement() { const wordElems = Array.from(document.querySelectorAll('.words.show .word')); wordElems.forEach(elem => { const word = elem.textContent.trim().toLowerCase(); if (!word) { return; } if (!wordList.includes(word)) { wordList.push(word); } if (word.trim() !== "" && !correctAnswers.includes(word)) { correctAnswers.push(word); GM_setValue('correctAnswers', correctAnswers); } }); } function observeInput() { const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]'); inputElem.addEventListener('input', generateGuesses); inputElem.addEventListener('keydown', handleKeyDown); const formElem = document.querySelector('#game-chat form'); formElem.addEventListener('submit', generateGuesses); } function handleKeyDown(event) { if (event.key === 'Tab' && possibleWords.length > 0) { event.preventDefault(); const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]'); inputElem.value = possibleWords[0]; inputElem.focus(); generateGuesses(); } } function generateGuesses() { const hintElems = Array.from(document.querySelectorAll('.hints .hint')); const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]'); const hintParts = hintElems.map(elem => elem.textContent === '_' ? '.' : elem.textContent).join('').split(' '); const inputText = inputElem.value ? String(inputElem.value) : ''; possibleWords = wordList.filter(word => { let wordParts = word.split(' '); if (wordParts.length !== hintParts.length) { return false; } for (let i = 0, len = wordParts.length; i < len; i++) { if (wordParts[i].length !== hintParts[i].length) { return false; } } if (hintParts.join(' ').trim().length <= 0 && inputText.trim().length <= 0) { return true; } let hintRegex = new RegExp(`^${hintParts.join(' ')}$`, 'i'); if (!hintRegex.test(word)) { return false; } let inputTextRegex = new RegExp(`^${inputText}`, 'i'); if (!inputTextRegex.test(word)) { return false; } return true; }); possibleWords.sort((a, b) => { let aIsCorrect = correctAnswers.includes(a); let bIsCorrect = correctAnswers.includes(b); if (aIsCorrect && !bIsCorrect) return -1; if (bIsCorrect && !aIsCorrect) return 1; return 0; }); guessElem.innerHTML = ''; renderGuesses(possibleWords, inputElem); } function renderGuesses(possibleWords, inputElem) { possibleWords.slice(0, 100).forEach((word, index) => { const wordElem = document.createElement('div'); wordElem.textContent = word; wordElem.style = 'font-weight: bold; display: inline-block; padding: 5px; margin-right: 2px; color: white;'; const maxValue = possibleWords.length > 100 ? 100 : possibleWords.length; let colorValue = possibleWords.length > 1 ? Math.floor(255 * index / (maxValue - 1)) : 0; wordElem.style.backgroundColor = `rgb(${colorValue}, ${255 - colorValue}, 0)`; addHoverEffect(wordElem, colorValue); addClickFunctionality(wordElem, word, inputElem, colorValue); guessElem.appendChild(wordElem); }); } function addHoverEffect(wordElem, colorValue) { wordElem.addEventListener('mouseenter', function() { if (!wordElem.classList.contains('pressed')) { wordElem.style.backgroundColor = 'lightgray'; } wordElem.classList.add('hovered'); }); wordElem.addEventListener('mouseleave', function() { if (!wordElem.classList.contains('pressed')) { wordElem.style.backgroundColor = `rgb(${colorValue}, ${255 - colorValue}, 0)`; } wordElem.classList.remove('hovered'); }); } function addClickFunctionality(wordElem, word, inputElem, colorValue) { wordElem.addEventListener('mousedown', function() { wordElem.classList.add('pressed'); wordElem.style.backgroundColor = 'gray'; }); wordElem.addEventListener('mouseup', function() { wordElem.classList.remove('pressed'); if (!wordElem.classList.contains('hovered')) { wordElem.style.backgroundColor = `rgb(${colorValue}, ${255 - colorValue}, 0)`; } else { wordElem.style.backgroundColor = 'lightgray'; } }); wordElem.addEventListener('click', function() { const formElem = document.querySelector('#game-chat form'); inputElem.value = word; formElem.dispatchEvent(new Event('submit', { bubbles: true })); }); } function createGuessElement() { let guessElem = document.createElement('div'); guessElem.style = 'position: fixed; bottom: 0; left: 0; right: 0; padding: 10px; background-color: white; max-height: 200px; overflow-x: auto; white-space: nowrap; max-width: 100vw;'; document.body.appendChild(guessElem); return guessElem; } })();