Advertisement
Guest User

Twitter Image Saver

a guest
Dec 13th, 2019
386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.97 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Twitter Image Saver
  3. // @author aloneunix
  4. // @namespace https://twitter.com/aloneunix
  5. // @description Script to download tweet images in one click.
  6. // @include https://twitter.com/*
  7. // @exclude https://twitter.com/settings/*
  8. // @grant GM_download
  9. // @version 1.0
  10. // @noframes
  11. // ==/UserScript==
  12.  
  13. ////MODIFY TO SPECIFY YOUR PREFERED FILE AND FODLER STRUCTURE
  14. //$u , %tid, %ts, %fts, %ext, %ind
  15. //%u = username, %tid = tweet id, %ts = timestamp, %fts = formated timestamp, %ext = extension, %ind = image index if there are multiple images in the tweet
  16. //use % also as a delimiter to seperate your formats from your normal text
  17. //eg '%u%\\%u%.%ext' in this case it will end up as username\username.ext
  18. //my default 'twitter\\%u%\\%u%_%tid%ind%.%ext'
  19. //just doing %u%_%tid%ind%.%ext will create the image in your download folder as opposed into the folder structure {downloadfolder}\twitter\username\
  20. const newFilename = 'media\\dwn\\twitter\\%u%\\%u%_%tid%ind%.%ext';
  21.  
  22.  
  23. var TwitterImageSaver;
  24. (function (TwitterImageSaver) {
  25. function cutSize(url) { // TODO: rename
  26. if (url.indexOf(":") != url.lastIndexOf(":")) {
  27. url = url.substr(0, url.lastIndexOf(':'));
  28. }
  29. return url;
  30. }
  31. function GetOrigUrl(url) {
  32. return cutSize(url) + ':orig';
  33. }
  34. function GetFileExtension(url) {
  35. url = cutSize(url);
  36. return url.substring(url.lastIndexOf(".")+1);
  37. }
  38. var Gallery;
  39. (function (Gallery) {
  40. var galleryTweetContainer = document.getElementsByClassName("GalleryTweet")[0];
  41. var observer = new MutationObserver(function (mutations) {
  42. mutations.forEach(function (mutation) {
  43. if (mutation.type == "childList") {
  44. if (galleryTweetContainer.children.length !== 0) {
  45. var tweet = galleryTweetContainer.getElementsByClassName("tweet")[0];
  46. new TweetTools(tweet);
  47. }
  48. }
  49. });
  50. });
  51. observer.observe(galleryTweetContainer, {
  52. childList: true
  53. });
  54. })(Gallery || (Gallery = {}));
  55. var TweetTools = (function () {
  56. function TweetTools(tweet) {
  57. this.dlButton = document.createElement("button");
  58. var t = this;
  59. t.tweet = tweet;
  60. t.GetMedia();
  61. t.actionFooter = tweet.getElementsByClassName("ProfileTweet-actionList")[0];
  62.  
  63. var dlContainer = document.createElement("div");
  64. dlContainer.className = "ProfileTweet-action ProfileTweet-action--reply tis-new-tab";
  65. dlContainer.appendChild(t.dlButton);
  66. if (t.actionFooter.lastElementChild.classList.contains("ProfileTweet-action--more")) {
  67. t.actionFooter.insertBefore(dlContainer, t.actionFooter.lastElementChild);
  68. } else {
  69. t.actionFooter.appendChild(dlContainer);
  70. }
  71. t.dlButton.className = "ProfileTweet-actionButton u-textUserColorHover js-actionButton js-tooltip";
  72. t.dlButton.title = "Download";
  73.  
  74. if (t.downloadableMedia.length == 1) {
  75. t.dlButton.onclick = function () {
  76. GM_download({url: t.downloadableMedia[0], name: t.GetFilename(t.downloadableMedia[0])});
  77. };
  78. }
  79. else {
  80. // download only current image if it's open in gallery
  81. var galleryImageConainer = document.getElementsByClassName("Gallery-media")[0];
  82. if (galleryImageConainer.children.length !== 0) {
  83. var image = galleryImageConainer.children[0];
  84. var image_orig_src = GetOrigUrl(image.src)
  85. // get index of opened image
  86. var i = (function () {
  87. for (var i=0; i<t.downloadableMedia.length; i++)
  88. if (t.downloadableMedia[i] === image_orig_src) {
  89. return i;
  90. }
  91. }());
  92. t.dlButton.onclick = function () {
  93. GM_download({url: t.downloadableMedia[i], name: t.GetFilename(t.downloadableMedia[i], i+1)});
  94. };
  95.  
  96. } else {
  97. t.dlButton.onclick = function () {
  98. t.downloadableMedia.forEach(function (mediaUrl, i) {
  99. GM_download({url: mediaUrl, name: t.GetFilename(mediaUrl, i+1)});
  100. });
  101. };
  102. }
  103. }
  104. var dlIcon = document.createElement("span");
  105. dlIcon.className = "Icon Icon--medium Icon--download";
  106.  
  107. var iconContainer = document.createElement("div");
  108. iconContainer.className = "IconContainer";
  109. iconContainer.appendChild(dlIcon);
  110. t.dlButton.appendChild(iconContainer);
  111.  
  112. tweet.className += " has-tis-tools";
  113. }
  114. TweetTools.prototype.GetFilename = function (url, index) {
  115. var t = this;
  116. var username = t.tweet.getAttribute("data-screen-name");
  117. var tweet_id = t.tweet.getAttribute("data-tweet-id");
  118. var ts = t.tweet.getElementsByClassName("_timestamp")[0].getAttribute("data-time-ms");
  119. var formatted_ts = new Date(parseInt(ts)).toISOString().slice(0,10);
  120. var extension = GetFileExtension(url);
  121. var _index = index !== undefined ? "_"+index : "";
  122.  
  123. // var filename = `${username}_${formatted_ts}_${tweet_id}${_index}.${extension}`;
  124. //var filename = `${username}_${tweet_id}${_index}.${extension}`;
  125.  
  126. let filename = '';
  127. let fnArray = newFilename.split('%');
  128.  
  129. for(let i=0; i<fnArray.length;i++){
  130. switch(fnArray[i]){
  131. case 'u':
  132. filename += `${username}`;
  133. break;
  134. case 'tid':
  135. filename += `${tweet_id}`;
  136. break;
  137. case 'ts':
  138. filename += `${ts}`;
  139. break;
  140. case 'fts':
  141. filename += `${formatted_ts}`;
  142. break;
  143. case 'ext':
  144. filename += `${extension}`;
  145. break;
  146. case 'ind':
  147. filename += `${_index}`;
  148. break;
  149. case '':
  150. break;
  151. default:
  152. filename += fnArray[i]
  153. }
  154. }
  155. return filename;
  156. };
  157. TweetTools.prototype.GetMedia = function () {
  158. var t = this;
  159. var media = t.tweet.getElementsByClassName("AdaptiveMedia")[0];
  160. t.downloadableMedia = [];
  161. var images = media.getElementsByTagName("img");
  162. [].forEach.call(images, function (image) {
  163. var origImg = GetOrigUrl(image.src);
  164. t.downloadableMedia.push(origImg);
  165. });
  166. };
  167. return TweetTools;
  168. }());
  169. function initTools() {
  170. var tweets = document.querySelectorAll(":not(.GalleryTweet) > .tweet.has-cards:not(.has-tis-tools):not(.cards-forward):not([data-card2-type])");
  171. tweets = Array.from(tweets).filter(function(tweet) {return tweet.querySelector(".AdaptiveMedia:not(.is-video)");});
  172. [].forEach.call(tweets, function (tweet) {
  173. new TweetTools(tweet);
  174. });
  175. }
  176. var timelineObserver = new MutationObserver(function (mutations) {
  177. mutations.forEach(function (mutation) {
  178. if (mutation.type == "childList") {
  179. initTools();
  180. }
  181. });
  182. });
  183. var overlayObserver = new MutationObserver(function (mutations) {
  184. mutations.forEach(function (mutation) {
  185. if (mutation.type == "childList") {
  186. var overlayContainer = document.getElementsByClassName("PermalinkOverlay-body")[0];
  187. if (overlayContainer.children.length !== 0) {
  188. timelineObserver.disconnect();
  189. initTools();
  190. var overlayStreams = overlayContainer.getElementsByClassName(".stream-items");
  191. [].forEach.call(overlayStreams, function (stream) {
  192. timelineObserver.observe(stream, {
  193. childList: true
  194. });
  195. });
  196. }
  197. }
  198. });
  199. });
  200. var bodyObserver = new MutationObserver(function (mutations) {
  201. mutations.forEach(function (mutation) {
  202. if (mutation.type == "attributes") {
  203. timelineObserver.disconnect();
  204. overlayObserver.disconnect();
  205. initTools();
  206. if (document.body.classList.contains("overlay-enabled")) {
  207. var overlayContainer = document.getElementsByClassName("PermalinkOverlay-body")[0];
  208. overlayObserver.observe(overlayContainer, {
  209. childList: true
  210. });
  211. [].forEach.call(overlayContainer.getElementsByClassName("stream-items"), function (stream) {
  212. timelineObserver.observe(stream, {
  213. childList: true
  214. });
  215. });
  216. }
  217. else {
  218. timelineObserver.observe(document.getElementById("stream-items-id"), {
  219. childList: true
  220. });
  221. }
  222. }
  223. });
  224. });
  225. function initBodyObserver() {
  226. bodyObserver.observe(document.body, {
  227. attributes: true
  228. });
  229. }
  230. initBodyObserver();
  231. })(TwitterImageSaver || (TwitterImageSaver = {}));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement