Fuck Elon Musk! Let's bring Twitter back.
// ==UserScript==
// @name Fuck Elon Musk
// @namespace https://greasyfork.org/scripts/471597-elon-musk
// @version 0.7.0
// @description Fuck Elon Musk! Let's bring Twitter back.
// @author Ray (https://github.com/so1ve)
// @license MIT
// @run-at document-start
// @homepageURL https://github.com/so1ve/fuck-elonmusk
// @supportURL https://github.com/so1ve/fuck-elonmusk
// @match https://twitter.com/**
// @grant GM_addStyle
// ==/UserScript==
(() => {
"use strict";
const COLOR_CSS =
'.__FUCK_MUSK_BLUE__ { color: rgb(29, 155, 240) !important; } @media (prefers-color-scheme: dark) { a[href="/home"][aria-label="Twitter"] .__FUCK_MUSK_BLUE__ { color: rgb(231, 233, 234) !important; } }';
const TWITTER_LOGO_G = `<g><path d="M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z"></path></g>`;
const TWITTER_LOGO = `<svg viewBox="0 0 24 24" aria-hidden="true" class="__FUCK_MUSK_BLUE__ r-4qtqp9 r-yyyyoo r-16y2uox r-8kz0gk r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-lrsllp">${TWITTER_LOGO_G}</svg>`;
/** @see https://greasyfork.org/zh-CN/scripts/471576-f-kelonmusk-twitter-com */
const TWITTER_LOGO_FOR_SHORTCUT_ICON = `data:image/svg+xml,%3Csvg width='500' height='500' viewBox='0 0 500 500' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3Etwitter-logo%3C/title%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M170.2264 442.7654c162.2648 0 251.0168-140.0367 251.0168-261.4758 0-3.9775 0-7.9371-.258-11.8788 17.2659-13.009 32.1701-29.1167 44.0148-47.5687-16.1013 7.4318-33.1817 12.3057-50.6712 14.4587 18.4168-11.4849 32.2005-29.5486 38.786-50.8295-17.3177 10.7044-36.2637 18.2483-56.0204 22.3062-27.3466-30.29-70.8-37.7036-105.9942-18.0837-35.194 19.62-53.3763 61.3941-44.351 101.8979-70.9346-3.7043-137.0242-38.6047-181.8212-96.0154-23.4157 41.9903-11.4554 95.7083 27.3136 122.6754-14.0397-.4335-27.7732-4.3786-40.0416-11.5025v1.1646c.0115 43.7452 29.6141 81.4229 70.778 90.085-12.9882 3.6897-26.6156 4.229-39.8352 1.5766 11.5575 37.4355 44.6783 63.0807 82.4224 63.8192-31.2398 25.5748-69.831 39.4584-109.564 39.4166A172.495 172.495 0 0 1 35 401.4854c40.345 26.9696 87.2885 41.275 135.2264 41.2083' fill='%231DA1F2'/%3E%3Cpath d='M35 35h430v430H35z'/%3E%3C/g%3E%3C/svg%3E%0A`;
const FUCKER_X =
'<g><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></g>';
/**
* @param {string} selector
* @returns {Promise<HTMLElement[]>}
*/
const waitForElements = (selector) =>
new Promise((resolve) => {
if (document.querySelectorAll(selector).length > 0) {
return resolve(document.querySelectorAll(selector));
}
const observer = new MutationObserver(() => {
if (document.querySelectorAll(selector).length > 0) {
resolve(document.querySelectorAll(selector));
observer.disconnect();
}
});
try {
observer.observe(document.body, {
childList: true,
subtree: true,
});
} catch {
// If failed, try again after 100ms
setTimeout(() => {
resolve(waitForElements(selector));
}, 100);
}
});
const createObserver = (valueToWatch) => (callback) => {
let oldValue = valueToWatch();
const observer = new MutationObserver(() => {
if (oldValue !== valueToWatch()) {
oldValue = valueToWatch();
callback();
}
});
function observe() {
observer.observe(document.body, {
childList: true,
subtree: true,
});
}
const timer = setInterval(() => {
if (document.body) {
clearInterval(timer);
observe();
}
}, 100);
};
const observeUrlChange = createObserver(() => document.location.href);
const observeTitleChange = createObserver(() => document.title);
const ICON_SELECTOR = 'link[rel="shortcut icon"]';
const LOGO_SELECTOR = 'a[href="/home"][aria-label="Twitter"]';
const NAVBAR_LOGO_SELECTOR =
'div[data-testid="TopNavBar"] > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(2)';
const PLACEHOLDER_SELECTOR = "#placeholder";
const HOMEPAGE_ICON_SELECTOR = "main > div > div > div > div > div > svg";
const HOMEPAGE_LEFT_ICON_SELECTOR =
"main > div > div > div > div:nth-child(2) > div > svg";
const LOGOUT_ICON_SELECTOR =
'div[data-testid="confirmationSheetDialog"] > svg';
const NOTIFICATIONS_SELECTOR = "article";
const createStyleMaker =
(selector) =>
/** @param {boolean} show */
(show) =>
`${selector} { display: ${show ? "flex" : "none"}; }`;
const makeTwitterLogoStyle = createStyleMaker(LOGO_SELECTOR);
const makeTwitterNavbarLogoStyle = createStyleMaker(NAVBAR_LOGO_SELECTOR);
const makePlaceholderStyle = createStyleMaker(PLACEHOLDER_SELECTOR);
const makeHomepageIconStyle = createStyleMaker(HOMEPAGE_ICON_SELECTOR);
const makeHomepageLeftIconStyle = createStyleMaker(
HOMEPAGE_LEFT_ICON_SELECTOR,
);
const makeLogoutIconStyle = createStyleMaker(LOGOUT_ICON_SELECTOR);
function initChangers() {
GM_addStyle(COLOR_CSS);
waitForElements(ICON_SELECTOR).then(([iconEl]) => {
iconEl.href = TWITTER_LOGO_FOR_SHORTCUT_ICON;
});
GM_addStyle(makePlaceholderStyle(false));
waitForElements(PLACEHOLDER_SELECTOR).then(([placeholder]) => {
placeholder.children[0].innerHTML = TWITTER_LOGO;
GM_addStyle(makePlaceholderStyle(true));
});
GM_addStyle(makeTwitterLogoStyle(false));
waitForElements(LOGO_SELECTOR).then(([a]) => {
a.children[0].innerHTML = TWITTER_LOGO;
GM_addStyle(makeTwitterLogoStyle(true));
});
if (location.pathname === "/") {
GM_addStyle(makeHomepageIconStyle(false));
waitForElements(HOMEPAGE_ICON_SELECTOR).then(([svg]) => {
svg.classList.add("__FUCK_MUSK_BLUE__");
svg.innerHTML = TWITTER_LOGO_G;
GM_addStyle(makeHomepageIconStyle(true));
});
GM_addStyle(makeHomepageLeftIconStyle(false));
waitForElements(HOMEPAGE_LEFT_ICON_SELECTOR).then(([svg]) => {
svg.innerHTML = TWITTER_LOGO_G;
GM_addStyle(makeHomepageLeftIconStyle(true));
});
}
if (location.pathname === "/home") {
GM_addStyle(makeTwitterNavbarLogoStyle(false));
waitForElements(NAVBAR_LOGO_SELECTOR).then(([div]) => {
div.children[1].classList.add("__FUCK_MUSK_BLUE__");
div.children[1].innerHTML = TWITTER_LOGO;
GM_addStyle(makeTwitterNavbarLogoStyle(true));
});
}
if (location.pathname === "/logout") {
GM_addStyle(makeLogoutIconStyle(false));
waitForElements(LOGOUT_ICON_SELECTOR).then(([svg]) => {
svg.classList.add("__FUCK_MUSK_BLUE__");
svg.innerHTML = TWITTER_LOGO_G;
GM_addStyle(makeLogoutIconStyle(true));
});
}
if (location.pathname === "/notifications") {
waitForElements(NOTIFICATIONS_SELECTOR).then((notifications) => {
for (const notification of notifications) {
const svg = notification.children[0].children[0].children[0];
if (svg.innerHTML === FUCKER_X) {
svg.classList.add("__FUCK_MUSK_BLUE__");
svg.innerHTML = TWITTER_LOGO_G;
}
}
});
}
}
initChangers();
observeUrlChange(initChangers);
window.addEventListener("resize", initChangers);
observeTitleChange(() => {
if (document.title.endsWith("X")) {
document.title = `${document.title.slice(0, -1)}Twitter`;
}
});
})();