Instagram List Links

Userscript that lets you back up your instagram media

  1. // ==UserScript==
  2. // @name Instagram List Links
  3. // @namespace instagram_list_links
  4. // @description Userscript that lets you back up your instagram media
  5. // @homepageURL https://github.com/daraeman/instagram_list_links
  6. // @author daraeman
  7. // @version 1.1.1
  8. // @date 2016-03-10
  9. // @include /^https?:\/\/www\.instagram\.com\/.*\/?$/
  10. // @exclude /^https?:\/\/www\.instagram\.com\/?$/
  11. // @exclude /^https?:\/\/www\.instagram\.com\/(explore|accounts|emails).*\/?$/
  12. // @grant none
  13. // ==/UserScript==
  14. /* jshint -W097 */
  15. 'use strict';
  16.  
  17. function doScroll( scroll_duration ) {
  18. scroll_duration = scroll_duration || 500;
  19. jQuery( "html, body" ).animate({
  20. scrollTop: ( jQuery( document ).height() - jQuery( window ).height() )
  21. }, scroll_duration );
  22. }
  23.  
  24. function scrollToNextPage() {
  25. var scroll_duration = 500;
  26. doScroll( scroll_duration );
  27. setTimeout(function(){
  28. var loop = 0,
  29. wait = 200;
  30. var max_loops = ( ( 1000 / wait ) * 60 );
  31. interval = setInterval(function(){
  32. loop++;
  33. if ( loop == max_loops ) {
  34. clearInterval( interval );
  35. getImages(function( a ) {
  36. printImages( a );
  37. });
  38. }
  39. else if ( ! isStillLoading() ) {
  40. if ( last_document_height != jQuery( document ).height() ) {
  41. last_document_height = jQuery( document ).height();
  42. clearInterval( interval );
  43. scrollToNextPage();
  44. }
  45. else {
  46. clearInterval( interval );
  47. getImages(function( a ) {
  48. printImages( a );
  49. });
  50. }
  51. }
  52. }, wait );
  53. }, scroll_duration );
  54. }
  55.  
  56. function isStillLoading() {
  57. var check = false;
  58. jQuery( "a" ).each(function(){
  59. if ( /Loading more/i.test( jQuery(this).text() ) ) {
  60. check = true;
  61. return false;
  62. }
  63. });
  64. return check;
  65. }
  66.  
  67. function getImages( callback ) {
  68. jQuery( "img" ).each(function(){
  69. var el = jQuery(this);
  70. var id = el.attr( "id" );
  71. if ( /^pImage/.test( id ) ) {
  72. var all_check = el.parent().parent().parent()[0].nodeName.toLowerCase() == "a";
  73. if ( all_check ) {
  74. var video_check = el.parent().parent().next().find( "span" );
  75. if ( /video/i.test( video_check.text() ) ) {
  76. videos.push({
  77. el: el.parent().parent().parent()
  78. });
  79. }
  80. else {
  81. images.push({
  82. src: el.attr( "src" ),
  83. text: el.attr( "alt" )
  84. });
  85. }
  86. }
  87. }
  88. });
  89.  
  90. if ( videos.length ) {
  91. getVideoLinks(function(){
  92. printImages();
  93. });
  94. }
  95. }
  96.  
  97. function getVideoLinks( callback ) {
  98. var videos_left = ( videos.length - 1 );
  99. var in_view = false;
  100. var current_video = 0;
  101. var max_retry = 20;
  102. var current_retry = 0;
  103. var interval_a = setInterval(function(){
  104. if ( ! in_view ) {
  105. videos[ current_video ].el[0].click();
  106. in_view = true;
  107. }
  108. else {
  109. var button = getCloseButton();
  110. if ( button.length ) {
  111. var src = jQuery( "video" ).attr( "src" );
  112. videos[ current_video ].src = src;
  113. button[0].click();
  114. in_view = false;
  115. if ( videos_left === 0 ) {
  116. clearInterval( interval_a );
  117. callback();
  118. }
  119. videos_left--;
  120. current_video++;
  121. }
  122. else {
  123. if ( current_retry == max_retry ) {
  124. current_retry = 0;
  125. in_view = false;
  126. }
  127. else {
  128. current_retry++;
  129. }
  130. }
  131. }
  132. }, video_interval_duration );
  133. }
  134.  
  135.  
  136. function printImages() {
  137. var img_txt = "";
  138. for ( var i = 0; i < images.length; i++ )
  139. img_txt += images[ i ].src + "\n";
  140.  
  141. var vid_txt = "";
  142. for ( var i = 0; i < videos.length; i++ )
  143. vid_txt += videos[ i ].src + "\n";
  144.  
  145. jQuery( "#react-root main" ).append( '<textarea style="width:90%;margin:30px auto;">'+ img_txt +'</textarea><textarea style="width:90%;margin:30px auto;">'+ vid_txt +'</textarea>' );
  146. }
  147.  
  148. function getCloseButton() {
  149. var button = false;
  150. jQuery( "button" ).each(function(){
  151. if ( /close/i.test( jQuery(this).text() ) ) {
  152. button = jQuery(this);
  153. return false;
  154. }
  155. });
  156. return button;
  157. }
  158.  
  159. function main(){
  160. var load_more = false;
  161. jQuery( "a" ).each(function(){ if ( /Load more/i.test( jQuery(this).text() ) ) load_more = jQuery(this); });
  162.  
  163. if ( load_more ) {
  164. last_document_height = jQuery( document ).height();
  165. load_more[0].click();
  166. scrollToNextPage();
  167. }
  168. }
  169.  
  170. function isPrivate() {
  171. if ( window._sharedData.entry_data.ProfilePage[0].user.is_private )
  172. return ! window._sharedData.entry_data.ProfilePage[0].user.followed_by_viewer;
  173. return false;
  174. }
  175.  
  176. function init() {
  177. if ( isPrivate() )
  178. return false;
  179.  
  180. button = jQuery( '<div style="position: absolute; right: 0px; padding: 9px 27px; border: 1px solid rgb( 235,235,235 ); color: rgb( 170,170,170 ); background: rgb( 255,255,255 ); z-index: 1000; cursor: pointer;">List Links</div>' )
  181. .click(function(){
  182. main();
  183. });
  184. jQuery( "nav" ).first().append( button );
  185. button.css( "bottom", -( button.outerHeight() ) + "px" );
  186. }
  187.  
  188. console.log( "Instagram List Links userscript loaded" );
  189.  
  190. var last_document_height,
  191. interval,
  192. images = [],
  193. videos = [],
  194. button,
  195. video_interval_duration = 500;
  196.  
  197. init();