A simple GreaseMonkey script to toggle auto-whisper on/off and at the same time prepending the current move
// ==UserScript==
// @name Lichess Whisper Switch by ipr
// @namespace http://tampermonkey.net/
// @version 0.3.16
// @description A simple GreaseMonkey script to toggle auto-whisper on/off and at the same time prepending the current move
// @author You
// @match https://lichess.org/*
// @grant GM_addStyle
// @run-at document-end
// ==/UserScript==
/* jshint esversion: 6 */
//--- Style our newly added elements using CSS.
GM_addStyle ( `
#myContainer {
position: absolute;
top: 0;
left: 0;
font-size: 10px;
margin: 5px;
opacity: 0.9;
z-index: 1100;
padding: 5px 20px;
}
#whisperButton {
background-color: #384722; /* Green */
border: none;
color: white;
padding: 12px 12px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
}
#prependMoveButton {
background-color: #384722; /* Green */
border: none;
color: white;
padding: 12px 12px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
}
#hiddenPrependMoveSwitch {
display: none;
}
#hiddenWhisperSwitch {
display: none;
}
` );
function blackMoved(){
return document.getElementsByTagName('l4x')[0].children.length % 3 === 0;
}
function getFormattedMoveNumber(){
const move_number = Math.round(document.getElementsByTagName('l4x')[0].children.length / 3);
const move = document.getElementsByTagName('l4x')[0].children[document.getElementsByTagName('l4x')[0].children.length -1].textContent;
if (blackMoved()) {
return "(" + move_number + "..." + move + ")";
}
else {
return "(" + move_number + "." + move + ")";
}
}
function gameInProgress(){
const accepted_game_conditions_when_not_playing = ["game__tv", "game__tournament"];
if (
document.getElementsByClassName("game__meta")[0].childNodes.length === 1 ||
accepted_game_conditions_when_not_playing.some(e=>document.getElementsByClassName("game__meta")[0].childNodes[1].className.includes(e)) ||
document.getElementsByClassName("game__meta")[0].childNodes[1].childNodes[0].nodeValue.includes("Chess960") // 960 game
)
{
return true;
}
else {
return false;
}
}
function shouldPrepend(){
const moves_have_been_played = Boolean(document.getElementsByTagName('l4x')[0]);
return moves_have_been_played && gameInProgress();
}
const user_is_deleting_comment = (event)=>{
const inputType = event.inputType;
switch(inputType)
{
case "deleteContentBackward":
return true;
case "deleteContentForward":
return true;
default:
return false;
}
};
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
const move_prepend = new RegExp('\\([0-9]+\.{1,3}.{1,5}\\) ', 'g');
const whisper_prepend = new RegExp('^\/w ', 'ig');
const current_move_number_matcher = () => new RegExp(escapeRegExp(getFormattedMoveNumber()), "g");
const strip_prependers = (value) => {
return value.replace(whisper_prepend,"").replace(move_prepend, "");
};
const whisper = (event)=>{
let chatbox = document.getElementsByClassName('mchat__say')[0];
const inputValue = event.currentTarget.value;
console.log("KEY CODE" + inputValue);
if (shouldPrepend() && !user_is_deleting_comment(event)){
chatbox.value = (current_move_number_matcher().test(chatbox.value) && whisper_prepend.test(chatbox.value)) ?
chatbox.value :
'/w ' + getFormattedMoveNumber() + " " + strip_prependers(chatbox.value);
}
};
const whisper_no_move = (event)=>{
const chatbox = document.getElementsByClassName('mchat__say')[0];
if (shouldPrepend() && !user_is_deleting_comment(event)){
chatbox.value = (!move_prepend.test(chatbox.value) && whisper_prepend.test(chatbox.value)) ?
chatbox.value :
'/w ' + strip_prependers(chatbox.value);
}
};
const nowhisper = (event)=>{
const chatbox = document.getElementsByClassName('mchat__say')[0];
if (shouldPrepend() && !user_is_deleting_comment(event)){
chatbox.value = (current_move_number_matcher().test(chatbox.value) && !whisper_prepend.test(chatbox.value)) ?
chatbox.value :
getFormattedMoveNumber() + " " + strip_prependers(chatbox.value);
}
};
function insertAfter(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
function userInPlayers(player, index, array){
return player.textContent.includes(document.getElementById("user_tag").text);
}
function userIsPlaying(){
const players = Array.from(document.getElementsByClassName("game__meta__players")[0].children);
return players.filter(userInPlayers).length !== 0;
}
const checkIfMetaExists = setInterval(function() {
const material = document.getElementsByClassName("game__meta")[0];
const chatbox = document.getElementsByClassName('mchat__say')[0];
const standings = document.getElementsByClassName('mchat__tab tourStanding')[0];
if (material && chatbox && !standings) {
clearInterval(checkIfMetaExists);
let div_block = document.createElement ('div');
div_block.setAttribute("id", "Whisperer");
if (gameInProgress()){
div_block.innerHTML = '<button id="whisperButton" type="button">Whisper</button><button id="prependMoveButton" type="button">Prepend move</button><input type="checkbox" id="hiddenPrependMoveSwitch" value="on" class="hidden"><input type="checkbox" id="hiddenWhisperSwitch" value="on" class="hidden">';
insertAfter(material, div_block);
document.getElementById ("whisperButton").addEventListener (
"click", whisperClickAction, false);
document.getElementById ("prependMoveButton").addEventListener (
"click", prependMoveClickAction, false);
// reset the colors now so that they match the theme
resetButtonColorOn(document.getElementById("whisperButton"));
resetButtonColorOn(document.getElementById("prependMoveButton"));
if (!userIsPlaying()){
document.getElementById("hiddenWhisperSwitch").value = "off";
document.getElementById("whisperButton").style.display = "none";
}
setChatboxInputMode();
}
}
}, 25);
const checkStatusUpdates = setInterval(function() {
if (document.getElementsByClassName("result-wrap")[0]){
document.getElementById("hiddenWhisperSwitch").value = "off";
document.getElementById("hiddenPrependMoveSwitch").value = "off";
document.getElementById("Whisperer").style.display = "none";
whisperClickAction();
prependMoveClickAction();
clearInterval(checkStatusUpdates);
}
}, 25);
function setChatboxInputMode(){
let chatbox = document.getElementsByClassName('mchat__say')[0];
const whisper_switch_value = document.getElementById("hiddenWhisperSwitch").value;
const prepend_switch_value = document.getElementById("hiddenPrependMoveSwitch").value;
if (whisper_switch_value === "on"){
if (prepend_switch_value === "on"){
resetButtonColorOn(document.getElementById("prependMoveButton"));
chatbox.oninput = whisper;
}
else{
chatbox.oninput = whisper_no_move;
}
}
else{
if (prepend_switch_value === "on"){
chatbox.oninput = nowhisper;
}
else{
chatbox.oninput = null;
}
}
}
function resetButtonColorOff (button) {
const colors = {
"dark": {"background": "#262421", "opacity": "0.5"}, // dark gray
"transp": {"background": "#9A2F2E", "opacity": "0.5"}, // red
"light": {"background": "#262421", "opacity": "0.5"} // white
};
for (const [key, value] of Object.entries(colors)) {
if (document.body.classList.contains(key)){
for (const [property, property_value] of Object.entries(value)) {
button.style[property]=property_value;
}
break;
}
}
}
function resetButtonColorOn (button) {
const colors = {
"dark": {"background": "#384722", "opacity": "1"}, // dark green
"transp": {"background": "#40a35a", "opacity": "0.8"}, // light green
"light": {"background": "#307843", "opacity": "0.8"} // light green
};
for (const [key, value] of Object.entries(colors)) {
if (document.body.classList.contains(key)){
for (const [property, property_value] of Object.entries(value)) {
button.style[property]=property_value;
}
break;
}
}
}
function whisperClickAction (zEvent) {
const whisper_switch_value = document.getElementById("hiddenWhisperSwitch").value;
if (whisper_switch_value === "on"){
document.getElementById("hiddenWhisperSwitch").value = "off";
resetButtonColorOff(document.getElementById("whisperButton"));
}
else{
document.getElementById("hiddenWhisperSwitch").value = "on";
resetButtonColorOn(document.getElementById("whisperButton"));
}
setChatboxInputMode();
}
function prependMoveClickAction (zEvent) {
const prepend_switch_value = document.getElementById("hiddenPrependMoveSwitch").value;
if (prepend_switch_value === "on"){
document.getElementById("hiddenPrependMoveSwitch").value = "off";
resetButtonColorOff(document.getElementById("prependMoveButton"));
}
else {
document.getElementById("hiddenPrependMoveSwitch").value = "on";
resetButtonColorOn(document.getElementById("prependMoveButton"));
}
setChatboxInputMode();
}