No more extra click to show a stupid tweets!
当前为
//* eslint-env browser, es6, greasemonkey */
// ==UserScript==
// @name Twitter Show Sensitive Content
// @namespace kTu*Kzukf&5p#85%xas!fBH4#GT@FQ7@
// @version 0.2
// @description No more extra click to show a stupid tweets!
// @author _SUDO
// @match *://*.twitter.com/*
// @icon https://www.google.com/s2/favicons?domain=twitter.com
// @license GPL
// @grant window.onurlchange
// ==/UserScript==
const maxCheckDeepness = 30
let observer = null
function findParent(elem) {
let tries = maxCheckDeepness
let currentNode = elem
let parent = currentNode.parentElement
while (parent.childElementCount === 1) {
if (tries <= 0) break;
tries--
currentNode = parent
parent = parent.parentElement
}
return parent
}
function findChild(elem) {
let tries = maxCheckDeepness
let currentNode = elem
let child = currentNode.children
while (child.length === 1) {
if (tries <= 0) break;
tries--
currentNode = child
child = child[0].children
}
return child
}
function unHideTweet(tweetElement) {
const hidden = tweetElement
console.log('[M] Hidden container found!', hidden)
// Now filter until we end up without singles divs and two elements
let tweet = findChild(hidden) // second element
console.log('[M] CHILDS:', tweet)
if (tweet.length === 1) {
console.log('[M] Only one child found!', tweet[0])
tweet = tweet[0]
} else {
console.log('[M] AAAAAA')
let running = true
while (running) {
console.log('[M] Multiple childs found, filtering one more time...', tweet)
if (tweet.length === 2 && tweet[0].childElementCount === 0)
tweet = findChild(tweet[1])
else {
tweet = tweet[1]
running = false
}
}
}
try {
// This should click the button instead of the actual container
// if the container is clicked, the page will be redirected
tweet.children[0].click()
} catch (err) {
// No page interaction, we scheduble click action
console.error('[M] NO PAGE INTERACTION!', err)
}
}
function watcher(disconnect = false) {
if (disconnect && observer) {
observer.disconnect()
return
}
// Twitter uses articles for every tweet.
// To use the observer we need to find all tweets parent element
const target = findParent(document.querySelector('article'))
const sensitiveContentElement = `div[role="presentation"] > div`
console.log('Target:', target)
// Show all elements loaded before the observer registration
const staticTweets = document.querySelectorAll(sensitiveContentElement)
if (staticTweets) staticTweets.forEach((e) => unHideTweet(e))
observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
// Well now we can filter elements
if (mutation.type === 'childList' && mutation.addedNodes.length) {
// console.log('[M]', mutation, mutation.type, mutation.type.attributes)
// console.log('[M]', mutation.addedNodes[0])
const hidden = mutation.addedNodes[0].querySelector(sensitiveContentElement)
if (hidden) {
unHideTweet(hidden)
}
}
})
})
observer.observe(target, {
childList: true,
subtree: false,
characterData: false,
})
}
function runOnURLChange() {
if (window.onurlchange === null) {
window.addEventListener('urlchange', (info) => {
init()
})
} else {
console.error('window.onurlchange not supported')
}
}
async function init() {
let tries = 30
while(!document.querySelector('article')) {
if (tries <= 0) {
console.error('Max tries excedeed, perhaps the element have changed?')
break;
}
tries--
await new Promise(r => setTimeout(r, 500));
}
// Not elements are loaded :)
watcher()
}
if (document.readyState === 'complete') init()
else {
document.addEventListener('readystatechange', (evt) => {
if (document.readyState === 'complete') init()
}, {once: true})
}
runOnURLChange()