-
-
Save waxpancake/0abb39e04f053a0fc989c8ade720fb09 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name @chaoticvibing Twitter Blue Clown - twitter.com | |
// @namespace Violentmonkey Scripts | |
// @match *://*.twitter.com/* | |
// @grant none | |
// @version 1.1.2 | |
// @author @chaoticvibing - GH @busybox11 | |
// @description 11/9/2022, 18:45:28 PM | |
// @updateURL https://gist.github.com/waxpancake/0abb39e04f053a0fc989c8ade720fb09 | |
// @downloadURL https://gist.github.com/waxpancake/0abb39e04f053a0fc989c8ade720fb09 | |
// ==/UserScript== | |
/* | |
* DISCLAIMER | |
* I made this in a rush because of a challenge I convinced myself to do in reply to a tweet: | |
* https://twitter.com/Quinten0508/status/1590464705822224384?s=20&t=R_KhoR4a-_3fI4n4mbmmGA | |
* It might have horrible performance and it could not be reliable as I've tested this very quickly | |
* on some places I could find Twitter blue checkmarks, but I haven't made much research on it. | |
* At least it runs fine on my Ryzen 9 5900HS laptop and I don't see any noticeable frame drops | |
* on my 165Hz QHD display since I made this script, which might be a sign it's not impacting much. | |
* (I don't care anyway, fell free to modify it if it isn't) | |
*/ | |
// 1.1.0 ALSO UPDATE ON HEADER OF PROFILE | |
// 1.1.1 AUTO UPDATE | |
// 1.1.2 CHANGED TO CLOWN ICON BY @WAXPANCAKE | |
// STOLEN FROM https://twitter.com/shadowbIood/status/1590462560515473409?s=20&t=AmfQmmFgdpKOsPqnoawjVQ | |
const clowntick = ` | |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"> | |
<circle fill="#4289C1" cx="29" cy="3" r="2"/><circle fill="#4289C1" cx="33" cy="8" r="3"/><circle fill="#4289C1" cx="33" cy="4" r="3"/> | |
<circle fill="#4289C1" cx="7" cy="3" r="2"/><circle fill="#4289C1" cx="3" cy="8" r="3"/><circle fill="#4289C1" cx="3" cy="4" r="3"/> | |
<path fill="#FEE7B8" d="M36 18c0 9.941-8.059 18-18 18S0 27.941 0 18 8.059 0 18 0s18 8.059 18 18"/> | |
<circle fill="#4289C1" cx="30.5" cy="4.5" r="2.5"/><circle fill="#4289C1" cx="32" cy="7" r="2"/> | |
<circle fill="#4289C1" cx="5.5" cy="4.5" r="2.5"/><circle fill="#4289C1" cx="4" cy="7" r="2"/> | |
<circle fill="#FF7892" cx="6.93" cy="21" r="4"/><circle fill="#FF7892" cx="28.93" cy="21" r="4"/> | |
<path fill="#DA2F47" d="M27.335 23.629c-.178-.161-.444-.171-.635-.029-.039.029-3.922 2.9-8.7 2.9-4.766 0-8.662-2.871-8.7-2.9-.191-.142-.457-.13-.635.029-.177.16-.217.424-.094.628C8.7 24.472 11.788 31 18 31s9.301-6.528 9.429-6.743c.123-.205.084-.468-.094-.628z"/> | |
<ellipse fill="#664500" cx="11.5" cy="11.5" rx="2.5" ry="3.5"/> | |
<ellipse fill="#664500" cx="25.5" cy="11.5" rx="2.5" ry="3.5"/><circle fill="#BB1A34" cx="18.5" cy="19.5" r="3.5"/> | |
</svg> | |
` | |
const regulartick = ` | |
<g><path d="M22.25 12c0-1.43-.88-2.67-2.19-3.34.46-1.39.2-2.9-.81-3.91s-2.52-1.27-3.91-.81c-.66-1.31-1.91-2.19-3.34-2.19s-2.67.88-3.33 2.19c-1.4-.46-2.91-.2-3.92.81s-1.26 2.52-.8 3.91c-1.31.67-2.2 1.91-2.2 3.34s.89 2.67 2.2 3.34c-.46 1.39-.21 2.9.8 3.91s2.52 1.26 3.91.81c.67 1.31 1.91 2.19 3.34 2.19s2.68-.88 3.34-2.19c1.39.45 2.9.2 3.91-.81s1.27-2.52.81-3.91c1.31-.67 2.19-1.91 2.19-3.34zm-11.71 4.2L6.8 12.46l1.41-1.42 2.26 2.26 4.8-5.23 1.47 1.36-6.2 6.77z"></path></g> | |
` | |
// STOLEN FROM https://stackoverflow.com/questions/70507318/how-to-get-react-element-props-from-html-element-with-javascript | |
function getReactProps(parent, target) { | |
const keyof_ReactProps = Object.keys(parent).find(k => k.startsWith("__reactProps$")); | |
const symof_ReactFragment = Symbol.for("react.fragment"); | |
//Find the path from target to parent | |
let path = []; | |
let elem = target; | |
while (elem !== parent) { | |
let index = 0; | |
for (let sibling = elem; sibling != null;) { | |
if (sibling[keyof_ReactProps]) index++; | |
sibling = sibling.previousElementSibling; | |
} | |
path.push({ child: elem, index }); | |
elem = elem.parentElement; | |
} | |
//Walk down the path to find the react state props | |
let state = elem[keyof_ReactProps]; | |
for (let i = path.length - 1; i >= 0 && state != null; i--) { | |
//Find the target child state index | |
let childStateIndex = 0, childElemIndex = 0; | |
while (childStateIndex < state.children.length) { | |
let childState = state.children[childStateIndex]; | |
if (childState instanceof Object) { | |
//Fragment children are inlined in the parent DOM element | |
let isFragment = childState.type === symof_ReactFragment && childState.props.children.length; | |
childElemIndex += isFragment ? childState.props.children.length : 1; | |
if (childElemIndex === path[i].index) break; | |
} | |
childStateIndex++; | |
} | |
let childState = state.children[childStateIndex] ?? (childStateIndex === 0 ? state.children : null); | |
state = childState?.props; | |
elem = path[i].child; | |
} | |
return state; | |
} | |
function updateBlueTick(elem, props) { | |
if (props.isBlueVerified) { | |
elem.setAttribute('viewBox', '0 0 96 96') | |
elem.innerHTML = clowntick | |
} else { | |
elem.setAttribute('viewBox', '0 0 24 24') | |
elem.innerHTML = regulartick | |
} | |
} | |
function handleMutation(mutations) { | |
try { | |
for (mutation of mutations) { | |
for (elem of mutation.addedNodes) { | |
const blueticks = elem.querySelectorAll('[aria-label="Verified account"]') | |
for (bluetick of blueticks) { | |
if (bluetick !== null) { | |
const propsElem = getReactProps(bluetick.parentElement, bluetick) | |
if (propsElem.children !== undefined) { | |
const props = propsElem.children[0][0].props | |
updateBlueTick(bluetick, props) | |
} else { | |
const propsElemParent = getReactProps(bluetick.parentElement.parentElement.parentElement, bluetick.parentElement.parentElement) | |
const propsParent = propsElemParent.children[0][0].props | |
updateBlueTick(bluetick, propsParent) | |
} | |
} | |
} | |
} | |
} | |
} catch(e) {console.log(e)} | |
} | |
const observer = new MutationObserver(handleMutation) | |
observer.observe(document, { childList: true, subtree: true }) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment