// ==UserScript== // @name Lichess Bot (stockfish8.17) // @description Fully automated lichess bot // @author Nuro // @match *://lichess.org/* // @run-at document-start // @grant none // @require https://raw.githubusercontent.com/workinworld/stkfish/refs/heads/main/stockfish8.js // ==/UserScript== let chessEngine; let currentFen = ""; let bestMove; let webSocketWrapper = null; let gameId = null; let isWhite = true; // Flag to determine if the bot is playing white function initializeChessEngine() { chessEngine = window.STOCKFISH(); } function interceptWebSocket() { let webSocket = window.WebSocket; const webSocketProxy = new Proxy(webSocket, { construct: function (target, args) { let wrappedWebSocket = new target(...args); webSocketWrapper = wrappedWebSocket; wrappedWebSocket.addEventListener("message", function (event) { let message = JSON.parse(event.data); // Extract game ID and player color if (message.type === "gameFull" && message.id) { gameId = message.id; isWhite = message.white.id === lichess.socket.settings.userId; } // Handle game state updates if (message.d && typeof message.d.fen === "string") { currentFen = message.d.fen; calculateMove(); } }); return wrappedWebSocket; } }); window.WebSocket = webSocketProxy; } function calculateMove() { if (!chessEngine || !currentFen) { return; } chessEngine.postMessage("position fen " + currentFen); chessEngine.postMessage("go depth 18"); } function handleEngineMessage(event) { if (event && event.includes("bestmove")) { bestMove = event.split(" ")[1]; makeMove(bestMove); } } function makeMove(move) { if (webSocketWrapper && gameId && move) { webSocketWrapper.send(JSON.stringify({ t: "move", d: { gameId: gameId, move: move, e: null } })); } } initializeChessEngine(); interceptWebSocket(); if (typeof window.STOCKFISH === 'function') { window.STOCKFISH().onmessage = function (event) { if (typeof event.data === 'string') { handleEngineMessage(event.data); } }; }