DEV Community

Cover image for Cheating 10fastfingers
Hieu
Hieu

Posted on

Cheating 10fastfingers

10fastfingers.com is an awesome application let you play typing game with your friends. Nothing is funnier than beating your friends by your extremely fast typing. But if you can't type fast, a little cheating is harmless. Moreover, learning the new thing while you make a cheat is a wonderful way to learn new knowledge. Now let start

Trying out 10fastfingers.com

At the first step, we must access 10fastfingers.com and play around with it. The rule of this game is very simple, we have to type as fast and correct as possible to defeat your friends. Who has the highest score will win the game. If you’re like me can’t type fast, we need a little cheat here. Why don’t let the computer type for us? Who can defeat the speed of the computer?

To cheat that game, we need 2 essential things: how to get or retrieve the text for typing and how to send that text to the input field

Retrieve the text for typing

By using our best friend “Developer tool”, we can inspect the element which is highlighted for the current word like
Code
We can easily detect that the text “children” which we want to retrieve is put inside a div element with a class name highlight. To get that value, just easily write

let text = document.querySelector(".highlight").textContent;
Enter fullscreen mode Exit fullscreen mode

try to run this in console window:

We have finished retrieving the word job. Now move on to step 2

Sending the text to the input field

Besides sending the retrieved text to input, we also need to fire and InputEvent in order to let the system to recognize the text and continue with the following texts. Simply like this

let text = document.querySelector(".highlight").textContent + " ";
document.querySelector("input").value = text;
var inputEvent = new InputEvent("input");
document.querySelector("input").dispatchEvent(inputEvent);
Enter fullscreen mode Exit fullscreen mode

Try to run this block of code in the console window to see. If you’re lucky, you will get the error message instead of the input is auto-filled.
Code

Why does this happen? Because you’re unlucky. I’m just kidding :), the problem is because we’re trying to access the highlight and input element which is not the same frame we run the code. Our code at the moment running at “top” frame, but highlight and input are rendered under other frame named 10ff.net. To fix this problem just simply select 10ff.net as a context in the console window and try one more time


Yeah, it works. But how can we defeat other people with we need to paste the code and enter so many times, this process is even slower than your typing, we need to make this code run continuously.

Run the code continuously

Beside run the code continuously, we also need to wait a few moments between each turn to let the system render the next word for us. We can use setTimeout at different time. Something like this:

var i = 0;
while (i < 100) {
    i++;
    setTimeout(() => {
        let text = document.querySelector(".highlight").textContent + " ";
        document.querySelector("input").value = text
        var inputEvent = new InputEvent("input");
        document.querySelector("input").dispatchEvent(inputEvent)
    }, i * 100) //Each turn is 100 miliseconds apart 
}
Enter fullscreen mode Exit fullscreen mode

We won !! But we still have a problem that we set the number of turns we want to run the code at the beginning, in this case, we set 100 times. In the beginning, we create 100 timeout functions, which is 100 milliseconds apart this way works well. However it’s not good enough because in some cases, the number of words is different from 100, so our code may don’t run enough time or run more times than we need. So we need to determine exactly the number of the turn we want to run during the execution time rather than in the beginning time. How can we do that? promises our answer. The promise in javascript give 2 possibilities to run the next turn: resolve lets us run the next turn or reject lets us break the loop. Let's convert our code to using Promise

var run = () => new Promise((resolve, reject) => {
    if (!document.querySelector(".highlight")) {
        console.log("stop")
        reject("stop")
    }
    let text = document.querySelector(".highlight").textContent + " ";
    document.querySelector("input").value = text
    var inputEvent = new InputEvent("input");
    document.querySelector("input").dispatchEvent(inputEvent)
    setTimeout(() => resolve("next"), 10)
})
while (true) {
    try {
        await run();
    } catch (e) {
        console.error("stop");
        break;
    }
}
Enter fullscreen mode Exit fullscreen mode

Enjoy your champion!

Wrap up

In this tutorial, we have just learned the way to inspect element, retrieve the data as well as the way to trigger an input event to simulate the user action. Moreover, we also learned how to create a loop which has the gap between each turn by using Promise comes with await. For deeper learning about Promise, you can visit Promise and Await and async. Please take your time to do this cheating by yourself and learn the new thing. See you soon in the next post

Top comments (1)

Collapse
 
0x04 profile image
Oliver Kühn

Nice post! I did something similar but in JS 1.8/jQuery. Now my attempt feels a bit more clumpsy :-)

var hackInput = document.querySelector('#inputfield')
var hackHighlight = null
var hackCurrent = 0
var hackInterval = 0

function hack() {
    hackHighlight = document.querySelector('#row1 .highlight')

    if (!hackHighlight) {
        clearInterval(hackInterval)
        return
    }

    hackType()
}

function hackType() {
    var down = new $.Event('keydown')
    var up = new $.Event('keyup')
    var value = hackHighlight.innerText.slice(0, hackCurrent + 1)

    if (hackCurrent < hackHighlight.innerText.length) {
        down.which = up.which = hackHighlight.innerText.slice(hackCurrent++, 1)
    }
    else {
        down.which = up.which = 32
        value += ' '
        hackCurrent = 0
    }
    console.info(value)
    $(document).trigger(down)
    $(hackInput).val(value)
    $(hackInput).trigger(up)
    $(document).trigger(up)
}

hackInterval = setInterval(hack, 25)