Robin Enhancement Script

Highlight mentions, auto link links & automatically remove spam

目前為 2016-04-03 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Robin Enhancement Script
  3. // @namespace https://www.reddit.com/
  4. // @version 1.7
  5. // @description Highlight mentions, auto link links & automatically remove spam
  6. // @author mr_bag
  7. // @match https://www.reddit.com/robin/
  8. // @grant none
  9. // ==/UserScript==
  10. (function() {
  11.  
  12. // Grab users username + play nice with RES
  13. var robin_user = $("#header-bottom-right .user a").first().text();
  14. var ignored_users = {};
  15.  
  16. /**
  17. * Check if a message is "spam"
  18. */
  19. var is_spam = function(line){
  20. return (
  21. // Hide auto vote messages
  22. (/^voted to (grow|stay|abandon)/.test(line)) ||
  23. // random unicode?
  24. (/[\u0080-\uFFFF]/.test(line)) ||
  25. // hide any auto voter messages
  26. (/\[.*autovoter.*\]/.test(line)) ||
  27. // Common bots
  28. (/^(\[binbot\]|\[robin-grow\])/.test(line)) ||
  29. // repeating chars in line (more than 5). e.g. aaaaaaa !!!!!!!!
  30. (/(.)\1{5,}/.test(line)) ||
  31. // Some common messages
  32. (/(voting will end in approximately|\[i spam the most used phrase\]|\[message from creator\])/.test(line)) ||
  33. // no spaces = spam if its longer than 25 chars (dont filter links)
  34. (line.indexOf(" ") === -1 && line.length > 25 && line.indexOf("http") === -1) ||
  35. // repeating same word
  36. /(\b\S+\b)\s+\b\1\b/i.test(line)
  37. );
  38. };
  39.  
  40. /**
  41. * Check if a message is from an ignored user
  42. *
  43. */
  44. var is_ignored = function($usr, $ele){
  45. // no user name, go looking for when said it
  46. if($usr.length === 0){
  47. while($usr.length === 0){
  48. $ele = $ele.prev();
  49. $usr = $ele.find(".robin--username");
  50. }
  51. }
  52. // are they ignored?
  53. return (ignored_users[$usr.text()]);
  54. };
  55.  
  56. /**
  57. * Make links clickable
  58. *
  59. */
  60. var auto_link = function($msg){
  61. var text = $msg.html(); // read as html so stuff stays escaped
  62. // normal links
  63. text = text.replace(/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim, '<a target="blank" href="$&">$&</a>');
  64. // reddit subreddit links
  65. text = text.replace(/ \/r\/(\w+)/gim, ' <a target="blank" href="https://reddit.com/r/$1">/r/$1</a>');
  66. // update text
  67. $msg.html(text);
  68. };
  69.  
  70. /**
  71. * Mute a user
  72. */
  73. var _mute_user = function(usr){
  74. // Add to ignore list
  75. ignored_users[usr] = true;
  76. _render_muted_list();
  77. };
  78.  
  79. /**
  80. * un-mute a user
  81. */
  82. var _unmute_user = function(usr){
  83. // Add to ignore list
  84. delete ignored_users[usr];
  85. _render_muted_list();
  86. };
  87.  
  88. // Render list of ignored users
  89. var _render_muted_list = function(){
  90. var html = "<strong>Ignored users</strong><br>";
  91. for(var u in ignored_users){
  92. html += "<div data-usr='"+ u + "'>" + u + " - [unmute]</div>";
  93. }
  94. $("#muted_users").html(html);
  95. };
  96.  
  97. // Scroll chat back to bottom
  98. var _scroll_to_bottom = function(){
  99. $("#robinChatWindow").scrollTop($("#robinChatMessageList").height());
  100. };
  101.  
  102. /**
  103. * Parse a link and apply changes
  104. */
  105. var parse_line = function($ele){
  106. var $msg = $ele.find(".robin-message--message");
  107. var $usr = $ele.find(".robin--username");
  108.  
  109. var line = $msg.text().toLowerCase();
  110.  
  111. // If user is ignored or message looks like "Spam". hide it
  112. if (is_ignored($usr, $ele) || is_spam(line)) {
  113. $ele.addClass("spam-hidden");
  114. }
  115.  
  116. // Highlight mentions
  117. if(line.indexOf(robin_user) !== -1){
  118. $ele.css("font-weight", "bold");
  119. }
  120.  
  121. // Make links clickable
  122. if(line.indexOf("http") !== -1){
  123. auto_link($msg);
  124. }
  125.  
  126. // Add mute button to users
  127. if(!$ele.hasClass("robin--user-class--system") && $usr.text() != robin_user){
  128. $("<span style='font-size:.8em;cursor:pointer'> [mute] </span>").insertBefore($usr).click(function(){
  129. _mute_user($usr.text());
  130. });
  131. }
  132.  
  133. // Add filter support
  134. if(line.indexOf("%") === 0){ $ele.addClass("filter-percent");}
  135. if(line.indexOf("$") === 0){ $ele.addClass("filter-dollar");}
  136. if(line.indexOf("#") === 0){ $ele.addClass("filter-hash"); }
  137. };
  138.  
  139. // Detect changes, are parse the new message
  140. $("#robinChatWindow").on('DOMNodeInserted', function(e) {
  141. if ($(e.target).is('div.robin-message')) {
  142. // Apply changes to line
  143. parse_line($(e.target));
  144. }
  145. });
  146.  
  147. // When everything is ready
  148. $(document).ready(function(){
  149. // Set default spam filter type
  150. $("#robinChatWindow").addClass("hide-spam");
  151.  
  152. // Add checkbox to toggle "hide" behaviors
  153. $("#robinDesktopNotifier").append("<label><input type='checkbox' checked='checked'>Hide spam completely</label>").click(function(){
  154. if($(this).find("input").is(':checked')){
  155. $("#robinChatWindow").removeClass("mute-spam").addClass("hide-spam");
  156. }else{
  157. $("#robinChatWindow").removeClass("hide-spam").addClass("mute-spam");
  158. }
  159. // correct scroll after spam filter change
  160. _scroll_to_bottom();
  161. });
  162.  
  163. // Add Muted list & hook up unmute logic
  164. $('<div id="muted_users" class="robin-chat--sidebar-widget robin-chat--notification-widget"><strong>Ignored users</strong></div>').insertAfter($("#robinDesktopNotifier"));
  165. $('#muted_users').click(function(e){
  166. var user = $(e.target).data("usr");
  167. if(user) _unmute_user(user);
  168. });
  169.  
  170. // Hook up toggles for filters
  171. $('<div id="filter_mode">Filter: <span data-filter="*">Show all</span> | <span data-filter="%">% Only</span> | <span data-filter="$">$ Only</span> | <span data-filter="#"># Only</span> | <span data-filter="hide">No channels</span></div>').insertAfter("#robinSendMessage").click(function(e){
  172. var filter = $(e.target).data("filter");
  173. if(filter === '*'){
  174. $("#robinChatWindow").removeClass("filter_on").removeAttr("data-filter").removeClass("filter_all_channels");
  175. }else if(filter === 'hide'){
  176. $("#robinChatWindow").removeClass("filter_on").removeAttr("data-filter").addClass("filter_all_channels");
  177. }else{
  178. $("#robinChatWindow").addClass("filter_on").attr("data-filter", filter);
  179. }
  180. // correct scroll after filter change
  181. _scroll_to_bottom();
  182. });
  183. // Auto append % when in filtered mode
  184. $("#robinSendMessage").submit(function(){
  185. if($("#robinChatWindow").hasClass("filter_on")){
  186. if($(".text-counter-input").val().indexOf("/") !== 0){ // /commands should work as normal
  187. $(".text-counter-input").val($("#robinChatWindow").attr("data-filter") + " " + $(".text-counter-input").val());
  188. }
  189. }
  190. });
  191. });
  192.  
  193.  
  194. // filter styles
  195. document.styleSheets[0].insertRule("#robinChatWindow.filter_on div.robin-message { display:none; }", 0);
  196. document.styleSheets[0].insertRule("#robinChatWindow.filter_on[data-filter='$'] div.robin-message.filter-dollar,#robinChatWindow.filter_on[data-filter='%'] div.robin-message.filter-percent,#robinChatWindow.filter_on[data-filter='#'] div.robin-message.filter-hash,#robinChatWindow.filter_on div.robin-message.robin--user-class--system { display:block; }", 0);
  197. document.styleSheets[0].insertRule("#robinChatWindow.filter_all_channels div.robin-message.filter-dollar,#robinChatWindow.filter_all_channels div.robin-message.filter-hash, #robinChatWindow.filter_all_channels div.robin-message.filter-percent { display:none; }", 0);
  198.  
  199. document.styleSheets[0].insertRule("#filter_mode span { cursor: pointer;}", 0);
  200.  
  201. // Add initial styles for "spam" messages
  202. document.styleSheets[0].insertRule("#robinChat #robinChatWindow.hide-spam div.robin-message.spam-hidden { display:none; }", 0);
  203. document.styleSheets[0].insertRule("#robinChat #robinChatWindow.mute-spam div.robin-message.spam-hidden { opacity:0.3; font-size:1.2em; }", 0);
  204.  
  205. // muted user box
  206. document.styleSheets[0].insertRule("#muted_users { font-size:1.2em; }", 0);
  207. document.styleSheets[0].insertRule("#muted_users div { padding: 2px 0; }", 0);
  208. document.styleSheets[0].insertRule("#muted_users strong { font-weight:bold; }", 0);
  209.  
  210. // FIX RES nightmode (ish)
  211. document.styleSheets[0].insertRule(".res-nightmode #robinChatWindow div.robin-message { color: #ccc; }", 0);
  212. })();