您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Extract original size images for Twitter.
// ==UserScript== // @author Jimmy Chin // @name Twitter Original Images Extractor // @version 1.0.11 // @include https://twitter.com* // @description Extract original size images for Twitter. // @namespace https://greasyfork.org/users/241557 // ==/UserScript== javascript:(function(){ const SELECTOR = { ARTICLE_CLASS: "css-1dbjc4n r-18u37iz r-1ny4l3l r-1udh08x r-1qhn6m8 r-i023vh", BUTTON_BAR_CLASS_ON_TIMELINE: ".css-1dbjc4n.r-1kbdv8c.r-18u37iz.r-1wtj0ep.r-1s2bzr4.r-hzcoqn", BUTTON_BAR_CLASS_ON_ARTICLE_IN_DIM_BACKGROUND: ".css-1dbjc4n.r-1oszu61.r-1ila09b.r-rull8r.r-qklmqi.r-1kfrmmb.r-1efd50x.r-5kkj8d.r-1kbdv8c.r-18u37iz.r-h3s6tt.r-1wtj0ep.r-3qxfft.r-s1qlax", BUTTON_BAR_CLASS_ON_ARTICLE_IN_DEFAULT_BACKGROUND: ".css-1dbjc4n.r-1oszu61.r-j5o65s.r-rull8r.r-qklmqi.r-1dgieki.r-1efd50x.r-5kkj8d.r-1kbdv8c.r-18u37iz.r-h3s6tt.r-1wtj0ep.r-3qxfft.r-s1qlax", BUTTON_BAR_CLASS_ON_ARTICLE_IN_LIGHT_OUT_BACKGROUND: ".css-1dbjc4n.r-1oszu61.r-1igl3o0.r-rull8r.r-qklmqi.r-2sztyj.r-1efd50x.r-5kkj8d.r-1kbdv8c.r-18u37iz.r-h3s6tt.r-1wtj0ep.r-3qxfft.r-s1qlax", TIME_CLASS_ON_ARTICLE: "css-4rbku5.css-18t94o4.css-901oao.css-16my406.r-111h2gw.r-1loqt21.r-poiln3.r-bcqeeo.r-qvutc0" } const ATTRIBUTE = { BUTTON_CLASS: "css-1dbjc4n r-18u37iz r-1h0z5md r-3qxfft r-h4g966 r-rjfia" } const BACKGROUND_COLOR = { DEFAULT: "rgb(255, 255, 255)", DIM: "rgb(21, 32, 43)", LIGHTS_OUT: "rgb(0, 0, 0)" } const PATTERN = { IMG: /^https:\/\/pbs.twimg.com\/media\// } init(); function init() { getTweetData(); setDOMObserver(); } function setDOMObserver() { const DOMObserver = new MutationObserver(() => getTweetData()); DOMObserver.observe(document.body, { attributes: true, childList: true, subtree: true }); } function getTweetData() { const tweets = document.querySelectorAll("article"); if (!isEmpty(tweets)) { tweets.forEach(tweet => { setTimeout(() => { if (!hasButtonBeenCreated(tweet)) { if (isArticle(tweet)) { createButtonForArticle(tweet); } else { createButtonForTimeline(tweet); } } }, 300); }); } } function isArticle(tweet) { if (!isEmpty(tweet)) { return tweet.getAttribute("class") == SELECTOR.ARTICLE_CLASS; } } function hasButtonBeenCreated(tweet) { if (isArticle(tweet)) { return document.querySelector("#buttonForArticle"); } else { return document.querySelector(`#button${getTweetIdFromTweet(tweet)}`); } } function createButtonForArticle(tweet) { if (!isEmpty(tweet)) { const buttonBar = document.querySelector(getButtonBarClassOnArticle()); if (!isEmpty(buttonBar)) { const button = document.createElement("div"); const lastButton = buttonBar.lastChild; const buttonWidth = lastButton.clientWidth; const buttonHeight = lastButton.clientHeight; button.setAttribute("class", ATTRIBUTE.BUTTON_CLASS); button.innerHTML = getButtonInnerHtml(buttonWidth, buttonHeight); button.id = "buttonForArticle"; buttonBar.appendChild(button); button.addEventListener("click", () => { const imgs = getImageFromTweet(tweet); if (!isEmpty(imgs)) { imgs.forEach(url => window.open(url)); } }); } } } function createButtonForTimeline(tweet) { if (!isEmpty(tweet)) { const buttonBar = tweet.querySelector(SELECTOR.BUTTON_BAR_CLASS_ON_TIMELINE); if (!isEmpty(buttonBar)) { const button = document.createElement("div"); const buttonCss = buttonBar.firstChild.getAttribute("class"); const lastButton = buttonBar.lastChild; const buttonWidth = lastButton.clientWidth; const buttonHeight = lastButton.clientHeight; lastButton.setAttribute("class", buttonCss) button.setAttribute("class", buttonCss); button.innerHTML = getButtonInnerHtml(buttonWidth, buttonHeight); button.id = `button${getTweetIdFromTweet(tweet)}`; buttonBar.appendChild(button); button.addEventListener("click", () => { const imgs = getImageFromTweet(tweet); if (!isEmpty(imgs)) { imgs.forEach(url => window.open(url)); } }); } } } function getTweetIdFromTweet(tweet) { let result = null; if (!isEmpty(tweet)) { const timeObj = tweet.querySelector("time"); if (!isEmpty(timeObj)) { const href = timeObj.parentNode.href; const lastSlashIndex = href.lastIndexOf("/"); result = href.substr(lastSlashIndex + 1); } } return result; } function getImageFromTweet(tweet) { let result = null; if (!isEmpty(tweet)) { const imgs = [...tweet.querySelectorAll("img")]; if (!isEmpty(imgs)) { const srcArray = []; imgs.filter(img => img.src.match(PATTERN.IMG)) .forEach(img => srcArray.push(img.src)); result = transImageUrlToOrig(srcArray); } } return result; } function transImageUrlToOrig(imgs) { const result = []; if (!isEmpty(imgs)) { imgs.forEach(img => { /* get the "name" param index of the query string*/ const nameParamKeyOfQueryString = img.indexOf("name="); const origImageUrl = img.substr(0, nameParamKeyOfQueryString) + "name=orig"; result.push(origImageUrl); }); } return result; } function isEmpty(data) { let result = false; if (data != undefined && data != null) { if (Array.isArray(data)) { if (data.length == 0) { result = true; } } else if (typeof data == "string") { if (data.trim() == "") { result = true; } } } else { result = true; } return result; } function getBGColor() { return document.body.style.backgroundColor; } function getButtonInnerHtml(buttonWidth, buttonHeight) { let result = null; switch (getBGColor()) { case BACKGROUND_COLOR.DEFAULT: result = getDefaultButtonInnerHtml(buttonWidth, buttonHeight); break; case BACKGROUND_COLOR.DIM: result = getDimButtonInnerHtml(buttonWidth, buttonHeight); break; case BACKGROUND_COLOR.LIGHTS_OUT: result = getLightsOutButtonInnerHtml(buttonWidth, buttonHeight); break; } return result; } function getButtonBarClassOnArticle() { let result = null; switch (getBGColor()) { case BACKGROUND_COLOR.DEFAULT: result = SELECTOR.BUTTON_BAR_CLASS_ON_ARTICLE_IN_DEFAULT_BACKGROUND; break; case BACKGROUND_COLOR.DIM: result = SELECTOR.BUTTON_BAR_CLASS_ON_ARTICLE_IN_DIM_BACKGROUND; break; case BACKGROUND_COLOR.LIGHTS_OUT: result = SELECTOR.BUTTON_BAR_CLASS_ON_ARTICLE_IN_LIGHT_OUT_BACKGROUND; break; } return result; } function getDefaultButtonInnerHtml(buttonWidth, buttonHeight) { return `<a> <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="${buttonWidth}" height="${buttonHeight}" viewBox="0 0 172 172" style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g fill="#657786"><path d="M99.33,37.84c-1.73344,0.215 -3.02344,1.69313 -3.01,3.44v24.295c-39.60031,1.20938 -60.9525,22.17188 -71.4875,43c-10.68281,21.11031 -11.05906,41.69656 -11.0725,42.355v0.215v0.215c-0.05375,1.89469 1.43781,3.49375 3.3325,3.5475c1.89469,0.05375 3.49375,-1.43781 3.5475,-3.3325v-0.215c0.02688,-0.3225 0.79281,-10.73656 10.6425,-21.8225c9.675,-10.87094 28.55469,-21.83594 65.0375,-22.575v23.7575c0,1.31688 0.7525,2.52625 1.94844,3.10406c1.19594,0.57781 2.60688,0.41656 3.64156,-0.41656l55.04,-44.72c0.81969,-0.65844 1.29,-1.63937 1.29,-2.6875c0,-1.04812 -0.47031,-2.02906 -1.29,-2.6875l-55.04,-44.72c-0.72562,-0.59125 -1.65281,-0.86 -2.58,-0.7525zM103.2,48.4825l46.1175,37.5175l-46.1175,37.5175v-20.3175c0,-1.89469 -1.54531,-3.44 -3.44,-3.44c-40.43344,0 -62.22906,12.42969 -73.6375,25.2625c-0.43,0.48375 -0.67187,0.91375 -1.075,1.3975c1.45125,-4.73 3.35938,-9.7825 5.9125,-14.835c10.03781,-19.83375 29.19969,-39.345 68.8,-39.345c1.89469,0 3.44,-1.54531 3.44,-3.44z"></path></g></g> </svg> <div class="css-1dbjc4n r-sdzlij r-1p0dtai r-xoduu5 r-1d2f490 r-xf4iuw r-1ny4l3l r-u8s1d r-zchlnj r-ipm5af r-o7ynqc r-6416eg"></div> <a>`; } function getDimButtonInnerHtml(buttonWidth, buttonHeight) { return `<a> <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="${buttonWidth}" height="${buttonHeight}" viewBox="0 0 172 172" style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g fill="#8899a6"><path d="M99.33,37.84c-1.73344,0.215 -3.02344,1.69313 -3.01,3.44v24.295c-39.60031,1.20938 -60.9525,22.17188 -71.4875,43c-10.68281,21.11031 -11.05906,41.69656 -11.0725,42.355v0.215v0.215c-0.05375,1.89469 1.43781,3.49375 3.3325,3.5475c1.89469,0.05375 3.49375,-1.43781 3.5475,-3.3325v-0.215c0.02688,-0.3225 0.79281,-10.73656 10.6425,-21.8225c9.675,-10.87094 28.55469,-21.83594 65.0375,-22.575v23.7575c0,1.31688 0.7525,2.52625 1.94844,3.10406c1.19594,0.57781 2.60688,0.41656 3.64156,-0.41656l55.04,-44.72c0.81969,-0.65844 1.29,-1.63937 1.29,-2.6875c0,-1.04812 -0.47031,-2.02906 -1.29,-2.6875l-55.04,-44.72c-0.72562,-0.59125 -1.65281,-0.86 -2.58,-0.7525zM103.2,48.4825l46.1175,37.5175l-46.1175,37.5175v-20.3175c0,-1.89469 -1.54531,-3.44 -3.44,-3.44c-40.43344,0 -62.22906,12.42969 -73.6375,25.2625c-0.43,0.48375 -0.67187,0.91375 -1.075,1.3975c1.45125,-4.73 3.35938,-9.7825 5.9125,-14.835c10.03781,-19.83375 29.19969,-39.345 68.8,-39.345c1.89469,0 3.44,-1.54531 3.44,-3.44z"></path></g></g> </svg> <div class="css-1dbjc4n r-sdzlij r-1p0dtai r-xoduu5 r-1d2f490 r-xf4iuw r-1ny4l3l r-u8s1d r-zchlnj r-ipm5af r-o7ynqc r-6416eg"></div> <a>`; } function getLightsOutButtonInnerHtml(buttonWidth, buttonHeight) { return `<a> <svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="${buttonWidth}" height="${buttonHeight}" viewBox="0 0 172 172" style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g fill="#6e767d"><path d="M99.33,37.84c-1.73344,0.215 -3.02344,1.69313 -3.01,3.44v24.295c-39.60031,1.20938 -60.9525,22.17188 -71.4875,43c-10.68281,21.11031 -11.05906,41.69656 -11.0725,42.355v0.215v0.215c-0.05375,1.89469 1.43781,3.49375 3.3325,3.5475c1.89469,0.05375 3.49375,-1.43781 3.5475,-3.3325v-0.215c0.02688,-0.3225 0.79281,-10.73656 10.6425,-21.8225c9.675,-10.87094 28.55469,-21.83594 65.0375,-22.575v23.7575c0,1.31688 0.7525,2.52625 1.94844,3.10406c1.19594,0.57781 2.60688,0.41656 3.64156,-0.41656l55.04,-44.72c0.81969,-0.65844 1.29,-1.63937 1.29,-2.6875c0,-1.04812 -0.47031,-2.02906 -1.29,-2.6875l-55.04,-44.72c-0.72562,-0.59125 -1.65281,-0.86 -2.58,-0.7525zM103.2,48.4825l46.1175,37.5175l-46.1175,37.5175v-20.3175c0,-1.89469 -1.54531,-3.44 -3.44,-3.44c-40.43344,0 -62.22906,12.42969 -73.6375,25.2625c-0.43,0.48375 -0.67187,0.91375 -1.075,1.3975c1.45125,-4.73 3.35938,-9.7825 5.9125,-14.835c10.03781,-19.83375 29.19969,-39.345 68.8,-39.345c1.89469,0 3.44,-1.54531 3.44,-3.44z"></path></g></g> </svg> <div class="css-1dbjc4n r-sdzlij r-1p0dtai r-xoduu5 r-1d2f490 r-xf4iuw r-1ny4l3l r-u8s1d r-zchlnj r-ipm5af r-o7ynqc r-6416eg"></div> <a>`; } })();