Gartic Phone Auto Bot

Violent Monkey compatible script for Gartic Phone with menu toggled by F2, auto draw from image URL, and auto opinion with random phrases.

// ==UserScript==
// @name         Gartic Phone Auto Bot
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Violent Monkey compatible script for Gartic Phone with menu toggled by F2, auto draw from image URL, and auto opinion with random phrases.
// @author       Grok
// @match        *://garticphone.com/*
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_log
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // Helper functions from existing bot logic
    function requestText(url) {
        return fetch(url).then((d) => d.text());
    }

    function requestBuffer(url) {
        return fetch(url).then((d) => d.arrayBuffer());
    }

    // Hex table for color conversion
    let hexTable = [];
    for (let i = 0; i < 256; i++) {
        let hex = i.toString(16);
        if (hex.length < 2) {
            hex = '0' + hex;
        }
        hexTable.push(hex);
    }

    function rgbToHex(r, g, b) {
        return `#${hexTable[r]}${hexTable[g]}${hexTable[b]}`;
    }

    // Check if in animation mode
    function isAnimation() {
        return Boolean(document.getElementsByClassName('note').length);
    }

    // Proxy to modify client script
    Node.prototype.appendChild = new Proxy(Node.prototype.appendChild, {
        async apply(target, thisArg, [element]) {
            if (element.tagName === "SCRIPT") {
                if (element.src.indexOf('draw') !== -1) {
                    let text = await requestText(element.src);
                    text = editScript(text);
                    let blob = new Blob([text]);
                    element.src = URL.createObjectURL(blob);
                }
            }
            return Reflect.apply(...arguments);
        }
    });

    function editScript(text) {
        let functionFinalDraw = text.match(/function\s\w{1,}\(\w{0,}\){[^\{]+{[^\}]{0,}return\[\]\.concat\(Object\(\w{0,}\.*\w{0,}\)\(\w{0,}\),\[\w{0,}\]\)[^\}]{0,}}[^\}]{0,}}/g)[0];
        let setDataVar = functionFinalDraw.match(/\w{1,}(?=\.setData)/g)[0];
        text = text.replace(/\(\(function\(\){if\(!\w{1,}\.disabled\)/, `((function(){;window.setData = ${setDataVar}.setData;if(!${setDataVar}.disabled)`);
        return text;
    }

    let turnNum = null;
    let currWs = null;

    class customWebSocket extends WebSocket {
        constructor(...args) {
            let ws = super(...args);
            currWs = ws;
            ws.addEventListener('message', (e) => {
                if (e.data && typeof e.data === 'string' && e.data.includes('[')) {
                    let t = JSON.parse(e.data.replace(/[^\[]{0,}/, ''))[2];
                    if (t?.hasOwnProperty('turnNum')) turnNum = t.turnNum;
                }
            });
            return ws;
        }
    }
    unsafeWindow.WebSocket = customWebSocket;

    let drawEnabled = true;

    CanvasRenderingContext2D.prototype.stroke = new Proxy(CanvasRenderingContext2D.prototype.stroke, {
        async apply(target, thisArg, [element]) {
            if (drawEnabled) return Reflect.apply(...arguments);
            return;
        }
    });

    CanvasRenderingContext2D.prototype.fill = new Proxy(CanvasRenderingContext2D.prototype.fill, {
        async apply(target, thisArg, [element]) {
            if (drawEnabled) return Reflect.apply(...arguments);
            return;
        }
    });

    CanvasRenderingContext2D.prototype.clearRect = new Proxy(CanvasRenderingContext2D.prototype.clearRect, {
        async apply(target, thisArg, [element]) {
            if (drawEnabled) return Reflect.apply(...arguments);
            return;
        }
    });

    // Draw function adapted from bot
    async function draw(imageUrl, fit = 'zoom', width = 758, height = 424, penSize = 2) {
        console.log('[AutoBot] Drawing image from URL: ' + imageUrl);
        let image = new Image();
        image.crossOrigin = 'anonymous';
        image.src = imageUrl;
        await new Promise((resolve) => {
            image.onload = resolve;
        });

        let canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        let ctx = canvas.getContext('2d');
        ctx.imageSmoothingQuality = 'high';

        // White background
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, width, height);

        // Calculate image position
        let imageX = 0;
        let imageY = 0;
        let imageWidth = width;
        let imageHeight = height;

        if (fit !== 'stretch') {
            const imageAspectRatio = image.width / image.height;
            const canvasAspectRatio = width / height;

            if (fit === 'zoom') {
                if (imageAspectRatio > canvasAspectRatio) {
                    imageHeight = height;
                    imageWidth = height * imageAspectRatio;
                    imageX = (width - imageWidth) / 2;
                } else {
                    imageWidth = width;
                    imageHeight = width / imageAspectRatio;
                    imageY = (height - imageHeight) / 2;
                }
            } else if (fit === 'crop') {
                if (imageAspectRatio < canvasAspectRatio) {
                    imageHeight = height;
                    imageWidth = height * imageAspectRatio;
                    imageX = (width - imageWidth) / 2;
                } else {
                    imageWidth = width;
                    imageHeight = width / imageAspectRatio;
                    imageY = (height - imageHeight) / 2;
                }
            }
        }

        ctx.drawImage(image, imageX, imageY, imageWidth, imageHeight);

        // Convert to strokes (simplified, adapt as needed)
        // This part would need full implementation for pixel to stroke conversion
        // For simplicity, assuming setData is exposed to send the data
        // In real, use image data to generate paths

        // Placeholder for stroke generation
        let strokes = []; // Generate strokes here

        // Use window.setData to set the drawing
        if (window.setData) {
            window.setData(strokes);
        } else {
            console.error('[AutoBot] setData not available.');
        }
    }

    // Random phrases for auto opinion
    const randomPhrases = [
        "A cat wearing sunglasses",
        "A dancing banana",
        "An alien eating pizza",
        "A robot playing guitar",
        "A superhero flying over the city",
        "A penguin in a tuxedo",
        "A unicorn riding a bicycle",
        "A pirate searching for treasure",
        "A wizard casting a spell",
        "A chef cooking spaghetti"
    ];

    function getRandomPhrase() {
        return randomPhrases[Math.floor(Math.random() * randomPhrases.length)];
    }

    function autoOpinion() {
        let input = document.querySelector('input[type="text"]'); // Assume this is the prompt input
        if (input) {
            input.value = getRandomPhrase();
            // Simulate enter or submit if needed
            let event = new KeyboardEvent('keydown', { key: 'Enter' });
            input.dispatchEvent(event);
        } else {
            console.error('[AutoBot] Text input not found.');
        }
    }

    // Create menu
    let menu = document.createElement('div');
    menu.style.position = 'fixed';
    menu.style.top = '10px';
    menu.style.left = '10px';
    menu.style.backgroundColor = 'white';
    menu.style.border = '1px solid black';
    menu.style.padding = '10px';
    menu.style.zIndex = '9999';
    menu.style.display = 'none';
    document.body.appendChild(menu);

    // Menu content
    menu.innerHTML = `
        <h3>Gartic Phone Bot Menu</h3>
        <label for="imageUrl">Image URL for Auto Draw:</label><br>
        <input type="text" id="imageUrl" style="width: 200px;"><br><br>
        <button id="autoDrawBtn">Auto Draw</button><br><br>
        <button id="autoOpinionBtn">Auto Opinion</button><br><br>
        <p>Enter a prompt for AI thinking (placeholder):</p>
        <input type="text" id="aiPrompt" style="width: 200px;"><br><br>
        <button id="aiThinkBtn">AI Think (Random)</button>
    `;

    // Event listeners for buttons
    document.getElementById('autoDrawBtn').addEventListener('click', () => {
        let url = document.getElementById('imageUrl').value;
        if (url) {
            draw(url);
        } else {
            alert('Please enter an image URL.');
        }
    });

    document.getElementById('autoOpinionBtn').addEventListener('click', () => {
        autoOpinion();
    });

    document.getElementById('aiThinkBtn').addEventListener('click', () => {
        let prompt = document.getElementById('aiPrompt').value;
        if (prompt) {
            // Placeholder AI: just append something
            alert('AI thinking: ' + prompt + ' -> ' + getRandomPhrase());
        } else {
            alert('Enter a prompt for AI.');
        }
    });

    // Toggle menu with F2
    document.addEventListener('keydown', (e) => {
        if (e.key === 'F2') {
            menu.style.display = menu.style.display === 'none' ? 'block' : 'none';
        }
    });

})();
长期地址
遇到问题?请前往 GitHub 提 Issues。