Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sakehl/4a843a22f7cdb58942d635784e8152c7 to your computer and use it in GitHub Desktop.
Save sakehl/4a843a22f7cdb58942d635784e8152c7 to your computer and use it in GitHub Desktop.
Disable automatic emoticon → emoji conversion in WhatsApp Web
// ==UserScript==
// @name WhatsApp Emoticon Preserver
// @namespace https://gist.github.com/sakehl/4a843a22f7cdb58942d635784e8152c7
// @version 0.6
// @author varkor, sakehl
// @description Disable automatic emoticon → emoji conversion in WhatsApp Web
// @match https://web.whatsapp.com/
// @grant none
// ==/UserScript==
(() => {
"use strict";
if (window.location.hostname !== "web.whatsapp.com") {
window.location = "https://web.whatsapp.com/";
} else {
const fixed = new Set();
const volatile = ["(y)", "(Y)", "(n)", "(N)", ":-)", ":)", ":-(", ":(", ":'(", ":-p", ":p", ":-P", ":P", ":O", "8)", ":-|", ":|", ":-\\", ":\\", ":-D", ":D", ":-*", "<3", "^_^", ">_<", ";-)"];
const fix = function () {
const input = document.querySelector('[data-testid=conversation-compose-box-input]');
if (input && !fixed.has(input)) {
input.addEventListener("beforeinput", (event) => {
const selection = window.getSelection();
if (selection.rangeCount >= 1) {
const range = selection.getRangeAt(0);
let containers = [range.startContainer, range.endContainer];
let start = range.startOffset;
let end = range.endOffset;
const walker = document.createTreeWalker(input, NodeFilter.SHOW_TEXT);
let node;
while (node = walker.nextNode()) {
if(containers[0] == node && containers[1] == node){
let possible_smiley = node.nodeValue.slice(start-2, start) + event.data;
let found_smiley = volatile.find(smiley => possible_smiley.endsWith(smiley));
if(!(found_smiley === undefined)){
node.nodeValue = node.nodeValue + "\u200B"
start += 1;
end += 1;
selection.removeAllRanges();
const range = document.createRange();
range.setStart(containers[0], start);
range.setEnd(containers[1], end);
selection.addRange(range);
}
}
}
}
});
fixed.add(input);
}
};
window.addEventListener("click", fix);
// window.addEventListener("paste", () => setTimeout(fix, 400));
fix();
}
})();
@nx10
Copy link

nx10 commented Nov 9, 2022

Great! I found some more that get converted currently: 8) :\ :O :P

@oscardianno
Copy link

Sweet, thanks! :D

@sakehl
Copy link
Author

sakehl commented Nov 10, 2022

Great! I found some more that get converted currently: 8) :\ :O :P

Added these emoticons to the list :)

@Tomblarom
Copy link

Finally 😍 Thanks for the effort!

@legeiger
Copy link

Wow really nice! Thank you :)

@shark0der
Copy link

Here's the entire list extracted from their js source:

const _ = "😛"
  , C = {
    "(y)": "👍",
    "(Y)": "👍",
    "(n)": "👎",
    "(N)": "👎",
    ":-)": "🙂",
    ":)": "🙂",
    ":-(": "🙁",
    ":(": "🙁",
    ":-p": _,
    ":-P": _,
    ":P": _,
    ":-\\": "😕",
    ":\\": "😕",
    ":-D": "😀",
    ":D": "😀",
    ":-o": "😮",
    ":O": "😮",
    ";-)": "😉",
    ";)": "😉",
    ":-*": "😘",
    ":-|": "😐",
    ":'(": "😢",
    "^_^": "😁",
    "<3": "❤️",
    ">_<": "😆",
    "8)": "😎"
};

Currently missing 3 more: "(Y)", "(N)", ":'("

@sakehl
Copy link
Author

sakehl commented Nov 10, 2022

Got everything now, thanks!

@AHermann94
Copy link

Hi,
Thank you for the script! But... is there a way to use it without downloading any untrusted add-ons? I tried executing it in the console but it didn't do it still auto-converted my emoticons.

@sakehl
Copy link
Author

sakehl commented Nov 10, 2022

I think it should work with executing in the console. That's how I developed it.

But even then, you'd need to execute it everytime you open web.whatsapp, so I'd say: no it is not possible without using an add-on.

@Tomblarom
Copy link

Emoticons are still being replaced when copy'n'pasting text, that contains one out of the list.

@tomwimmenhove
Copy link

Thank you!

@sirthomasii
Copy link

thank you god

@jemand771
Copy link

a small downside of this is that the searching for emojis e.g. :smile breaks when the search term starts with an "emoji"
e.g. I can't search for :pray because the script kills the :p

I have never written tampermonkey scripts myself and have no clue how to address this, but maybe someone here has an idea 👀

@sabretou
Copy link

You, sir, are a legend 🫡 Thank you for fixing this script!

@shark0der
Copy link

I've created an alternative script that takes a different approach and instead of manipulating the DOM it patches the webpack chunks/functions that do the conversion so instead of undoing the converted emojis it prevents the app from changing them in the first place. Should also fix @jemand771's issue as well as copy-pasting. Will not work by copy-pasting it into the console as it has to be executed before any other javascript loads.

Script here: https://gist.github.com/shark0der/5cae3356dddd21573aaef6d4933ca43c

@sakehl
Copy link
Author

sakehl commented Nov 14, 2022

I've created an alternative script that takes a different approach and instead of manipulating the DOM it patches the webpack chunks/functions that do the conversion so instead of undoing the converted emojis it prevents the app from changing them in the first place. Should also fix @jemand771's issue as well as copy-pasting. Will not work by copy-pasting it into the console as it has to be executed before any other javascript loads.

Script here: https://gist.github.com/shark0der/5cae3356dddd21573aaef6d4933ca43c

Ah, that looks great thanks! This is indeed a very ad-hoc fix, since I did not find out where the conversion exactly happened, and your approach just removes it completely. Great job, thanks!

@ahmetberkinc
Copy link

Perfect! Thanks :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment