// ==UserScript== // @name Chess Compass Analysis for Chess.com // @match https://www.chess.com/* // @run-at document-end // @grant none // @version 1.2 // @author AndyVuj24 // @description This plugin adds buttons next to the chess board allowing for a quick post-game analysis of the current game on screen // @supportURL https://github.com/andyvuj24/Chess-Compass-Analysis-for-Chess.com/issues // @homepageURL https://github.com/andyvuj24/Chess-Compass-Analysis-for-Chess.com // @namespace https://greasyfork.org/users/708710 // @downloadURL none // ==/UserScript== var counter = 0; const $ = document.querySelector.bind(document); const $$ = document.querySelectorAll.bind(document); const log = (message) => { console.log(`[Chess.com Plugin Log]: ${message}`); }; const addStyling = async () => { // button styling log("Adding styling to page for plugin buttons"); const styleElement = document.createElement("style"); styleElement.innerHTML = `.gf-chess-compass-button-container{margin:auto;display:flex;align-items:center;justify-content:center;border-radius:3px;color:#fff;font-size:16px}.gf-chess-compass-button-container>a{width:100%}.gf-chess-compass-button{background-color:#489e5d;width:100%;margin:auto;height:40px;display:flex;align-items:center;justify-content:center;border-radius:3px 3px 0 0;color:#fff;cursor:pointer;font-size:16px;font-weight:500;}.gf-chess-compass-button:hover{background-color:#57b26e}`; $("head")?.appendChild(styleElement); }; const addButtons = async (element) => { // for button element log("Adding buttons to sidebar"); $(element)?.insertAdjacentHTML( "beforebegin", '
' ); $(element)?.insertAdjacentHTML( "beforebegin", '
' ); }; const setupButton = async (id) => { log(`Configuring button -> ${id}`); const btn = $(id); if (id.indexOf("PGN") !== -1) { btn.addEventListener("click", function () { const data = ($("chess-board") ?.game.getPGN?.() .replace(/\[[^\]]*\]|\{[^\}]*\}/g, "") || [ ...$$( "div.vertical-move-list-component span.vertical-move-list-column:not(.move-timestamps-component)" ), ] .map(({ innerText }) => innerText) .join(" ") .replace(/\[[^\]]*\]|\{[^\}]*\}/g, "")) ?? null; if (!data) { log("Unable to find data for PGN"); return; } log("PGN: " + data); fetch("https://www.chesscompass.com/api/get_game_id", { method: "post", body: JSON.stringify({ gameData: data, }), }) .then((response) => { return response.json(); }) .then(({ gameId }) => { window.open( "https://www.chesscompass.com/analyze/" + gameId, "_blank" ); }); }); } if (id.indexOf("FEN") !== -1) { btn.addEventListener("click", function () { const data = ($("chess-board")?.game.getFEN?.() || $("div.v-board")?.getChessboardInstance?.().state.selectedNode.fen) ?? null; if (!data) { log("Unable to find data for FEN"); return; } log("FEN: " + data); fetch("https://www.chesscompass.com/api/get_game_id", { method: "post", body: JSON.stringify({ gameData: data, }), }) .then((response) => { return response.json(); }) .then(({ gameId }) => { window.open( "https://www.chesscompass.com/analyze/" + gameId, "_blank" ); }); }); } }; const waitForContainer = async () => { const existCondition = setInterval(function () { [ ".sidebar-component", ".sidebar-v5-component", "vertical-move-list", ].forEach((element) => { if ($(element)) { clearInterval(existCondition); main(element); return; } if (counter > 600) { log("No sidebars found for us to use..."); clearInterval(existCondition); } }); counter++; }, 100); // check every 100ms }; const clearAds = async () => { log("Clearing ads..."); const adsToRemove = [ "#tall-sidebar-ad", "#adblocker-check", "#board-layout-ad", ]; adsToRemove.forEach((selector) => { $$(selector).forEach((ele) => { ele.remove(); }); }); log("Ads cleared!"); }; async function main(element) { await addStyling(); await addButtons(element); await setupButton("#btnPGN"); await setupButton("#btnFEN"); await clearAds(); } if ( document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll) ) { waitForContainer(); } else { document.addEventListener("DOMContentLoaded", waitForContainer); }