javascriptgoogle-chrome-extensiondiscordtampermonkey

How to insert text into a Discord search bar using JavaScript?


I'm trying to create a tampermonkey script that will simply take a predefined string and put it in discord search bar then triggers a search, the text gets inserted in the search bar but it's not interactable and the search isn't performed, the text is "overlayed" over the hint, I think that the bar dynamically changing size when being clicked is related but I'm not sure.

The search bar still works if I try to use it manually but any text I type inside it after executing the script is hidden, the search results do show what I've typed though not what's being displayed (the text inserted by the script)

I've wanted to skip the search bar entirely but couldn't figure out what function is being used to search.

Here's what I've tried:

function performSearch() {
    const searchString = 'Search String';
    const searchBar = document.querySelector('.search_ff5f90 .public-DraftEditor-content');

    if (searchBar) {
        searchBar.focus();
        searchBar.textContent = searchString;

        const inputEvent = new Event('input', { bubbles: true });
        searchBar.dispatchEvent(inputEvent);

        const enterEvent = new KeyboardEvent('keydown', {
            bubbles: true,
            cancelable: true,
            key: 'Enter',
            keyCode: 13,
        });
        searchBar.dispatchEvent(enterEvent);
    }
}

Html of the search bar in different states

Empty Search Bar:

<div class="search_ff5f90"><div class="search_a46bef"><div class="searchBar_a46bef"><div class="DraftEditor-root"><div class="public-DraftEditorPlaceholder-root"><div class="public-DraftEditorPlaceholder-inner" id="placeholder-8p48t" style="white-space: pre-wrap;">Search</div></div><div class="DraftEditor-editorContainer"><div aria-describedby="placeholder-8p48t" aria-expanded="false" aria-label="Search" autocorrect="off" class="notranslate public-DraftEditor-content" contenteditable="true" role="combobox" spellcheck="false" style="outline: none; user-select: text; white-space: pre-wrap; overflow-wrap: break-word;" aria-haspopup="listbox"><div data-contents="true"><div class="" data-block="true" data-editor="8p48t" data-offset-key="fkrf5-0-0"><div data-offset-key="fkrf5-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="fkrf5-0-0"><br data-text="true"></span></div></div></div></div></div></div><div class="icon_a46bef iconLayout_effbe2 small_effbe2" tabindex="-1" aria-hidden="true" aria-label="Clear search" role="button"><div class="iconContainer_effbe2"><svg class="icon_effbe2 visible_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.62 17.03a9 9 0 1 1 1.41-1.41l4.68 4.67a1 1 0 0 1-1.42 1.42l-4.67-4.68ZM17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z" clip-rule="evenodd" class=""></path></svg><svg class="icon_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M17.3 18.7a1 1 0 0 0 1.4-1.4L13.42 12l5.3-5.3a1 1 0 0 0-1.42-1.4L12 10.58l-5.3-5.3a1 1 0 0 0-1.4 1.42L10.58 12l-5.3 5.3a1 1 0 1 0 1.42 1.4L12 13.42l5.3 5.3Z" class=""></path></svg></div></div></div></div></div>

Search Bar with Example String (Manually added):

<div class="search_ff5f90"><div class="search_a46bef open_a46bef"><div class="searchBar_a46bef"><div class="DraftEditor-root"><div class="DraftEditor-editorContainer"><div aria-describedby="placeholder-8p48t" aria-expanded="false" aria-label="Search" autocorrect="off" class="notranslate public-DraftEditor-content" contenteditable="true" role="combobox" spellcheck="false" style="outline: none; user-select: text; white-space: pre-wrap; overflow-wrap: break-word;" aria-haspopup="listbox" aria-activedescendant="uid_10--1"><div data-contents="true"><div class="" data-block="true" data-editor="8p48t" data-offset-key="fkrf5-0-0"><div data-offset-key="fkrf5-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="fkrf5-0-0"><span data-text="true">Example String</span></span></div></div></div></div></div></div><div class="icon_a46bef iconLayout_effbe2 small_effbe2 clear_effbe2" tabindex="0" aria-hidden="false" aria-label="Clear search" role="button"><div class="iconContainer_effbe2"><svg class="icon_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.62 17.03a9 9 0 1 1 1.41-1.41l4.68 4.67a1 1 0 0 1-1.42 1.42l-4.67-4.68ZM17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z" clip-rule="evenodd" class=""></path></svg><svg class="icon_effbe2 visible_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M17.3 18.7a1 1 0 0 0 1.4-1.4L13.42 12l5.3-5.3a1 1 0 0 0-1.42-1.4L12 10.58l-5.3-5.3a1 1 0 0 0-1.4 1.42L10.58 12l-5.3 5.3a1 1 0 1 0 1.42 1.4L12 13.42l5.3 5.3Z" class=""></path></svg></div></div></div></div></div>

