您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Script to download tweet images in one click.
// ==UserScript== // @name Tweetdeck Image Saver // @namespace https://twitter.com/aloneunix // @version 1.1 // @description Script to download tweet images in one click. // @author aloneunix // @include https://tweetdeck.twitter.com/* // @grant GM_download // ==/UserScript== (function() { var TweetType = { Column: 0, Detail: 1, Modal: 2 }; function GetOrigUrl(url) { var u = new URL(url); u.searchParams = new URLSearchParams(url.search); u.searchParams.set("format", u.pathname.substring(u.pathname.lastIndexOf(".")+1)); // because sometimes png images have jpg format u.searchParams.set("name", "orig"); return u } var TweetTools = (function () { function TweetTools(tweet, type) { var self = this; this.tweet = tweet; this.type = type; this.GatherData(); var dlButton = this.CreateDLButton(); dlButton.onclick = function () { var urls = self.GetImages(); if (urls.length == 1) { var u = GetOrigUrl(urls[0]); GM_download({url: u.href, name: self.GetFilename(u)}); } else { urls.forEach(function(url, i) { var u = GetOrigUrl(url); GM_download({url: u.href, name: self.GetFilename(u, i)}); }); } }; } TweetTools.prototype.GetImages = function () { var urls = []; if (this.type == TweetType.Modal) { urls.push(this.tweet.querySelector(".js-media-image-link img").src); } else if (this.type == TweetType.Column || this.type == TweetType.Detail) { var imgLinks = this.tweet.getElementsByClassName("js-media-image-link"); if (imgLinks.length == 1) { if (this.type == TweetType.Column) urls.push(imgLinks[0].style.backgroundImage.slice(4, -1).replace(/"/g, "")); if (this.type == TweetType.Detail) urls.push(imgLinks[0].firstElementChild.src); } else { Array.from(imgLinks).forEach(function(url) { urls.push(url.style.backgroundImage.slice(4, -1).replace(/"/g, "")); }); } } return urls; }; TweetTools.prototype.GatherData = function () { this.username = this.tweet.querySelector("span.username").innerHTML.slice(1); if (this.type == TweetType.Modal) { this.tweet_id = this.tweet.querySelector("time.tweet-timestamp a").href.split("status/")[1]; } else { this.tweet_id = this.tweet.getAttribute("data-tweet-id"); } var ts; if (this.type == TweetType.Detail) { ts = this.tweet.querySelector(".margin-tl a").text.split(" · ")[1]; } else { ts = parseInt(this.tweet.getElementsByClassName("tweet-timestamp")[0].getAttribute("data-time")); } ts = new Date(ts); this.ts = ts.getFullYear() + '-' + ('0'+ (ts.getMonth()+1)).slice(-2) + '-' + ('0'+ ts.getDate()).slice(-2); // I don't want to live on this planet anymore }; TweetTools.prototype.CreateDLButton = function () { var actions = this.tweet.querySelector("footer ul"); var dlIcon = document.createElement("i"); dlIcon.className = "icon icon-share txt-right"; var iconContainer = document.createElement("a"); iconContainer.href = "#"; iconContainer.appendChild(dlIcon); var dlButton = document.createElement("li"); if (this.type == TweetType.Detail) { iconContainer.className = "tweet-detail-action"; dlButton.className = "tweet-detail-action-item position-rel"; Array.from(actions.children).forEach(function (action) { action.style.width = "20%"; }); dlButton.style.width = "20%"; } else { iconContainer.className = "tweet-action"; dlButton.className = "tweet-action-item position-rel pull-left margin-r--13"; } dlButton.appendChild(iconContainer); actions.appendChild(dlButton); this.tweet.className += " has-tis-tools"; return dlButton; }; TweetTools.prototype.GetFilename = function(url, index) { var extension = url.searchParams.get("format"); var _index = index !== undefined ? "_"+(index+1) : ""; return `${this.username}_${this.ts}_${this.tweet_id}${_index}.${extension}`; }; return TweetTools; }()); var columnDetailObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.type == "childList") { var tweet = mutation.target.querySelector(".js-tweet-detail article:not(.has-tis-tools)"); if (tweet) new TweetTools(tweet, TweetType.Detail); var replies = mutation.target.querySelectorAll(".tweet-detail-reply article:not(.has-tis-tools)"); if (replies.length !== 0) { replies = Array.from(replies).filter(function(tweet) { return tweet.querySelector(".js-media .js-media-image-link") && !tweet.querySelector(".quoted-tweet, .video-overlay"); }); replies.forEach(function (reply) { new TweetTools(reply, TweetType.Column); }); } } }); }); var columnObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.type == "childList") { var tweets = document.querySelectorAll("article.stream-item.is-actionable:not(.has-tis-tools)"); tweets = Array.from(tweets).filter(function(tweet) { return tweet.querySelector(".js-media .js-media-image-link") && !tweet.querySelector(".quoted-tweet, .video-overlay"); }); tweets.forEach(function(tweet) { new TweetTools(tweet, TweetType.Column); }); } }); }); var modalObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.type == "childList") { var modal = document.querySelector("#open-modal .js-modal-panel"); if (!modal) { return; } var tweet = modal.querySelector(".med-tweet .item-box"); if (tweet) { new TweetTools(modal, TweetType.Modal); } } }); }); function initModalObserver() { var modalPanel = document.querySelector("#open-modal"); modalObserver.observe(modalPanel, { childList: true }); } function initColumnObserver() { var columns = document.querySelectorAll("#container section.column"); Array.from(columns).forEach(function(column) { columnObserver.observe(column.querySelector("div.chirp-container"), { childList: true }); columnDetailObserver.observe(column.querySelector("div.column-detail"), { childList: true, subtree: true }); }); } function initAppObserver() { var app = document.querySelector("div.application"); new MutationObserver(function(mutations) { var appColumns = app.querySelector(".app-content .app-columns"); if (appColumns.children.length !== 0) { this.disconnect(); initColumnObserver(); initModalObserver(); } }).observe(app, { childList: true, }); } initAppObserver(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址