Greasy Fork is available in English.

UnfollowHater

Shows who unfollowed you on Tumblr

  1. // ==UserScript==
  2. // @name UnfollowHater
  3. // @namespace tumblr-unfollowhater
  4. // @description Shows who unfollowed you on Tumblr
  5. // @include http://www.tumblr.com/blog/*
  6. // @include https://www.tumblr.com/blog/*
  7. // @author Adrian Sanchez
  8. // @version 2.0.0 beta
  9. // @grant none
  10. // @require http://code.jquery.com/jquery-2.1.4.js
  11. // @require http://code.jquery.com/ui/1.11.4/jquery-ui.js
  12. // ==/UserScript==
  13.  
  14. //***********************************************************************************
  15. // This program is free software: you can redistribute it and/or modify
  16. // it under the terms of the GNU General Public License as published by
  17. // the Free Software Foundation, either version 3 of the License, or
  18. // (at your option) any later version.
  19. //
  20. // This program is distributed in the hope that it will be useful,
  21. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. // GNU General Public License for more details.
  24. //
  25. // You should have received a copy of the GNU General Public License
  26. // along with this program. If not, see http://www.gnu.org/licenses/gpl-3.0.html
  27. //***********************************************************************************
  28. if (window.top != window.self) //-- Don't run on frames or iframes
  29. return;
  30. var FUNCTION_DESCRIPTION_UNFOLLOWER = 'Current new unfollows:';
  31. var FUNCTION_DESCRIPTION_NEWFOLLOWER = 'Current new followers:';
  32. var FUNCTION_DESCRIPTION_TOTAL_UNFOLLOWER = 'Total unfollows since this script is running:';
  33. var loading_control = {function_name:'loading', title:'Parsing Pages', function_description:''};
  34. var error_control = {function_name:'error', title:'Error', function_description:'There was an error while the script was executing: '};
  35. var unfollow_control = {function_name:'unfollower', title:'Unfollowers', function_description:FUNCTION_DESCRIPTION_UNFOLLOWER};
  36. var new_follow_control = {function_name:'new_follower', title:'New Followers', function_description:FUNCTION_DESCRIPTION_NEWFOLLOWER};
  37. var total_follow_control = {function_name:'total_unfollower', title:'Total Unfollowers', function_description:FUNCTION_DESCRIPTION_TOTAL_UNFOLLOWER};
  38.  
  39. function load_css(){
  40. var css_jqueryui = document.createElement('link');
  41. css_jqueryui.rel = 'stylesheet';
  42. css_jqueryui.type = 'text/css';
  43. css_jqueryui.href = 'https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css';
  44.  
  45. var style = document.createElement('style');
  46. style.innerHTML = "#feedback { font-size: 1.4em; }"+
  47. " #selectable .ui-selecting { background: #FECA40; }"+
  48. " #selectable .ui-selected { background: #F39814; color: white; }"+
  49. " #selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; }"+
  50. " #selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; text-align: center; }";
  51.  
  52. document.getElementsByTagName("head")[0].appendChild(css_jqueryui);
  53. document.getElementsByTagName("head")[0].appendChild(style);
  54.  
  55. }
  56.  
  57. function getTumblelog(){
  58. return document.URL.split("/")[4].replace(/[#]/gi,"");
  59. }
  60.  
  61. function get_dom_from_string(data){
  62. var element = document.createElement('div');
  63. element.innerHTML = data;
  64. return element;
  65. }
  66.  
  67. function process(){
  68. load_css();
  69. display_control(loading_control, 0);
  70.  
  71. $.ajax({
  72. url: furl,
  73. cache: false
  74. }).done(function(data) {
  75. var follower_list = get_follower_list(data);
  76. var current_list = jQuery.parseJSON(localStorage.getItem(getTumblelog()+"_followersList"));
  77. var storage_string_unfollower = localStorage.getItem(getTumblelog()+"_unfollowersList");
  78.  
  79. var unfollowers_list = compare_lists(current_list,follower_list);
  80. var new_followers_list = compare_lists(follower_list,current_list);
  81. var total_unfollowers_list = create_total_unfollowers_list((storage_string_unfollower===null)?[]:jQuery.parseJSON(storage_string_unfollower),new_followers_list,unfollowers_list);
  82.  
  83. if ((unfollowers_list !==null)&&(unfollowers_list.length > 0)){
  84. localStorage.setItem(getTumblelog()+"_unfollowersList",JSON.stringify(total_unfollowers_list));
  85. }
  86. remove_control(loading_control);
  87. set_control(unfollowers_list,unfollow_control);
  88. set_control(new_followers_list,new_follow_control);
  89. set_control(total_unfollowers_list,total_follow_control);
  90. localStorage.setItem(getTumblelog()+"_followersList",JSON.stringify(follower_list));
  91. console.log("done");
  92. }).fail(function(data,textStatus,errorThrown) {
  93. display_error({text_status:textStatus, error_thrown:errorThrown});
  94. });
  95. }
  96.  
  97. function create_total_unfollowers_list(total_unfollowers_list, new_followers_list, unfollowers_list){
  98. var tul_wo_nf_list = compare_lists(total_unfollowers_list,new_followers_list);
  99. var tul_wo_uf_list = compare_lists(tul_wo_nf_list,unfollowers_list);
  100. return tul_wo_uf_list.concat(unfollowers_list);
  101. }
  102.  
  103. function get_follower_list(data){
  104. var followerPages = Math.ceil(get_follower_count(data)/followersPage);
  105. var furl_ext = furl+"/page/";
  106. var followerList = [];
  107.  
  108. for(i=0; i<followerPages; i++){
  109. var page = i+1;
  110. $.ajax({
  111. async: false,
  112. url: furl_ext+page,
  113. cache: false
  114. }).done(function(data) {
  115. update_counter_control(loading_control, page+"/"+followerPages);
  116. var element = get_dom_from_string(data);
  117. $(element).find('.name').each(function(){
  118. var link = $(this).find('a').attr('href');
  119. followerList[followerList.length] = {name: $(this).text(),
  120. url: link};
  121. });
  122. }).fail(function(data,textStatus,errorThrown) {
  123. display_error({text_status:textStatus, error_thrown:errorThrown});
  124. });
  125. }
  126. set_new_follower_list(followerList);
  127. return followerList;
  128. }
  129.  
  130.  
  131. function get_follower_count(data){
  132. var element = get_dom_from_string(data);
  133. return parseInt($(element).find('.title_and_controls').text().replace(/\,/g,'').replace(/\./g,'').replace(/\ /g,'').match("[0-9]+"));
  134. }
  135.  
  136. function set_new_follower_list(list){
  137. if(virgen){
  138. localStorage.setItem(getTumblelog()+"_followersList",JSON.stringify(list));
  139. }
  140. }
  141.  
  142. function compare_lists(current_list, new_list){
  143. var diff = [];
  144. for(var i=0; i<current_list.length; i++){
  145. var found=false;
  146. for(var j=0; j<new_list.length; j++){
  147. if(new_list[j]["name"]==current_list[i]["name"]){
  148. found=true;
  149. break;
  150. }
  151. }
  152. if(!found){
  153. diff[diff.length]=current_list[i];
  154. }
  155. }
  156. return diff;
  157. }
  158.  
  159. function set_control(list, control) {
  160. var count = list.length;
  161.  
  162.  
  163. display_control(control, count);
  164.  
  165.  
  166. insert_content_dialog(control,
  167. function(){
  168. var element = create_content_dialog(control);
  169. var list_element = display_list(list);
  170. $('#'+element.id).empty();
  171. $(element).append(list_element);
  172. $(element).append(please_donate());
  173. $(element).dialog({
  174. title: control.title,
  175. close: function( event, ui ) {
  176. list_element.innerHTML="";
  177. }
  178. });
  179. $(element).position({
  180. my: "center"
  181. });
  182. });
  183.  
  184. }
  185.  
  186. function create_content_dialog(control){
  187. var element = document.createElement('div');
  188. var description_text = document.createElement('div');
  189. element.id = control.function_name+"_dialog";
  190. description_text.id = control.function_name+"_text";
  191. description_text.innerHTML = control.function_description;
  192. $(element).append(description_text);
  193. return element;
  194. }
  195.  
  196. function insert_content_dialog(control, functionality){
  197. $('#'+control.function_name+'_control').click(functionality);
  198. }
  199.  
  200. function display_control(control, count){
  201. $('#dashboard_controls_open_blog').append('<li id="'+control.function_name+'_control" class="controls_section_item "><a class="control-item control-anchor posts"><div class="hide_overflow">'+control.title+'</div><span id="'+control.function_name+'_count" class="count"></span></a></li>');
  202. $('#'+control.function_name+'_count').text(count);
  203. }
  204.  
  205. function update_counter_control(control, count){
  206. $('#'+control.function_name+'_count').text(count);
  207. }
  208.  
  209. function remove_control(control){
  210. $('#'+control.function_name+'_control').remove();
  211. }
  212.  
  213. function display_list(follower_list){
  214. var ol = document.createElement('ol');
  215. $(ol).selectable();
  216. for(i=0;i<follower_list.length;i++){
  217. var li = document.createElement('li');
  218. var a = document.createElement('a');
  219.  
  220. $(a).attr('href',follower_list[i]["url"]).text(follower_list[i]["name"]);
  221. $(a).attr('target','_blank');
  222. $(li).addClass('ui-widget-content').append(a);
  223. $(ol).append(li);
  224. }
  225. return ol;
  226. }
  227.  
  228. function please_donate(){
  229. var paypal_html='<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">'+
  230. '<input type="hidden" name="cmd" value="_s-xclick">'+
  231. '<input type="hidden" name="hosted_button_id" value="WD4YNAQALVHLC">'+
  232. '<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">'+
  233. '<img alt="" border="0" src="https://www.paypalobjects.com/es_XC/i/scr/pixel.gif" width="1" height="1"></form>';
  234.  
  235. var paypal_element = document.createElement('div');
  236. paypal_element.innerHTML = paypal_html;
  237.  
  238. return paypal_element;
  239. }
  240.  
  241. function display_error(error){
  242. display_control(error_control, error);
  243. insert_content_dialog(error_control, function(){
  244. var element = create_content_dialog(error_control);
  245. $('#'+element.id).empty();
  246. $(element).append(please_donate());
  247. $('#'+control.function_name+'_text').text('\n\n'+error.text_status+": "+error.error_thrown);
  248. $(element).dialog({
  249. title: control.title,
  250. close: function( event, ui ) {
  251. $('#'+control.function_name+'_text').text('');
  252. }
  253. });
  254. $(element).position({
  255. my: "center"
  256. });
  257. });
  258. }
  259.  
  260. function top_icon(){
  261. }
  262.  
  263. var followersPage = 40;
  264. var blogUrl = window.location.protocol+"//www.tumblr.com/blog/";
  265. var furl = blogUrl+getTumblelog()+"/followers";
  266. var virgen = (localStorage.getItem(getTumblelog()+"_followersList")===null);
  267. console.log("start");
  268.  
  269. $(document).ready(function() {
  270. process();
  271. });
  272.  
  273.  
  274.