Gitter Done for FreeCodeCamp

Fix annoyances of of gitter.im FreeCodeCamp channels

  1. // ==UserScript==
  2. // @name Gitter Done for FreeCodeCamp
  3. // @namespace http://aimless.info/
  4. // @version 0.4
  5. // @description Fix annoyances of of gitter.im FreeCodeCamp channels
  6. // @author Chuck Adams
  7. // @match https://gitter.im/FreeCodeCamp/*
  8. // @grant unsafeWindow
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
  10. // @require https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. //// config
  17.  
  18. var STFU = ['@camperbot'];
  19. var GAGGED_TEXT = '...';
  20.  
  21. //// main
  22.  
  23. var $ = unsafeWindow.jQuery;
  24.  
  25. addStyles();
  26.  
  27. var targetNodes = $("#chat-container");
  28. var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
  29. var myObserver = new MutationObserver(mutationObserved);
  30. var obsConfig = { childList: true, characterData: false, attributes: false, subtree: true };
  31.  
  32. targetNodes.each(function () {
  33. myObserver.observe (this, obsConfig);
  34. });
  35.  
  36. //// end main
  37.  
  38. function mutationObserved(recs) {
  39. _.each(recs, handleMutation);
  40. }
  41.  
  42. function handleMutation(rec) {
  43. _.each(rec.addedNodes, nodeAdded);
  44. }
  45.  
  46. function addStyles() {
  47. // Bit of a hack but it does the job
  48. $('<style>.gagged .chat-item__content { display: none; }</style>').appendTo('head');
  49. $('<style>.gagged .chat-item__actions { display: none; }</style>').appendTo('head');
  50. $('<style>.gagged .avatar__image { border: 5px double #fcf; }</style>').appendTo('head');
  51. $('<style>.muffled-screaming { display: none; position: absolute; top: 0; left: 64px; white-space: nowrap; }</style>').appendTo('head');
  52. $('<style>.muffled-screaming.audible { display: inline; color: #ccc; font-style: italic; }</style>').appendTo('head');
  53. }
  54.  
  55. function nodeAdded(node) {
  56. var from = $('.chat-item__username', node);
  57. if (from.length === 0) return;
  58.  
  59. var who = from.text();
  60. if (who === '') return;
  61.  
  62. if (_.contains(STFU, who)) {
  63. gag(node);
  64. }
  65. }
  66.  
  67. function gag(node) {
  68. var avatar = $('img.avatar__image', node);
  69. if (avatar.length === 0) return; // node is deeper than we wanted
  70.  
  71. $(node).addClass('gagged');
  72. avatar.click(function () { ungag(node); });
  73.  
  74. var screams = $('.muffled-screaming', node);
  75. if (screams.length === 0) {
  76. $('<span class="muffled-screaming audible">' + GAGGED_TEXT + '</span>').insertAfter(avatar);
  77. screams = $('.muffled-screaming', node);
  78. }
  79. screams.addClass('audible');
  80. }
  81.  
  82. function ungag(node) {
  83. $(node).removeClass('gagged');
  84. var avatar = $('img.avatar__image', node);
  85. avatar.click(function () { gag(node); });
  86. $('.muffled-screaming', node).removeClass('audible');
  87. }
  88.  
  89. })();