您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
No more extra click to show stupid tweets!
- //* eslint-env browser, es6, greasemonkey */
- // ==UserScript==
- // @name Twitter Show Sensitive Content
- // @namespace kTu*Kzukf&5p#85%xas!fBH4#GT@FQ7@
- // @version 0.3.6
- // @description No more extra click to show stupid tweets!
- // @author _SUDO
- // @match *://*.twitter.com/*
- // @icon https://www.google.com/s2/favicons?domain=twitter.com
- // @license GPL
- // @grant window.onurlchange
- // @run-at document-start
- // ==/UserScript==
- (function () {
- 'use strict';
- //* Bypass NSFW warnings
- // Thanks to TURTLE: https://stackoverflow.com/a/43144531
- //! IF IS NOT WORKING OR GENERATES SOME KIND OF PROBLEM, COMMENT FROM HERE:
- const open_prototype = XMLHttpRequest.prototype.open;
- const intercept_response = function (urlpattern, callback) {
- XMLHttpRequest.prototype.open = function () {
- arguments['1'].match(urlpattern) &&
- this.addEventListener('readystatechange', function (event) {
- if (this.readyState === 4) {
- var response = callback(
- event.target.responseText,
- event.target.responseURL
- );
- Object.defineProperty(this, 'response', { writable: true });
- Object.defineProperty(this, 'responseText', { writable: true });
- this.response = this.responseText = response;
- }
- });
- return open_prototype.apply(this, arguments);
- };
- };
- // Creates and caches a random string to replace later the possibly_sensitive object key
- const ranString = (() => Array(5).fill().map(() => 'abcdefghijklmnopqrstuvwxyz'.charAt(Math.random() * 62)).join(''))();
- intercept_response(
- /\/User|TweetDetail|Adaptive/gi, // 179 steps, 0.01ms
- function (response, responseURL) {
- // console.log('[API] FOUND RESPONSE!', responseURL, response);
- const new_response = response
- .replace(/sensitive_media/gim, '')
- .replace(/possibly_sensitive/gim, ranString)
- .replace(/offensive_profile_content/gim, '');
- return new_response;
- }
- );
- // TO HERE
- //! DOM DEPENDENT, USE IF THE ABOVE METHOD DO NOT WORK
- /*
- 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 {
- 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
- 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');
- }
- }
- let executed = false;
- async function init() {
- let tries = 30;
- while (!document.querySelector('article')) {
- if (tries <= 0) {
- console.error('Max tries exceeded, perhaps the element have changed?');
- // Maybe the user let the page in the button to show the profile
- // Add an click event listener to re-execute when technically clicking the button to show the profile
- if (!executed) {
- executed = true;
- console.log(
- 'Re-checking tweets container in the next click event...'
- );
- document.body.addEventListener('click', init, { once: true });
- }
- return;
- }
- tries--;
- await new Promise((r) => setTimeout(r, 500));
- }
- watcher();
- }
- if (document.readyState === 'complete') init()
- else {
- document.addEventListener('readystatechange', (evt) => {
- if (document.readyState === 'complete') init()
- }
- )
- }
- runOnURLChange();
- */
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址