Skip to content

Instantly share code, notes, and snippets.

@JakeLunn
Forked from busybox11/twitterblue-clown.js
Created November 10, 2022 20:53
Show Gist options
  • Save JakeLunn/dc842c006da3fb7d14dfbd59a9a723ec to your computer and use it in GitHub Desktop.
Save JakeLunn/dc842c006da3fb7d14dfbd59a9a723ec to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name @chaoticvibing Twitter Blue Clown - twitter.com
// @namespace Violentmonkey Scripts
// @match *://*.twitter.com/*
// @grant none
// @version 1.2.2clown
// @author @chaoticvibing - GH @busybox11
// @description 11/9/2022, 11:45:28 PM
// @updateURL https://gist.githubusercontent.com/busybox11/270a9ca89a26c79f467f214761303242/raw/twitterblue-nerd.js
// @downloadURL https://gist.githubusercontent.com/busybox11/270a9ca89a26c79f467f214761303242/raw/twitterblue-nerd.js
// ==/UserScript==
// YOU'RE FREE TO DO WHATEVER YOU WANT WITH THIS SCRIPT BUT IF YOU DO MAKE SOMETHING
// PLEASE MAKE SURE TO MENTION ME SOMEWHERE - I hope you'll understand why :)
// Also https://paypal.me/busybox11 because I am broke
/* INSTRUCTIONS
*
* - Install a userscript browser extension
* (I used ViolentMonkey https://chrome.google.com/webstore/detail/violentmonkey/jinjaccalgkegednnccohejagnlnfdag,
* but you can use any extension you want, such as tampermonkey, it should work fine)
* FIREFOX USERS: It seems to work better with TamperMonkey: https://addons.mozilla.org/fr/firefox/addon/tampermonkey/
* - Import the script
* On ViolentMonkey, click on the extension icon, then gear icon (Open dashboard)
* There should be a plus icon on the top left hand corner, click on it and select Install from URL
* Use this URL: https://gist.githubusercontent.com/busybox11/270a9ca89a26c79f467f214761303242/raw/twitterblue-nerd.js
* It should now work and update by itself
*
*/
/*
* 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 Better handling of verified notifications
// 1.1.3 Better error logging
// 1.2.0 INITIAL VERY WIP FIREFOX SUPPORT
// 1.2.1 Misc code quality changes
// 1.2.2clown Clown version
// STOLEN FROM https://twitter.com/shadowbIood/status/1590462560515473409?s=20&t=AmfQmmFgdpKOsPqnoawjVQ
const nerdtick = `
<g>
<path d="m37.724 16.691c1.073-3.147 0.907-6.541-0.467-9.558s-3.792-5.293-6.807-6.414c-4.546-1.687-9.569-0.321-12.769 3.242-2.339-0.935-4.893-0.993-7.297-0.15-2.737 0.961-4.952 2.977-6.237 5.676-1.141 2.398-1.421 5.1-0.828 7.655-1.161 1.266-2.055 2.776-2.625 4.449-2.14 6.28 0.837 13.183 6.659 15.724 0.202 0.088 0.407 0.171 0.615 0.248 3.812 1.414 7.999 0.741 11.23-1.8 1.744-1.172 6.853-5.936 9.194-8.195 8.385-8.097 9.074-10.117 9.332-10.877zm29.885 10.954c2.341 2.26 7.45 7.024 9.194 8.195 3.231 2.541 7.418 3.215 11.23 1.8 0.208-0.078 0.413-0.16 0.615-0.248 5.823-2.541 8.799-9.444 6.659-15.724-0.569-1.673-1.464-3.183-2.625-4.449 0.592-2.556 0.313-5.257-0.828-7.655-1.285-2.7-3.499-4.715-6.237-5.677-2.404-0.844-4.958-0.785-7.297 0.15-3.2-3.563-8.223-4.929-12.769-3.242-3.015 1.121-5.433 3.397-6.807 6.414s-1.54 6.411-0.467 9.558c0.258 0.76 0.946 2.78 9.332 10.878z" fill="#0092FF"/>
<path d="m92.224 52.048c0-6.944-3.685-12.966-9.046-15.823 0.649-1.912 1.002-3.978 1.002-6.153 0-9.713-7.202-17.572-16.08-17.572-1.979 0-3.875 0.369-5.627 1.099-2.603-5.876-8.111-9.898-14.471-9.898s-11.86 4.03-14.475 9.889c-1.748-0.725-3.647-1.099-5.627-1.099-8.886 0-16.08 7.867-16.08 17.581 0 2.171 0.35 4.237 0.998 6.153-5.357 2.857-9.042 8.87-9.042 15.823 0 6.571 3.293 12.298 8.179 15.322-0.084 0.747-0.135 1.494-0.135 2.259 0 9.713 7.193 17.581 16.08 17.581 1.979 0 3.875-0.378 5.622-1.099 2.612 5.863 8.113 9.889 14.476 9.889 6.368 0 11.868-4.026 14.475-9.889 1.748 0.716 3.643 1.09 5.627 1.09 8.886 0 16.08-7.867 16.08-17.581 0-0.765-0.051-1.512-0.139-2.255 4.877-3.02 8.183-8.746 8.183-15.313v-4e-3z" fill="#FEE7B8"/>
<ellipse cx="23.209" cy="52.616" rx="7.894" ry="6.077" fill="#F97E58"/>
<ellipse cx="76.004" cy="52.616" rx="7.894" ry="6.077" fill="#F97E58"/>
<path d="m49.31 83.149c-7.662 0-14.99-3.42-20.104-9.382-2.282-2.66-2.065-6.748 0.484-9.129 2.549-2.382 6.466-2.155 8.748 0.505 2.767 3.226 6.729 5.076 10.872 5.076 4.142 0 8.105-1.85 10.872-5.076 2.282-2.661 6.199-2.887 8.748-0.505 2.55 2.381 2.766 6.469 0.484 9.129-5.115 5.962-12.442 9.382-20.104 9.382z" fill="#c33"/>
<path d="m49.31 77.429c-6.106 0-11.945-2.726-16.021-7.478-0.263-0.307-0.238-0.779 0.056-1.053 0.294-0.275 0.746-0.249 1.009 0.058 3.805 4.436 9.256 6.98 14.956 6.98 5.699 0 11.15-2.544 14.955-6.98 0.263-0.307 0.715-0.334 1.01-0.058 0.294 0.274 0.319 0.746 0.056 1.053-4.076 4.753-9.916 7.478-16.021 7.478z" fill="#FF6700"/>
<path d="m59.623 50.864c0 5.773-4.484 10.452-10.016 10.452s-10.016-4.679-10.016-10.452 4.484-10.453 10.016-10.453 10.016 4.68 10.016 10.453z" fill="#c33"/>
<ellipse cx="31.103" cy="28.795" rx="5.889" ry="9.573" fill="#282D35"/>
<ellipse cx="65.513" cy="28.795" rx="5.889" ry="9.573" fill="#282D35"/>
</g>
`
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) {
// INITIAL VERY WIP FIREFOX HANDLING
parent = (window.chrome) ? parent : parent.wrappedJSObject;
target = (window.chrome) ? target : target.wrappedJSObject;
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 = nerdtick
} else {
elem.setAttribute('viewBox', '0 0 24 24')
elem.innerHTML = regulartick
}
}
function handleMutation(mutations) {
try {
for (let mutation of mutations) {
for (let elem of mutation.addedNodes) {
const blueticks = elem.querySelectorAll('[aria-label="Verified account"]')
try {
for (let bluetick of blueticks) {
if (bluetick !== null) {
let propsElem = getReactProps(bluetick.parentElement, bluetick)
if (propsElem.children !== undefined) {
const props = propsElem.children[0][0].props
if (props.isBlueVerified !== undefined) {
updateBlueTick(bluetick, props)
} else {
// VERY HACKY FIX DO BETTER NEXT TIME
const otherProps = propsElem.children[0][2].props
updateBlueTick(bluetick, otherProps)
}
} 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)}
}
}
} catch(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