Greasy Fork is available in English.

Twitch Pokecatch Bot

Auto catch pokemmons

// ==UserScript==
// @name          Twitch Pokecatch Bot
// @description   Auto catch pokemmons
// @namespace     https://github.com/victornpb
// @version       1.0
// @match         *://*.twitch.tv/*
// @run-at        document-idle
// @author        victornpb
// @homepageURL   https://github.com/victornpb/
// @supportURL    https://github.com/victornpb/
// @contributionURL https://www.buymeacoffee.com/vitim
// @grant         none
// @license       MIT
// ==/UserScript==

/* jshint esversion: 8 */

(function () {

    const LOGPREFIX = '[POKECATCH]';

    function createElm(html) {
        const div = document.createElement('div');
        div.innerHTML = html;
        return div.removeChild(div.children[0]);
    }

    document.head.appendChild(createElm`
    <style>
    .pokeBtn {
        display: inline-flex;
        -webkit-box-align: center;
        align-items: center;
        -webkit-box-pack: center;
        justify-content: center;
        user-select: none;
        height: var(--button-size-default);
        width: var(--button-size-default);
        border-radius: var(--border-radius-medium);
        background-color: var(--color-background-button-text-default);
        color: var(--color-fill-button-icon);
    }
    </style>`);


    // activation button
    const activateBtn = createElm(`
        <span class="pokeBtn" title="Pokecatching...">
            <svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 980 978.9" style="fill: currentcolor;">
                <path d="M509 979h-38l-5-1A485 485 0 0 1 2 531c-1-7 0-14-2-21v-43a59 59 0 0 0 1-5 461 461 0 0 1 18-107Q66 194 201 95c67-50 143-80 226-91a480 480 0 0 1 103-2c38 3 75 10 111 22q208 70 299 271c22 48 34 100 38 153 1 7 0 14 2 20v42l-1 7a464 464 0 0 1-18 106q-43 150-164 248-117 94-267 106c-7 1-14 0-21 2ZM178 521H82c-8 0-8 0-7 7a456 456 0 0 0 8 49q33 148 153 242a406 406 0 0 0 365 72 413 413 0 0 0 304-364c0-4 1-6-5-6H704c-3 0-4 1-5 4l-2 14a212 212 0 0 1-416-14c-1-3-2-4-6-4h-97Zm165-32a147 147 0 0 0 294 0 147 147 0 0 0-294 0Z"/>
            </svg>
        </span>
    `);
    // activateBtn.onclick = toggle;

    let enabled;
    let watchdogTimer;

    setInterval(activatorWatchdog, 5000);
    function activatorWatchdog() {
        const modBtn = document.querySelector('[data-a-target="chat-settings"]');
        if (modBtn) {
            const twitchBar = modBtn.parentElement.parentElement.parentElement.parentElement.parentElement;
            if (twitchBar && !twitchBar.contains(activateBtn)) {
                console.log(LOGPREFIX, 'Adding button...');
                twitchBar.insertBefore(activateBtn, twitchBar.firstChild);
                if (!enabled) {
                    console.log(LOGPREFIX, 'Started chatWatchdog...');
                    watchdogTimer = setInterval(chatWatchdog, 500);
                    enabled = true;
                }
            }
        }
        else {
            if (enabled) {
                console.log(LOGPREFIX, 'Stopped chatWatchdog!');
                clearInterval(watchdogTimer);
                watchdogTimer = enabled = false;
            }
        }
    }


    function parseChat() {
        return Array.from(document.querySelectorAll('[data-test-selector="chat-line-message"]')).map(chat => {
            return {
                username: chat.querySelector('[data-test-selector="message-username"]')?.innerText || '',
                message: chat.querySelector('[data-test-selector="chat-line-message-body"]')?.innerText || '',
                // timestamp: chat.querySelector('[data-test-selector="chat-timestamp"]').innerText,
            };
        });
    }

    const delay = t => new Promise(r => setTimeout(r, t));

    let ignoredMessage = new Set();

    async function chatWatchdog() {
        const messages = parseChat().filter(m => !ignoredMessage.has(m.message));
        for (const m of messages) {
            if (m.username === 'PokemonCommunityGame' && m.message.match(/A wild (\w+) appears/)) {
                ignoredMessage.add(m.message);

                console.log(LOGPREFIX, 'Catching pokemon...', m);
                sendMessage('!pokecatch greatball');
            }
        }
    }

    function sendMessage(msg) {
        console.log(LOGPREFIX, 'Sending...', msg);
        const textarea = document.querySelector("[data-a-target='chat-input']");
        const nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, "value").set;
        nativeTextAreaValueSetter.call(textarea, msg);
        const event = new Event('input', { bubbles: true });
        textarea.dispatchEvent(event);
        document.querySelector("[data-a-target='chat-send-button']").click();
    }

})();