I'm working on a JavaScript project where I need to simulate typing into the message box in Instagram Direct Messages. However, the message box is not a standard input or textarea element but a div with contenteditable="true". My attempts to simulate keypresses on this div have been unsuccessful.
Here's what I've tried so far:
Simulating Keypress on Focused Element: I attempted to dispatch keyboard events to the currently focused element (the div message box), hoping to simulate typing. However, this method didn't work as expected. Here's the code snippet:
function typeTextLikeHuman(text, delay = 100) {
let index = 0;
let focusedElement = document.activeElement;
function typeChar() {
if (index < text.length) {
const char = text.charAt(index);
const keyEvent = new KeyboardEvent('keydown', {
key: char,
bubbles: true,
cancelable: true,
});
focusedElement.dispatchEvent(keyEvent);
// Directly append the char for contenteditable divs
if (focusedElement.isContentEditable) {
focusedElement.textContent += char;
}
index++;
if (index < text.length) {
setTimeout(typeChar, delay);
}
}
}
typeChar();
}
// Usage
// Whenever im in the bot reaches the url of the direct messaging to the desirede person, i call
typeTextLikeHuman("hola"); // not working
XPath Selection: I also tried selecting the div using XPath but had no success. The XPath to the element seems correct, but document.evaluate doesn't find it.
The primary issue seems to be with the way Instagram secures the textbox from being written (indeed they dont have a textbox, so makes more confusing from where they are writing the message or how is written, thats why i went to the keypress solutions that also dont work)
Any advice or insights would be greatly appreciated!
EDIT: Tried with MutationObserver to check when the texbox div is focused, to change te content of the 'textbox' itself, changed the tex but when sending the message, its not working:
code:
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.addedNodes.length) {
const editableDiv = document.querySelector('div[contenteditable]');
if (editableDiv) {
// Found the element, do something
editableDiv.addEventListener('focus', () => {
editableDiv.innerHTML = '<p class="xat24cr xdj266r xdpxx8g" dir="ltr"><span data-lexical-text="true">kk</span></p>'; // add the span and <p> tags inside the textarea div as instagram does!
setTimeout(function() {
var xpath = '/html/body/div[2]/div/div/div[2]/div/div/div[1]/div[1]/div[2]/section/div/div/div/div[1]/div/div[2]/div/div/div/div/div/div[2]/div/div/div[2]/div/div/div[3]'; // button div of 'send'
clickElementByXPath(xpath); // does not send anything, it only clears the textbox and nothing sent :(
}, 5000);
});
}
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
I grabbed the HTML from Instagram and made it work like this
No need for the event - however there is more going on at Instagram when the user types so it will not work at the site.