Monkey Chat Handler (Typing Style)

A mod that handles monke bot's chats with a cool typing animation.

当前为 2025-08-24 提交的版本,查看 最新版本

// ==UserScript==
// @name         Monkey Chat Handler (Typing Style)
// @namespace    http://tampermonkey.net/
// @version      3.0
// @license MIT
// @description  A mod that handles monke bot's chats with a cool typing animation.
// @author       You & AI Assistant
// @match        https://bonk.io/gameframe-release.html
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bonk.io
// @grant        GM_addStyle
// ==/UserScript==

GM_addStyle(`
    .cool-chat-message {
        border-left: 3px solid #4CAF50;
        padding: 5px 8px;
        margin: 4px 0;
        word-wrap: break-word;
    }

    .cool-chat-message a {
        color: #87CEEB;
        text-decoration: none;
        font-weight: bold;
        transition: color 0.2s ease, text-decoration 0.2s ease;
    }

    .cool-chat-message a:hover {
        color: #98FB98;
        text-decoration: underline;
    }
`);

let autoCanv = function() {
    Object.defineProperty(this, 'chatBox1', {
        get: function() { return document.getElementById('newbonklobby_chat_content'); }
    });
    Object.defineProperty(this, 'chatBox2', {
        get: function() { return document.getElementById('ingamechatcontent'); }
    });
};
let canv = new autoCanv();

function linkify(text) {
    const urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, url => `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`);
}

async function displayInChat(msg, color = '#228B22', inner = true, size) {
    const TYPING_SPEED_MS = 30;
    const chatBox1 = canv.chatBox1;
    const chatBox2 = canv.chatBox2;

    if (!chatBox1 && !chatBox2) {
        console.error("No chatbox elements found!");
        return;
    }

    const scrollToBottom = () => {
        if (chatBox1) chatBox1.scrollTop = chatBox1.scrollHeight;
        if (chatBox2) chatBox2.scrollTop = chatBox2.scrollHeight;
    };

    const finalHtml = inner ? linkify(msg) : linkify(msg.replace(/</g, "&lt;").replace(/>/g, "&gt;"));

    const tempDiv = document.createElement('div');
    tempDiv.innerHTML = finalHtml;
    const plainText = tempDiv.textContent || "";

    const createMessageElements = () => {
        const messageContainer = document.createElement('div');
        messageContainer.className = 'cool-chat-message';
        const typingSpan = document.createElement('span');
        typingSpan.style.color = color;
        if (size) {
            typingSpan.style.fontSize = size + 'px';
        }
        messageContainer.appendChild(typingSpan);
        return { messageContainer, typingSpan };
    };

    const elements1 = chatBox1 ? createMessageElements() : null;
    const elements2 = chatBox2 ? createMessageElements() : null;

    if (elements1) chatBox1.appendChild(elements1.messageContainer);
    if (elements2) chatBox2.appendChild(elements2.messageContainer);
    scrollToBottom();

    for (let i = 0; i < plainText.length; i++) {
        const char = plainText[i];
        if (elements1) elements1.typingSpan.textContent += char;
        if (elements2) elements2.typingSpan.textContent += char;
        scrollToBottom();
        await new Promise(resolve => setTimeout(resolve, TYPING_SPEED_MS));
    }

    if (elements1) elements1.typingSpan.innerHTML = finalHtml;
    if (elements2) elements2.typingSpan.innerHTML = finalHtml;
}

let autoName = function() {
    Object.defineProperty(this, 'name', {
        get: function() {
            return document.getElementById("pretty_top_name")?.textContent;
        }
    });
};
let name = new autoName();

let monkTypes = {
    handleJoining: {
        run: function(data) {
            if (data[0].to == name.name) {
                pack(`4,{"initiator":"monke","type":"returnMessage","confirmed":"yes","from":"${name.name}"}`);
            }
        },
        variables: ['data'],
    },
    chatMessage: {
        run: function(data) {
            if (data[0].to == name.name) {
                const message = data[0].message;
                displayInChat(message);
            }
        },
        variables: ['data'],
    },
};
let monkVariableTypes = {
    data: {
        description: 'returns the data from the monk command',
        returned: function(data) {
            return data;
        }
    }
};

function handleMonk(data) {
    let runner = monkTypes[data.type];
    if (!runner) return;
    runner.run(runner.variables.map(variable => monkVariableTypes[variable].returned(data)));
}

let oldsend = WebSocket.prototype.send;
let code = function(xx) {
    if (xx == "5") {
        window.bonkws = this;
        let old_onmsg = this.onmessage;
        this.onmessage = function(yy) {
            if (yy.data.startsWith("42[")) {
                try {
                    let data = JSON.parse(yy.data.slice(2));
                    if (data[0] == 7 && data[2].initiator == 'monke') {
                        handleMonk(data[2]);
                    }
                } catch (e) {}
            }
            return old_onmsg.call(this, yy);
        };
    }
    return oldsend.call(this, xx);
};

function fixOverwriteBitch() {
    WebSocket.prototype.send = code;
}
fixOverwriteBitch();

async function pack(input) {
    if (window.bonkws && window.bonkws.readyState === 1) {
        await window.bonkws.send("42[" + input + "]");
    } else {
        console.error("Bonk WebSocket not ready to send message.");
    }
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址