/*! @file soundboardPI.js @brief Contains PI for the Soundboard action @author Andrew story @copyright (c) 2023, Corsair Memory, Inc. All Rights Reserved. */ let EmojiData = null; // Helper function to return the twemoji for a given unicode emoji. Strips off codepoints until the longest prefix is found. function GetEmojiPath(emoji){ if(!emoji){ return ""; } let name = twemoji.convert.toCodePoint(emoji); let result = null; let split = name.split("-"); while(!result && split.length > 0){ result = EmojiData[split.join("-")]; if(result){ return split.join("-"); } split.pop(); } return ""; } function GetEmojiData(emoji){ if(!emoji){ return ""; } result = EmojiData[GetEmojiPath(emoji)]; return result ? result : ""; } function GetCustomEmojiLink(snowflake, size=128){ return "https://cdn.discordapp.com/emojis/" + snowflake + ".webp?size="+size+"&quality=lossless"; } function SoundboardPI(inContext, inLanguage) { // Inherit from PI PI.call(this, inContext, inLanguage); if(!EmojiData){ fetch("assets/emoji.json").then((data)=>{ data.json().then((data)=>{ EmojiData = data; const searcher = document.getElementById("searcher"); this.filterData(searcher.value); }); }); } this.labelSearchResults = "Search Results"; this.labelSearchEmpty = "No Sounds Found"; this.labelDefaultSounds = "Discord Sounds"; const GUILDID_SEARCH = "SEARCH"; const GUILDID_DEFAULT = "DEFAULT"; const NITRO_NONE = 0; const NITRO_CLASSIC = 1; const NITRO_FULL = 2; const NITRO_BASIC = 3; // Save a copy of a method var piSaveSettings = this.saveSettings; let sounds = []; let currentServer = ""; let premiumLevel = NITRO_NONE; // Add fields var fields =`
`; document.getElementById('placeholder').innerHTML = fields; const els = { "searcher": document.getElementById('searcher'), "body": document.getElementsByTagName("body")[0], "soundboard": document.getElementById('soundboard'), }; let selection = null; if (settings["sound_id"]){ selection = settings["sound_id"]; els.searcher.setAttribute("placeholder", settings["sound_name"]); } this.filterData = (filter)=>{ while(els.soundboard.firstChild){ els.soundboard.removeChild(els.soundboard.firstChild); } const orderedGuilds = []; let dataCount = 0; const dataByGuild = {} if (!filter){ if(sounds){ for( const d of sounds){ let guild_id = d.guild_id; if (!dataByGuild[guild_id]){ dataByGuild[guild_id] = []; } dataByGuild[guild_id].push(d); dataCount ++; } } if(currentServer){ orderedGuilds.push(currentServer); } if(premiumLevel != NITRO_FULL ){ orderedGuilds.push(GUILDID_DEFAULT); } const guilds = []; for(const gid in dataByGuild){ if( currentServer != gid && GUILDID_DEFAULT != gid){ guilds.push(gid); } } guilds.sort((lhs,rhs)=>{ let a = dataByGuild[lhs]; let b = dataByGuild[rhs]; let nameA = ""; let nameB = ""; if( a && a[0] && a[0].guild_name && a[0].guild_name.toLowerCase ){ nameA = a[0].guild_name.toLowerCase(); } if( b && b[0] && b[0].guild_name && b[0].guild_name.toLowerCase ){ nameB = b[0].guild_name.toLowerCase(); } return nameA.localeCompare(nameB); }); orderedGuilds.push(...guilds); if(premiumLevel == NITRO_FULL ){ orderedGuilds.push(GUILDID_DEFAULT); } } else { orderedGuilds.push(GUILDID_SEARCH); const results = fuzzysort.go(filter, sounds, { keys:["name", "guild_name"], all: true }); const trimmed = []; for(const sound of results){ trimmed.push(sound.obj); } dataByGuild[GUILDID_SEARCH] = trimmed; dataCount = trimmed.length; } if(dataCount == 0 ){ const labelRow = document.createElement("tr"); labelRow.className = "sb-label"; const labelData = document.createElement("td"); labelData.textContent = this.labelSearchEmpty; labelData.colSpan = 2; els.soundboard.appendChild(labelRow); labelRow.appendChild(labelData); return; } for(const gid of orderedGuilds){ const g = dataByGuild[gid]; if(!g){ continue; } if(g.length && g.length > 0){ const labelRow = document.createElement("tr"); labelRow.className = "sb-label"; const labelData = document.createElement("td"); if(gid == GUILDID_SEARCH){ labelData.textContent = this.labelSearchResults; } else if(gid == GUILDID_DEFAULT){ labelData.textContent = this.labelDefaultSounds; } else { labelData.textContent = g[0].guild_name; } labelData.colSpan = 2; els.soundboard.appendChild(labelRow); labelRow.appendChild(labelData); let offset = 0; let currentRow = document.createElement("tr"); for(const sound of g){ const currentData = document.createElement("td"); currentData.className = "interactive"; currentData.id = "sound_id-" + sound.sound_id; if( sound.sound_id == selection){ currentData.classList.add("picked"); } const span = document.createElement("span"); const txt = document.createTextNode(sound.name); span.className = "soundboard-item"; currentData.addEventListener("click", ()=>{ if(selection){ const other = document.getElementById("sound_id-" + selection); if (other){ other.classList.remove("picked"); } } selection = sound.sound_id; document.getElementById("sound_id-" + selection).classList.add("picked"); els.searcher.setAttribute("placeholder", sound.name); els.searcher.value = ""; settings['sound_id'] = sound.sound_id; settings['guild_id'] = sound.guild_id; settings['sound_name'] = sound.name; if(!sound.emoji_id){ settings['emoji_path'] = GetEmojiPath(sound.emoji_name); } else { settings['emoji_path'] = GetCustomEmojiLink(sound.emoji_id, 128); } piSaveSettings(); this.filterData(); }) if(!sound.emoji_id){ if(EmojiData){ if (sound.emoji_name){ const filename = GetEmojiData(sound.emoji_name); const img = document.createElement("img"); img.className = "sb-img"; img.src = filename; span.appendChild(img); } span.appendChild(txt); currentData.appendChild(span); } } else { const img = document.createElement("img"); img.className = "sb-img"; img.src = GetCustomEmojiLink(sound.emoji_id, 24); span.appendChild(img); span.appendChild(txt); currentData.appendChild(span); } currentRow.appendChild(currentData); if( ++offset == 2){ els.soundboard.appendChild(currentRow); currentRow = document.createElement("tr"); offset = 0; } } if(offset > 0){ while(offset++ < 2){ const currentData = document.createElement("td"); currentData.className = "dummy"; const span = document.createElement("span"); currentData.appendChild(span); currentRow.appendChild(currentData); } els.soundboard.appendChild(currentRow); currentRow = document.createElement("tr"); } } } } this.filterData(); els.body.addEventListener("keydown", ()=>{ if(document.activeElement != els.searcher){ els.searcher.focus(); } }); els.searcher.addEventListener("input", (e)=>{ const searcher = els.searcher; this.filterData(searcher.value); }); // Before overwriting parrent method, save a copy of it var piLoad = this.load; // Public function called to load the fields this.load = function (data) { // Call PI load method piLoad.call(this, data); // If action enabled if (!data.disabled && !data.unauthorized) { sounds = data["sounds"]; for(const sound of sounds){ if(sound.guild_id == GUILDID_DEFAULT){ sound.guild_name = this.labelDefaultSounds + " default"; } } premiumLevel = data["premiumLevel"]; currentServer = data["serverId"]; this.filterData(els.searcher.value); } // Enable / Disable the fields els.searcher.disabled = data.disabled || data.unauthorized; if(data.disabled || data.unauthorized){ sounds = []; this.filterData(); } // Show PI document.getElementById('pi').style.display = "block"; } /* --- Localization --- */ // Before overwriting parent method, save a copy of it var piLocalize = this.localize; // Localize the UI this.localize = function (tr) { // Call PIs localize method piLocalize.call(this, tr); // Capture default labels this.labelSearchResults = tr("SoundboardSearch"); this.labelSearchEmpty = tr("SoundboardSearchEmpty"); this.labelDefaultSounds = tr("SoundboardDefaults"); }; }