Skip to content

Instantly share code, notes, and snippets.

@busybox11
Last active November 13, 2024 18:48
Show Gist options
  • Save busybox11/53c76f57a577a47a19fab649a76f18e3 to your computer and use it in GitHub Desktop.
Save busybox11/53c76f57a577a47a19fab649a76f18e3 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name @chaoticvibing Twitter Blue Nerd - twitter.com
// @namespace Violentmonkey Scripts
// @match *://*.twitter.com/*
// @match *://*.x.com/*
// @grant none
// @version 1.9.2
// @author @chaoticvibing - GH @busybox11
// @description 11/9/2022, 11:45:28 PM
// @updateURL https://gist.githubusercontent.com/busybox11/53c76f57a577a47a19fab649a76f18e3/raw
// @downloadURL https://gist.githubusercontent.com/busybox11/53c76f57a577a47a19fab649a76f18e3/raw
// ==/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
// 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.3.0 MADE IT WORK WITH THEORETICALLY ALL NOTIFICATIONS
// 1.4.0 ALSO SHOW ON PROFILE VERIFICATION POPUP
// 1.5.0 WIP SHOULD WORK ON ALL LANGUAGES
// 1.6.0 PATH-BASED BLUE CHECK DETECTION
// 1.7.0 SOMEHOW FIXES NEWER FIREFOX VERSIONS
// 1.7.1 FIREFOX AGAIN...
// 1.8.0 TWITTER CHANGED STUFF AGAIN PLEASE SEND HELP
// 1.9.0 UPDATED POPUP BECAUSE TWITTER (elon) HAVE DECIDED TO BE DUMB (thanks @tom-wharf for the update!)
/*
* 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/53c76f57a577a47a19fab649a76f18e3/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)
*
*/
// STOLEN FROM https://twitter.com/shadowbIood/status/1590462560515473409?s=20&t=AmfQmmFgdpKOsPqnoawjVQ
const nerdtick = `
<path d="M89 48C89 42.28 85.48 37.32 80.24 34.64C82.08 29.08 81.04 23.04 77 19C72.96 14.96 66.92 13.92 61.36 15.76C58.72 10.52 53.72 7 48 7C42.28 7 37.32 10.52 34.68 15.76C29.08 13.92 23.04 14.96 19 19C14.96 23.04 13.96 29.08 15.8 34.64C10.56 37.32 7 42.28 7 48C7 53.72 10.56 58.68 15.8 61.36C13.96 66.92 14.96 72.96 19 77C23.04 81.04 29.08 82.04 34.64 80.24C37.32 85.48 42.28 89 48 89C53.72 89 58.72 85.48 61.36 80.24C66.92 82.04 72.96 81.04 77 77C81.04 72.96 82.08 66.92 80.24 61.36C85.48 58.68 89 53.72 89 48Z" fill="#FFCC4D"/>
<path d="M80 47C80 64.6729 65.6729 79 48 79C30.3271 79 16 64.6729 16 47C16 29.3271 30.3271 15 48 15C65.6729 15 80 29.3271 80 47Z" fill="#FFCC4D"/>
<path d="M64.4846 57.0069C64.1681 56.7207 63.6952 56.7029 63.3557 56.9554C63.2864 57.0069 56.3832 62.1109 47.889 62.1109C39.4161 62.1109 32.4899 57.0069 32.4224 56.9554C32.0828 56.7029 31.6099 56.7243 31.2935 57.0069C30.9788 57.2914 30.9077 57.7607 31.1264 58.1234C31.3557 58.5056 36.8455 67.4443 47.889 67.4443C58.9326 67.4443 64.4241 58.5056 64.6517 58.1234C64.8704 57.7589 64.801 57.2914 64.4846 57.0069Z" fill="#664500"/>
<path d="M47.8892 62.2729C47.6261 62.2729 47.3719 62.2533 47.1123 62.2444V70.2729H48.6661V62.2427C48.4065 62.2516 48.1523 62.2729 47.8892 62.2729Z" fill="#65471B"/>
<path d="M55.0003 61.2222C55.0288 61.2151 52.4225 61.8942 50.6519 62.0862C50.0012 62.1609 49.3416 62.2196 48.6661 62.2427V70.2729H51.4448C53.4003 70.2729 55.0003 68.6729 55.0003 66.7173V64.4738V61.2222Z" fill="white"/>
<path d="M40.7781 61.2222C40.7496 61.2151 43.3559 61.8942 45.1265 62.0862C45.7772 62.1609 46.4368 62.2196 47.1123 62.2427V70.2729H44.3336C42.3781 70.2729 40.7781 68.6729 40.7781 66.7173V64.4738V61.2222Z" fill="white"/>
<path d="M64.4846 57.0069C64.1681 56.7207 63.6952 56.7029 63.3557 56.9554C63.3041 56.9945 59.3397 59.9207 53.7361 61.3465C52.9486 61.5456 50.4224 62.1109 47.8944 62.1109C45.3628 62.1109 42.8295 61.5456 42.0419 61.3465C36.4384 59.9207 32.4757 56.9945 32.4224 56.9554C32.0846 56.7029 31.6099 56.7207 31.2935 57.0069C30.9788 57.2914 30.9077 57.7589 31.1281 58.1234C31.2988 58.4114 34.4775 63.5758 40.7779 66.0896V62.838C40.7495 62.8309 43.3557 63.51 45.1264 63.702C45.777 63.7767 46.4366 63.8354 47.1121 63.8585V63.8603C47.3717 63.8692 47.6259 63.8887 47.889 63.8887C48.1521 63.8887 48.4064 63.8692 48.6677 63.8603V63.8585C49.3415 63.8354 50.001 63.7767 50.6517 63.702C52.4224 63.51 55.0286 62.8309 55.0001 62.838V66.0896C61.3006 63.5758 64.4792 58.4114 64.6517 58.1234C64.8704 57.7589 64.801 57.2914 64.4846 57.0069Z" fill="#65471B"/>
<path d="M63.3323 39.9317C63.3323 42.9788 61.6647 45.45 59.606 45.45C57.5492 45.45 55.8816 42.9788 55.8816 39.9317C55.8816 36.8846 57.5492 34.4135 59.606 34.4135C61.6647 34.4135 63.3323 36.8846 63.3323 39.9317Z" fill="#65471B"/>
<path d="M70.9184 38.1545C70.7068 39.8505 70.1451 44.4034 68.6695 45.5038C67.4891 46.3838 64.4704 47.0007 62.2926 47.0007H62.2908C60.3246 47.0007 58.4455 46.4994 57.0037 45.6798C54.6517 44.3412 54.3015 40.5918 54.1646 38.6274C54.0882 37.5465 53.8517 35.3385 55.6384 34.2398C57.6562 32.9989 61.7931 32.9136 63.0251 32.9136C65.7148 32.9136 68.3442 33.406 70.2286 34.0478C71.4162 34.4532 71.0535 37.0754 70.9184 38.1545ZM41.9815 38.6043C41.8428 40.5687 41.4944 44.3412 39.1424 45.6798C37.6988 46.4994 35.8215 47.0007 33.8535 47.0007H33.8517C31.674 47.0007 28.6553 46.3838 27.4748 45.5038C25.9993 44.4034 25.4393 39.8736 25.226 38.1794C25.0908 37.1003 24.73 34.462 25.9157 34.0567C27.802 33.4149 30.4295 32.9136 33.1193 32.9136C34.3513 32.9136 38.4899 32.99 40.5059 34.2309C42.2926 35.3296 42.0562 37.5234 41.9815 38.6043ZM80.882 32.1154C80.578 31.8185 75.6295 32.6025 73.6579 31.598C69.5904 29.5252 59.3113 27.5234 52.6197 32.2647C51.9033 32.7732 48.9095 32.8585 48.0722 32.8212C47.2366 32.8585 44.2411 32.7732 43.5246 32.2647C36.8348 27.5234 26.5539 29.5252 22.4882 31.598C20.5148 32.6025 15.5664 31.8185 15.2642 32.1154C14.8233 32.5403 14.8251 34.2416 15.2642 34.6665C15.7015 35.0914 20.89 35.582 21.3255 36.8585C21.7646 38.1349 21.7682 45.6727 25.2615 48.2772C28.5291 50.7163 36.1557 51.4505 40.9895 48.702C45.2082 46.302 45.0588 41.2532 45.8322 38.2469C46.1077 37.1732 46.8846 36.6327 48.0722 36.6327C49.2615 36.6327 50.0366 37.1732 50.3122 38.2469C51.0855 41.2532 50.938 46.302 55.1548 48.702C59.9886 51.4505 67.6153 50.7163 70.8846 48.2772C74.3779 45.6727 74.3815 38.1349 74.8188 36.8585C75.2544 35.582 80.4428 35.0914 80.8802 34.6665C81.3211 34.2416 81.3211 32.5403 80.882 32.1154Z" fill="#292F33"/>
<path d="M32.8126 39.9317C32.8126 42.9788 34.4802 45.45 36.5388 45.45C38.5957 45.45 40.2633 42.9788 40.2633 39.9317C40.2633 36.8846 38.5957 34.4135 36.5388 34.4135C34.4802 34.4135 32.8126 36.8846 32.8126 39.9317Z" fill="#65471B"/>
`
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"]'
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"]'
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>
`
// EDITED, 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) {
elem.setAttribute('viewBox', '0 0 96 96')
elem.innerHTML = nerdtick
} else {
elem.setAttribute('viewBox', '0 0 24 24')
elem.innerHTML = regulartick
}
}
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) {
let tickChild = profileBluetick.firstChild
let tickChildProps = getReactProps(profileBluetick.parentElement, profileBluetick)
updateBlueTick(tickChild, tickChildProps)
}
}
} 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 })
@spacesynth
Copy link

@phiter
https://gist.github.com/vaporwave9/bc03970747598ca7f28865d8a8e96894
The old method + artesea's & your tweaks work good. I could not use the new method as it slowed my browser because CanvasBlocker didn't work well with 1.6.0 or their changes.

grafik

Right now on my forked 1.5.2 everything is fast.

@hopkapi
Copy link

hopkapi commented Nov 12, 2022

Anyone know why in Safari (via the Userscripts extension), the changed icon only shows up on the popup after I click the official verified icon on someone's profile? Only thing I can see in the console related to the extension is a bunch of the below messages referencing line 203 of the script:

TypeError: undefined is not an object (evaluating 'propsElem.children') bluetickHandling handleMutation

@Ph4nt0mRM
Copy link

image

Works on mozilla with goodtwitter! Nice job!

@srifqi
Copy link

srifqi commented Nov 16, 2022

On Firefox 107 (64-bit), I removed these lines in getReactProps():

// INITIAL VERY WIP FIREFOX HANDLING
parent = (window.chrome) ? parent : parent.wrappedJSObject;
target = (window.chrome) ? target : target.wrappedJSObject;

to make it work.

@BrixsterPlanet
Copy link

On Firefox 107 (64-bit), I removed these lines in getReactProps():

// INITIAL VERY WIP FIREFOX HANDLING
parent = (window.chrome) ? parent : parent.wrappedJSObject;
target = (window.chrome) ? target : target.wrappedJSObject;

to make it work.

Amazing fix, thank you so much. 🙏

@busybox11
Copy link
Author

Huh, firefox support seems very hit or miss, sometimes the userscripts extensions seem to expose properties when others do not, I don't really know how to handle this. Glad it fixed it for you, weird thing is that it didn't work on firefox before without this haha

@TylerGlaiel
Copy link

stopped working for these types of notifications (still works for tweets in the timeline and profile views)

image

@TylerGlaiel
Copy link

ah its also starting to not work on profiles as well

@Russcool-TM
Copy link

How does it work with the millions of different verified categories now, such as Legacy vs Brand verification? I've seen it apply nerd emojis to accounts I know are Legacy verified accounts, although Twitter claims they subscribed to Twitter Blue.

@Suznyan
Copy link

Suznyan commented Feb 18, 2023

Is there anyway to whitelist some accounts?

@real-wolf
Copy link

ah its also starting to not work on profiles as well

this issue is solved in firefox by commenting out lines 80 and 81

@busybox11
Copy link
Author

Hey, going back on this gist. Apologies for the late reply, I've been pretty busy lately.
@TylerGlaiel @real-wolf I don't see any issues on my side, Chrome and Firefox. What version / extension script host do you use?

@Russcool-TM If is it blue verified of some sort with a "legacy-style" checkbox, it will replace it, basically.

@Suznyan Currently there is no built-in feature that can do this, but it might be a cool thing to add. Will take a look at it as soon as I have some free time - it might take a long time though, apologies for that.

@busybox11
Copy link
Author

I was able to replicate the issue only on firefox. It was not the case for me until yesterday or today apparently, because it worked great until then. It's probably some kind of upstream update that did not happen for me, until now.
Will probably take a look at it overnight. I'll keep you updated.

@busybox11
Copy link
Author

I just updated the script, you can update it with your extension's UI!

@real-wolf was right, the commenting trick seems to work. I'll have to check if this also work on older firefox versions, as this seems to be a fairly recent change in Firefox's JS DOM implementation. For now, as everyone seems to be using newer versions, I'll keep those lines commented. Also, a new tick path was introduced in Twitter, so that is added too.

@Ian-07
Copy link

Ian-07 commented Mar 15, 2023

Script has once again mostly stopped working for me, with the nerd emoji one only showing up in the popup when you click on the checkmark. On Firefox 111.0 but haven't updated; this happened in the middle of my browsing session.

@busybox11
Copy link
Author

@Ian-07 sorry about that, twitter changed their frontend code again
It's updated and working now!

@busybox11
Copy link
Author

I just noticed it does not work again. Twitter keeps changing things lately. Will fix asap

@busybox11
Copy link
Author

It fixed itself, apparently. Twitter Moment™

@navjotjsingh
Copy link

https://github.com/wseagar/eight-dollars

If you find this complicated, grab the browser extension from the above link. Works.

@DiegoFleitas
Copy link

DiegoFleitas commented Apr 3, 2023

how do i get this to work lol

 * 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/53c76f57a577a47a19fab649a76f18e3/raw/twitterblue-nerd.js
 * It should now work and update by itself
 *
 *

@lewisje
Copy link

lewisje commented Apr 3, 2023

how do i get this to work lol

 * 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/53c76f57a577a47a19fab649a76f18e3/raw/twitterblue-nerd.js
 * It should now work and update by itself
 *
 *
  1. Install ViolentMonkey, TamperMonkey, or Greasemonkey (or use a browser with native UserScript support).
  2. Click the "Raw" button on this gist, or use this URL to Install from URL: https://gist.githubusercontent.com/busybox11/53c76f57a577a47a19fab649a76f18e3/raw/twitterblue-nerd.js

@tom-wharf
Copy link

tom-wharf commented Apr 4, 2023

Fixed the issue with clicking the badge on profile showing wrong tick mark in the hover card, in my fork
https://gist.github.com/tom-wharf/106c5c949480549736b415662c5f8443#file-twitterblue-nerd-js-L188-L190

and also fixed the issue, with people getting nerd tickmark when they buy twitter blue even after having legacy verified, now it shouldn't with this fix:
https://gist.github.com/tom-wharf/106c5c949480549736b415662c5f8443#file-twitterblue-nerd-js-L126

example image for the problem:
https://twitter.com/rodrigoleitao25/status/1642701713432887302

@busybox11
Copy link
Author

Ah, thank you so much @tom-wharf! Haven't had the time to update it, I really appreciate your help.
I'll 'merge' your fork very soon.

About the nerd tickmark for legacy verified, I am putting a nerd tick for everyone that has a Twitter Blue checkmark of some sort. I woudln't consider that as an issue, but rather a preference haha

@uintdev
Copy link

uintdev commented Apr 4, 2023

Anyone know why in Safari (via the Userscripts extension), the changed icon only shows up on the popup after I click the official verified icon on someone's profile? Only thing I can see in the console related to the extension is a bunch of the below messages referencing line 203 of the script:

TypeError: undefined is not an object (evaluating 'propsElem.children') bluetickHandling handleMutation

Looks like it was not able to find the reactProps element property from the checkmark elements being observed, perhaps as they did not exist while running through the logic of what to do on detected checkbox elements. Or just flat-out weren't included in the resulting observation. They do exist if you check said element yourself manually. Could be an 'issue' with how mutation observers work under WebKit.

@JewelDonut
Copy link

JewelDonut commented Apr 10, 2023

About the nerd tickmark for legacy verified, I am putting a nerd tick for everyone that has a Twitter Blue checkmark of some sort. I woudln't consider that as an issue, but rather a preference haha

+1 I want to know who is paying for Twitter clout.

@lewisje
Copy link

lewisje commented Apr 12, 2023

It would be neat to further distinguish legacy-verified users who paid for Twitter Blue from Twitter Blue users who are not legacy-verified, the way one fork I went with does.

@ErykDarnowski
Copy link

ErykDarnowski commented Apr 26, 2023

Hey! I found a little bug. So when you at companies while writing a tweet in the little window that pops up, the nerd icon is shown instead of the corpo (gold) one.

image
image

@busybox11
Copy link
Author

@lewisje I thought about this and actually have a working PoC, but I am kind of concerned with the legal implications of doing this. Maybe they will make their way to this script - maybe.

@ErykDarnowski Hey! That is half-intended behavior. Twitter doesn't return the same properties everywhere, and unfortunately, the Blue verified status isn't always present - this is an example of it. I will take another look at it as soon as I have some time, but AFAIK it isn't possible now - at least easily. This script will always prioritiize Nerd status anyways.
Thank you for the report :)

@ErykDarnowski
Copy link

@busybox11
Ahh! I see, I should've dug a bit deeper 😅

However I'm not sure if always priotitizing the Nerd badge is best (like this case shows) 🤔 Then again, for instance showing it only on profile pages isn't good either...

Maybe checking where on the page the profile element shows up would be a solution? But that would get messy quickly!
Ahhh it's a complicated issue for sure :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment