Discord - Custom Background Image

You can set custom background image of Discord

  1. // ==UserScript==
  2. // @name Discord - Custom Background Image
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.9
  5. // @description You can set custom background image of Discord
  6. // @author You
  7. // @match https://discord.com/channels/*
  8. // @match https://discord.com/channels/*/*
  9. // @icon https://www.google.com/s2/favicons?domain=discord.com
  10. // @grant GM.xmlHttpRequest
  11. // @grant GM.registerMenuCommand
  12. // @grant GM.getValue
  13. // @grant GM.setValue
  14. // @grant GM.addElement
  15. // @connect i.imgur.com
  16. // @license MIT
  17. // ==/UserScript==
  18.  
  19. (async window => {
  20. 'use strict';
  21.  
  22. let intervalTime = 30 * 1000;
  23. let urls = [
  24. 'https://i.imgur.com/cHKbKQT.jpeg',
  25. 'https://i.imgur.com/sqmqy20.png',
  26. 'https://i.imgur.com/cCL6TPk.jpeg',
  27. 'https://i.imgur.com/Z6GYpxh.jpeg',
  28. 'https://i.imgur.com/FNJdY5h.jpeg',
  29. 'https://i.imgur.com/uKVG1XM.jpeg'
  30. ];
  31.  
  32. let g_elm = null;
  33.  
  34. const del = () => {
  35. if (g_elm) {
  36. g_elm.remove();
  37. g_elm = null;
  38. return true;
  39. }
  40. return false;
  41. };
  42.  
  43. const addInput = async (value) => {
  44. if (del()) return;
  45.  
  46. g_elm = await GM.addElement(document.body, 'div', {});
  47. Object.assign(g_elm.style, {
  48. 'position': 'fixed',
  49. 'width': '100vw',
  50. 'height': '100vh',
  51. 'display': 'flex',
  52. 'flex-wrap': 'wrap',
  53. 'justify-content': 'center',
  54. 'align-items': 'center',
  55. 'z-index': Infinity
  56. });
  57.  
  58. const input = await GM.addElement(g_elm, 'textarea', {
  59. textContent: value
  60. });
  61.  
  62. Object.assign(input.style, {
  63. 'width': '50vw',
  64. 'height': '30vh',
  65. 'font-size': '24px',
  66. 'font-weight': 'bold'
  67. });
  68.  
  69. const btnSave = await GM.addElement(g_elm, 'button', {
  70. textContent: 'save'
  71. });
  72.  
  73. await GM.addElement(g_elm, 'div', {
  74. textContent: ' '
  75. });
  76.  
  77. const btnCancel = await GM.addElement(g_elm, 'button', {
  78. textContent: 'cancel'
  79. });
  80.  
  81. for (const v of [btnSave, btnCancel]) {
  82. Object.assign(v.style, {
  83. 'color': 'white',
  84. 'backgroundColor': 'red'
  85. });
  86. }
  87.  
  88. return new Promise((resolve, reject) => {
  89. btnSave.addEventListener('click', () => del() && resolve(input.value));
  90. btnCancel.addEventListener('click', () => del() && reject());
  91. });
  92. };
  93.  
  94. const key1 = 'intervalTime';
  95. GM.registerMenuCommand('config interval time', async () => {
  96. const res = await addInput(await GM.getValue(key1, intervalTime));
  97. if (!res) return;
  98.  
  99. const m = res.match(/[0-9]+/);
  100. if (!m) return;
  101.  
  102. const n = Number(m[0]);
  103. intervalTime = n;
  104. GM.setValue(key1, n);
  105. });
  106.  
  107. intervalTime = await GM.getValue(key1, intervalTime);
  108.  
  109. const key2 = 'URL';
  110. GM.registerMenuCommand('config URL', async () => {
  111. const res = await addInput(await GM.getValue(key2, urls.join('\n')));
  112. if (!res) return;
  113.  
  114. const a = findURL(res);
  115. if (!a.length) return;
  116.  
  117. urls = a;
  118. GM.setValue(key2, a.join('\n'));
  119. });
  120.  
  121. urls = (await GM.getValue(key2, urls.join('\n'))).split('\n');
  122.  
  123. const findURL = (str) => {
  124. const m = str.match(/(https?|ftp)(:\/\/[-_.!~*'()a-zA-Z0-9;\/?:@&=+$,%#]+)/g);
  125. return m || [];
  126. };
  127.  
  128. const memo = new Map();
  129. const get = async (url) => {
  130. if (memo.has(url)) return memo.get(url);
  131.  
  132. const res = await GM.xmlHttpRequest({
  133. method: 'GET',
  134. url: url,
  135. withCredentials: true,
  136. responseType: 'arraybuffer',
  137. });
  138.  
  139. const blobUrl = URL.createObjectURL(new Blob([res.response], { type: 'application/octet-binary' }));
  140. memo.set(url, blobUrl);
  141.  
  142. return blobUrl;
  143. };
  144.  
  145. let g_url = await get(urls[0]);
  146.  
  147. const wait = (resolve) => {
  148. if (document.querySelector('[class^="chatContent"]')) return resolve();
  149. setTimeout(() => wait(resolve), 500);
  150. };
  151.  
  152. await new Promise(resolve => wait(resolve));
  153.  
  154. const setURL = () => {
  155. Object.assign(document.body.children[0].style, {
  156. 'background-image': 'url("' + g_url + '")',
  157. 'background-attachment': 'fixed',
  158. 'background-position': 'center center',
  159. 'background-size': 'cover',
  160. 'background-repeat': 'no-repeat',
  161. 'transition-duration': '1.5s'
  162. });
  163. };
  164.  
  165. setURL();
  166.  
  167. const setOther = () => {
  168. for (const v of document.querySelectorAll('*')) {
  169. v.style.backgroundColor = 'rgba(0, 0, 0, 0)';
  170. }
  171. document.body.children[0].children[3].style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  172.  
  173. const aplicarTransparencia = () => {
  174. const embeds = document.querySelectorAll('.embed');
  175. embeds.forEach(embed => {
  176. embed.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  177. embed.style.backdropFilter = 'blur(10px)';
  178. });
  179.  
  180. const embedContents = document.querySelectorAll('.embed .embed-content');
  181. embedContents.forEach(content => {
  182. content.style.backgroundColor = 'rgba(0, 0, 0, 0.3)';
  183. });
  184.  
  185. const attachments = document.querySelectorAll('.attachment');
  186. attachments.forEach(attachment => {
  187. attachment.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
  188. attachment.style.backdropFilter = 'blur(10px)';
  189. });
  190. };
  191.  
  192. const observeEmbeds = () => {
  193. const observer = new MutationObserver(mutations => {
  194. aplicarTransparencia();
  195. });
  196.  
  197. observer.observe(document.body, { childList: true, subtree: true });
  198.  
  199. setInterval(() => {
  200. aplicarTransparencia();
  201. }, 50); // Verificação a cada 50ms
  202. };
  203.  
  204. observeEmbeds();
  205.  
  206. aplicarTransparencia();
  207. };
  208.  
  209. setOther();
  210.  
  211. let _url = location.href;
  212. let _time = 0;
  213. let index = 0;
  214.  
  215. const update = async () => {
  216. const time = performance.now();
  217.  
  218. if (time - _time > intervalTime) {
  219. g_url = await get(urls[(++index) % urls.length]);
  220. _time = performance.now();
  221. setURL();
  222. } else {
  223. const url = location.href;
  224. if (url !== _url) {
  225. _url = url;
  226. setOther();
  227. }
  228. }
  229.  
  230. requestAnimationFrame(update);
  231. };
  232.  
  233. update();
  234. })(window.unsafeWindow || window);