Skip to content

Instantly share code, notes, and snippets.

@Jacbo1
Forked from busybox11/twitter-logo.user.js
Last active May 24, 2024 02:11
Show Gist options
  • Save Jacbo1/5829dbba56e8cfa34242e57f2221802a to your computer and use it in GitHub Desktop.
Save Jacbo1/5829dbba56e8cfa34242e57f2221802a to your computer and use it in GitHub Desktop.
Bring back old twitter logo
// ==UserScript==
// @name Bring back bird logo - twitter.com
// @namespace twitter scripts
// @match *://*.twitter.com/*
// @match *://*.x.com/*
// @grant none
// @version 3
// @author -
// @description 7/24/2023, 1:47:07 PM
// @downloadURL https://gist.github.com/Jacbo1/5829dbba56e8cfa34242e57f2221802a/raw/67713c9089348bac91c121c2e56716732517b52d
// @updateURL https://gist.github.com/Jacbo1/5829dbba56e8cfa34242e57f2221802a/raw/67713c9089348bac91c121c2e56716732517b52d/twitter-logo.user.js
// @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com
// ==/UserScript==
(function() {
const handleFaviconUpdate = (element) => {
element.href = element.href.replace('.3.ico', '.2.ico');
}
const cooldown = 250
let queue = []
let lastRunTime = 0
let timerStarted = false
function run() {
lastRunTime = new Date().getTime()
timerStarted = false
while (queue.length != 0) {
let item = queue.shift()
let mutationsList = item[0]
let observer = item[1]
lastRunTime = new Date().getTime()
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
const nodes = mutation.addedNodes
for (const node of nodes) {
if (node) {
if (typeof node.getElementsByTagName === "function") {
let arr = node.getElementsByTagName('span')
for (let i = 0; i < arr.length; i++) {
switch (arr[i].innerHTML) {
case 'Only on X · Trending': arr[i].innerHTML = 'Only on Twitter · Trending'; break;
case ' reposted a reply to you': arr[i].innerHTML = ' retweeted a reply to you'; break;
case 'View post engagements': arr[i].innerHTML = 'View tweet engagements'; break;
case 'View post analytics': arr[i].innerHTML = 'View tweet analytics'; break;
case 'Embed post': arr[i].innerHTML = 'Embed tweet'; break;
case 'Report post': arr[i].innerHTML = 'Report tweet'; break;
case 'Post Analytics': arr[i].innerHTML = 'Tweet Analytics'; break;
case 'Post engagements': arr[i].innerHTML = 'Tweet engagements'; break;
case 'Turn off reposts': arr[i].innerHTML = 'Turn off retweets'; break;
case 'Scheduled posts': arr[i].innerHTML = 'Scheduled tweets'; break;
case 'Unsent posts': arr[i].innerHTML = 'Unsent tweets'; break;
case 'Your posts': arr[i].innerHTML = 'Your tweets'; break;
case 'You will find a list of everyone who quoted this post here.': arr[i].innerHTML = 'You will find a list of everyone who quoted this tweet here.'; break;
case 'No Reposts yet': arr[i].innerHTML = 'No retweets yet'; break;
case 'Share someone else’s post on your timeline by reposting it. When you do, it’ll show up here.': arr[i].innerHTML = 'Share someone else’s tweet on your timeline by retweeting it. When you do, it’ll show up here.'; break;
case 'When someone taps the heart to Like this post, it’ll show up here.': arr[i].innerHTML = 'When someone taps the heart to Like this tweet, it’ll show up here.'; break;
case 'Add location information to your posts': arr[i].innerHTML = 'Add location information to your tweets'; break;
case 'Remove all location information attached to your posts': arr[i].innerHTML = 'Remove all location information attached to your tweets'; break;
case 'This prevents posts with potentially sensitive content from displaying in your search results.': arr[i].innerHTML = 'This prevents tweets with potentially sensitive content from displaying in your search results.'; break;
case 'Choose to filter out content such as duplicate or automated posts. This doesn’t apply to notifications from accounts you follow or have interacted with recently.': arr[i].innerHTML = 'Choose to filter out content such as duplicate or automated tweets. This doesn’t apply to notifications from accounts you follow or have interacted with recently.'; break;
case 'Post': arr[i].innerHTML = 'Tweet'; break;
case 'Posts': arr[i].innerHTML = 'Tweets'; break;
case 'Repost': arr[i].innerHTML = 'Retweet'; break;
case 'Reposts': arr[i].innerHTML = 'Retweets'; break;
case 'Reposted by': arr[i].innerHTML = 'Retweeted by'; break;
case ' reposted': arr[i].innerHTML = ' retweeted'; break;
case ' reposted your reply': arr[i].innerHTML = ' retweeted your reply'; break;
case ' reposted your post': arr[i].innerHTML = ' retweeted your tweet'; break;
case ' liked your post': arr[i].innerHTML = ' liked your tweet'; break;
case ' liked your repost': arr[i].innerHTML = ' liked your retweet'; break;
case ' liked a post you were mentioned in': arr[i].innerHTML = ' liked a tweet you were mentioned in'; break;
case 'You reposted': arr[i].innerHTML = 'You retweeted'; break;
case 'Undo repost': arr[i].innerHTML = 'Undo retweet'; break;
case 'Undo post': arr[i].innerHTML = 'Undo tweet'; break;
case 'Longer posts': arr[i].innerHTML = 'Longer tweets'; break;
case 'Edit post': arr[i].innerHTML = 'Edit tweet'; break;
case 'Post longer videos': arr[i].innerHTML = 'Tweet longer videos'; break;
default:
let textNode = arr[i].childNodes[arr[i].TEXT_NODE - 1]
if (typeof textNode !== 'undefined' && textNode.textContent == ' reposted') {
textNode.textContent = ' retweeted'
break;
}
let match = arr[i].innerHTML.match(/^ liked (\d+) of your posts$/)
if (match) {
arr[i].innerHTML = ' liked ' + match[1] + ' of your tweets'
break;
}
// Doesn't work. Span is likely set by JS and not static.
// Affects the "x posts" on profile pages.
// match = arr[i].innerHTML.match(/^([\d\.,KM]+) posts$/)
// if (match) {
// arr[i].innerHTML = match[1] + ' tweets'
// break;
// }
match = arr[i].innerHTML.match(/^ and (\d+) others reposted a reply to you$/)
if (match) {
arr[i].innerHTML = ' and ' + match[1] + ' others retweeted a reply to you'
break;
}
match = arr[i].innerHTML.match(/^Show (\d+) posts$/)
if (match) {
arr[i].innerHTML = 'Show ' + match[1] + ' tweets'
break;
}
match = arr[i].innerHTML.match(/^ and (\d+) others reposted your reply$/)
if (match) {
arr[i].innerHTML = ' and ' + match[1] + ' others retweeted your reply'
break;
}
match = arr[i].innerHTML.match(/^ and (\d+) others liked your post$/)
if (match) {
arr[i].innerHTML = ' and ' + match[1] + ' others liked your tweet'
break;
}
match = arr[i].innerHTML.match(/^ liked (\d+) posts you were mentioned in$/)
if (match) {
arr[i].innerHTML = ' liked ' + match[1] + ' tweets you were mentioned in'
break;
}
match = arr[i].innerHTML.match(/^ and (\d+) others reposted your post$/)
if (match) {
arr[i].innerHTML = ' and ' + match[1] + ' others retweeted your tweet'
break;
}
break;
}
}
}
if (node.tagName == 'DIV') {
let match = node.innerHTML.match(/^(\d+) posts$/)
if (match) node.innerHTML = match[1] + ' tweets'
}
if (typeof node.querySelectorAll === "function") {
const logoElems = node.querySelectorAll('h1[role="heading"]')
for (const logoElemCont of logoElems) {
logoElemCont.querySelectorAll('svg').forEach((svgElem) => {
svgElem.innerHTML = `
<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>
`
})
}
}
if (node.tagName == "TITLE") {
new MutationObserver(function(mutations) {
const titleElem = mutations[0].target;
if (titleElem.innerHTML.slice(-1) == "X") {
titleElem.innerHTML = titleElem.innerHTML.slice(0, -1) + 'Twitter'
} else {
let match = titleElem.innerHTML.match(/^(.*) on X:(.*)$/)
if (match) {
titleElem.innerHTML = match[1] + ' on Twitter:' + match[2]
}
}
}).observe(
document.querySelector('title'),
{ subtree: true, characterData: true, childList: true }
);
}
}
}
} else if (mutation.type === 'attributes') {
if (mutation.target.localName === 'link' && mutation.target.rel === 'shortcut icon' && mutation.target.href?.endsWith('.3.ico')) {
handleFaviconUpdate(mutation.target)
}
}
}
}
}
const handleMutation = (mutList, obs) => {
let time = new Date().getTime()
queue.push([mutList, obs])
if (time - cooldown < lastRunTime) {
if (!timerStarted) {
timerStarted = true
setTimeout(run, cooldown)
}
} else run()
}
const splashElems = document.querySelectorAll('#placeholder')
for (const logoElemCont of splashElems) {
logoElemCont.querySelectorAll('svg').forEach((svgElem) => {
svgElem.innerHTML = `
<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>
`
svgElem.style.fill = 'rgba(29,161,242,1.00)';
})
}
// Initialize favicon
handleFaviconUpdate(document.querySelector("link[rel='shortcut icon']"))
const sc = {
log: (...args) => {
console.log('[twitter-logo]', ...args)
}
}
const observer = new MutationObserver(handleMutation)
observer.observe(document, {
childList: true,
subtree: true,
attributeFilter: ["href"],
attributeOldValue: true
})
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment