// ==UserScript== // @name 推特获取原图 // @namespace https://github.com/MuXia-0326/twitter-auto-original-picture // @version 1.3 // @description 推特在新标签页打开图片自动原图 // @author Mossia // @match https://pbs.twimg.com/* // @match https://twitter.com/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; //载入css样式 const css = `/* From www.lingdaima.com */ .twitter-Btn { position: relative; display: inline-block; padding: 10px; text-align: center; font-size: 18px; letter-spacing: 1px; text-decoration: none; color: rgb(29, 155, 240); background: transparent; cursor: pointer; transition: ease-out 0.5s; border: 2px solid rgb(29, 155, 240); border-radius: 10px; box-shadow: inset 0 0 0 0 rgb(29, 155, 240); } .twitter-Btn:hover { color: white; box-shadow: inset 0 -100px 0 0 rgb(29, 155, 240); } .twitter-Btn:active { transform: scale(0.9); } .twitter-Btn:hover svg { fill: white; } .twitter-Btn:active svg, .twitter-Btn svg { fill: rgb(29, 155, 240); } .Btn { position: absolute; top: 2px; right: 2px; } .svgClass { display: flex; } `; let styleTag = document.createElement('style'); styleTag.innerText = css; document.head.append(styleTag); // 获取当前页面的URL if (window.location.hostname === 'pbs.twimg.com') { let newUrl = replaceImageSizeName(window.location.href); if (newUrl !== window.location.href) { window.location.href = newUrl; } } else if (window.location.hostname === 'twitter.com') { document.js_nsfw = setInterval(main, 100); } function main() { // 推文页的按钮 let className = 'div[aria-label="图像"][data-testid="tweetPhoto"]'; let temp = [...new Set(baseSelector(className))]; for (let i = 0; i < temp.length; i++) { setBtn([temp[i]]); } // 图片详情页的按钮 let classDetailsName = 'div[data-testid="swipe-to-dismiss"] div[aria-label="图像"]'; let tempDetails = [...new Set(baseSelector(classDetailsName))]; for (let i = 0; i < tempDetails.length; i++) { setDetailsBtn([tempDetails[i]]); } } function baseSelector(selector) { let items = document.querySelectorAll(selector); return Array.from(items).filter((item) => { let node = getParentByNum(item, 5).querySelectorAll('div[data-nsfw]'); return !(node && node.length > 0); }); } function setBtn(node) { for (let container of node) { let images = container.querySelectorAll('img'); for (let image of images) { let imageUrl = image.getAttribute('src'); let classText = image.getAttribute('class') + getRandomIntExclusive(10); let buttonHtml = getBtnHtml(classText); let parentElement = getParentByNum(image, 5); let newUrl = replaceImageSizeName(imageUrl); appendBtn(parentElement, newUrl, buttonHtml, classText); } } } function setDetailsBtn(node) { for (let container of node) { console.log(container); let images = container.querySelectorAll('img'); for (let image of images) { let imageUrl = image.getAttribute('src'); let classText = image.getAttribute('class') + getRandomIntExclusive(10); let buttonHtml = getBtnHtml(classText); let newUrl = replaceImageSizeName(imageUrl); appendBtn(container, newUrl, buttonHtml, classText); } } } function getBtnHtml(classText) { const buttonHtml = `
`; return buttonHtml; } function appendBtn(parentElement, newUrl, buttonHtml, classText) { // 创建按钮元素 let button = document.createElement('div'); button.setAttribute('data-nsfw', 'x'); button.innerHTML = buttonHtml; // 按钮点击事件处理程序 button.querySelector(`#copy-${classText}`).addEventListener('click', () => navigator.clipboard.writeText(newUrl)); // 发起fetch请求获取图片内容 button.querySelector(`#download-${classText}`).addEventListener('click', () => { fetch(newUrl) .then(function (response) { if (response.ok) { return response.blob(); // 以Blob形式解析响应内容 } else { throw new Error('下载失败'); } }) .then(function (imageBlob) { // 创建一个Blob URL,用于保存图片内容 var imageUrl = URL.createObjectURL(imageBlob); let urlParams = new URL(newUrl); // 创建一个下载链接 var downloadLink = document.createElement('a'); downloadLink.href = imageUrl; downloadLink.download = urlParams.pathname.substring(urlParams.pathname.lastIndexOf('/') + 1) + '.' + urlParams.searchParams.get('format'); // 模拟用户点击下载链接 downloadLink.click(); // 释放Blob URL以节省内存 URL.revokeObjectURL(imageUrl); }) .catch(function (error) { console.error('下载失败:', error); }); }); parentElement.appendChild(button); } function getParentByNum(element, number) { let ancestor = element; for (let i = 0; i < number; i++) { if (ancestor.parentNode) { ancestor = ancestor.parentNode; } else { break; } } return ancestor; } /** * @param {string} urlString */ function replaceImageSizeName(urlString) { // 替换name参数的值为"orig" const url = new URL(urlString); url.searchParams.set('name', 'orig'); return url.toString(); } /** * @param {number} max */ function getRandomIntExclusive(max) { return Math.floor(Math.random() * max); } })();