Search Bar with Example String (Photo):

<div class="search_ff5f90"><div class="search_a46bef"><div class="searchBar_a46bef"><div class="DraftEditor-root"><div class="public-DraftEditorPlaceholder-root"><div class="public-DraftEditorPlaceholder-inner" id="placeholder-anc41" style="white-space: pre-wrap;">Search</div></div><div class="DraftEditor-editorContainer"><div aria-describedby="placeholder-anc41" aria-expanded="false" aria-label="Search" autocorrect="off" class="notranslate public-DraftEditor-content" contenteditable="true" role="combobox" spellcheck="false" style="outline: none; user-select: text; white-space: pre-wrap; overflow-wrap: break-word;" aria-haspopup="listbox"><div data-contents="true"><div data-block="true" data-editor="ncf4zujpt0i" data-offset-key="ncf4zujpt0i-0-0"><div data-offset-key="ncf4zujpt0i-0-0" class="public-DraftStyleDefault-block public-DraftStyleDefault-ltr"><span data-offset-key="ncf4zujpt0i-0-0"><span data-text="true">G• example string</span></span></div></div></div></div></div></div><div class="icon_a46bef iconLayout_effbe2 small_effbe2" tabindex="-1" aria-hidden="true" aria-label="Clear search" role="button"><div class="iconContainer_effbe2"><svg class="icon_effbe2 visible_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M15.62 17.03a9 9 0 1 1 1.41-1.41l4.68 4.67a1 1 0 0 1-1.42 1.42l-4.67-4.68ZM17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z" clip-rule="evenodd" class=""></path></svg><svg class="icon_effbe2" aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path fill="currentColor" d="M17.3 18.7a1 1 0 0 0 1.4-1.4L13.42 12l5.3-5.3a1 1 0 0 0-1.42-1.4L12 10.58l-5.3-5.3a1 1 0 0 0-1.4 1.42L10.58 12l-5.3 5.3a1 1 0 1 0 1.42 1.4L12 13.42l5.3 5.3Z" class=""></path></svg></div></div></div></div></div>

Solution

  • This was tricky; dispatching keydown/keyup/keypress events did nothing, and there is no input element. the search query seems to be saved in memory as modifying the span's text does nothing and still searches for the old query.

    But I was able to get it to work by simulating a paste event, then an enter event with this code:

    function simulatePaste(target, data){
        const pasteEvent = Object.assign(new Event('paste', { bubbles: true, cancelable: true }), {
            clipboardData: {
                getData: (type = 'text') => data
            }
        });
    
        target.focus();
        target.dispatchEvent(pasteEvent);
    }
    
    function simulateEnter(target){
        const enterEvent = new KeyboardEvent('keydown', {
            bubbles: true,
            cancelable: true,
            key: 'Enter',
            keyCode: 13,
        });
    
        target.dispatchEvent(enterEvent);
    }
    
    
    function performSearch(){
        const searchString = 'Hello world';
        const searchBar = document.querySelector('div[aria-label=Search]');
    
        if (!searchBar) return;
    
        simulatePaste(searchBar, searchString);
        setTimeout(() => simulateEnter(searchBar), 10);
    }