Discord Reaction Spammer

This script adds a button in Discord's text box that allows you to automatically add reactions to new messages in text channels for however long is specified. Note: If a channel does not allow reactions, some odd things might happen.

  1. // ==UserScript==
  2. // @name Discord Reaction Spammer
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2
  5. // @author You
  6. // @match *://discord.com/*
  7. // @grant none
  8. // @description This script adds a button in Discord's text box that allows you to automatically add reactions to new messages in text channels for however long is specified. Note: If a channel does not allow reactions, some odd things might happen.
  9. // ==/UserScript==
  10.  
  11. // Grab token to send messages
  12.  
  13. window.onload = (() => {
  14. var frame = document.createElement('iframe');
  15. frame.style.display = "none"; // Ensure this is hosted on the same domain
  16. document.body.appendChild(frame)
  17. window.tkn = JSON.parse(frame.contentWindow.localStorage.token)
  18. })();
  19.  
  20. // create all elements
  21.  
  22. const spamMenu = document.createElement("div");
  23. const spamInput = document.createElement("input");
  24. const spamButton = document.createElement("button");
  25. const spamEnter = document.createElement("button");
  26.  
  27. spamMenu.className = "hiddenclass spamMenu";
  28. spamButton.className = "hiddenclass spamButton";
  29. spamInput.className = "hiddenclass spamInput";
  30. spamEnter.className = "hiddenclass spamEnter";
  31.  
  32. const style = document.createElement("style");
  33. style.classList.add("customstyles"); // to detect it later on
  34. style.type = "text/css";
  35. style.innerHTML =
  36. ".spamMenu { border-radius: 8px; background-color: #2f3136; height: 0px; width: 250px; overflow: hidden; z-index: 1; position: absolute; right: 0; bottom: calc(100% + 8px); box-shadow: none; transition: all 0.2s; }" +
  37. ".spamInput { padding: 2px; width: 150px; height: 30px; background: #40444B; color: #dcddde; border: none; border-radius: 8px; position: absolute; overflow: hidden; margin-left: 48px; margin-top: 35px; }" +
  38. ".spamButton { letter-spacing: 0.4px; font-weight: bold; width: 50px; color: #CECECE; transition: all 0.2s ease-in; background:var(--bg-overlay-app-frame)} .spamButton:hover { color: #FFFFFF } " +
  39. ".spamEnter { background: #7289DA; color: white; border-radius: 8px; border: none; height: 32px; width: 60px; margin-top: 85px; margin-left: 95px; }" +
  40. ".spamMenuActive { box-shadow: 0 0 0 1px rgba(4,4,5,0.15), 0 8px 16px rgba(0,0,0,0.24); height: 150px; display: block; }" +
  41. ".spamButtonActive { color: #FFFFFF }";
  42.  
  43. // from https://stackoverflow.com/questions/1720320/how-to-dynamically-create-css-class-in-javascript-and-apply
  44. // much better than the "system" I had previously
  45.  
  46. setInterval(() => {
  47. // main function that does the actual spamming
  48.  
  49. function theBestSpammer(sec) {
  50. let emojiarray = ["😀", "😁", "😂", "🤣", "😃", "🥵", "🤑", "😎", "😲"];
  51. console.log(sec);
  52. let sec4 = parseInt(sec) * 4;
  53. if (!sec) sec4 = 120;
  54. let n = 1;
  55. let emojiindex = 0;
  56. let msgid;
  57. let channel_id;
  58. let channel_url;
  59. for (var i = 0; i < sec4; i++) {
  60. setTimeout(() => {
  61. try {
  62. channel_id = window.location.href.substring(
  63. window.location.href.lastIndexOf("/") + 1,
  64. window.location.href.length
  65. );
  66. msgid = document
  67. .querySelectorAll('[id^="message-content"]')
  68. [
  69. document.querySelectorAll('[id^="message-content"]').length - n
  70. ].id.slice("message-content-".length);
  71. channel_url = `https://discord.com/api/v8/channels/${channel_id}/messages/${msgid}/reactions/${emojiarray[emojiindex]}/%40me`;
  72. request = new XMLHttpRequest();
  73. request.withCredentials = true;
  74. request.open("PUT", channel_url);
  75. request.setRequestHeader("authorization", window.tkn);
  76. request.setRequestHeader("accept", "/");
  77. request.setRequestHeader("authority", "discord.com");
  78. request.setRequestHeader("content-type", "application/json");
  79. request.send(JSON.stringify({}));
  80. if (emojiindex >= emojiarray.length - 1) {
  81. n++;
  82. emojiindex = 0;
  83. }
  84. emojiindex++;
  85. } catch (err) {
  86. console.error(err + "\nerror");
  87. }
  88. }, 400 * i);
  89. }
  90. }
  91.  
  92. // detect if the styles have been added yet
  93. if (!document.querySelector(".customstyles")) {
  94. document.getElementsByTagName("head")[0].appendChild(style);
  95. }
  96.  
  97. if (!document.querySelector(".hiddenclass")) {
  98. const buttonCollection = document.querySelectorAll(
  99. "form > div > div > div > div"
  100. )[document.querySelectorAll(
  101. "form > div > div > div > div"
  102. ).length - 1];
  103. const textArea = document.querySelectorAll("form > div")[0];
  104.  
  105. buttonCollection.appendChild(spamButton);
  106. textArea.appendChild(spamMenu);
  107. spamMenu.appendChild(spamInput);
  108. spamMenu.appendChild(spamEnter);
  109.  
  110. spamButton.innerText = "Spam";
  111. spamButton.onclick = function () {
  112. spamButton.classList.toggle("spamButtonActive");
  113. spamMenu.classList.toggle("spamMenuActive");
  114. };
  115. window.onclick = (e) => {
  116. if (
  117. !e.target.classList.contains("hiddenclass") &&
  118. spamMenu.style.height != "0px"
  119. ) {
  120. spamButton.classList.remove("spamButtonActive");
  121. spamMenu.classList.remove("spamMenuActive");
  122. }
  123. };
  124. spamInput.placeholder = "Seconds, e.g., 60";
  125. spamInput.style.placeholder = "color: #666971";
  126. spamInput.addEventListener("keyup", function (event) {
  127. if (event.keyCode === 13) {
  128. spamEnter.click();
  129. document.querySelector('body').click();
  130. }
  131. });
  132. spamEnter.innerText = "Spam!";
  133. spamEnter.onclick = () => {
  134. theBestSpammer(
  135. parseInt(document.querySelector("input.hiddenclass").value)
  136. );
  137. spamButton.click();
  138. };
  139. }
  140. }, 50);
  141.  
  142.