WordSleuth

A script that helps you guess words in skribblio

目前为 2023-05-24 提交的版本。查看 最新版本

// ==UserScript==
// @name         WordSleuth
// @namespace    https://greasyfork.org/en/users/1084087-kueldev
// @version      0.2.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        none
// @license MIT
// ==/UserScript==

(function() {
  'use strict';

  let wordSet = new Set();
  const guessElem = createGuessElement();
  let possibleWords = [];

  fetchWords().then(words => {
    words.forEach(word => wordSet.add(word));
    observeHints();
    observeInput();
  });

  function fetchWords() {
    const url = 'https://raw.githubusercontent.com/arstgit/high-frequency-vocabulary/master/30k.txt';
    return fetch(url).then(response => response.text()).then(data => data.split('\n').map(word => word.trim()));
  }

  function observeHints() {
    const targetNode = document.querySelector('.hints .container');
    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') {
          generateGuesses();
        }
      }
    };

    const observer = new MutationObserver(callback);
    observer.observe(targetNode, config);
  }

  function observeInput() {
    const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]');
    inputElem.addEventListener('input', generateGuesses);
    inputElem.addEventListener('keydown', handleKeyDown);

    // Trigger generateGuesses when the user sends a message
    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 wordLengthElem = document.querySelector('.hints .word-length');
    const wordLength = wordLengthElem ? parseInt(wordLengthElem.textContent) : 0;

    const hintElems = Array.from(document.querySelectorAll('.hints .hint'));
    let hints = hintElems.map(elem => elem.textContent === '_' ? '.' : elem.textContent).join('');

    const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]');
    const inputText = inputElem.value;

    if (inputText) {
      // Replace the part of the hints with the input text, then fill the remainder with '.'.
      let hintArray = hints.split('');
      hintArray.splice(0, inputText.length, ...inputText.split(''));
      hints = hintArray.join('');
    }

    const regex = new RegExp('^' + hints + '$');

    possibleWords = Array.from(wordSet.values()).filter(word => word.length === wordLength && regex.test(word));

    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;';

      let colorValue = possibleWords.length > 1 ? Math.floor(255 * index / (possibleWords.length - 1)) : 0;
      wordElem.style.backgroundColor = `rgb(${colorValue}, ${255 - colorValue}, 0)`;

      addHoverEffect(wordElem, colorValue);
      addClickFunctionality(wordElem, word, inputElem);

      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) {
    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;
  }
})();
// ==UserScript==
// @name         WordSleuth
// @namespace    https://greasyfork.org/en/users/1084087-kueldev
// @version      0.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        none
// @license MIT
// ==/UserScript==

(function() {
  'use strict';

  let wordSet = new Set();
  const guessElem = createGuessElement();
  let possibleWords = [];

  fetchWords().then(words => {
    words.forEach(word => wordSet.add(word));
    observeHints();
    observeInput();
  });

  function fetchWords() {
    const url = 'https://raw.githubusercontent.com/arstgit/high-frequency-vocabulary/master/30k.txt';
    return fetch(url).then(response => response.text()).then(data => data.split('\n').map(word => word.trim()));
  }

  function observeHints() {
    const targetNode = document.querySelector('.hints .container');
    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') {
          generateGuesses();
        }
      }
    };

    const observer = new MutationObserver(callback);
    observer.observe(targetNode, config);
  }

  function observeInput() {
    const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]');
    inputElem.addEventListener('input', generateGuesses);
    inputElem.addEventListener('keydown', handleKeyDown);

    // Trigger generateGuesses when the user sends a message
    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 wordLengthElem = document.querySelector('.hints .word-length');
    const wordLength = wordLengthElem ? parseInt(wordLengthElem.textContent) : 0;

    const hintElems = Array.from(document.querySelectorAll('.hints .hint'));
    let hints = hintElems.map(elem => elem.textContent === '_' ? '.' : elem.textContent).join('');

    const inputElem = document.querySelector('#game-chat input[data-translate="placeholder"]');
    const inputText = inputElem.value;

    if (inputText) {
      // Replace the part of the hints with the input text, then fill the remainder with '.'.
      let hintArray = hints.split('');
      hintArray.splice(0, inputText.length, ...inputText.split(''));
      hints = hintArray.join('');
    }

    const regex = new RegExp('^' + hints + '$');

    possibleWords = Array.from(wordSet.values()).filter(word => word.length === wordLength && regex.test(word));

    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);

      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) {
    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;
  }
})();