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.7
  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. let intervalTime = 30 * 1000;
  22. let urls = [
  23. 'https://i.imgur.com/cHKbKQT.jpeg',
  24. 'https://i.imgur.com/sqmqy20.png',
  25. 'https://i.imgur.com/cCL6TPk.jpeg',
  26. 'https://i.imgur.com/Z6GYpxh.jpeg',
  27. 'https://i.imgur.com/FNJdY5h.jpeg',
  28. 'https://i.imgur.com/uKVG1XM.jpeg'
  29. ];
  30. let g_elm = null;
  31. const del = () => {
  32. if(g_elm) {
  33. g_elm.remove();
  34. g_elm = null;
  35. return true;
  36. }
  37. else return false;
  38. };
  39. const addInput = async value => {
  40. if(del()) return;
  41. g_elm = await GM.addElement(document.body, 'div', {});
  42. Object.assign(g_elm.style, {
  43. 'position': 'fixed',
  44. 'width': '100vw',
  45. 'height': '100vh',
  46. 'display': 'flex',
  47. 'flex-wrap': 'wrap',
  48. 'justify-content': 'center',
  49. 'align-items': 'center',
  50. 'z-index': Infinity
  51. });
  52. const input = await GM.addElement(g_elm, 'textarea', {
  53. textContent: value
  54. });
  55. Object.assign(input.style, {
  56. 'width': '50vw',
  57. 'height': '30vh',
  58. 'font-size': '24px',
  59. 'font-weight': 'bold'
  60. });
  61. const btnSave = await GM.addElement(g_elm, 'button', {
  62. textContent: 'save'
  63. });
  64. await GM.addElement(g_elm, 'div', {
  65. textContent: ' '
  66. });
  67. const btnCancel = await GM.addElement(g_elm, 'button', {
  68. textContent: 'cancel'
  69. });
  70. for(const v of [btnSave, btnCancel]) Object.assign(v.style, {
  71. 'color': 'white',
  72. 'backgroundColor': 'red'
  73. });
  74. return new Promise((resolve, reject) => {
  75. btnSave.addEventListener('click', () => del() && resolve(input.value));
  76. btnCancel.addEventListener('click', () => del() && reject());
  77. });
  78. };
  79. const key1 = 'intervalTime';
  80. GM.registerMenuCommand('config interval time', async () => {
  81. const res = await addInput(await GM.getValue(key1, intervalTime));
  82. if(!res) return;
  83. const m = res.match(/[0-9]+/);
  84. if(!m) return;
  85. const n = Number(m[0]);
  86. intervalTime = n;
  87. GM.setValue(key1, n);
  88. });
  89. intervalTime = await GM.getValue(key1, intervalTime);
  90. const key2 = 'URL';
  91. GM.registerMenuCommand('config URL', async () => {
  92. const res = await addInput(await GM.getValue(key2, urls.join('\n')));
  93. if(!res) return;
  94. const a = findURL(res);
  95. if(!a.length) return;
  96. urls = a;
  97. GM.setValue(key2, a.join('\n'));
  98. });
  99. urls = (await GM.getValue(key2, urls.join('\n'))).split('\n');
  100. const findURL = str => {
  101. const m = str.match(/(https?|ftp)(:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:\@&=+\$,%#]+)/g);
  102. return m ? m : [];
  103. };
  104. const memo = new Map;
  105. const get = async url => {
  106. if(memo.has(url)) return memo.get(url);
  107. const res = await GM.xmlHttpRequest({
  108. method: 'GET',
  109. url: url,
  110. withCredentials: true,
  111. responseType: 'arraybuffer',
  112. });
  113. const _url = URL.createObjectURL(new Blob([res.response], {type: 'application/octet-binary'}));
  114. memo.set(url, _url);
  115. return _url;
  116. };
  117. let g_url = await get(urls[0]);
  118. const wait = resolve => {
  119. if(document.querySelector('[class^="chatContent"]')) return resolve();
  120. setTimeout(() => wait(resolve), 500);
  121. };
  122. await new Promise(resolve => wait(resolve));
  123. const setURL = () => {
  124. Object.assign(document.body.children[0].style, {
  125. 'background-image': 'url("' + g_url + '")',
  126. 'background-attachment': 'fixed',
  127. 'background-position': 'center center',
  128. 'background-size': 'cover',
  129. 'background-repeat': 'no-repeat',
  130. 'transition-duration': '1.5s'
  131. });
  132. };
  133. setURL();
  134. const setOther = () => {
  135. for(const v of document.querySelectorAll('*')) v.style.backgroundColor = 'rgba(0, 0, 0, 0)';
  136. document.body.children[0].children[3].style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
  137. };
  138. setOther();
  139. let _url = location.href,
  140. _time = 0,
  141. index = 0;
  142. const update = async () => {
  143. const time = performance.now();
  144. if(time - _time > intervalTime) {
  145. g_url = await get(urls[(++index) % urls.length]);
  146. _time = performance.now();
  147. setURL();
  148. }
  149. else {
  150. const url = location.href;
  151. if(url !== _url) {
  152. _url = url;
  153. setOther();
  154. }
  155. }
  156. requestAnimationFrame(update);
  157. };
  158. update();
  159. })(window.unsafeWindow || window);