Discord Keyword Notification

Displays a browser notification whenever a user mentions specific textual word(s) in a channel.

当前为 2018-10-20 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Discord Keyword Notification
  3. // @namespace http://tampermonkey.net/
  4. // @license GNU AGPLv3
  5. // @version 1.0.1
  6. // @description Displays a browser notification whenever a user mentions specific textual word(s) in a channel.
  7. // @author jcunews
  8. // @match https://discordapp.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13.  
  14. //=== CONFIGURATION BEGIN ===
  15.  
  16. //maximum duration to display notification
  17. var notificationDuration = 5000; //in milliseconds. 1000ms = 1 second. 0 or less = disable auto-dismiss notification.
  18.  
  19. //keywords are specified as regular expression. note: the "g" flag is required.
  20. //quick tutorial: https://www.codeproject.com/Articles/199382/Simple-and-Useful-JavaScript-Regular-Expression-Tu
  21. //full tutorial: https://www.regular-expressions.info/tutorial.html
  22. var keywordsRegexp = /\bnotifyme\b|\bspotme\b|\bmatchwordstart|matchwordend\b|^matchmessagestart|matchmessageend$/gi;
  23.  
  24. //=== CONFIGURATION END ===
  25.  
  26. var observer, observing, selector = '[class^="messagesWrapper-"] [class^="messages-"]', matches = [];
  27. function notify(keywords, nt) {
  28. var nt = new Notification("Keyword Notification", {
  29. body: keywords.shift() + " mentions: " + keywords.join(", ")
  30. });
  31. setTimeout(function() {
  32. matches.shift();
  33. }, 500);
  34. if (notificationDuration > 0) setTimeout(function() {
  35. nt.close();
  36. }, notificationDuration);
  37. }
  38.  
  39. function getMatches(s, r, m) {
  40. r = [];
  41. while (m = keywordsRegexp.exec(s)) r.push(m[0]);
  42. return r;
  43. }
  44.  
  45. function check(records) {
  46. records.forEach(function(record) {
  47. record.addedNodes.forEach(function(node, m, s) {
  48. if (node && (node = node.querySelector('[class^="markup-"]')) && ((m = getMatches(node.textContent)).length)) {
  49. m.unshift(node.querySelector("h2 span").textContent.trim());
  50. if (!matches.includes(s = m.join("\uffff"))) {
  51. matches.push(s);
  52. notify(m);
  53. }
  54. }
  55. });
  56. });
  57. }
  58.  
  59. function init(observerInit) {
  60. observerInit = {childList: true, subtree: true};
  61. setInterval(function(ele) {
  62. if (location.pathname.substr(0, 10) === "/channels/") {
  63. if (!observing && (ele = document.querySelector(selector))) {
  64. observing = true;
  65. if (!observer) observer = new MutationObserver(check);
  66. observer.observe(ele, observerInit);
  67. }
  68. } else if (observing) {
  69. observer.disconnect();
  70. observing = false;
  71. }
  72. }, 500);
  73. }
  74.  
  75. if (window.Notification) {
  76. Notification.requestPermission().then(function() {
  77. if (Notification.permission === "granted") {
  78. init();
  79. } else alert("Access to Browser Notification feature is not granted by user.\nKeyword notification can not be displayed.");
  80. });
  81. } else alert("Browser Notification feature is disabled or not supported.");
  82.  
  83. })();