NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name WhatsAppOffline
// @namespace https://github.com/ansiwen
// @version 0.1.3
// @description Disable WhatsApp online and message-read status
// @author Sven Anderson
// @homepage https://github.com/ansiwen/userscripts/
// @supportURL https://github.com/ansiwen/userscripts/issues
// @downloadURL https://raw.githubusercontent.com/ansiwen/userscripts/master/whatsappoffline.user.js
// @license AGPL-3.0-or-later; https://www.gnu.org/licenses/agpl-3.0.txt
// @icon https://web.whatsapp.com/favicon.ico
// @match https://web.whatsapp.com/
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// ==/UserScript==
(function() {
'use strict';
var objDefPropOrig = Object.defineProperty;
var presencePatched = false;
var seenPatched = false;
var menuIDs = [];
var offlineConf = "WhatsAppOffline_offlineMode";
var unreadConf = "WhatsAppOffline_unreadMode";
var getConf = function(key) {
var val = window.localStorage.getItem(key);
return val === "false" ? false : true;
}
var setConf = function(key, val) {
return window.localStorage.setItem(key, val);
}
var wrapper = function(f, name, conf, g) {
return function() {
var args = Array.prototype.splice.call(arguments, 0);
if (getConf(conf)) {
if (g) {
console.log("Redirecting", name);
return g.apply(this, args);
} else {
console.log("Intercepting", name);
return Promise.resolve();
}
}
return f.apply(this, args);
};
};
var maybeReset = function() {
if (presencePatched && seenPatched) {
console.log("restoring Object.defineProperty()");
Object.defineProperty = objDefPropOrig;
}
};
var refreshMenu = function() {
for (var id; id = menuIDs.pop();) {
GM_unregisterMenuCommand(id);
};
menuIDs.push(GM_registerMenuCommand(`${getConf(offlineConf) ? "✅" : "⬛"} OfflineMode`, function(){ toggle(offlineConf); }));
menuIDs.push(GM_registerMenuCommand(`${getConf(unreadConf) ? "✅" : "⬛"} UnreadMode`, function(){ toggle(unreadConf); }));
};
var toggle = function(conf) {
console.log("toggled:", conf);
setConf(conf, !getConf(conf));
refreshMenu();
};
refreshMenu();
console.log("patching Object.defineProperty()");
Object.defineProperty = function(obj, prop, desc) {
if (!presencePatched && obj.sendPresenceAvailable && obj.sendPresenceUnavailable) {
console.log("patching sendPresenceAvailable()");
obj.sendPresenceAvailable = wrapper(obj.sendPresenceAvailable, "sendPresenceAvailable", offlineConf, obj.sendPresenceUnavailable);
presencePatched = true;
maybeReset();
}
if (!seenPatched && prop === "__esModule") {
setTimeout(function (){
if (obj.sendSeen) {
console.log("patching sendSeen()");
obj.sendSeen = wrapper(obj.sendSeen, "sendSeen", unreadConf);
seenPatched = true;
maybeReset();
}
});
}
return objDefPropOrig.call(this, obj, prop, desc);
};
})();