module.exports = (Plugin, Api, Vendor) => { if (!global.BDFDB || typeof BDFDB != "object") global.BDFDB = {myPlugins:{}, BDv2Api: Api}; return class extends Plugin { initConstructor () { this.patchModules = { "Channels":["componentDidMount","componentDidUpdate"], "ChannelItem":"componentDidMount", "ChannelCategoryItem":"componentDidMount" }; this.categoryMarkup = `
hidden
`; this.channelTextMarkup = `
`; this.channelVoiceMarkup = `
`; this.channelCategoryMarkup = `
`; this.css = ` .container-hidden .containerDefault-1ZnADq .iconTransition-2pOJ7l { position: static; }`; this.defaults = { settings: { showText: {value:true, description:"Show hidden Textchannels:"}, showVoice: {value:true, description:"Show hidden Voicechannels:"}, showCategory: {value:false, description:"Show hidden Categories:"}, showAllowedRoles: {value:true, description:"Show allowed Roles on hover:"}, showAllowedUsers: {value:true, description:"Show specifically allowed Users on hover:"}, showOverWrittenRoles: {value:true, description:"Include overwritten Roles in allowed Roles:"}, showDeniedRoles: {value:true, description:"Show denied Roles on hover:"}, showDeniedUsers: {value:true, description:"Show denied Users on hover:"}, showForNormal: {value:false, description:"Also show Roles/Users for allowed channels:"}, showTopic: {value:false, description:"Show the topic of hidden channels:"} }, amounts: { hoverDelay: {value:0, description:"Tooltip delay in millisec:"} } }; } onStart () { if (global.BDFDB && global.BDFDB.myPlugins && typeof global.BDFDB.myPlugins == "object") global.BDFDB.myPlugins[this.name] = this; var libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]'); if (!libraryScript || performance.now() - libraryScript.getAttribute("date") > 600000) { if (libraryScript) libraryScript.remove(); libraryScript = document.createElement("script"); libraryScript.setAttribute("type", "text/javascript"); libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"); libraryScript.setAttribute("date", performance.now()); libraryScript.addEventListener("load", () => {if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize();}); document.head.appendChild(libraryScript); } else if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) this.initialize(); this.startTimeout = setTimeout(() => {this.initialize();}, 30000); } initialize () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { if (this.started) return true; BDFDB.loadMessage(this); this.React = BDFDB.WebModules.findByProperties("createElement", "cloneElement"); this.ChannelTypes = BDFDB.WebModules.findByProperties("ChannelTypes").ChannelTypes; this.UserStore = BDFDB.WebModules.findByProperties("getUsers", "getUser"); this.MemberStore = BDFDB.WebModules.findByProperties("getMember", "getMembers"); this.GuildStore = BDFDB.WebModules.findByProperties("getGuilds", "getGuild"); this.ChannelStore = BDFDB.WebModules.findByProperties("getChannels", "getDMFromUserId"); this.GuildChannels = BDFDB.WebModules.findByProperties("getChannels", "getDefaultChannel"); this.Permissions = BDFDB.WebModules.findByProperties("Permissions", "ActivityTypes").Permissions; BDFDB.WebModules.forceAllUpdates(this, "Channels"); return true; } else { console.error(`%c[${this.name}]%c`, 'color: #3a71c1; font-weight: 700;', '', 'Fatal Error: Could not load BD functions!'); return false; } } onStop () { if (global.BDFDB && typeof BDFDB === "object" && BDFDB.loaded) { BDFDB.removeEles(".container-hidden"); BDFDB.unloadMessage(this); return true; } else { return false; } } // begin of own functions processChannels (instance, wrapper, methodnames) { if (instance.props && instance.props.guild) { if (methodnames.includes("componentDidMount")) this.appendHiddenContainer(instance.props.guild); if (methodnames.includes("componentDidUpdate")) this.reappendHiddenContainer(instance.props.guild); } } processChannelItem (instance, wrapper) { if (instance.props && instance.props.channel) this.reappendHiddenContainer(this.GuildStore.getGuild(instance.props.channel.guild_id)); } processChannelCategoryItem (instance, wrapper) { if (instance.props && instance.props.channel) this.reappendHiddenContainer(this.GuildStore.getGuild(instance.props.channel.guild_id)); } appendHiddenContainer (guild) { BDFDB.removeEles(".container-hidden"); if (!guild) return; this.currentGuild = guild.id; var allChannels = this.ChannelStore.getChannels(); var shownChannels = this.GuildChannels.getChannels(guild.id); var hiddenChannels = {}; for (let type in this.ChannelTypes) hiddenChannels[this.ChannelTypes[type]] = []; for (let channel_id in allChannels) { var channel = allChannels[channel_id]; if (channel.guild_id == guild.id) { var isHidden = true; if (channel.type == this.ChannelTypes.GUILD_CATEGORY) { for (let type in this.ChannelTypes) if (shownChannels[this.ChannelTypes[type]]) for (let shownChannel of shownChannels[this.ChannelTypes[type]]) { if (!channel.id || shownChannel.channel.parent_id == channel.id) { isHidden = false; break; } } } else { for (let shownChannel of shownChannels[channel.type]) if (shownChannel.channel.id == channel.id) { isHidden = false; break; } } if (isHidden) hiddenChannels[channel.type].push(channel); } } var settings = BDFDB.getAllData(this, "settings"); var count = 0; for (let type in this.ChannelTypes) { if (!settings.showText && type == "GUILD_TEXT" || !settings.showVoice && type == "GUILD_VOICE" || !settings.showCategory && type == "GUILD_CATEGORY") { hiddenChannels[this.ChannelTypes[type]] = []; } BDFDB.sortArrayByKey(hiddenChannels[this.ChannelTypes[type]], "name"); count += hiddenChannels[this.ChannelTypes[type]].length; } hiddenChannels.count = count; if (count > 0) { var category = BDFDB.htmlToElement(this.categoryMarkup); var wrapper = category.querySelector(BDFDB.dotCN.cursorpointer); var svg = category.querySelector(BDFDB.dotCN.categoryicontransition); var name = category.querySelector(BDFDB.dotCN.categorycolortransition); var inner = category.querySelector(BDFDB.dotCN.categorycontainerdefault + " > " + BDFDB.dotCN.flex); category.setAttribute("guild", guild.id); inner.addEventListener("click", () => { BDFDB.toggleClass(wrapper, BDFDB.disCN.categorywrapperhovered, BDFDB.disCN.categorywrapperhoveredcollapsed); BDFDB.toggleClass(svg, BDFDB.disCN.categoryiconhovered, BDFDB.disCN.categoryiconhoveredcollapsed, BDFDB.disCN.directionright); BDFDB.toggleClass(name, BDFDB.disCN.categorynamehovered, BDFDB.disCN.categorynamehoveredcollapsed); var visible = BDFDB.containsClass(svg, BDFDB.disCN.directionright); BDFDB.toggleEles(category.querySelectorAll(BDFDB.dotCN.channelcontainerdefault), !visible); BDFDB.saveData(guild.id, !visible, this, "categorystatus"); }); var togglecontainer = () => { if (!BDFDB.containsClass(svg, BDFDB.disCN.directionright)) { BDFDB.toggleClass(wrapper, BDFDB.disCN.categorywrapperdefault, BDFDB.disCN.categorywrapperhovered); BDFDB.toggleClass(svg, BDFDB.disCN.categoryicondefault, BDFDB.disCN.categoryiconhovered); BDFDB.toggleClass(name, BDFDB.disCN.categorynamedefault,BDFDB.disCN.categorynamehovered); } else { BDFDB.toggleClass(wrapper, BDFDB.disCN.categorywrappercollapsed, BDFDB.disCN.categorywrapperhoveredcollapsed) BDFDB.toggleClass(svg, BDFDB.disCN.categoryiconcollapsed, BDFDB.disCN.categoryiconhoveredcollapsed); BDFDB.toggleClass(name, BDFDB.disCN.categorynamecollapsed, BDFDB.disCN.categorynamehoveredcollapsed) } }; inner.addEventListener("mouseenter", togglecontainer); inner.addEventListener("mouseleave", togglecontainer); for (let hiddenChannel of hiddenChannels[0]) { let channel = BDFDB.htmlToElement(this.channelTextMarkup); let channelwrapper = channel.querySelector(BDFDB.dotCN.channelwrapper); let channelicon = channel.querySelector(BDFDB.dotCN.channelcontent); let channelsvg = channel.querySelector(BDFDB.dotCN.channelicon); let channelname = channel.querySelector(BDFDB.dotCN.channelname); this.setReactInstanceOfChannel(hiddenChannel, channel); channelname.innerText = hiddenChannel.name; BDFDB.addChildEventListener(channel, "mouseenter mouseleave", BDFDB.dotCN.channelwrapper, e => { BDFDB.toggleClass(channelwrapper, BDFDB.disCN.channelwrapperdefaulttext, BDFDB.disCN.channelwrapperhoveredtext); BDFDB.toggleClass(channelicon, BDFDB.disCN.channelcontentdefaulttext, BDFDB.disCN.channelcontenthoveredtext); BDFDB.toggleClass(channelsvg, BDFDB.disCN.channelcolordefaulttext, BDFDB.disCN.channelcolorhoveredtext); BDFDB.toggleClass(channelname, BDFDB.disCN.channelnamedefaulttext, BDFDB.disCN.channelnamehoveredtext); this.showAccessRoles(guild, hiddenChannel, e, false); }); channel.addEventListener("click", () => { BDFDB.showToast(`You can not enter the hidden textchannel ${hiddenChannel.name}.`, {type:"error"}); }); channel.addEventListener("contextmenu", e => { this.createHiddenObjContextMenu(guild, hiddenChannel, "TEXT", e); }); category.appendChild(channel); } for (let hiddenChannel of hiddenChannels[2]) { let channel = BDFDB.htmlToElement(this.channelVoiceMarkup); let channelwrapper = channel.querySelector(BDFDB.dotCN.channelwrapper); let channelicon = channel.querySelector(BDFDB.dotCN.channelcontent); let channelsvg = channel.querySelector(BDFDB.dotCN.channelicon); let channelname = channel.querySelector(BDFDB.dotCN.channelname); this.setReactInstanceOfChannel(hiddenChannel, channel); channelname.innerText = hiddenChannel.name; BDFDB.addChildEventListener(channel, "mouseenter mouseleave", BDFDB.dotCN.channelwrapper, e => { BDFDB.toggleClass(channelwrapper, BDFDB.disCN.channelwrapperdefaultvoice, BDFDB.disCN.channelwrapperhoveredvoice); BDFDB.toggleClass(channelicon, BDFDB.disCN.channelcontentdefaultvoice, BDFDB.disCN.channelcontenthoveredvoice); BDFDB.toggleClass(channelsvg, BDFDB.disCN.channelcolordefaultvoice, BDFDB.disCN.channelcolorhoveredvoice); BDFDB.toggleClass(channelname, BDFDB.disCN.channelnamedefaultvoice, BDFDB.disCN.channelnamehoveredvoice); this.showAccessRoles(guild, hiddenChannel, e, false); }); channel.addEventListener("click", () => { BDFDB.showToast(`You can not enter the hidden voicechannel ${hiddenChannel.name}.`, {type:"error"}); }); channel.addEventListener("contextmenu", e => { this.createHiddenObjContextMenu(guild, hiddenChannel, "VOICE", e); }); category.appendChild(channel); } for (let hiddenChannel of hiddenChannels[4]) { let channel = BDFDB.htmlToElement(this.channelCategoryMarkup); let channelwrapper = channel.querySelector(BDFDB.dotCN.categorywrappercollapsed); let channelsvg = channel.querySelector(BDFDB.dotCN.categoryiconcollapsed); let channelname = channel.querySelector(BDFDB.dotCN.categorynamecollapsed); this.setReactInstanceOfChannel(hiddenChannel, channel); channelname.innerText = hiddenChannel.name; BDFDB.addChildEventListener(channel, "mouseenter mouseleave", BDFDB.dotCN.flex, e => { BDFDB.toggleClass(channelwrapper, BDFDB.disCN.categorywrappercollapsed, BDFDB.disCN.categorywrapperhoveredcollapsed); BDFDB.toggleClass(channelsvg, BDFDB.disCN.categoryiconcollapsed, BDFDB.disCN.categoryiconhoveredcollapsed); BDFDB.toggleClass(channelname, BDFDB.disCN.categorynamecollapsed, BDFDB.disCN.categorynamehoveredcollapsed); this.showAccessRoles(guild, hiddenChannel, e, false); }); channel.addEventListener("click", () => { BDFDB.showToast(`You can not open the hidden category ${hiddenChannel.name}.`, {type:"error"}); }); channel.addEventListener("contextmenu", e => { this.createHiddenObjContextMenu(guild, hiddenChannel, "CATEGORY", e); }); category.appendChild(channel); } if (BDFDB.loadData(guild.id, this, "categorystatus") === false) { BDFDB.toggleClass(wrapper, BDFDB.disCN.categorywrapperdefault, BDFDB.disCN.categorywrappercollapsed); BDFDB.toggleClass(svg, BDFDB.disCN.categoryicondefault, BDFDB.disCN.categoryiconcollapsed, BDFDB.disCN.directionright); BDFDB.toggleClass(name, BDFDB.disCN.categorynamedefault, BDFDB.disCN.categorynamecollapsed); BDFDB.toggleEles(category.querySelectorAll(BDFDB.dotCN.channelcontainerdefault), false); } this.reappendHiddenContainer(guild, category); } let channellist = document.querySelector(BDFDB.dotCNS.channels + BDFDB.dotCN.scroller); if (channellist) { BDFDB.removeEventListener(this, channellist, "mouseenter", BDFDB.dotCNC.channelcontainerdefault + BDFDB.dotCN.categorycontainerdefault); if (settings.showForNormal) BDFDB.addEventListener(this, channellist, "mouseenter", BDFDB.dotCNC.channelcontainerdefault + BDFDB.dotCN.categorycontainerdefault, e => { if (!BDFDB.containsClass(e.currentTarget, "hidden-channel")) { var channel = BDFDB.getKeyInformation({"node":e.currentTarget,"key":"channel"}); if (channel) this.showAccessRoles(guild, channel, e, false); } }); } } reappendHiddenContainer (guild, category = document.querySelector(BDFDB.dotCNS.channels + BDFDB.dotCNS.scroller + ".container-hidden")) { if (!guild) return; if (guild.id != this.currentGuild) this.appendHiddenContainer(guild); else if (category) { var scroller = document.querySelector(BDFDB.dotCNS.channels + BDFDB.dotCN.scroller); if (!scroller || scroller.lastChild.previousSibling == category) return; category.remove(); let count = parseInt(scroller.lastChild.previousSibling.className.split("-")[1])+1; category.className = "container-" + count + " container-hidden"; scroller.insertBefore(category, scroller.lastChild); } } setReactInstanceOfChannel (guild, div) { var reactInstance = BDFDB.React.createElement(div); reactInstance.memoizedProps = {channel:guild}; div.__reactInternalInstance = reactInstance; } createHiddenObjContextMenu (guild, channel, type, e) { e.preventDefault(); e.stopPropagation(); var contextMenu = BDFDB.htmlToElement(`
${BDFDB.isPluginEnabled("PermissionsViewer") ? '
' : ''}
${BDFDB.LanguageStrings.COPY_ID}
`); var reactInstance = BDFDB.React.createElement(contextMenu); reactInstance.memoizedProps = {displayName:"ChannelDeleteGroup",guild,channel}; reactInstance.return = {memoizedProps:{type:("CHANNEL_LIST_" + type),guild,channel}}; contextMenu.__reactInternalInstance = reactInstance; BDFDB.addChildEventListener(contextMenu, "click", ".copyid-item", e2 => { contextMenu.remove(); require("electron").clipboard.write({text: channel.id}); }); BDFDB.appendContextMenu(contextMenu, e); } showAccessRoles (guild, channel, e, allowed) { if ((e.type != "mouseenter" && e.type != "mouseover") || !guild || !channel) return; var settings = BDFDB.getAllData(this, "settings"); var myMember = this.MemberStore.getMember(guild.id, BDFDB.myData.id); var allowedRoles = [], allowedUsers = [], overwrittenRoles = [], deniedRoles = [], deniedUsers = []; var everyoneDenied = false; for (let id in channel.permissionOverwrites) { if (settings.showAllowedRoles && channel.permissionOverwrites[id].type == "role" && (guild.roles[id].name != "@everyone") && (channel.permissionOverwrites[id].allow | this.Permissions.VIEW_CHANNEL) == channel.permissionOverwrites[id].allow) { if (myMember.roles.includes(id) && !allowed) { if (settings.showOverWrittenRoles) overwrittenRoles.push(guild.roles[id]); } else { allowedRoles.push(guild.roles[id]); } } else if (settings.showAllowedUsers && channel.permissionOverwrites[id].type == "member" && (channel.permissionOverwrites[id].allow | this.Permissions.VIEW_CHANNEL) == channel.permissionOverwrites[id].allow) { let user = this.UserStore.getUser(id); let member = this.MemberStore.getMember(guild.id,id); if (user && member) allowedUsers.push(Object.assign({name:user.username},member)); } if (settings.showDeniedRoles && channel.permissionOverwrites[id].type == "role" && (channel.permissionOverwrites[id].deny | this.Permissions.VIEW_CHANNEL) == channel.permissionOverwrites[id].deny) { deniedRoles.push(guild.roles[id]); if (guild.roles[id].name == "@everyone") everyoneDenied = true; } else if (settings.showDeniedUsers && channel.permissionOverwrites[id].type == "member" && (channel.permissionOverwrites[id].deny | this.Permissions.VIEW_CHANNEL) == channel.permissionOverwrites[id].deny) { let user = this.UserStore.getUser(id); let member = this.MemberStore.getMember(guild.id,id); if (user && member) deniedUsers.push(Object.assign({name:user.username},member)); } } if (settings.showAllowedRoles && allowed && !everyoneDenied) { allowedRoles.push({"name":"@everyone"}); } var htmlString = ``; if (settings.showTopic && !allowed && channel.topic && channel.topic.replace(/[\t\n\r\s]/g, "")) { htmlString += `
Topic:
${BDFDB.encodeToHTML(channel.topic)}
`; } if (allowedRoles.length > 0 || overwrittenRoles.length > 0) { htmlString += `
Allowed Roles:
`; for (let role of allowedRoles) { let color = role.colorString ? BDFDB.colorCONVERT(role.colorString, "RGBCOMP") : [255,255,255]; htmlString += `
${BDFDB.encodeToHTML(role.name)}
`; } for (let role of overwrittenRoles) { let color = role.colorString ? BDFDB.colorCONVERT(role.colorString, "RGBCOMP") : [255,255,255]; htmlString += `
${BDFDB.encodeToHTML(role.name)}
`; } htmlString += `
`; } if (allowedUsers.length > 0) { htmlString += `
Allowed Users:
`; for (let user of allowedUsers) { let color = user.colorString ? BDFDB.colorCONVERT(user.colorString, "RGBCOMP") : [255,255,255]; htmlString += `
${BDFDB.encodeToHTML(user.nick ? user.nick : user.name)}
`; } htmlString += `
`; } if (deniedRoles.length > 0) { htmlString += `
Denied Roles:
`; for (let role of deniedRoles) { let color = role.colorString ? BDFDB.colorCONVERT(role.colorString, "RGBCOMP") : [255,255,255]; htmlString += `
${BDFDB.encodeToHTML(role.name)}
`; } htmlString += `
`; } if (deniedUsers.length > 0) { htmlString += `
Denied Users:
`; for (let user of deniedUsers) { let color = user.colorString ? BDFDB.colorCONVERT(user.colorString, "RGBCOMP") : [255,255,255]; htmlString += `
${BDFDB.encodeToHTML(user.nick ? user.nick : user.name)}
`; } htmlString += `
`; } if (htmlString) { var width = window.outerWidth/2; var tooltip = BDFDB.createTooltip(htmlString, e.currentTarget, {type:"right", selector:"showhiddenchannels-tooltip", html:true, style:`max-width: ${width < 200 ? 400 : width}px !important;`, delay:BDFDB.getData("hoverDelay", this, "amounts")}); var style = getComputedStyle(e.currentTarget); tooltip.style.setProperty("top", BDFDB.getRects(tooltip).top - style.paddingBottom.replace("px","")/2 + style.paddingTop.replace("px","")/2 + "px"); } } getSettingsPanel () { if (!global.BDFDB || typeof BDFDB != "object" || !BDFDB.loaded || !this.started) return; var settings = BDFDB.getAllData(this, "settings"); var amounts = BDFDB.getAllData(this, "amounts"); var settingshtml = `
${this.name}
`; for (let key in settings) { settingshtml += `

${this.defaults.settings[key].description}

`; } for (let key in amounts) { settingshtml += `

${this.defaults.amounts[key].description}

`; } settingshtml += `
`; let settingspanel = BDFDB.htmlToElement(settingshtml); BDFDB.initElements(settingspanel, this); BDFDB.addEventListener(this, settingspanel, "input", ".amountInput", e => { var input = parseInt(e.currentTarget.value); if (!isNaN(input) && input > -1) BDFDB.saveData(e.currentTarget.getAttribute("option"), input, this, "amounts"); }); return settingspanel; } onSettingsClosed () { if (this.SettingsUpdated) { delete this.SettingsUpdated; BDFDB.WebModules.forceAllUpdates(this, "Channels"); } } } };