How can I submit an html form using Tampermonkey, if the form requires the user to have typed something?

72 Views Asked by At

I am using Tampermonkey to sort of cheat on this game. I have taken the number that you need to memorize from the HTML and waited until there you can type the answer. I have my code do this:

inputElement.value = answerString;

Although this puts the answer into the <input> I can't submit my answer unless I manually type/change at least one character in the <input>.

(Additionally, the <input> cannot be empty. It will not let you submit the <form> if there is nothing in the <input>)

My problem is that I can't figure out any way to make the game think that the user has typed something into the <input>. I know that the obvious solution is to use something other than javascript to enter the correct answer, but I just want the final product to be elegant and just in one place. Is there any way that I can get this form to submit using javascript? I'm thinking that the most likely way is to somehow submit the form. I have tried to do that though, but it doesn't work because that forces the page to reset. They must have the form submit it's values using javascript. Does anybody know how to emulate that without actually typing into the <input> and then clicking submit?

My code (Note that in order for it to work you should press enter when you are supposed to be memorizing the number.):

// ==UserScript==
// @name         Human Benchmark Cheat
// @namespace    http://tampermonkey.net/
// @version      2024-02-04
// @description  This script helps cheat on the Number Memory test on Human Benchmark by automatically entering the number you need to remember.
// @author       Caleb
// @match        https://humanbenchmark.com/tests/number-memory
// @icon         https://humanbenchmark.com/favicon.ico
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Listen for keypress events on the page
    let numberToRemember = '';
    document.addEventListener('keypress', function(event) {
        // If the Enter key is pressed, start the cheat
        if (event.key === 'Enter') {
            startCheat();
        }
    });

    // Click the button to start the test
    function pressButton() {
        // Find and click the button
        const button = document.querySelector('.css-de05nr.e19owgy710');
        button.click();
    }

    // Extracts and stores the number to remember
    function saveNumber() {
        // Find the element displaying the number
        var elements = document.querySelectorAll('.big-number');
        // Combine the text content of these elements into a single string
        numberToRemember = Array.from(elements).map(function(element) {
            return element.textContent;
        }).join('');
        // Log the number to the console for reference
        console.log(numberToRemember);
    }

    //  Put the remembered number into the input field
    function typeString() {
        // Find the input field
        var inputElement = document.querySelector('input');
        // Set the value of the input field to the remembered number
        inputElement.value = numberToRemember;
    }

    // Starts the cheat
    function startCheat() {
        // Define the class name of the element to monitor
        const className = 'number-timer-bar';

        // Find the element with the specified class name
        const elementWithClass = document.querySelector(`.${className}`);

        // Create an observer to detect when the number appears or disappears
        const observer = new IntersectionObserver(entries => {
            // Check if the element with the specified class is visible
            if (entries[0].isIntersecting) {
                // The number is visible, save it
                console.log(`Element with class '${className}' is visible!`);
                saveNumber();
            } else {
                // The number is not visible, paste the answer and submit
                console.log(`Element with class '${className}' is not visible!`);
                typeString();
                pressButton();
            }
        });

        // Start observing the element with the specified class name
        observer.observe(elementWithClass);
    }
})();
1

There are 1 best solutions below

0
cssyphus On

I wasn't successful getting this to work, but what I usually do in these circs is to send to the input element a few events that are usually triggered when a human types in a field. Events like focus, keyup, keydown and change.

Often this works, some times it doesn't -- in this case it didn't work. Perhaps I just didn't find the right event. Because the source code is uglified / obfuscated, reverse engineering the source could be a bit tricky.

Passing this (non-working example) along to you to fiddle with further.

async function typeString() {
    // Find the input field
    var inputElement = document.querySelector('input');
    // Set the value of the input field to the remembered number
    //inputElement.value = numberToRemember;
    simulateUserTyping(inputElement, numberToRemember)
}

async function simulateUserTyping(el, str) {
    el.focus();
    let delay, value = el.value;
    delay = ((Math.floor(Math.random() * 63)) + 2);
    await sleep(delay);
    const evtFcs = new Event('focus', { bubbles: true });
    const evtDn = new Event('keydown', { bubbles: true });
    const evtUp = new Event('keyup', { bubbles: true });
    const evtChg = new Event('change', { bubbles: true });

    for (let i = 0; i < str.length; i++) {
        delay = ((Math.floor(Math.random() * 63)) + 2); //*10
        await sleep(delay);
        value += str.charAt(i);
        el.value = value;
        el.dispatchEvent(evtFcs);
        el.dispatchEvent(evtDn);
        el.dispatchEvent(evtUp);
        el.dispatchEvent(evtChg);
    }
}
function sleep(ms){
    return new Promise(function (resolve, reject) {
        setTimeout(()=>{
            resolve();
        },ms);
    })
}