-
-
Save istrueuser/89b2fb7f203a7de028e8a77c35fd46f8 to your computer and use it in GitHub Desktop.
Red for 8$, Purple for verified 8$
This file contains 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 @istrueuser Twitter Blue Red - twitter.com | |
// @namespace Violentmonkey Scripts | |
// @match *://*.twitter.com/* | |
// @grant none | |
// @version 1.8.0 | |
// @author @istrueuser - trueuser.tk | |
// @description 4/3/2023, 6:11:21 PM | |
// @updateURL https://gist.githubusercontent.com/istrueuser/89b2fb7f203a7de028e8a77c35fd46f8/raw/twitterblue-nerd.js | |
// @downloadURL https://gist.githubusercontent.com/istrueuser/89b2fb7f203a7de028e8a77c35fd46f8/raw/twitterblue-nerd.js | |
// ==/UserScript== | |
// ORIGINAL BY @chaoticvibing - GH @busybox11 | |
// FORKED FROM https://gist.githubusercontent.com/busybox11/53c76f57a577a47a19fab649a76f18e3/raw/twitterblue-nerd.js | |
// DONATE TO ORIGINAL AUTHOR https://paypal.me/busybox11 | |
// DONATE TO FORK CREATOR https://paypal.me/istrueuser | |
const nerdtick = ` | |
<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" fill="#EE4B2B"></path></g> | |
` | |
let regularVerifiedPath = 'svg 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"]' | |
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" fill="#1D9BF0"></path></g>` | |
const redtick = ` | |
<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" fill="#BF40BF"></path></g> | |
` | |
let otherRegularVerifiedPath = 'svg path[d^="M20.396 11c-.018-.646-.215-1.275-.57-1.816-.354-.54-.852-.972-1.438-1.246.223-.607.27-1.264.14-1.897-.131-.634-.437-1.218-.882-1.687-.47-.445-1.053-.75-1.687-.882-.633-.13-1.29-.083-1.897.14-.273-.587-.704-1.086-1.245-1.44S11.647 1.62 11 1.604c-.646.017-1.273.213-1.813.568s-.969.854-1.24 1.44c-.608-.223-1.267-.272-1.902-.14-.635.13-1.22.436-1.69.882-.445.47-.749 1.055-.878 1.688-.13.633-.08 1.29.144 1.896-.587.274-1.087.705-1.443 1.245-.356.54-.555 1.17-.574 1.817.02.647.218 1.276.574 1.817.356.54.856.972 1.443 1.245-.224.606-.274 1.263-.144 1.896.13.634.433 1.218.877 1.688.47.443 1.054.747 1.687.878.633.132 1.29.084 1.897-.136.274.586.705 1.084 1.246 1.439.54.354 1.17.551 1.816.569.647-.016 1.276-.213 1.817-.567s.972-.854 1.245-1.44c.604.239 1.266.296 1.903.164.636-.132 1.22-.447 1.68-.907.46-.46.776-1.044.908-1.681s.075-1.299-.165-1.903c.586-.274 1.084-.705 1.439-1.246.354-.54.551-1.17.569-1.816zM9.662 14.85l-3.429-3.428 1.293-1.302 2.072 2.072 4.4-4.794 1.347 1.246z"]' | |
// STOLEN FROM https://stackoverflow.com/questions/70507318/how-to-get-react-element-props-from-html-element-with-javascript | |
function getReactProps(parent, target) { | |
parent = parent.wrappedJSObject ?? parent; | |
target = target.wrappedJSObject ?? 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 && props.isVerified) { | |
elem.setAttribute('viewBox', '0 0 24 24') | |
elem.innerHTML = redtick | |
} else if (props.isBlueVerified) { | |
elem.setAttribute('viewBox', '0 0 24 24') | |
elem.innerHTML = nerdtick | |
} else { | |
elem.setAttribute('viewBox', '0 0 24 24') | |
elem.innerHTML = regulartick | |
} | |
} | |
function bluetickHandling(bluetick) { | |
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][propsElem.children[0].length - 1].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) | |
} | |
} | |
function bluetickHandling(bluetick) { | |
let propsElem = getReactProps(bluetick.parentElement.parentElement, bluetick.parentElement) | |
if (propsElem.children !== undefined) { | |
let props; | |
try { | |
props = propsElem.children[0][0].props | |
} catch(e) { | |
propsElem = getReactProps(bluetick.parentElement.parentElement.parentElement.parentElement, bluetick.parentElement.parentElement.parentElement) | |
props = propsElem.children[0][0].props | |
sc.log(props) | |
} | |
if (props.isBlueVerified !== undefined) { | |
updateBlueTick(bluetick, props) | |
} else { | |
const otherProps = propsElem.children[0][propsElem.children[0].length - 1].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) | |
} | |
} | |
function handleMutation(mutations) { | |
try { | |
for (let mutation of mutations) { | |
for (let elem of mutation.addedNodes) { | |
// SVG PATH DETECTION | |
// Thanks GH @artesea - https://gist.github.com/busybox11/53c76f57a577a47a19fab649a76f18e3?permalink_comment_id=4366043#gistcomment-4366043 | |
// Author of this snippet | |
let blueticksPath = elem.querySelectorAll(regularVerifiedPath) | |
let differentBlueticksPath = elem.querySelectorAll(otherRegularVerifiedPath) | |
const blueTicks = [ | |
...blueticksPath, | |
...differentBlueticksPath | |
] | |
for (let bluetick of blueTicks.flat()) { | |
try { | |
if (bluetick !== null) { | |
bluetickHandling(bluetick.parentElement.parentElement) | |
} | |
} catch(e) {sc.log("blueTicks check", bluetick, e)} | |
} | |
// PROFILE POPUPS | |
const profileBlueticks = elem.querySelectorAll('.css-1dbjc4n.r-xoduu5.r-1pcd2l5') | |
try { | |
for (let profileBluetick of profileBlueticks) { | |
if (profileBluetick !== null) { | |
if (profileBluetick.lastChild.firstChild.innerText.includes('Twitter Blue')) { | |
updateBlueTick(profileBluetick.firstChild, {isBlueVerified: true, isVerified: false}) | |
} | |
} | |
} | |
} catch(e) {sc.log(e)} | |
} | |
} | |
} catch(e) {sc.log(e)} | |
} | |
const sc = { | |
log: (...args) => { | |
console.log('[nerdtick]', ...args) | |
} | |
} | |
const observer = new MutationObserver(handleMutation) | |
observer.observe(document, { childList: true, subtree: true }) |
The correct update and download URLs are https://gist.githubusercontent.com/istrueuser/89b2fb7f203a7de028e8a77c35fd46f8/raw/twitterblue-nerd.js without the version-component between the raw
and the twitterblue-nerd.js
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would like to suggest adding
fill="#1D9BF0"
to the regulartick SVG data. That way it would make anyone using dark mode consistently see blue checkmarks instead of white ones for actual verified accounts.Also, I noticed that if I click on a red checkmark profile in the "You Might Like" section to the right on profile pages, when it loads the red checkmark profile it shows the default-colored checkmark (white for dark mode, blue for light mode). If I refresh the page, it then correctly shows a red checkmark.