1/** 2 * Swap decoy Discord invite links (in HTML for scrapers) to the live community invite. 3 * Decoy code: document.documentElement[data-discord-decoy] 4 * Live code: only in this file (never emitted from PHP/HTML). 5 */ 6(function (global) { 7 'use strict'; 8 9 var LIVE_INVITE_CODE = '7qVBUTebX7'; 10 var LIVE_INVITE_URL = 'https://discord.gg/' + LIVE_INVITE_CODE; 11 var LINK_SELECTOR = 'a.discord-invite[href]'; 12 var ACTIVATED_ATTR = 'data-discord-invite-live'; 13 14 var decoyCodeCache = null; 15 16 function readDecoyCode() { 17 if (decoyCodeCache !== null) { 18 return decoyCodeCache; 19 } 20 var fromDom = document.documentElement.getAttribute('data-discord-decoy'); 21 if (typeof fromDom === 'string' && /^[A-Za-z0-9]+$/.test(fromDom)) { 22 decoyCodeCache = fromDom; 23 return decoyCodeCache; 24 } 25 decoyCodeCache = 'YdMes7g6'; 26 return decoyCodeCache; 27 } 28 29 function discordInviteSlug(href) { 30 try { 31 var url = new URL(href, document.baseURI || global.location.href); 32 var host = url.hostname.toLowerCase(); 33 if (host !== 'discord.gg' && host !== 'www.discord.gg' && host !== 'discord.com' && host !== 'www.discord.com') { 34 return null; 35 } 36 var slug = url.pathname.replace(/^\/+/, '').split('/')[0]; 37 return slug || null; 38 } catch (err) { 39 return null; 40 } 41 } 42 43 function isDecoyInviteLink(anchor) { 44 if (!(anchor instanceof HTMLAnchorElement)) { 45 return false; 46 } 47 if (anchor.hasAttribute(ACTIVATED_ATTR)) { 48 return false; 49 } 50 var slug = discordInviteSlug(anchor.getAttribute('href') || ''); 51 return slug !== null && slug === readDecoyCode(); 52 } 53 54 function activateInviteLink(anchor) { 55 anchor.href = LIVE_INVITE_URL; 56 anchor.setAttribute(ACTIVATED_ATTR, '1'); 57 } 58 59 function applyDiscordInvites(root) { 60 var scope = root && typeof root.querySelectorAll === 'function' ? root : document; 61 scope.querySelectorAll(LINK_SELECTOR).forEach(function (anchor) { 62 if (isDecoyInviteLink(anchor)) { 63 activateInviteLink(anchor); 64 } 65 }); 66 } 67 68 function observeDom() { 69 if (typeof MutationObserver !== 'function' || !document.documentElement) { 70 return; 71 } 72 73 var pending = false; 74 75 var flush = function () { 76 pending = false; 77 applyDiscordInvites(document); 78 }; 79 80 var schedule = function () { 81 if (pending) { 82 return; 83 } 84 pending = true; 85 if (typeof requestAnimationFrame === 'function') { 86 requestAnimationFrame(flush); 87 } else { 88 setTimeout(flush, 0); 89 } 90 }; 91 92 new MutationObserver(schedule).observe(document.documentElement, { 93 childList: true, 94 subtree: true, 95 }); 96 } 97 98 function init() { 99 applyDiscordInvites(document); 100 observeDom(); 101 } 102 103 global.applyDiscordInvites = applyDiscordInvites; 104 105 if (document.readyState === 'loading') { 106 document.addEventListener('DOMContentLoaded', init); 107 } else { 108 init(); 109 } 110})(typeof window !== 'undefined' ? window : globalThis);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.