delete git history

This commit is contained in:
Mirco Wittrien 2018-10-11 10:21:26 +02:00
commit 8759922bdc
235 changed files with 5020146 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
MessageLogger/

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,286 @@
//META{"name":"BadgesEverywhere"}*//
class BadgesEverywhere {
initConstructor () {
this.css = `
.BE-badge {
display: inline-block;
background-position: 50%;
background-repeat: no-repeat;
background-size: cover;
height: 17px;
margin: 0 2px;
}
.BE-badge-chat {
margin-bottom: -3px;
}
.BE-badge-popout {
margin-bottom: -2px;
}
.BE-badge:first-of-type {
margin-left: 5px;
}
.BE-badge:last-of-type {
margin-right: 5px;
}
.BE-badge-Staff {width:17px;min-width:17px;}
.BE-badge-Partner {width:22px;min-width:22px;}
.BE-badge-HypeSquad {width:17px;min-width:17px;}
.BE-badge-BugHunter {width:17px;min-width:17px;}
.BE-badge-HypeSquadBravery {width:17px;min-width:17px;}
.BE-badge-HypeSquadBrilliance {width:17px;min-width:17px;}
.BE-badge-HypeSquadBalance {width:17px;min-width:17px;}
.BE-badge-Nitro {width:21px;min-width:21px;}`;
this.loading = false;
this.updateBadges = false;
this.badges = {
1: {name:"Staff", implemented:true, white:"url(https://discordapp.com/assets/7cfd90c8062139e4804a1fa59f564731.svg)", color:"url(https://discordapp.com/assets/4358ad1fb423b346324516453750f569.svg)"},
2: {name:"Partner", implemented:true, white:"url(https://discordapp.com/assets/a0e288a458c48dfcf548dadc277e42e6.svg)", color:"url(https://discordapp.com/assets/33fedf082addb91d88abc272b4b18daa.svg)"},
4: {name:"HypeSquad", implemented:true, white:"url(https://discordapp.com/assets/3a050fcc884255231b99b7033c776070.svg)", color:"url(https://discordapp.com/assets/6c73f47daf179ffade99f501bfc5101b.svg)"},
8: {name:"BugHunter", implemented:true, white:"url(https://discordapp.com/assets/df26f079738a4dcd07cbce6eb3c957f1.svg)", color:"url(https://discordapp.com/assets/f61b8981e92feead854f52e5a1ba14f0.svg)"},
16: {name:"MFASMS", implemented:false, white:"", color:""},
32: {name:"PROMODISMISSED", implemented:false, white:"", color:""},
64: {name:"HypeSquad Bravery", implemented:true, white:"url(https://discordapp.com/assets/1115767aed344e96a27a12e97718c171.svg)", color:"url(https://discordapp.com/assets/64ae1208b6aefc0a0c3681e6be36f0ff.svg)"},
128: {name:"HypeSquad Brilliance", implemented:true, white:"url(https://discordapp.com/assets/48cf0556d93901c8cb16317be2436523.svg)", color:"url(https://discordapp.com/assets/48cf0556d93901c8cb16317be2436523.svg)"},
256: {name:"HypeSquad Balance", implemented:true, white:"url(https://discordapp.com/assets/2a085ed9c86f3613935a6a8667ba8b89.svg)", color:"url(https://discordapp.com/assets/9fdc63ef8a3cc1617c7586286c34e4f1.svg)"},
2048: {name:"Nitro", implemented:true, white:"url(https://discordapp.com/assets/379d2b3171722ef8be494231234da5d1.svg)", color:"url(https://discordapp.com/assets/386884eecd36164487505ddfbac35a9d.svg)"}
};
this.requestedusers = {};
this.loadedusers = {};
this.defaults = {
settings: {
showInChat: {value:true, description:"Show Badge in Chat Window."},
showInMemberList: {value:true, description:"Show Badge in Member List."},
showInPopout: {value:true, description:"Show Badge in User Popout."},
useColoredVersion: {value:true, description:"Use colored version of the Badges."}
}
};
}
getName () {return "BadgesEverywhere";}
getDescription () {return "Displays Badges (Nitro, HypeSquad, etc...) in the chat/memberlist/userpopout. Thanks for Zerebos' help.";}
getVersion () {return "1.0.9";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UserModalUtils = BDFDB.WebModules.findByProperties(["fetchMutualFriends","open"]);
this.APIModule = BDFDB.WebModules.findByProperties(["getAPIBaseURL"]);
this.DiscordConstants = BDFDB.WebModules.findByProperties(["Permissions", "ActivityTypes", "StatusTypes"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.tagName && node.querySelector(BDFDB.dotCN.memberusername) && BDFDB.getData("showInMemberList", this, "settings")) {
this.addBadges(node, "list", false);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.memberswrap, {name:"userListObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (BDFDB.getData("showInChat", this, "settings")) {
if (node.tagName && node.querySelector(BDFDB.dotCN.messageusername)) {
this.addBadges(node, "chat", BDFDB.getDiscordMode() == "compact");
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.userpopout) && BDFDB.getData("showInPopout", this, "settings")) {
this.addBadges(node, "popout", false);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"userPopoutObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings" && this.updateBadges) {
this.updateBadges = false;
this.loadBadges();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
for (let flag in this.badges) {
if (!this.badges[flag].implemented) delete this.badges[flag];
}
this.loadBadges();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".BE-badge").forEach(node=>{node.remove();});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
BDFDB.addObserver(this, BDFDB.dotCN.memberswrap, {name:"userListObserver"}, {childList:true, subtree:true});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
this.loadBadges();
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
this.updateBadges = true;
}
loadBadges() {
document.querySelectorAll(".BE-badge").forEach(node=>{node.remove();});
var settings = BDFDB.getAllData(this, "settings");
if (settings.showInMemberList) {
for (let user of document.querySelectorAll(BDFDB.dotCN.member)) {
this.addBadges(user, "list", false, settings);
}
}
if (settings.showInChat) {
for (let messagegroup of document.querySelectorAll(BDFDB.dotCN.messagegroupcozy)) {
this.addBadges(messagegroup, "chat", false, settings);
}
for (let messagegroup of document.querySelectorAll(BDFDB.dotCN.messagegroupcompact)) {
for (let message of messagegroup.querySelectorAll(BDFDB.dotCN.messagemarkup)) {
this.addBadges(message, "chat", true, settings);
}
}
}
if (settings.showInPopout) {
for (let user of document.querySelectorAll(BDFDB.dotCN.userpopout)) {
this.addBadges(user.parentElement, "popout", false, settings);
}
}
}
addBadges (wrapper, type, compact, settings = BDFDB.getAllData(this, "settings")) {
if (!wrapper) return;
let user = compact ? BDFDB.getKeyInformation({"node":wrapper.classList.contains(BDFDB.disCN.messagegroup) ? wrapper : $(BDFDB.dotCN.messagegroup).has(wrapper)[0],"key":"message"}).author : BDFDB.getKeyInformation({"node":wrapper,"key":"user"});
if (user && !user.bot) {
if (!this.requestedusers[user.id]) {
this.requestedusers[user.id] = [[wrapper,type]]
this.APIModule.get(this.DiscordConstants.Endpoints.USER_PROFILE(user.id)).then(result => {
let usercopy = Object.assign({},result.body.user);
if (result.body.premium_since) usercopy.flags += 2048;
this.loadedusers[user.id] = usercopy;
for (let queredobj of this.requestedusers[user.id]) this.addToWrapper(queredobj[0], user.id, queredobj[1], settings);
});
}
else if (!this.loadedusers[user.id]) {
this.requestedusers[user.id].push([wrapper,type]);
}
else {
this.addToWrapper(wrapper, user.id, type, settings);
}
}
}
addToWrapper (wrapper, id, type, settings) {
if (wrapper.querySelector(".BE-badge")) return;
let memberwrap = wrapper.querySelector(BDFDB.dotCN.memberusername);
if (!memberwrap) memberwrap = wrapper.querySelector(BDFDB.dotCN.messageusername);
if (memberwrap) memberwrap = memberwrap.parentElement;
if (!memberwrap) memberwrap = wrapper.querySelector(BDFDB.dotCN.nametag);
if (memberwrap) for (let flag in this.badges) {
if ((this.loadedusers[id].flags | flag) == this.loadedusers[id].flags) {
let badge = document.createElement("div");
badge.className = "BE-badge BE-badge-" + this.badges[flag].name.replace(/ /g, "") + " BE-badge-" + type;
badge.style.backgroundImage = settings.useColoredVersion ? this.badges[flag].color : this.badges[flag].white;
memberwrap.appendChild(badge);
$(badge)
.on("mouseenter." + this.getName(), (e) => {
BDFDB.createTooltip(this.badges[flag].name, e.currentTarget, {"type":type == "list" ? "left" : "top"});
});
}
}
}
}

View File

@ -0,0 +1,3 @@
# Badges Everywhere - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BadgesEverywhere/BadgesEverywhere.plugin.js)
Displays Badges (Nitro, Hypesquad, etc...) in the chat/memberlist/userpopout. Thanks for Zerebos' help.

View File

@ -0,0 +1,126 @@
//META{"name":"BetterFriendCount"}*//
class BetterFriendCount {
initConstructor () {
this.css = `
${BDFDB.idCNS.friends + BDFDB.dotCNS.friendstabbaritem + BDFDB.dotCN.badge}:not(.betterfriendcount-badge),
${BDFDB.idCNS.friends + BDFDB.dotCNS.friendstabbaritem + BDFDB.dotCN.badgewrapper}:not(.betterfriendcount-badge) {
display: none !important;
}
${BDFDB.idCNS.friends + BDFDB.dotCNS.friendstabbaritem + BDFDB.dotCN.badgewrapper}.betterfriendcount-badge {
margin-left: 5px !important;
}
`;
this.relationshipTypes = {};
}
getName () {return "BetterFriendCount";}
getDescription () {return "Shows the amount of total and online friends and blocked users in the friends tab.";}
getVersion () {return "1.0.7";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.friendscolumn)) {
this.addCountNumbers();
}
});
}
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.friendscolumn)) {
this.addCountNumbers();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.idCN.friends, {name:"friendListObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
this.addCountNumbers();
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.friendsonline, {name:"friendCountObserver",instance:observer}, {childList:true, subtree:true, characterData:true});
this.FriendUtils = BDFDB.WebModules.findByProperties(["getFriendIDs", "getRelationships"]);
this.UserMetaStore = BDFDB.WebModules.findByProperties(["getStatus", "getOnlineFriendCount"]);
var RelationshipTypes = BDFDB.WebModules.findByProperties(["RelationshipTypes"]).RelationshipTypes;
for (let type in RelationshipTypes) {
this.relationshipTypes[RelationshipTypes[type]] = type;
}
this.addCountNumbers();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".betterfriendcount-badge").forEach(counter => {counter.remove();});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
this.addCountNumbers();
BDFDB.addObserver(this, BDFDB.idCN.friends, {name:"friendListObserver"}, {childList:true, subtree:true});
}
// begin of own functions
addCountNumbers () {
var friendstabbar = document.querySelector(BDFDB.idCNS.friends + BDFDB.dotCN.friendstabbar);
if (!friendstabbar) return;
friendstabbar.querySelectorAll(".betterfriendcount-badge").forEach(counter => {counter.remove();});
var relationships = this.FriendUtils.getRelationships(), relationshipCount = {};
for (let type in this.relationshipTypes) {relationshipCount[this.relationshipTypes[type]] = 0;}
for (let id in relationships) {relationshipCount[this.relationshipTypes[relationships[id]]]++;}
var tabitems = friendstabbar.querySelectorAll(BDFDB.dotCN.friendstabbaritem);
$(`<div class="${BDFDB.disCN.badgewrapper} betterfriendcount-badge friendcount">${relationshipCount.FRIEND}</div>`).appendTo(tabitems[1]);
$(`<div class="${BDFDB.disCN.badgewrapper} betterfriendcount-badge onlinefriendcount">${this.UserMetaStore.getOnlineFriendCount()}</div>`).appendTo(tabitems[2]);
$(`<div class="${BDFDB.disCN.badgewrapper} betterfriendcount-badge requestincount">${relationshipCount.PENDING_INCOMING}</div>`).appendTo(tabitems[3]);
$(`<div class="${BDFDB.disCN.badgewrapper} betterfriendcount-badge requestoutcount">${relationshipCount.PENDING_OUTGOING}</div>`).appendTo(tabitems[3]);
$(`<div class="${BDFDB.disCN.badgewrapper} betterfriendcount-badge blockedcount">${relationshipCount.BLOCKED}</div>`).appendTo(tabitems[4]);
}
}

View File

@ -0,0 +1,3 @@
# Better Friend Count - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterFriendCount/BetterFriendCount.plugin.js)
Shows the amount of total and online friends and blocked users in the friends tab.

View File

@ -0,0 +1,121 @@
//META{"name":"BetterNsfwTag"}*//
class BetterNsfwTag {
initConstructor () {
this.css = `
.nsfw-tag {
position: relative;
overflow: hidden;
padding: 1px 2px 1px 2px;
margin-left: 5px;
height: 13px;
border-radius: 3px;
text-transform: uppercase;
font-size: 12px;
font-weight: 500;
line-height: 14px;
white-space: nowrap;
color: rgb(240, 71, 71);
background-color: rgba(240, 71, 71, 0.0980392);
border: 1px solid rgba(240, 71, 71, 0.498039);
}`;
this.tagMarkup = `<span class="nsfw-tag">NSFW</span>`;
}
getName () {return "BetterNsfwTag";}
getDescription () {return "Adds a more noticeable tag to NSFW channels.";}
getVersion () {return "1.1.5";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.classList && node.classList.contains(BDFDB.disCN.channelcontainerdefault)) {
this.checkChannel(node);
}
if (node && node.className && node.className.length > 0 && node.className.indexOf("container-") > -1) {
this.checkContainerForNsfwChannel(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.channels, {name:"channelListObserver",instance:observer}, {childList: true, subtree: true});
this.checkAllContainers();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(".nsfw-tag").remove();
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.checkAllContainers();
}
}
// begin of own functions
checkAllContainers () {
document.querySelectorAll(BDFDB.dotCNS.channels + "[class*=container-]").forEach(container => {
this.checkContainerForNsfwChannel(container);
});
}
checkContainerForNsfwChannel (container) {
container.querySelectorAll(BDFDB.dotCN.channelcontainerdefault).forEach(channel => {
this.checkChannel(channel);
});
}
checkChannel (channel) {
let channelData = BDFDB.getKeyInformation({"node":channel,"key":"channel"});
if (channelData && channelData.nsfw == true) {
if (!channel.querySelector(".nsfw-tag")) {
$(this.tagMarkup).appendTo(channel.querySelector(BDFDB.dotCN.channelname));
}
}
}
}

View File

@ -0,0 +1,3 @@
# Better NSFW Tag - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterNsfwTag/BetterNsfwTag.plugin.js)
Adds a more noticeable tag to NSFW channels.

View File

@ -0,0 +1,285 @@
//META{"name":"BetterSearchPage"}*//
class BetterSearchPage {
initConstructor () {
this.css = `
.BSP-pagination-button {
background: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" width="30" height="25"><g fill="#737f8d" fill-rule="evenodd" clip-rule="evenodd"><path xmlns="http://www.w3.org/2000/svg" d="M17.338 12.485c-4.156 4.156-8.312 8.312-12.468 12.467-1.402-1.402-2.805-2.804-4.207-4.206 2.756-2.757 5.513-5.514 8.27-8.27C6.176 9.72 3.419 6.963.663 4.207L4.87 0c-.058-.059 12.555 12.562 12.468 12.485z"/><path xmlns="http://www.w3.org/2000/svg" d="M17.338 12.485c-4.156 4.156-8.312 8.312-12.468 12.467-1.402-1.402-2.805-2.804-4.207-4.206 2.756-2.757 5.513-5.514 8.27-8.27C6.176 9.72 3.419 6.963.663 4.207L4.87 0c-.058-.059 12.555 12.562 12.468 12.485z" transform="translate(12 0)"/></g></svg>') 50%/9px 12px no-repeat;
border: 1px solid rgba(79,84,92,.16);
border-radius: 2px;
cursor: pointer;
height: 18px;
left: 20px;
opacity: .7;
top: 20px;
width: 18px;
}
${BDFDB.dotCN.themedark} .BSP-pagination-button {
background-image: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" width="30" height="25"><g fill="#FFF" fill-rule="evenodd" clip-rule="evenodd"><path xmlns="http://www.w3.org/2000/svg" d="M17.338 12.485c-4.156 4.156-8.312 8.312-12.468 12.467-1.402-1.402-2.805-2.804-4.207-4.206 2.756-2.757 5.513-5.514 8.27-8.27C6.176 9.72 3.419 6.963.663 4.207L4.87 0c-.058-.059 12.555 12.562 12.468 12.485z" /><path xmlns="http://www.w3.org/2000/svg" d="M17.338 12.485c-4.156 4.156-8.312 8.312-12.468 12.467-1.402-1.402-2.805-2.804-4.207-4.206 2.756-2.757 5.513-5.514 8.27-8.27C6.176 9.72 3.419 6.963.663 4.207L4.87 0c-.058-.059 12.555 12.562 12.468 12.485z" transform="translate(12 0)"/></g></svg>');
border: 1px solid hsla(0,0%,100%,.16);
}
.BSP-pagination-button.BSP-pagination-first {
-webkit-transform: rotate(180deg);
margin-right: 10px;
transform: rotate(180deg);
}
.BSP-pagination-button.BSP-pagination-last {
margin-left: 10px;
margin-right: 10px;
}
.BSP-pagination-button.BSP-pagination-jump {
margin-left: 10px;
transform: rotate(90deg);
}
.BSP-pagination-button${BDFDB.dotCN.searchresultspaginationdisabled} {
cursor: default;
opacity: .3;
}
.BSP-pagination-button:not(${BDFDB.dotCN.searchresultspaginationdisabled}):hover {
opacity: 1;
}
`;
this.defaults = {
settings: {
addFirstLast: {value:true, description:"Adds a first and last page button."},
addJumpTo: {value:true, description:"Adds a jump to input field (press enter to jump)."},
cloneToTheTop: {value:true, description:"Clones the controls to the top of the results page."}
}
};
}
getName () {return "BetterSearchPage";}
getDescription () {return "Adds some extra controls to the search results page.";}
getVersion () {return "1.0.3";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.SearchNavigation = BDFDB.WebModules.findByProperties(["searchNextPage","searchPreviousPage"]);
this.SearchUtils = BDFDB.WebModules.findByProperties(["getCurrentSearchId"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.classList.contains(BDFDB.disCN.searchresultswrap)) {
BDFDB.addObserver(this, node, {name:"searchResultsObserver"}, {childList:true, subtree:true});
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCNS.chat + BDFDB.dotCN.chatcontent, {name:"chatContentObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
let pagination = null;
if (node && node.tagName && (pagination = node.querySelector(BDFDB.dotCN.searchresultspagination)) != null) {
this.addNewControls(pagination);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCNS.searchresultswrap, {name:"searchResultsObserver",instance:observer}, {childList:true, subtree:true});
let pagination = document.querySelector(BDFDB.dotCNS.searchresultswrap + BDFDB.dotCNS.searchresultspagination);
if (pagination) this.addNewControls(pagination);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".BSP-pagination, .BSP-pagination-button, .BSP-pagination-jumpinput").forEach(ele => {ele.remove();});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
BDFDB.addObserver(this, BDFDB.dotCNS.chat + BDFDB.dotCN.chatcontent, {name:"chatContentObserver"}, {childList:true});
BDFDB.addObserver(this, BDFDB.dotCNS.searchresultswrap, {name:"searchResultsObserver"}, {childList:true, subtree:true});
let pagination = document.querySelector(BDFDB.dotCNS.searchresultswrap + BDFDB.dotCNS.searchresultspagination);
if (pagination) this.addNewControls(pagination);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
addNewControls (pagination) {
if (!pagination || document.querySelector(".BSP-pagination, .BSP-pagination-button, .BSP-pagination-jumpinput")) return;
let searchResults = document.querySelector(BDFDB.dotCN.searchresults);
let searchID = this.SearchUtils.getCurrentSearchId();
if (!searchResults || !searchID) return;
let currentpage, maxpage;
for (let word of pagination.textContent.split(" ")) {
let number = parseInt(word.replace(/\./g,""));
if (!isNaN(number) && !currentpage) {
currentpage = number;
}
else if (!isNaN(number)) {
maxpage = number;
break;
}
}
if (!currentpage || !maxpage) return;
let temppage = currentpage;
currentpage = currentpage < maxpage ? currentpage : maxpage;
maxpage = temppage < maxpage ? maxpage : temppage;
if (maxpage > 201) {
if (currentpage == 201) BDFDB.showToast("Discord doesn't allow you to go further than page 201.",{type:"error"});
maxpage = 201;
}
if (currentpage == maxpage && maxpage == 201) pagination.querySelector(BDFDB.dotCN.searchresultspaginationnext).classList.add(BDFDB.disCN.searchresultspaginationdisabled);
let settings = BDFDB.getAllData(this, "settings");
if (settings.addFirstLast) {
let BSPpaginatonFirst = document.createElement("div");
BSPpaginatonFirst.className = "BSP-pagination-button BSP-pagination-first";
if (currentpage == 1) BSPpaginatonFirst.classList.add(BDFDB.disCN.searchresultspaginationdisabled);
pagination.insertBefore(BSPpaginatonFirst, pagination.firstElementChild);
let BSPpaginatonLast = document.createElement("div");
BSPpaginatonLast.className = "BSP-pagination-button BSP-pagination-last";
if (currentpage == maxpage) BSPpaginatonLast.classList.add(BDFDB.disCN.searchresultspaginationdisabled);
pagination.appendChild(BSPpaginatonLast);
}
if (settings.addJumpTo) {
$(`<div class="inputNumberWrapper inputNumberWrapperMini BSP-pagination-jumpinput ${BDFDB.disCN.inputwrapper}"><span class="numberinput-buttons-zone"><span class="numberinput-button-up"></span><span class="numberinput-button-down"></span></span><input type="number" min="1" max="${maxpage}" placeholder="${currentpage}" value="${currentpage}" class="${BDFDB.disCNS.inputmini + BDFDB.disCNS.input + BDFDB.disCN.size16}"></div><div class="BSP-pagination-button BSP-pagination-jump"></div>`).appendTo(pagination);;
}
BDFDB.initElements(pagination);
if (settings.cloneToTheTop) {
let BSPpaginaton = pagination.cloneNode(true);
BSPpaginaton.classList.add("BSP-pagination");
searchResults.parentElement.insertBefore(BSPpaginaton, searchResults);
BDFDB.initElements(BSPpaginaton);
}
var doJump = (input) => {
let value = input.value;
if (value < 1 || value > maxpage) {
input.value = currentpage;
if (maxpage == 201 && value > maxpage) BDFDB.showToast("Discord doesn't allow you to go further than page 201.",{type:"error"});
}
else if (value < currentpage) {
for (; currentpage - value > 0; value++) {
this.SearchNavigation.searchPreviousPage(searchID);
}
}
else if (value > currentpage) {
for (; value - currentpage > 0; value--) {
this.SearchNavigation.searchNextPage(searchID);
}
}
};
$(searchResults.parentElement)
.off("click." + this.getName()).off("mouseenter." + this.getName()).off("keydown." + this.getName())
.on("click." + this.getName(), BDFDB.dotCN.searchresultspaginationprevious + BDFDB.dotCN.searchresultspaginationdisabled, (e) => {
e.preventDefault();
e.stopPropagation();
})
.on("click." + this.getName(), BDFDB.dotCN.searchresultspaginationnext + BDFDB.dotCN.searchresultspaginationdisabled, (e) => {
e.preventDefault();
e.stopPropagation();
})
.on("mouseenter." + this.getName(), BDFDB.dotCN.searchresultspaginationprevious + ":not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
BDFDB.createTooltip("Previous", e.currentTarget, {type:"top"});
})
.on("mouseenter." + this.getName(), BDFDB.dotCN.searchresultspaginationnext + ":not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
BDFDB.createTooltip("Next", e.currentTarget, {type:"top"});
})
.on("mouseenter." + this.getName(), ".BSP-pagination-first:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
BDFDB.createTooltip("First", e.currentTarget, {type:"top"});
})
.on("mouseenter." + this.getName(), ".BSP-pagination-last:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
BDFDB.createTooltip("Last", e.currentTarget, {type:"top"});
})
.on("mouseenter." + this.getName(), ".BSP-pagination-jump:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
BDFDB.createTooltip("Go To", e.currentTarget, {type:"top"});
})
.on("click." + this.getName(), ".BSP-pagination " + BDFDB.dotCN.searchresultspaginationprevious + ":not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", () => {
this.SearchNavigation.searchPreviousPage(searchID);
})
.on("click." + this.getName(), ".BSP-pagination " + BDFDB.dotCN.searchresultspaginationnext + ":not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", () => {
this.SearchNavigation.searchNextPage(searchID);
})
.on("click." + this.getName(), ".BSP-pagination-first:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", () => {
for (let i = 0; currentpage - 1 - i > 0; i++) {
this.SearchNavigation.searchPreviousPage(searchID);
}
})
.on("click." + this.getName(), ".BSP-pagination-last:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", () => {
for (let i = 0; maxpage - currentpage - i > 0; i++) {
this.SearchNavigation.searchNextPage(searchID);
}
})
.on("keydown." + this.getName(), ".BSP-pagination-jumpinput " + BDFDB.dotCN.inputmini, (e) => {
e.stopPropagation();
if (e.which == 13) doJump(e.currentTarget);
})
.on("click." + this.getName(), ".BSP-pagination-jump:not(" + BDFDB.dotCN.searchresultspaginationdisabled + ")", (e) => {
doJump(e.currentTarget.parentElement.querySelector(".BSP-pagination-jumpinput " + BDFDB.dotCN.inputmini));
});
}
}

View File

@ -0,0 +1,3 @@
# Better Search Page - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterSearchPage/BetterSearchPage.plugin.js)
Adds some extra controls to the search results page.

View File

@ -0,0 +1,153 @@
//META{"name":"CharCounter"}*//
class CharCounter {
initConstructor () {
this.selecting = false;
this.counterMarkup = `<div id="charcounter"></div>`;
this.css = `
${BDFDB.dotCN.themelight} #charcounter {
color: #747f8d;
opacity: .7;
}
${BDFDB.dotCN.themedark} #charcounter {
color: #ccc;
opacity: .5;
}
${BDFDB.dotCNS.typing + BDFDB.dotCN.cooldownwrapper} {
margin-right: 64px;
}
#charcounter {
display: block;
position: absolute;
z-index: 1000;
pointer-events: none;
}
#charcounter.normal {
right: 0;
bottom: -1.3em;
}
#charcounter.edit {
left: 0;
bottom: -1.3em;
}
#charcounter.form {
right: 0;
bottom: -1.0em;
}`;
}
getName () {return "CharCounter";}
getDescription () {return "Adds a charcounter in the chat.";}
getVersion () {return "1.2.6";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.textareainner + ":not(" + BDFDB.dotCN.textareainnerdisabled + ")")) {
this.appendCounter(node.querySelector("textarea"));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"textareaObserver",instance:observer}, {childList: true, subtree: true});
document.querySelectorAll("textarea").forEach(textarea => {this.appendCounter(textarea);});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$("#charcounter").remove();
$(".charcounter-added").removeClass("charcounter-added");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
appendCounter (textarea) {
if (!textarea) return;
var textareaWrap = textarea.parentElement;
if (textareaWrap && !textareaWrap.querySelector("#charcounter")) {
var textareaInstance = BDFDB.getOwnerInstance({"node":textarea, "props":["handlePaste","saveCurrentText"], "up":true});
if (textareaInstance && textareaInstance.props && textareaInstance.props.type) {
var counter = $(this.counterMarkup);
counter.addClass(textareaInstance.props.type).appendTo(textareaWrap);
var updateCounter = () => {
var selection = textarea.selectionEnd - textarea.selectionStart == 0 ? "" : " (" + (textarea.selectionEnd - textarea.selectionStart) + ")";
counter.text(BDFDB.getParsedLength(textarea.value) + "/2000" + selection);
}
textareaWrap.parentElement.classList.add("charcounter-added");
$(textarea)
.off("keydown." + this.getName() + " click." + this.getName())
.on("keydown." + this.getName() + " click." + this.getName(), e => {
clearTimeout(textarea.charcountertimeout);
textarea.charcountertimeout = setTimeout(() => {updateCounter();},100);
})
.off("mousedown." + this.getName())
.on("mousedown." + this.getName(), e => {
this.selecting = true;
});
$(document)
.off("mouseup." + this.getName())
.on("mouseup." + this.getName(), e => {
if (this.selecting) {
this.selecting = false;
}
})
.off("mousemove." + this.getName())
.on("mousemove." + this.getName(), e => {
if (this.selecting) {
setTimeout(() => {
updateCounter();
},10);
}
});
updateCounter();
}
}
}
}

View File

@ -0,0 +1,3 @@
# Char Counter - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CharCounter/CharCounter.plugin.js)
Adds a character counter to your textarea.

View File

@ -0,0 +1,483 @@
//META{"name":"ChatAliases"}*//
class ChatAliases {
initConstructor () {
this.configs = ["case","exact","autoc","regex","file"];
this.defaults = {
settings: {
addAutoComplete: {value:true, description:"Add an Autocomplete-Menu for Non-Regex Aliases:"}
}
};
}
getName () {return "ChatAliases";}
getDescription () {return "Allows the user to configure their own chat-aliases which will automatically be replaced before the message is being sent.";}
getVersion () {return "1.9.0";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Replace:</h3><input action="add" type="text" placeholder="Wordvalue" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} wordInputs" id="input-wordvalue" style="flex: 1 1 auto;"><button action="add" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-addword" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">With:</h3><input action="add" type="text" placeholder="Replacevalue" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} wordInputs" id="input-replacevalue" style="flex: 1 1 auto;"><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} file-navigator" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div><input id="input-file" type="file" style="display:none!important;"></button></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto; max-width: ${556 - (this.configs.length * 33)}px;">List of Chataliases:</h3><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifycenter + BDFDB.disCNS.alignend + BDFDB.disCN.nowrap}" style="flex: 1 1 auto; max-width: ${this.configs.length * 34}px;">`;
for (let config of this.configs) {
settingshtml += `<div class="${BDFDB.disCNS.margintop8 + BDFDB.disCNS.tableheadersize + BDFDB.disCNS.size10 + BDFDB.disCNS.primary + BDFDB.disCN.weightbold}" style="flex: 1 1 auto; width: 34px !important; text-align: center;">${config.toUpperCase()}</div>`;
}
settingshtml += `</div></div><div class="DevilBro-settings-inner-list alias-list ${BDFDB.disCNS.gamesettings + BDFDB.disCN.marginbottom8}">`;
for (let word in this.aliases) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><input type="text" word="${word}" action="edit" class="${BDFDB.disCNS.gamename + BDFDB.disCN.gamenameinput} word-name" value="${BDFDB.encodeToHTML(word)}"><input type="text" word="${word}" action="edit" class="${BDFDB.disCNS.gamename + BDFDB.disCN.gamenameinput} replace-name" value="${BDFDB.encodeToHTML(this.aliases[word].replace)}">`;
for (let config of this.configs) {
settingshtml += `<div class="${BDFDB.disCNS.checkboxcontainer + BDFDB.disCN.marginreset}" style="flex: 0 0 auto;"><label class="${BDFDB.disCN.checkboxwrapper}"><input word="${word}" config="${config}" type="checkbox" class="${BDFDB.disCNS.checkboxinputdefault + BDFDB.disCN.checkboxinput}"${this.aliases[word][config] ? " checked" : ""}><div class="${BDFDB.disCNS.checkbox + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.checkboxround}"><svg name="Checkmark" width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><polyline stroke="transparent" stroke-width="2" points="3.5 9.5 7 13 15 5"></polyline></g></svg></div></label></div>`;
console.log();
}
settingshtml += `</div><div word="${word}" action="remove" class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Remove all added words.</h3><button action="removeall" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} remove-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
var infoHidden = BDFDB.loadData("hideInfo", this, "hideInfo");
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.cursorpointer} ${infoHidden ? BDFDB.disCN.categorywrappercollapsed : BDFDB.disCN.categorywrapperdefault} toggle-info" style="flex: 1 1 auto;"><svg class="${BDFDB.disCNS.categoryicontransition + (infoHidden ? BDFDB.disCNS.closed + BDFDB.disCN.categoryiconcollapsed : BDFDB.disCN.categoryicondefault)}" width="12" height="12" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10"></path></svg><div class="${BDFDB.disCNS.categorycolortransition + BDFDB.disCNS.overflowellipsis + BDFDB.disCN.categorynamecollapsed}" style="flex: 1 1 auto;">Information</div></div>`;
settingshtml += `<div class="DevilBro-settings-inner-list info-container" ${infoHidden ? "style='display:none;'" : ""}><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Case: Will replace words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Not Case: Will replace words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Exact: Will replace words that are exactly the replaceword. apple to pear => applepie stays applepie</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Not Exact: Will replace words anywhere they appear. apple to pear => applepieapple to pearpiepear</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Autoc: Will appear in the Autocomplete Menu (if enabled).</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Regex: Will treat the entered wordvalue as a regular expression. <a target="_blank" href="https://regexr.com/">Help</a></div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">File: If the replacevalue is a filepath it will try to upload the file located at the filepath.</div></div>`;
settingshtml += `</div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("keypress", ".wordInputs", (e) => {if (e.which == 13) this.updateContainer(settingspanel, e.currentTarget);})
.on("keyup", BDFDB.dotCN.gamenameinput, (e) => {this.updateWord(e.currentTarget);})
.on("click", ".btn-addword, .remove-word, .remove-all", (e) => {this.updateContainer(settingspanel, e.currentTarget);})
.on("click", BDFDB.dotCN.checkboxinput, (e) => {this.updateConfig(e.currentTarget);})
.on("click", ".toggle-info", (e) => {this.toggleInfo(settingspanel, e.currentTarget);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UploadModule = BDFDB.WebModules.findByProperties(["instantBatchUpload"]);
this.CurrentUserPerms = BDFDB.WebModules.findByProperties(["getChannelPermissions", "can"]);
this.Permissions = BDFDB.WebModules.findByProperties(["Permissions", "ActivityTypes"]).Permissions;
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
document.querySelectorAll("textarea" + BDFDB.dotCN.textarea).forEach(textarea => {this.bindEventToTextArea(textarea);});
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.textareainner + ":not(" + BDFDB.dotCN.textareainnerdisabled + ")")) {
this.bindEventToTextArea(node.querySelector("textarea"));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"textareaObserver",instance:observer}, {childList: true, subtree:true});
this.aliases = BDFDB.loadAllData(this, "words");
document.querySelectorAll("textarea" + BDFDB.dotCN.textarea).forEach(textarea => {this.bindEventToTextArea(textarea);});
$(document).off("click." + this.getName()).on("click." + this.getName(), (e) => {
if (!e.target.tagName === "TEXTAREA") $(".autocompleteAliases, .autocompleteAliasesRow").remove();
});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(".autocompleteAliases, .autocompleteAliasesRow").remove();
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
document.querySelectorAll("textarea" + BDFDB.dotCN.textarea).forEach(textarea => {this.bindEventToTextArea(textarea);});
}
updateContainer (settingspanel, ele) {
var update = false, wordvalue = null, replacevalue = null;
var action = ele.getAttribute("action");
if (action == "add") {
var wordinput = settingspanel.querySelector("#input-wordvalue");
var replaceinput = settingspanel.querySelector("#input-replacevalue");
var fileselection = settingspanel.querySelector("#input-file");
wordvalue = wordinput.value;
replacevalue = replaceinput.value;
if (wordvalue && wordvalue.trim().length > 0 && replacevalue && replacevalue.trim().length > 0) {
wordvalue = wordvalue.trim();
replacevalue = replacevalue.trim();
var filedata = null;
var fs = require("fs");
if (fileselection.files && fileselection.files[0] && fs.existsSync(replacevalue)) {
filedata = JSON.stringify({
data: fs.readFileSync(replacevalue).toString("base64"),
name: fileselection.files[0].name,
type: fileselection.files[0].type
});
}
this.aliases[wordvalue] = {
replace: replacevalue,
filedata: filedata,
case: false,
exact: wordvalue.indexOf(" ") == -1,
autoc: true,
regex: false,
file: filedata != null
};
wordinput.value = null;
replaceinput.value = null;
update = true;
}
}
else if (action == "remove") {
wordvalue = ele.getAttribute("word");
if (wordvalue) {
delete this.aliases[wordvalue];
update = true;
}
}
else if (action == "removeall") {
if (confirm("Are you sure you want to remove all added Words from your list?")) {
this.aliases = {};
update = true;
}
}
if (update) {
BDFDB.saveAllData(this.aliases, this, "words");
var containerhtml = ``;
for (let word in this.aliases) {
containerhtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><input type="text" word="${word}" action="edit" class="${BDFDB.disCNS.gamename + BDFDB.disCN.gamenameinput} word-name" value="${BDFDB.encodeToHTML(word)}"><input type="text" word="${word}" action="edit" class="${BDFDB.disCNS.gamename + BDFDB.disCN.gamenameinput} replace-name" value="${BDFDB.encodeToHTML(this.aliases[word].replace)}">`;
for (let config of this.configs) {
containerhtml += `<div class="${BDFDB.disCNS.checkboxcontainer + BDFDB.disCN.marginreset}" style="flex: 0 0 auto;"><label class="${BDFDB.disCN.checkboxwrapper}"><input word="${word}" config="${config}" type="checkbox" class="${BDFDB.disCNS.checkboxinputdefault + BDFDB.disCN.checkboxinput}"${this.aliases[word][config] ? " checked" : ""}><div class="${BDFDB.disCNS.checkbox + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.checkboxround}"><svg name="Checkmark" width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><polyline stroke="transparent" stroke-width="2" points="3.5 9.5 7 13 15 5"></polyline></g></svg></div></label></div>`;
}
containerhtml += `</div><div word="${word}" action="remove" class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
$(settingspanel).find(".alias-list").html(containerhtml);
BDFDB.initElements(settingspanel);
}
}
updateWord (ele) {
clearTimeout(ele.updateTimeout);
ele.updateTimeout = setTimeout(() => {
var card = ele.parentElement.parentElement;
var oldwordvalue = ele.getAttribute("word");
if (oldwordvalue && this.aliases[oldwordvalue]) {
var wordinput = card.querySelector(".word-name");
var replaceinput = card.querySelector(".replace-name");
var removebutton = card.querySelector(".remove-word");
var newwordvalue = wordinput.value;
var newreplacevalue = replaceinput.value;
wordinput.setAttribute("word", newwordvalue);
wordinput.setAttribute("value", newwordvalue);
replaceinput.setAttribute("word", newwordvalue);
replaceinput.setAttribute("value", newreplacevalue);
removebutton.setAttribute("word", newwordvalue);
this.aliases[newwordvalue] = this.aliases[oldwordvalue];
this.aliases[newwordvalue].replace = newreplacevalue;
if (newwordvalue != oldwordvalue) delete this.aliases[oldwordvalue];
BDFDB.saveAllData(this.aliases, this, "words");
}
},500);
}
updateConfig (ele) {
var wordvalue = ele.getAttribute("word");
var config = ele.getAttribute("config");
if (wordvalue && this.aliases[wordvalue] && config) {
this.aliases[wordvalue][config] = ele.checked;
BDFDB.saveAllData(this.aliases, this, "words");
}
}
toggleInfo (settingspanel, ele) {
ele.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
ele.classList.toggle(BDFDB.disCN.categorywrapperdefault);
var svg = ele.querySelector(BDFDB.dotCN.categoryicontransition);
svg.classList.toggle(BDFDB.disCN.closed);
svg.classList.toggle(BDFDB.disCN.categoryiconcollapsed);
svg.classList.toggle(BDFDB.disCN.categoryicondefault);
var visible = $(settingspanel).find(".info-container").is(":visible");
$(settingspanel).find(".info-container").toggle(!visible);
BDFDB.saveData("hideInfo", visible, this, "hideInfo");
}
bindEventToTextArea (textarea) {
if (!textarea) return;
var channelObj = BDFDB.getSelectedChannel();
var channel = channelObj ? channelObj.data : null;
if (!channel) return;
var settings = BDFDB.getAllData(this, "settings");
$(textarea)
.off("input." + this.getName())
.on("input." + this.getName(), () => {
if (this.format) {
this.format = false;
textarea.focus();
textarea.selectionStart = 0;
textarea.selectionEnd = textarea.value.length;
if (document.activeElement == textarea) {
var messageInput = this.formatText(textarea.value);
if (messageInput && messageInput.text != null) {
document.execCommand("insertText", false, messageInput.text ? messageInput.text + " " : "");
}
if (messageInput && messageInput.files.length > 0 && (channel.type == 1 || this.CurrentUserPerms.can(this.Permissions.ATTACH_FILES, channel))) {
this.UploadModule.instantBatchUpload(channel.id, messageInput.files);
}
}
}
})
.off("keydown." + this.getName())
.on("keydown." + this.getName(), e => {
let autocompletemenu = textarea.parentElement.querySelector(BDFDB.dotCN.autocomplete);
if ((e.which == 9 || e.which == 13) && autocompletemenu) {
if (autocompletemenu.querySelector(BDFDB.dotCN.autocompleteselected).parentElement.classList.contains("autocompleteAliasesRow")) {
e.preventDefault();
e.stopPropagation();
this.swapWordWithAlias(textarea);
}
}
else if ((e.which == 38 || e.which == 40) && autocompletemenu) {
let autocompleteitems = autocompletemenu.querySelectorAll(BDFDB.dotCN.autocompleteselectable + ":not(.autocompleteAliasesSelector)");
let selected = autocompletemenu.querySelector(BDFDB.dotCN.autocompleteselected);
if (selected.classList.contains("autocompleteAliasesSelector") || autocompleteitems[e.which == 38 ? 0 : (autocompleteitems.length-1)] == selected) {
e.preventDefault();
e.stopPropagation();
let next = this.getNextSelection(autocompletemenu, null, e.which == 38 ? false : true);
selected.classList.remove(BDFDB.disCN.autocompleteselected);
next.classList.add(BDFDB.disCN.autocompleteselected);
if (!next.classList.contains("autocompleteAliasesSelector")) {
// if next element is a default discord autocomplete item, trigger the keypress again so the item is internally selected
var press = new KeyboardEvent("keypress", e);
Object.defineProperty(press, "keyCode", {value: e.which});
Object.defineProperty(press, "which", {value: e.which});
textarea.dispatchEvent(press);
}
}
}
else if (textarea.value && !e.shiftKey && e.which == 13 && !autocompletemenu && textarea.value.indexOf("s/") != 0) {
this.format = true;
$(textarea).trigger("input");
}
else if (!e.ctrlKey && settings.addAutoComplete && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length) {
clearTimeout(textarea.chataliastimeout);
textarea.chataliastimeout = setTimeout(() => {this.addAutoCompleteMenu(textarea);},100);
}
if (!e.ctrlKey && e.which != 38 && e.which != 40) {
if (!(e.which == 39 && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length)) {
$(".autocompleteAliases, .autocompleteAliasesRow").remove();
}
}
})
.off("click." + this.getName())
.on("click." + this.getName(), e => {
if (settings.addAutoComplete && textarea.selectionStart == textarea.selectionEnd && textarea.selectionEnd == textarea.value.length) {
setImmediate(() => {this.addAutoCompleteMenu(textarea);});
}
});
}
addAutoCompleteMenu (textarea) {
if (textarea.parentElement.querySelector(".autocompleteAliasesRow")) return;
let words = textarea.value.split(" ");
let lastword = words[words.length-1].trim();
if (words.length == 1 && BDFDB.isPluginEnabled("WriteUpperCase")) {
let first = lastword.charAt(0);
if (first === first.toUpperCase() && lastword.toLowerCase().indexOf("http") == 0) {
lastword = lastword.charAt(0).toLowerCase() + lastword.slice(1);
}
else if (first === first.toLowerCase() && first !== first.toUpperCase() && lastword.toLowerCase().indexOf("http") != 0) {
lastword = lastword.charAt(0).toUpperCase() + lastword.slice(1);
}
}
if (lastword) {
let matchedaliases = {};
for (let word in this.aliases) {
let aliasdata = this.aliases[word];
if (!aliasdata.regex && aliasdata.autoc) {
if (aliasdata.exact) {
if (aliasdata.case && word.indexOf(lastword) == 0) matchedaliases[word] = aliasdata;
else if (!aliasdata.case && word.toLowerCase().indexOf(lastword.toLowerCase()) == 0) matchedaliases[word] = aliasdata;
}
else {
if (aliasdata.case && word.indexOf(lastword) > -1) matchedaliases[word] = aliasdata;
else if (!aliasdata.case && word.toLowerCase().indexOf(lastword.toLowerCase()) > -1) matchedaliases[word] = aliasdata;
}
}
}
if (!BDFDB.isObjectEmpty(matchedaliases)) {
let autocompletemenu = textarea.parentElement.querySelector(BDFDB.dotCNS.autocomplete + BDFDB.dotCN.autocompleteinner), amount = 15;
if (!autocompletemenu) {
autocompletemenu = $(`<div class="${BDFDB.disCNS.autocomplete + BDFDB.disCN.autocomplete2} autocompleteAliases"><div class="${BDFDB.disCN.autocompleteinner}"></div></div>`)[0];
textarea.parentElement.appendChild(autocompletemenu);
autocompletemenu = autocompletemenu.firstElementChild;
}
else {
amount -= autocompletemenu.querySelectorAll(BDFDB.dotCN.autocompleteselectable).length;
}
$(autocompletemenu)
.append(`<div class="${BDFDB.disCNS.autocompleterowvertical + BDFDB.disCN.autocompleterow} autocompleteAliasesRow"><div class="${BDFDB.disCN.autocompleteselector} autocompleteAliasesSelector"><div class="${BDFDB.disCNS.autocompletecontenttitle + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.weightsemibold}">Aliases: <strong class="lastword">${BDFDB.encodeToHTML(lastword)}</strong></div></div></div>`)
.off("mouseenter." + this.getName()).on("mouseenter." + this.getName(), BDFDB.dotCN.autocompleteselectable, (e) => {
autocompletemenu.querySelectorAll(BDFDB.dotCN.autocompleteselected).forEach(selected => {selected.classList.remove(BDFDB.disCN.autocompleteselected);});
e.currentTarget.classList.add(BDFDB.disCN.autocompleteselected);
});
for (let word in matchedaliases) {
if (amount-- < 1) break;
$(`<div class="${BDFDB.disCNS.autocompleterowvertical + BDFDB.disCN.autocompleterow} autocompleteAliasesRow"><div class="${BDFDB.disCNS.autocompleteselector + BDFDB.disCN.autocompleteselectable} autocompleteAliasesSelector"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.autocompletecontent}" style="flex: 1 1 auto;"><div class="${BDFDB.disCN.flexchild} aliasword" style="flex: 1 1 auto;">${BDFDB.encodeToHTML(word)}</div><div class="${BDFDB.disCNS.autocompletedescription + BDFDB.disCN.flexchild}">${BDFDB.encodeToHTML(matchedaliases[word].replace)}</div></div></div></div>`)
.appendTo(autocompletemenu)
.off("click." + this.getName()).on("click." + this.getName(), BDFDB.dotCN.autocompleteselectable, (e) => {
this.swapWordWithAlias(textarea);
});
}
if (!autocompletemenu.querySelector(BDFDB.dotCN.autocompleteselected)) {
autocompletemenu.querySelector(".autocompleteAliasesRow " + BDFDB.dotCN.autocompleteselectable).classList.add(BDFDB.disCN.autocompleteselected);
}
}
}
}
getNextSelection (menu, selected, forward) {
selected = selected ? selected : menu.querySelector(BDFDB.dotCN.autocompleteselected).parentElement;
let next, sibling = forward ? selected.nextElementSibling : selected.previousElementSibling;
if (sibling) {
next = sibling.querySelector(BDFDB.dotCN.autocompleteselectable);
}
else {
let items = menu.querySelectorAll(BDFDB.dotCN.autocompleteselectable);
next = forward ? items[0] : items[items.length-1];
}
return next ? next : this.getNextSelection(menu, sibling, forward);
}
swapWordWithAlias (textarea) {
let aliasword = textarea.parentElement.querySelector(".autocompleteAliasesRow " + BDFDB.dotCN.autocompleteselected + " .aliasword").innerText;
let lastword = textarea.parentElement.querySelector(".autocompleteAliasesRow .lastword").innerText;
if (aliasword && lastword) {
$(".autocompleteAliases, .autocompleteAliasesRow").remove();
textarea.focus();
textarea.selectionStart = textarea.value.length - lastword.length;
textarea.selectionEnd = textarea.value.length;
document.execCommand("insertText", false, aliasword);
textarea.selectionStart = textarea.value.length;
textarea.selectionEnd = textarea.value.length;
}
}
formatText (text) {
var newText = [], files = [], wordAliases = {}, multiAliases = {};
for (let word in this.aliases) {
if (!this.aliases[word].regex && word.indexOf(" ") == -1) wordAliases[word] = this.aliases[word];
else multiAliases[word] = this.aliases[word];
}
for (let word of text.trim().split(" ")) {
newText.push(this.useAliases(word, wordAliases, files, true));
}
newText = newText.length == 1 ? newText[0] : newText.join(" ");
newText = this.useAliases(newText, multiAliases, files, false);
return {text:newText, files};
}
useAliases (string, aliases, files, singleword) {
for (let word in aliases) {
let aliasdata = aliases[word];
let escpAlias = aliasdata.regex ? word : BDFDB.regEscape(word);
let result = true, replaced = false, tempstring1 = string, tempstring2 = "";
let regstring = aliasdata.exact ? "^" + escpAlias + "$" : escpAlias;
while (result != null) {
result = new RegExp(regstring, (aliasdata.case ? "" : "i") + (aliasdata.exact ? "" : "g")).exec(tempstring1);
if (result) {
replaced = true;
let replace = aliasdata.file ? "" : BDFDB.insertNRST(aliasdata.replace);
if (result.length > 1) for (var i = 1; i < result.length; i++) replace = replace.replace(new RegExp("\\\\" + i, "g"), result[i]);
tempstring2 += tempstring1.slice(0, result.index + result[0].length).replace(result[0], replace);
tempstring1 = tempstring1.slice(result.index + result[0].length);
if (aliasdata.file && typeof aliasdata.filedata == "string") {
var filedata = JSON.parse(aliasdata.filedata);
files.push(new File([Buffer.from(filedata.data, "base64")], filedata.name, {type:filedata.type}));
}
if (aliasdata.regex && regstring.indexOf("^") == 0) result = null;
}
if (!result) {
tempstring2 += tempstring1;
}
}
if (replaced) {
string = tempstring2;
if (singleword) break;
}
}
return string;
}
replaceWord (string, regex) {
let result = regex.exec(string), rest = "";
if (result) {
rest = string.slice(a.indexOf(b)+b.length);
}
}
}

View File

@ -0,0 +1,3 @@
# Chat Aliases - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatAliases/ChatAliases.plugin.js)
Allows the user to configure their own chat-aliases which will automatically be replaced before the message is being sent.

View File

@ -0,0 +1,442 @@
//META{"name":"ChatFilter"}*//
class ChatFilter {
initConstructor () {
this.configs = ["case","exact"];
this.css = `
${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messageaccessory}.blocked:not(.revealed),
${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messagemarkup}.blocked:not(.revealed) {
font-weight: bold;
font-style: italic;
}
${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messageaccessory}.censored:not(.revealed),
${BDFDB.dotCNS.messagegroup + BDFDB.dotCN.messagemarkup}:not(.revealed) {
}`;
this.defaults = {
replaces: {
blocked: {value:"~~BLOCKED~~", title:"Block:", description:"Default Replace Word for blocked Messages:"},
censored: {value:"$!%&%!&", title:"Censor:", description:"Default Replace Word for censored Messages:"}
},
settings: {
showMessageOnClick: {value:{blocked:true, censored:true}, enabled:{blocked:true, censored:true}, description:"Show original Message on Click:"},
hideMessage: {value:{blocked:false, censored:false}, enabled:{blocked:true, censored:false}, description:"Completely hide targeted Messages:"}
}
};
}
getName () {return "ChatFilter";}
getDescription () {return "Allows the user to censor words or block complete messages based on words in the chatwindow.";}
getVersion () {return "3.2.3";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var replaces = BDFDB.getAllData(this, "replaces");
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let rtype in replaces) {
var words = BDFDB.loadData(rtype, this, "words");
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto; min-width:55px;">${this.defaults.replaces[rtype].title}</h3><input rtype="${rtype}" action="add" type="text" placeholder="Wordvalue" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} wordInputs" id="input-${rtype}-wordvalue" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">With:</h3><input rtype="${rtype}" action="add" type="text" placeholder="Replacevalue" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} wordInputs" id="input-${rtype}-replacevalue" style="flex: 1 1 auto;"><button rtype="${rtype}" action="add" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-addword" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div>`;
for (let key in settings) {
settingshtml += `<div rtype="${rtype}" value="${key}" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" rtype="${rtype}" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key][rtype] ? " checked" : ""}></div></div>`;
}
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto; min-width: 320px;">${this.defaults.replaces[rtype].description}</h3><input rtype="${rtype}" type="text" placeholder="${this.defaults.replaces[rtype].value}" value="${replaces[rtype]}" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} defaultInputs" id="input-${rtype}-defaultvalue" style="flex: 1 1 auto;"></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto; max-width: 495px;">List of ${rtype} Words:</h3><div class="${BDFDB.disCNS.margintop8 + BDFDB.disCNS.tableheadersize + BDFDB.disCNS.size10 + BDFDB.disCNS.primary + BDFDB.disCN.weightbold}" style="flex: 1 1 auto; max-width: 32px;">CASE</div><div class="${BDFDB.disCNS.margintop8 + BDFDB.disCNS.tableheadersize + BDFDB.disCNS.size10 + BDFDB.disCNS.primary + BDFDB.disCN.weightbold}" style="flex: 0 0 auto;">EXACT</div></div><div class="DevilBro-settings-inner-list ${rtype}-list">`;
for (let word in words) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis}" style="flex: 1 1 auto;">${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(words[word].replace)})</div>`
for (let config of this.configs) {
settingshtml += `<div class="${BDFDB.disCNS.checkboxcontainer + BDFDB.disCN.marginreset}" style="flex: 0 0 auto;"><label class="${BDFDB.disCN.checkboxwrapper}"><input word="${word}" rtype="${rtype}" config="${config}" type="checkbox" class="${BDFDB.disCNS.checkboxinputdefault + BDFDB.disCN.checkboxinput}"${words[word][config] ? " checked" : ""}><div class="${BDFDB.disCNS.checkbox + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.checkboxround}"><svg name="Checkmark" width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><polyline stroke="transparent" stroke-width="2" points="3.5 9.5 7 13 15 5"></polyline></g></svg></div></label></div>`;
}
settingshtml += `</div><div word="${word}" rtype="${rtype}" action="remove" class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
settingshtml += `</div>`
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Remove all added words.</h3><button rtype="${rtype}" action="removeall" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} remove-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCNS.modaldividerdefault + BDFDB.disCN.marginbottom40}"></div>`;
}
var infoHidden = BDFDB.loadData("hideInfo", this, "hideInfo");
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.cursorpointer} ${infoHidden ? BDFDB.disCN.categorywrappercollapsed : BDFDB.disCN.categorywrapperdefault} toggle-info" style="flex: 1 1 auto;"><svg class="${BDFDB.disCNS.categoryicontransition + (infoHidden ? BDFDB.disCNS.closed + BDFDB.disCN.categoryiconcollapsed : BDFDB.disCN.categoryicondefault)}" width="12" height="12" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10"></path></svg><div class="${BDFDB.disCNS.categorycolortransition + BDFDB.disCNS.overflowellipsis + BDFDB.disCN.categorynamecollapsed}" style="flex: 1 1 auto;">Information</div></div>`;
settingshtml += `<div class="DevilBro-settings-inner-list info-container" ${infoHidden ? "style='display:none;'" : ""}><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Case: Will block/censor words while comparing lowercase/uppercase. apple => apple, not APPLE or AppLe</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Not Case: Will block/censor words while ignoring lowercase/uppercase. apple => apple, APPLE and AppLe</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Exact: Will block/censor words that are exactly the selected word. apple => apple, not applepie or pineapple</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">Not Exact: Will block/censor all words containing the selected word. apple => apple, applepie and pineapple</div></div>`;
settingshtml += `</div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("keypress", ".wordInputs", (e) => {if (e.which == 13) this.updateContainer(settingspanel, e.currentTarget);})
.on("keyup", ".defaultInputs", (e) => {this.saveReplace(e.currentTarget);})
.on("click", ".btn-addword, .remove-word, .remove-all", (e) => {this.updateContainer(settingspanel, e.currentTarget);})
.on("click", BDFDB.dotCN.checkboxinput, (e) => {this.updateConfig(e.currentTarget);})
.on("click", ".toggle-info", (e) => {this.toggleInfo(settingspanel, e.currentTarget);});
for (let key in settings) {
for (let rtype in this.defaults.settings[key].enabled) {
if (!this.defaults.settings[key].enabled[rtype]) $(settingspanel).find(`${BDFDB.dotCN.flex}[value='${key}'][rtype='${rtype}']`).hide();
}
}
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.type == "characterData") {
this.hideMessage(change.target.parentElement);
}
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.classList.contains(BDFDB.disCN.message)) this.hideMessage(node.querySelector(BDFDB.dotCN.messagemarkup));
});
}
}
);
});
BDFDB.addObserver(this, null, {name:"messageChangeObserver",instance:observer,multi:true}, {childList:true, characterData:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.message)) {
BDFDB.addObserver(this, node, {name:"messageChangeObserver",multi:true}, {childList:true, characterData:true, subtree:true});
node.querySelectorAll(BDFDB.dotCNC.messagemarkup + BDFDB.dotCN.messageaccessory).forEach(message => {
this.hideMessage(message);
});
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && $(node).attr("layer-id") == "user-settings") this.hideAllMessages();
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
this.hideAllMessages();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(`${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored, ${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored`).forEach(message => {
this.resetMessage(message);
});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.hideAllMessages();
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
}
}
// begin of own functions
updateContainer (settingspanel, ele) {
var update = false, wordvalue = null, replacevalue = null;
var action = ele.getAttribute("action"), rtype = ele.getAttribute("rtype");
var words = BDFDB.loadData(rtype, this, "words") || {};
if (action == "add") {
var wordinput = settingspanel.querySelector("#input-" + rtype + "-wordvalue");
var replaceinput = settingspanel.querySelector("#input-" + rtype + "-replacevalue");
wordvalue = wordinput.value;
replacevalue = replaceinput.value;
if (wordvalue && wordvalue.trim().length > 0) {
wordvalue = wordvalue.trim();
replacevalue = replacevalue.trim();
words[wordvalue] = {
replace: replacevalue,
case: false,
exact: true,
regex: false,
};
wordinput.value = null;
replaceinput.value = null;
update = true;
}
}
else if (action == "remove") {
wordvalue = ele.getAttribute("word");
if (wordvalue) {
delete words[wordvalue];
update = true;
}
}
else if (action == "removeall") {
if (confirm("Are you sure you want to remove all added Words from your list?")) {
words = {};
update = true;
}
}
if (update) {
BDFDB.saveData(rtype, words, this, "words");
words = BDFDB.loadData(rtype, this, "words");
var containerhtml = ``;
for (let word in words) {
containerhtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis}" style="flex: 1 1 auto;">${BDFDB.encodeToHTML(word)} (${BDFDB.encodeToHTML(words[word].replace)})</div>`
for (let config of this.configs) {
containerhtml += `<div class="${BDFDB.disCNS.checkboxcontainer + BDFDB.disCN.marginreset}" style="flex: 0 0 auto;"><label class="${BDFDB.disCN.checkboxwrapper}"><input word="${word}" rtype="${rtype}" config="${config}" type="checkbox" class="${BDFDB.disCNS.checkboxinputdefault + BDFDB.disCN.checkboxinput}"${words[word][config] ? " checked" : ""}><div class="${BDFDB.disCNS.checkbox + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.checkboxround}"><svg name="Checkmark" width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><polyline stroke="transparent" stroke-width="2" points="3.5 9.5 7 13 15 5"></polyline></g></svg></div></label></div>`;
}
containerhtml += `</div><div word="${word}" rtype="${rtype}" action="remove" class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
containerhtml += `</div>`;
$(settingspanel).find("." + rtype + "-list").html(containerhtml);
BDFDB.initElements(settingspanel);
}
}
saveReplace (input) {
var rtype = input.getAttribute("rtype");
var wordvalue = input.value;
if (rtype) {
var replaces = BDFDB.getData(rtype, this, "replaces");
BDFDB.saveData(rtype, wordvalue.trim(), this, "replaces");
}
}
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
let key = input.getAttribute("value");
let rtype = input.getAttribute("rtype");
if (!settings[key]) settings[key] = {};
settings[key][rtype] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
updateConfig (ele) {
var wordvalue = ele.getAttribute("word");
var config = ele.getAttribute("config");
var rtype = ele.getAttribute("rtype");
var words = BDFDB.loadData(rtype, this, "words") || {};
if (wordvalue && words[wordvalue] && config) {
words[wordvalue][config] = ele.checked;
BDFDB.saveData(rtype, words, this, "words");
}
}
toggleInfo (settingspanel, ele) {
ele.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
ele.classList.toggle(BDFDB.disCN.categorywrapperdefault);
var svg = ele.querySelector(BDFDB.dotCN.categoryicontransition);
svg.classList.toggle(BDFDB.disCN.closed);
svg.classList.toggle(BDFDB.disCN.categoryiconcollapsed);
svg.classList.toggle(BDFDB.disCN.categoryicondefault);
var visible = $(settingspanel).find(".info-container").is(":visible");
$(settingspanel).find(".info-container").toggle(!visible);
BDFDB.saveData("hideInfo", visible, this, "hideInfo");
}
hideAllMessages () {
document.querySelectorAll(`${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored, ${BDFDB.dotCN.messagemarkup}.blocked, ${BDFDB.dotCN.messageaccessory}.censored`).forEach(message => {
this.resetMessage(message);
});
document.querySelectorAll(BDFDB.dotCN.messagegroup).forEach(messageContainer => {
BDFDB.addObserver(this, messageContainer, {name:"messageChangeObserver",multi:true}, {childList:true, characterData:true, subtree:true});
messageContainer.querySelectorAll(BDFDB.dotCNC.messagemarkup + BDFDB.dotCN.messageaccessory).forEach(message => {
this.hideMessage(message);
});
});
}
hideMessage (message) {
if (!$(message).hasClass("blocked") && !$(message).hasClass("censored")) {
var orightml = $(message).html();
var newhtml = "";
if (orightml) {
var blocked = null;
var strings = [];
var count = 0;
orightml.split("").forEach((chara) => {
if (chara == "<") {
if (strings[count]) count++;
}
strings[count] = strings[count] ? strings[count] + chara : chara;
if (chara == ">") {
count++;
}
});
var settings = BDFDB.getAllData(this, "settings");
var replaces = BDFDB.getAllData(this, "replaces");
var blockedWords = BDFDB.loadData("blocked", this, "words");
var blocked = false;
for (let bWord in blockedWords) {
var blockedReplace = blockedWords[bWord].replace || replaces.blocked;
var reg = this.createReg(bWord, blockedWords[bWord]);
strings.forEach(string => {
let emojiname = this.getEmojiName(string);
if (emojiname && reg.test(emojiname)) blocked = true;
else if (string.indexOf('<img src="http') == 0) {
var url = string.split('src="').length > 0 ? string.split('src="')[1] : null;
url = url ? url.split('"')[0] : null;
if (reg.test(url)) blocked = true;
}
else if (string.indexOf("<") != 0) {
string.split(" ").forEach((word) => {
if (reg.test(word)) blocked = true;
});
}
});
if (blocked) break;
}
if (blocked) {
if (settings.hideMessage.blocked) $(message).hide();
newhtml = BDFDB.encodeToHTML(blockedReplace);
$(message)
.html(newhtml)
.addClass("blocked")
.data("newhtmlChatFilter",newhtml)
.data("orightmlChatFilter",orightml);
this.addClickListener(message, settings.showMessageOnClick.blocked);
}
else {
var censoredWords = BDFDB.loadData("censored", this, "words");
for (let cWord in censoredWords) {
var censoredReplace = censoredWords[cWord].replace || replaces.censored;
var reg = this.createReg(cWord, censoredWords[cWord]);
strings.forEach((string,i) => {
let emojiname = this.getEmojiName(string);
if (emojiname && reg.test(emojiname)) {
strings[i] = BDFDB.encodeToHTML(censoredReplace);
if (strings[i+1] && strings[i+1].indexOf("<input") == 0) {
strings[i+1] = "";
if (strings[i-1] && strings[i-1].indexOf("<span") == 0) strings[i-1] = "";
if (strings[i+2] && strings[i+2].indexOf("</span") == 0) strings[i+2] = "";
}
}
else if (string.indexOf('<img src="http') == 0) {
var url = string.split('src="').length > 0 ? string.split('src="')[1] : null;
url = url ? url.split('"')[0] : null;
if (reg.test(url)) {
strings = [BDFDB.encodeToHTML(censoredReplace)];
}
}
else if (string.indexOf("<") != 0) {
var newstring = [];
string.split(" ").forEach((word) => {
newstring.push(reg.test(word) ? BDFDB.encodeToHTML(censoredReplace) : word);
});
strings[i] = newstring.join(" ");
}
});
}
newhtml = strings.join("");
if (newhtml != orightml) {
$(message)
.html(newhtml)
.addClass("censored")
.data("newhtmlChatFilter",newhtml)
.data("orightmlChatFilter",orightml);
this.addClickListener(message, settings.showMessageOnClick.censored);
}
}
}
}
}
createReg (word, config) {
return new RegExp(BDFDB.encodeToHTML(config.exact ? "^" + BDFDB.regEscape(word) + "$" : BDFDB.regEscape(word)), config.case ? "" : "i");
}
getEmojiName (string) {
if (string.indexOf("<img ") == 0 && (string.indexOf('class="emote') > -1 || string.indexOf('class="emoji') > -1)) {
var emojiname = string.split('alt="').length > 0 ? string.split('alt="')[1] : null;
emojiname = emojiname ? emojiname.split('" src')[0] : null;
return emojiname = emojiname ? emojiname.replace(new RegExp(":", 'g'), "") : null;
}
}
resetMessage (message) {
$(message)
.html($(message).data("orightmlChatFilter"))
.off("click." + this.getName())
.removeClass("blocked")
.removeClass("censored")
.removeClass("revealed");
}
addClickListener (message, add) {
$(message)
.off("click." + this.getName());
if (add) {
var orightml = $(message).data("orightmlChatFilter");
var newhtml = $(message).data("newhtmlChatFilter");
$(message)
.on("click." + this.getName(), () => {
if ($(message).hasClass("revealed")) {
$(message)
.html(newhtml)
.removeClass("revealed");
}
else {
$(message)
.html(orightml)
.addClass("revealed");
}
});
}
}
}

View File

@ -0,0 +1,4 @@
# Chat Filter - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatFilter/ChatFilter.plugin.js)
Allows the user to censor words or block complete messages based on words in the chatwindow. Blocked in this case means, that a message that contains one of the words will be completely blocked in your chat window. Censored means you will still be able to read the message but the censored words will be unreadable. You can also completely hide blocked messages and enable the option to see the original message while hovering over a censored/blocked message.
Supports Regular Expressions.

View File

@ -0,0 +1,370 @@
//META{"name":"CompleteTimestamps"}*//
class CompleteTimestamps {
initConstructor () {
this.languages;
this.updateTimestamps = false;
this.defaults = {
settings: {
showInChat: {value:true, description:"Replace Chat Timestamp with Complete Timestamp:"},
showOnHover: {value:false, description:"Also show Timestamp when you hover over a message:"},
changeForEdit: {value:false, description:"Change the Time for the Edited Time Tooltips:"},
displayTime: {value:true, description:"Display the Time in the Timestamp:"},
displayDate: {value:true, description:"Display the Date in the Timestamp:"},
cutSeconds: {value:false, description:"Cut off Seconds of the Time:"},
forceZeros: {value:false, description:"Force leading Zeros:"},
otherOrder: {value:false, description:"Show the Time before the Date:"}
},
choices: {
creationDateLang: {value:"$discord", description:"Timestamp Format:"}
},
formats: {
ownFormat: {value:"$hour:$minute:$second, $day.$month.$year", description:"Own Format:"}
}
};
}
getName () {return "CompleteTimestamps";}
getDescription () {return "Replace all timestamps with complete timestamps.";}
getVersion () {return "1.2.6";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var choices = BDFDB.getAllData(this, "choices");
var formats = BDFDB.getAllData(this, "formats");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
for (let key in choices) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 30%; line-height: 38px;">${this.defaults.choices[key].description}</h3><div class="${BDFDB.disCN.selectwrap}" style="flex: 1 1 70%;"><div class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}" option="${key}" value="${choices[key]}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal} languageName" style="flex: 1 1 42%; padding:0;">${this.languages[choices[key]].name}</div><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal} languageTimestamp" style="flex: 1 1 58%; padding:0;">${this.getTimestamp(this.languages[choices[key]].id)}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div></div></div>`;
}
for (let key in formats) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 30%; line-height: 38px;">${this.defaults.formats[key].description}</h3><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCN.directioncolumn}" style="flex: 1 1 auto;"><input type="text" option="${key}" value="${formats[key]}" placeholder="${this.defaults.formats[key].value}" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}"></div></div>`;
}
var infoHidden = BDFDB.loadData("hideInfo", this, "hideInfo");
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.cursorpointer} ${infoHidden ? BDFDB.disCN.categorywrappercollapsed : BDFDB.disCN.categorywrapperdefault} toggle-info" style="flex: 1 1 auto;"><svg class="${BDFDB.disCNS.categoryicontransition + (infoHidden ? BDFDB.disCNS.closed + BDFDB.disCN.categoryiconcollapsed : BDFDB.disCN.categoryicondefault)}" width="12" height="12" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10"></path></svg><div class="${BDFDB.disCNS.categorycolortransition + BDFDB.disCNS.overflowellipsis + BDFDB.disCN.categorynamecollapsed}" style="flex: 1 1 auto;">Information</div></div>`;
settingshtml += `<div class="DevilBro-settings-inner-list info-container" ${infoHidden ? "style='display:none;'" : ""}>`;
settingshtml += `<div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$hour will be replaced with the current hour</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$minute will be replaced with the current minutes</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$second will be replaced with the current seconds</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$msecond will be replaced with the current milliseconds</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$timemode will change $hour to a 12h format and will be replaced with AM/PM</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$year will be replaced with the current year</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$month will be replaced with the current month</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$day will be replaced with the current day</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$monthnameL will be replaced with the monthname in long format based on the Discord Language</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$monthnameS will be replaced with the monthname in short format based on the Discord Language</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$weekdayL will be replaced with the weekday in long format based on the Discord Language</div><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">$weekdayS will be replaced with the weekday in short format based on the Discord Language</div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("keyup", BDFDB.dotCN.input, () => {this.saveInputs(settingspanel);})
.on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu(e);})
.on("click", ".toggle-info", (e) => {this.toggleInfo(settingspanel, e.currentTarget);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.tagName && node.querySelector("time")) {
node.querySelectorAll("time").forEach(stamp => {this.changeTimestamp(stamp);});
}
else if (node.tagName && node.tagName == "TIME") {
this.changeTimestamp(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"messageObserver",instance:observer}, {childList: true, subtree: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (this.updateTimestamps && node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
this.setMaxWidth();
document.querySelectorAll(".complete-timestamp").forEach(timestamp => {timestamp.classList.remove("complete-timestamp");});
document.querySelectorAll("time").forEach(stamp => {this.changeTimestamp(stamp);})
this.updateTimestamps = false;
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
this.languages = Object.assign({},
{"own": {name:"Own", id:"own", integrated:false, dic:false}},
BDFDB.languages
);
this.setMaxWidth();
$(document)
.on("mouseenter." + this.getName(), BDFDB.dotCNS.message + BDFDB.dotCN.messagecontent, (e) => {
if (BDFDB.getData("showOnHover", this, "settings")) {
let message = e.currentTarget;
let messagegroup = this.getMessageGroup(message);
if (!messagegroup || !messagegroup.tagName) return;
let info = this.getMessageData(message, messagegroup);
if (!info || !info.timestamp || !info.timestamp._i) return;
let choice = BDFDB.getData("creationDateLang", this, "choices");
BDFDB.createTooltip(this.getTimestamp(this.languages[choice].id, info.timestamp._i), message, {type:"left",selector:"completetimestamp-tooltip"});
}
})
.on("mouseenter." + this.getName(), BDFDB.dotCNS.message + BDFDB.dotCN.messageedited, (e) => {
if (BDFDB.getData("changeForEdit", this, "settings")) {
let marker = e.currentTarget;
let time = marker.getAttribute("datetime");
if (!time) return;
let choice = BDFDB.getData("creationDateLang", this, "choices");
let customTooltipCSS = `
body ${BDFDB.dotCN.tooltip}:not(.completetimestampedit-tooltip) {
display: none !important;
}`;
BDFDB.createTooltip(this.getTimestamp(this.languages[choice].id, time), marker, {type:"top",selector:"completetimestampedit-tooltip",css:customTooltipCSS});
}
});
document.querySelectorAll("time").forEach(stamp => {this.changeTimestamp(stamp);})
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".complete-timestamp").forEach(stamp => {stamp.classList.remove("complete-timestamp");});
BDFDB.removeLocalStyle(this.getName() + "CompactCorrection");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
this.updateSettingsPanel(settingspanel);
}
saveInputs (settingspanel) {
var formats = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.input)) {
formats[input.getAttribute("option")] = input.value;
}
BDFDB.saveAllData(formats, this, "formats");
this.updateSettingsPanel(settingspanel);
}
updateSettingsPanel (settingspanel) {
var choices = BDFDB.getAllData(this, "choices");
for (let key in choices) {
settingspanel.querySelector(`${BDFDB.dotCN.select}[option='${key}'] .languageTimestamp`).innerText = this.getTimestamp(this.languages[choices[key]].id);
}
this.updateTimestamps = true;
}
toggleInfo (settingspanel, ele) {
ele.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
ele.classList.toggle(BDFDB.disCN.categorywrapperdefault);
var svg = ele.querySelector(BDFDB.dotCN.categoryicontransition);
svg.classList.toggle(BDFDB.disCN.closed);
svg.classList.toggle(BDFDB.disCN.categoryiconcollapsed);
svg.classList.toggle(BDFDB.disCN.categoryicondefault);
var visible = $(settingspanel).find(".info-container").is(":visible");
$(settingspanel).find(".info-container").toggle(!visible);
BDFDB.saveData("hideInfo", visible, this, "hideInfo");
}
openDropdownMenu (e) {
var selectControl = e.currentTarget;
var selectWrap = selectControl.parentElement;
if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return;
selectWrap.classList.add(BDFDB.disCN.selectisopen);
$("li").has(selectWrap).css("overflow", "visible");
var selectMenu = this.createDropdownMenu(selectWrap.getAttribute("value"));
selectWrap.appendChild(selectMenu);
$(selectMenu).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => {
var language = e2.currentTarget.getAttribute("value");
selectWrap.setAttribute("value", language);
selectControl.querySelector(".languageName").innerText = this.languages[language].name;
selectControl.querySelector(".languageTimestamp").innerText = this.getTimestamp(this.languages[language].id);
BDFDB.saveData(selectWrap.getAttribute("option"), language, this, "choices");
});
$(document).on("mousedown.select" + this.getName(), (e2) => {
if (e2.target.parentElement == selectMenu) return;
$(document).off("mousedown.select" + this.getName());
selectMenu.remove();
$("li").has(selectWrap).css("overflow", "auto");
setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100);
});
}
createDropdownMenu (choice) {
var menuhtml = `<div class="${BDFDB.disCN.selectmenuouter}"><div class="${BDFDB.disCN.selectmenu}">`;
for (var key in this.languages) {
var isSelected = key == choice ? ` ${BDFDB.disCN.selectselected}` : ``;
menuhtml += `<div value="${key}" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectoption + isSelected}" style="flex: 1 1 auto; display:flex;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="flex: 1 1 42%;">${this.languages[key].name}</div><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="flex: 1 1 58%;">${this.getTimestamp(this.languages[key].id)}</div></div>`
}
menuhtml += `</div></div>`;
return $(menuhtml)[0];
}
changeTimestamp (stamp) {
if (!stamp.className || stamp.className.toLowerCase().indexOf("timestamp") == -1 || stamp.classList.contains("complete-timestamp")) return;
let time = stamp.getAttribute("datetime");
if (!time) return;
let choice = BDFDB.getData("creationDateLang", this, "choices");
stamp.classList.add("complete-timestamp");
BDFDB.setInnerText(stamp, this.getTimestamp(this.languages[choice].id, time));
}
getMessageGroup (div) {
var messagegroup = null;
while (messagegroup == null || div.parentElement) {
div = div.parentElement;
if (div.classList && div.classList.contains(BDFDB.disCN.messagegroup)) messagegroup = div;
}
return messagegroup;
}
getMessageData (div, messagegroup) {
var pos = Array.from(messagegroup.querySelectorAll("." + div.className.replace(/ /g, "."))).indexOf(div);
var instance = BDFDB.getReactInstance(messagegroup);
if (!instance) return;
var info = instance.return.stateNode.props.messages;
return info && pos > -1 ? info[pos] : null;
}
getTimestamp (languageid, time) {
let timeobj = time ? time : new Date();
if (typeof time == "string") timeobj = new Date(time);
if (timeobj.toString() == "Invalid Date") timeobj = new Date(parseInt(time));
if (timeobj.toString() == "Invalid Date") return;
var settings = BDFDB.getAllData(this, "settings"), timestring = "";
if (languageid != "own") {
var timestamp = [];
if (settings.displayDate) timestamp.push(timeobj.toLocaleDateString(languageid));
if (settings.displayTime) timestamp.push(settings.cutSeconds ? this.cutOffSeconds(timeobj.toLocaleTimeString(languageid)) : timeobj.toLocaleTimeString(languageid));
if (settings.otherOrder) timestamp.reverse();
timestring = timestamp.length > 1 ? timestamp.join(", ") : (timestamp.length > 0 ? timestamp[0] : "");
if (timestring && settings.forceZeros) timestring = this.addLeadingZeros(timestring);
}
else {
var ownformat = BDFDB.getData("ownFormat", this, "formats");
languageid = BDFDB.getDiscordLanguage().id;
var hour = timeobj.getHours(), minute = timeobj.getMinutes(), second = timeobj.getSeconds(), msecond = timeobj.getMilliseconds(), day = timeobj.getDate(), month = timeobj.getMonth()+1, timemode = "";
if (ownformat.indexOf("$timemode") > -1) {
timemode = hour >= 12 ? "PM" : "AM";
hour = hour % 12;
hour = hour ? hour : 12;
}
timestring = ownformat
.replace("$hour", settings.forceZeros && hour < 10 ? "0" + hour : hour)
.replace("$minute", minute < 10 ? "0" + minute : minute)
.replace("$second", second < 10 ? "0" + second : second)
.replace("$msecond", msecond)
.replace("$timemode", timemode)
.replace("$weekdayL", timeobj.toLocaleDateString(languageid,{weekday: "long"}))
.replace("$weekdayS", timeobj.toLocaleDateString(languageid,{weekday: "short"}))
.replace("$monthnameL", timeobj.toLocaleDateString(languageid,{month: "long"}))
.replace("$monthnameS", timeobj.toLocaleDateString(languageid,{month: "short"}))
.replace("$day", settings.forceZeros && day < 10 ? "0" + day : day)
.replace("$month", settings.forceZeros && month < 10 ? "0" + month : month)
.replace("$year", timeobj.getFullYear());
}
return timestring;
}
cutOffSeconds (timestring) {
return timestring.replace(/(.*):(.*):(.{2})(.*)/, "$1:$2$4");
}
addLeadingZeros (timestring) {
var chararray = timestring.split("");
var numreg = /[0-9]/;
for (var i = 0; i < chararray.length; i++) {
if (!numreg.test(chararray[i-1]) && numreg.test(chararray[i]) && !numreg.test(chararray[i+1])) chararray[i] = "0" + chararray[i];
}
return chararray.join("");
}
setMaxWidth () {
var timestamp = document.querySelector(BDFDB.dotCN.messagetimestampcompact);
if (timestamp) {
var choice = BDFDB.getData("creationDateLang", this, "choices");
var testtimestamp = $(`<time class="${timestamp.className}" style="width: auto !important;">${this.getTimestamp(this.languages[choice].id, new Date(253402124399995))}</time>`);
$(testtimestamp).appendTo(document.body);
var width = testtimestamp.outerWidth() + 5;
testtimestamp.remove();
BDFDB.appendLocalStyle(this.getName() + "CompactCorrection", `
${BDFDB.dotCN.messagetimestampcompact} {
width: ${width}px !important;
}
${BDFDB.dotCN.messagetimestampcompactismentioned} {
width: ${width + 2}px !important;
}
${BDFDB.dotCN.messagemarkupiscompact} {
margin-left: ${width}px !important;
text-indent: -${width}px !important;
}
${BDFDB.dotCN.messageaccessorycompact} {
padding-left: ${width}px !important;
}
`);
}
else {
BDFDB.removeLocalStyle(this.getName() + "CompactCorrection");
}
}
}

View File

@ -0,0 +1,3 @@
# Complete Timestamp - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CompleteTimestamps/CompleteTimestamps.plugin.js)
Replace all timestamps with complete timestamps.

View File

@ -0,0 +1,314 @@
//META{"name":"CreationDate"}*//
class CreationDate {
initConstructor () {
this.labels = {};
this.languages;
this.creationDateMarkup = `<div class="creationDate ${BDFDB.disCN.textrow}"></div>`;
this.css = `
${BDFDB.dotCNS.themelight + BDFDB.dotCN.userpopoutheadernormal} .creationDate {
color: #b9bbbe;
}
${BDFDB.dotCNS.themelight + BDFDB.dotCN.userpopoutheader}:not(${BDFDB.dotCN.userpopoutheadernormal}) .creationDate,
${BDFDB.dotCNS.themedark + BDFDB.dotCN.userpopoutheader} .creationDate {
color: hsla(0,0%,100%,.6);
}
${BDFDB.dotCNS.themelight + BDFDB.dotCN.userprofiletopsectionnormal} .creationDate {
color: hsla(216,4%,74%,.6);
}
${BDFDB.dotCN.themelight} [class*='topSection']:not(${BDFDB.dotCN.userprofiletopsectionnormal}) .creationDate,
${BDFDB.dotCN.themedark} [class*='topSection'] .creationDate {
color: hsla(0,0%,100%,.6);
}`;
this.defaults = {
settings: {
addInUserPopout: {value:true, description:"Add in User Popouts:"},
addInUserProfil: {value:true, description:"Add in User Profil Modal:"},
addCreationTime: {value:true, description:"Display the Time of Creation:"},
forceZeros: {value:false, description:"Force leading Zeros:"}
},
choices: {
creationDateLang: {value:"$discord", description:"Creation Date Format:"}
}
};
}
getName () {return "CreationDate";}
getDescription () {return "Displays the Creation Date of an Account in the UserPopout and UserModal.";}
getVersion () {return "1.1.8";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var choices = BDFDB.getAllData(this, "choices");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
for (let key in choices) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 30%; line-height: 38px;">${this.defaults.choices[key].description}</h3><div class="${BDFDB.disCN.selectwrap}" style="flex: 1 1 70%;"><div class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}" type="${key}" value="${choices[key]}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal} languageName" style="flex: 1 1 42%; padding:0;">${this.languages[choices[key]].name}</div><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal} languageTimestamp" style="flex: 1 1 58%; padding:0;">${this.getCreationTime(this.languages[choices[key]].id)}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {
this.updateSettings(settingspanel);
var choices = BDFDB.getAllData(this, "choices");
for (let key in choices) {
settingspanel.querySelector(`${BDFDB.dotCN.select}[type='${key}'] .languageTimestamp`).innerText = this.getCreationTime(this.languages[choices[key]].id);
}
})
.on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu(e);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.userpopout)) {
if (BDFDB.getData("addInUserPopout", this, "settings")) this.addCreationDate(node.querySelector(BDFDB.dotCN.userpopoutheadertext));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"userPopoutObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector("[class*='topSection']")) {
if (BDFDB.getData("addInUserProfil", this, "settings")) this.addCreationDate(node.querySelector(BDFDB.dotCN.userprofileheaderinfo));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.app + " ~ [class^='theme-']:not([class*='popouts'])", {name:"userProfilModalObserver",instance:observer}, {childList: true});
this.languages = Object.assign({},BDFDB.languages);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
openDropdownMenu (e) {
var selectControl = e.currentTarget;
var selectWrap = selectControl.parentElement;
if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return;
selectWrap.classList.add(BDFDB.disCN.selectisopen);
$("li").has(selectWrap).css("overflow", "visible");
var type = selectWrap.getAttribute("type");
var selectMenu = this.createDropdownMenu(selectWrap.getAttribute("value"), type);
selectWrap.appendChild(selectMenu);
$(selectMenu).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => {
var language = e2.currentTarget.getAttribute("value");
selectWrap.setAttribute("value", language);
selectControl.querySelector(".languageName").innerText = this.languages[language].name;
selectControl.querySelector(".languageTimestamp").innerText = this.getCreationTime(language);
BDFDB.saveData(type, language, this, "choices");
});
$(document).on("mousedown.select" + this.getName(), (e2) => {
if (e2.target.parentElement == selectMenu) return;
$(document).off("mousedown.select" + this.getName());
selectMenu.remove();
$("li").has(selectWrap).css("overflow", "auto");
setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100);
});
}
createDropdownMenu (choice, type) {
var menuhtml = `<div class="${BDFDB.disCN.selectmenuouter}"><div class="${BDFDB.disCN.selectmenu}">`;
for (var key in this.languages) {
var isSelected = key == choice ? ` ${BDFDB.disCN.selectselected}` : ``;
menuhtml += `<div value="${key}" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectoption + isSelected}" style="flex: 1 1 auto; display:flex;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="flex: 1 1 42%;">${this.languages[key].name}</div><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="flex: 1 1 58%;">${this.getCreationTime(this.languages[key].id)}</div></div>`
}
menuhtml += `</div></div>`;
return $(menuhtml)[0];
}
addCreationDate (container) {
if (!container) return;
var info = BDFDB.getKeyInformation({"node":container,"key":"user"});
if (info) {
var creationDate = $(this.creationDateMarkup);
var choice = BDFDB.getData("creationDateLang", this, "choices");
creationDate.text(this.labels.createdat_text + " " + this.getCreationTime(this.languages[choice].id, info.createdAt));
var nametag = container.querySelector(BDFDB.dotCN.nametag);
container.insertBefore(creationDate[0], nametag ? nametag.nextSibling : null);
}
}
getCreationTime (languageid, timestamp = new Date()) {
var settings = BDFDB.getAllData(this, "settings");
var timestring = settings.addCreationTime ? timestamp.toLocaleString(languageid) : timestamp.toLocaleDateString(languageid);
if (timestring && settings.forceZeros) timestring = this.addLeadingZeros(timestring);
return timestring;
}
addLeadingZeros (timestring) {
var chararray = timestring.split("");
var numreg = /[0-9]/;
for (var i = 0; i < chararray.length; i++) {
if (!numreg.test(chararray[i-1]) && numreg.test(chararray[i]) && !numreg.test(chararray[i+1])) chararray[i] = "0" + chararray[i];
}
return chararray.join("");
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
createdat_text: "Izrađen"
};
case "da": //danish
return {
createdat_text: "Oprettet den"
};
case "de": //german
return {
createdat_text: "Erstellt am"
};
case "es": //spanish
return {
createdat_text: "Creado el"
};
case "fr": //french
return {
createdat_text: "Créé le"
};
case "it": //italian
return {
createdat_text: "Creato il"
};
case "nl": //dutch
return {
createdat_text: "Gemaakt op"
};
case "no": //norwegian
return {
createdat_text: "Opprettet på"
};
case "pl": //polish
return {
createdat_text: "Utworzono"
};
case "pt-BR": //portuguese (brazil)
return {
createdat_text: "Criado em"
};
case "fi": //finnish
return {
createdat_text: "Luotu"
};
case "sv": //swedish
return {
createdat_text: "Skapat den"
};
case "tr": //turkish
return {
createdat_text: "Oluşturma tarihi"
};
case "cs": //czech
return {
createdat_text: "Vytvořeno dne"
};
case "bg": //bulgarian
return {
createdat_text: "Създадена на"
};
case "ru": //russian
return {
createdat_text: "Создано"
};
case "uk": //ukrainian
return {
createdat_text: "Створено"
};
case "ja": //japanese
return {
createdat_text: "作成日"
};
case "zh-TW": //chinese (traditional)
return {
createdat_text: "創建於"
};
case "ko": //korean
return {
createdat_text: "생성 일"
};
default: //default: english
return {
createdat_text: "Created on"
};
}
}
}

View File

@ -0,0 +1,3 @@
# Creation Date - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CreationDate/CreationDate.plugin.js)
Displays the Creation Date of an Account in the UserPopout and UserModal.

View File

@ -0,0 +1,252 @@
//META{"name":"DisplayServersAsChannels"}*//
class DisplayServersAsChannels {
initConstructor () {
this.verificationBadgeMarkup =
`<svg class="DSAC-verification-badge" name="Verified" width="24" height="24" viewBox="0 0 20 20">
<g fill="none" fill-rule="evenodd">
<path fill="transparent" d="M10,19.9894372 C10.1068171,19.9973388 10.2078869,20.000809 10.3011305,19.9998419 C11.2600164,19.8604167 12.3546966,19.5885332 12.8510541,19.0579196 C13.25685,18.6241176 13.617476,18.0901301 13.7559228,17.5412583 C14.9847338,18.4452692 17.0357846,18.1120142 18.1240732,16.9486174 C19.1632035,15.8377715 18.521192,14.1691402 18.1240732,13.1586037 C18.4557396,12.9959068 18.8016154,12.6966801 19.0750308,12.4043949 C19.7126372,11.7227841 20.0201294,10.9139249 19.9989792,10.0282152 C20.0201294,9.14250542 19.7126372,8.3336462 19.0750308,7.65203538 C18.8016154,7.35975019 18.4557396,7.06052352 18.1240732,6.89782664 C18.521192,5.88729007 19.1632035,4.21865882 18.1240732,3.10781287 C17.0357846,1.94441607 14.9847338,1.61116112 13.7559228,2.51517206 C13.617476,1.96630024 13.25685,1.4323127 12.8510541,0.998510722 C12.3546966,0.467897141 11.2584098,0.139640848 10.2995239,0.036840309 C10.2065991,-0.000647660524 10.1059015,0.00279555358 9.99948865,0.0106399384 C9.87772075,0.00268415336 9.76807998,-0.00081194858 9.67455589,0.000158000197 C8.88885259,0.157529668 7.63153446,0.482616331 7.14894593,0.998510722 C6.74314998,1.4323127 6.382524,1.96630024 6.24407717,2.51517206 C5.01526618,1.61116112 2.96421535,1.94441607 1.87592682,3.10781287 C0.836796482,4.21865882 1.47880798,5.88729007 1.87592682,6.89782664 C1.54426039,7.06052352 1.19838464,7.35975019 0.924969216,7.65203538 C0.287362828,8.3336462 -0.0201294289,9.14250542 0.00102081603,10.0282151 C-0.0201294289,10.9139249 0.287362828,11.7227841 0.924969216,12.4043949 C1.19838464,12.6966801 1.54426039,12.9959068 1.87592682,13.1586037 C1.47880798,14.1691402 0.836796482,15.8377715 1.87592682,16.9486174 C2.96421535,18.1120142 5.01526618,18.4452692 6.24407717,17.5412583 C6.382524,18.0901301 6.74314998,18.6241176 7.14894593,19.0579196 C7.63153446,19.573814 8.89045919,19.8426283 9.6761625,19.9541287 C9.7694061,20.000809 9.87866986,19.9973388 10,19.9894372 Z"/>
<path fill="#4f545c" d="M10.0004091,17.9551224 C10.0858672,17.9614327 10.1667272,17.964204 10.2413259,17.9634317 C11.0084737,17.8520863 11.8842627,17.6349594 12.281369,17.2112099 C12.6060224,16.8647745 12.8945379,16.4383305 13.005301,16 C13.9884001,16.7219456 15.6293247,16.4558073 16.5,15.5267154 C17.3313468,14.6395908 16.8177113,13.3070173 16.5,12.5 C16.7653467,12.3700698 17.0420615,12.1311066 17.260805,11.8976868 C17.7709162,11.3533505 18.0169226,10.7073933 18.0000015,10.0000632 C18.0169226,9.29273289 17.7709162,8.64677569 17.260805,8.10243942 C17.0420615,7.86901966 16.7653467,7.63005642 16.5,7.50012624 C16.8177113,6.69310896 17.3313468,5.36053545 16.5,4.47341082 C15.6293247,3.54431894 13.9884001,3.27818062 13.005301,4.00012624 C12.8945379,3.5617957 12.6060224,3.13535178 12.281369,2.78891632 C11.8842627,2.36516686 11.0071884,2.10302048 10.2400405,2.02092369 C10.1656968,1.99098569 10.0851346,1.99373545 10,2 C9.9025807,1.99364649 9.8148636,1.99085449 9.7400405,1.9916291 C9.11144571,2.11730654 8.10553978,2.37692165 7.71944921,2.78891632 C7.39479585,3.13535178 7.10628031,3.5617957 6.99551718,4.00012624 C6.01241812,3.27818062 4.37149355,3.54431894 3.5008182,4.47341082 C2.66947142,5.36053545 3.18310688,6.69310896 3.5008182,7.50012624 C3.23547149,7.63005642 2.95875674,7.86901966 2.74001321,8.10243942 C2.22990202,8.64677569 1.98389563,9.29273289 2.00081669,10.0000631 C1.98389563,10.7073933 2.22990202,11.3533505 2.74001321,11.8976868 C2.95875674,12.1311066 3.23547149,12.3700698 3.5008182,12.5 C3.18310688,13.3070173 2.66947142,14.6395908 3.5008182,15.5267154 C4.37149355,16.4558073 6.01241812,16.7219456 6.99551718,16 C7.10628031,16.4383305 7.39479585,16.8647745 7.71944921,17.2112099 C8.10553978,17.6232046 9.11273107,17.8378805 9.74132585,17.926925 C9.81592455,17.964204 9.90334002,17.9614327 10.0004091,17.9551224 Z"/>
<path fill="#ffffff" d="M8.84273967,12.8167603 L13.8643,7.7952 C14.0513,7.6072 14.0513,7.3042 13.8643,7.1172 C13.6773,6.9312 13.3743,6.9312 13.1863,7.1172 L8.52303089,11.78139 L6.8883,10.1475 C6.6843,9.9445 6.3553,9.9445 6.1523,10.1475 C5.9493,10.3515 5.9493,10.6805 6.1523,10.8835 L8.08381122,12.8160053 C8.09561409,12.8309877 8.10844368,12.8454178 8.1223,12.8592 C8.3093,13.0472 8.6123,13.0472 8.8003,12.8592 L8.82157566,12.8379243 C8.82518839,12.8345112 8.82876362,12.8310364 8.8323,12.8275 C8.83584168,12.8239583 8.83932157,12.820378 8.84273967,12.8167603 Z"/>
</g>
</svg>`;
this.css = `
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled,
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.scrollerwrapold},
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guilds} {
width: 160px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled,
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.scrollerwrapold},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guilds} {
width: 240px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guilds}::-webkit-scrollbar-track-piece {
background-color: rgb(27, 29, 32);
border-color: rgb(32, 34, 37);
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guilds}::-webkit-scrollbar-thumb {
background-color: rgb(17, 19, 22);
border-color: rgb(32, 34, 37);
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guild} {
margin-left: 55px;
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.friendsonline},
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled #RANbutton-frame {
margin-left: 40px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner} a,
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCNS.guildinner + BDFDB.dotCN.avataricon},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildserror} {
margin-left: 0px;
height: 32px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guild},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.friendsonline} {
margin-left: 80px;
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator},
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild},
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildserror} {
width: 130px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildserror} {
width: 215px;
box-sizing: border-box;
opacity: 0.4;
padding-left: 5px;
border-radius: 3px;
display: flex !important;
align-items: center;
justify-content: flex-start;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildunread} {
opacity: 0.7;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild}:not(${BDFDB.dotCN.guildselected}):hover {
opacity: 0.9;
background-color: rgba(79,84,92,.3);
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildselected} {
opacity: 1;
background-color: rgba(79,84,92,.6);
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild} > div[draggable] {
flex: 1 1 auto;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildaudio} > div[draggable],
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildvideo} > div[draggable] {
padding-right: 20px;
margin-right: 5px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildaudio} > div[draggable] {
background: url(/assets/382ca83d9dc390c4be715248bb4864f4.svg) right no-repeat !important;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildvideo} > div[draggable] {
background: url(/assets/c46f51f425c824899b6138ea2b61b41d.svg) right no-repeat !important;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.badge} {
position: static;
margin-right: 5px;
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner} {
width: unset;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner} {
background: transparent !important;
border-radius: 0px !important;
position: relative;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCNS.guildaudio + BDFDB.dotCN.guildinner}:after,
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCNS.guildvideo + BDFDB.dotCN.guildinner}:after {
display: none !important;
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.avataricon} {
font-size: 14px !important;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.avataricon} {
background: transparent !important;
font-size: 16px !important;
line-height: 32px;
white-space: nowrap;
text-align: left;
position: absolute;
left: 0;
right: 0;
width: unset;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner} .DSAC-verification-badge {
position: absolute;
left: 0;
top: 4px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildinner} .DSAC-verification-badge + ${BDFDB.dotCN.avataricon} {
left: 25px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildserror} {
border-radius: 3px;
margin-left: -5px;
line-height: 32px;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCNS.guild + BDFDB.dotCN.guildserror},
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCN.guildsadd} {
display: block !important;
}
.bd-minimal ${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCNS.guildsadd + BDFDB.dotCN.guildsaddinner} {
top: 0;
}
${BDFDB.dotCN.guildswrapper}.DSAC-styled ${BDFDB.dotCN.guildseparator} ~ ${BDFDB.dotCN.guild + BDFDB.dotCNS.guildsadd + BDFDB.dotCN.guildsaddinner} {
top: -5px;
}`;
}
getName () {return "DisplayServersAsChannels";}
getDescription () {return "Display servers in a similar way as channels.";}
getVersion () {return "1.1.0";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
var addedNodes = change.addedNodes;
if (change.attributeName == "class" && change.oldValue && change.oldValue.indexOf(BDFDB.disCN.guildplaceholder) > -1) addedNodes = [change.target];
if (change.attributeName == "draggable" && change.oldValue && change.oldValue == "false") addedNodes = [change.target.parentElement];
if (addedNodes) {
addedNodes.forEach((node) => {
if (node && node.classList && node.classList.contains(BDFDB.disCN.guild) && !node.querySelector(BDFDB.dotCN.guildserror)) {
var id = BDFDB.getIdOfServer(node);
if (id) this.changeServer(BDFDB.getDivOfServer(id));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.guilds, {name:"serverListObserver",instance:observer}, {childList: true, subtree:true, attributes:true, attributeFilter: ["class", "draggable"], attributeOldValue: true});
BDFDB.readServerList().forEach(serverObj => {
this.changeServer(serverObj);
});
$(BDFDB.dotCN.guildswrapper).addClass("DSAC-styled");
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.readServerList().forEach(serverObj => {
this.resetServer(serverObj);
});
$(".DSAC-styled").removeClass("DSAC-styled");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
changeServer (serverObj) {
if (!serverObj) return;
var avatar = serverObj.div.querySelector(BDFDB.dotCN.avataricon);
if (avatar) {
avatar.DSAColdName = avatar.textContent;
avatar.textContent = serverObj.name;
if (serverObj.features.has("VERIFIED")) $(this.verificationBadgeMarkup).insertBefore(avatar);
$(serverObj.div)
.off("." + this.getName())
.on("mouseenter." + this.getName(), () => {
BDFDB.appendLocalStyle("HideAllToolTips" + this.getName(), `${BDFDB.dotCN.tooltip} {display: none !important;}`);
})
.on("mouseleave." + this.getName(), () => {
BDFDB.removeLocalStyle("HideAllToolTips" + this.getName());
});
}
}
resetServer (serverObj) {
if (!serverObj) return;
var avatar = serverObj.div.querySelector(BDFDB.dotCN.avataricon);
if (avatar) {
avatar.textContent = avatar.DSAColdName;
$(serverObj.div).off("." + this.getName()).find(".DSAC-verification-badge").remove();
}
}
}

View File

@ -0,0 +1,3 @@
# Display Servers As Channels - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/DisplayServersAsChannels/DisplayServersAsChannels.plugin.js)
Display servers in a similar way as channels.

View File

@ -0,0 +1,657 @@
//META{"name":"EditChannels"}*//
class EditChannels {
initConstructor () {
this.labels = {};
this.channelContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} localchannelsettings-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>REPLACE_context_localchannelsettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.channelContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} editchannels-submenu">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} channelsettings-item">
<span>REPLACE_submenu_channelsettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
<div class="${BDFDB.disCN.contextmenuitem} resetsettings-item ${BDFDB.disCN.contextmenuitemdisabled}">
<span>REPLACE_submenu_resetsettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>
</div>`;
this.channelSettingsModalMarkup =
`<span class="editchannels-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizemedium}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">REPLACE_modal_header_text</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_channelname_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-channelname"></div>
</div>
<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCNS.modaldividerdefault + BDFDB.disCN.margintop20}"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_colorpicker1_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="swatches1"></div>
</div>
</div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-save ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_save_text</div>
</button>
</div>
</div>
</div>
</div>
</span>`;
this.defaults = {
settings: {
changeInChannelHeader: {value:true, description:"Change in Channel Header."}
}
};
}
getName () {return "EditChannels";}
getDescription () {return "Allows you to rename and recolor channelnames.";}
getVersion () {return "3.7.6";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Reset all Channels.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("click", ".reset-button", () => {this.resetAll();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.LastGuildStore = BDFDB.WebModules.findByProperties(["getLastSelectedGuildId"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.attributeName == "class") {
var node = change.target;
if (node.className && node.className.length > -1 && node.className.includes("wrapper") && $("[custom-editchannels]").has(node)[0]) {
let info = BDFDB.getKeyInformation({"node":node, "key":"channel"});
if (info) this.loadChannel(BDFDB.getDivOfChannel(info.id));
}
}
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.classList && (node.classList.contains(BDFDB.disCN.channelcontainerdefault) || node.classList.contains(BDFDB.disCN.categorycontainerdefault))) {
let info = BDFDB.getKeyInformation({"node":node, "key":"channel"});
if (info) this.loadChannel(BDFDB.getDivOfChannel(info.id));
}
if (node.className && node.className.length > -1 && node.className.includes("container-")) {
for (let channel of node.querySelectorAll(BDFDB.dotCNC.channelcontainerdefault + BDFDB.dotCN.categorycontainerdefault)) {
let info = BDFDB.getKeyInformation({"node":channel, "key":"channel"});
if (info) this.loadChannel(BDFDB.getDivOfChannel(info.id));
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.channels, {name:"channelListObserver",instance:observer}, {childList: true, attributes:true, subtree: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"channelContextObserver",instance:observer}, {childList: true});
this.loadAllChannels();
this.changeChannelHeader();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
this.resetAllChannels();
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
$(`${BDFDB.dotCN.channelheadertitletext}[custom-editchannelsheader]`).find(BDFDB.dotCN.channelheaderchannelname + BDFDB.dotCN.channelheaderprivate).css("color", "").css("background-color", "").parent().removeAttr("custom-editchannelsheader");
this.loadAllChannels();
setImmediate(() => {this.changeChannelHeader();}); //setImmediate so EditChannels sets the color after EditUsers set it back to white
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
resetAll () {
if (confirm("Are you sure you want to reset all channels?")) {
BDFDB.removeAllData(this, "channels");
this.resetAllChannels();
}
}
changeLanguageStrings () {
this.channelContextEntryMarkup = this.channelContextEntryMarkup.replace("REPLACE_context_localchannelsettings_text", this.labels.context_localchannelsettings_text);
this.channelContextSubMenuMarkup = this.channelContextSubMenuMarkup.replace("REPLACE_submenu_channelsettings_text", this.labels.submenu_channelsettings_text);
this.channelContextSubMenuMarkup = this.channelContextSubMenuMarkup.replace("REPLACE_submenu_resetsettings_text", this.labels.submenu_resetsettings_text);
this.channelSettingsModalMarkup = this.channelSettingsModalMarkup.replace("REPLACE_modal_header_text", this.labels.modal_header_text);
this.channelSettingsModalMarkup = this.channelSettingsModalMarkup.replace("REPLACE_modal_channelname_text", this.labels.modal_channelname_text);
this.channelSettingsModalMarkup = this.channelSettingsModalMarkup.replace("REPLACE_modal_colorpicker1_text", this.labels.modal_colorpicker1_text);
this.channelSettingsModalMarkup = this.channelSettingsModalMarkup.replace("REPLACE_btn_save_text", this.labels.btn_save_text);
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".localchannelsettings-item")) return;
var info = BDFDB.getKeyInformation({"node":context, "key":"channel"});
if (info && BDFDB.getKeyInformation({"node":context, "key":"displayName", "value":"ChannelDeleteGroup"})) {
$(context).append(this.channelContextEntryMarkup)
.on("mouseenter", ".localchannelsettings-item", (e) => {
this.createContextSubMenu(info, e, context);
});
BDFDB.updateContextPosition(context);
}
}
createContextSubMenu (info, e, context) {
var channelContextSubMenu = $(this.channelContextSubMenuMarkup);
channelContextSubMenu
.on("click", ".channelsettings-item", () => {
$(context).hide();
this.showChannelSettings(info);
});
if (BDFDB.loadData(info.id, this, "channels")) {
channelContextSubMenu
.find(".resetsettings-item")
.removeClass(BDFDB.disCN.contextmenuitemdisabled)
.on("click", () => {
$(context).hide();
this.removeChannelData(info);
});
}
BDFDB.appendSubMenu(e.currentTarget, channelContextSubMenu);
}
showChannelSettings (info) {
var channelObj = BDFDB.getDivOfChannel(info.id);
var data = BDFDB.loadData(info.id, this, "channels");
var name = data ? data.name : null;
var color = data ? data.color : null;
var channelSettingsModal = $(this.channelSettingsModalMarkup);
channelSettingsModal.find(BDFDB.dotCN.modalguildname).text(info.name);
channelSettingsModal.find("#input-channelname").val(name);
channelSettingsModal.find("#input-channelname").attr("placeholder", info.name);
BDFDB.setColorSwatches(color, channelSettingsModal.find(".swatches1"), "swatch1");
BDFDB.appendModal(channelSettingsModal);
channelSettingsModal
.on("click", ".btn-save", (event) => {
event.preventDefault();
name = null;
if (channelSettingsModal.find("#input-channelname").val()) {
if (channelSettingsModal.find("#input-channelname").val().trim().length > 0) {
name = channelSettingsModal.find("#input-channelname").val().trim();
}
}
color = BDFDB.getSwatchColor("swatch1");
if (color) {
if (color[0] < 30 && color[1] < 30 && color[2] < 30) BDFDB.colorCHANGE(color, 30);
else if (color[0] > 225 && color[1] > 225 && color[2] > 225) BDFDB.colorCHANGE(color, -30);
}
if (name == null && color == null) {
this.removeChannelData(info.id);
}
else {
BDFDB.saveData(info.id, {name,color}, this, "channels");
this.loadChannel(channelObj);
this.changeChannelHeader();
}
});
channelSettingsModal.find("#input-channelname").focus();
}
removeChannelData (info) {
this.resetChannel(BDFDB.getDivOfChannel(info.id));
BDFDB.removeData(info.id, this, "channels");
this.changeChannelHeader();
}
resetChannel (channelObj) {
if (!channelObj || !channelObj.div) return;
var channel = channelObj.div.querySelector(BDFDB.dotCNC.channelname + BDFDB.dotCN.categorycolortransition);
$(channelObj.div)
.removeAttr("custom-editchannels");
$(channel)
.css("color", "");
BDFDB.setInnerText(channel, channelObj.name);
}
loadChannel (channelObj) {
if (!channelObj || !channelObj.div) return;
var channel = channelObj.div.querySelector(BDFDB.dotCNC.channelname + BDFDB.dotCN.categorycolortransition);
var data = BDFDB.loadData(channelObj.id, this, "channels");
if (data) {
var name = data.name ? data.name : channelObj.name;
var color = data.color ? this.chooseColor(channel, data.color) : "";
$(channelObj.div)
.attr("custom-editchannels", true);
$(channel)
.css("color", color);
BDFDB.setInnerText(channel, name);
}
}
loadAllChannels () {
for (let channelObj of BDFDB.readChannelList()) {
this.loadChannel(channelObj);
}
}
changeChannelHeader () {
if (BDFDB.getData("changeInChannelHeader", this, "settings") && this.LastGuildStore.getGuildId() ) {
var channelHeader = document.querySelector(BDFDB.dotCNS.channelheadertitle + BDFDB.dotCN.channelheadertitletext);
if (!channelHeader) return;
var channel = channelHeader.querySelector(BDFDB.dotCN.channelheaderchannelname);
if (!channel) return;
var info = BDFDB.getKeyInformation({"node":channelHeader,"key":"channel"});
if (info) {
var data = BDFDB.loadData(info.id, this, "channels");
var name = data && data.name ? data.name : info.name;
var color = data && data.color ? BDFDB.color2RGB(data.color) : "";
BDFDB.setInnerText(channel, name);
$(channel).css("color", color);
if (data && (data.name || data.color)) {
$(channelHeader).attr("custom-editchannelsheader", true);
}
else {
$(channelHeader).removeAttr("custom-editchannelsheader");
}
}
}
}
resetAllChannels () {
document.querySelectorAll("[custom-editchannels]").forEach(channelDiv => {
var info = BDFDB.getKeyInformation({"node":channelDiv, "key":"channel"});
if (info) this.resetChannel({div:channelDiv,info});
});
var channelHeader = document.querySelector("[custom-editchannelsheader]");
if (channelHeader) {
var info = BDFDB.getKeyInformation({"node":channelHeader, "key":"channel"});
if (info) {
var channel = channelHeader.querySelector(BDFDB.dotCN.channelheaderchannelname);
BDFDB.setInnerText(channel, info.name);
$(channel).css("color", "");
$(channelHeader).removeAttr("custom-editchannelsheader");
}
}
}
chooseColor (channel, color) {
if (color && channel && channel.className) {
if (channel.className.indexOf("nameMuted") > -1 || channel.className.indexOf("nameLocked") > -1) {
color = BDFDB.colorCHANGE(color, -50);
}
if (channel.className.indexOf("nameDefault") > -1) {
color = color;
}
if (channel.className.indexOf("nameSelected") > -1 || channel.className.indexOf("nameHovered") > -1 || channel.className.indexOf("nameUnread") > -1) {
color = BDFDB.colorCHANGE(color, 50);
}
return BDFDB.color2RGB(color);
}
return null;
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
context_localchannelsettings_text: "Postavke lokalnih kanala",
submenu_channelsettings_text: "Promijeni postavke",
submenu_resetsettings_text: "Vraćanje kanala",
modal_header_text: "Postavke lokalnih kanala",
modal_channelname_text: "Naziv lokalnog kanala",
modal_colorpicker1_text: "Boja lokalnog kanala",
btn_cancel_text: "Prekid",
btn_save_text: "Uštedjeti"
};
case "da": //danish
return {
context_localchannelsettings_text: "Lokal kanalindstillinger",
submenu_channelsettings_text: "Skift indstillinger",
submenu_resetsettings_text: "Nulstil kanal",
modal_header_text: "Lokal kanalindstillinger",
modal_channelname_text: "Lokalt kanalnavn",
modal_colorpicker1_text: "Lokal kanalfarve",
btn_cancel_text: "Afbryde",
btn_save_text: "Spare"
};
case "de": //german
return {
context_localchannelsettings_text: "Lokale Kanaleinstellungen",
submenu_channelsettings_text: "Einstellungen ändern",
submenu_resetsettings_text: "Kanal zurücksetzen",
modal_header_text: "Lokale Kanaleinstellungen",
modal_channelname_text: "Lokaler Kanalname",
modal_colorpicker1_text: "Lokale Kanalfarbe",
btn_cancel_text: "Abbrechen",
btn_save_text: "Speichern"
};
case "es": //spanish
return {
context_localchannelsettings_text: "Ajustes local de canal",
submenu_channelsettings_text: "Cambiar ajustes",
submenu_resetsettings_text: "Restablecer canal",
modal_header_text: "Ajustes local de canal",
modal_channelname_text: "Nombre local del canal",
modal_colorpicker1_text: "Color local del canal",
btn_cancel_text: "Cancelar",
btn_save_text: "Guardar"
};
case "fr": //french
return {
context_localchannelsettings_text: "Paramètres locale du canal",
submenu_channelsettings_text: "Modifier les paramètres",
submenu_resetsettings_text: "Réinitialiser le canal",
modal_header_text: "Paramètres locale du canal",
modal_channelname_text: "Nom local du canal",
modal_colorpicker1_text: "Couleur locale de la chaîne",
btn_cancel_text: "Abandonner",
btn_save_text: "Enregistrer"
};
case "it": //italian
return {
context_localchannelsettings_text: "Impostazioni locale canale",
submenu_channelsettings_text: "Cambia impostazioni",
submenu_resetsettings_text: "Ripristina canale",
modal_header_text: "Impostazioni locale canale",
modal_channelname_text: "Nome locale canale",
modal_colorpicker1_text: "Colore locale canale",
btn_cancel_text: "Cancellare",
btn_save_text: "Salvare"
};
case "nl": //dutch
return {
context_localchannelsettings_text: "Lokale kanaalinstellingen",
submenu_channelsettings_text: "Verandere instellingen",
submenu_resetsettings_text: "Reset kanaal",
modal_header_text: "Lokale kanaalinstellingen",
modal_channelname_text: "Lokale kanaalnaam",
modal_colorpicker1_text: "Lokale kanaalkleur",
btn_cancel_text: "Afbreken",
btn_save_text: "Opslaan"
};
case "no": //norwegian
return {
context_localchannelsettings_text: "Lokal kanalinnstillinger",
submenu_channelsettings_text: "Endre innstillinger",
submenu_resetsettings_text: "Tilbakestill kanal",
modal_header_text: "Lokal kanalinnstillinger",
modal_channelname_text: "Lokalt kanalnavn",
modal_colorpicker1_text: "Lokal kanalfarge",
btn_cancel_text: "Avbryte",
btn_save_text: "Lagre"
};
case "pl": //polish
return {
context_localchannelsettings_text: "Lokalne ustawienia kanału",
submenu_channelsettings_text: "Zmień ustawienia",
submenu_resetsettings_text: "Resetuj ustawienia",
modal_header_text: "Lokalne ustawienia kanału",
modal_channelname_text: "Lokalna nazwa kanału",
modal_colorpicker1_text: "Lokalny kolor kanału",
btn_cancel_text: "Anuluj",
btn_save_text: "Zapisz"
};
case "pt-BR": //portuguese (brazil)
return {
context_localchannelsettings_text: "Configurações local do canal",
submenu_channelsettings_text: "Mudar configurações",
submenu_resetsettings_text: "Redefinir canal",
modal_header_text: "Configurações local do canal",
modal_channelname_text: "Nome local do canal",
modal_colorpicker1_text: "Cor local do canal",
btn_cancel_text: "Cancelar",
btn_save_text: "Salvar"
};
case "fi": //finnish
return {
context_localchannelsettings_text: "Paikallinen kanavan asetukset",
submenu_channelsettings_text: "Vaihda asetuksia",
submenu_resetsettings_text: "Nollaa kanava",
modal_header_text: "Paikallinen kanavan asetukset",
modal_channelname_text: "Paikallinen kanavanimi",
modal_colorpicker1_text: "Paikallinen kanavanväri",
btn_cancel_text: "Peruuttaa",
btn_save_text: "Tallentaa"
};
case "sv": //swedish
return {
context_localchannelsettings_text: "Lokal kanalinställningar",
submenu_channelsettings_text: "Ändra inställningar",
submenu_resetsettings_text: "Återställ kanal",
modal_header_text: "Lokal kanalinställningar",
modal_channelname_text: "Lokalt kanalnamn",
modal_colorpicker1_text: "Lokal kanalfärg",
btn_cancel_text: "Avbryta",
btn_save_text: "Spara"
};
case "tr": //turkish
return {
context_localchannelsettings_text: "Yerel Kanal Ayarları",
submenu_channelsettings_text: "Ayarları Değiştir",
submenu_resetsettings_text: "Kanal Sıfırla",
modal_header_text: "Yerel Kanal Ayarları",
modal_channelname_text: "Yerel Kanal Adı",
modal_colorpicker1_text: "Yerel Kanal Rengi",
btn_cancel_text: "Iptal",
btn_save_text: "Kayıt"
};
case "cs": //czech
return {
context_localchannelsettings_text: "Místní nastavení kanálu",
submenu_channelsettings_text: "Změnit nastavení",
submenu_resetsettings_text: "Obnovit kanál",
modal_header_text: "Místní nastavení kanálu",
modal_channelname_text: "Místní název kanálu",
modal_colorpicker1_text: "Místní barvy kanálu",
btn_cancel_text: "Zrušení",
btn_save_text: "Uložit"
};
case "bg": //bulgarian
return {
context_localchannelsettings_text: "Настройки за локални канали",
submenu_channelsettings_text: "Промяна на настройките",
submenu_resetsettings_text: "Възстановяване на канал",
modal_header_text: "Настройки за локални канали",
modal_channelname_text: "Локално име на канал",
modal_colorpicker1_text: "Локален цветен канал",
btn_cancel_text: "Зъбести",
btn_save_text: "Cпасяване"
};
case "ru": //russian
return {
context_localchannelsettings_text: "Настройки локального канала",
submenu_channelsettings_text: "Изменить настройки",
submenu_resetsettings_text: "Сбросить канал",
modal_header_text: "Настройки локального канала",
modal_channelname_text: "Имя локального канала",
modal_colorpicker1_text: "Цвет локального канала",
btn_cancel_text: "Отмена",
btn_save_text: "Cпасти"
};
case "uk": //ukrainian
return {
context_localchannelsettings_text: "Налаштування локального каналу",
submenu_channelsettings_text: "Змінити налаштування",
submenu_resetsettings_text: "Скидання каналу",
modal_header_text: "Налаштування локального каналу",
modal_channelname_text: "Локальне ім'я каналу",
modal_colorpicker1_text: "Колір місцевого каналу",
btn_cancel_text: "Скасувати",
btn_save_text: "Зберегти"
};
case "ja": //japanese
return {
context_localchannelsettings_text: "ローカルチャネル設定",
submenu_channelsettings_text: "設定を変更する",
submenu_resetsettings_text: "チャネルをリセットする",
modal_header_text: "ローカルチャネル設定",
modal_channelname_text: "ローカルチャネル名",
modal_colorpicker1_text: "ローカルチャネルの色",
btn_cancel_text: "キャンセル",
btn_save_text: "セーブ"
};
case "zh-TW": //chinese (traditional)
return {
context_localchannelsettings_text: "本地頻道設置",
submenu_channelsettings_text: "更改設置",
submenu_resetsettings_text: "重置通道",
modal_header_text: "本地頻道設置",
modal_channelname_text: "本地頻道名稱",
modal_colorpicker1_text: "本地頻道顏色",
btn_cancel_text: "取消",
btn_save_text: "保存"
};
case "ko": //korean
return {
context_localchannelsettings_text: "로컬 채널 설정",
submenu_channelsettings_text: "설정 변경",
submenu_resetsettings_text: "채널 재설정",
modal_header_text: "로컬 채널 설정",
modal_channelname_text: "로컬 채널 이름",
modal_colorpicker1_text: "지역 채널 색깔",
btn_cancel_text: "취소",
btn_save_text: "저장"
};
default: //default: english
return {
context_localchannelsettings_text: "Local Channelsettings",
submenu_channelsettings_text: "Change Settings",
submenu_resetsettings_text: "Reset Channel",
modal_header_text: "Local Channelsettings",
modal_channelname_text: "Local Channelname",
modal_colorpicker1_text: "Local Channelcolor",
btn_cancel_text: "Cancel",
btn_save_text: "Save"
};
}
}
}

View File

@ -0,0 +1,6 @@
# Edit Channels - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditChannels/EditChannels.plugin.js)
Adds two options on your channel context menu.
- You can open a popout, where you can change the local name and color for the selected channel.
- You can set the selected channel back to its original state.

View File

@ -0,0 +1,985 @@
//META{"name":"EditServers"}*//
class EditServers {
initConstructor () {
this.labels = {};
this.serverDragged = false;
this.serverContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} localserversettings-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>REPLACE_context_localserversettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.serverContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} editservers-submenu">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} serversettings-item">
<span>REPLACE_submenu_serversettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
<div class="${BDFDB.disCN.contextmenuitem} resetsettings-item ${BDFDB.disCN.contextmenuitemdisabled}">
<span>REPLACE_submenu_resetsettings_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>
</div>`;
this.serverSettingsModalMarkup =
`<span class="editservers-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizemedium}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">REPLACE_modal_header_text</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.marginbottom8 + BDFDB.disCN.modalsubinner}" style="flex: 0 0 auto;">
<div tab="server" class="tab">REPLACE_modal_tabheader1_text</div>
<div tab="icon" class="tab">REPLACE_modal_tabheader2_text</div>
<div tab="tooltip" class="tab">REPLACE_modal_tabheader3_text</div>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner}">
<div tab="server" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20} tab-content" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_servername_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-servername"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_servershortname_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-servershortname"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_serverurl_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-serverurl"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">REPLACE_modal_removeicon_text</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-removeicon">
</div>
</div>
</div>
<div tab="icon" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20} tab-content" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_colorpicker1_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="swatches1"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_colorpicker2_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="swatches2"></div>
</div>
</div>
<div tab="tooltip" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20} tab-content" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_colorpicker3_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="swatches3"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">REPLACE_modal_colorpicker4_text</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="swatches4"></div>
</div>
</div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-save ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_save_text</div>
</button>
</div>
</div>
</div>
</div>
</span>`;
}
getName () {return "EditServers";}
getDescription () {return "Allows you to change the icon, name and color of servers.";}
getVersion () {return "1.8.5";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Reset all Servers.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".reset-button", () => {this.resetAll();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"serverContextObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
var addedNodes = change.addedNodes;
if (change.attributeName == "class" && change.oldValue && change.oldValue.indexOf(BDFDB.disCN.guildplaceholder) > -1) addedNodes = [change.target];
if (change.attributeName == "draggable" && change.oldValue && change.oldValue == "false") addedNodes = [change.target.parentElement];
if (addedNodes) {
addedNodes.forEach((node) => {
if (node && node.classList && node.classList.contains(BDFDB.disCN.guild) && !node.querySelector(BDFDB.dotCN.guildserror)) {
var id = BDFDB.getIdOfServer(node);
if (id) this.loadServer(BDFDB.getDivOfServer(id));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.guilds, {name:"serverListObserver",instance:observer}, {childList: true, subtree:true, attributes:true, attributeFilte: ["class", "draggable"], attributeOldValue: true});
setTimeout(() => {
this.loadAllServers();
},3000);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll("[custom-editservers]").forEach(serverDiv => {this.resetServer(BDFDB.getIdOfServer(serverDiv));});
BDFDB.unloadMessage(this);
}
}
// begin of own functions
resetAll () {
if (confirm("Are you sure you want to reset all servers?")) {
BDFDB.removeAllData(this, "servers");
document.querySelectorAll("[custom-editservers]").forEach(serverDiv => {this.resetServer(BDFDB.getIdOfServer(serverDiv));});
}
}
changeLanguageStrings () {
this.serverContextEntryMarkup = this.serverContextEntryMarkup.replace("REPLACE_context_localserversettings_text", this.labels.context_localserversettings_text);
this.serverContextSubMenuMarkup = this.serverContextSubMenuMarkup.replace("REPLACE_submenu_serversettings_text", this.labels.submenu_serversettings_text);
this.serverContextSubMenuMarkup = this.serverContextSubMenuMarkup.replace("REPLACE_submenu_resetsettings_text", this.labels.submenu_resetsettings_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_header_text", this.labels.modal_header_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_servername_text", this.labels.modal_servername_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_servershortname_text", this.labels.modal_servershortname_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_serverurl_text", this.labels.modal_serverurl_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_removeicon_text", this.labels.modal_removeicon_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_tabheader1_text", this.labels.modal_tabheader1_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_tabheader2_text", this.labels.modal_tabheader2_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_tabheader3_text", this.labels.modal_tabheader3_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_colorpicker1_text", this.labels.modal_colorpicker1_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_colorpicker2_text", this.labels.modal_colorpicker2_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_colorpicker3_text", this.labels.modal_colorpicker3_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_modal_colorpicker4_text", this.labels.modal_colorpicker4_text);
this.serverSettingsModalMarkup = this.serverSettingsModalMarkup.replace("REPLACE_btn_save_text", this.labels.btn_save_text);
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".localserversettings-item")) return;
var info = BDFDB.getKeyInformation({"node":context, "key":"guild"});
if (info && BDFDB.getKeyInformation({"node":context, "key":"displayName", "value":"GuildLeaveGroup"})) {
$(context).append(this.serverContextEntryMarkup)
.on("mouseenter", ".localserversettings-item", (e) => {
this.createContextSubMenu(info, e, context);
});
BDFDB.updateContextPosition(context);
}
}
createContextSubMenu (info, e, context) {
var id = info.id;
var serverContextSubMenu = $(this.serverContextSubMenuMarkup);
serverContextSubMenu
.on("click", ".serversettings-item", () => {
$(context).hide();
this.showServerSettings(info);
});
if (BDFDB.loadData(id, this, "servers")) {
serverContextSubMenu
.find(".resetsettings-item")
.removeClass(BDFDB.disCN.contextmenuitemdisabled)
.on("click", () => {
$(context).hide();
this.removeServerData(info.id);
});
}
BDFDB.appendSubMenu(e.currentTarget, serverContextSubMenu);
}
showServerSettings (info) {
var data = BDFDB.loadData(info.id, this, "servers");
var name = data ? data.name : null;
var shortName = data ? data.shortName : null;
var url = data ? data.url : null;
var removeIcon = data ? data.removeIcon : false;
var color1 = data ? data.color1 : null;
var color2 = data ? data.color2 : null;
var color3 = data ? data.color3 : null;
var color4 = data ? data.color4 : null;
var serverSettingsModal = $(this.serverSettingsModalMarkup);
serverSettingsModal.find(BDFDB.dotCN.modalguildname).text(info.name);
serverSettingsModal.find("#input-servername").val(name);
serverSettingsModal.find("#input-servername").attr("placeholder", info.name);
serverSettingsModal.find("#input-servershortname").val(shortName ? shortName : (info.icon ? "" : info.acronym));
serverSettingsModal.find("#input-servershortname").attr("placeholder", info.acronym);
serverSettingsModal.find("#input-serverurl").val(url);
serverSettingsModal.find("#input-serverurl").attr("placeholder", info.icon ? "https://cdn.discordapp.com/icons/" + info.id + "/" + info.icon + ".png" : null);
serverSettingsModal.find("#input-serverurl").addClass(url ? "valid" : "");
serverSettingsModal.find("#input-serverurl").prop("disabled", removeIcon);
serverSettingsModal.find("#input-removeicon").prop("checked", removeIcon);
BDFDB.setColorSwatches(color1, serverSettingsModal.find(".swatches1"), "swatch1");
BDFDB.setColorSwatches(color2, serverSettingsModal.find(".swatches2"), "swatch2");
BDFDB.setColorSwatches(color3, serverSettingsModal.find(".swatches3"), "swatch3");
BDFDB.setColorSwatches(color4, serverSettingsModal.find(".swatches4"), "swatch4");
BDFDB.appendModal(serverSettingsModal);
serverSettingsModal
.on("click", "#input-removeicon", (event) => {
serverSettingsModal.find("#input-serverurl").prop("disabled", event.target.checked);
})
.on("change keyup paste", "#input-serverurl", (event) => {
this.checkUrl(serverSettingsModal, event);
})
.on("mouseenter", "#input-serverurl", (event) => {
$(event.target).addClass("hovering");
this.createNoticeTooltip(event);
})
.on("mouseleave", "#input-serverurl", (event) => {
$(BDFDB.dotCN.tooltips).find(".notice-tooltip").remove();
$(event.target).removeClass("hovering");
})
.on("click", ".btn-save", (event) => {
event.preventDefault();
name = null;
if (serverSettingsModal.find("#input-servername").val()) {
if (serverSettingsModal.find("#input-servername").val().trim().length > 0) {
name = serverSettingsModal.find("#input-servername").val().trim();
}
}
shortName = null;
if (serverSettingsModal.find("#input-servershortname").val()) {
if (serverSettingsModal.find("#input-servershortname").val().trim().length > 0) {
shortName = serverSettingsModal.find("#input-servershortname").val().trim();
shortName = shortName == info.acronym ? null : shortName;
}
}
if (serverSettingsModal.find("#input-serverurl:not('.invalid')").length > 0) {
url = null;
if (!serverSettingsModal.find("#input-removeicon").prop("checked") && serverSettingsModal.find("#input-serverurl").val()) {
if (serverSettingsModal.find("#input-serverurl").val().trim().length > 0) {
url = serverSettingsModal.find("#input-serverurl").val().trim();
}
}
}
removeIcon = serverSettingsModal.find("#input-removeicon").prop("checked");
color1 = BDFDB.getSwatchColor("swatch1");
color2 = BDFDB.getSwatchColor("swatch2");
color3 = BDFDB.getSwatchColor("swatch3");
color4 = BDFDB.getSwatchColor("swatch4");
if (name == null && shortName == null && url == null && !removeIcon && color1 == null && color2 == null && color3 == null && color4 == null) {
this.removeServerData(info.id);
}
else {
BDFDB.saveData(info.id, {name,shortName,url,removeIcon,color1,color2,color3,color4}, this, "servers");
this.loadServer(BDFDB.getDivOfServer(info.id));
}
});
serverSettingsModal.find("#input-servername").focus();
}
checkUrl (modal, e) {
if (!e.target.value) {
$(e.target)
.removeClass("valid")
.removeClass("invalid");
if ($(e.target).hasClass("hovering")) $(BDFDB.dotCN.tooltips).find(".notice-tooltip").remove();
}
else {
let request = require("request");
request(e.target.value, (error, response, result) => {
if (response && response.headers["content-type"] && response.headers["content-type"].indexOf("image") != -1) {
$(e.target)
.removeClass("invalid")
.addClass("valid");
}
else {
$(e.target)
.removeClass("valid")
.addClass("invalid");
}
if ($(e.target).hasClass("hovering")) this.createNoticeTooltip(e);
});
}
}
createNoticeTooltip (e) {
$(BDFDB.dotCN.tooltips).find(".notice-tooltip").remove();
var input = e.target;
var disabled = $(input).prop("disabled");
var valid = $(input).hasClass("valid");
var invalid = $(input).hasClass("invalid");
if (disabled || valid || invalid) {
var text = disabled ? this.labels.modal_ignoreurl_text : valid ? this.labels.modal_validurl_text : this.labels.modal_invalidurl_text;
var bgColor = disabled ? "#282524" : valid ? "#297828" : "#8C2528";
var customTooltipCSS = `
body .notice-tooltip {
background-color: ${bgColor} !important;
}
body .notice-tooltip:after {
border-right-color: ${bgColor} !important;
}`;
BDFDB.createTooltip(text, input, {type:"right",selector:"notice-tooltip",css:customTooltipCSS});
}
}
removeServerData (id) {
this.resetServer(id);
BDFDB.removeData(id, this, "servers");
}
resetServer (id) {
let serverObj = BDFDB.getDivOfServer(id);
if (typeof serverObj !== "object" || !serverObj) return;
$(serverObj.div)
.off("mouseenter." + this.getName())
.removeAttr("custom-editservers")
.find(BDFDB.dotCN.avataricon)
.text(serverObj.icon ? "" : serverObj.data.acronym)
.toggleClass(BDFDB.disCN.avatarnoicon, !serverObj.icon)
.css("font-size", !serverObj.icon ? "10px" : "")
.css("background-image", serverObj.icon ? "url('https://cdn.discordapp.com/icons/" + serverObj.id + "/" + serverObj.icon + ".png')" : "")
.css("background-color", "")
.css("color", "");
}
loadServer (serverObj) {
if (typeof serverObj !== "object" || !serverObj) return;
var data = BDFDB.loadData(serverObj.id, this, "servers");
if (data) {
var name = data.name ? data.name : serverObj.name;
var bgImage = data.url ? ("url(" + data.url + ")") : (serverObj.icon ? "url('https://cdn.discordapp.com/icons/" + serverObj.id + "/" + serverObj.icon + ".png')" : "");
var removeIcon = data.removeIcon;
var shortName = data.shortName ? data.shortName : (serverObj.icon && !removeIcon ? "" : serverObj.data.acronym);
var color1 = data.color1 ? BDFDB.color2RGB(data.color1) : "";
var color2 = data.color2 ? BDFDB.color2RGB(data.color2) : "";
$(serverObj.div)
.off("mouseenter." + this.getName())
.on("mouseenter." + this.getName(), () => {this.createServerToolTip(serverObj);})
.attr("custom-editservers", true)
.find(BDFDB.dotCN.avataricon)
.text(bgImage && !removeIcon ? "" : shortName)
.toggleClass(BDFDB.disCN.avatarnoicon, removeIcon || bgImage)
.css("font-size", removeIcon || !bgImage ? "10px" : "")
.css("background-image", removeIcon ? "" : bgImage)
.css("background-color", color1)
.css("color", color2);
}
}
loadAllServers () {
var serverObjs = BDFDB.readServerList();
for (var i = 0; i < serverObjs.length; i++) {
this.loadServer(serverObjs[i]);
}
}
createServerToolTip (serverObj) {
var data = BDFDB.loadData(serverObj.id, this, "servers");
if (data) {
var text = data.name ? data.name : serverObj.name;
var bgColor = data.color3 ? BDFDB.color2RGB(data.color3) : "";
var fontColor = data.color4 ? BDFDB.color2RGB(data.color4) : "";
var customTooltipCSS = `
body ${BDFDB.dotCN.tooltip}:not(.guild-custom-tooltip) {
display: none !important;
}
body .guild-custom-tooltip {
color: ${fontColor} !important;
background-color: ${bgColor} !important;
}
body .guild-custom-tooltip:after {
border-right-color: ${bgColor} !important;
}`;
BDFDB.createTooltip(text, serverObj.div, {type:"right",selector:"guild-custom-tooltip",css:customTooltipCSS});
}
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
context_localserversettings_text: "Lokalne postavke poslužitelja",
submenu_serversettings_text: "Promijeni postavke",
submenu_resetsettings_text: "Ponovno postavite poslužitelj",
modal_header_text: "Lokalne postavke poslužitelja",
modal_servername_text: "Naziv lokalnog poslužitelja",
modal_servershortname_text: "Poslužitelj prečaca",
modal_serverurl_text: "Ikona",
modal_removeicon_text: "Ukloni ikonu",
modal_tabheader1_text: "Poslužitelja",
modal_tabheader2_text: "Boja ikona",
modal_tabheader3_text: "Boja tooltip",
modal_colorpicker1_text: "Boja ikona",
modal_colorpicker2_text: "Boja fonta",
modal_colorpicker3_text: "Boja tooltip",
modal_colorpicker4_text: "Boja fonta",
modal_ignoreurl_text: "URL ignorirati",
modal_validurl_text: "Vrijedi URL",
modal_invalidurl_text: "Nevažeći URL",
btn_cancel_text: "Prekid",
btn_save_text: "Uštedjeti"
};
case "da": //danish
return {
context_localserversettings_text: "Lokal serverindstillinger",
submenu_serversettings_text: "Skift indstillinger",
submenu_resetsettings_text: "Nulstil server",
modal_header_text: "Lokal serverindstillinger",
modal_servername_text: "Lokalt servernavn",
modal_servershortname_text: "Initialer",
modal_serverurl_text: "Ikon",
modal_removeicon_text: "Fjern ikon",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Ikonfarve",
modal_tabheader3_text: "Tooltipfarve",
modal_colorpicker1_text: "Ikonfarve",
modal_colorpicker2_text: "Skriftfarve",
modal_colorpicker3_text: "Tooltipfarve",
modal_colorpicker4_text: "Skriftfarve",
modal_ignoreurl_text: "Ignorer URL",
modal_validurl_text: "Gyldig URL",
modal_invalidurl_text: "Ugyldig URL",
btn_cancel_text: "Afbryde",
btn_save_text: "Spare"
};
case "de": //german
return {
context_localserversettings_text: "Lokale Servereinstellungen",
submenu_serversettings_text: "Einstellungen ändern",
submenu_resetsettings_text: "Server zurücksetzen",
modal_header_text: "Lokale Servereinstellungen",
modal_servername_text: "Lokaler Servername",
modal_servershortname_text: "Serverkürzel",
modal_serverurl_text: "Icon",
modal_removeicon_text: "Entferne Icon",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Iconfarbe",
modal_tabheader3_text: "Tooltipfarbe",
modal_colorpicker1_text: "Iconfarbe",
modal_colorpicker2_text: "Schriftfarbe",
modal_colorpicker3_text: "Tooltipfarbe",
modal_colorpicker4_text: "Schriftfarbe",
modal_ignoreurl_text: "URL ignorieren",
modal_validurl_text: "Gültige URL",
modal_invalidurl_text: "Ungültige URL",
btn_cancel_text: "Abbrechen",
btn_save_text: "Speichern"
};
case "es": //spanish
return {
context_localserversettings_text: "Ajustes local de servidor",
submenu_serversettings_text: "Cambiar ajustes",
submenu_resetsettings_text: "Restablecer servidor",
modal_header_text: "Ajustes local de servidor",
modal_servername_text: "Nombre local del servidor",
modal_servershortname_text: "Iniciales",
modal_serverurl_text: "Icono",
modal_removeicon_text: "Eliminar icono",
modal_tabheader1_text: "Servidor",
modal_tabheader2_text: "Color del icono",
modal_tabheader3_text: "Color de tooltip",
modal_colorpicker1_text: "Color del icono",
modal_colorpicker2_text: "Color de fuente",
modal_colorpicker3_text: "Color de tooltip",
modal_colorpicker4_text: "Color de fuente",
modal_ignoreurl_text: "Ignorar URL",
modal_validurl_text: "URL válida",
modal_invalidurl_text: "URL inválida",
btn_cancel_text: "Cancelar",
btn_save_text: "Guardar"
};
case "fr": //french
return {
context_localserversettings_text: "Paramètres locale du serveur",
submenu_serversettings_text: "Modifier les paramètres",
submenu_resetsettings_text: "Réinitialiser le serveur",
modal_header_text: "Paramètres locale du serveur",
modal_servername_text: "Nom local du serveur",
modal_servershortname_text: "Initiales",
modal_serverurl_text: "Icône",
modal_removeicon_text: "Supprimer l'icône",
modal_tabheader1_text: "Serveur",
modal_tabheader2_text: "Couleur de l'icône",
modal_tabheader3_text: "Couleur de tooltip",
modal_colorpicker1_text: "Couleur de l'icône",
modal_colorpicker2_text: "Couleur de la police",
modal_colorpicker3_text: "Couleur de tooltip",
modal_colorpicker4_text: "Couleur de la police",
modal_ignoreurl_text: "Ignorer l'URL",
modal_validurl_text: "URL valide",
modal_invalidurl_text: "URL invalide",
btn_cancel_text: "Abandonner",
btn_save_text: "Enregistrer"
};
case "it": //italian
return {
context_localserversettings_text: "Impostazioni locale server",
submenu_serversettings_text: "Cambia impostazioni",
submenu_resetsettings_text: "Ripristina server",
modal_header_text: "Impostazioni locale server",
modal_servername_text: "Nome locale server",
modal_servershortname_text: "Iniziali",
modal_serverurl_text: "Icona",
modal_removeicon_text: "Rimuova l'icona",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Colore dell'icona",
modal_tabheader3_text: "Colore della tooltip",
modal_colorpicker1_text: "Colore dell'icona",
modal_colorpicker2_text: "Colore del carattere",
modal_colorpicker3_text: "Colore della tooltip",
modal_colorpicker4_text: "Colore del carattere",
modal_ignoreurl_text: "Ignora l'URL",
modal_validurl_text: "URL valido",
modal_invalidurl_text: "URL non valido",
btn_cancel_text: "Cancellare",
btn_save_text: "Salvare"
};
case "nl": //dutch
return {
context_localserversettings_text: "Lokale serverinstellingen",
submenu_serversettings_text: "Verandere instellingen",
submenu_resetsettings_text: "Reset server",
modal_header_text: "Lokale serverinstellingen",
modal_servername_text: "Lokale servernaam",
modal_servershortname_text: "Initialen",
modal_serverurl_text: "Icoon",
modal_removeicon_text: "Verwijder icoon",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Icoonkleur",
modal_tabheader3_text: "Tooltipkleur",
modal_colorpicker1_text: "Icoonkleur",
modal_colorpicker2_text: "Doopvontkleur",
modal_colorpicker3_text: "Tooltipkleur",
modal_colorpicker4_text: "Doopvontkleur",
modal_ignoreurl_text: "URL negeren",
modal_validurl_text: "Geldige URL",
modal_invalidurl_text: "Ongeldige URL",
btn_cancel_text: "Afbreken",
btn_save_text: "Opslaan"
};
case "no": //norwegian
return {
context_localserversettings_text: "Lokal serverinnstillinger",
submenu_serversettings_text: "Endre innstillinger",
submenu_resetsettings_text: "Tilbakestill server",
modal_header_text: "Lokal serverinnstillinger",
modal_servername_text: "Lokalt servernavn",
modal_servershortname_text: "Initialer",
modal_serverurl_text: "Ikon",
modal_removeicon_text: "Fjern ikon",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Ikonfarge",
modal_tabheader3_text: "Tooltipfarge",
modal_colorpicker1_text: "Ikonfarge",
modal_colorpicker2_text: "Skriftfarge",
modal_colorpicker3_text: "Tooltipfarge",
modal_colorpicker4_text: "Skriftfarge",
modal_ignoreurl_text: "Ignorer URL",
modal_validurl_text: "Gyldig URL",
modal_invalidurl_text: "Ugyldig URL",
btn_cancel_text: "Avbryte",
btn_save_text: "Lagre"
};
case "pl": //polish
return {
context_localserversettings_text: "Lokalne ustawienia serwera",
submenu_serversettings_text: "Zmień ustawienia",
submenu_resetsettings_text: "Resetuj ustawienia",
modal_header_text: "Lokalne ustawienia serwera",
modal_servername_text: "Lokalna nazwa serwera",
modal_servershortname_text: "Krótka nazwa",
modal_serverurl_text: "Ikona",
modal_removeicon_text: "Usuń ikonę",
modal_tabheader1_text: "Serwer",
modal_tabheader2_text: "Kolor ikony",
modal_tabheader3_text: "Kolor podpowiedzi",
modal_colorpicker1_text: "Kolor ikony",
modal_colorpicker2_text: "Kolor czcionki",
modal_colorpicker3_text: "Kolor podpowiedzi",
modal_colorpicker4_text: "Kolor czcionki",
modal_ignoreurl_text: "Ignoruj URL",
modal_validurl_text: "Prawidłowe URL",
modal_invalidurl_text: "Nieprawidłowe URL",
btn_cancel_text: "Anuluj",
btn_save_text: "Zapisz"
};
case "pt-BR": //portuguese (brazil)
return {
context_localserversettings_text: "Configurações local do servidor",
submenu_serversettings_text: "Mudar configurações",
submenu_resetsettings_text: "Redefinir servidor",
modal_header_text: "Configurações local do servidor",
modal_servername_text: "Nome local do servidor",
modal_servershortname_text: "Iniciais",
modal_serverurl_text: "Icone",
modal_removeicon_text: "Remover ícone",
modal_tabheader1_text: "Servidor",
modal_tabheader2_text: "Cor do ícone",
modal_tabheader3_text: "Cor da tooltip",
modal_colorpicker1_text: "Cor do ícone",
modal_colorpicker2_text: "Cor da fonte",
modal_colorpicker3_text: "Cor da tooltip",
modal_colorpicker4_text: "Cor da fonte",
modal_ignoreurl_text: "Ignorar URL",
modal_validurl_text: "URL válido",
modal_invalidurl_text: "URL inválida",
btn_cancel_text: "Cancelar",
btn_save_text: "Salvar"
};
case "fi": //finnish
return {
context_localserversettings_text: "Paikallinen palvelimen asetukset",
submenu_serversettings_text: "Vaihda asetuksia",
submenu_resetsettings_text: "Nollaa palvelimen",
modal_header_text: "Paikallinen palvelimen asetukset",
modal_servername_text: "Paikallinen palvelimenimi",
modal_servershortname_text: "Nimikirjaimet",
modal_serverurl_text: "Ikonin",
modal_removeicon_text: "Poista kuvake",
modal_tabheader1_text: "Palvelimen",
modal_tabheader2_text: "Ikoninväri",
modal_tabheader3_text: "Tooltipväri",
modal_colorpicker1_text: "Ikoninväri",
modal_colorpicker2_text: "Fontinväri",
modal_colorpicker3_text: "Tooltipväri",
modal_colorpicker4_text: "Fontinväri",
modal_ignoreurl_text: "Ohita URL",
modal_validurl_text: "Voimassa URL",
modal_invalidurl_text: "Virheellinen URL",
btn_cancel_text: "Peruuttaa",
btn_save_text: "Tallentaa"
};
case "sv": //swedish
return {
context_localserversettings_text: "Lokal serverinställningar",
submenu_serversettings_text: "Ändra inställningar",
submenu_resetsettings_text: "Återställ server",
modal_header_text: "Lokal serverinställningar",
modal_servername_text: "Lokalt servernamn",
modal_servershortname_text: "Initialer",
modal_serverurl_text: "Ikon",
modal_removeicon_text: "Ta bort ikonen",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Ikonfärg",
modal_tabheader3_text: "Tooltipfärg",
modal_colorpicker1_text: "Ikonfärg",
modal_colorpicker2_text: "Fontfärg",
modal_colorpicker3_text: "Tooltipfärg",
modal_colorpicker4_text: "Fontfärg",
modal_ignoreurl_text: "Ignorera URL",
modal_validurl_text: "Giltig URL",
modal_invalidurl_text: "Ogiltig URL",
btn_cancel_text: "Avbryta",
btn_save_text: "Spara"
};
case "tr": //turkish
return {
context_localserversettings_text: "Yerel Sunucu Ayarları",
submenu_serversettings_text: "Ayarları Değiştir",
submenu_resetsettings_text: "Sunucu Sıfırla",
modal_header_text: "Yerel Sunucu Ayarları",
modal_servername_text: "Yerel Sunucu Adı",
modal_servershortname_text: "Baş harfleri",
modal_serverurl_text: "Simge",
modal_removeicon_text: "Simge kaldır",
modal_tabheader1_text: "Sunucu",
modal_tabheader2_text: "Simge rengi",
modal_tabheader3_text: "Tooltip rengi",
modal_colorpicker1_text: "Simge rengi",
modal_colorpicker2_text: "Yazı rengi",
modal_colorpicker3_text: "Tooltip rengi",
modal_colorpicker4_text: "Yazı rengi",
modal_ignoreurl_text: "URL yoksay",
modal_validurl_text: "Geçerli URL",
modal_invalidurl_text: "Geçersiz URL",
btn_cancel_text: "Iptal",
btn_save_text: "Kayıt"
};
case "cs": //czech
return {
context_localserversettings_text: "Místní nastavení serveru",
submenu_serversettings_text: "Změnit nastavení",
submenu_resetsettings_text: "Obnovit server",
modal_header_text: "Místní nastavení serveru",
modal_servername_text: "Místní název serveru",
modal_servershortname_text: "Iniciály",
modal_serverurl_text: "Ikony",
modal_removeicon_text: "Odstranit ikonu",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Barva ikony",
modal_tabheader3_text: "Barva tooltip",
modal_colorpicker1_text: "Barva ikony",
modal_colorpicker2_text: "Barva fontu",
modal_colorpicker3_text: "Barva tooltip",
modal_colorpicker4_text: "Barva fontu",
modal_ignoreurl_text: "Ignorovat URL",
modal_validurl_text: "Platná URL",
modal_invalidurl_text: "Neplatná URL",
btn_cancel_text: "Zrušení",
btn_save_text: "Uložit"
};
case "bg": //bulgarian
return {
context_localserversettings_text: "Настройки за локални cървър",
submenu_serversettings_text: "Промяна на настройките",
submenu_resetsettings_text: "Възстановяване на cървър",
modal_header_text: "Настройки за локални cървър",
modal_servername_text: "Локално име на cървър",
modal_servershortname_text: "Инициали",
modal_serverurl_text: "Икона",
modal_removeicon_text: "Премахване на иконата",
modal_tabheader1_text: "Cървър",
modal_tabheader2_text: "Цвят на иконата",
modal_tabheader3_text: "Цвят на подсказка",
modal_colorpicker1_text: "Цвят на иконата",
modal_colorpicker2_text: "Цвят на шрифта",
modal_colorpicker3_text: "Цвят на подсказка",
modal_colorpicker4_text: "Цвят на шрифта",
modal_ignoreurl_text: "Игнориране на URL",
modal_validurl_text: "Валиден URL",
modal_invalidurl_text: "Невалиден URL",
btn_cancel_text: "Зъбести",
btn_save_text: "Cпасяване"
};
case "ru": //russian
return {
context_localserversettings_text: "Настройки локального cервер",
submenu_serversettings_text: "Изменить настройки",
submenu_resetsettings_text: "Сбросить cервер",
modal_header_text: "Настройки локального cервер",
modal_servername_text: "Имя локального cервер",
modal_servershortname_text: "Инициалы",
modal_serverurl_text: "Значок",
modal_removeicon_text: "Удалить значок",
modal_tabheader1_text: "Cервер",
modal_tabheader2_text: "Цвет значков",
modal_tabheader3_text: "Цвет подсказка",
modal_colorpicker1_text: "Цвет значков",
modal_colorpicker2_text: "Цвет шрифта",
modal_colorpicker3_text: "Цвет подсказка",
modal_colorpicker4_text: "Цвет шрифта",
modal_ignoreurl_text: "Игнорировать URL",
modal_validurl_text: "Действительный URL",
modal_invalidurl_text: "Неверная URL",
btn_cancel_text: "Отмена",
btn_save_text: "Cпасти"
};
case "uk": //ukrainian
return {
context_localserversettings_text: "Налаштування локального cервер",
submenu_serversettings_text: "Змінити налаштування",
submenu_resetsettings_text: "Скидання cервер",
modal_header_text: "Налаштування локального cервер",
modal_servername_text: "Локальне ім'я cервер",
modal_servershortname_text: "Ініціали",
modal_serverurl_text: "Іконка",
modal_removeicon_text: "Видалити піктограму",
modal_tabheader1_text: "Cервер",
modal_tabheader2_text: "Колір ікони",
modal_tabheader3_text: "Колір підказка",
modal_colorpicker1_text: "Колір ікони",
modal_colorpicker2_text: "Колір шрифту",
modal_colorpicker3_text: "Колір підказка",
modal_colorpicker4_text: "Колір шрифту",
modal_ignoreurl_text: "Ігнорувати URL",
modal_validurl_text: "Дійсна URL",
modal_invalidurl_text: "Недійсна URL",
btn_cancel_text: "Скасувати",
btn_save_text: "Зберегти"
};
case "ja": //japanese
return {
context_localserversettings_text: "ローカルサーバー設定",
submenu_serversettings_text: "設定を変更する",
submenu_resetsettings_text: "サーバーをリセットする",
modal_header_text: "ローカルサーバー設定",
modal_servername_text: "ローカルサーバー名",
modal_servershortname_text: "イニシャル",
modal_serverurl_text: "アイコン",
modal_removeicon_text: "アイコンを削除",
modal_tabheader1_text: "サーバー",
modal_tabheader2_text: "アイコンの色",
modal_tabheader3_text: "ツールチップの色",
modal_colorpicker1_text: "アイコンの色",
modal_colorpicker2_text: "フォントの色",
modal_colorpicker3_text: "ツールチップの色",
modal_colorpicker4_text: "フォントの色",
modal_ignoreurl_text: "URL を無視する",
modal_validurl_text: "有効な URL",
modal_invalidurl_text: "無効な URL",
btn_cancel_text: "キャンセル",
btn_save_text: "セーブ"
};
case "zh-TW": //chinese (traditional)
return {
context_localserversettings_text: "本地服務器設置",
submenu_serversettings_text: "更改設置",
submenu_resetsettings_text: "重置服務器",
modal_header_text: "本地服務器設置",
modal_servername_text: "服務器名稱",
modal_servershortname_text: "聲母",
modal_serverurl_text: "圖標",
modal_removeicon_text: "刪除圖標",
modal_tabheader1_text: "服務器",
modal_tabheader2_text: "圖標顏色",
modal_tabheader3_text: "工具提示顏色",
modal_colorpicker1_text: "圖標顏色",
modal_colorpicker2_text: "字體顏色",
modal_colorpicker3_text: "工具提示顏色",
modal_colorpicker4_text: "字體顏色",
modal_ignoreurl_text: "忽略 URL",
modal_validurl_text: "有效的 URL",
modal_invalidurl_text: "無效的 URL",
btn_cancel_text: "取消",
btn_save_text: "保存"
};
case "ko": //korean
return {
context_localserversettings_text: "로컬 서버 설정",
submenu_serversettings_text: "설정 변경",
submenu_resetsettings_text: "서버 재설정",
modal_header_text: "로컬 서버 설정",
modal_servername_text: "로컬 서버 이름",
modal_servershortname_text: "머리 글자",
modal_serverurl_text: "상",
modal_removeicon_text: "상 삭제",
modal_tabheader1_text: "서버",
modal_tabheader2_text: "상 색깔",
modal_tabheader3_text: "툴팁 색깔",
modal_colorpicker1_text: "상 색깔",
modal_colorpicker2_text: "글꼴 색깔",
modal_colorpicker3_text: "툴팁 색깔",
modal_colorpicker4_text: "글꼴 색깔",
modal_ignoreurl_text: "URL 무시",
modal_validurl_text: "유효한 URL",
modal_invalidurl_text: "잘못된 URL",
btn_cancel_text: "취소",
btn_save_text: "저장"
};
default: //default: english
return {
context_localserversettings_text: "Local Serversettings",
submenu_serversettings_text: "Change Settings",
submenu_resetsettings_text: "Reset Server",
modal_header_text: "Local Serversettings",
modal_servername_text: "Local Servername",
modal_servershortname_text: "Initials",
modal_serverurl_text: "Icon",
modal_removeicon_text: "Remove Icon",
modal_tabheader1_text: "Server",
modal_tabheader2_text: "Iconcolor",
modal_tabheader3_text: "Tooltipcolor",
modal_colorpicker1_text: "Iconcolor",
modal_colorpicker2_text: "Fontcolor",
modal_colorpicker3_text: "Tooltipcolor",
modal_colorpicker4_text: "Fontcolor",
modal_ignoreurl_text: "Ignore URL",
modal_validurl_text: "Valid URL",
modal_invalidurl_text: "Invalid URL",
btn_cancel_text: "Cancel",
btn_save_text: "Save"
};
}
}
}

View File

@ -0,0 +1,6 @@
# Edit Servers - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditServers/EditServers.plugin.js)
Adds two options on your server context menu.
- You can open a popout, where you can change the local name, initials, icon and color for the selected server.
- You can set the selected server back to its original state.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
# Edit Users - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditUsers/EditUsers.plugin.js)
Allows you to change the icon, name, tag and color of users.

View File

@ -0,0 +1,618 @@
//META{"name":"EmojiStatistics"}*//
class EmojiStatistics {
initConstructor () {
this.labels = {};
this.css = `
.emojistatistics-modal .titles {
height: 20px;
}
.emojistatistics-modal .emojiserver-entry {
height: 50px;
padding-top: 5px;
padding-bottom: 5px;
}
.emojistatistics-modal .emojiserver-entry .modal-emojiserver-icon {
background-color: #484B51;
background-size: cover;
border-radius: 25px;
color: #b9bbbe;
display: inline-block;
font-size: 16px;
font-weight: 600;
height: 35px;
letter-spacing: .5px;
overflow: hidden;
padding-top: 15px;
text-align: center;
width: 50px;
}
.emojistatistics-modal .titles-entry label,
.emojistatistics-modal .emojiserver-entry label {
color: #b9bbbe;
display: inline-block;
flex: 1;
font-size: 12px;
font-weight: 600;
letter-spacing: .5px;
margin-left: 10px;
margin-top: 20px;
overflow: hidden;
vertical-align: top;
text-transform: uppercase;
}
.emojistatistics-modal .emojiserver-entry label {
height: 12px;
overflow: hidden;
}
.emojistatistics-modal .titles-entry label {
margin-top: 0px;
}
.emojistatistics-modal .titles-entry .modal-titlesicon-label {
margin-left: 0px;
text-align: center;
width: 50px;
}
.emojistatistics-modal .titles-entry .modal-titlesname-label,
.emojistatistics-modal .emojiserver-entry .modal-emojiname-label {
width: 300px;
}
.emojistatistics-modal .titles-entry .modal-sorttitle-label {
cursor: pointer;
}
.emojistatistics-modal .titles-entry .modal-titlestotal-label,
.emojistatistics-modal .titles-entry .modal-titlesglobal-label,
.emojistatistics-modal .titles-entry .modal-titleslocal-label,
.emojistatistics-modal .titles-entry .modal-titlescopies-label,
.emojistatistics-modal .emojiserver-entry .modal-emojitotal-label,
.emojistatistics-modal .emojiserver-entry .modal-emojiglobal-label,
.emojistatistics-modal .emojiserver-entry .modal-emojilocal-label,
.emojistatistics-modal .emojiserver-entry .modal-emojicopies-label {
text-align: center;
width: 82px;
}
.emojistatistics-button {
background-image: url("/assets/f24711dae4f6d6b28335e866a93e9d9b.png");
background-position: -770px -374px;
background-size: 924px 704px;
cursor: pointer;
height: 22px;
margin-right: 10px;
width: 22px;
}`;
this.emojiInformationModalMarkup =
`<span class="emojistatistics-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizelarge}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">REPLACE_modal_header_text</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalsubinner} titles" style="flex: 0 0 auto;"></div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} entries"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-ok ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_ok_text</div>
</button>
</div>
</div>
</div>
</div>
</span>`;
this.emojiserverTitlesMarkup =
`<div class="titles-entry">
<label class="modal-titlesicon-label">REPLACE_modal_titlesicon-label</label>
<label class="modal-sorttitle-label modal-titlesname-label" sortkey="name">REPLACE_modal_titlesname_text</label>
<label class="modal-sorttitle-label modal-titlestotal-label" sortkey="total">REPLACE_modal_titlestotal_text</label>
<label class="modal-sorttitle-label modal-titlesglobal-label" sortkey="global">REPLACE_modal_titlesglobal_text</label>
<label class="modal-sorttitle-label modal-titleslocal-label" sortkey="local">REPLACE_modal_titleslocal_text</label>
<label class="modal-sorttitle-label modal-titlescopies-label" sortkey="copies">REPLACE_modal_titlescopies_text</label>
</div>`;
this.emojiserverEntryMarkup =
`<div class="emojiserver-entry">
<div class="modal-emojiserver-icon"></div>
<label class="modal-emojiname-label">modal-emojiname-label</label>
<label class="modal-emojitotal-label">modal-emojitotal-label</label>
<label class="modal-emojiglobal-label">modal-emojiglobal-label</label>
<label class="modal-emojilocal-label">modal-emojilocal-label</label>
<label class="modal-emojicopies-label">modal-emojicopies-label</label>
</div>`;
this.dividerMarkup = `<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCN.modaldividerdefault}"></div>`;
this.emojiButtonMarkup = `<div class="emojistatistics-button"></div>`;
this.defaults = {
settings: {
enableEmojiHovering: {value:true, description:"Show Information about Emojis on hover over an Emoji in the Emojipicker."},
enableEmojiStatisticsButton: {value:true, description:"Add a Button in the Emojipicker to open the Statistics Overview."}
}
};
}
getName () {return "EmojiStatistics";}
getDescription () {return "Adds some helpful options to show you more information about emojis and emojiservers.";}
getVersion () {return "2.7.5";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.emojipicker)) {
this.loadEmojiList();
if (!node.querySelector(".emojistatistics-button") && BDFDB.getData("enableEmojiStatisticsButton", this, "settings")) {
this.addEmojiInformationButton(node);
}
if (BDFDB.getData("enableEmojiHovering", this, "settings")) {
this.hoverEmoji(node);
}
}
});
}
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node.querySelector(BDFDB.dotCN.emojipicker)) {
$(BDFDB.dotCN.tooltips).find(".emoji-tooltip").remove();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"emojiPickerObserver",instance:observer}, {childList: true});
this.GuildEmojis = BDFDB.WebModules.findByProperties(["getGuildEmoji", "getDisambiguatedEmojiContext"]);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
changeLanguageStrings () {
this.emojiInformationModalMarkup = this.emojiInformationModalMarkup.replace("REPLACE_modal_header_text", this.labels.modal_header_text);
this.emojiInformationModalMarkup = this.emojiInformationModalMarkup.replace("REPLACE_btn_ok_text", this.labels.btn_ok_text);
this.emojiInformationModalMarkup = this.emojiInformationModalMarkup.replace("REPLACE_btn_all_text", this.labels.btn_all_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titlesicon-label", this.labels.modal_titlesicon_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titlesname_text", this.labels.modal_titlesname_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titlestotal_text", this.labels.modal_titlestotal_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titlesglobal_text", this.labels.modal_titlesglobal_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titleslocal_text", this.labels.modal_titleslocal_text);
this.emojiserverTitlesMarkup = this.emojiserverTitlesMarkup.replace("REPLACE_modal_titlescopies_text", this.labels.modal_titlescopies_text);
}
loadEmojiList () {
this.emojiReplicaList = {};
this.emojiToServerList = {};
for (let serverObj of BDFDB.readServerList()) {
for (let emoji of this.GuildEmojis.getGuildEmoji(serverObj.id)) {
this.emojiToServerList[emoji.url] = {emoji:emoji.allNamesString, server:serverObj.name};
if (emoji.managed) {
if (this.emojiReplicaList[emoji.name] != undefined) {
this.emojiReplicaList[emoji.name] = true;
}
else {
this.emojiReplicaList[emoji.name] = false;
}
}
}
}
}
hoverEmoji (picker) {
$(picker)
.off("mouseenter." + this.getName())
.on("mouseenter." + this.getName(), BDFDB.dotCN.emojipickeremojiitem, (e) => {
var data = this.emojiToServerList[$(e.target).css("background-image").replace("url(\"","").replace("\")","")];
if (data) {
var text = `${BDFDB.encodeToHTML(data.emoji)}\n${BDFDB.encodeToHTML(data.server)}`;
BDFDB.createTooltip(text, e.target, {type:"right",selector:"emoji-tooltip",css:`.emoji-tooltip{z-index:30000;}`});
}
});
}
addEmojiInformationButton (node) {
$(node).find(BDFDB.dotCN.emojipickerheader)
.append(this.emojiButtonMarkup)
.off("click." + this.getName())
.on("click." + this.getName(), ".emojistatistics-button", () => {
$(node).hide();
this.showEmojiInformationModal();
});
}
showEmojiInformationModal () {
var emojiInformationModal = $(this.emojiInformationModalMarkup);
BDFDB.appendModal(emojiInformationModal);
var entries = [], index = 0;
for (let serverObj of BDFDB.readServerList()) {
let amountGlobal = 0, amountLocal = 0, amountCopies = 0;
for (let emoji of this.GuildEmojis.getGuildEmoji(serverObj.id)) {
if (emoji.managed) {
amountGlobal++;
if (this.emojiReplicaList[emoji.name]) amountCopies++;
}
else {
amountLocal++;
}
}
var entry = $(this.emojiserverEntryMarkup);
if (serverObj.icon) {
entry.find(".modal-emojiserver-icon").css("background-image", "url('https://cdn.discordapp.com/icons/" + serverObj.id + "/" + serverObj.icon + ".png')");
}
else {
entry.find(".modal-emojiserver-icon").text(serverObj.div.querySelector("a").innerText);
}
entry.find(".modal-emojiname-label").text(serverObj.name);
entry.find(".modal-emojitotal-label").text(amountGlobal+amountLocal);
entry.find(".modal-emojiglobal-label").text(amountGlobal);
entry.find(".modal-emojilocal-label").text(amountLocal);
entry.find(".modal-emojicopies-label").text(amountCopies);
entries.push({entry:entry, index:index++, name:serverObj.name, total:amountGlobal+amountLocal, global:amountGlobal, local:amountLocal, copies:amountCopies});
}
var titleentry = $(this.emojiserverTitlesMarkup)
.appendTo(".emojistatistics-modal .titles")
.on("click", ".modal-sorttitle-label ", (e2) => {
var oldTitle = e2.target.innerText;
var reverse = oldTitle.indexOf("▼") < 0 ? false : true;
titleentry.find(".modal-titlesname-label").text(this.labels.modal_titlesname_text);
titleentry.find(".modal-titlestotal-label").text(this.labels.modal_titlestotal_text);
titleentry.find(".modal-titlesglobal-label").text(this.labels.modal_titlesglobal_text);
titleentry.find(".modal-titleslocal-label").text(this.labels.modal_titleslocal_text);
titleentry.find(".modal-titlescopies-label").text(this.labels.modal_titlescopies_text);
var sortKey = "index";
if (oldTitle.indexOf("▲") < 0) {
sortKey = e2.target.getAttribute("sortkey");
var title = this.labels["modal_titles" + sortKey + "_text"];
e2.target.innerText = oldTitle.indexOf("▼") < 0 ? title + "▼" : title + "▲";
}
BDFDB.sortArrayByKey(entries, sortKey);
if (reverse) entries.reverse();
this.updateAllEntries(emojiInformationModal, entries);
});
this.updateAllEntries(emojiInformationModal, entries);
}
updateAllEntries (modal, entries) {
var container = modal.find(".entries");
container.children().remove();
for (let i = 0; entries.length > i; i++) {
if (i > 0) container.append(this.dividerMarkup);
container.append(entries[i].entry);
}
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
modal_header_text: "Statistike o emojima",
modal_titlesicon_text: "Ikona",
modal_titlesname_text: "Naziv poslužitelja",
modal_titlestotal_text: "Cjelokupni:",
modal_titlesglobal_text: "Globalno:",
modal_titleslocal_text: "Kokalne:",
modal_titlescopies_text: "Kopije:",
btn_ok_text: "OK"
};
case "da": //danish
return {
modal_header_text: "Statistikker af emojis",
modal_titlesicon_text: "Icon",
modal_titlesname_text: "Servernavn",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Lokal:",
modal_titlescopies_text: "Copies:",
btn_ok_text: "OK"
};
case "de": //german
return {
modal_header_text: "Statistiken über Emojis",
modal_titlesicon_text: "Icon",
modal_titlesname_text: "Servername",
modal_titlestotal_text: "Gesamt:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Lokal:",
modal_titlescopies_text: "Kopien:",
btn_ok_text: "OK"
};
case "es": //spanish
return {
modal_header_text: "Estadísticas de emojis",
modal_titlesicon_text: "Icono",
modal_titlesname_text: "Nombre del servidor",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Local:",
modal_titlescopies_text: "Copias:",
btn_ok_text: "OK"
};
case "fr": //french
return {
modal_header_text: "Statistiques des emojis",
modal_titlesicon_text: "Icône",
modal_titlesname_text: "Nom du serveur",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Local:",
modal_titlescopies_text: "Copies:",
btn_ok_text: "OK"
};
case "it": //italian
return {
modal_header_text: "Statistiche di emojis",
modal_titlesicon_text: "Icona",
modal_titlesname_text: "Nome del server",
modal_titlestotal_text: "Totale:",
modal_titlesglobal_text: "Globale:",
modal_titleslocal_text: "Locale:",
modal_titlescopies_text: "Copie:",
btn_ok_text: "OK"
};
case "nl": //dutch
return {
modal_header_text: "Statistieken van emojis",
modal_titlesicon_text: "Icoon",
modal_titlesname_text: "Servernaam",
modal_titlestotal_text: "Totaal:",
modal_titlesglobal_text: "Globaal:",
modal_titleslocal_text: "Lokaal:",
modal_titlescopies_text: "Kopieën:",
btn_ok_text: "OK"
};
case "no": //norwegian
return {
modal_header_text: "Statistikk av emojis",
modal_titlesicon_text: "Ikon",
modal_titlesname_text: "Servernavn",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Lokal:",
modal_titlescopies_text: "Kopier:",
btn_ok_text: "OK"
};
case "pl": //polish
return {
modal_header_text: "Statystyki emoji",
modal_titlesicon_text: "Ikona",
modal_titlesname_text: "Nazwa",
modal_titlestotal_text: "Całkowity:",
modal_titlesglobal_text: "Światowy:",
modal_titleslocal_text: "Lokalny:",
modal_titlescopies_text: "Kopie:",
btn_ok_text: "OK"
};
case "pt-BR": //portuguese (brazil)
return {
modal_header_text: "Estatísticas de emojis",
modal_titlesicon_text: "Ícone",
modal_titlesname_text: "Nome do servidor",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Local:",
modal_titlescopies_text: "Cópias:",
btn_ok_text: "OK"
};
case "fi": //finnish
return {
modal_header_text: "Tilastot emojista",
modal_titlesicon_text: "Ikoni",
modal_titlesname_text: "Palvelimen nimi",
modal_titlestotal_text: "Koko:",
modal_titlesglobal_text: "Globaali:",
modal_titleslocal_text: "Paikallinen:",
modal_titlescopies_text: "Kopiot:",
btn_ok_text: "OK"
};
case "sv": //swedish
return {
modal_header_text: "Statistik för emojis",
modal_titlesicon_text: "Ikon",
modal_titlesname_text: "Servernamn",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Lokal:",
modal_titlescopies_text: "Kopior:",
btn_ok_text: "OK"
};
case "tr": //turkish
return {
modal_header_text: "Emojis istatistikleri",
modal_titlesicon_text: "Icon",
modal_titlesname_text: "Sunucuadı",
modal_titlestotal_text: "Toplam:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Yerel:",
modal_titlescopies_text: "Kopya:",
btn_ok_text: "Okey"
};
case "cs": //czech
return {
modal_header_text: "Statistiky emojis",
modal_titlesicon_text: "Ikona",
modal_titlesname_text: "Název serveru",
modal_titlestotal_text: "Celkový:",
modal_titlesglobal_text: "Globální:",
modal_titleslocal_text: "Místní:",
modal_titlescopies_text: "Kopie:",
btn_ok_text: "OK"
};
case "bg": //bulgarian
return {
modal_header_text: "Статистика на емотис",
modal_titlesicon_text: "Икона",
modal_titlesname_text: "Име на сървъра",
modal_titlestotal_text: "Oбщо:",
modal_titlesglobal_text: "Cветовен:",
modal_titleslocal_text: "Mестен:",
modal_titlescopies_text: "Копия:",
btn_ok_text: "Добре"
};
case "ru": //russian
return {
modal_header_text: "Статистика emojis",
modal_titlesicon_text: "Значок",
modal_titlesname_text: "Имя сервера",
modal_titlestotal_text: "Всего:",
modal_titlesglobal_text: "Mировой:",
modal_titleslocal_text: "Местный:",
modal_titlescopies_text: "Копии:",
btn_ok_text: "ОК"
};
case "uk": //ukrainian
return {
modal_header_text: "Статистика емідій",
modal_titlesicon_text: "Ікона",
modal_titlesname_text: "Ім'я сервера",
modal_titlestotal_text: "Всього:",
modal_titlesglobal_text: "Cвітовий:",
modal_titleslocal_text: "Місцевий:",
modal_titlescopies_text: "Копії:",
btn_ok_text: "Добре"
};
case "ja": //japanese
return {
modal_header_text: "エモジスの統計",
modal_titlesicon_text: "アイコン",
modal_titlesname_text: "サーバーの名前",
modal_titlestotal_text: "合計:",
modal_titlesglobal_text: "グローバル:",
modal_titleslocal_text: "地元:",
modal_titlescopies_text: "コピー:",
btn_ok_text: "はい"
};
case "zh-TW": //chinese (traditional)
return {
modal_header_text: "表情統計",
modal_titlesicon_text: "圖標",
modal_titlesname_text: "服務器名稱",
modal_titlestotal_text: "總:",
modal_titlesglobal_text: "全球:",
modal_titleslocal_text: "本地:",
modal_titlescopies_text: "副本:",
btn_ok_text: "好"
};
case "ko": //korean
return {
modal_header_text: "그림 이모티콘의 통계",
modal_titlesicon_text: "상",
modal_titlesname_text: "서버 이름",
modal_titlestotal_text: "합계:",
modal_titlesglobal_text: "글로벌:",
modal_titleslocal_text: "지방의:",
modal_titlescopies_text: "사본:",
btn_ok_text: "승인"
};
default: //default: english
return {
modal_header_text: "Statistics of emojis",
modal_titlesicon_text: "Icon",
modal_titlesname_text: "Servername",
modal_titlestotal_text: "Total:",
modal_titlesglobal_text: "Global:",
modal_titleslocal_text: "Local:",
modal_titlescopies_text: "Copies:",
btn_ok_text: "OK"
};
}
}
}

View File

@ -0,0 +1,6 @@
# Emoji Statistics - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EmojiStatistics/EmojiStatistics.plugin.js)
Adds several options to get more information about emojis and emojiservers.
- You can enable/disable the option to get the name and server of an emoji when you hover over it inside the emojipicker.
- You can enable/disable the option to add a button in the emojipicker to open an overview of your servers with some information.

View File

@ -0,0 +1,256 @@
//META{"name":"FixGermanTranslation"}*//
class FixGermanTranslation {
initConstructor () {
this.newStrings = {
NO_THANKS: "Nein Danke",
VAD_PERMISSION_SMALL: "Dieser Kanal erfordert Push-to-Talk um zu sprechen.",
FORM_HELP_NSFW: "Benutzer müssen bestätigen, dass sie über 18 Jahre alt sind, um Inhalte des Kanals zu sehen.\nNSFW-Kanäle sind vom expliziten Inhaltsfilter ausgeschlossen.",
SEND_TTS_MESSAGES_DESCRIPTION: "Mitglieder mit dieser Berechtigung können Text-zu-Sprache-Nachrichten schicken, indem sie die Nachricht mit /tts (Text-to-Speech) beginnen. Diese Nachrichten können von jedem gehört werden, der sich in dem Kanal befindet.",
MANAGE_MESSAGES_DESCRIPTION: "Mitglieder mit dieser Berechtigung können Nachrichten von anderen Mitgliedern löschen oder eine Nachricht anpinnen.",
MOVE_MEMBERS_DESCRIPTION: "Mitglieder mit dieser Berechtigung können andere Mitglieder aus diesem Kanal herausziehen. Sie können ausschließlich Mitglieder zwischen Kanälen hin- und herziehen, in denen sowohl sie als auch das Mitglied Zutritt haben.",
USE_VAD_DESCRIPTION: "Wenn diese Berechtigung entzogen wird, müssen Benutzer in diesem Kanal Push-to-Talk verwenden.",
MENTION_USERS_WITH_ROLE: "Benachrichtige Benutzer mit dieser Rolle, welche die Rechte haben diesen Kanal zu sehen.",
MENTION_EVERYONE_AUTOCOMPLETE_DESCRIPTION: "Benachrichtige jeden, der die Berechtigung zum Lesen des Kanals hat.",
MENTION_HERE_AUTOCOMPLETE_DESCRIPTION: "Benachrichtige jeden der Online ist und der die Rechte hat diesen Kanal zu sehen.",
FORM_HELP_CHANNEL_PERMISSIONS: "Das Auswählen der Rollen wird automatisch grundlegende Berechtigungen für diesen Kanal erstellen.",
JOIN_SERVER_DESCRIPTION_MOBILE: "Gib eine Soforteinladung ein, um einen existierenden Server beizutreten.",
INSTANT_INVITE_LOOKS_LIKE: "Die Einladung wird in etwa so aussehen:",
FORM_LABEL_INSTANT_INVITE: "Gib eine Soforteinladung ein",
INVALID_INVITE_LINK_ERROR: "Bitte gib einen gültigen Einladungslink oder Code ein.",
EDIT_CHANNEL: "Kanal bearbeiten",
EDIT_VOICE_CHANNEL_NO_PERMISSION: "Deine Rolle hat keine Berechtigung diesen Sprachkanal zu bearbeiten.",
DELETE_SERVER_ENTER_NAME: "Gib den Servernamen ein",
EXPLICIT_CONTENT_FILTER_HIGH_DESCRIPTION: "Empfohlen, wenn du alles blitze blank haben willst.",
GUILD_SETTINGS_AUDIT_LOG_CHANNEL_PERMISSION_OVERRIDES_CREATE: "Mit Berechtigungsüberschreibung",
GUILD_SETTINGS_AUDIT_LOG_CHANNEL_NSFW_ENABLED: "Hat den Kanal als NSFW markiert",
GUILD_SETTINGS_AUDIT_LOG_ROLE_HOIST_OFF: "Nicht separiert",
SORTING: "Am Sortieren",
GUILD_SETTINGS_WIDGET_ENABLE_WIDGET: "Server Widget aktivieren",
ADMINISTRATOR_DESCRIPTION: "Mitglieder mit dieser Berechtigung haben jede Berechtigung und können kanalspezifische Berechtigungen umgehen. Mit dieser Berechtigung ist vorsichtig umzugehen.",
VIEW_AUDIT_LOG_DESCRIPTION: "Mitglieder mit dieser Berechtigung können die Audit Logs des Servers einsehen.",
ANIMATED_EMOJI: "Animierter Emoji",
NO_EMOJI_BODY: "Nichts",
TOO_MANY_EMOJI: "Du hast keine freien Plätze mehr für Emojis.",
TOO_MANY_ANIMATED_EMOJI: "Du hast keine freien Plätze mehr für animierte Emojis.",
INVITE_FRIEND_MODAL_TITLE: "Lade deine Freunde ein",
INVITE_FRIEND_MODAL_LOADING: "Lädt deine Freundesliste...",
INSTANT_INVITE_INVALID_CHANNEL: "Du kannst keine Soforteinladung für diesen Kanal erstellen. Versuch's mit einem anderen!",
INSTANT_INVITE_NOT_ALLOWED: "Mist. Scheint als könntest du für diesen Server keine Soforteinladung erstellen.",
LOGIN_BODY: "Log dich mit deiner E-Mail-Adresse ein um loszulegen",
FORM_LABEL_EMAIL: "E-Mail",
EMAIL_REQUIRED: "Eine gültige E-Mail-Adresse wird benötigt.",
EMAIL_INVALID: "Die angegebene E-Mail-Adresse ist ungültig. Bitte aktualisiere sie und versuch es erneut.",
PASSWORD_REQUIRED: "Ein Passwort ist erforderlich.",
FORGOT_PASSWORD_BODY: "Keine Sorge. Bitte gib die E-Mail-Adresse deines Accounts an, damit wir deine Identität überprüfen können.",
ACCOUNT_SCHEDULED_FOR_DELETION_TITLE: "Account zur Löschung geplant",
ACCOUNT_SCHEDULED_FOR_DELETION_DESCRIPTION: "Dein Account wird sich bald selbst zerstören.. sicher, dass du dies immer noch möchtest?",
BEGINNING_GROUP_DM_PARTY: "Willkommen zu LFG. Bitte sei freundlich und respektvoll zu einander. Wenn du Freunde findest, vergiss nicht sie hinzuzufügen!",
USERNAME_REQUIRED: "Ein Benutzername ist erforderlich.",
RESEND: "Erneut senden",
NOTICE_SPOTIFY_AUTO_PAUSED: "Dein Mikrofon sendet seit 30 Sekunden. Spotify wurde pausiert.",
SELF_MUTED: "Selbst stummschalten",
SERVER_MUTE: "Mikrofone deaktivieren",
SERVER_UNMUTE: " Mikrofone aktivieren",
SERVER_MUTED: "Mikrofone deaktiviert",
SERVER_DEAFEN: "Lautsprecher deaktivieren",
SERVER_UNDEAFEN: "Lautsprecher aktivieren",
SERVER_DEAFENED: "Lautsprecher deaktiviert",
USER_SETTINGS_STARTUP_BEHAVIOR: "System Startup Behavior",
USER_SETTINGS_CLOSE_BUTTON: "Schließknopf",
USER_SETTINGS_OPEN_ON_STARTUP_LABEL: "Discord öffnen",
USER_SETTINGS_OPEN_ON_STARTUP_BODY: "Spar dir ein paar Klicks und lass Discord dich grüßen, wenn du nach Hause kommst wie ein guter Junge",
USER_SETTINGS_START_MINIMIZED_LABEL: "Minimiert starten",
USER_SETTINGS_START_MINIMIZED_BODY: "Discord startet minimiert wie ein guter Junge und steht dir nicht im Weg",
USER_SETTINGS_MINIMIZE_TO_TRAY_LABEL: "In Symbolleiste minimieren",
USER_SETTINGS_MINIMIZE_TO_TRAY_BODY: "Lass Discord in deiner Symbolleiste wie ein guter Junge kuscheln, wenn du die Anwendung schließt",
USER_SETTINGS_LINUX_SETTINGS: "Linux-Einstellungen",
ADD_KEYBIND_WARNING: "Hotkeys sind deaktiviert, während diese Schaltfläche sichtbar ist.",
GAME_NOTIFICATIONS_USER_OVERRIDES: "Leute mit denen du spielst",
GAME_NOTIFICATION_SETTING_DESKTOP_ONLY_DESC: "Benachrichtigungen werden auf deinem Desktop angezeigt, wenn du online oder untätig bist.",
GAME_NOTIFICATION_SETTINGS_FOLLOWING_EMPTY: "Wir versuchen immer noch herauszufinden mit wem du Spiele spielst. Los spiel ein Bisschen mit deinen Freunden!",
VERIFICATION_EMAIL_ERROR_TITLE: "Fehler bei deiner Verifizierungs-E-Mail",
DESKTOP_NOTIFICATIONS_ENABLE: "Aktiviere Desktopbenachrichtigungen",
MOBILE_ENABLE_HARDWARE_SCALING_DESC: "Experimentelle Funktion, die die Performanz bei Videogesprächen verbessern könnte. Vorsicht kann Stuss verursachen.",
PIN_MESSAGE_BODY_PRIVATE_CHANNEL: "Möchte nur sicherstellen, dass du diese scheinbar bedeutsame Nachricht wirklich in diesen Kanal für die Nachwelt anheften möchtest.",
PINS_DISABLED_NSFW: "Dies ist ein NSFW-Kanal und der Inhalt sollte lieber für niemanden als angeheftete Nachricht sichtbar sein.",
SERVER_MUTE_DMS: "Direktnachrichten stummschalten",
SCOPE_WEBHOOK_INCOMING: "Fügt einen WebHook zu einem Kanal hinzu",
CLAIM_ACCOUNT_REQUIRED_BODY: "Bitte registriere deinen Account um die Desktop App zu benutzen.",
CLAIM_ACCOUNT_GET_APP: "Hol dir die Desktop App",
NOTE_PLACEHOLDER: "Hier tippen, um eine Notiz hinzuzufügen",
VANITY_URL_HELP_CONFLICT: "Vergiss nicht, dass wir Vanity-URLs zurücknehmen, wenn wir einen Missbrauch oder Interessenkonflikt feststellen.",
SCREENSHARE_UNAVAILABLE: "Bildschirmübertragung nicht verfügbar",
SCREENSHARE_UNAVAILABLE_DOWNLOAD_APP: "Lade die Desktop App herunter, um Bildschirmübertragungen zu benutzen!",
VIDEO_POOR_CONNECTION_BODY: "Video wurde deaktiviert. Es wird automatisch fortgesetzt, sobald sich deine Verbindung verbessert hat.",
INVITE_MODAL_ERROR_TITLE: "Upps...",
DISABLE_EMAIL_NOTIFICATIONS_FAILED: "Upps! Wir konnten die E-Mail Benachrichtigungen für deine E-Mail Adresse nicht ausschalten.",
KEYBIND_DESCRIPTION_MODAL_TOGGLE_PINS: "Verankerte Pins an-/ausschalten",
KEYBIND_DESCRIPTION_MODAL_FOCUS_TEXT_AREA: "Textbereich fokussieren",
INVALID_ANIMATED_EMOJI_BODY: "Dieser Emoji funktioniert nicht, da er animiert ist. Hol dir Discord Nitro, um all deine animierten Emoji Träume zu erfüllen.",
INVALID_ANIMATED_EMOJI_BODY_UPGRADE: "Dieser Emoji funktioniert nicht, da er animiert ist. Discord Nitro löst dieses Problem, schau auf Benutzereinstellungen > Discord Nitro für mehr Informationen.",
INVALID_EXTERNAL_EMOJI_BODY: "Dieser Emoji funktioniert nicht, da er von einem anderem Server stammt. Hol dir Discord Nitro, um Emojis von anderen Servern zu benutzen.",
INVALID_EXTERNAL_EMOJI_BODY_UPGRADE: "Dieser Emoji funktioniert nicht, da er von einem anderem Server stammt. Discord Nitro löst dieses Problem, schau auf Benutzereinstellungen > Discord Nitro für mehr Informationen.",
NEW_TERMS_TITLE: "Neue AGBs und Nutzungsbedingungen",
NEW_TERMS_DESCRIPTION: "Um weiterhin Discord zu nutzen, lies und stimme bitte\nunseren neuen AGBs und Nutzungsbedingungen zu.",
PREMIUM_FEATURE_DESCRIPTION_ANIMATED_AVATAR: "Lade ein GIF als Benutzerprofilbild hoch und spiel es ab wenn du im Chat mit der Maus darüber fährst.",
PAYMENT_SOURCE_TITLE: "Zahlungsmethode",
PAYMENT_SOURCE_CREDIT_CARD: "Kreditkarte",
PAYMENT_SOURCE_CHANGE_CARD: "Kreditkarte ändern",
PAYMENT_SOURCE_REMOVE_CARD: "Kreditkarte entfernen",
PAYMENT_SOURCE_CHANGE_PAYPAL: "PayPal-Account ändern",
PAYMENT_SOURCE_INVALID_DETAILS: "Du musst deine Kreditkarte aktualisieren oder dein Nitro Abonnement läuft ab",
PAYMENT_SOURCE_CONFIRM_PAYPAL_DETAILS: "Bestätige deine PayPal Daten in deinem Browser!",
PAYMENT_SOURCE_PAYPAL_REOPEN: "Fenster erneut öffnen",
PAYMENT_STEPS_GO_BACK: "Zurück",
PAYMENT_MODAL_TITLE_CHANGE_CARD: "Kreditkarte ändern",
PAYMENT_MODAL_TITLE_CHANGE_PAYPAL: "PayPal-Account ändern",
PAYMENT_MODAL_SUBTITLE: "Discord Nitro Abonnement",
PAYMENT_MODAL_BUTTON_CHANGE_CARD: "Kreditkarte aktualisieren",
PAYMENT_MODAL_BUTTON_CHANGE_PAYPAL: "PayPal-Account aktualisieren",
PAYPAL_ACCOUNT_VERIFYING: "Zu PayPal verbinden",
PAYPAL_CALLBACK_ERROR: "Etwas ist schief gelaufen, versuche es erneut.",
PERMISSION_CAMERA_ACCESS_DENIED: "Kamerazugriff verweigert - Discord braucht Videozugriff, um einen Videostream zu senden.",
GUILD_SETTINGS_SERVER_INVITE_BACKGROUND: "Soforteinladungshintergrund",
VERIFICATION_FOOTER: "Glaubst du du siehst dies fälschlicher Weise?",
USER_SETTINGS_NOTIFICATIONS_SHOW_BADGE_LABEL: "Ungelesene Nachrichten Indikator aktivieren",
USER_SETTINGS_NOTIFICATIONS_SHOW_BADGE_BODY: "Zeigt einen roten Punkt-Indikator auf dem App Symbol, wenn du ungelesene Nachrichten hast.",
USER_SETTINGS_NOTIFICATIONS_SHOW_FLASH_LABEL: "Taskleisten Blinken aktivieren",
USER_SETTINGS_NOTIFICATIONS_SHOW_FLASH_BODY: "Lässt das App Symbol in der Taskleiste blinken, wenn du neue Benachrichtigungen hast.",
HIDE_MUTED_CHANNELS: "Stumme Kanäle verstecken",
SHOW_MUTED_CHANNELS: "Stumme Kanäle anzeigen",
CREATE_CATEGORY: "Kategorie erstellen",
ADD_CHANNEL_TO_OVERRIDE: "Füge einen Kanal hinzu, um die Standard-Benachrichtigungseinstellungen zu überschreiben",
PRIVATE_CHANNEL_NOTE: "Wenn du einen Kanal auf privat stellst, können nur ausgewählte Rollen Nachrichten in diesem Kanal lesen oder sich mit ihm verbinden.",
PRIVATE_CATEGORY_NOTE: "Wenn du einen Kategorie auf privat stellst, werden alle privaten Kanäle in ihr die Rechte vererbt bekommen.",
USER_ACTIVITY_ERROR_FRIENDS_TITLE: "Freunde!",
USER_ACTIVITY_CANNOT_SPECTATE_SELF: "Du kannst dich nicht selbst beobachten.",
USER_ACTIVITY_LISTEN_ALONG: "Hör zu",
USER_ACTIVITY_CANNOT_PLAY_SELF: "Du kannst nicht mit dir selbst spielen.",
USER_ACTIVITY_CANNOT_SYNC_SELF: "Du kannst dir nicht selbst zuhören.",
USER_ACTIVITY_ALREADY_PLAYING: "Du spielst bereits dieses Spiel.",
USER_ACTIVITY_ALREADY_SYNCING: "Du hörst bereits zu.",
USER_ACTIVITY_NEVER_MIND: "Vergiss es",
USER_ACTIVITY_INVITE_EDUCATION_MODAL_TITLE: "Wusstest du schon?",
USER_ACTIVITY_INVITE_EDUCATION_MODAL_BODY_BOTTOM: "Halte Ausschau nach dem grünen Spielsymbol. Wenn du es siehst, dann kannst Spieleinladungen verschicken! Los hab Spaß!",
INVITE_EMBED_SESSION_HAS_ENDED: "Sitzung wurde beendet",
INVITE_EMBED_JOINED: "Beigetreten",
NUX_POST_REG_JOIN_SERVER_DESCRIPTION: "Hol das Meiste aus Discord raus, indem du einem Server beitrittst.",
VERIFY_BY_RECAPTCHA: "Durch reCaptcha bestätigen",
VERIFY_BY_RECAPTCHA_DESCRIPTION: "Wir müssen überprüfen, dass es sich bei dir um keinen Roboter handelt.",
CAPTCHA_FAILED: "Das Captcha ist fehlgeschlagen. Versuch es erneut.",
CAPTCHA_FAILED_UNSUPPORTED: "Das Captcha ist fehlgeschlagen. Dein Gerät wird nicht unterstützt.",
CAPTCHA_FAILED_PLAY_SERVICES: "Das Captcha ist fehlgeschlagen, Google Play wird benötigt. Nachdem du es heruntergeladen oder aktualisiert hast, versuche es erneut.",
SPOTIFY_APP_NOT_FOUND: "Die Spotify App konnte nicht gefunden werden.",
SPOTIFY_APP_NOT_OPENED: "Die Spotify App konnte nicht geöffnet werden.",
BROWSER_HANDOFF_DETECTING_TITLE: "Ermittle Account",
BROWSER_HANDOFF_DONE_DESCRIPTION: "Es wird versucht die Discord Desktop App zu authentisieren. Schließe nicht das Fenster.",
GAME_FEED_EMPTY_STATE_TITLE: "Niemand spielt gerade irgend etwas...",
GAME_FEED_DIVIDER_TITLE: "Kürzlich gespielte Spiele",
GAME_FEED_RECENT_ACTIVITY: "Letzte Aktivität´",
GAME_FEED_USER_PLAYING_JUST_STARTED: "Gerade angefangen zu spielen",
GAME_FEED_SETTINGS_SHOW_GAME_TITLE: "Du wirst nicht in dem Aktivitäten-Feed von anderen angezeigt!",
GAME_FEED_SETTINGS_SEARCH_MORE_FRIENDS: "Suche um mehr Freunde zu finden.",
GAME_FEED_SETTINGS_SEARCH_MORE_SERVER_MEMBERS: "Suche um mehr Servermitglieder zu finden.",
SPOTIFY_PREMIUM_UPGRADE_HEADER: "*Schallplatten reißen*",
SPOTIFY_PREMIUM_UPGRADE_BODY: "Schade, sieht aus als wärst du kein Spotify Premium Mitglied! Premium Mitglieder können bei anderen Benutzern mithören.",
SPOTIFY_PREMIUM_UPGRADE_BUTTON: "Spotify aktualisieren",
EXPERIMENT_BUTTON_CONNECT_FACEBOOK: "Facebook verbinden",
EXPERIMENT_BUTTON_CONNECT_STEAM: "Steam verbinden",
LFG_FULL: "Gruppe suchen (LFG)",
LFG_LANDING_TITLE: "Suchst du eine Gruppe?",
LFG_LANDING_BODY_1: "Kannste den letzten Platz nicht besetzen? Niemand online?",
LFG_LANDING_BODY_2: "Wähle ein Spiel aus und finde Gruppen mit Leuten mit denen du spielen kannst.",
LFG_SELECT_GAME: "Wähle ein Spiel um zu beginnen:",
LFG_NO_GROUPS_FOUND_TITLE: "Keine Gruppen verfügbar",
LFG_NO_GROUPS_FOUND_BODY: "Sei ein Trendsetter. Erstelle eine neue Gruppe!",
LFG_ALREADY_IN_PARTY_TITLE: "Du bist bereits in einer Gruppe",
LFG_ALREADY_IN_PARTY_BODY: "Möchtest du deine jetzige Gruppe verlassen, um diese Gruppe beizutreten?",
LFG_ALREADY_IN_PARTY_BODY_ALT: "Möchtest du deine jetzige Gruppe verlassen, um eine neue Gruppe zu erstellen?",
LFG_SWITCH_PARTY: "Gruppen wechseln",
GROUP_OWNER: "Gruppenbesitzer",
PARTY_EDIT_HEADER: "Gruppe bearbeiten",
PARTY_CREATE_NEW: "Neue Gruppe erstellen",
PARTY_CREATE_SELECT_GAME: "Spiel auswählen",
PARTY_CREATE_PARTY_TITLE: "Gruppenname",
PARTY_CREATE_PARTY_TITLE_PLACEHOLDER: "Wonach schaust du dich um?",
PARTY_CREATE_PARTY_DESCRIPTION: "Beschreibung",
PARTY_CREATE_PARTY_DESCRIPTION_PLACEHOLDER: "Provide more details like region, rank, classes, level, etc, to better find the right players.",
PARTY_CREATE_PARTY_SIZE: "Gruppengröße",
PARTY_LOCKED: "Geschlossen",
PARTY_FULL: "Volle Gruppe",
FULL: "Voll",
PARTY_JOIN: "Gruppe beitreten",
PARTY_JOINED: "In Gruppe",
LFG_GROUP_ADD_FRIENDS: "Füge Freunde deiner Gruppe hinzu",
LFG_INVITE_FULL_MAIN: "Diese Gruppe ist voll!",
LFG_JOIN_FAILED_TOO_MANY_MEMBERS: "Upps. Du kannst dieser Gruppe nicht beitreten, da sie bereits voll ist.",
LFG_JOIN_FAILED_BLOCKED: "Upps. Du kannst dieser Gruppe nicht beitreten. Entweder blockiert dich der Gruppenbesitzer oder du ihn.",
LFG_REPORT_HEADER: "LFG Gruppe melden",
LFG_LEAVE_BODY: "Bist du sicher, dass du die Gruppe verlassen möchtest?",
LFG_RATE_LIMIT_CREATE_BODY: "Du erstellst Gruppen zu schnell!",
LFG_RATE_LIMIT_JOIN_BODY: "Du trittst Gruppen zu schnell bei!",
LFG_HAS_CHANGES: "Gruppen aktualisieren"
};
this.oldStrings = {};
}
getName () {return "FixGermanTranslation";}
getDescription () {return "Fixes the german translation.";}
getVersion () {return "2.0.1";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
unload () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.LanguageUtils = BDFDB.WebModules.findByProperties(["getLanguages"]);
this.translateInterval = setInterval(() => {
if (document.querySelector("html").lang && document.querySelector("html").lang == "de") {
clearInterval(this.translateInterval);
for (var key in this.newStrings) {
this.oldStrings[key] = this.LanguageUtils.Messages[key];
this.LanguageUtils.Messages[key] = this.newStrings[key];
}
}
},100);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
clearInterval(this.translateInterval);
for (var key in this.oldStrings) {
this.LanguageUtils.Messages[key] = this.oldStrings[key];
}
BDFDB.unloadMessage(this);
}
}
}

View File

@ -0,0 +1,3 @@
# Fix German Translation - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/FixGermanTranslation/FixGermanTranslation.plugin.js)
Fixes some minor translation errors and some untranslated parts in the german version of discord.

View File

@ -0,0 +1,199 @@
//META{"name":"ForceImagePreviews"}*//
class ForceImagePreviews {
initConstructor () {
this.waitTime = 3000;
}
getName () {return "ForceImagePreviews";}
getDescription () {return "Forces embedded Image Previews, if Discord doesn't do it itself.";}
getVersion () {return "1.0.7";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.type == "characterData") {
setTimeout(() => {this.addPreviews(change.target.parentElement);},this.waitTime);
}
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.classList.contains(BDFDB.disCN.message)) {
setTimeout(() => {this.addPreviews(node.querySelector(BDFDB.dotCN.messagemarkup));},this.waitTime);
}
});
}
}
);
});
BDFDB.addObserver(this, null, {name:"messageChangeObserver",instance:observer,multi:true}, {childList:true, characterData:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.message)) {
BDFDB.addObserver(this, node, {name:"messageChangeObserver",multi:true}, {childList:true, characterData:true, subtree:true});
node.querySelectorAll(BDFDB.dotCN.messagemarkup).forEach(message => {
setTimeout(() => {this.addPreviews(message);},this.waitTime);
});
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true});
this.addAllPreviews();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".FIP-embed").forEach(embed => {embed.remove();});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.addAllPreviews();
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
}
}
// begin of own functions
addAllPreviews () {
document.querySelectorAll(".FIP-embed").forEach(embed => {embed.remove();});
document.querySelectorAll(BDFDB.dotCN.messagegroup).forEach(messageContainer => {
BDFDB.addObserver(this, messageContainer, {name:"messageChangeObserver",multi:true}, {childList:true, characterData:true, subtree:true});
messageContainer.querySelectorAll(BDFDB.dotCN.messagemarkup).forEach(message => {
this.addPreviews(message);
});
});
}
addPreviews (message) {
let scroller = document.querySelector(BDFDB.dotCNS.chat + BDFDB.dotCN.messages);
if (!message || !scroller) return;
var messageData = BDFDB.getKeyInformation({node:message,key:"message",up:true});
if (!messageData) return;
let accessory = this.getAccessoryOfMessage(message);
if (accessory) {
let links = [];
for (let word of messageData.content.split(new RegExp("\\n|\\s|\\r|\\t|\\0"))) {
if (word.indexOf("https://") > -1 || word.indexOf("http://") > -1) {
if (word.indexOf("<") == 0 && word.indexOf(">") == word.length-1) links.push({src:word.slice(1,-1),embedded:false});
else if (!accessory.querySelector(`${BDFDB.dotCN.embedimage}[href="${this.parseSrc(word)}"]`) && !accessory.querySelector(`${BDFDB.dotCN.embedtitlelink}[href="${this.parseSrc(word)}"]`)) {
links.push({src:word,embedded:false});
}
else links.push({src:word,embedded:true});
}
}
if (links.length > 0) this.addItemToAccessory(null, links, accessory, scroller);
}
}
addItemToAccessory (previmage, links, accessory, scroller) {
let item = links.shift();
if (!item) return;
else if (item.embedded) this.addItemToAccessory(item, links, accessory, scroller);
else {
let itemsrc = this.parseSrc(item.src);
require("request")(itemsrc, (error, response, result) => {
if (response && response.headers["content-type"] && response.headers["content-type"].indexOf("image") > -1) {
let imagethrowaway = document.createElement("img");
imagethrowaway.src = itemsrc;
imagethrowaway.onload = () => {
let width = imagethrowaway.naturalWidth > 400 ? 400 : imagethrowaway.naturalWidth;
let height = Math.round(width*(imagethrowaway.naturalHeight/imagethrowaway.naturalWidth));
if (height > 300) {
width = Math.round(width*(300/height));
height = 300;
}
let checkedsrc = itemsrc.indexOf("imgur.com/") > -1 ? ("imgur.com/" + itemsrc.split("/")[3].split(".")[0]) : itemsrc;
if (!accessory.querySelector(`${BDFDB.dotCN.embedimage}[href*="${checkedsrc}"]`)) {
let embed = $(`<div class="FIP-embed ${BDFDB.disCNS.embed + BDFDB.disCNS.flex + BDFDB.disCN.embedold}"><a class="${BDFDB.disCNS.imagewrapper + BDFDB.disCNS.imagezoom + BDFDB.disCN.embedimage}" href="${itemsrc}" rel="noreferrer noopener" target="_blank" style="width: ${width}px; height: ${height}px;"><img src="${itemsrc}" style="width: ${width}px; height: ${height}px;"></a></div>`)[0];
this.insertEmbed(embed, previmage, links, accessory, scroller);
}
this.addItemToAccessory(item, links, accessory, scroller);
};
}
else if (response && response.headers["server"] && response.headers["server"].toLowerCase().indexOf("youtube") > -1 && result.indexOf("yt-user-info") > -1) {
if (!accessory.querySelector(`${BDFDB.dotCN.embedtitlelink}[href="${itemsrc}"]`)) {
result = result.replace(new RegExp("[\\r|\\n|\\t]|[\\s]{2,}", "g"), "");
let width = 400;
let height = Math.round(width*(result.split('<meta itemprop="height" content="')[1].split('"')[0]/result.split('<meta itemprop="width" content="')[1].split('"')[0]));
let embed = $(`<div class="FIP-embed ${BDFDB.disCNS.embed + BDFDB.disCNS.flex + BDFDB.disCN.embedold}" style="max-width: 426px;"><div class="${BDFDB.disCN.embedpill}" style="background-color: rgb(255, 0, 0);"></div><div class="${BDFDB.disCN.embedinner}"><div class="${BDFDB.disCNS.embedcontent + BDFDB.disCN.flex}"><div class="${BDFDB.disCN.embedcontentinner}"><div class=""><a class="${BDFDB.disCNS.anchor + BDFDB.disCNS.embedproviderlink + BDFDB.disCNS.embedlink + BDFDB.disCNS.embedprovider + BDFDB.disCNS.size12 + BDFDB.disCN.weightnormal}" href="https://www.youtube.com/" rel="noreferrer noopener" target="_blank">YouTube</a></div><div class="${BDFDB.disCNS.embedauthor + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCNS.embedmargin + BDFDB.disCN.margintop4}"><a class="${BDFDB.disCNS.anchor + BDFDB.disCNS.embedauthornamelink + BDFDB.disCNS.embedlink + BDFDB.disCNS.embedauthorname + BDFDB.disCNS.weightmedium + BDFDB.disCN.size14}" href="https://www.youtube.com${result.split('<div class="yt-user-info"><a href="')[1].split('"')[0]}" rel="noreferrer noopener" target="_blank">${BDFDB.encodeToHTML(result.split('<div class="yt-user-info"><a href="')[1].split('>')[1].split('<')[0])}</a></div><div class="${BDFDB.disCNS.embedmargin + BDFDB.disCN.margintop4}"><a class="${BDFDB.disCNS.anchor + BDFDB.disCNS.embedtitlelink + BDFDB.disCNS.embedlink + BDFDB.disCNS.embedtitle + BDFDB.disCNS.size14 + BDFDB.disCN.weightmedium}" href="${itemsrc}" rel="noreferrer noopener" target="_blank">${BDFDB.encodeToHTML(result.split('<meta property="og:title" content="')[1].split('"')[0])}</a></div></div></div><div class="${BDFDB.disCNS.embedvideo + BDFDB.disCNS.embedimage + BDFDB.disCNS.embedmarginlarge + BDFDB.disCN.margintop8}" style="width: ${width}px; height: ${height}px;"><div class="${BDFDB.disCNS.imagewrapper + BDFDB.disCN.imagezoom}" style="width: ${width}px; height: ${height}px;"><img alt="" src="${result.split('<link itemprop="thumbnailUrl" href="')[1].split('"')[0]}" style="width: ${width}px; height: ${height}px;"></div><div class="${BDFDB.disCNS.embedvideoactions + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifycenter + BDFDB.disCN.aligncenter}"><div class="${BDFDB.disCNS.embedvideoactionsinner + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifycenter + BDFDB.disCN.aligncenter}"><div class="${BDFDB.disCN.iconactionswrapper}"><div tabindex="0" class="${BDFDB.disCN.iconwrapper}" role="button"><svg name="Play" class="${BDFDB.disCNS.iconplay + BDFDB.disCN.icon}" width="16" height="16" viewBox="0 0 24 24"><polygon fill="currentColor" points="0 0 0 14 11 7" transform="translate(7 5)"></polygon></svg></div><a class="${BDFDB.disCNS.anchor + BDFDB.disCN.iconwrapper}" href="${itemsrc}" rel="noreferrer noopener" target="_blank"><svg name="OpenExternal" class="${BDFDB.disCNS.iconexternalmargins + BDFDB.disCN.icon}" width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" transform="translate(3.000000, 4.000000)" d="M16 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h4v-2H2V4h14v10h-4v2h4c1.1 0 2-.9 2-2V2a2 2 0 0 0-2-2zM9 6l-4 4h3v6h2v-6h3L9 6z"></path></svg></a></div></div></div></div></div></div>`)[0];
$(embed).on("click." + this.getName(), BDFDB.dotCN.iconplay, (e) => {
let videowrapper = embed.querySelector(BDFDB.dotCN.embedvideo);
while (videowrapper.firstChild) videowrapper.firstChild.remove();
$(`<iframe src="${result.split('<link itemprop="embedURL" href="')[1].split('"')[0]}?start=0&amp;autoplay=1&amp;auto_play=1" width="${width}" height="${height}" frameborder="0" allowfullscreen=""></iframe>`).appendTo(videowrapper);
});
this.insertEmbed(embed, previmage, links, accessory, scroller);
}
this.addItemToAccessory(item, links, accessory, scroller);
}
else this.addItemToAccessory(item, links, accessory, scroller);
});
}
}
insertEmbed (embed, previmage, links, accessory, scroller) {
let prev = accessory.querySelector(`${BDFDB.dotCNS.embed + BDFDB.dotCN.embedimage}[href="${previmage ? this.parseSrc(previmage.src) : void 0}"]`);
let next = accessory.querySelector(`${BDFDB.dotCNS.embed + BDFDB.dotCN.embedimage}[href="${links[0] ? this.parseSrc(links[0].src) : void 0}"]`);
prev = prev ? prev : accessory.querySelector(`${BDFDB.dotCNS.embed + BDFDB.dotCN.embedtitlelink}[href="${previmage ? this.parseSrc(previmage.src) : void 0}"]`);
next = next ? next : accessory.querySelector(`${BDFDB.dotCNS.embed + BDFDB.dotCN.embedtitlelink}[href="${links[0] ? this.parseSrc(links[0].src) : void 0}"]`);
accessory.insertBefore(embed, prev ? prev.nextSibling : next);
scroller.scrollTop += embed.getBoundingClientRect().height;
}
getAccessoryOfMessage (message) {
var accessory = null;
while (message && !message.querySelector(BDFDB.dotCN.messagegroup) && !accessory) {
accessory = message.querySelector(BDFDB.dotCN.messageaccessory);
message = message.parentElement;
}
return accessory;
}
parseSrc (src) {
return src.replace(/"/g, "");
}
}

View File

@ -0,0 +1,3 @@
# Force Image Previews - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ForceImagePreviews/ForceImagePreviews.plugin.js)
Forces embedded Image Previews, if Discord doesn't do it itself.

View File

@ -0,0 +1,357 @@
//META{"name":"FriendNotifications"}*//
class FriendNotifications {
initConstructor () {
this.friendsOnlineList = {};
this.timeLog = [];
this.timeLogModalMarkup =
`<span class="FriendNotifications-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizemedium}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">Friends LogIn/-Out Timelog</h4>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} entries">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-ok ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}"></div>
</button>
</div>
</div>
</div>
</div>
</span>`;
this.logEntryMarkup =
`<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCN.marginbottom4} entry" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCNS.flexchild + BDFDB.disCNS.overflowellipsis} log-time" style="flex: 0 0 auto;"></h3>
<div class="log-avatar"></div>
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCNS.flexchild + BDFDB.disCNS.overflowellipsis} log-description" style="flex: 1 1 auto;"></h3>
</div>`;
this.dividerMarkup = `<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCN.modaldividerdefault}"></div>`;
this.css = `
${BDFDB.dotCN.guilds} > ${BDFDB.dotCN.friendsonline} {
cursor: pointer;
}
.FriendNotifications-modal .log-time {
width: 110px;
}
.FriendNotifications-modal .log-avatar {
width: 35px;
height: 35px;
background-size: cover;
background-position: center;
border-radius: 50%;
}
.FriendNotifications-settings .avatar-list {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.FriendNotifications-settings .type-toast, .FriendNotifications-settings .type-desktop {
border-radius: 3px;
padding: 0 3px;
}
.FriendNotifications-settings .type-toast {
background-color: #7289DA;
}
.FriendNotifications-settings .type-desktop {
background-color: #43B581;
}
.FriendNotifications-settings .settings-avatar.desktop {
border-color: #43B581;
}
.FriendNotifications-settings .settings-avatar {
margin: 5px;
width: 50px;
height: 50px;
background-size: cover;
background-position: center;
border: 5px solid #7289DA;
border-radius: 50%;
box-sizing: border-box;
cursor: pointer;
}
.FriendNotifications-settings .settings-avatar.desktop {
border-color: #43B581;
}
.FriendNotifications-settings .settings-avatar.disabled {
border-color: #36393F;
filter: grayscale(100%) brightness(50%);
}
.FriendNotifications-settings .disable-all {
color: white;
background-color: #36393F;
}
`;
this.defaults = {
settings: {
muteOnDND: {value:false, description:"Do not notify me when I am DnD:"},
onlyOnOnline: {value:false, description:"Only notify me when a User logs in:"},
openOnClick: {value:false, description:"Open the DM when you click a Notification:"}
}
};
}
getName () {return "FriendNotifications";}
getDescription () {return "Notifies you when a friend either logs in or out. Click the Online Friend-Counter to display a timelog of the current session.";}
getVersion () {return "1.1.1";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var notificationsound = BDFDB.loadAllData(this, "notificationsound");
var desktop = BDFDB.loadAllData(this, "desktop");
var disabled = BDFDB.loadAllData(this, "disabled");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} settings-checkbox"${settings[key] ? " checked" : ""}></div></div>`;
}
if ("Notification" in window) settingshtml += `<div class="${BDFDB.disCNS.flexchild + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h5 class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 1 1 auto;">Desktop Notification Sound:</h5><h5 class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 0 0 auto;">Mute:</h5><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} mute-checkbox"${notificationsound.mute ? " checked" : ""}></div></div><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" value="${notificationsound.url ? notificationsound.url : ""}" placeholder="Url or Filepath" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} songInput"></div><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} file-navigator" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div><input type="file" accept="audio/*,video/*" style="display:none!important;"></button><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-save btn-savesong" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Click on a Icon to toggle <label class="type-toast">Toast</label> Notifications for that User:</h3></div>`;
if ("Notification" in window) settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Rightclick on a Icon to toggle <label class="type-desktop">Desktop</label> Notifications for that User:</h3></div>`;
settingshtml += `<div class="avatar-list ${BDFDB.disCN.marginbottom8}">`;
for (let id of this.FriendUtils.getFriendIDs()) {
let user = this.UserUtils.getUser(id);
if (user) {
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
settingshtml += `<div class="settings-avatar${desktop[id] ? " desktop" : ""}${disabled[id] ? " disabled" : ""}" user-id="${id}" style="background-image: url(${data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(user.id))});"></div>`;
}
}
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Batch set Users:</h3><button type="button" do-disable=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} disable-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Disable</div></button><button type="button" do-toast=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} toast-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Toast</div></button>${"Notification" in window ? `<button type="button" do-desktop=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorgreen + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} desktop-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Desktop</div></button>` : ``}</div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".settings-checkbox", () => {this.updateSettings(settingspanel);})
.on("click", ".btn-savesong", () => {this.saveAudio(settingspanel);})
.on("click", ".mute-checkbox", (e) => {
var notificationsound = BDFDB.loadAllData(this, "notificationsound");
notificationsound.mute = e.currentTarget.checked;
BDFDB.saveAllData(notificationsound, this, "notificationsound");
})
.on("mouseenter", ".settings-avatar", (e) => {
let user = this.UserUtils.getUser(e.currentTarget.getAttribute("user-id"));
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
BDFDB.createTooltip(data.name ? data.name : user.username, e.currentTarget, {type:"top"});
})
.on("contextmenu", ".settings-avatar", (e) => {
if (!("Notification" in window)) return;
let desktopoff = !e.currentTarget.classList.contains("desktop");
let id = e.currentTarget.getAttribute("user-id");
e.currentTarget.classList.remove("disabled");
e.currentTarget.classList.toggle("desktop", desktopoff);
BDFDB.saveData(id, desktopoff, this, "desktop");
BDFDB.removeData(id, this, "disabled");
})
.on("click", ".settings-avatar", (e) => {
let disableoff = !e.currentTarget.classList.contains("disabled");
let id = e.currentTarget.getAttribute("user-id");
e.currentTarget.classList.remove("desktop");
e.currentTarget.classList.toggle("disabled", disableoff);
BDFDB.saveData(id, disableoff, this, "disabled");
BDFDB.removeData(id, this, "desktop");
})
.on("click", ".disable-all, .toast-all, .desktop-all", (e) => {
let button = e.currentTarget;
let disableon = button.getAttribute("do-disable");
let desktopon = button.getAttribute("do-desktop");
let disabledata = BDFDB.loadAllData(this, "disabled");
let desktopdata = BDFDB.loadAllData(this, "desktop");
settingspanel.querySelectorAll(".settings-avatar").forEach(avatar => {
let id = avatar.getAttribute("user-id");
avatar.classList.toggle("disabled", disableon);
avatar.classList.toggle("desktop", desktopon);
disableon ? disabledata[id] = true : delete disabledata[id];
desktopon ? desktopdata[id] = true : delete desktopdata[id];
});
BDFDB.saveAllData(disabledata, this, "disabled");
BDFDB.saveAllData(desktopdata, this, "desktop");
});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.FriendUtils = BDFDB.WebModules.findByProperties(["getFriendIDs", "getRelationships"]);
this.ChannelUtils = BDFDB.WebModules.findByProperties(["getDMFromUserId"]);
this.ChannelSwitchUtils = BDFDB.WebModules.findByProperties(["selectPrivateChannel"]);
this.UserMetaStore = BDFDB.WebModules.findByProperties(["getStatus", "getOnlineFriendCount"]);
this.UserUtils = BDFDB.WebModules.findByProperties(["getUsers"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
let settings = BDFDB.getAllData(this, "settings");
let notificationsound = BDFDB.loadAllData(this, "notificationsound");
for (let id of this.FriendUtils.getFriendIDs()) {
let online = this.UserMetaStore.getStatus(id) != "offline";
let user = this.UserUtils.getUser(id);
if (user && this.friendsOnlineList[id] != online && !BDFDB.loadData(id, this, "disabled")) {
this.timeLog.push({user, online, time: new Date()});
if (!(settings.onlyOnOnline && !online) && !(settings.muteOnDND && BDFDB.getUserStatus() == "dnd")) {
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
let string = `${BDFDB.encodeToHTML(data.name ? data.name : user.username)} is ${online ? "online" : "offline"}.`;
let avatar = data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(user.id));
let openChannel = () => {
if (settings.openOnClick){
let DMid = this.ChannelUtils.getDMFromUserId(user.id);
if (DMid) {
require("electron").remote.getCurrentWindow().maximize();
this.ChannelSwitchUtils.selectPrivateChannel(DMid);
}
}
};
if (!BDFDB.loadData(id, this, "desktop")) {
let toast = BDFDB.showToast(`<div class="toast-inner"><div class="toast-avatar" style="background-image:url(${avatar});"></div><div>${string}</div></div>`, {html:true, timeout:5000, type:(online ? "success" : null), icon:false});
$(toast).on("click." + this.getName(), openChannel);
}
else {
BDFDB.showDesktopNotification(string, {icon:avatar, timeout:5000, click:openChannel, silent:notificationsound.mute, sound:notificationsound.song});
}
}
}
this.friendsOnlineList[id] = online;
}
}
);
});
BDFDB.addObserver(this, `${BDFDB.dotCN.guilds} > ${BDFDB.dotCN.friendsonline}`, {name:"friendCountObserver",instance:observer}, {childList:true, subtree:true, characterData:true});
for (let id of this.FriendUtils.getFriendIDs()) {
this.friendsOnlineList[id] = this.UserMetaStore.getStatus(id) != "offline";
}
$(`${BDFDB.dotCN.guilds} > ${BDFDB.dotCN.friendsonline}`).first()
.on("mouseenter." + this.getName(), (e) => {
BDFDB.createTooltip("Timelog", e.currentTarget, {type:"right"});
})
.on("click." + this.getName(), (e) => {
this.showTimeLog();
});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
saveAudio (settingspanel) {
var successSavedAudio = (parsedurl, parseddata) => {
if (parsedurl && parseddata) BDFDB.showToast(`Sound was saved successfully.`, {type:"success"});
let notificationsound = BDFDB.loadAllData(this, "notificationsound");
notificationsound.url = parsedurl;
notificationsound.song = parseddata;
BDFDB.saveAllData(notificationsound, this, "notificationsound");
};
var url = settingspanel.querySelector(".songInput").value;
if (url.length == 0) {
BDFDB.showToast(`Sound was set to the default sound.`, {type:"warn"});
successSavedAudio(url, url);
}
else if (url.indexOf("http") == 0) {
require("request")(url, (error, response, result) => {
if (response) {
var type = response.headers["content-type"];
if (type && (type.indexOf("octet-stream") > -1 || type.indexOf("audio") > -1 || type.indexOf("video") > -1)) {
successSavedAudio(url, url);
return;
}
}
BDFDB.showToast("Use a valid direct link to a video or audio source. They usually end on something like .mp3, .mp4 or .wav.", {type:"danger"});
});
}
else {
require("fs").readFile(url, (error, response) => {
if (error) {
BDFDB.showToast("Could not fetch file. Please make sure the file exists.", {type:"danger"});
}
else {
successSavedAudio(url, `data:audio/mpeg;base64,${response.toString("base64")}`);
}
});
}
}
showTimeLog () {
var timeLogModal = $(this.timeLogModalMarkup);
let logs = this.timeLog.slice(0).reverse();
for (let log of logs) {
let entry = $(this.logEntryMarkup);
let divider = $(this.dividerMarkup);
let data = BDFDB.loadData(log.user.id, "EditUsers", "users") || {};
entry.find(".log-time").text(`[${log.time.toLocaleTimeString()}]`);
entry.find(".log-avatar").css("background-image", `url(${data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(log.user.id))})`);
entry.find(".log-description").text(`${data.name ? data.name : log.user.username} is ${log.online ? "online" : "offline"}.`);
timeLogModal.find(".entries").append(entry).append(divider);
}
timeLogModal.find(BDFDB.dotCN.modaldivider + ":last-of-type").remove();
BDFDB.appendModal(timeLogModal);
}
}

View File

@ -0,0 +1,3 @@
# Friend Notifications - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/FriendNotifications/FriendNotifications.plugin.js)
Notifies you when a friend either logs in or out. Click the Online Friend-Counter to display a timelog of the current session.

View File

@ -0,0 +1,299 @@
//META{"name":"GoogleSearchReplace"}*//
class GoogleSearchReplace {
initConstructor () {
this.labels = {};
this.textUrlReplaceString = "DEVILBRO_BD_GOOGLESEARCHREPLACE_REPLACE_TEXTURL";
this.defaults = {
engines: {
_all: {value:true, name:BDFDB.getLibraryStrings().btn_all_text, url:null},
Ask: {value:true, name:"Ask", url:"https://ask.com/web?q=" + this.textUrlReplaceString},
Bing: {value:true, name:"Bing", url:"https://www.bing.com/search?q=" + this.textUrlReplaceString},
DogPile: {value:true, name:"DogPile", url:"http://www.dogpile.com/search/web?q=" + this.textUrlReplaceString},
DuckDuckGo: {value:true, name:"DuckDuckGo", url:"https://duckduckgo.com/?q=" + this.textUrlReplaceString},
Google: {value:true, name:"Google", url:"https://www.google.com/search?q=" + this.textUrlReplaceString},
GoogleScholar: {value:true, name:"Google Scholar", url:"https://scholar.google.com/scholar?q=" + this.textUrlReplaceString},
Quora: {value:true, name:"Quora", url:"https://www.quora.com/search?q=" + this.textUrlReplaceString},
Qwant: {value:true, name:"Qwant", url:"https://www.qwant.com/?t=all&q=" + this.textUrlReplaceString},
Searx: {value:true, name:"Searx", url:"https://searx.me/?q=" + this.textUrlReplaceString},
WolframAlpha: {value:true, name:"Wolfram Alpha", url:"https://www.wolframalpha.com/input/?i=" + this.textUrlReplaceString},
Yandex: {value:true, name:"Yandex", url:"https://yandex.com/search/?text=" + this.textUrlReplaceString},
Yahoo: {value:true, name:"Yahoo", url:"https://search.yahoo.com/search?p=" + this.textUrlReplaceString},
YouTube: {value:true, name:"YouTube", url:"https://www.youtube.com/results?q=" + this.textUrlReplaceString}
}
};
this.messageContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitem} googlereplacesearch-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>REPLACE_context_googlesearchreplace_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>`;
this.messageContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} googleReplaceSearchSubMenu">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} alldisabled-item ${BDFDB.disCN.contextmenuitemdisabled}">
<span>REPLACE_submenu_disabled_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
${Object.keys(this.defaults.engines).map((key, i) => `<div engine="${key}" class="${BDFDB.disCN.contextmenuitem} GRS-item"><span>${this.defaults.engines[key].name}</span><div class="${BDFDB.disCN.contextmenuhint}"></div></div>`).join("")}
</div>
</div>`;
}
getName () {return "GoogleSearchReplace";}
getDescription () {return "Replaces the default Google Text Search with a selection menu of several search engines.";}
getVersion () {return "1.1.4";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var engines = BDFDB.getAllData(this, "engines");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Search Engines:</h3></div><div class="DevilBro-settings-inner-list">`;
for (let key in engines) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.engines[key].name}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${engines[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"messageContextObserver",instance:observer}, {childList: true});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "engines");
}
changeLanguageStrings () {
this.messageContextEntryMarkup = this.messageContextEntryMarkup.replace("REPLACE_context_googlesearchreplace_text", this.labels.context_googlesearchreplace_text);
this.messageContextSubMenuMarkup = this.messageContextSubMenuMarkup.replace("REPLACE_submenu_disabled_text", this.labels.submenu_disabled_text);
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".googlereplacesearch-item")) return;
for (let group of context.querySelectorAll(BDFDB.dotCN.contextmenuitemgroup)) {
if (BDFDB.getKeyInformation({"node":group, "key":"handleSearchWithGoogle"})) {
var text = BDFDB.getKeyInformation({"node":group, "key":"value"});
if (text) {
$(group).find(BDFDB.dotCN.contextmenuitem).hide();
$(group).append(this.messageContextEntryMarkup)
.on("mouseenter", ".googlereplacesearch-item", (e) => {
this.createContextSubMenu(text, e, context);
});
BDFDB.updateContextPosition(context);
}
break;
}
}
}
createContextSubMenu (text, e, context) {
var messageContextSubMenu = $(this.messageContextSubMenuMarkup);
messageContextSubMenu
.on("click", ".GRS-item", (e2) => {
$(context).hide();
var engine = e2.currentTarget.getAttribute("engine");
if (engine == "_all") {
var engines = BDFDB.getAllData(this, "engines");
for (let key in engines) {
if (key != "_all" && engines[key]) window.open(this.defaults.engines[key].url.replace(this.textUrlReplaceString, encodeURIComponent(text)), "_blank");
}
}
else {
window.open(this.defaults.engines[engine].url.replace(this.textUrlReplaceString, encodeURIComponent(text)), "_blank");
}
});
var engines = BDFDB.getAllData(this, "engines");
for (let key in engines) {
if (!engines[key]) messageContextSubMenu.find("[engine='" + key + "']").remove();
}
if (messageContextSubMenu.find(".GRS-item").length > 0) {
messageContextSubMenu.find(".alldisabled-item").remove();
}
BDFDB.appendSubMenu(e.currentTarget, messageContextSubMenu);
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
context_googlesearchreplace_text: "Pretražujte s ...",
submenu_disabled_text: "Svi su onemogućeni"
};
case "da": //danish
return {
context_googlesearchreplace_text: "Søg med ...",
submenu_disabled_text: "Alle deaktiveret"
};
case "de": //german
return {
context_googlesearchreplace_text: "Suche mit ...",
submenu_disabled_text: "Alle deaktiviert"
};
case "es": //spanish
return {
context_googlesearchreplace_text: "Buscar con ...",
submenu_disabled_text: "Todo desactivado"
};
case "fr": //french
return {
context_googlesearchreplace_text: "Rechercher avec ...",
submenu_disabled_text: "Tous désactivés"
};
case "it": //italian
return {
context_googlesearchreplace_text: "Cerca con ...",
submenu_disabled_text: "Tutto disattivato"
};
case "nl": //dutch
return {
context_googlesearchreplace_text: "Zoeken met ...",
submenu_disabled_text: "Alles gedeactiveerd"
};
case "no": //norwegian
return {
context_googlesearchreplace_text: "Søk med ...",
submenu_disabled_text: "Alle deaktivert"
};
case "pl": //polish
return {
context_googlesearchreplace_text: "Szukaj za pomocą ...",
submenu_disabled_text: "Wszystkie wyłączone"
};
case "pt-BR": //portuguese (brazil)
return {
context_googlesearchreplace_text: "Pesquisar com ...",
submenu_disabled_text: "Todos desativados"
};
case "fi": //finnish
return {
context_googlesearchreplace_text: "Etsi ...",
submenu_disabled_text: "Kaikki on poistettu käytöstä"
};
case "sv": //swedish
return {
context_googlesearchreplace_text: "Sök med ...",
submenu_disabled_text: "Alla avaktiverade"
};
case "tr": //turkish
return {
context_googlesearchreplace_text: "Ile ara ...",
submenu_disabled_text: "Hepsi deaktive"
};
case "cs": //czech
return {
context_googlesearchreplace_text: "Hledat s ...",
submenu_disabled_text: "Všechny deaktivované"
};
case "bg": //bulgarian
return {
context_googlesearchreplace_text: "Търсене с ...",
submenu_disabled_text: "Всички са деактивирани"
};
case "ru": //russian
return {
context_googlesearchreplace_text: "Поиск с ...",
submenu_disabled_text: "Все деактивированные"
};
case "uk": //ukrainian
return {
context_googlesearchreplace_text: "Пошук з ...",
submenu_disabled_text: "Всі вимкнені"
};
case "ja": //japanese
return {
context_googlesearchreplace_text: "で検索する ...",
submenu_disabled_text: "すべて非アクティブ化"
};
case "zh-TW": //chinese (traditional)
return {
context_googlesearchreplace_text: "搜索 ...",
submenu_disabled_text: "全部停用"
};
case "ko": //korean
return {
context_googlesearchreplace_text: "다음으로 검색 ...",
submenu_disabled_text: "모두 비활성화 됨"
};
default: //default: english
return {
context_googlesearchreplace_text: "Search with ...",
submenu_disabled_text: "All disabled"
};
}
}
}

View File

@ -0,0 +1,3 @@
# Google Search Replace - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleSearchReplace/GoogleSearchReplace.plugin.js)
Replaces the default Google Text Search with a selection menu of several search engines.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
# Google Translate Option - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleTranslateOption/GoogleTranslateOption.plugin.js)
Adds a Google Translate option to your context menu, which shows a preview of the translated text and on click will open the selected text in Google Translate. Also adds a translation button to your textareas, which will automatically translate the text for you before it is being send.

View File

@ -0,0 +1,218 @@
//META{"name":"ImageGallery"}*//
class ImageGallery {
initConstructor () {
this.eventFired = false;
this.imageMarkup = `<div class="${BDFDB.disCN.imagewrapper}" style="width: 100px; height: 100px;"><img src="" style="width: 100px; height: 100px; display: inline;"></div>`;
this.css = `
.image-gallery ${BDFDB.dotCN.imagewrapper}.prev,
.image-gallery ${BDFDB.dotCN.imagewrapper}.next {
position: absolute;
}
.image-gallery ${BDFDB.dotCN.imagewrapper}.prev {
right: 90%;
}
.image-gallery ${BDFDB.dotCN.imagewrapper}.next {
left: 90%;
}`;
}
getName () {return "ImageGallery";}
getDescription () {return "Allows the user to browse through images sent inside the same message.";}
getVersion () {return "1.5.5";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.imagewrapper) && node.querySelector(BDFDB.dotCN.downloadlink)) {
this.loadImages(node);
}
});
}
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.imagewrapper) && node.querySelector(BDFDB.dotCN.downloadlink)) {
$(document).off("keyup." + this.getName()).off("keydown." + this.getName());
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.app + " ~ [class^='theme-']:not([class*='popouts'])", {name:"imageModalObserver",instance:observer}, {childList: true});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
loadImages (modal) {
var start = performance.now();
var waitForImg = setInterval(() => {
var img = modal.querySelector(BDFDB.dotCNS.imagewrapper + "img");
if (img && img.src) {
clearInterval(waitForImg);
var message = this.getMessageGroupOfImage(img);
if (message) {
modal.classList.add("image-gallery");
this.addImages(modal, message.querySelectorAll(BDFDB.dotCNS.imagewrapper + "img"), img);
}
}
else if (performance.now() - start > 10000) {
clearInterval(waitForImg);
}
}, 100);
}
getMessageGroupOfImage (thisimg) {
if (thisimg && thisimg.src) {
for (let group of document.querySelectorAll(BDFDB.dotCN.messagegroup)) {
for (let img of group.querySelectorAll(BDFDB.dotCNS.imagewrapper + "img")) {
if (img.src && this.getSrcOfImage(img) == this.getSrcOfImage(thisimg)) {
return group;
}
}
}
}
return null;
}
getSrcOfImage (img) {
var src = img.src ? img.src : (img.querySelector("canvas") ? img.querySelector("canvas").src : "");
return src.split("?width=")[0];
}
addImages (modal, imgs, img) {
modal.querySelectorAll(`${BDFDB.dotCN.imagewrapper}.prev, ${BDFDB.dotCN.imagewrapper}.next`).forEach(ele => {ele.remove();});
var prevImg, nextImg, index;
for (index = 0; index < imgs.length; index++) {
if (this.getSrcOfImage(img) == this.getSrcOfImage(imgs[index])) {
prevImg = imgs[index-1];
img = imgs[index];
nextImg = imgs[index+1];
break;
}
}
$(modal).find(BDFDB.dotCN.imagewrapper)
.addClass("current")
.find("img").attr("src", this.getSrcOfImage(img));
$(modal.querySelector(BDFDB.dotCN.downloadlink))
.attr("href", this.getSrcOfImage(img));
this.resizeImage(modal, img, modal.querySelector(BDFDB.dotCN.imagewrapper + ".current img"));
if (prevImg) {
$(this.imageMarkup)
.appendTo(modal.querySelector(BDFDB.dotCN.modalinner))
.addClass("prev")
.off("click." + this.getName()).on("click." + this.getName(), () => {
this.addImages(modal, imgs, prevImg);
})
.find("img").attr("src", this.getSrcOfImage(prevImg));
this.resizeImage(modal, prevImg, modal.querySelector(BDFDB.dotCN.imagewrapper + ".prev img"));
}
if (nextImg) {
$(this.imageMarkup)
.appendTo(modal.querySelector(BDFDB.dotCN.modalinner))
.addClass("next")
.off("click." + this.getName()).on("click." + this.getName(), () => {
this.addImages(modal, imgs, nextImg);
})
.find("img").attr("src", this.getSrcOfImage(nextImg));
this.resizeImage(modal, nextImg, modal.querySelector(BDFDB.dotCN.imagewrapper + ".next img"));
}
$(document).off("keydown." + this.getName()).off("keyup." + this.getName())
.on("keydown." + this.getName(), (e) => {
this.keyPressed({modal, imgs, prevImg, nextImg}, e);
})
.on("keyup." + this.getName(), () => {
this.eventFired = false;
});
}
resizeImage (container, src, img) {
$(img).hide();
var temp = new Image();
temp.src = src.src.split("?width=")[0];
temp.onload = function () {
var resizeX = (container.clientWidth/src.clientWidth) * 0.71;
var resizeY = (container.clientHeight/src.clientHeight) * 0.57;
var resize = resizeX < resizeY ? resizeX : resizeY;
var newWidth = src.clientWidth * resize;
var newHeight = src.clientHeight * resize;
newWidth = temp.width > newWidth ? newWidth : temp.width;
newHeight = temp.height > newHeight ? newHeight : temp.height;
var wrapper = img.parentElement;
$(wrapper)
.css("top", !wrapper.classList.contains("current") ? (container.clientHeight - newHeight) / 2 : "")
.css("width", newWidth)
.css("height", newHeight);
$(img)
.css("width", newWidth)
.css("height", newHeight)
.show();
};
}
keyPressed (data, e) {
if (!this.eventFired) {
this.eventFired = true;
if (e.keyCode == 37 && data.prevImg) {
this.addImages(data.modal, data.imgs, data.prevImg);
}
else if (e.keyCode == 39 && data.nextImg) {
this.addImages(data.modal, data.imgs, data.nextImg);
}
}
}
}

View File

@ -0,0 +1,3 @@
# Image Gallery - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ImageGallery/ImageGallery.plugin.js)
Allows the user to browse through images sent inside the same message.

View File

@ -0,0 +1,387 @@
//META{"name":"MessageUtilities"}*//
class MessageUtilities {
initConstructor () {
this.bindings = {};
this.firedEvents = [];
this.clickMap = ["SINGLE" /*[0]*/, "DOUBLE" /*[1]*/];
this.keyboardMap = [
"NONE" /*[0]*/, "" /*[1]*/, "" /*[2]*/, "CANCEL" /*[3]*/, "" /*[4]*/, "" /*[5]*/, "HELP" /*[6]*/, "" /*[7]*/, "BACK_SPACE" /*[8]*/, "TAB" /*[9]*/, "" /*[10]*/, "" /*[11]*/, "CLEAR" /*[12]*/, "ENTER" /*[13]*/, "ENTER_SPECIAL" /*[14]*/, "" /*[15]*/, "SHIFT" /*[16]*/, "CONTROL" /*[17]*/, "ALT" /*[18]*/, "PAUSE" /*[19]*/, "CAPS_LOCK" /*[20]*/, "KANA" /*[21]*/, "EISU" /*[22]*/, "JUNJA" /*[23]*/, "FINAL" /*[24]*/, "HANJA" /*[25]*/, "" /*[26]*/, "ESCAPE" /*[27]*/, "CONVERT" /*[28]*/, "NONCONVERT" /*[29]*/, "ACCEPT" /*[30]*/, "MODECHANGE" /*[31]*/, "SPACE" /*[32]*/, "PAGE_UP" /*[33]*/, "PAGE_DOWN" /*[34]*/, "END" /*[35]*/, "HOME" /*[36]*/, "LEFT" /*[37]*/, "UP" /*[38]*/, "RIGHT" /*[39]*/, "DOWN" /*[40]*/, "SELECT" /*[41]*/, "PRINT" /*[42]*/, "EXECUTE" /*[43]*/, "PRINTSCREEN" /*[44]*/, "INSERT" /*[45]*/, "DELETE" /*[46]*/, "" /*[47]*/,"0" /*[48]*/, "1" /*[49]*/, "2" /*[50]*/, "3" /*[51]*/, "4" /*[52]*/, "5" /*[53]*/, "6" /*[54]*/, "7" /*[55]*/, "8" /*[56]*/, "9" /*[57]*/, "COLON" /*[58]*/, "SEMICOLON" /*[59]*/, "LESS_THAN" /*[60]*/, "EQUALS" /*[61]*/, "GREATER_THAN" /*[62]*/, "QUESTION_MARK" /*[63]*/, "AT" /*[64]*/, "A" /*[65]*/, "B" /*[66]*/, "C" /*[67]*/, "D" /*[68]*/, "E" /*[69]*/, "F" /*[70]*/, "G" /*[71]*/, "H" /*[72]*/, "I" /*[73]*/, "J" /*[74]*/, "K" /*[75]*/, "L" /*[76]*/, "M" /*[77]*/, "N" /*[78]*/, "O" /*[79]*/, "P" /*[80]*/, "Q" /*[81]*/, "R" /*[82]*/, "S" /*[83]*/, "T" /*[84]*/, "U" /*[85]*/, "V" /*[86]*/, "W" /*[87]*/, "X" /*[88]*/, "Y" /*[89]*/, "Z" /*[90]*/, "OS_KEY" /*[91]*/, "" /*[92]*/, "CONTEXT_MENU" /*[93]*/, "" /*[94]*/, "SLEEP" /*[95]*/, "NUMPAD0" /*[96]*/, "NUMPAD1" /*[97]*/, "NUMPAD2" /*[98]*/, "NUMPAD3" /*[99]*/, "NUMPAD4" /*[100]*/, "NUMPAD5" /*[101]*/, "NUMPAD6" /*[102]*/, "NUMPAD7" /*[103]*/, "NUMPAD8" /*[104]*/, "NUMPAD9" /*[105]*/, "MULTIPLY" /*[106]*/, "ADD" /*[107]*/, "SEPARATOR" /*[108]*/, "SUBTRACT" /*[109]*/, "DECIMAL" /*[110]*/, "DIVIDE" /*[111]*/, "F1" /*[112]*/, "F2" /*[113]*/, "F3" /*[114]*/, "F4" /*[115]*/, "F5" /*[116]*/, "F6" /*[117]*/, "F7" /*[118]*/, "F8" /*[119]*/, "F9" /*[120]*/, "F10" /*[121]*/, "F11" /*[122]*/, "F12" /*[123]*/, "F13" /*[124]*/, "F14" /*[125]*/, "F15" /*[126]*/, "F16" /*[127]*/, "F17" /*[128]*/, "F18" /*[129]*/, "F19" /*[130]*/, "F20" /*[131]*/, "F21" /*[132]*/, "F22" /*[133]*/, "F23" /*[134]*/, "F24" /*[135]*/, "" /*[136]*/, "" /*[137]*/, "" /*[138]*/, "" /*[139]*/, "" /*[140]*/, "" /*[141]*/, "" /*[142]*/, "" /*[143]*/, "NUM_LOCK" /*[144]*/, "SCROLL_LOCK" /*[145]*/, "WIN_OEM_FJ_JISHO" /*[146]*/, "WIN_OEM_FJ_MASSHOU" /*[147]*/, "WIN_OEM_FJ_TOUROKU" /*[148]*/, "WIN_OEM_FJ_LOYA" /*[149]*/, "WIN_OEM_FJ_ROYA" /*[150]*/, "" /*[151]*/, "" /*[152]*/, "" /*[153]*/, "" /*[154]*/, "" /*[155]*/, "" /*[156]*/, "" /*[157]*/, "" /*[158]*/, "" /*[159]*/, "CIRCUMFLEX" /*[160]*/, "EXCLAMATION" /*[161]*/, "DOUBLE_QUOTE" /*[162]*/, "HASH" /*[163]*/, "DOLLAR" /*[164]*/, "PERCENT" /*[165]*/, "AMPERSAND" /*[166]*/, "UNDERSCORE" /*[167]*/, "OPEN_PAREN" /*[168]*/, "CLOSE_PAREN" /*[169]*/, "ASTERISK" /*[170]*/, "PLUS" /*[171]*/, "PIPE" /*[172]*/, "HYPHEN_MINUS" /*[173]*/, "OPEN_CURLY_BRACKET" /*[174]*/, "CLOSE_CURLY_BRACKET" /*[175]*/, "TILDE" /*[176]*/, "" /*[177]*/, "" /*[178]*/, "" /*[179]*/, "" /*[180]*/, "VOLUME_MUTE" /*[181]*/, "VOLUME_DOWN" /*[182]*/, "VOLUME_UP" /*[183]*/, "" /*[184]*/, "" /*[185]*/, "SEMICOLON" /*[186]*/, "EQUALS" /*[187]*/, "COMMA" /*[188]*/, "MINUS" /*[189]*/, "PERIOD" /*[190]*/, "SLASH" /*[191]*/, "BACK_QUOTE" /*[192]*/, "" /*[193]*/, "" /*[194]*/, "" /*[195]*/, "" /*[196]*/, "" /*[197]*/, "" /*[198]*/, "" /*[199]*/, "" /*[200]*/, "" /*[201]*/, "" /*[202]*/, "" /*[203]*/, "" /*[204]*/, "" /*[205]*/, "" /*[206]*/, "" /*[207]*/, "" /*[208]*/, "" /*[209]*/, "" /*[210]*/, "" /*[211]*/, "" /*[212]*/, "" /*[213]*/, "" /*[214]*/, "" /*[215]*/, "" /*[216]*/, "" /*[217]*/, "" /*[218]*/, "OPEN_BRACKET" /*[219]*/, "BACK_SLASH" /*[220]*/, "CLOSE_BRACKET" /*[221]*/, "QUOTE" /*[222]*/, "" /*[223]*/, "META" /*[224]*/, "ALTGR" /*[225]*/, "" /*[226]*/, "WIN_ICO_HELP" /*[227]*/, "WIN_ICO_00" /*[228]*/, "" /*[229]*/, "WIN_ICO_CLEAR" /*[230]*/, "" /*[231]*/,"" /*[232]*/, "WIN_OEM_RESET" /*[233]*/, "WIN_OEM_JUMP" /*[234]*/, "WIN_OEM_PA1" /*[235]*/, "WIN_OEM_PA2" /*[236]*/, "WIN_OEM_PA3" /*[237]*/, "WIN_OEM_WSCTRL" /*[238]*/,"WIN_OEM_CUSEL" /*[239]*/, "WIN_OEM_ATTN" /*[240]*/, "WIN_OEM_FINISH" /*[241]*/, "WIN_OEM_COPY" /*[242]*/, "WIN_OEM_AUTO" /*[243]*/, "WIN_OEM_ENLW" /*[244]*/, "WIN_OEM_BACKTAB" /*[245]*/, "ATTN" /*[246]*/, "CRSEL" /*[247]*/, "EXSEL" /*[248]*/, "EREOF" /*[249]*/, "PLAY" /*[250]*/, "ZOOM" /*[251]*/, "" /*[252]*/, "PA1" /*[253]*/, "WIN_OEM_CLEAR" /*[254]*/, "" /*[255]*/
];
this.clicks = ["click"];
this.keys = ["key1","key2"];
this.defaults = {
settings: {
"clearOnEscape": {value:true, description:"Clear chat input when Escape is pressed:"},
"Edit_Message": {value:true},
"Delete_Message": {value:true},
"Pin/Unpin_Message": {value:true},
"React_to_Message": {value:true},
"__Note_Message": {value:false},
"__Translate_Message": {value:false},
"__Quote_Message": {value:false},
"__Citate_Message": {value:false}
},
bindings: {
"Edit_Message": {name:"Edit Message", func:this.doEdit, value:{click:1, key1:0, key2:0}},
"Delete_Message": {name:"Delete Message", func:this.doDelete, value:{click:0, key1:46, key2:0}},
"Pin/Unpin_Message": {name:"Pin/Unpin Message", func:this.doPinUnPin, value:{click:0, key1:17, key2:0}},
"React_to_Message": {name:"React to Message", func:this.doOpenReact, value:{click:0, key1:9, key2:0}},
"__Note_Message": {name:"Note Message (Pesonal Pins)", func:this.doNote, value:{click:0, key1:16, key2:0}},
"__Translate_Message": {name:"Translate Message (Google Translate Option)", func:this.doTranslate, value:{click:0, key1:20, key2:0}},
"__Quote_Message": {name:"Quote Message (Quoter)", func:this.doQuote, value:{click:0, key1:113, key2:0}},
"__Citate_Message": {name:"Quote Message (Citador)", func:this.doCitate, value:{click:0, key1:114, key2:0}}
}
};
}
getName () {return "MessageUtilities";}
getDescription () {return "Offers a number of useful message options. Remap the keybindings in the settings.";}
getVersion () {return "1.4.0";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var bindings = BDFDB.getAllData(this, "bindings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
if (this.defaults.settings[key].description) settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
for (let action in bindings) {
settingshtml += `<div class="${action}-key-settings"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.bindings[action].name}:</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${action}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[action] ? " checked" : ""}></div></div><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">`;
for (let click of this.clicks) {
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 20%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">${click}:</h5><div class="${BDFDB.disCN.selectwrap}"><div type="${action}" option="${click}" value="${bindings[action][click]}" class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="padding:0;">${this.clickMap[bindings[action][click]]}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div></div></div>`;
}
for (let key of this.keys) {
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 40%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">${key}:<label class="reset-recorder" style="float:right;padding-right:5px;cursor:pointer;">✖</label></h5><div type="${action}" option="${key}" value="${bindings[action][key]}" class="${BDFDB.disCNS.hotkeycontainer + BDFDB.disCNS.hotkeycontainer2 + BDFDB.disCN.hotkeyhasvalue}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.hotkeylayout + BDFDB.disCN.hotkeylayout2}" style="flex: 1 1 auto;"><input type="text" placeholder="${this.keyboardMap[bindings[action][key]]}" readonly="" value="${this.keyboardMap[bindings[action][key]]}" class="${BDFDB.disCNS.hotkeyinput + BDFDB.disCNS.hotkeyinput2 + BDFDB.disCN.hotkeybase}" style="flex: 1 1 auto;"></input><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCN.nowrap}" style="flex: 0 1 auto; margin: 0px;"><button type="button" class="${BDFDB.disCNS.hotkeybutton + BDFDB.disCNS.hotkeybutton2 + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookghost + BDFDB.disCNS.buttoncolorgrey + BDFDB.disCNS.buttonsizemin + BDFDB.disCN.buttongrow}"><div class="${BDFDB.disCN.buttoncontents}"><span class="${BDFDB.disCN.hotkeytext}">${BDFDB.LanguageStrings.SHORTCUT_RECORDER_BUTTON_EDIT}</span><span class="${BDFDB.disCN.hotkeyediticon}"/></div></button></div></div></div></div>`;
}
settingshtml += `</div></div>`;
}
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Reset all key bindings.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu(settingspanel, e);})
.on("click", BDFDB.dotCN.hotkeycontainer, (e) => {this.startRecording(settingspanel, e);})
.on("click", ".reset-recorder", (e) => {this.resetRecorder(settingspanel, e);})
.on("click", ".reset-button", () => {this.resetAll(settingspanel);});
$(settingspanel).find(".__Note_Message-key-settings").toggle(BDFDB.isPluginEnabled("PersonalPins") == true);
$(settingspanel).find(".__Translate_Message-key-settings").toggle(BDFDB.isPluginEnabled("GoogleTranslateOption") == true);
$(settingspanel).find(".__Quote_Message-key-settings").toggle(BDFDB.isPluginEnabled("Quoter") == true);
$(settingspanel).find(".__Citate_Message-key-settings").toggle(BDFDB.isPluginEnabled("Citador") == true);
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.ChannelStore = BDFDB.WebModules.findByProperties(["getChannel", "getChannels"]);
this.MessageActions = BDFDB.WebModules.findByProperties(["startEditMessage", "endEditMessage"]);
this.PinActions = BDFDB.WebModules.findByProperties(["pinMessage", "unpinMessage"]);
this.CurrentUserPerms = BDFDB.WebModules.findByProperties(["getChannelPermissions", "can"]);
this.Permissions = BDFDB.WebModules.findByProperties(["Permissions", "ActivityTypes"]).Permissions
$(document)
.on("click." + this.getName(), BDFDB.dotCNC.message + BDFDB.dotCN.messagesystem, (e) => {
this.onClick(e.currentTarget, 0, "onSglClick");
})
.on("dblclick." + this.getName(), BDFDB.dotCNC.message + BDFDB.dotCN.messagesystem, (e) => {
this.onClick(e.currentTarget, 1, "onDblClick");
})
.on("keydown." + this.getName(), BDFDB.dotCN.textareawrapchat, (e) => {
this.onKeyDown(e.currentTarget, e.which, "onKeyDown");
});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(document).off("click." + this.getName(), BDFDB.dotCNC.message + BDFDB.dotCN.messagesystem);
$(document).off("dblclick." + this.getName(), BDFDB.dotCNC.message + BDFDB.dotCN.messagesystem);
$(document).off("keydown." + this.getName(), BDFDB.dotCN.textareawrapchat);
BDFDB.unloadMessage(this);
}
}
//begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
resetAll (settingspanel) {
if (confirm("Are you sure you want to delete all key bindings?")) {
BDFDB.removeAllData(this, "bindings");
var bindings = BDFDB.getAllData(this, "bindings");
settingspanel.querySelectorAll(BDFDB.dotCN.select).forEach((wrap) => {
var action = wrap.getAttribute("type");
var option = wrap.getAttribute("option");
wrap.setAttribute("value", bindings[action][option]);
wrap.querySelector(BDFDB.dotCN.title).innerText = this.clickMap[bindings[action][option]];
});
settingspanel.querySelectorAll(BDFDB.dotCN.hotkeycontainer).forEach((wrap) => {
var action = wrap.getAttribute("type");
var option = wrap.getAttribute("option");
wrap.setAttribute("value", bindings[action][option]);
wrap.querySelector("input").setAttribute("value", this.keyboardMap[bindings[action][option]]);
});;
}
}
openDropdownMenu (settingspanel, e) {
var selectControl = e.currentTarget;
var selectWrap = e.currentTarget.parentElement;
if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return;
selectWrap.classList.add(BDFDB.disCN.selectisopen);
var action = selectWrap.getAttribute("type");
var option = selectWrap.getAttribute("option");
var value = selectWrap.getAttribute("value");
var selectMenu = this.createDropdownMenu(action, value);
selectWrap.appendChild(selectMenu);
$(selectMenu).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => {
var binding = BDFDB.getData(action, this, "bindings");
var selection = e2.currentTarget.getAttribute("value");
selectWrap.setAttribute("value", selection);
selectControl.querySelector(BDFDB.dotCN.title).innerText = e2.currentTarget.textContent;
binding[option] = parseInt(selection);
BDFDB.saveData(action, binding, this, "bindings");
});
$(document).on("mousedown.select" + this.getName(), (e2) => {
if (e2.target.parentElement == selectMenu) return;
$(document).off("mousedown.select" + this.getName());
selectMenu.remove()
setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100);
});
}
createDropdownMenu (action, value) {
var menuhtml = `<div class="${BDFDB.disCN.selectmenuouter}"><div class="${BDFDB.disCN.selectmenu}">`;
for (var i in this.clickMap) {
var isSelected = i == value ? ` ${BDFDB.disCN.selectselected}` : ``;
menuhtml += `<div value="${i}" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectoption + isSelected}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}">${this.clickMap[i]}</div></div>`
}
menuhtml += `</div></div>`;
return $(menuhtml)[0];
}
startRecording (settingspanel, e) {
var recorderWrap = e.currentTarget;
if (recorderWrap.classList.contains(BDFDB.disCN.hotkeyrecording)) return;
var recorderInput = recorderWrap.querySelector("input");
var recorderText = recorderWrap.querySelector(BDFDB.dotCN.hotkeytext);
var action = recorderWrap.getAttribute("type");
var option = recorderWrap.getAttribute("option");
recorderWrap.classList.add(BDFDB.disCN.hotkeyrecording);
recorderWrap.classList.remove(BDFDB.disCN.hotkeyhasvalue);
recorderText.innerText = BDFDB.LanguageStrings.SHORTCUT_RECORDER_BUTTON_RECORDING;
$(document).on("keydown.recorder" + this.getName(), (e) => {
recorderWrap.setAttribute("value", e.which);
recorderInput.setAttribute("value", this.keyboardMap[e.which]);
});
$(document).on("mousedown.recorder" + this.getName(), () => {
$(document).off("mousedown.recorder" + this.getName());
$(document).off("keydown.recorder" + this.getName());
var binding = BDFDB.getData(action, this, "bindings");
binding[option] = parseInt(recorderWrap.getAttribute("value"));
BDFDB.saveData(action, binding, this, "bindings");
setTimeout(() => {
recorderWrap.classList.remove(BDFDB.disCN.hotkeyrecording);
recorderWrap.classList.add(BDFDB.disCN.hotkeyhasvalue);
recorderText.innerText = BDFDB.LanguageStrings.SHORTCUT_RECORDER_BUTTON_EDIT;
},100);
});
}
resetRecorder (settingspanel, e) {
var resetButton = e.currentTarget;
var recorderWrap = e.currentTarget.parentElement.parentElement.querySelector(BDFDB.dotCN.hotkeycontainer);
var recorderInput = recorderWrap.querySelector("input");
var action = recorderWrap.getAttribute("type");
var option = recorderWrap.getAttribute("option");
recorderWrap.setAttribute("value", 0);
recorderInput.setAttribute("value", this.keyboardMap[0]);
var binding = BDFDB.getData(action, this, "bindings");
binding[option] = parseInt(recorderWrap.getAttribute("value"));
BDFDB.saveData(action, binding, this, "bindings");
}
onClick (div, click, name) {
if (!this.isEventFired(name)) {
this.fireEvent(name);
var settings = BDFDB.getAllData(this, "settings");
var bindings = BDFDB.getAllData(this, "bindings")
for (let action in bindings) {
if (settings[action] && this.checkIfBindingIsValid(bindings[action], click)) {
var message = this.getMessageData(div);
if (message) this.defaults.bindings[action].func.bind(this)(message);
break;
}
}
this.cancelEvent(name);
}
}
checkIfBindingIsValid (binding, doneclick) {
var valid = true;
for (let click of this.clicks) {
if (binding[click] != doneclick) valid = false;
}
for (let key of this.keys) {
if (!BDFDB.pressedKeys.includes(binding[key]) && binding[key] != 0) valid = false;
}
return valid;
}
doDelete (message) {
var channel = this.ChannelStore.getChannel(message.channel_id);
if ((channel && this.CurrentUserPerms.can(this.Permissions.MANAGE_MESSAGES, channel)) || message.author.id == BDFDB.myData.id) {
this.MessageActions.deleteMessage(message.channel_id, message.id);
}
}
doEdit (message) {
if (message.author.id == BDFDB.myData.id) {
this.MessageActions.startEditMessage(message.channel_id, message.id, message.content);
}
}
doOpenReact (message) {
var reactButton = message.div.querySelector(BDFDB.dotCN.emojipickerbutton);
if (reactButton) reactButton.click();
}
doPinUnPin (message) {
var channel = this.ChannelStore.getChannel(message.channel_id);
if (channel && this.CurrentUserPerms.can(this.Permissions.MANAGE_MESSAGES, channel)) {
if (message.pinned) this.PinActions.unpinMessage(channel, message.id);
else this.PinActions.pinMessage(channel, message.id);
}
}
doNote (message) {
if (BDFDB.isPluginEnabled("PersonalPins") == true) {
var PersonalPins = window.bdplugins["PersonalPins"].plugin;
PersonalPins.getMessageData(message.div);
PersonalPins.addMessageToNotes();
}
}
doTranslate (message) {
if (BDFDB.isPluginEnabled("GoogleTranslateOption") == true) {
var GoogleTranslateOption = window.bdplugins["GoogleTranslateOption"].plugin;
GoogleTranslateOption.getMessageData(message.div);
GoogleTranslateOption.translateMessage();
}
}
doQuote (message) {
if (BDFDB.isPluginEnabled("Quoter") == true) {
var quoteButton = message.div.querySelector(".btn-quote");
if (quoteButton) quoteButton.click();
}
}
doCitate (message) {
if (BDFDB.isPluginEnabled("Citador") == true) {
var citarButton = message.div.parentElement.querySelector(".citar-btn");
if (citarButton) citarButton.click();
}
}
onKeyDown (div, key, name) {
if (!this.isEventFired(name)) {
this.fireEvent(name);
if (key == 27 && BDFDB.getData("clearOnEscape", this, "settings")) {
var instance = BDFDB.getOwnerInstance({"node":div, "name":"ChannelTextAreaForm", "up":true});
if (instance) instance.setState({textValue:""});
}
this.cancelEvent(name);
}
}
getMessageGroup (message) {
var messagegroup = null;
while (messagegroup == null || message.parentElement) {
message = message.parentElement;
if (message.classList && message.classList.contains(BDFDB.disCN.messagegroup)) messagegroup = message;
}
return messagegroup;
}
getMessageData (div) {
if (div) {
var messagegroup = this.getMessageGroup(div);
var pos = Array.from(messagegroup.querySelectorAll(BDFDB.dotCNC.message + BDFDB.dotCN.messagesystem)).indexOf(div);
var instance = BDFDB.getReactInstance(messagegroup);
if (!instance) return;
var info = instance.return.stateNode.props.messages;
if (info && pos > -1) return Object.assign({},info[pos],{"div":div, "group":messagegroup, "pos":pos});
}
return null;
}
fireEvent (name) {
this.firedEvents.push(name);
}
isEventFired (name) {
return this.firedEvents.includes(name);
}
cancelEvent (name) {
BDFDB.removeFromArray(this.firedEvents, name);
}
}

View File

@ -0,0 +1,3 @@
# MessageUtilities - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/MessageUtilities/MessageUtilities.plugin.js)
Offers a number of useful message options. Remap the keybindings in the settings.

View File

@ -0,0 +1,130 @@
//META{"name":"MoveablePopups"}*//
class MoveablePopups {
initConstructor () {
}
getName () {return "MoveablePopups";}
getDescription () {return "Adds the feature to move all popups and modals around like on a normal desktop. Ctrl + drag with your left mousebutton to drag element.";}
getVersion () {return "1.1.0";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.classList && node.classList.length > 0 && node.classList.contains(BDFDB.disCN.popout)) {
this.makeMoveable(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"popoutObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.classList && node.classList.contains(BDFDB.disCN.modal) && !node.querySelector(BDFDB.dotCN.downloadlink)) {
this.makeMoveable(node.querySelector(BDFDB.dotCN.modalinner));
}
else if (node && node.tagName && node.querySelector(BDFDB.dotCN.modal) && !node.querySelector(BDFDB.dotCN.downloadlink)) {
this.makeMoveable(node.querySelector(BDFDB.dotCN.modalinner));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.app + " ~ [class^='theme-']:not([class*='popouts'])", {name:"modalObserver",instance:observer}, {childList: true});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
makeMoveable (div) {
$(div)
.off("mousedown." + this.getName()).off("click." + this.getName())
.on("click." + this.getName(), (e) => {
if (this.dragging) {
e.stopPropagation();
e.preventDefault();
}
})
.on("mousedown." + this.getName(), (e) => {
if (e.ctrlKey) {
this.dragging = true;
var disableTextSelectionCSS = `
* {
user-select: none !important;
}`;
BDFDB.appendLocalStyle("disableTextSelection", disableTextSelectionCSS);
var left = div.getBoundingClientRect().left;
var top = div.getBoundingClientRect().top;
var oldX = e.pageX;
var oldY = e.pageY;
$(document)
.off("mouseup." + this.getName()).off("mousemove." + this.getName())
.on("mouseup." + this.getName(), () => {
BDFDB.removeLocalStyle("disableTextSelection");
$(document).off("mouseup." + this.getName()).off("mousemove." + this.getName());
setTimeout(() => {this.dragging = false},1);
})
.on("mousemove." + this.getName(), (e2) => {
var newX = e2.pageX;
var newY = e2.pageY;
left = left - (oldX - newX);
top = top - (oldY - newY);
oldX = newX;
oldY = newY;
$(div).offset({"left":left,"top":top});
});
}
});
}
}

View File

@ -0,0 +1,3 @@
# Moveable Popups - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/MoveablePopups/MoveablePopups.plugin.js)
Adds the feature to move all popups and modals around like on a normal desktop. Ctrl + drag with your left mousebutton to drag element.

View File

@ -0,0 +1,505 @@
//META{"name":"NotificationSounds"}*//
class NotificationSounds {
initConstructor () {
this.patchCancels = [];
this.types = {
"message1": {implemented:true, name:"New Chatmessage", src:"/assets/dd920c06a01e5bb8b09678581e29d56f.mp3"},
"dm": {implemented:true, name:"Direct Message", src:"/assets/84c9fa3d07da865278bd77c97d952db4.mp3"},
"mentioned": {implemented:true, name:"Mention Ping", src:"/assets/a5f42064e8120e381528b14fd3188b72.mp3"},
"deafen": {implemented:true, name:"Voicechat Deafen", src:"/assets/e4d539271704b87764dc465b1a061abd.mp3"},
"mute": {implemented:true, name:"Voicechat Mute", src:"/assets/429d09ee3b86e81a75b5e06d3fb482be.mp3"},
"disconnect": {implemented:true, name:"Voicechat Disconnect", src:"/assets/7e125dc075ec6e5ae796e4c3ab83abb3.mp3"},
"undeafen": {implemented:true, name:"Voicechat Undeafen", src:"/assets/5a000a0d4dff083d12a1d4fc2c7cbf66.mp3"},
"unmute": {implemented:true, name:"Voicechat Unmute", src:"/assets/43805b9dd757ac4f6b9b58c1a8ee5f0d.mp3"},
"user_join": {implemented:true, name:"Voicechat User Joined", src:"/assets/5dd43c946894005258d85770f0d10cff.mp3"},
"user_leave": {implemented:true, name:"Voicechat User Left", src:"/assets/4fcfeb2cba26459c4750e60f626cebdc.mp3"},
"user_moved": {implemented:true, name:"Voicechat User Moved", src:"/assets/e81d11590762728c1b811eadfa5be766.mp3"},
"ptt_start": {implemented:true, name:"Push2Talk Start", src:"/assets/8b63833c8d252fedba6b9c4f2517c705.mp3"},
"ptt_stop": {implemented:true, name:"Push2Talk Stop", src:"/assets/74ab980d6890a0fa6aa0336182f9f620.mp3"},
"call_calling": {implemented:true, name:"Outgoing Call", src:"/assets/c6e92752668dde4eee5923d70441579f.mp3"},
"call_ringing": {implemented:true, name:"Incoming Call", src:"/assets/84a1b4e11d634dbfa1e5dd97a96de3ad.mp3"},
"call_ringing_beat": {implemented:false, name:"Incoming Call Beat", src:"/assets/b9411af07f154a6fef543e7e442e4da9.mp3"},
"ddr-down": {implemented:true, name:"HotKeys Window Down", src:"/assets/71f048f8aa7d4b24bf4268a87cbbb192.mp3"},
"ddr-left": {implemented:true, name:"HotKeys Window Left", src:"/assets/1de04408e62b5d52ae3ebbb91e9e1978.mp3"},
"ddr-right": {implemented:true, name:"HotKeys Window Right", src:"/assets/2c0433f93db8449e4a82b76dc520cb29.mp3"},
"ddr-up": {implemented:true, name:"HotKeys Window Up", src:"/assets/68472713f7a62c7c37e0a6a5d5a1faeb.mp3"},
"human_man": {implemented:false, name:"Human Man Voice", src:"/assets/a37dcd6272ae41cf49295d58c9806fe3.mp3"},
"mention1": {implemented:false, name:"Mention Ping 1", src:"/assets/fa4d62c3cbc80733bf1f01b9c6f181de.mp3"},
"mention2": {implemented:false, name:"Mention Ping 2", src:"/assets/a5f42064e8120e381528b14fd3188b72.mp3"},
"mention3": {implemented:false, name:"Mention Ping 3", src:"/assets/84c9fa3d07da865278bd77c97d952db4.mp3"},
"message2": {implemented:false, name:"New Chatmessage 2", src:"/assets/15fe810f6cfab609c7fcda61652b9b34.mp3"},
"message3": {implemented:false, name:"New Chatmessage 3", src:"/assets/53ce6a92d3c233e8b4ac529d34d374e4.mp3"},
"overlayunlock": {implemented:false, name:"Overlay Unlocked", src:"/assets/ad322ffe0a88436296158a80d5d11baa.mp3"},
"reconnect": {implemented:false, name:"Voicechat Reconnect", src:"/assets/471cfd0005b112ff857705e894bf41a6.mp3"},
"robot_man": {implemented:false, name:"Robot Man Voice", src:"/assets/66598bea6e59eb8acdf32cf2d9d75ba9.mp3"}
};
this.defaults = {
"---": {
"---": null
},
"Default": {
"Communication Channel": "https://notificationsounds.com/soundfiles/63538fe6ef330c13a05a3ed7e599d5f7/file-sounds-917-communication-channel.wav",
"Isn't it": "https://notificationsounds.com/soundfiles/ba2fd310dcaa8781a9a652a31baf3c68/file-sounds-969-isnt-it.wav",
"Job Done": "https://notificationsounds.com/soundfiles/5b69b9cb83065d403869739ae7f0995e/file-sounds-937-job-done.wav",
"Served": "https://notificationsounds.com/soundfiles/b337e84de8752b27eda3a12363109e80/file-sounds-913-served.wav",
"Solemn": "https://notificationsounds.com/soundfiles/53fde96fcc4b4ce72d7739202324cd49/file-sounds-882-solemn.wav",
"System Fault": "https://notificationsounds.com/soundfiles/ebd9629fc3ae5e9f6611e2ee05a31cef/file-sounds-990-system-fault.wav",
"You wouldn't believe": "https://notificationsounds.com/soundfiles/087408522c31eeb1f982bc0eaf81d35f/file-sounds-949-you-wouldnt-believe.wav"
},
"Discord": {
"HotKeys Window Down": "/assets/71f048f8aa7d4b24bf4268a87cbbb192.mp3",
"HotKeys Window Left": "/assets/1de04408e62b5d52ae3ebbb91e9e1978.mp3",
"HotKeys Window Right": "/assets/2c0433f93db8449e4a82b76dc520cb29.mp3",
"HotKeys Window Up": "/assets/68472713f7a62c7c37e0a6a5d5a1faeb.mp3",
"Human Man Voice": "/assets/a37dcd6272ae41cf49295d58c9806fe3.mp3",
"Incoming Call": "/assets/84a1b4e11d634dbfa1e5dd97a96de3ad.mp3",
"Incoming Call Beat": "/assets/b9411af07f154a6fef543e7e442e4da9.mp3",
"Mention Ping 1": "/assets/fa4d62c3cbc80733bf1f01b9c6f181de.mp3",
"Mention Ping 2": "/assets/a5f42064e8120e381528b14fd3188b72.mp3",
"Mention Ping 3": "/assets/84c9fa3d07da865278bd77c97d952db4.mp3",
"New Chatmessage 1": "/assets/dd920c06a01e5bb8b09678581e29d56f.mp3",
"New Chatmessage 2": "/assets/15fe810f6cfab609c7fcda61652b9b34.mp3",
"New Chatmessage 3": "/assets/53ce6a92d3c233e8b4ac529d34d374e4.mp3",
"Outgoing Call": "/assets/c6e92752668dde4eee5923d70441579f.mp3",
"Overlay Unlocked": "/assets/ad322ffe0a88436296158a80d5d11baa.mp3",
"Push2Talk Start": "/assets/8b63833c8d252fedba6b9c4f2517c705.mp3",
"Push2Talk Stop": "/assets/74ab980d6890a0fa6aa0336182f9f620.mp3",
"Robot Man Voice": "/assets/66598bea6e59eb8acdf32cf2d9d75ba9.mp3",
"Voicechat Deafen": "/assets/e4d539271704b87764dc465b1a061abd.mp3",
"Voicechat Disconnect": "/assets/7e125dc075ec6e5ae796e4c3ab83abb3.mp3",
"Voicechat Mute": "/assets/429d09ee3b86e81a75b5e06d3fb482be.mp3",
"Voicechat Undeafen": "/assets/5a000a0d4dff083d12a1d4fc2c7cbf66.mp3",
"Voicechat Unmute": "/assets/43805b9dd757ac4f6b9b58c1a8ee5f0d.mp3",
"Voicechat User Joined": "/assets/5dd43c946894005258d85770f0d10cff.mp3",
"Voicechat User Left": "/assets/4fcfeb2cba26459c4750e60f626cebdc.mp3",
"Voicechat User Moved": "/assets/e81d11590762728c1b811eadfa5be766.mp3",
"Voicechat Reconnect": "/assets/471cfd0005b112ff857705e894bf41a6.mp3"
}
};
this.settingsaudio = new Audio();
this.audios = {};
this.choices = [];
this.firedEvents = {};
this.hasPatchedOutgoing = false;
}
getName () {return "NotificationSounds";}
getDescription () {return "Allows you to replace the native sounds of Discord with your own";}
getVersion () {return "3.1.9";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var fields = ["category","song"];
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="add-new-song-settings"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Add New Song:</h3></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">`;
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 50%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">Categoryname:</h5><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" placeholder="Category" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} songInput" id="input-category"></div></div>`;
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 50%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">Songname:</h5><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" placeholder="Name" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} songInput" id="input-song"></div></div>`;
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">`;
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">File:</h5><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" placeholder="Url or Filepath" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} songInput" id="input-url"></div><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} file-navigator" id="input-file" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div><input type="file" accept="audio/*,video/*" style="display:none!important;"></button><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-addsong" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div></div>`;
settingshtml += `</div>`;
settingshtml += `</div>`;
for (var type in this.types) {
var choice = BDFDB.loadData(type, this, "choices");
var unimplemented = this.types[type].implemented ? "" : " unimplemented";
settingshtml += `<div class="${type}-song-settings ${unimplemented}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">${this.types[type].name}:</h3></div><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">`;
for (var key of fields) {
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 33%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">${key}:</h5><div class="${BDFDB.disCN.selectwrap}"><div type="${type}" option="${key}" value="${choice[key]}" class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="padding:0;">${choice[key]}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div></div></div>`;
}
settingshtml += `<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 33%;"><h5 class="${BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin + BDFDB.disCN.marginbottom4}">volume:</h5><div type="${type}" class="${BDFDB.disCN.slider}"><input type="number" class="${type}-volume ${BDFDB.disCN.sliderinput} volumeInput" value="${choice.volume}" readonly=""><div class="${BDFDB.disCN.sliderbar}"><div class="${BDFDB.disCN.sliderbarfill}" style="width: ${choice.volume}%;"></div></div><div class="${BDFDB.disCN.slidertrack}"><div class="${BDFDB.disCN.slidergrabber} marginTop" style="left: ${choice.volume}%;"></div></div></div></div>`;
settingshtml += `</div></div>`;
}
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Show unimplemented Sounds</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-unimplemented"></div></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Remove all added songs.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu(settingspanel, e);})
.on("click", ".btn-addsong", (e) => {this.saveAudio(settingspanel);})
.on("keyup", ".songInput", (e) => {if (e.which == 13) this.saveAudio(settingspanel);})
.on("click", ".reset-button", () => {this.resetAll(settingspanel);})
.on("click", "#input-unimplemented", (e) => {
$(settingspanel).find(".unimplemented").toggle(e.currentTarget.checked);
})
.on("mousedown", BDFDB.dotCN.slidergrabber, (e) => {this.dragSlider(settingspanel,e);})
.find(".unimplemented").hide();
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.ChannelSettingsModule = BDFDB.WebModules.findByProperties(["isChannelMuted"]);
this.patchCancels.push(BDFDB.WebModules.monkeyPatch(BDFDB.WebModules.findByProperties(["receiveMessage"]), "receiveMessage", {before: (e) => {
if (this.dontPlayAudio()) return;
let message = e.methodArguments[1];
if (message.author.id != BDFDB.myData.id) {
if (!message.guild_id) {
if (!this.ChannelSettingsModule.isChannelMuted(null, message.channel_id)) {
this.fireEvent("dm");
this.playAudio("dm");
}
}
else if (message.mentions) {
for (let mention of message.mentions) if (mention.id == BDFDB.myData.id) {
this.fireEvent("mentioned");
this.playAudio("mentioned");
}
}
}
}}));
this.patchCancels.push(BDFDB.WebModules.monkeyPatch(BDFDB.WebModules.findByProperties(["playSound"]), "playSound", {instead: (e) => {
if (this.dontPlayAudio()) return;
setImmediate(() => {
var type = e.methodArguments[0];
if (type == "message1") {
if (this.firedEvents["dm"]) {
this.firedEvents["dm"] = false;
}
else if (this.firedEvents["mentioned"]) {
this.firedEvents["mentioned"] = false;
}
else this.playAudio(type);
}
else this.playAudio(type);
});
}}));
var incomingCallAudio = new Audio();
this.incomingCallOwnerInstance = BDFDB.getOwnerInstance({"node":document.querySelector(BDFDB.dotCN.callcontainer), "props":["startRinging","stopRinging"], "up":true});
this.oldStartRining = this.incomingCallOwnerInstance.startRinging;
this.oldStopRining = this.incomingCallOwnerInstance.stopRinging;
this.incomingCallOwnerInstance.startRinging = () => {
incomingCallAudio.pause();
if (this.dontPlayAudio()) return;
incomingCallAudio.loop = true;
incomingCallAudio.src = this.choices["call_ringing"].src;
incomingCallAudio.volume = this.choices["call_ringing"].volume/100;
incomingCallAudio.play();
};
this.incomingCallOwnerInstance.stopRinging = () => {incomingCallAudio.pause();};
this.loadAudios();
this.loadChoices();
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.classList.contains(BDFDB.disCN.callcurrentcontainer)) {
if (!this.hasPatchedOutgoing) {
var outgoingCallAudio = new Audio();
let play = () => {
if (this.dontPlayAudio()) return;
outgoingCallAudio.loop = true;
outgoingCallAudio.src = this.choices["call_calling"].src;
outgoingCallAudio.volume = this.choices["call_calling"].volume/100;
outgoingCallAudio.play();
};
let stop = () => {outgoingCallAudio.pause();}
var outgoingCallOwnerInstance = BDFDB.getOwnerInstance({"node":node, "props":["startRinging"], "up":true});
outgoingCallOwnerInstance.stopRinging();
outgoingCallOwnerInstance.startRinging = play;
outgoingCallOwnerInstance.stopRinging = stop;
let CallingWrap = outgoingCallOwnerInstance._reactInternalFiber.type;
this.patchCancels.push(BDFDB.WebModules.monkeyPatch(CallingWrap.prototype, "startRinging", {instead: play}));
this.patchCancels.push(BDFDB.WebModules.monkeyPatch(CallingWrap.prototype, "stopRinging", {instead: stop}));
this.hasPatchedOutgoing = true;
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCNS.chat, {name:"chatObserver",instance:observer}, {childList:true});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
if (typeof this.patchCancels === "object") for (let p of this.patchCancels) p();
this.incomingCallOwnerInstance.startRinging = this.oldStartRining;
this.incomingCallOwnerInstance.stopRinging = this.oldStopRining;
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
if (!this.hasPatchedOutgoing) BDFDB.addObserver(this, BDFDB.dotCNS.chat, {name:"chatObserver"}, {childList:true});
}
}
// begin of own functions
resetAll (settingspanel) {
if (confirm("Are you sure you want to delete all added songs?")) {
BDFDB.removeAllData(this, "choices");
BDFDB.removeAllData(this, "audios");
this.loadAudios();
this.loadChoices();
settingspanel.querySelectorAll(BDFDB.dotCN.select).forEach((wrap) => {
wrap.setAttribute("value", "---");
wrap.querySelector(BDFDB.dotCN.title).innerText = "---";
});
settingspanel.querySelectorAll(BDFDB.dotCN.slidergrabber).forEach((grabber) => {
grabber.style.left = "100%";
});
settingspanel.querySelectorAll(BDFDB.dotCN.sliderbarfill).forEach((bar) => {
bar.style.width = "100%";
});
settingspanel.querySelectorAll(".volumeInput").forEach((input) => {
input.value = 100;
});
}
}
openDropdownMenu (settingspanel, e) {
var selectControl = e.currentTarget;
var selectWrap = selectControl.parentElement;
if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return;
selectWrap.classList.add(BDFDB.disCN.selectisopen);
var type = selectWrap.getAttribute("type");
var option = selectWrap.getAttribute("option");
var categorySelect = settingspanel.querySelector(`${BDFDB.dotCN.select}[type="${type}"][option="category"]`);
var songSelect = settingspanel.querySelector(`${BDFDB.dotCN.select}[type="${type}"][option="song"]`);
var category = categorySelect.getAttribute("value");
var song = songSelect.getAttribute("value");
var selectMenu = this.createDropdownMenu({type, option, category, song});
selectWrap.appendChild(selectMenu);
$(selectMenu).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => {
var choice = BDFDB.loadData(type, this, "choices");
var selection = e2.currentTarget.textContent;
selectWrap.setAttribute("value", selection);
selectControl.querySelector(BDFDB.dotCN.title).innerText = selection;
choice[option] = selection;
if (option == "category") {
choice.song = Object.keys(this.audios[selection])[0];
songSelect.outerHTML = `<div type="${type}" option="song" value="${choice.song}" class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="padding:0;">${choice.song}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div>`;
}
choice.src = this.audios[choice.category][choice.song];
choice.src = choice.src ? choice.src : this.types[type].src;
choice.volume = settingspanel.querySelector(`.${type}-volume`).value;
this.saveChoice(type, choice, true);
});
$(document).on("mousedown.select" + this.getName(), (e2) => {
if (e2.target.parentElement == selectMenu) return;
$(document).off("mousedown.select" + this.getName());
selectMenu.remove()
setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100);
});
}
createDropdownMenu ({type, option, category, song} = data) {
var choice = BDFDB.loadData(type, this, "choices");
var eles = option == "song" ? this.audios[category] : this.audios;
var menuhtml = `<div class="${BDFDB.disCN.selectmenuouter}"><div class="${BDFDB.disCN.selectmenu}">`;
for (var ele in eles) {
var isSelected = choice[option] == ele ? ` ${BDFDB.disCN.selectselected}` : ``;
menuhtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectoption + isSelected}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}">${ele}</div></div>`
}
menuhtml += `</div></div>`;
return $(menuhtml)[0];
}
dragSlider (settingspanel, e) {
var grabber = e.target;
var track = grabber.parentNode;
var slider = track.parentNode;
var input = slider.querySelector(".volumeInput");
var bar = slider.querySelector(BDFDB.dotCN.sliderbarfill);
var disableTextSelectionCSS = `
* {
user-select: none !important;
}`;
BDFDB.appendLocalStyle("disableTextSelection", disableTextSelectionCSS);
var volume = 0;
var sY = 0;
var sHalfW = grabber.offsetWidth/2;
var sMinX = $(track).offset().left;
var sMaxX = sMinX + track.offsetWidth;
$(document)
.off("mouseup.slider" + this.getName()).off("mousemove.slider" + this.getName())
.on("mouseup.slider" + this.getName(), () => {
$(document).off("mouseup.slider" + this.getName()).off("mousemove.slider" + this.getName());
BDFDB.removeLocalStyle("disableTextSelection");
var type = slider.getAttribute("type");
var choice = this.choices[type];
choice.volume = volume;
this.saveChoice(type, choice, true);
})
.on("mousemove.slider" + this.getName(), (e2) => {
sY = e2.clientX > sMaxX ? sMaxX - sHalfW : (e2.clientX < sMinX ? sMinX - sHalfW : e2.clientX - sHalfW);
volume = BDFDB.mapRange([sMinX - sHalfW, sMaxX - sHalfW], [0, 100], sY);
grabber.style.left = volume + "%";
bar.style.width = volume + "%";
input.value = volume;
});
}
loadAudios () {
this.audios = BDFDB.loadAllData(this, "audios");
if (BDFDB.isObjectEmpty(this.audios)) this.audios = this.defaults;
BDFDB.saveAllData(this.audios, this, "audios");
}
saveAudio (settingspanel) {
var valid = true;
var inputs = settingspanel.querySelectorAll(".songInput");
inputs.forEach((input) => {
if (!input.value || input.value.length == 0 || input.value.trim().length == 0) valid = false;
});
if (valid) {
var successSavedAudio;
var category = settingspanel.querySelector("#input-category").value;
var song = settingspanel.querySelector("#input-song").value;
var url = settingspanel.querySelector("#input-url").value;
if (url.indexOf("http") == 0) {
require("request")(url, (error, response, result) => {
if (response) {
var type = response.headers["content-type"];
if (type && (type.indexOf("octet-stream") > -1 || type.indexOf("audio") > -1 || type.indexOf("video") > -1)) {
successSavedAudio();
return;
}
}
BDFDB.showToast("Use a valid direct link to a video or audio source. They usually end on something like .mp3, .mp4 or .wav.", {type:"danger"});
});
}
else {
require("fs").readFile(url, (error, response) => {
if (error) {
BDFDB.showToast("Could not fetch file. Please make sure the file exists.", {type:"danger"});
}
else {
url = `data:audio/mpeg;base64,${response.toString("base64")}`;
successSavedAudio();
}
});
}
successSavedAudio = () => {
BDFDB.showToast(`Song ${song} was added to category ${category}.`, {type:"success"});
if (!this.audios[category]) this.audios[category] = {};
this.audios[category][song] = url;
BDFDB.saveAllData(this.audios, this, "audios");
inputs.forEach((input) => {
input.value = "";
});
};
}
else {
BDFDB.showToast("Fill out all fields to add a new song.", {type:"danger"});
}
}
loadChoices () {
for (var type in this.types) {
var choice = BDFDB.loadData(type, this, "choices");
choice = choice ? choice : {};
var songFound = false;
for (var category in this.audios) {
if (choice.category == category) {
for (var song in this.audios[category]) {
if (choice.song == song) {
songFound = true;
break;
}
}
}
}
if (!songFound) choice = {"category":"---","song":"---","volume":100,"src":this.types[type].src};
this.saveChoice(type, choice, false);
}
}
saveChoice (type, choice, play) {
BDFDB.saveData(type, choice, this, "choices");
this.choices[type] = choice;
if (play) this.playAudio(type, this.settingsaudio);
}
playAudio (type, audio = new Audio()) {
audio.pause();
audio.src = this.choices[type].src;
audio.volume = this.choices[type].volume/100;
audio.play();
}
dontPlayAudio () {
let status = BDFDB.getUserStatus();
return status == "dnd" || status == "streaming";
}
fireEvent (type) {
this.firedEvents[type] = true;
setTimeout(() => {this.firedEvents[type] = false;},3000);
}
}

View File

@ -0,0 +1,3 @@
# Notification Sounds - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/NotificationSounds/NotificationSounds.plugin.js)
Allows you to replace the native sounds of Discord with your own.

View File

@ -0,0 +1,359 @@
//META{"name":"OldTitleBar"}*//
class OldTitleBar {
initConstructor () {
this.patched = false;
this.css = `
${BDFDB.dotCN.titlebar}.hidden-by-OTB {
display: none;
}
${BDFDB.dotCN.titlebar}.hidden-by-OTB + ${BDFDB.dotCNS.app + BDFDB.dotCN.splashbackground}:before {
display: none;
}
${BDFDB.dotCN.channelheaderheaderbardrag} {
-webkit-app-region: drag !important;
}
${BDFDB.dotCN.channelheaderheaderbardrag} *,
${BDFDB.dotCN.contextmenu} * {
-webkit-app-region: no-drag !important;
}
.settingsTitlebarOTB {
position: relative;
z-index: 1000;
text-align: right;
padding: 10px;
-webkit-app-region: drag;
}`;
this.dividerMarkup = `<div class="dividerOTB ${BDFDB.disCN.channelheaderdivider}"></div>`;
this.reloadButtonMarkup =
`<span class="${BDFDB.disCN.channelheadericonmargin} reloadButtonOTB">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" xmlns="http://www.w3.org/2000/svg">
<g fill="none" class="${BDFDB.disCN.channelheadericonforeground}" fill-rule="evenodd">
<path fill="currentColor" transform="translate(4,4)" d="M17.061,7.467V0l-2.507,2.507C13.013,0.96,10.885,0,8.528,0C3.813,0,0.005,3.819,0.005,8.533s3.808,8.533,8.523,8.533c3.973,0,7.301-2.72,8.245-6.4h-2.219c-0.88,2.485-3.237,4.267-6.027,4.267c-3.536,0-6.4-2.864-6.4-6.4s2.864-6.4,6.4-6.4c1.765,0,3.349,0.736,4.507,1.893l-3.44,3.44H17.061z"/>
</g>
</svg>
</span>`;
this.minButtonMarkup =
`<span class="${BDFDB.disCN.channelheadericonmargin} minButtonOTB">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" xmlns="http://www.w3.org/2000/svg" width="26" height="26">
<g fill="none" class="${BDFDB.disCN.channelheadericonforeground}" fill-rule="evenodd">
<path stroke-width="2" stroke="currentColor" d="M6 18 l13 0"/>
</g>
</svg>
</span>`;
this.maxButtonIsMaxMarkup =
`<span class="${BDFDB.disCN.channelheadericonmargin} maxButtonOTB">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" xmlns="http://www.w3.org/2000/svg" width="26" height="26">
<g fill="none" class="${BDFDB.disCN.channelheadericonforeground}" fill-rule="evenodd">
<path stroke-width="2" stroke="currentColor" d="M6 9 l10 0 l0 10 l-10 0 l0 -10 m3 -3 l10 0 l0 10"/>
</g>
</svg>
</span>`;
this.maxButtonIsMinMarkup =
`<span class="${BDFDB.disCN.channelheadericonmargin} maxButtonOTB">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" xmlns="http://www.w3.org/2000/svg" width="26" height="26">
<g fill="none" class="${BDFDB.disCN.channelheadericonforeground}" fill-rule="evenodd">
<path stroke-width="2" stroke="currentColor" d="M6 6 l13 0 l0 13 l-13 0 l0 -13"/>
</g>
</svg>
</span>`;
this.closeButtonMarkup =
`<span class="${BDFDB.disCN.channelheadericonmargin} closeButtonOTB">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" xmlns="http://www.w3.org/2000/svg" width="26" height="26">
<g fill="none" class="${BDFDB.disCN.channelheadericonforeground}" fill-rule="evenodd">
<path stroke-width="2" stroke="currentColor" d="M6 6 l13 13 m0 -13 l-13 13"/>
</g>
</svg>
</span>`;
this.defaults = {
settings: {
displayNative: {value:!!document.querySelector(".platform-linux"), description:"Displays the native titlebar."},
addToSettings: {value:true, description:"Add a Title Bar to Settings Windows."},
reloadButton: {value:false, description:"Add a Reload Button to the Title Bar."}
}
};
}
getName () {return "OldTitleBar";}
getDescription () {return "Reverts the title bar back to its former self.";}
getVersion () {return "1.4.5";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, (e) => {this.updateSettings(settingspanel, e.currentTarget.value);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
setImmediate(() => {
if (node && node.tagName && node.classList.contains(BDFDB.disCN.loginscreen)) {
this.addSettingsTitleBar(node);
}
});
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.app, {name:"loginScreenObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
setImmediate(() => {
if (node && node.tagName && node.getAttribute("layer-id") || node.querySelector(".ui-standard-sidebar-view")) {
if (BDFDB.getData("addToSettings", this, "settings")) this.addSettingsTitleBar(node);
}
});
});
}
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.getAttribute("layer-id") || node.querySelector(".ui-standard-sidebar-view")) {
this.removeTitleBar();
this.addTitleBar();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
$(window).on("resize." + this.getName(), (e) => {
this.changeMaximizeButton();
});
this.addTitleBar();
this.patchMainScreen(BDFDB.getData("displayNative", this, "settings"));
$(BDFDB.dotCN.titlebar).addClass("hidden-by-OTB");
var settingswindow = document.querySelector(BDFDB.dotCN.layer + "[layer-id]");
if (settingswindow && BDFDB.getData("addToSettings", this, "settings")) {
this.addSettingsTitleBar(settingswindow);
}
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
this.removeTitleBar();
$(".hidden-by-OTB").removeClass("hidden-by-OTB");
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
setImmediate(() => {this.addTitleBar();});
}
}
// begin of own functions
updateSettings (settingspanel, key) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
if (key == "displayNative") {
if (this.patchMainScreen(settings[key])) {
this.patched = !this.patched;
let notifybar = document.querySelector("#OldTitleBarNotifyBar");
if (notifybar) notifybar.querySelector(BDFDB.dotCN.noticedismiss).click();
if (this.patched) {
notifybar = BDFDB.createNotificationsBar("Changed nativebar settings, relaunch to see changes:", {type:"danger",btn:"Relaunch",id:"OldTitleBarNotifyBar"});
$(notifybar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => {
this.doRelaunch();
});
}
}
}
}
addTitleBar () {
this.removeTitleBar();
var settings = BDFDB.getAllData(this, "settings");
var container = $(BDFDB.dotCNS.channelheaderheaderbardrag + BDFDB.dotCN.flex + " > " + BDFDB.dotCN.channelheadericonmargin).parent();
if (settings.reloadButton) {
container
.append(this.dividerMarkup)
.append(this.reloadButtonMarkup)
.on("click." + this.getName(), ".reloadButtonOTB", () => {
this.doReload();
})
.on("mouseenter." + this.getName(), ".reloadButtonOTB", (e) => {
this.createReloadToolTip(e);
});
}
container
.append(this.dividerMarkup)
.append(this.minButtonMarkup)
.append(require("electron").remote.getCurrentWindow().isMaximized() ? this.maxButtonIsMaxMarkup : this.maxButtonIsMinMarkup)
.append(this.closeButtonMarkup)
.on("click." + this.getName(), ".minButtonOTB", () => {
this.doMinimize();
})
.on("click." + this.getName(), ".maxButtonOTB", () => {
this.doMaximize();
})
.on("click." + this.getName(), ".closeButtonOTB", () => {
this.doClose();
});
}
addSettingsTitleBar (settingspane) {
if (!settingspane.querySelector(".dividerOTB, .reloadButtonOTB, .minButtonOTB, .maxButtonOTB, .closeButtonOTB")) {
var settingsbar = $(`<div class="settingsTitlebarOTB"></div>`);
var settings = BDFDB.getAllData(this, "settings");
if (settings.reloadButton) {
settingsbar
.append(this.reloadButtonMarkup)
.on("click." + this.getName(), ".reloadButtonOTB", () => {
this.doReload();
})
.on("mouseenter." + this.getName(), ".reloadButtonOTB", (e) => {
this.createReloadToolTip(e);
});
}
settingsbar
.append(this.minButtonMarkup)
.append(require("electron").remote.getCurrentWindow().isMaximized() ? this.maxButtonIsMaxMarkup : this.maxButtonIsMinMarkup)
.append(this.closeButtonMarkup)
.on("click." + this.getName(), ".minButtonOTB", () => {
this.doMinimize();
})
.on("click." + this.getName(), ".maxButtonOTB", () => {
this.doMaximize();
})
.on("click." + this.getName(), ".closeButtonOTB", () => {
this.doClose();
});
$(settingspane).append(settingsbar);
}
}
doReload () {
require("electron").remote.getCurrentWindow().reload();
}
doMinimize () {
require("electron").remote.getCurrentWindow().minimize();
}
doMaximize () {
if (require("electron").remote.getCurrentWindow().isMaximized()) require("electron").remote.getCurrentWindow().unmaximize();
else require("electron").remote.getCurrentWindow().maximize();
}
doClose () {
require("electron").remote.getCurrentWindow().close();
}
doRelaunch () {
require("electron").remote.app.relaunch();
require("electron").remote.app.quit();
}
changeMaximizeButton () {
var maxButtonHTML = require("electron").remote.getCurrentWindow().isMaximized() ? this.maxButtonIsMaxMarkup : this.maxButtonIsMinMarkup;
document.querySelectorAll(".maxButtonOTB").forEach(maxButton => {
maxButton.outerHTML = maxButtonHTML;
});
}
removeTitleBar () {
$(".headerbarOTB, .settingsTitlebarOTB").remove();
var container = $(BDFDB.dotCNS.channelheaderheaderbardrag + BDFDB.dotCN.flex + " > " + BDFDB.dotCN.channelheadericonmargin).parent();
container
.off("click." + this.getName())
.off("mouseenter." + this.getName())
.find(".dividerOTB, .reloadButtonOTB, .minButtonOTB, .maxButtonOTB, .closeButtonOTB").remove();
}
createReloadToolTip (e) {
BDFDB.createTooltip("Reload", e.currentTarget, {type:"bottom",selector:"reload-button-tooltip"});
}
patchMainScreen (enable) {
let fs = require("fs")
let mainScreenPath = require("path").resolve(BDFDB.getDiscordFolder(), "modules/discord_desktop_core/core/app/mainScreen.js");
let mainScreen = fs.readFileSync(mainScreenPath).toString();
if (!mainScreen.includes("frame: " + enable) || !mainScreen.includes(".frame = " + enable)) {
fs.writeFileSync(mainScreenPath, mainScreen.replace("frame: " + !enable, "frame: " + enable).replace(".frame = " + !enable, ".frame = " + enable));
return true;
}
return false;
}
}

View File

@ -0,0 +1,3 @@
# Old Title Bar - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/OldTitleBar/OldTitleBar.plugin.js)
Reverts the title bar back to its former self.

View File

@ -0,0 +1,970 @@
//META{"name":"PersonalPins"}*//
class PersonalPins {
initConstructor () {
this.labels = {};
this.messageContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} personalpin-item">
<span>REPLACE_context_noteoption_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.notesButton =
`<span class="${BDFDB.disCN.channelheadericonmargin} notesButton">
<svg class="${BDFDB.disCNS.channelheadericoninactive + BDFDB.disCN.channelheadericon}" name="Note" width="16" height="16" viewBox="0 0 26 26">
<g fill="none" fill-rule="evenodd" transform="translate(3,2)">
<path class="${BDFDB.disCN.channelheadericonforeground}" fill="currentColor" d="M 4.618, 0 c -0.316, 0 -0.573, 0.256 -0.573, 0.573 v 1.145 c 0, 0.316, 0.256, 0.573, 0.573, 0.573 s 0.573 -0.256, 0.573 -0.573 V 0.573 C 5.191, 0.256, 4.935, 0, 4.618, 0 z"/>
<path class="${BDFDB.disCN.channelheadericonforeground}" fill="currentColor" d="M 8.053, 0 c -0.316, 0 -0.573, 0.256 -0.573, 0.573 v 1.145 c 0, 0.316, 0.256, 0.573, 0.573, 0.573 s 0.573 -0.256, 0.573 -0.573 V 0.573 C 8.626, 0.256, 8.37, 0, 8.053, 0 z"/>
<path class="${BDFDB.disCN.channelheadericonforeground}" fill="currentColor" d="M 11.489, 0 c -0.316, 0 -0.573, 0.256 -0.573, 0.573 v 1.145 c 0, 0.316, 0.256, 0.573, 0.573, 0.573 c 0.316, 0, 0.573 -0.256, 0.573 -0.573 V 0.573 C 12.061, 0.256, 11.805, 0, 11.489, 0 z "/>
<path class="${BDFDB.disCN.channelheadericonforeground}" fill="currentColor" d="M 14.924, 0 c -0.316, 0 -0.573, 0.256 -0.573, 0.573 v 1.145 c 0, 0.316, 0.256, 0.573, 0.573, 0.573 c 0.316, 0, 0.573 -0.256, 0.573 -0.573 V 0.573 C 15.496, 0.256, 15.24, 0, 14.924, 0 z"/>
<path class="${BDFDB.disCN.channelheadericonforeground}" fill="currentColor" d="M 16.641, 1.25 V 1.718 c 0, 0.947 -0.77, 1.718 -1.718, 1.718 c -0.947, 0 -1.718 -0.77 -1.718 -1.718 c 0, 0.947 -0.77, 1.718 -1.718, 1.718 c -0.947, 0 -1.718 -0.77 -1.718 -1.718 c 0, 0.947 -0.77, 1.718 -1.718, 1.718 c -0.947, 0 -1.718 -0.77 -1.718 -1.718 c 0, 0.947 -0.77, 1.718 -1.718, 1.718 c -0.947, 0 -1.718 -0.77 -1.718 -1.718 V 1.25 C 2.236, 1.488, 1.756, 2.117, 1.756, 2.863 v 14.962 c 0, 0.947, 0.77, 1.718, 1.718, 1.718 h 12.595 c 0.947, 0, 1.718 -0.77, 1.718 -1.718 V 2.863 C 17.786, 2.117, 17.306, 1.488, 16.641, 1.25 z M 14.924, 16.679 H 4.618 c -0.316, 0 -0.573 -0.256 -0.573 -0.573 c 0 -0.316, 0.256 -0.573, 0.573 -0.573 h 10.305 c 0.316, 0, 0.573, 0.256, 0.573, 0.573 C 15.496, 16.423, 15.24, 16.679, 14.924, 16.679 z M 14.924, 13.244 H 4.618 c -0.316, 0 -0.573 -0.256 -0.573 -0.573 c 0 -0.316, 0.256 -0.573, 0.573 -0.573 h 10.305 c 0.316, 0, 0.573, 0.256, 0.573, 0.573 C 15.496, 12.988, 15.24, 13.244, 14.924, 13.244 z M 14.924, 9.733 H 4.618 c -0.316, 0 -0.573 -0.256 -0.573 -0.573 s 0.256 -0.573, 0.573 -0.573 h 10.305 c 0.316, 0, 0.573, 0.256, 0.573, 0.573 S 15.24, 9.733, 14.924, 9.733 z M 14.924, 6.298 H 4.618 c -0.316, 0 -0.573 -0.256 -0.573 -0.573 s 0.256 -0.573, 0.573 -0.573 h 10.305 c 0.316, 0, 0.573, 0.256, 0.573, 0.573 S 15.24, 6.298, 14.924, 6.298 z"/>
</g>
</svg>
</span>`;
this.notesPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCNS.popoutnoarrow + BDFDB.disCN.popoutnoshadow} popout-personalpins-notes DevilBro-modal" style="z-index: 1000; visibility: visible; left: 544.844px; top: 35.9896px; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div class="${BDFDB.disCNS.messagespopoutwrap + BDFDB.disCNS.recentmentionspopout + BDFDB.disCN.popoutthemedpopout}" style="max-height: 740px; width: 500px;">
<div class="${BDFDB.disCNS.recentmentionsheader + BDFDB.disCNS.recentmentionsheader2 + BDFDB.disCN.messagespopoutheader}" style="padding-bottom: 0;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.margintop8}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCNS.recentmentionstitle + BDFDB.disCN.messagespopouttitle}">REPLACE_popout_note_text</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.searchbar + BDFDB.disCN.size14}" style="flex: 1 1 auto;">
<input class="${BDFDB.disCNS.searchbarinput + BDFDB.disCN.flexchild}" value="" placeholder="Search for ..." style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.searchbariconwrap + BDFDB.disCN.flexchild}">
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCNS.searchbareyeglass + BDFDB.disCN.searchbarvisible}"/>
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCN.searchbarclear}"/>
</div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.margintop8}" style="flex: 0 0 auto;">
<div tab="channel" class="tab">REPLACE_popout_channel_text</div>
<div tab="server" class="tab">REPLACE_popout_server_text</div>
<div tab="allservers" class="tab">REPLACE_popout_allservers_text</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="padding-bottom: 15px; float:right;">
<div class="${BDFDB.disCN.quickselectlabel}">REPLACE_popout_sort_text:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick}" style="flex: 0 0 auto;">
<div option="timestamp" class="${BDFDB.disCN.quickselectvalue}">REPLACE_popout_messagesort_text</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
</div>
</div>
<div class="${BDFDB.disCN.scrollerwrap}">
<div class="${BDFDB.disCNS.messagespopout + BDFDB.disCN.scroller}">
<div class="${BDFDB.disCN.messagespopoutemptyplaceholder}">
<div class="${BDFDB.disCN.messagespopoutimage}" style="background-image: url(/assets/6793e022dc1b065b21f12d6df02f91bd.svg);"></div>
<div class="${BDFDB.disCN.messagespopoutbody}"></div>
</div>
</div>
</div>
</div>
</div>`;
this.sortPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} personalpins-sort-popout" style="z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div option="timestamp" class="${BDFDB.disCN.contextmenuitem}">REPLACE_popout_messagesort_text</div>
<div option="addedat" class="${BDFDB.disCN.contextmenuitem}">REPLACE_popout_datesort_text</div>
</div>
</div>
</div>
</div>`;
this.optionButtonMarkup =
`<div class="${BDFDB.disCN.optionpopoutbutton} btn-personalpins"></div>`;
this.optionsPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottom + BDFDB.disCN.popoutnoarrow} popout-personalpins-options" style="z-index: 1000; visibility: visible;">
<div class="${BDFDB.disCN.optionpopout}"></div
</div>`;
this.popoutEntryMarkup =
`<button type="button" class="${BDFDB.disCNS.optionpopoutitem + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookblank + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCN.buttongrow} btn-item-personalpins">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_popout_noteoption_text</div>
</button>`;
this.messageMarkupCozy =
`<div class="${BDFDB.disCN.messagegroupwrapper}">
<div class="${BDFDB.disCN.messagegroupwrapperoffsetcorrection}">
<div class="${BDFDB.disCNS.messagegroup + BDFDB.disCN.messagegroupcozy}">
<div class="${BDFDB.disCNS.messagecozy + BDFDB.disCN.message}" aria-disabled="false">
<div class="${BDFDB.disCN.messageheadercozy}">
<div tabindex="0" class="${BDFDB.disCNS.avatarwrapper + BDFDB.disCNS.avatarlarge + BDFDB.disCN.avatar}" role="button">
<div class="${BDFDB.disCNS.avatarimage + BDFDB.disCN.avatarlarge}"></div>
</div>
<span>
<span class="${BDFDB.disCN.messageusernamewrapper}">
<strong tabindex="0" class="${BDFDB.disCN.messageusername}" role="button"></strong>
</span>
<time class="${BDFDB.disCN.messagetimestampcozy}" datetime="1531959706620"></time>
</span>
</div>
<div class="${BDFDB.disCNS.messagecontentcozy + BDFDB.disCN.messagecontent}">
<div class="${BDFDB.disCNS.messagebodycozy + BDFDB.disCN.messagebody}">
<div class="${BDFDB.disCN.messagebuttoncontainerouter}">
<div class="${BDFDB.disCN.messagebuttoncontainer}">
<div class="${BDFDB.disCN.emojipickerbutton}"></div>
<div class="${BDFDB.disCN.optionpopoutbutton}"></div>
</div>
</div>
<div class="${BDFDB.disCN.messagemarkup}"></div>
</div>
<div class="${BDFDB.disCNS.messageaccessorycozy + BDFDB.disCN.messageaccessory}"></div>
<div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCN.primary} server-channel"></div>
</div>
<div class="${BDFDB.disCNS.sinkinteractions + BDFDB.disCN.clickable}"></div>
<div class="${BDFDB.disCN.messagespopoutactionbuttons}">
<div tabindex="0" class="${BDFDB.disCN.messagespopoutjumpbutton} jump" role="button">
<div class="${BDFDB.disCN.messagespopouttext}">REPLACE_popout_jump_text</div>
</div>
<div tabindex="0" class="${BDFDB.disCN.messagespopoutjumpbutton} copy" role="button">
<div class="${BDFDB.disCN.messagespopouttext}">REPLACE_popout_copy_text</div>
</div>
<button type="button" class="${BDFDB.disCNS.button + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonlookblank + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">
<div class="${BDFDB.disCN.messagespopoutclosebutton}"></div>
</div>
</button>
</div>
</div>
<hr class="${BDFDB.disCNS.messagedividerenabled + BDFDB.messagedivider}">
</div>
</div>
</div>`;
}
getName () {return "PersonalPins";}
getDescription () {return "Similar to normal pins. Lets you save messages as notes for yourself.";}
getVersion () {return "1.6.1";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Delete all Notes.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".reset-button", () => {this.resetAll();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.GuildStore = BDFDB.WebModules.findByProperties(["getGuild"]);
this.ChannelStore = BDFDB.WebModules.findByProperties(["getChannel"]);
this.UserStore = BDFDB.WebModules.findByProperties(["getUser"]);
this.MemberStore = BDFDB.WebModules.findByProperties(["getMember"]);
this.IconUtils = BDFDB.WebModules.findByProperties(["getUserAvatarURL"]);
this.HistoryUtils = BDFDB.WebModules.findByProperties(["transitionTo", "replaceWith", "getHistory"]);
this.MainDiscord = BDFDB.WebModules.findByProperties(["ActionTypes"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"messageContextObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.classList && node.classList.contains(BDFDB.disCN.messagegroup)) {
node.querySelectorAll(BDFDB.dotCN.message).forEach(message => {this.addOptionButton(message);});
}
else if (node && node.tagName && node.classList && node.classList.contains(BDFDB.disCN.message)) {
this.addOptionButton(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.optionpopout) && !node.querySelector(".btn-item-personalpins")) {
$(node).find(BDFDB.dotCN.optionpopout).append(this.popoutEntryMarkup);
this.addClickListener(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"optionPopoutObserver",instance:observer}, {childList: true});
$(document).off("click." + this.getName(), BDFDB.dotCN.optionpopoutbutton).off("contextmenu." + this.getName(), BDFDB.dotCN.message)
.on("click." + this.getName(), BDFDB.dotCN.optionpopoutbutton, (e) => {
this.getMessageData($(BDFDB.dotCN.message).has(e.currentTarget)[0]);
})
.on("contextmenu." + this.getName(), BDFDB.dotCN.message, (e) => {
this.getMessageData(e.currentTarget);
});
document.querySelectorAll(BDFDB.dotCNS.messagegroup + BDFDB.dotCN.message).forEach(message => {this.addOptionButton(message);});
this.addNotesButton();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(document).off("click." + this.getName(), BDFDB.dotCN.optionpopoutbutton).off("contextmenu." + this.getName(), BDFDB.dotCN.message);
$(".btn-personalpins, .notesButton").remove();
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
document.querySelectorAll(BDFDB.dotCNS.messages + BDFDB.dotCN.message).forEach(message => {this.addOptionButton(message);});
setTimeout(() => {
this.addNotesButton();
},1);
}
}
// begin of own functions
resetAll () {
if (confirm("Are you sure you want to delete all pinned notes?")) {
BDFDB.removeAllData(this, "pins");
}
}
changeLanguageStrings () {
this.messageContextEntryMarkup = this.messageContextEntryMarkup.replace("REPLACE_context_noteoption_text", this.labels.context_noteoption_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_note_text", this.labels.popout_note_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_channel_text", this.labels.popout_channel_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_server_text", this.labels.popout_server_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_allservers_text", this.labels.popout_allservers_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_sort_text", this.labels.popout_sort_text);
this.notesPopoutMarkup = this.notesPopoutMarkup.replace("REPLACE_popout_messagesort_text", this.labels.popout_messagesort_text);
this.messageMarkupCozy = this.messageMarkupCozy.replace("REPLACE_popout_jump_text", this.labels.popout_jump_text);
this.messageMarkupCozy = this.messageMarkupCozy.replace("REPLACE_popout_copy_text", this.labels.popout_copy_text);
this.sortPopoutMarkup = this.sortPopoutMarkup.replace("REPLACE_popout_messagesort_text", this.labels.popout_messagesort_text);
this.sortPopoutMarkup = this.sortPopoutMarkup.replace("REPLACE_popout_datesort_text", this.labels.popout_datesort_text);
this.popoutEntryMarkup = this.popoutEntryMarkup.replace("REPLACE_popout_noteoption_text", this.labels.popout_noteoption_text);
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".personalpin-item")) return;
for (let group of context.querySelectorAll(BDFDB.dotCN.contextmenuitemgroup)) {
if (BDFDB.getKeyInformation({"node":group, "key":"displayName", "value":"MessagePinItem"})) {
$(this.messageContextEntryMarkup).insertAfter(group)
.on("click", ".personalpin-item", () => {
$(context).hide();
this.addMessageToNotes();
});
BDFDB.updateContextPosition(context);
break;
}
}
}
getMessageGroup (message) {
var messagegroup = null;
while (messagegroup == null || message.parentElement) {
message = message.parentElement;
if (message.classList && message.classList.contains(BDFDB.disCN.messagegroup)) messagegroup = message;
}
return messagegroup;
}
getMessageData (div) {
if (div && !div.querySelector(BDFDB.dotCN.messagesystem)) {
var messagegroup = this.getMessageGroup(div);
var pos = Array.from(messagegroup.querySelectorAll(BDFDB.dotCN.message)).indexOf(div);
var instance = BDFDB.getReactInstance(messagegroup);
if (!instance) return;
var info = instance.return.stateNode.props.messages;
if (info && pos > -1) this.message = Object.assign({},info[pos],{"div":div, "group":messagegroup, "pos":pos});
}
else {
this.message = null;
}
}
addNotesButton () {
$(".notesButton").remove();
$(this.notesButton)
.insertBefore(BDFDB.dotCNS.channelheadertitle + BDFDB.dotCN.channelheadersearch)
.on("click." + this.getName(), (e) => {
this.openNotesPopout(e);
})
.on("mouseenter." + this.getName(), (e) => {
BDFDB.createTooltip(this.labels.popout_note_text, e.currentTarget, {type:"bottom",selector:"note-button-tooltip"});
});
}
addOptionButton (message) {
if (!message.querySelector(BDFDB.dotCN.optionpopoutbutton) && !message.querySelector(BDFDB.dotCN.messagesystem) && !message.querySelector(BDFDB.dotCN.messageuploadcancel)) {
$(this.optionButtonMarkup).appendTo(message.querySelector(BDFDB.dotCN.messagebuttoncontainer));
$(message).off("click." + this.getName()).on("click." + this.getName(), ".btn-personalpins", (e) => {
this.openOptionPopout(e);
});
}
}
openNotesPopout (e) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains("popout-open")) return;
wrapper.classList.add("popout-open");
var popout = $(this.notesPopoutMarkup);
BDFDB.initElements(popout);
var wrappersize = wrapper.getBoundingClientRect();
popout
.appendTo(BDFDB.dotCN.popouts)
.css("left", wrappersize.width/2 + wrappersize.left + "px")
.css("top", wrappersize.height + wrappersize.top + "px")
.on("click", ".tab:not(.selected)", () => {
this.addNotes(popout[0]);
})
.on("keyup." + this.getName(), BDFDB.dotCN.searchbarinput, () => {
clearTimeout(popout.searchTimeout);
popout.searchTimeout = setTimeout(() => {this.addNotes(popout[0]);},1000);
})
.on("click." + this.getName(), BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => {
clearTimeout(popout.searchTimeout);
popout.searchTimeout = setTimeout(() => {this.addNotes(popout[0]);},1000);
})
.on("click", BDFDB.dotCN.quickselectclick, (e2) => {
this.openSortPopout(e2, popout[0]);
});
$(document).on("mousedown.notepopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0 && $(".personalpins-sort-popout").has(e2.target).length == 0) {
$(document).off("mousedown.notepopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
}
});
this.addNotes(popout[0]);
}
openSortPopout (e, notespopout) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains("popout-open")) return;
wrapper.classList.add("popout-open");
var value = $(wrapper).find(BDFDB.dotCN.quickselectvalue);
var popout = $(this.sortPopoutMarkup);
$(BDFDB.dotCN.popouts).append(popout)
.off("click", BDFDB.dotCN.contextmenuitem)
.on("click", BDFDB.dotCN.contextmenuitem, (e2) => {
value.text($(e2.currentTarget).text());
value.attr("option", $(e2.currentTarget).attr("option"));
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
this.addNotes(notespopout);
});
popout
.css("left", $(e.currentTarget).offset().left + $(e.currentTarget).outerWidth() + "px")
.css("top", $(e.currentTarget).offset().top + value.outerHeight() + "px")
.find(BDFDB.dotCN.contextmenu).addClass(BDFDB.getDiscordTheme());
$(document).on("mousedown.sortpopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0) {
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
}
});
}
openOptionPopout (e) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains(BDFDB.disCN.optionpopoutopen)) return;
wrapper.classList.add(BDFDB.disCN.optionpopoutopen);
var popout = $(this.optionsPopoutMarkup);
$(BDFDB.dotCN.popouts).append(popout);
$(popout).find(BDFDB.dotCN.optionpopout).append(this.popoutEntryMarkup);
this.addClickListener(popout);
popout
.css("left", e.pageX - ($(popout).outerWidth() / 2) + "px")
.css("top", e.pageY + "px");
$(document).on("mousedown.optionpopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0) {
$(document).off("mousedown.optionpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove(BDFDB.disCN.optionpopoutopen);},300);
}
});
}
addClickListener (popout) {
$(popout)
.off("click." + this.getName(), ".btn-item-personalpins")
.on("click." + this.getName(), ".btn-item-personalpins", (e) => {
$(BDFDB.dotCN.popout).has(BDFDB.dotCN.optionpopout).hide();
this.addMessageToNotes();
var popoutbutton = document.querySelector(BDFDB.dotCN.optionpopoutbutton + BDFDB.dotCN.optionpopoutopen);
if (popoutbutton) popoutbutton.classList.remove(BDFDB.disCN.optionpopoutopen);
});
}
addMessageToNotes () {
if (!this.message) return;
var channelObj = BDFDB.getSelectedChannel();
var serverObj = BDFDB.getSelectedServer() || {};
if (this.message && channelObj) {
var author = this.message.author;
var channelID = channelObj.id;
var serverID = serverObj.id ? serverObj.id : "@me";
var pins = BDFDB.loadAllData(this, "pins");
pins[serverID] = pins[serverID] ? pins[serverID] : {}
pins[serverID][channelID] = pins[serverID][channelID] ? pins[serverID][channelID] : {}
var messageID = this.message.id;
var position = this.message.pos;
var channelname = channelObj.name;
if (!channelname && channelObj.recipients.length > 0) {
for (let dmmemberID of channelObj.recipients) {
channelname = channelname ? channelname + ", @" : channelname;
channelname = channelname + this.UserStore.getUser(dmmemberID).username;
}
}
var markup = this.message.div.querySelector(BDFDB.dotCN.messagemarkup).cloneNode(true);
markup.querySelectorAll(BDFDB.dotCN.messageheadercompact).forEach(h2 => {h2.remove();});
var message = {
"serverID": serverID,
"serverName": serverObj.name ? serverObj.name : "Direct Messages",
"channelID": channelID,
"channelName": channelname,
"id": messageID,
"pos": position,
"timestamp": this.message.timestamp._i.getTime(),
"addedat": new Date().getTime(),
"color": this.message.colorString,
"authorID": author.id,
"authorName": author.username,
"avatar": this.IconUtils.getUserAvatarURL(author),
"content": this.message.content,
"markup": markup.innerHTML,
"accessory": this.message.div.querySelector(BDFDB.dotCN.messageaccessory).innerHTML
};
pins[serverID][channelID][messageID + "_" + position] = message;
BDFDB.saveAllData(pins, this, "pins");
BDFDB.showToast(this.labels.toast_noteadd_text, {type:"success"});
}
this.message = null;
}
addNotes (notespopout) {
notespopout.querySelectorAll(BDFDB.dotCN.messagegroupwrapper).forEach(message => {message.remove();});
var channelObj = BDFDB.getSelectedChannel();
if (channelObj) {
var serverID = channelObj.guild_id ? channelObj.guild_id : "@me";
var channelID = channelObj.id;
var pins = BDFDB.loadAllData(this, "pins");
if (!BDFDB.isObjectEmpty(pins)) {
var language = BDFDB.getDiscordLanguage().id;
var container = notespopout.querySelector(BDFDB.dotCN.messagespopout);
var placeholder = notespopout.querySelector(BDFDB.dotCN.messagespopoutemptyplaceholder);
var messages = {};
switch (notespopout.querySelector(".tab.selected").getAttribute("tab")) {
case "channel":
messages = pins[serverID] && pins[serverID][channelID] ? pins[serverID][channelID] : {};
break;
case "server":
if (pins[serverID]) for (let channel in pins[serverID]) messages = Object.assign(messages, pins[serverID][channel]);
break;
case "allservers":
for (let server in pins) if (pins[server]) for (let channel in pins[server]) messages = Object.assign(messages, pins[server][channel]);
break;
}
var messageArray = [];
for (var id in messages) {
messageArray.push(messages[id]);
}
BDFDB.sortArrayByKey(messageArray, notespopout.querySelector(BDFDB.dotCN.quickselectvalue).getAttribute("option"));
var compact = BDFDB.getDiscordMode == "compact";
for (let messageData of messageArray) {
let message = $(this.messageMarkupCozy)[0];
let server = this.GuildStore.getGuild(messageData.serverID);
let channel = this.ChannelStore.getChannel(messageData.channelID);
let user = this.UserStore.getUser(messageData.authorID);
let member = this.MemberStore.getMember(messageData.serverID, messageData.authorID);
let date = new Date(messageData.timestamp);
container.insertBefore(message, container.firstChild);
message.querySelector(BDFDB.dotCN.avatarimage).style.backgroundImage =
user ? "url(" + this.IconUtils.getUserAvatarURL(user) + ")" : "url(" + messageData.avatar + ")";
message.querySelector(BDFDB.dotCN.messageusername).innerText = user ? user.username : messageData.authorName;
message.querySelector(BDFDB.dotCN.messageusername).style.color = member ? member.colorString : messageData.color;
message.querySelector(compact ? BDFDB.dotCN.messagetimestampcompact : BDFDB.dotCN.messagetimestampcozy).innerText = date.toLocaleString(language);
message.querySelector(".server-channel").innerText =
(server && server.name ? server.name : messageData.serverName) +
(messageData.serverID == "@me" ? " @" : " #") +
(channel && channel.name ? channel.name : messageData.channelName);
message.querySelector(BDFDB.dotCN.messagemarkup).innerHTML = messageData.markup;
message.querySelector(BDFDB.dotCN.messageaccessory).innerHTML = messageData.accessory;
if (messageData.accessory) {
let ytvideo = message.querySelector(BDFDB.dotCN.embed + " iframe[src*='https://www.youtube.com']");
if (ytvideo) {
let ytlink = ytvideo.parentElement.parentElement.querySelector(BDFDB.dotCN.embedtitle).href;
let wrapper = ytvideo.parentElement;
ytvideo.remove();
require("request")(ytlink, (error, response, result) => {
if (result) {
wrapper.innerHTML = `<a class="${BDFDB.disCNS.imagewrapper + BDFDB.disCN.imagezoom}" href="" rel="noreferrer noopener" target="_blank" style="width: 400px; height: 225px;"><img alt="" src="${result.split('<link itemprop="thumbnailUrl" href="')[1].split('"')[0]}" style="width: 400px; height: 225px;"></a><div class="${BDFDB.disCNS.embedvideoactions + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifycenter + BDFDB.disCN.aligncenter}"><div class="${BDFDB.disCNS.embedvideoactionsinner + BDFDB.disCNS.flexcenter + BDFDB.disCNS.flex + BDFDB.disCNS.justifycenter + BDFDB.disCN.aligncenter}"><div class="${BDFDB.disCN.iconactionswrapper}"><div tabindex="0" class="${BDFDB.disCNS.iconwrapper + BDFDB.disCN.iconwrapperactive}" role="button"><svg name="Play" class="${BDFDB.disCNS.iconplay + BDFDB.disCN.icon}" width="16" height="16" viewBox="0 0 24 24"><polygon fill="currentColor" points="0 0 0 14 11 7" transform="translate(7 5)"></polygon></svg></div><a class="${BDFDB.disCNS.anchor + BDFDB.disCN.iconwrapper}" href="${ytlink}" rel="noreferrer noopener" target="_blank"><svg name="OpenExternal" class="${BDFDB.disCNS.iconexternalmargins + BDFDB.disCN.icon}" width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" transform="translate(3.000000, 4.000000)" d="M16 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h4v-2H2V4h14v10h-4v2h4c1.1 0 2-.9 2-2V2a2 2 0 0 0-2-2zM9 6l-4 4h3v6h2v-6h3L9 6z"></path></svg></a></div></div></div></div>`;
$(wrapper).on("click." + this.getName(), BDFDB.dotCN.iconplay, (e) => {
while (wrapper.firstChild) wrapper.firstChild.remove();
let width = 400;
let height = Math.round(width*(result.split('<meta itemprop="height" content="')[1].split('"')[0]/result.split('<meta itemprop="width" content="')[1].split('"')[0]));
$(`<iframe src="${result.split('<link itemprop="embedURL" href="')[1].split('"')[0]}?start=0&amp;autoplay=1&amp;auto_play=1" width="${width}" height="${height}" frameborder="0" allowfullscreen=""></iframe>`).appendTo(wrapper);
});
}
});
}
}
$(message).on("click." + this.getName(), BDFDB.dotCN.messagespopoutclosebutton, (e) => {
message.remove();
delete pins[messageData.serverID][messageData.channelID][messageData.id + "_" + messageData.pos];
BDFDB.saveAllData(pins, this, "pins");
if (!container.querySelector(BDFDB.dotCN.messagegroup)) $(placeholder).show();
BDFDB.showToast(this.labels.toast_noteremove_text, {type:"danger"});
})
.on("click." + this.getName(), BDFDB.dotCN.messagespopoutjumpbutton + ".jump", (e) => {
this.HistoryUtils.transitionTo(this.MainDiscord.Routes.MESSAGE(messageData.serverID, messageData.channelID, messageData.id));
})
.on("click." + this.getName(), BDFDB.dotCN.messagespopoutjumpbutton + ".copy", (e) => {
let clipboard = require("electron").clipboard;
if (messageData.content) clipboard.write({text: messageData.content});
else {
var image = message.querySelector(BDFDB.dotCNS.imagewrapper + "img");
if (image) {
// stolen from Image2Clipboard
require("request")({url: image.src, encoding: null}, (error, response, buffer) => {
if (buffer) {
var platform = require("process").platform;
if (platform === "win32" || platform === "darwin") {
clipboard.write({image: require("electron").nativeImage.createFromBuffer(buffer)});
}
else {
var file = require("path").join(require("process").env["HOME"], "personalpinstemp.png");
require("fs").writeFileSync(file, buffer, {encoding: null});
clipboard.write({image: file});
require("fs").unlinkSync(file);
}
}
});
}
}
});
}
var searchstring = notespopout.querySelector(BDFDB.dotCN.searchbarinput).value.replace(/[<|>]/g, "");
if (searchstring) for (let note of notespopout.querySelectorAll(BDFDB.dotCN.messagegroup)) {
note.innerHTML = BDFDB.highlightText(note.innerHTML, searchstring);
if (!note.querySelector(BDFDB.dotCN.highlight)) note.remove();
}
$(placeholder).toggle(notespopout.querySelectorAll(BDFDB.dotCN.messagegroup).length == 0);
}
}
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
popout_note_text: "Bilješke",
popout_channel_text: "Kanal",
popout_server_text: "Poslužavnik",
popout_allservers_text: "Svi poslužitelji",
popout_sort_text: "Poredaj po",
popout_messagesort_text: "Vijesti-Datum",
popout_datesort_text: "Bilješka-Datum",
popout_jump_text: "Skok",
popout_copy_text: "Kopija",
context_noteoption_text: "Napominjemo poruku",
popout_noteoption_text: "Bilješka",
toast_noteadd_text: "Poruka dodana u bilježnicu.",
toast_noteremove_text: "Poruka uklonjena iz bilježnice."
};
case "da": //danish
return {
popout_note_text: "Noter",
popout_channel_text: "Kanal",
popout_server_text: "Server",
popout_allservers_text: "Alle servere",
popout_sort_text: "Sorter efter",
popout_messagesort_text: "Meddelelse-Dato",
popout_datesort_text: "Note-Dato",
popout_jump_text: "Hop",
popout_copy_text: "Kopi",
context_noteoption_text: "Noter Meddelelse",
popout_noteoption_text: "Noter",
toast_noteadd_text: "Meddelelse tilføjet til notesbog.",
toast_noteremove_text: "Meddelelse fjernet fra notesbog."
};
case "de": //german
return {
popout_note_text: "Notizen",
popout_channel_text: "Kanal",
popout_server_text: "Server",
popout_allservers_text: "Alle Server",
popout_sort_text: "Sortieren nach",
popout_messagesort_text: "Nachrichten-Datum",
popout_datesort_text: "Notiz-Datum",
popout_jump_text: "Springen",
popout_copy_text: "Kopieren",
context_noteoption_text: "Nachricht notieren",
popout_noteoption_text: "Notieren",
toast_noteadd_text: "Nachricht zum Notizbuch hinzugefügt.",
toast_noteremove_text: "Nachricht aus dem Notizbuch entfernt."
};
case "es": //spanish
return {
popout_note_text: "Notas",
popout_channel_text: "Canal",
popout_server_text: "Servidor",
popout_allservers_text: "Todos los servidores",
popout_sort_text: "Ordenar por",
popout_messagesort_text: "Mensaje-Fecha",
popout_datesort_text: "Nota-Fecha",
popout_jump_text: "Ir a",
popout_copy_text: "Copiar",
context_noteoption_text: "Anotar mensaje",
popout_noteoption_text: "Anotar",
toast_noteadd_text: "Mensaje agregado al cuaderno.",
toast_noteremove_text: "Mensaje eliminado del cuaderno."
};
case "fr": //french
return {
popout_note_text: "Notes",
popout_channel_text: "Canal",
popout_server_text: "Serveur",
popout_allservers_text: "Tous les serveurs",
popout_sort_text: "Trier par",
popout_messagesort_text: "Message-Date",
popout_datesort_text: "Note-Date",
popout_jump_text: "Accéder",
popout_copy_text: "Copier",
context_noteoption_text: "Noter le message",
popout_noteoption_text: "Noter",
toast_noteadd_text: "Message ajouté au bloc-notes.",
toast_noteremove_text: "Message supprimé du bloc-notes."
};
case "it": //italian
return {
popout_note_text: "Note",
popout_channel_text: "Canale",
popout_server_text: "Server",
popout_allservers_text: "Tutti i server",
popout_sort_text: "Ordina per",
popout_messagesort_text: "Messaggio-Data",
popout_datesort_text: "Nota-Data",
popout_jump_text: "Vai",
popout_copy_text: "Copiare",
context_noteoption_text: "Annotare il messaggio",
popout_noteoption_text: "Annotare",
toast_noteadd_text: "Messaggio aggiunto al blocco note.",
toast_noteremove_text: "Messaggio rimosso dal blocco note."
};
case "nl": //dutch
return {
popout_note_text: "Notities",
popout_channel_text: "Kanaal",
popout_server_text: "Server",
popout_allservers_text: "Alle servers",
popout_sort_text: "Sorteer op",
popout_messagesort_text: "Bericht-Datum",
popout_datesort_text: "Notitie-Datum",
popout_jump_text: "Openen",
popout_copy_text: "Kopiëren",
context_noteoption_text: "Noteer bericht",
popout_noteoption_text: "Noteer",
toast_noteadd_text: "Bericht toegevoegd aan notitieblok.",
toast_noteremove_text: "Bericht verwijderd van notitieblok."
};
case "no": //norwegian
return {
popout_note_text: "Notatene",
popout_channel_text: "Kanal",
popout_server_text: "Server",
popout_allservers_text: "Alle servere",
popout_sort_text: "Sorter etter",
popout_messagesort_text: "Melding-Dato",
popout_datesort_text: "Merknad-Dato",
popout_jump_text: "Hoppe",
popout_copy_text: "Kopiere",
context_noteoption_text: "Notat ned meldingen",
popout_noteoption_text: "Notere",
toast_noteadd_text: "Melding lagt til i notisboken.",
toast_noteremove_text: "Melding fjernet fra notatboken."
};
case "pl": //polish
return {
popout_note_text: "Notatki",
popout_channel_text: "Kanał",
popout_server_text: "Serwer",
popout_allservers_text: "Wszystkie serwery",
popout_sort_text: "Sortuj według",
popout_messagesort_text: "Wiadomość-Data",
popout_datesort_text: "Notatka-Data",
popout_jump_text: "Skocz",
popout_copy_text: "Kopiować",
context_noteoption_text: "Notuj wiadomość",
popout_noteoption_text: "Notuj",
toast_noteadd_text: "Wiadomość została dodana do notatnika.",
toast_noteremove_text: "Wiadomość została usunięta z notatnika."
};
case "pt-BR": //portuguese (brazil)
return {
popout_note_text: "Notas",
popout_channel_text: "Canal",
popout_server_text: "Servidor",
popout_allservers_text: "Todos os servidores",
popout_sort_text: "Ordenar por",
popout_messagesort_text: "Mensagem-Data",
popout_datesort_text: "Nota-Data",
popout_jump_text: "Pular",
popout_copy_text: "Copiar",
context_noteoption_text: "Anote a mensagem",
popout_noteoption_text: "Anotar",
toast_noteadd_text: "Mensagem adicionada ao caderno.",
toast_noteremove_text: "Mensagem removida do caderno."
};
case "fi": //finnish
return {
popout_note_text: "Muistiinpanot",
popout_channel_text: "Kanava",
popout_server_text: "Palvelin",
popout_allservers_text: "Kaikki palvelimet",
popout_sort_text: "Järjestä",
popout_messagesort_text: "Viesti-Päivämäärä",
popout_datesort_text: "Huomaa-Päivämäärä",
popout_jump_text: "Siirry",
popout_copy_text: "Kopioida",
context_noteoption_text: "Huomaa viesti",
popout_noteoption_text: "Huomaa",
toast_noteadd_text: "Viesti lisätty muistikirjaan.",
toast_noteremove_text: "Viesti poistettiin muistikirjaan."
};
case "sv": //swedish
return {
popout_note_text: "Anteckningarna",
popout_channel_text: "Kanal",
popout_server_text: "Server",
popout_allservers_text: "Alla servrar",
popout_sort_text: "Sortera efter",
popout_messagesort_text: "Meddelande-Datum",
popout_datesort_text: "Anteckningen-Datum",
popout_jump_text: "Hoppa",
popout_copy_text: "Kopiera",
context_noteoption_text: "Anteckna meddelande",
popout_noteoption_text: "Anteckna",
toast_noteadd_text: "Meddelandet läggs till i anteckningsboken.",
toast_noteremove_text: "Meddelande borttaget från anteckningsboken."
};
case "tr": //turkish
return {
popout_note_text: "Notlar",
popout_channel_text: "Kanal",
popout_server_text: "Sunucu",
popout_allservers_text: "Tüm Sunucular",
popout_sort_text: "Göre sırala",
popout_messagesort_text: "Mesaj-Tarih",
popout_datesort_text: "Not-Tarih",
popout_jump_text: "Git",
popout_copy_text: "Kopyalamak",
context_noteoption_text: "Mesajı not alın",
popout_noteoption_text: "Not almak",
toast_noteadd_text: "Mesaj not defteri'ya eklendi.",
toast_noteremove_text: "Mesaj not defteri'dan kaldırıldı."
};
case "cs": //czech
return {
popout_note_text: "Poznámky",
popout_channel_text: "Kanál",
popout_server_text: "Server",
popout_allservers_text: "Všechny servery",
popout_sort_text: "Seřazeno podle",
popout_messagesort_text: "Zpráva-datum",
popout_datesort_text: "Poznámka-datum",
popout_jump_text: "Skok",
popout_copy_text: "Kopírovat",
context_noteoption_text: "Poznámka dolů zprávu",
popout_noteoption_text: "Poznámka dolů",
toast_noteadd_text: "Zpráva byla přidána do notebooku.",
toast_noteremove_text: "Zpráva byla odebrána z notebooku."
};
case "bg": //bulgarian
return {
popout_note_text: "бележките",
popout_channel_text: "Канал",
popout_server_text: "Сървър",
popout_allservers_text: "Всички сървъри",
popout_sort_text: "Сортиране по",
popout_messagesort_text: "Съобщение-Дата",
popout_datesort_text: "Забележка-Дата",
popout_jump_text: "Направо",
popout_copy_text: "Копирам",
context_noteoption_text: "Oтбележете съобщението",
popout_noteoption_text: "Oтбележете",
toast_noteadd_text: "Съобщението бе добавено към бележника.",
toast_noteremove_text: "Съобщението е премахнато от преносимия компютър."
};
case "ru": //russian
return {
popout_note_text: "Заметки",
popout_channel_text: "Канал",
popout_server_text: "Cервер",
popout_allservers_text: "Все серверы",
popout_sort_text: "Сортировать по",
popout_messagesort_text: "Сообщение-дата",
popout_datesort_text: "Заметки-Дата",
popout_jump_text: "Перейти",
popout_copy_text: "Копировать",
context_noteoption_text: "Записывать вниз",
popout_noteoption_text: "Записывать",
toast_noteadd_text: "Сообщение добавлено в блокнот.",
toast_noteremove_text: "Сообщение удалено из записной книжки."
};
case "uk": //ukrainian
return {
popout_note_text: "Замітки",
popout_channel_text: "Канал",
popout_server_text: "Сервер",
popout_allservers_text: "Всі сервери",
popout_sort_text: "Сортувати за",
popout_messagesort_text: "Повідомлення-дата",
popout_datesort_text: "Примітка-дата",
popout_jump_text: "Плиг",
popout_copy_text: "Копіювати",
context_noteoption_text: "Зверніть увагу на повідомлення",
popout_noteoption_text: "Занотуйте",
toast_noteadd_text: "Повідомлення додається до ноутбука.",
toast_noteremove_text: "Повідомлення видалено з ноутбука."
};
case "ja": //japanese
return {
popout_note_text: "ノート",
popout_channel_text: "チャネル",
popout_server_text: "サーバ",
popout_allservers_text: "すべてのサーバー",
popout_sort_text: "並び替え",
popout_messagesort_text: "メッセージ-日付",
popout_datesort_text: "注-日付",
popout_jump_text: "ジャンプ",
popout_copy_text: "写す",
context_noteoption_text: "ノートダウンメッセージ",
popout_noteoption_text: "書き留める",
toast_noteadd_text: "ノートブックにメッセージが追加されました.",
toast_noteremove_text: "ノートブックからメッセージが削除されました."
};
case "zh-TW": //chinese (traditional)
return {
popout_note_text: "筆記",
popout_channel_text: "渠道",
popout_server_text: "服務器",
popout_allservers_text: "所有服務器",
popout_sort_text: "排序方式",
popout_messagesort_text: "消息-日期",
popout_datesort_text: "注-日期",
popout_jump_text: "跳到",
popout_copy_text: "複製",
context_noteoption_text: "記下下來的消息",
popout_noteoption_text: "記下",
toast_noteadd_text: "消息添加到筆記本.",
toast_noteremove_text: "消息從筆記本中刪除."
};
case "ko": //korean
return {
popout_note_text: "노트",
popout_channel_text: "채널",
popout_server_text: "섬기는 사람",
popout_allservers_text: "모든 서버",
popout_sort_text: "정렬 기준",
popout_messagesort_text: "메시지-날짜",
popout_datesort_text: "주-날짜",
popout_jump_text: "이동",
popout_copy_text: "베끼다",
context_noteoption_text: "메모 다운 메시지",
popout_noteoption_text: "메모하다",
toast_noteadd_text: "노트북에 메시지 추가됨.",
toast_noteremove_text: "노트에서 메시지 삭제됨."
};
default: //default: english
return {
popout_note_text: "Notes",
popout_channel_text: "Channel",
popout_server_text: "Server",
popout_allservers_text: "All Servers",
popout_sort_text: "Sort by",
popout_messagesort_text: "Message-Date",
popout_datesort_text: "Note-Date",
popout_jump_text: "Jump",
popout_copy_text: "Copy",
context_noteoption_text: "Note Message",
popout_noteoption_text: "Note",
toast_noteadd_text: "Message added to notebook.",
toast_noteremove_text: "Message removed from notebook."
};
}
}
}

View File

@ -0,0 +1,3 @@
# Personal Pins - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PersonalPins/PersonalPins.plugin.js)
Allows you to pin messages in your own personal note books. Similar to pins you can check the notes of the current channel via the controlbar on the top.

View File

@ -0,0 +1,409 @@
//META{"name":"PinDMs"}*//
class PinDMs {
initConstructor () {
this.pinDMEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitem} pindm-item">
<span>REPLACE_context_pindm_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>`;
this.pinDMsHeaderMarkup =
`<header class="pinneddms-header">REPLACE_header_pinneddms_text</header>`;
this.pinnedDMMarkup =
`<div class="${BDFDB.disCN.dmchannel} pinned" style="height: 42px; opacity: 1;">
<a>
<div class="${BDFDB.disCNS.avatarwrapper + BDFDB.disCNS.avatarsmall + BDFDB.disCNS.forcedarktheme + BDFDB.disCN.avatarsmallold}">
<div class="${BDFDB.disCN.avatarsmallold} stop-animation"></div>
<div class="${BDFDB.disCNS.status + BDFDB.disCNS.statusold + BDFDB.disCN.avatarsmall}"></div>
</div>
<div class="${BDFDB.disCN.dmchannelname}">
<label style="cursor: pointer;"></label>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.dmchannelactivity}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCN.dmchannelactivitytext}"></div>
</div>
</div>
<button class="${BDFDB.disCN.dmchannelclose}"></button>
</a>
</div>`;
this.richActivityMarkup =
`<svg name="RichActivity" class="${BDFDB.disCN.dmchannelactivityicon}" width="16" height="16" viewBox="0 0 16 16">
<path class="${BDFDB.disCN.dmchannelactivityiconforeground}" fill="currentColor" d="M6,7 L2,7 L2,6 L6,6 L6,7 Z M8,5 L2,5 L2,4 L8,4 L8,5 Z M8,3 L2,3 L2,2 L8,2 L8,3 Z M8.88888889,0 L1.11111111,0 C0.494444444,0 0,0.494444444 0,1.11111111 L0,8.88888889 C0,9.50253861 0.497461389,10 1.11111111,10 L8.88888889,10 C9.50253861,10 10,9.50253861 10,8.88888889 L10,1.11111111 C10,0.494444444 9.5,0 8.88888889,0 Z" transform="translate(3 3)"></path>
</svg>`;
}
getName () {return "PinDMs";}
getDescription () {return "Allows you to pin DMs, making them appear at the top of your DM-list.";}
getVersion () {return "1.1.4";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UserStore = BDFDB.WebModules.findByProperties(["getUsers", "getUser"]);
this.ActivityModule = BDFDB.WebModules.findByProperties(["getActivity","getStatuses"]) || BDFDB.WebModules.findByProperties(["getApplicationActivity","getStatus"]);
this.ChannelStore = BDFDB.WebModules.findByProperties(["getDMFromUserId"]);
this.ChannelSwitchUtils = BDFDB.WebModules.findByProperties(["selectPrivateChannel"]);
this.UserContextMenuUtils = BDFDB.WebModules.findByProperties(["openUserContextMenu"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"dmContextObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(`a[href="/channels/@me"]`)) {
$(BDFDB.dotCN.dmchannel + ".pinned, header.pinneddms-header").remove();
this.addAllPinnedDMs();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCNS.dmchannels + BDFDB.dotCN.scroller, {name:"friendButtonObserver",instance:observer}, {childList: true});
setTimeout(() => {this.onSwitch();},1000);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(BDFDB.dotCN.dmchannel + ".pinned, header.pinneddms-header").remove();
clearInterval(this.statusInterval);
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (BDFDB.getSelectedServer()) clearInterval(this.statusInterval);
if (!document.querySelector(BDFDB.dotCNS.guildselected + BDFDB.dotCN.friendsicon) || document.querySelector(BDFDB.dotCN.dmchannel + ".pinned")) return;
this.addAllPinnedDMs();
BDFDB.addObserver(this, BDFDB.dotCNS.dmchannels + BDFDB.dotCN.scroller, {name:"friendButtonObserver"}, {childList: true});
}
// begin of own functions
changeLanguageStrings () {
this.pinDMsHeaderMarkup = this.pinDMsHeaderMarkup.replace("REPLACE_header_pinneddms_text", this.labels.header_pinneddms_text);
this.pinDMEntryMarkup = this.pinDMEntryMarkup.replace("REPLACE_context_pindm_text", this.labels.context_pindm_text);
}
onContextMenu (context) {
if (!document.querySelector(BDFDB.dotCNS.guildselected + BDFDB.dotCN.friendsicon) || !context || !context.tagName || !context.parentElement || context.querySelector(".pindm-item")) return;
var info = BDFDB.getKeyInformation({"node":context, "key":"user"}), ele = null;
if (info && BDFDB.getKeyInformation({"node":context, "key":"handleClose"})) {
ele = context.querySelectorAll(BDFDB.dotCN.contextmenuitem)[3];
}
else {
info = BDFDB.getKeyInformation({"node":context, "key":"channel"});
if (info && BDFDB.getKeyInformation({"node":context, "key":"handleChangeIcon"})) {
ele = context.querySelectorAll(BDFDB.dotCN.contextmenuitem)[1];
}
}
if (ele) {
$(this.pinDMEntryMarkup).insertBefore(ele)
.on("click", (e) => {
$(context).hide();
var pinnedDMs = BDFDB.loadAllData(this, "pinnedDMs");
if (typeof pinnedDMs[info.id] == "undefined") {
var pos = Object.keys(pinnedDMs).length;
pinnedDMs[info.id] = pos;
BDFDB.saveAllData(pinnedDMs, this, "pinnedDMs")
this.addPinnedDM(info.id, pos);
}
});
BDFDB.updateContextPosition(context);
}
}
addAllPinnedDMs () {
let pinnedDMs = BDFDB.loadAllData(this, "pinnedDMs");
let sortedDMs = [];
delete pinnedDMs[""];
for (let id in pinnedDMs) this.sortDM(sortedDMs, pinnedDMs[id], id);
sortedDMs = sortedDMs.filter(n => n);
for (let pos in sortedDMs) {
pinnedDMs[sortedDMs[pos]] = parseInt(pos);
this.addPinnedDM(sortedDMs[pos], pos);
}
BDFDB.saveAllData(pinnedDMs, this, "pinnedDMs");
}
sortDM (sortedDMs, pos, id) {
if (typeof sortedDMs[pos] == "undefined") sortedDMs[pos] = id;
else this.sortDM(sortedDMs, pos+1, id);
}
addPinnedDM (id, pos) {
if (!document.querySelector(BDFDB.dotCN.dmchannel + " + header.pinneddms-header")) {
$(this.pinDMsHeaderMarkup).insertBefore(document.querySelector(BDFDB.dotCN.dmchannel + " + header"));
this.startUpdateInterval();
}
let user = this.UserStore.getUser(id);
let channel = this.ChannelStore.getChannel(id);
if (user || channel) {
let DMid = user ? this.ChannelStore.getDMFromUserId(user.id) : channel.id;
let pinnedDM = $(this.pinnedDMMarkup);
pinnedDM.attr("user-id", user ? user.id : null).attr("channel-id", DMid).insertAfter(BDFDB.dotCN.dmchannel + " + header.pinneddms-header")
.on("contextmenu." + this.getName(), (e) => {
if (user && DMid) this.UserContextMenuUtils.openUserContextMenu(e, user, this.ChannelStore.getChannel(DMid));
else {
var channelObj = BDFDB.getDivOfChannel(channel.id);
if (channelObj && channelObj.div) BDFDB.getKeyInformation({"node":channelObj.div,"key":"onContextMenu"})(e);
else BDFDB.showToast("Could not open ContextMenu, make sure the DM exists, Group DMs habe to be loaded in the list.", {type:"error"});
}
})
.on("click." + this.getName(), (e) => {
if (e.target.classList && e.target.classList.contains(BDFDB.disCN.dmchannelclose)) return;
if (DMid) this.ChannelSwitchUtils.selectPrivateChannel(DMid);
else BDFDB.showToast("Could not open DM, make sure it exists.", {type:"error"});
})
.on("click." + this.getName(), BDFDB.dotCN.dmchannelclose, () => {
pinnedDM.remove();
BDFDB.removeData(user ? user.id : DMid, this, "pinnedDMs");
this.updatePinnedDMPositions();
});
this.setPinnedDM(pinnedDM[0]);
}
}
setPinnedDM (pinnedDM) {
if (pinnedDM && pinnedDM.parentElement) {
let id = pinnedDM.getAttribute("user-id");
let user = this.UserStore.getUser(id);
if (user) {
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
let activity = this.ActivityModule.getActivity ? this.ActivityModule.getActivity(id) : this.ActivityModule.getApplicationActivity(id);
pinnedDM.querySelector(BDFDB.dotCN.avatarsmallold + ":not(" + BDFDB.dotCN.avatarwrapper + ")").style.backgroundImage = `url(${data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(user.id))})`;
pinnedDM.querySelector(BDFDB.dotCN.status).classList.add(BDFDB.disCN[`status${BDFDB.getUserStatus(user.id)}`]);
pinnedDM.querySelector(BDFDB.dotCN.dmchannelname + " > label").textContent = data.name ? data.name : user.username;
pinnedDM.querySelector(BDFDB.dotCN.dmchannelname).style.color = data.color1 ? BDFDB.color2RGB(data.color1) : "";
pinnedDM.querySelector(BDFDB.dotCN.dmchannelname).style.background = data.color2 ? BDFDB.color2RGB(data.color2) : "";
pinnedDM.querySelector(BDFDB.dotCN.dmchannelactivitytext).innerHTML = activity ? this.getActivityString(activity.type, activity.name) : "";
if (activity && activity.application_id && activity.session_id) {
if (!pinnedDM.querySelector(BDFDB.dotCN.dmchannelactivityicon)) $(BDFDB.dotCN.dmchannelactivity, pinnedDM).append(this.richActivityMarkup);
}
else $(BDFDB.dotCN.dmchannelactivityicon, pinnedDM).remove();
}
else {
id = pinnedDM.getAttribute("channel-id")
let channel = this.ChannelStore.getChannel(id);
if (channel) {
pinnedDM.querySelector(BDFDB.dotCN.avatarsmallold + ":not(" + BDFDB.dotCN.avatarwrapper + ")").style.backgroundImage = `url(${BDFDB.getChannelAvatar(channel.id)})`;
var channelname = channel.name;
if (!channelname && channel.recipients.length > 0) {
for (let dmmemberID of channel.recipients) {
channelname = channelname ? channelname + ", " : channelname;
channelname = channelname + this.UserStore.getUser(dmmemberID).username;
}
}
pinnedDM.querySelector(BDFDB.dotCN.dmchannelname + " > label").textContent = channelname ? channelname : BDFDB.LanguageStrings.UNNAMED;
pinnedDM.querySelectorAll(BDFDB.dotCNC.status + BDFDB.dotCN.dmchannelactivitytext).forEach(ele => {ele.remove();});
pinnedDM.querySelector(BDFDB.dotCN.dmchannelactivity).innerHTML = channel.recipients.length+1 + " " + (channel.recipients.length+1 == 1 ? BDFDB.LanguageStrings.MEMBER : BDFDB.LanguageStrings.MEMBERS);
}
}
}
}
updatePinnedDMPositions () {
let pinnedDMs = BDFDB.loadAllData(this, "pinnedDMs");
let pinnedDMEles = Array.from(document.querySelectorAll(BDFDB.dotCN.dmchannel + ".pinned")).reverse();
for (let i = 0; i < pinnedDMEles.length; i++) {
pinnedDMs[pinnedDMEles[i].getAttribute("user-id") ? pinnedDMEles[i].getAttribute("user-id") : pinnedDMEles[i].getAttribute("channel-id")] = i;
}
if (pinnedDMEles.length == 0) $(BDFDB.dotCN.dmchannel + " + header.pinneddms-header").remove();
BDFDB.saveAllData(pinnedDMs, this, "pinnedDMs")
}
startUpdateInterval () {
clearInterval(this.statusInterval);
this.statusInterval = setInterval(() => {
for (let pinnedDM of document.querySelectorAll(BDFDB.dotCN.dmchannel + ".pinned")) this.setPinnedDM(pinnedDM);
if (!document.querySelector(BDFDB.dotCN.dmchannel + " + header.pinneddms-header")) clearInterval(this.statusInterval);
},10000);
}
getActivityString (type, name) {
let stringname = "";
switch (type) {
case 0:
stringname = "PLAYING_GAME";
break;
case 1:
stringname = "STREAMING";
break;
case 2:
stringname = "LISTENING_TO";
break;
case 3:
stringname = "WATCHING";
break;
}
let string = BDFDB.LanguageStrings[stringname] || "";
return string.replace("**!!{name}!!**", `<strong>${name}</strong>`).replace("**!!{game}!!**", `<strong>${name}</strong>`);
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
context_pindm_text: "Prikljucite Izravnu Dopisivanje",
header_pinneddms_text: "Prikvačene izravne poruke"
};
case "da": //danish
return {
context_pindm_text: "Pin DB",
header_pinneddms_text: "Pinned Privat Beskeder"
};
case "de": //german
return {
context_pindm_text: "Direktnachricht anpinnen",
header_pinneddms_text: "Gepinnte Direktnachrichten"
};
case "es": //spanish
return {
context_pindm_text: "Pin MD",
header_pinneddms_text: "Mensajes Directos Fijados"
};
case "fr": //french
return {
context_pindm_text: "Épingler MP",
header_pinneddms_text: "Messages Prives Épinglés"
};
case "it": //italian
return {
context_pindm_text: "Appuntare il messaggio diretto",
header_pinneddms_text: "Messaggi Diretti Aggiunti"
};
case "nl": //dutch
return {
context_pindm_text: "PB vastpinnen",
header_pinneddms_text: "Vastgezette Persoonluke Berichten"
};
case "no": //norwegian
return {
context_pindm_text: "Pinne DM",
header_pinneddms_text: "Pinned Direktemeldinger"
};
case "pl": //polish
return {
context_pindm_text: "Przypnij PW",
header_pinneddms_text: "Prywatne Wiadomości Bezpośrednie"
};
case "pt-BR": //portuguese (brazil)
return {
context_pindm_text: "Fixar MD",
header_pinneddms_text: "Mensagens diretas fixadas"
};
case "fi": //finnish
return {
context_pindm_text: "Kiinnitä yksityisviestit",
header_pinneddms_text: "Liitetyt yksityisviestit"
};
case "sv": //swedish
return {
context_pindm_text: "Peka DM",
header_pinneddms_text: "Inlagda Direktmeddelanden"
};
case "tr": //turkish
return {
context_pindm_text: "DM'yi Sabitle",
header_pinneddms_text: "Direkt Mesajlar Sabitleyin"
};
case "cs": //czech
return {
context_pindm_text: "Připojte PZ",
header_pinneddms_text: "Připojené přímá zpráva"
};
case "bg": //bulgarian
return {
context_pindm_text: "Закачете",
header_pinneddms_text: "Свързани директни съобщения"
};
case "ru": //russian
return {
context_pindm_text: "Подключить ЛС",
header_pinneddms_text: "Прикрепленные Личные сообщения"
};
case "uk": //ukrainian
return {
context_pindm_text: "Прикріпити ОП",
header_pinneddms_text: "Прикріплені oсобисті повідомлення"
};
case "ja": //japanese
return {
context_pindm_text: "DMをピン留めする",
header_pinneddms_text: "固定された直接メッセージ"
};
case "zh-TW": //chinese (traditional)
return {
context_pindm_text: "引用私人信息",
header_pinneddms_text: "固定私人信息"
};
case "ko": //korean
return {
context_pindm_text: "개인 메시지 비공개",
header_pinneddms_text: "고정 된 비공개 메시지"
};
default: //default: english
return {
context_pindm_text: "Pin DM",
header_pinneddms_text: "Pinned Direct Messages"
};
}
}
}

View File

@ -0,0 +1,3 @@
# Pin DMs - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PinDMs/PinDMs.plugin.js)
Allows you to pin DMs, making them appear at the top of your DM-list.

View File

@ -0,0 +1,874 @@
//META{"name":"PluginRepo"}*//
class PluginRepo {
initConstructor () {
this.sortings = {
sort: {
name: "Name",
author: "Author",
version: "Version",
description: "Description",
state: "Update State",
fav: "Favorites"
},
order: {
asc: "Ascending",
desc: "Descending"
}
};
this.loading = false;
this.grabbedPlugins = [];
this.foundPlugins = [];
this.loadedPlugins = {};
this.updateInterval;
this.pluginRepoButtonMarkup =
`<button class="bd-pfbtn bd-pluginrepobutton">Plugin Repo</button>`;
this.settingsContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitem} pluginrepo-item">
<span>Plugin Repo</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>`;
this.pluginEntryMarkup =
`<li class="pluginEntry jiiks">
<div class="bda-left">
<span class="bda-name"></span>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCN.scrollerthemed}">
<div class="${BDFDB.disCN.scroller} bda-description"></div>
</div>
</div>
<div class="bda-right">
<div class="bda-header">
<svg class="favIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><path fill="none" stroke="black" d="M 19.542, 9.092 c 0.393 -0.383, 0.532 -0.946, 0.362 -1.468 c -0.17 -0.523 -0.613 -0.896 -1.157 -0.975 l -4.837 -0.703 c -0.206 -0.03 -0.384 -0.159 -0.476 -0.346 L 11.273, 1.217 c -0.243 -0.492 -0.736 -0.798 -1.285 -0.798 c -0.549, 0 -1.042, 0.306 -1.284, 0.798 L 6.541, 5.6 c -0.092, 0.187 -0.27, 0.316 -0.476, 0.346 L 1.228, 6.649 c -0.544, 0.079 -0.987, 0.452 -1.157, 0.975 c -0.17, 0.523 -0.031, 1.085, 0.362, 1.468 l 3.5, 3.411 c 0.149, 0.146, 0.218, 0.355, 0.182, 0.56 L 3.29, 17.88 c -0.073, 0.424, 0.038, 0.836, 0.312, 1.162 c 0.426, 0.507, 1.171, 0.661, 1.766, 0.348 l 4.326 -2.274 c 0.181 -0.095, 0.408 -0.094, 0.589, 0 l 4.326, 2.274 c 0.21, 0.111, 0.435, 0.167, 0.666, 0.167 c 0.423, 0, 0.824 -0.188, 1.099 -0.515 c 0.275 -0.325, 0.386 -0.738, 0.312 -1.162 l -0.826 -4.817 c -0.035 -0.205, 0.033 -0.414, 0.182 -0.56 L 19.542, 9.092 z"/></svg>
<svg class="gitIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 7.19, 16.027 c -0.139, 0.026 -0.199, 0.091 -0.182, 0.195 c 0.017, 0.104, 0.095, 0.138, 0.234, 0.104 c 0.139 -0.035, 0.199 -0.095, 0.182 -0.182 C 7.406, 16.049, 7.328, 16.01, 7.19, 16.027 z"/><path d="M 6.45, 16.131 c -0.138, 0 -0.208, 0.047 -0.208, 0.143 c 0, 0.112, 0.074, 0.16, 0.221, 0.143 c 0.138, 0, 0.208 -0.048, 0.208 -0.143 C 6.671, 16.162, 6.597, 16.114, 6.45, 16.131 z"/><path d="M 5.438, 16.092 c -0.035, 0.095, 0.022, 0.16, 0.169, 0.195 c 0.13, 0.052, 0.212, 0.026, 0.247 -0.078 c 0.026 -0.095 -0.03 -0.164 -0.169 -0.208 C 5.554, 15.967, 5.472, 15.996, 5.438, 16.092 z"/><path d="M 18.837, 1.097 C 18.106, 0.366, 17.226, 0, 16.196, 0 H 3.738 C 2.708, 0, 1.828, 0.366, 1.097, 1.097 C 0.366, 1.828, 0, 2.708, 0, 3.738 v 12.459 c 0, 1.03, 0.366, 1.91, 1.097, 2.641 c 0.731, 0.731, 1.612, 1.097, 2.641, 1.097 h 2.907 c 0.19, 0, 0.333 -0.007, 0.428 -0.019 c 0.095 -0.013, 0.19 -0.069, 0.285 -0.169 c 0.095 -0.099, 0.143 -0.244, 0.143 -0.435 c 0 -0.026 -0.002 -0.32 -0.007 -0.883 c -0.004 -0.562 -0.007 -1.008 -0.007 -1.337 l -0.298, 0.052 c -0.19, 0.035 -0.43, 0.05 -0.72, 0.045 c -0.29 -0.004 -0.59 -0.035 -0.902 -0.091 c -0.312 -0.056 -0.601 -0.186 -0.87 -0.389 c -0.268 -0.203 -0.458 -0.469 -0.571 -0.798 l -0.13 -0.299 c -0.086 -0.199 -0.223 -0.419 -0.409 -0.662 c -0.186 -0.242 -0.374 -0.407 -0.564 -0.493 l -0.091 -0.065 c -0.06 -0.043 -0.117 -0.095 -0.169 -0.156 c -0.052 -0.061 -0.091 -0.121 -0.117 -0.182 c -0.026 -0.061 -0.004 -0.11, 0.065 -0.149 c 0.069 -0.039, 0.195 -0.058, 0.376 -0.058 l 0.259, 0.039 c 0.173, 0.035, 0.387, 0.138, 0.642, 0.311 c 0.255, 0.173, 0.465, 0.398, 0.629, 0.675 c 0.199, 0.355, 0.439, 0.625, 0.72, 0.811 c 0.281, 0.186, 0.565, 0.279, 0.85, 0.279 s 0.532 -0.022, 0.74 -0.065 c 0.208 -0.043, 0.402 -0.108, 0.584 -0.195 c 0.078 -0.58, 0.29 -1.025, 0.636 -1.337 c -0.493 -0.052 -0.936 -0.13 -1.33 -0.234 c -0.394 -0.104 -0.8 -0.272 -1.22 -0.506 c -0.42 -0.234 -0.768 -0.523 -1.045 -0.87 c -0.277 -0.346 -0.504 -0.8 -0.681 -1.363 c -0.177 -0.562 -0.266 -1.211 -0.266 -1.947 c 0 -1.047, 0.342 -1.938, 1.025 -2.673 c -0.32 -0.787 -0.29 -1.67, 0.091 -2.647 c 0.251 -0.078, 0.623 -0.019, 1.116, 0.175 c 0.493, 0.195, 0.854, 0.361, 1.084, 0.5 c 0.229, 0.138, 0.413, 0.255, 0.552, 0.35 c 0.805 -0.225, 1.635 -0.337, 2.492 -0.337 c 0.856, 0, 1.687, 0.112, 2.492, 0.337 l 0.493 -0.311 c 0.338 -0.208, 0.735 -0.398, 1.194 -0.571 c 0.459 -0.173, 0.809 -0.221, 1.051 -0.143 c 0.389, 0.978, 0.424, 1.86, 0.104, 2.647 c 0.683, 0.735, 1.025, 1.627, 1.025, 2.673 c 0, 0.735 -0.089, 1.387 -0.266, 1.953 c -0.177, 0.567 -0.406, 1.021 -0.688, 1.363 c -0.281, 0.342 -0.632, 0.629 -1.051, 0.863 c -0.42, 0.234 -0.826, 0.402 -1.22, 0.506 c -0.394, 0.104 -0.837, 0.182 -1.33, 0.234 c 0.45, 0.389, 0.675, 1.003, 0.675, 1.843 v 3.102 c 0, 0.147, 0.021, 0.266, 0.065, 0.357 c 0.044, 0.091, 0.113, 0.153, 0.208, 0.188 c 0.096, 0.035, 0.18, 0.056, 0.253, 0.065 c 0.074, 0.009, 0.18, 0.013, 0.318, 0.013 h 2.907 c 1.029, 0, 1.91 -0.366, 2.641 -1.097 c 0.731 -0.731, 1.097 -1.612, 1.097 -2.641 V 3.738 C 19.933, 2.708, 19.568, 1.827, 18.837, 1.097 z"/><path d="M 3.945, 14.509 c -0.06, 0.043 -0.052, 0.112, 0.026, 0.208 c 0.087, 0.086, 0.156, 0.1, 0.208, 0.039 c 0.061 -0.043, 0.052 -0.112 -0.026 -0.208 C 4.066, 14.47, 3.997, 14.457, 3.945, 14.509 z"/><path d="M 3.517, 14.184 c -0.026, 0.061, 0.004, 0.113, 0.091, 0.156 c 0.069, 0.043, 0.126, 0.035, 0.169 -0.026 c 0.026 -0.061 -0.004 -0.113 -0.091 -0.156 C 3.599, 14.132, 3.543, 14.141, 3.517, 14.184 z"/><path d="M 4.348, 15.015 c -0.078, 0.043 -0.078, 0.121, 0, 0.234 c 0.078, 0.113, 0.151, 0.143, 0.221, 0.091 c 0.078 -0.061, 0.078 -0.143, 0 -0.247 C 4.499, 14.981, 4.425, 14.954, 4.348, 15.015 z"/><path d="M 4.802, 15.599 c -0.078, 0.069 -0.061, 0.151, 0.052, 0.247 c 0.104, 0.104, 0.19, 0.117, 0.259, 0.039 c 0.069 -0.069, 0.052 -0.151 -0.052 -0.246 C 4.958, 15.534, 4.871, 15.521, 4.802, 15.599 z"/></g></svg>
</div>
<div class="bda-footer">
<svg class="trashIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 18.012, 0.648 H 12.98 C 12.944, 0.284, 12.637, 0, 12.264, 0 H 8.136 c -0.373, 0 -0.68, 0.284 -0.716, 0.648 H 2.389 c -0.398, 0 -0.72, 0.322 -0.72, 0.72 v 1.368 c 0, 0.398, 0.322, 0.72, 0.72, 0.72 h 15.623 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 1.368 C 18.731, 0.97, 18.409, 0.648, 18.012, 0.648 z"/><path d="M 3.178, 4.839 v 14.841 c 0, 0.397, 0.322, 0.72, 0.72, 0.72 h 12.604 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 4.839 H 3.178 z M 8.449, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 c -0.438, 0 -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z M 13.538, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 s -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z"/></g></svg>
<button class="btn-download bda-settings-button">Download</button>
</div>
</div>
</li>`;
this.pluginEntryZackMarkup =
`<li class="pluginEntry settings-closed ui-switch-item zack">
<div class="bda-header">
<span class="bda-header-title">
<span class="bda-name"></span> v<span class="bda-version"></span> by <span class="bda-author"></span>
</span>
<svg class="favIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><path fill="none" stroke="black" d="M 19.542, 9.092 c 0.393 -0.383, 0.532 -0.946, 0.362 -1.468 c -0.17 -0.523 -0.613 -0.896 -1.157 -0.975 l -4.837 -0.703 c -0.206 -0.03 -0.384 -0.159 -0.476 -0.346 L 11.273, 1.217 c -0.243 -0.492 -0.736 -0.798 -1.285 -0.798 c -0.549, 0 -1.042, 0.306 -1.284, 0.798 L 6.541, 5.6 c -0.092, 0.187 -0.27, 0.316 -0.476, 0.346 L 1.228, 6.649 c -0.544, 0.079 -0.987, 0.452 -1.157, 0.975 c -0.17, 0.523 -0.031, 1.085, 0.362, 1.468 l 3.5, 3.411 c 0.149, 0.146, 0.218, 0.355, 0.182, 0.56 L 3.29, 17.88 c -0.073, 0.424, 0.038, 0.836, 0.312, 1.162 c 0.426, 0.507, 1.171, 0.661, 1.766, 0.348 l 4.326 -2.274 c 0.181 -0.095, 0.408 -0.094, 0.589, 0 l 4.326, 2.274 c 0.21, 0.111, 0.435, 0.167, 0.666, 0.167 c 0.423, 0, 0.824 -0.188, 1.099 -0.515 c 0.275 -0.325, 0.386 -0.738, 0.312 -1.162 l -0.826 -4.817 c -0.035 -0.205, 0.033 -0.414, 0.182 -0.56 L 19.542, 9.092 z"/></svg>
<svg class="gitIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 7.19, 16.027 c -0.139, 0.026 -0.199, 0.091 -0.182, 0.195 c 0.017, 0.104, 0.095, 0.138, 0.234, 0.104 c 0.139 -0.035, 0.199 -0.095, 0.182 -0.182 C 7.406, 16.049, 7.328, 16.01, 7.19, 16.027 z"/><path d="M 6.45, 16.131 c -0.138, 0 -0.208, 0.047 -0.208, 0.143 c 0, 0.112, 0.074, 0.16, 0.221, 0.143 c 0.138, 0, 0.208 -0.048, 0.208 -0.143 C 6.671, 16.162, 6.597, 16.114, 6.45, 16.131 z"/><path d="M 5.438, 16.092 c -0.035, 0.095, 0.022, 0.16, 0.169, 0.195 c 0.13, 0.052, 0.212, 0.026, 0.247 -0.078 c 0.026 -0.095 -0.03 -0.164 -0.169 -0.208 C 5.554, 15.967, 5.472, 15.996, 5.438, 16.092 z"/><path d="M 18.837, 1.097 C 18.106, 0.366, 17.226, 0, 16.196, 0 H 3.738 C 2.708, 0, 1.828, 0.366, 1.097, 1.097 C 0.366, 1.828, 0, 2.708, 0, 3.738 v 12.459 c 0, 1.03, 0.366, 1.91, 1.097, 2.641 c 0.731, 0.731, 1.612, 1.097, 2.641, 1.097 h 2.907 c 0.19, 0, 0.333 -0.007, 0.428 -0.019 c 0.095 -0.013, 0.19 -0.069, 0.285 -0.169 c 0.095 -0.099, 0.143 -0.244, 0.143 -0.435 c 0 -0.026 -0.002 -0.32 -0.007 -0.883 c -0.004 -0.562 -0.007 -1.008 -0.007 -1.337 l -0.298, 0.052 c -0.19, 0.035 -0.43, 0.05 -0.72, 0.045 c -0.29 -0.004 -0.59 -0.035 -0.902 -0.091 c -0.312 -0.056 -0.601 -0.186 -0.87 -0.389 c -0.268 -0.203 -0.458 -0.469 -0.571 -0.798 l -0.13 -0.299 c -0.086 -0.199 -0.223 -0.419 -0.409 -0.662 c -0.186 -0.242 -0.374 -0.407 -0.564 -0.493 l -0.091 -0.065 c -0.06 -0.043 -0.117 -0.095 -0.169 -0.156 c -0.052 -0.061 -0.091 -0.121 -0.117 -0.182 c -0.026 -0.061 -0.004 -0.11, 0.065 -0.149 c 0.069 -0.039, 0.195 -0.058, 0.376 -0.058 l 0.259, 0.039 c 0.173, 0.035, 0.387, 0.138, 0.642, 0.311 c 0.255, 0.173, 0.465, 0.398, 0.629, 0.675 c 0.199, 0.355, 0.439, 0.625, 0.72, 0.811 c 0.281, 0.186, 0.565, 0.279, 0.85, 0.279 s 0.532 -0.022, 0.74 -0.065 c 0.208 -0.043, 0.402 -0.108, 0.584 -0.195 c 0.078 -0.58, 0.29 -1.025, 0.636 -1.337 c -0.493 -0.052 -0.936 -0.13 -1.33 -0.234 c -0.394 -0.104 -0.8 -0.272 -1.22 -0.506 c -0.42 -0.234 -0.768 -0.523 -1.045 -0.87 c -0.277 -0.346 -0.504 -0.8 -0.681 -1.363 c -0.177 -0.562 -0.266 -1.211 -0.266 -1.947 c 0 -1.047, 0.342 -1.938, 1.025 -2.673 c -0.32 -0.787 -0.29 -1.67, 0.091 -2.647 c 0.251 -0.078, 0.623 -0.019, 1.116, 0.175 c 0.493, 0.195, 0.854, 0.361, 1.084, 0.5 c 0.229, 0.138, 0.413, 0.255, 0.552, 0.35 c 0.805 -0.225, 1.635 -0.337, 2.492 -0.337 c 0.856, 0, 1.687, 0.112, 2.492, 0.337 l 0.493 -0.311 c 0.338 -0.208, 0.735 -0.398, 1.194 -0.571 c 0.459 -0.173, 0.809 -0.221, 1.051 -0.143 c 0.389, 0.978, 0.424, 1.86, 0.104, 2.647 c 0.683, 0.735, 1.025, 1.627, 1.025, 2.673 c 0, 0.735 -0.089, 1.387 -0.266, 1.953 c -0.177, 0.567 -0.406, 1.021 -0.688, 1.363 c -0.281, 0.342 -0.632, 0.629 -1.051, 0.863 c -0.42, 0.234 -0.826, 0.402 -1.22, 0.506 c -0.394, 0.104 -0.837, 0.182 -1.33, 0.234 c 0.45, 0.389, 0.675, 1.003, 0.675, 1.843 v 3.102 c 0, 0.147, 0.021, 0.266, 0.065, 0.357 c 0.044, 0.091, 0.113, 0.153, 0.208, 0.188 c 0.096, 0.035, 0.18, 0.056, 0.253, 0.065 c 0.074, 0.009, 0.18, 0.013, 0.318, 0.013 h 2.907 c 1.029, 0, 1.91 -0.366, 2.641 -1.097 c 0.731 -0.731, 1.097 -1.612, 1.097 -2.641 V 3.738 C 19.933, 2.708, 19.568, 1.827, 18.837, 1.097 z"/><path d="M 3.945, 14.509 c -0.06, 0.043 -0.052, 0.112, 0.026, 0.208 c 0.087, 0.086, 0.156, 0.1, 0.208, 0.039 c 0.061 -0.043, 0.052 -0.112 -0.026 -0.208 C 4.066, 14.47, 3.997, 14.457, 3.945, 14.509 z"/><path d="M 3.517, 14.184 c -0.026, 0.061, 0.004, 0.113, 0.091, 0.156 c 0.069, 0.043, 0.126, 0.035, 0.169 -0.026 c 0.026 -0.061 -0.004 -0.113 -0.091 -0.156 C 3.599, 14.132, 3.543, 14.141, 3.517, 14.184 z"/><path d="M 4.348, 15.015 c -0.078, 0.043 -0.078, 0.121, 0, 0.234 c 0.078, 0.113, 0.151, 0.143, 0.221, 0.091 c 0.078 -0.061, 0.078 -0.143, 0 -0.247 C 4.499, 14.981, 4.425, 14.954, 4.348, 15.015 z"/><path d="M 4.802, 15.599 c -0.078, 0.069 -0.061, 0.151, 0.052, 0.247 c 0.104, 0.104, 0.19, 0.117, 0.259, 0.039 c 0.069 -0.069, 0.052 -0.151 -0.052 -0.246 C 4.958, 15.534, 4.871, 15.521, 4.802, 15.599 z"/></g></svg>
</div>
<div class="bda-description-wrap ${BDFDB.disCN.scrollerwrap}">
<div class="bda-description ${BDFDB.disCN.scroller}" style="display: block;"></div>
</div>
<div class="bda-footer">
<span class="bda-links"></span>
<svg class="trashIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 18.012, 0.648 H 12.98 C 12.944, 0.284, 12.637, 0, 12.264, 0 H 8.136 c -0.373, 0 -0.68, 0.284 -0.716, 0.648 H 2.389 c -0.398, 0 -0.72, 0.322 -0.72, 0.72 v 1.368 c 0, 0.398, 0.322, 0.72, 0.72, 0.72 h 15.623 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 1.368 C 18.731, 0.97, 18.409, 0.648, 18.012, 0.648 z"/><path d="M 3.178, 4.839 v 14.841 c 0, 0.397, 0.322, 0.72, 0.72, 0.72 h 12.604 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 4.839 H 3.178 z M 8.449, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 c -0.438, 0 -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z M 13.538, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 s -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z"/></g></svg>
<button class="btn-download bda-settings-button">Download</button>
</div>
</li>`;
this.pluginRepoModalMarkup =
`<span class="pluginrepo-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizelarge}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto; padding: 20px 20px 0 20px;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset} pluginAmount">Plugin Repository</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.modalheader + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto; padding: 10px 20px 0px 20px;">
<div tab="plugins" class="tab selected">Plugins</div>
<div tab="settings" class="tab">Settings</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.searchbar + BDFDB.disCN.size14}" style="flex: 1 1 auto; margin: -15px 5px 0 0;">
<input class="${BDFDB.disCNS.searchbarinput + BDFDB.disCN.flexchild}" value="" placeholder="Search for ..." style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.searchbariconwrap + BDFDB.disCN.flexchild}">
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCNS.searchbareyeglass + BDFDB.disCN.searchbarvisible}"/>
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCN.searchbarclear}"/>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="padding-bottom: 15px;">
<div class="${BDFDB.disCN.quickselectlabel}">Sort by:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} sort-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.sort)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="padding-bottom: 15px;">
<div class="${BDFDB.disCN.quickselectlabel}">Order:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} order-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.order)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.order[Object.keys(this.sortings.order)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
</div>
<div tab="plugins" class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline} tab-content">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} ui-standard-sidebar-view">
<ul class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCN.nowrap} bda-slist plugins" style="flex: 1 1 auto;"></ul>
</div>
</div>
<div tab="settings" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalsubinner} tab-content" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto; width: 800px;">To expierence PluginRepo in the best way. I would recommend you to download Restart-No-More, which automatically loads newly downloaded Plugins into your BetterDiscord, so you won't have to reload after downloading a Plugin.</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide updated Plugins.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="updated" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hideupdated">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide outdated Plugins.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="outdated" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hideoutdated">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide downloadable Plugins.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="downloadable" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hidedownloadable">
</div>
</div>
<div id="RNMoption" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Start Plugin after Download (Restart-No-More needed)</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-rnmstart">
</div>
</div>
</div>
</div>
</div>
</div>
</span>`;
this.sortPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} pluginrepo-sort-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.sort).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.sort[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.orderPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} pluginrepo-order-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.order).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.order[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.css = `
.pluginrepo-modal ${BDFDB.dotCN.modalinner} {
min-height: 100%;
}
.pluginrepo-modal .pluginEntry.zack {
overflow: visible !important;
}
.pluginrepo-modal .pluginEntry .gitIcon,
.pluginrepo-modal .pluginEntry .favIcon,
.pluginrepo-modal .pluginEntry .trashIcon {
margin-right: 5px;
cursor: pointer;
}
.pluginrepo-modal .pluginEntry .trashIcon,
.pluginrepo-modal .pluginEntry .favIcon {
margin-left: auto;
}
.pluginrepo-modal .pluginEntry .btn-download {
margin-left: 0 !important;
}
.pluginrepo-modal .pluginEntry .favIcon path {
stroke: yellow;
fill: none;
}
.pluginrepo-modal .pluginEntry .favIcon.favorized path {
stroke: yellow;
fill: yellow;
}
.pluginrepo-modal .pluginEntry.downloadable .trashIcon {
display: none;
}
.pluginrepo-modal .pluginEntry.downloadable .btn-download {
background-color: rgb(114, 137, 218) !important;
margin-left: auto !important;
}
.pluginrepo-modal .pluginEntry.outdated .btn-download {
background-color: rgb(240, 71, 71) !important;
margin-left: 0 !important;
}
.pluginrepo-modal .pluginEntry.updated .btn-download {
background-color: rgb(67, 181, 129) !important;
margin-left: 0 !important;
}
.pluginrepo-trashicon-tooltip{
z-index: 3500!important;
}
.pluginrepo-modal .pluginEntry.jiiks .bda-right {
flex: 1 1 auto;
}
.pluginrepo-modal .pluginEntry.jiiks .bda-header,
.pluginrepo-modal .pluginEntry.jiiks .bda-footer {
display: flex;
align-items: center;
margin: 0 !important;
}
.pluginrepo-modal .pluginEntry.jiiks .bda-footer {
margin-top: 33% !important;
}`;
}
getName () {return "PluginRepo";}
getDescription () {return "Allows you to look at all plugins from the plugin repo and download them on the fly. Repo button is in the plugins settings.";}
getVersion () {return "1.5.3";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Add Plugin:</h3><input type="text" placeholder="Insert Raw Github Link of Plugin (https://raw.githubusercontent.com/...)" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-pluginurl" style="flex: 1 1 auto;"><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-addplugin" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div>`;
settingshtml += `<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Your additional Plugin List:</h3><div class="DevilBro-settings-inner-list plugin-list ${BDFDB.disCN.marginbottom8}">`;
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
for (let url of ownlist) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryurl">${url}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-plugin"></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Force all Plugins to be fetched again.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} refresh-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Refresh</div></button></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Remove all added Plugins from your own list.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} remove-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".btn-addplugin", () => {this.addPluginToOwnList(settingspanel);})
.on("keyup", "#input-pluginurl", (e) => {if (e.which == 13) this.addPluginToOwnList(settingspanel);})
.on("click", ".remove-plugin", (e) => {this.removePluginFromOwnList(e);})
.on("click", ".remove-all", () => {this.removeAllFromOwnList(settingspanel);})
.on("click", ".refresh-button", () => {this.loadPlugins();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, j) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
this.checkIfPluginsPage(node);
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layer + "[layer-id='user-settings']", {name:"innerSettingsWindowObserver",instance:observer}, {childList:true,subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
setImmediate(() => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
BDFDB.addObserver(this, node, {name:"innerSettingsWindowObserver"}, {childList:true,subtree:true});
this.checkIfPluginsPage(node);
}
});
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"settingsContextObserver",instance:observer}, {childList: true});
var settingswindow = document.querySelector(BDFDB.dotCN.layer + "[layer-id='user-settings']");
if (settingswindow) this.checkIfPluginsPage(settingswindow);
this.loadPlugins();
this.updateInterval = setInterval(() => {this.checkForNewPlugins();},1000*60*30);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
clearInterval(this.updateInterval);
$(".pluginrepo-modal, .bd-pluginrepobutton, webview[webview-PluginRepo]").remove();
BDFDB.unloadMessage(this);
}
}
// begin of own functions
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement) return;
for (let entry of context.querySelectorAll(BDFDB.dotCN.contextmenuitem)) {
if (entry.textContent == "BetterDiscord") {
let innerObserver = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu) && !node.querySelector(".pluginrepo-item")) {
for (let innerEntry of node.querySelectorAll(BDFDB.dotCN.contextmenuitem)) {
if (innerEntry.textContent == "Themes") {
$(this.settingsContextEntryMarkup)
.on("click", () => {
if (!this.loading) $(context).hide();
this.openPluginRepoModal();
})
.insertAfter(innerEntry);
$(node).css("top", $(context).css("top").replace("px","") - $(node).outerHeight() + $(context).outerHeight());
break;
}
}
}
});
}
}
);
});
innerObserver.observe(entry, {childList: true});
break;
}
}
}
addPluginToOwnList (settingspanel) {
var pluginUrlInput = settingspanel.querySelector("#input-pluginurl");
var pluginList = settingspanel.querySelector(".plugin-list");
if (pluginUrlInput && pluginList) {
var url = pluginUrlInput.value;
pluginUrlInput.value = null;
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
if (!ownlist.includes(url)) {
ownlist.push(url);
BDFDB.saveData("ownlist", ownlist, this, "ownlist");
$(`<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryurl">${url}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-plugin"></div></div>`).appendTo(pluginList);
}
}
}
removePluginFromOwnList (e) {
var entry = e.currentTarget.parentElement;
var url = entry.querySelector(".entryurl").textContent;
entry.remove();
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
BDFDB.removeFromArray(ownlist, url);
BDFDB.saveData("ownlist", ownlist, this, "ownlist");
}
removeAllFromOwnList (settingspanel) {
if (confirm("Are you sure you want to remove all added Plugins from your own list?")) {
BDFDB.saveData("ownlist", [], this, "ownlist");
settingspanel.querySelectorAll(BDFDB.dotCN.hovercard).forEach(ele => {ele.remove();});
}
}
checkIfPluginsPage (container) {
if (container && container.tagName) {
var folderbutton = container.querySelector(".bd-pfbtn");
if (folderbutton) {
var buttonbar = folderbutton.parentElement;
if (buttonbar && buttonbar.tagName) {
var header = buttonbar.querySelector("h2");
if (header && header.innerText.toUpperCase() === "PLUGINS") {
this.addPluginRepoButton(buttonbar);
}
}
}
}
}
addPluginRepoButton (container) {
if (container && !container.querySelector(".bd-pluginrepobutton")) {
$(container).find(".bda-description").css("display", "block");
$(this.pluginRepoButtonMarkup)
.insertAfter(container.querySelector(".bd-pfbtn"))
.on("click", () => {
this.openPluginRepoModal()
})
.on("mouseenter", (e) => {
BDFDB.createTooltip("Open Plugin Repo", e.currentTarget, {type:"top",selector:"pluginrepo-button-tooltip"});
});
}
}
openPluginRepoModal (showOnlyOutdated = false) {
if (this.loading) {
BDFDB.showToast(`Plugins are still being fetched. Try again in some seconds.`, {type:"danger"});
return;
}
var pluginRepoModal = $(this.pluginRepoModalMarkup);
pluginRepoModal.updateModal = true;
pluginRepoModal.enableSearch = false;
var hiddenSettings = BDFDB.loadAllData(this, "hidden");
pluginRepoModal.find("#input-hideupdated").prop("checked", hiddenSettings.updated || showOnlyOutdated);
pluginRepoModal.find("#input-hideoutdated").prop("checked", hiddenSettings.outdated && !showOnlyOutdated);
pluginRepoModal.find("#input-hidedownloadable").prop("checked", hiddenSettings.downloadable || showOnlyOutdated);
if (!BDFDB.isRestartNoMoreEnabled()) pluginRepoModal.find("#RNMoption").remove();
else pluginRepoModal.find("#input-rnmstart").prop("checked", BDFDB.loadData("RNMstart", this, "settings"));
pluginRepoModal
.on("keyup." + this.getName(), BDFDB.dotCN.searchbarinput, () => {
clearTimeout(pluginRepoModal.searchTimeout);
pluginRepoModal.searchTimeout = setTimeout(() => {this.addPluginEntries(pluginRepoModal);},1000);
})
.on("click." + this.getName(), BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => {
clearTimeout(pluginRepoModal.searchTimeout);
pluginRepoModal.searchTimeout = setTimeout(() => {this.addPluginEntries(pluginRepoModal);},1000);
})
.on("change." + this.getName(), ".hide-checkbox", (e) => {
var hideButton = $(e.currentTarget);
hiddenSettings[hideButton.val()] = hideButton.prop("checked");
BDFDB.saveAllData(hiddenSettings, this, "hidden");
})
.on("change." + this.getName(), "#input-rnmstart", (e) => {
BDFDB.saveData("RNMstart", $(e.currentTarget).prop("checked"), this, "settings");
})
.on("click." + this.getName(), ".sort-filter", (e) => {
this.openSortPopout(e, this.sortPopoutMarkup, pluginRepoModal);
})
.on("click." + this.getName(), ".order-filter", (e) => {
this.openSortPopout(e, this.orderPopoutMarkup, pluginRepoModal);
})
.on("click." + this.getName(), ".tab[tab=plugins]:not(.selected)", (e) => {
this.addPluginEntries(pluginRepoModal);
});
this.createPluginEntries(pluginRepoModal);
BDFDB.appendModal(pluginRepoModal);
}
openSortPopout (e, markup, modal) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains("popout-open")) return;
wrapper.classList.add("popout-open");
var value = $(wrapper).find(BDFDB.dotCN.quickselectvalue);
var popout = $(markup);
$(BDFDB.dotCN.popouts).append(popout)
.off("click", BDFDB.dotCN.contextmenuitem)
.on("click", BDFDB.dotCN.contextmenuitem, (e2) => {
value.text($(e2.currentTarget).text());
value.attr("option", $(e2.currentTarget).attr("option"));
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
this.addPluginEntries(modal);
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
});
popout
.css("left", $(wrapper).offset().left + $(wrapper).outerWidth() + "px")
.css("top", $(wrapper).offset().top + value.outerHeight() + "px")
.find(BDFDB.dotCN.contextmenu).addClass(BDFDB.getDiscordTheme());
$(document).on("mousedown.sortpopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0) {
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
}
});
}
createPluginEntries (modal) {
var favorites = BDFDB.loadAllData(this, "favorites");
modal.entries = [];
for (let url in this.loadedPlugins) {
let plugin = this.loadedPlugins[url];
let div = BDFDB.zacksFork() ? $(this.pluginEntryZackMarkup) : $(this.pluginEntryMarkup);
var installedPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null;
if (installedPlugin && installedPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase()) {
if (installedPlugin.getVersion() != plugin.getVersion) {
plugin.getState = 1;
div.addClass("outdated")
.find(".btn-download").text("Outdated");
}
else {
plugin.getState = 0;
div.addClass("updated")
.find(".btn-download").text("Updated");
}
}
else {
plugin.getState = 2;
div.addClass("downloadable")
.find(".btn-download").text("Download");
}
if (favorites[url]) {
plugin.getFav = 0;
div.find(".favIcon")[0].classList.add("favorized");
}
else {
plugin.getFav = 1;
div.find(".favIcon")[0].classList.remove("favorized");
}
modal.entries.push({
div: div,
url: plugin.url,
search: (plugin.getName + " " + plugin.getVersion + " " + plugin.getAuthor + " " + plugin.getDescription).toUpperCase(),
name: plugin.getName,
version: plugin.getVersion,
author: plugin.getAuthor,
description: plugin.getDescription ? plugin.getDescription : "No Description found.",
fav: plugin.getFav,
state: plugin.getState
});
}
this.addPluginEntries(modal);
}
addPluginEntries (modal) {
if (typeof modal.entries != "object") return;
modal.find(".pluginEntry").remove();
var searchstring = modal.find(BDFDB.dotCN.searchbarinput).val().replace(/[<|>]/g, "").toUpperCase();
var entries = modal.entries;
if (modal.find("#input-hideupdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 0 ? entry : null;});
if (modal.find("#input-hideoutdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 1 ? entry : null;});
if (modal.find("#input-hidedownloadable").prop("checked")) entries = entries.filter((entry) => {return entry.state != 2 ? entry : null;});
entries = entries.filter((entry) => {return entry.search.indexOf(searchstring) > -1 ? entry : null;});
BDFDB.sortArrayByKey(entries, modal.find(".sort-filter " + BDFDB.dotCN.quickselectvalue).attr("option"));
if (modal.find(".order-filter " + BDFDB.dotCN.quickselectvalue).attr("option") == "desc") entries.reverse();
modal.find(".pluginAmount").text("Plugin Repository " + entries.length + "/" + Object.keys(this.loadedPlugins).length + " Plugins");
var container = modal.find(".plugins");
entries.forEach((entry) => {
var div = entry.div;
var values = [entry.name, entry.version, entry.author, entry.description];
if (searchstring.length > 0) {
for (let i in values) values[i] = BDFDB.highlightText(values[i], searchstring);
}
if (BDFDB.zacksFork()) {
div.find(".bda-name").html(values[0]);
div.find(".bda-version").html(values[1]);
div.find(".bda-author").html(values[2]);
}
else {
div.find(".bda-name").html(values[0] + " v" + values[1] + " by " + values[2]);
}
div.find(".bda-description").html(values[3]);
div
.on("click." + this.getName(), ".favIcon", (e) => {
e.currentTarget.classList.toggle("favorized");
if (e.currentTarget.classList.contains("favorized")) {
entry.fav = 0;
BDFDB.saveData(entry.url, true, this, "favorites");
}
else {
entry.fav = 1;
BDFDB.removeData(entry.url, this, "favorites");
}
})
.on("click." + this.getName(), ".gitIcon", (e) => {
var giturl = null;
if (entry.url.indexOf("https://raw.githubusercontent.com") == 0) {
var temp = entry.url.replace("//raw.githubusercontent", "//github").split("/");
temp.splice(5, 0, "blob");
giturl = temp.join("/");
}
else if (entry.url.indexOf("https://gist.githubusercontent.com/") == 0) {
giturl = entry.url.replace("//gist.githubusercontent", "//gist.github").split("/raw/")[0];
}
if (giturl) {
window.open(giturl, "_blank");
}
})
.on("click." + this.getName(), ".trashIcon", () => {
if (div.hasClass("outdated") || div.hasClass("updated")) {
entry.state = 2;
div.removeClass("outdated").removeClass("updated").addClass("downloadable")
.find(".btn-download").text("Download");
this.deletePluginFile(entry);
if (!BDFDB.isRestartNoMoreEnabled()) this.stopPlugin(entry);
}
})
.on("click." + this.getName(), ".btn-download", () => {
entry.state = 0;
div.removeClass("downloadable").removeClass("outdated").addClass("updated")
.find(".btn-download").text("Updated");
this.downloadPlugin(entry);
if (modal.find("#input-rnmstart").prop("checked")) setTimeout(() => {this.startPlugin(entry);},3000);
})
.on("mouseenter." + this.getName(), ".favIcon", (e) => {
BDFDB.createTooltip("Favorize", e.currentTarget, {type:"top",selector:"pluginrepo-favicon-tooltip"});
})
.on("mouseenter." + this.getName(), ".gitIcon", (e) => {
BDFDB.createTooltip("Go to Git", e.currentTarget, {type:"top",selector:"pluginrepo-giticon-tooltip"});
})
.on("mouseenter." + this.getName(), ".trashIcon", (e) => {
BDFDB.createTooltip("Delete Pluginfile", e.currentTarget, {type:"top",selector:"pluginrepo-trashicon-tooltip"});
});
container.append(div);
});
}
loadPlugins () {
var getPluginInfo, outdated = 0, i = 0;
var tags = ["getName", "getVersion", "getAuthor", "getDescription"];
var seps = ["\"", "\'", "\`"];
let request = require("request");
request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => {
if (response) {
this.loadedPlugins = {};
this.grabbedPlugins = result.split("\n");
this.foundPlugins = this.grabbedPlugins.concat(BDFDB.loadData("ownlist", this, "ownlist") || []);
this.loading = true;
createWebview().then((webview) => {
getPluginInfo(webview, () => {
this.loading = false;
console.log("PluginRepo: Finished fetching Plugins.");
if (document.querySelector(".bd-pluginrepobutton")) BDFDB.showToast(`Finished fetching Plugins.`, {type:"success"});
if (outdated > 0) {
var text = `${outdated} of your Plugins ${outdated == 1 ? "is" : "are"} outdated. Check:`;
var bar = BDFDB.createNotificationsBar(text,{type:"danger",btn:"PluginRepo",selector:"pluginrepo-notice"});
$(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => {
this.openPluginRepoModal(true);
e.delegateTarget.querySelector(BDFDB.dotCN.noticedismiss).click();
});
}
setTimeout(() => {webview.remove();},10000);
if (BDFDB.myData.id == "278543574059057154") {
let wrongUrls = [];
for (let url of this.foundPlugins) if (url && !this.loadedPlugins[url]) wrongUrls.push(url);
if (wrongUrls.length > 0) {
var bar = BDFDB.createNotificationsBar(`PluginRepo: ${wrongUrls.length} Plugin${wrongUrls.length > 1 ? "s" : ""} could not be loaded.`, {type:"danger",btn:"List"});
$(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => {
var toast = BDFDB.showToast(wrongUrls.join("\n"),{type:"error"});
toast.style.overflow = "hidden";
console.log(wrongUrls.length == 1 ? wrongUrls[0] : wrongUrls);
});
}
}
});
});
}
});
getPluginInfo = (webview, callback) => {
if (i >= this.foundPlugins.length) {
callback();
return;
}
let url = this.foundPlugins[i].replace(new RegExp("[\\r|\\n|\\t]", "g"), "");
this.foundPlugins[i] = url;
request(url, (error, response, body) => {
if (response) {
let plugin = {};
let bodycopy = body;
if (body.length / body.split("\n").length > 1000) {
/* code is minified -> add newlines */
bodycopy = body.replace(new RegExp("}", "g"), "}\n");
}
for (let tag of tags) {
let result = new RegExp(tag + "[\\s|\\t|\\n|\\r|=|>|_|:|function|\(|\)|\{|return]*([\"|\'|\`]).*\\1","gi").exec(bodycopy);
if (result) {
let separator = result[1];
result = result[0].replace(new RegExp("\\\\" + separator, "g"), separator).split(separator);
if (result.length > 2) {
result = result.slice(1, -1).join(separator).replace(new RegExp("\\\\n", "g"), "<br>").replace(new RegExp("\\\\", "g"), "");
plugin[tag] = tag != "getVersion" ? result.charAt(0).toUpperCase() + result.slice(1) : result;
}
}
}
let valid = true;
for (let tag of tags) {
if (!plugin[tag] || plugin[tag].length > 10000) valid = false;
}
if (valid) {
plugin.url = url;
this.loadedPlugins[url] = plugin;
var installedPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null;
if (installedPlugin && installedPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase() && installedPlugin.getVersion() != plugin.getVersion) {
if (PluginUpdates && PluginUpdates.plugins && !PluginUpdates.plugins[url]) outdated++;
}
}
else {
let name = body.replace(new RegExp("\\s*\:\\s*", "g"), ":").split('"name":"');
if (name.length > 1 && webview) {
name = name[1].split('"')[0];
webview.getWebContents().executeJavaScript(body).then(() => {
webview.getWebContents().executeJavaScript(`
var p = new ` + name + `();
var data = {
"getName":p.getName(),
"getAuthor":p.getAuthor(),
"getVersion":p.getVersion(),
"getDescription":p.getDescription()
};
Promise.resolve(data);`
).then((plugin) => {
plugin.url = url;
this.loadedPlugins[url] = plugin;
var installedPlugin = window.bdplugins[plugin.getName] ? window.bdplugins[plugin.getName].plugin : null;
if (installedPlugin && installedPlugin.getAuthor().toUpperCase() == plugin.getAuthor.toUpperCase() && installedPlugin.getVersion() != plugin.getVersion) outdated++;
});
});
}
}
}
i++;
getPluginInfo(webview, callback);
});
}
function createWebview () {
return new Promise(function(callback) {
var webview;
webview = document.createElement("webview");
webview.src = "https://discordapp.com/";
webview.setAttribute("webview-PluginRepo", null);
webview.style.setProperty("visibility", "hidden");
webview.addEventListener("dom-ready", () => {
callback(webview);
});
document.body.appendChild(webview);
});
}
}
checkForNewPlugins () {
let request = require("request");
request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/PluginRepo/res/PluginList.txt", (error, response, result) => {
if (response && !BDFDB.equals(result.split("\n"), this.grabbedPlugins)) this.loadPlugins();
});
}
downloadPlugin (entry) {
let request = require("request");
request(entry.url, (error, response, body) => {
if (error) {
BDFDB.showToast(`Unable to download Plugin "${plugin.getName}".`, {type:"danger"});
}
else {
let filename = entry.url.split("/");
this.createPluginFile(filename[filename.length - 1], body);
}
});
}
createPluginFile (filename, content) {
let fileSystem = require("fs");
let path = require("path");
var file = path.join(BDFDB.getPluginsFolder(), filename);
fileSystem.writeFile(file, content, (error) => {
if (error) {
BDFDB.showToast(`Unable to save Plugin "${filename}".`, {type:"danger"});
}
else {
BDFDB.showToast(`Successfully saved Plugin "${filename}".`, {type:"success"});
}
});
}
startPlugin (entry) {
var name = entry.name;
if (BDFDB.isPluginEnabled(name) == false) {
bdplugins[name].plugin.start();
pluginCookie[name] = true;
pluginModule.savePluginData();
console.log("PluginRepo: started Plugin " + name);
}
}
deletePluginFile (entry) {
let fileSystem = require("fs");
let path = require("path");
let filename = entry.url.split("/");
filename = filename[filename.length - 1];
var file = path.join(BDFDB.getPluginsFolder(), filename);
fileSystem.unlink(file, (error) => {
if (error) {
BDFDB.showToast(`Unable to delete Plugin "${filename}".`, {type:"danger"});
}
else {
BDFDB.showToast(`Successfully deleted Plugin "${filename}".`, {type:"success"});
}
});
}
stopPlugin (entry) {
var name = entry.name;
if (BDFDB.isPluginEnabled(name) == true) {
bdplugins[name].plugin.stop();
pluginCookie[name] = false;
delete bdplugins[name];
pluginModule.savePluginData();
console.log("PluginRepo: stopped Plugin " + name);
}
}
}

View File

@ -0,0 +1,3 @@
# Plugin Repo - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PluginRepo/PluginRepo.plugin.js)
Allows you to look at all plugins from the plugin repo and download them on the fly. Repo button is in the plugins settings.

View File

@ -0,0 +1,191 @@
https://gist.githubusercontent.com/Jiiks/7eb81b8950c073a09fbc2493da3ec714/raw/249f01f981a9a6a14bfbd170f28b8bf0e0a540d3/fullSizeLightbox.plugin.js
https://gist.githubusercontent.com/megamit/29757d819de5356595271cebb577f6a8/raw/dfaf0d0474e4545a2968eaad1838ac01c31494bd/DetachableYoutube.plugin.js
https://gist.githubusercontent.com/samogot/355ba0ff414a6a9551baff500b1af60e/raw/4251658b52b9591ea6bbd38e1a5309ffd101e266/count-unread.plugin.js
https://gist.githubusercontent.com/samogot/026e8894684cd76839c786910192aabd/raw/eb6848d53e8c203ef7ab3b7c624b6d0c5ff47374/return-scroll.plugin.js
https://gist.githubusercontent.com/shtrih/8a72a36d513ec704c7a9/raw/957d08fe0d802d8d74668f6374bb868f82f002ab/EmbedAV.plugin.js
https://gist.githubusercontent.com/shtrih/59a8be1f9ff53f0499c2/raw/c42c62ad3cf477714d1564d9c04f1f35c30081ac/CollapsibleEmbeds.plugin.js
https://raw.githubusercontent.com/Anxeal/BDEnhancements/master/plugins/HideImages/HideImages.plugin.js
https://raw.githubusercontent.com/Anxeal/BDEnhancements/master/plugins/ResizeX/ResizeX.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/doesNotEqualsInsertion.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/greenText.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/Miscellanious/backtickInsertion.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/Miscellanious/catImg.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/Miscellanious/jsMaterialThemeCodeblocks.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/Miscellanious/statusProfileContainer.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/ChatUserIDsRedux/ChatUserIDsRedux.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/HashTagsReborn/HashTagsReborn.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/HideServersChannelsRedux/HideServersChannelsRedux.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/HideUtils/HideUtils.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/KillXD/KillXD.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/LineNumbersRedux/LineNumbersRedux.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/MemberCount/MemberCount.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/messageTimestamps/messageTimestamps.plugin.js
https://raw.githubusercontent.com/Arashiryuu/crap/master/ToastIntegrated/TitleForTitlebar/TitleForTitlebar.plugin.js
https://raw.githubusercontent.com/ciaran/bd-switcher/master/switcher.plugin.js
https://raw.githubusercontent.com/cosmicsalad/Discord-Themes-and-Plugins/master/plugins/emoteSorter.plugin.js
https://raw.githubusercontent.com/cosmicsalad/Discord-Themes-and-Plugins/master/plugins/replyer.plugin.js
https://raw.githubusercontent.com/cosmicsalad/Discord-Themes-and-Plugins/master/plugins/sorter.plugin.js
https://raw.githubusercontent.com/Curtis-D/FullScreenSearch/master/FullScreenSearch.plugin.js
https://raw.githubusercontent.com/Curtis-D/PinnedMessagesPlugin/master/PinnedMessagesPage.plugin.js
https://raw.githubusercontent.com/Curtis-D/VIPs/master/VIPs.plugin.js
https://raw.githubusercontent.com/DeathStrikeV/EvenBetterDiscord/master/EvenBetterDiscord.plugin.js
https://raw.githubusercontent.com/Finicalmist/ChangingBackground/master/changingBackground.plugin.js
https://raw.githubusercontent.com/Finicalmist/CopyCode/master/copyCode.plugin.js
https://raw.githubusercontent.com/hammy1/BDStuff/master/Plugins/dateViewer/dateViewer.plugin.js
https://raw.githubusercontent.com/HoLLy-HaCKeR/BetterDiscord-Themes-and-Plugins/master/Plugins/lazyload_patcher.plugin.js
https://raw.githubusercontent.com/Hyperbot-one/hideServersChannels-plugin/master/hideServersChannels.plugin.js
https://raw.githubusercontent.com/Hyperbot-one/showEmojiServer-plugin/master/showEmojiServer.plugin.js
https://raw.githubusercontent.com/intrnl/discordextensions/master/NativeTitlebarPatcher/NativeTitlebarPatcher.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/autocompleteHoverFix.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/AvatarHover.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/botInfo.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/channelHistory.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/CharacterCounter.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/clearInputOnEsc.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/debugger.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/defaultToEmojis.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/directDownload.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/discordexperiments.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/enableReactDevtools.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/linkProfilePicture.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/localFileServer.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/minimizeShortcut.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/MultiInstance.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/QuickDeleteMessages.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/restartNoMore.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/scrollToLast.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/Snowfall.plugin.js
https://raw.githubusercontent.com/Inve1951/BetterDiscordStuff/master/plugins/toggleYourStuff.plugin.js
https://raw.githubusercontent.com/IRDeNial/BD-Server-Themes/master/serverTheme.plugin.js
https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/master/Plugins/clock.plugin.js
https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/master/Plugins/dblClickEdit.plugin.js
https://raw.githubusercontent.com/Jiiks/BetterDiscordApp/master/Plugins/mediaSupport.plugin.js
https://raw.githubusercontent.com/kosshishub/BetterCustomCSS-BD-plugin/master/BetterCustomCSS.plugin.js
https://raw.githubusercontent.com/kosshishub/CompactGuilds-BD-plugin/master/CompactGuilds.plugin.js
https://raw.githubusercontent.com/kosshishub/Quicksave-BD-plugin/master/Quicksave.plugin.js
https://raw.githubusercontent.com/leogx9r/DiscordCrypt/master/build/discordCrypt.plugin.js
https://raw.githubusercontent.com/mashirochan/Mashiro-chan/master/Plugins/AutoServerSelect/AutoServerSelect.plugin.js
https://raw.githubusercontent.com/mashirochan/Mashiro-chan/master/Plugins/CheckAllPluginsButton/CheckAllPluginsButton.plugin.js
https://raw.githubusercontent.com/mashirochan/Mashiro-chan/master/Plugins/EmoteBlacklistRedux/EmoteBlacklistRedux.plugin.js
https://raw.githubusercontent.com/mashirochan/Mashiro-chan/master/Plugins/HorizontalCodeScroll/HorizontalCodeScroll.plugin.js
https://raw.githubusercontent.com/mashirochan/Mashiro-chan/master/Plugins/PasteSend/PasteSend.plugin.js
https://raw.githubusercontent.com/Mega-Mewthree/BetterDiscordPlugins/master/Plugins/AlwaysMentionEveryone/AlwaysMentionEveryone.plugin.js
https://raw.githubusercontent.com/Mega-Mewthree/BetterDiscordPlugins/master/Plugins/AutoStartRichPresence/AutoStartRichPresence.plugin.js
https://raw.githubusercontent.com/Mega-Mewthree/BetterDiscordPlugins/master/Plugins/DiscordCakeDay/DiscordCakeDay.plugin.js
https://raw.githubusercontent.com/Mega-Mewthree/BetterDiscordPlugins/master/Plugins/RightClickRoleForID/RightClickRoleForID.plugin.js
https://raw.githubusercontent.com/megamit/repository/gh-pages/renamer/1.5.4/renamer.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/AvatarIconViewer.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/BetterEmoteSizes.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/CustomizableAvatarDPI.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/DiscordLogger.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/DoubleClickVoiceChannels.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/FormattableMessageCopier.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/GuildAndFriendRemovalAlerts.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/GuildCounter.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/IdleGuildlistScroller.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/MentionAliases.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/OpenLinksInDiscord.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/SaveTo.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/SelectedChannelNotifications.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/SendBDEmotes.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/ShareButton.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/TheClapBestClapPluginClapEver.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/TransitioningBackgrounds.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/UserBirthdays.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/VCMuteSounds.plugin.js
https://raw.githubusercontent.com/Metalloriff/BetterDiscordPlugins/master/ViewGuildRelationships.plugin.js
https://raw.githubusercontent.com/Modder4869/LazyStuff/master/LazyPlugins/CSSCode.plugin.js
https://raw.githubusercontent.com/Modder4869/LazyStuff/master/LazyPlugins/DeveloperUtils.plugin.js
https://raw.githubusercontent.com/Modder4869/LazyStuff/master/LazyPlugins/ThemePreview.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BadgesEverywhere/BadgesEverywhere.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterFriendCount/BetterFriendCount.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterNsfwTag/BetterNsfwTag.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/BetterSearchPage/BetterSearchPage.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CharCounter/CharCounter.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatAliases/ChatAliases.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ChatFilter/ChatFilter.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CompleteTimestamps/CompleteTimestamps.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/CreationDate/CreationDate.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/DisplayServersAsChannels/DisplayServersAsChannels.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditChannels/EditChannels.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditServers/EditServers.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EditUsers/EditUsers.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/EmojiStatistics/EmojiStatistics.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ForceImagePreviews/ForceImagePreviews.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/FriendNotifications/FriendNotifications.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleSearchReplace/GoogleSearchReplace.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/GoogleTranslateOption/GoogleTranslateOption.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ImageGallery/ImageGallery.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/MessageUtilities/MessageUtilities.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/MoveablePopups/MoveablePopups.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/NotificationSounds/NotificationSounds.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/OldTitleBar/OldTitleBar.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PersonalPins/PersonalPins.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PinDMs/PinDMs.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/PluginRepo/PluginRepo.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ReadAllNotificationsButton/ReadAllNotificationsButton.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/RemoveNicknames/RemoveNicknames.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/RepoControls/RepoControls.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ReverseImageSearch/ReverseImageSearch.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SendLargeMessages/SendLargeMessages.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ServerFolders/ServerFolders.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ServerHider/ServerHider.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ShowHiddenChannels/ShowHiddenChannels.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ShowImageDetails/ShowImageDetails.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SpellCheck/SpellCheck.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/StalkerNotifications/StalkerNotifications.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SteamProfileLink/SteamProfileLink.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ThemeRepo/ThemeRepo.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/TopRoleEverywhere/TopRoleEverywhere.plugin.js
https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/WriteUpperCase/WriteUpperCase.plugin.js
https://raw.githubusercontent.com/ngrst183/SuppressMentions/master/suppressmentions.plugin.js
https://raw.githubusercontent.com/nirewen/BotsMutualGuilds/master/BotsMutualGuilds.plugin.js
https://raw.githubusercontent.com/nirewen/Citador/master/Citador.plugin.js
https://raw.githubusercontent.com/nirewen/Quicksave/master/Quicksave.plugin.js
https://raw.githubusercontent.com/noodlebox/betterdiscord-plugins/master/KawaiiEmotes.plugin.js
https://raw.githubusercontent.com/noodlebox/betterdiscord-plugins/master/LineNumbers.plugin.js
https://raw.githubusercontent.com/noodlebox/betterdiscord-plugins/master/OwnerTag.plugin.js
https://raw.githubusercontent.com/noodlebox/betterdiscord-plugins/master/SilentTyping.plugin.js
https://raw.githubusercontent.com/noodlebox/betterdiscord-plugins/master/StaticAvatars.plugin.js
https://raw.githubusercontent.com/Orrielel/BetterDiscordAddons/master/Plugins/BetterImagePopups/BetterImagePopups.plugin.js
https://raw.githubusercontent.com/Orrielel/BetterDiscordAddons/master/Plugins/TwitchStreamPanel/TwitchStreamPanel.plugin.js
https://raw.githubusercontent.com/planetarian/BetterDiscordPlugins/master/Zalgo.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/AccountDetailsPlus/AccountDetailsPlus.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/AutoPlayGifs/AutoPlayGifs.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/BDContextMenu/BDContextMenu.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/BetterFormattingRedux/BetterFormattingRedux.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/BetterRoleColors/BetterRoleColors.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/BlurNSFW/BlurNSFW.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/DoNotTrack/DoNotTrack.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/EmojiUtilities/EmojiUtilities.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/HideDisabledEmojis/HideDisabledEmojis.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/HideIconBadge/HideIconBadge.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/ImageToClipboard/ImageToClipboard.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/PermissionsViewer/PermissionsViewer.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/ResizableCSS/ResizableCSS.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/RemoveMinimumSize/RemoveMinimumSize.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/ReplySystem/ReplySystem.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/RoleMembers/RoleMembers.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/SendButton/SendButton.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/ServerSearch/ServerSearch.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/ServerSorter/ServerSorter.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/StatusEverywhere/StatusEverywhere.plugin.js
https://raw.githubusercontent.com/rauenzi/BetterDiscordAddons/master/Plugins/TransparencyPatcher/TransparencyPatcher.plugin.js
https://raw.githubusercontent.com/samfun123/script-storage/master/betterdiscord/plugins/directMedia.plugin.js
https://raw.githubusercontent.com/samfun123/script-storage/master/betterdiscord/plugins/unshortenLinks.plugin.js
https://raw.githubusercontent.com/samogot/betterdiscord-plugins/master/v1/1lib_discord_internals.plugin.js
https://raw.githubusercontent.com/samogot/betterdiscord-plugins/master/v1/full_offline_list.plugin.js
https://raw.githubusercontent.com/samogot/betterdiscord-plugins/master/v1/no_send_scroll.plugin.js
https://raw.githubusercontent.com/samogot/betterdiscord-plugins/master/v1/quoter.plugin.js
https://raw.githubusercontent.com/satoru8/spoilerAlert/master/spoilerAlert.plugin.js
https://raw.githubusercontent.com/tony311/betterdiscord-plugins/master/afk-deafen.plugin.js
https://raw.githubusercontent.com/tony311/betterdiscord-plugins/master/auto-select-server.plugin.js
https://raw.githubusercontent.com/tony311/betterdiscord-plugins/master/tts-events.plugin.js
https://raw.githubusercontent.com/XFoxPrower/Notice-Me-Senpai/master/Notice%20Me%2C%20Senpai.plugin.js
https://raw.githubusercontent.com/XFoxPrower/Quick-Open-Link/master/Quick%20Open%20Link.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/BetterReplyer.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/GuildSeparators.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/LinkTooltips.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/SendEmbeds.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/ThemeCustomizer.plugin.js
https://raw.githubusercontent.com/Zerthox/BetterDiscord-Plugins/master/plugins/ToggleAll.plugin.js

View File

@ -0,0 +1,44 @@
## Plugins
- [BadgesEverywhere](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BadgesEverywhere) - Displays Badges (Nitro, Hypesquad, etc...) in the chat/memberlist/userpopout. Thanks for Zerebos' help.
- [Better Friend Count](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BetterFriendCount) - Shows the amount of total and online friends and blocked users in the friends tab.
- [Better NSFW Tag](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BetterNsfwTag) - Adds a more noticeable tag to NSFW channels.
- [Better Search Page](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/BetterSearchPage) - Adds some extra controls to the search results page.
- [Char Counter](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/CharCounter) - Adds a character counter to the chat.
- [Chat Aliases](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ChatAliases) - Allows the user to configure their own chat-aliases which will automatically be replaced before the message is being sent.
- [Chat Filter](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ChatFilter) - Allows the user to censor words or block complete messages based on words in the chatwindow.
- [Complete Timestamps](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/CompleteTimestamps) - Replace all timestamps with complete timestamps.
- [Creation Date](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/CreationDate) - Displays the Creation Date of an Account in the UserPopout and UserModal.
- [Display Servers As Channels](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/DisplayServersAsChannels) - Display servers in a similar way as channels.
- [Edit Channels](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/EditChannels) - Allows the user to locally change the name and color of channels.
- [Edit Servers](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/EditServers) - Allows the user to locally change the name, initials, icon and color of servers.
- [Edit Users](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/EditUsers) - Allows you to change the icon, name, tag and color of users.
- [Emoji Statistics](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/EmojiStatistics) - Displays emojiinformation when hovering over an emoji in the emojipicker and adds a button to the emojipicker to open a statistics overview.
- [Fix German Translation](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/FixGermanTranslation) - Fixes some minor translation errors in the german version of Discord.
- [Fix Twitch Emotes](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/FixTwitchEmotes) - Fixes the problem with twitch emotes not being properly inserted in the textarea.
- [Force Image Previews](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ForceImagePreviews) - Forces embedded Image Previews, if Discord doesn't do it itself.
- [Friend Notifications](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/FriendNotifications) - Notifies you when a friend either logs in or out. Click the Online Friend-Counter to display a timelog of the current session.
- [Google Search Replace](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/GoogleSearchReplace) - Replaces the default Google Text Search with a selection menu of several search engines.
- [Google Translate Option](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/GoogleTranslateOption) - Adds a Google Translate option to your context menu, which will open the selected text in Google Translate.
- [Image Gallery](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ImageGallery) - Allows the user to browse through images sent inside the same message.
- [Message Utilities](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/MessageUtilities) - Offers a number of useful message options.
- [Moveable Popups](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/MoveablePopups) - Adds the feature to move all popups and modals around like on a normal desktop. Ctrl + drag with your left mousebutton to drag element.
- [Notification Sounds](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/NotificationSounds) - Allows you to replace the native sounds of Discord with your own.
- [Old Title Bar](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/OldTitleBar) - Reverts the title bar back to its former self.
- [Personal Pins](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/PersonalPins) - Similar to normal pins. Lets you save messages as notes for yourself.
- [Pin DMs](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/PinDMs) - Allows you to pin DMs, making them appear at the top of your DM-list.
- [Plugin Repo](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/PluginRepo) - Allows you to look at all plugins from the plugin repo and download them on the fly.
- [Read All Notifications Button](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ReadAllNotificationsButton) - Adds a little button at the top of your serverlist that enables you to clear all mentions and messagesnotifications at once.
- [Remove Nicknames](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/RemoveNicknames) - Replace all nicknames with the actual accountnames.
- [Repo Controls](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/RepoControls) - Lets you sort and filter your list of downloaded Themes and Plugins.
- [Reverse Image Search](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ReverseImageSearch) - Adds the option to reverse image search images in discord via several engines.
- [Send Large Messages](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SendLargeMessages) - Opens a popout when your message is too large, which allows you to automatically send the message in several smaller messages.
- [Server Hider](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ServerHider) - Adds two options on your server context menu to hide servers in your server list.
- [Server Folders](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ServerFolders) - Adds the option to create pseudo folders that, click the folder to hide/display all folders between two folders. Easily gets broken by moving server icons.
- [Show Hidden Channels](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ShowHiddenChannels) - Displays all hidden channels that can't be accessed due to role restrictions in a new category.
- [Show Image Details](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ShowImageDetails) - Display the name, size and dimensions of uploaded images (does not include embed images) in the chat as an header or as a tooltip.
- [Spell Check](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SpellCheck) - Adds a spellcheck to all textareas.
- [Stalker Notifications](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/StalkerNotifications) - Lets you observe the status of people that aren't your friends.
- [Steam Profile Link](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SteamProfileLink) - Opens a steam profile in steam instead of a browser when clicking the steamlink in a userprofile. With the help of square.
- [Theme Repo](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/ThemeRepo) - Allows you to preview all themes from the theme repo and download them on the fly.
- [Top Role Everywhere](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/TopRoleEverywhere) - Adds the highest role of a user as a tag.
- [Write UpperCase](https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/WriteUpperCase) - Changes the input in the textarea to uppercase.

View File

@ -0,0 +1,3 @@
# Read All Notifications Button - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ReadAllNotificationsButton/ReadAllNotificationsButton.plugin.js)
Adds a little button at the top of your serverlist that enables you to clear all mentions and messagesnotifications at once.

View File

@ -0,0 +1,144 @@
//META{"name":"ReadAllNotificationsButton"}*//
class ReadAllNotificationsButton {
initConstructor () {
this.RANbuttonMarkup =
`<div class="${BDFDB.disCN.guild}" id="RANbutton-frame" style="height: 20px; margin-bottom: 10px;">
<div class="${BDFDB.disCN.guildinner}" style="height: 20px; border-radius: 4px;">
<a>
<div id="RANbutton" style="line-height: 20px; font-size: 12px;">read all</div>
</a>
</div>
</div>`;
this.RAMbuttonMarkup =
`<button type="button" id="RAMbutton" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemin + BDFDB.disCN.buttongrow}" style="flex: 0 0 auto; margin-top: -5px; height: 25px;">
<div class="${BDFDB.disCN.buttoncontents}">Clear all Mentions</div>
</button>`;
this.defaults = {
settings: {
includeMuted: {value:false, description:"Include muted Servers (means more API-Requests):"}
}
};
}
getName () {return "ReadAllNotificationsButton";}
getDescription () {return "Adds a button to clear all notifications.";}
getVersion () {return "1.3.5";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
var mentionspopout = null;
if (node && node.tagName && (mentionspopout = node.querySelector(BDFDB.dotCN.recentmentionspopout)) != null) {
let filter = node.querySelector(BDFDB.dotCN.recentmentionsmentionfilter);
if (filter) {
$(this.RAMbuttonMarkup).insertBefore(filter, mentionspopout)
.on("click", () => {
var loadinterval = setInterval(() => {
if (!mentionspopout || !mentionspopout.parentElement) clearInterval(loadinterval);
var loadbutton = mentionspopout.querySelector(BDFDB.dotCNS.messagespopouthasmore + "button");
var closebuttons = mentionspopout.querySelectorAll(BDFDB.dotCN.messagespopoutclosebutton);
if (!loadbutton) {
closebuttons.forEach((btn) => {btn.click();});
clearInterval(loadinterval);
}
else {
closebuttons.forEach((btn,i) => {if (closebuttons.length-1 > i) btn.click();});
loadbutton.click();
}
},2000);
});
mentionspopout.classList.add("RAM-added");
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.popouts, {name:"mentionsPopoutObserver",instance:observer}, {childList: true});
$(this.RANbuttonMarkup).insertBefore(document.querySelector(BDFDB.dotCN.guildseparator))
.on("click", "#RANbutton", () => {
let servers = BDFDB.getData("includeMuted", this, "settings") ? BDFDB.readServerList() : BDFDB.readUnreadServerList();
BDFDB.clearReadNotifications(servers);
});
$(BDFDB.dotCN.guilds).addClass("RAN-added");
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$("#RANbutton-frame, #RAMbutton").remove();
$(".RAN-added").removeClass("RAN-added");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
}

View File

@ -0,0 +1,3 @@
# Remove Nicknames - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/RemoveNicknames/RemoveNicknames.plugin.js)
Replace all nicknames with the actual accountnames.

View File

@ -0,0 +1,246 @@
//META{"name":"RemoveNicknames"}*//
class RemoveNicknames {
initConstructor () {
this.defaults = {
settings: {
replaceOwn: {value:false, description:"Replace your own name:"},
addNickname: {value:false, description:"Add nickname as parentheses:"},
swapPositions: {value:false, description:"Swap the position of username and nickname:"}
}
};
}
getName () {return "RemoveNicknames";}
getDescription () {return "Replace all nicknames with the actual accountnames.";}
getVersion () {return "1.1.1";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UserStore = BDFDB.WebModules.findByProperties(["getUsers", "getUser"]);
this.MemberPerms = BDFDB.WebModules.findByProperties(["getNicknames", "getNick"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.voiceuserdefault)) {
this.loadUser(node.querySelector(BDFDB.dotCN.voiceuserdefault).parentElement, "voice", false);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.channels, {name:"channelListObserver",instance:observer}, {childList: true, subtree: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.memberusername)) {
this.loadUser(node, "list", false);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.members, {name:"userListObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.messageusername)) {
this.loadUser(node, "chat", BDFDB.getDiscordTheme() == "compact");
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
this.resetAllUsers();
this.loadAllUsers();
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
this.loadAllUsers();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
this.resetAllUsers();
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
BDFDB.addObserver(this, BDFDB.dotCN.members, {name:"userListObserver"}, {childList:true});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
setImmediate(() => {this.loadAllUsers();});
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
loadAllUsers () {
for (let user of document.querySelectorAll(BDFDB.dotCN.member)) {
this.loadUser(user, "list", false);
}
for (let messagegroup of document.querySelectorAll(BDFDB.dotCN.messagegroupcozy)) {
this.loadUser(messagegroup, "chat", false);
}
for (let messagegroup of document.querySelectorAll(BDFDB.dotCN.messagegroupcompact)) {
for (let message of messagegroup.querySelectorAll(BDFDB.dotCN.messagemarkup)) {
this.loadUser(message, "chat", true);
}
}
for (let user of document.querySelectorAll(BDFDB.dotCN.voiceuserdefault)) {
this.loadUser(user.parentElement, "voice", false);
}
}
loadUser (div, type, compact) {
if (!div || $(div).attr("removed-nickname") || !div.tagName) return;
let usernameWrapper = this.getNameWrapper(div);
if (!usernameWrapper) return;
$(div).data("compact", compact);
var info = this.getUserInfo(compact ? $(BDFDB.dotCN.messagegroup).has(div)[0] : div);
if (!info) return;
var settings = BDFDB.getAllData(this, "settings");
if (info.id == BDFDB.myData.id && !settings.replaceOwn) return;
var serverObj = BDFDB.getSelectedServer();
if (!serverObj) return;
var member = this.MemberPerms.getMember(serverObj.id, info.id);
if (!member || !member.nick) return;
var newname = settings.addNickname ? (settings.swapPositions ? (member.nick + " (" + info.username + ")") : (info.username + " (" + member.nick + ")")) : info.username;
BDFDB.setInnerText(usernameWrapper, newname);
div.setAttribute("removed-nickname", true);
}
resetAllUsers () {
document.querySelectorAll("[removed-nickname]").forEach((div) => {
let usernameWrapper = this.getNameWrapper(div);
if (!usernameWrapper) return;
var info = this.getUserInfo($(div).data("compact") ? $(BDFDB.dotCN.messagegroup).has(div)[0] : div);
if (!info) return;
var serverObj = BDFDB.getSelectedServer();
if (!serverObj) return;
var member = this.MemberPerms.getMember(serverObj.id, info.id);
if (!member || !member.nick) return;
BDFDB.setInnerText(usernameWrapper, member.nick);
div.removeAttribute("removed-nickname");
});
}
getNameWrapper (div) {
return div.querySelector(BDFDB.dotCNC.memberusername + BDFDB.dotCNC.voicenamedefault + BDFDB.dotCN.messageusername);
}
getUserInfo (div) {
var info = BDFDB.getKeyInformation({"node":div,"key":"user"});
if (!info) {
info = BDFDB.getKeyInformation({"node":div,"key":"message"});
if (info) info = info.author;
else {
info = BDFDB.getKeyInformation({"node":div,"key":"channel"});
if (info) info = {"id":info.recipients[0]};
else {
info = BDFDB.getKeyInformation({"node":$(BDFDB.dotCN.messagegroup).has(div)[0],"key":"message"});
if (info) info = info.author;
}
}
}
return info && info.id ? this.UserStore.getUser(info.id) : null;
}
}

View File

@ -0,0 +1,3 @@
# Repo Controls - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/RepoControls/RepoControls.plugin.js)
Lets you sort and filter your list of downloaded Themes and Plugins.

View File

@ -0,0 +1,492 @@
//META{"name":"RepoControls"}*//
class RepoControls {
initConstructor () {
this.sortings = {
sort: {
name: "Name",
author: "Author",
version: "Version",
description: "Description",
enabled: "Enabled",
adddate: "Added",
moddate: "Modified"
},
order: {
asc: "Ascending",
desc: "Descending"
}
};
this.repoControlsMarkup =
`<div class="repo-controls ${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.searchbar + BDFDB.disCN.size14}" style="flex: 1 1 auto;">
<input class="${BDFDB.disCNS.searchbarinput + BDFDB.disCN.flexchild}" value="" placeholder="Search for ..." style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.searchbariconwrap + BDFDB.disCN.flexchild}">
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCNS.searchbareyeglass + BDFDB.disCN.searchbarvisible}"/>
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCN.searchbarclear}"/>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.nowrap}" style="flex: 0 1 auto;">
<button action="add" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorgreen + BDFDB.disCNS.buttonsizeicon + BDFDB.disCN.buttongrow} btn-enableall" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.buttoncontents}">Enable All</div>
</button>
<button action="add" type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizeicon + BDFDB.disCN.buttongrow} btn-disableall" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.buttoncontents}">Disable All</div>
</button>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="flex: 0 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCN.quickselectlabel} style="flex: 0 0 auto;"">Sort by:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} sort-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.sort)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="flex: 0 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCN.quickselectlabel} style="flex: 0 0 auto;"">Order:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} order-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.order)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.order[Object.keys(this.sortings.order)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
</div>`;
this.sortPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} repocontrols-sort-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);" option="sort">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.sort).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.sort[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.orderPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} repocontrols-order-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);" option="order">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.order).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.order[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.deleteButtonMarkup =
`<svg class="trashIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px">
<g fill="white">
<path d="M 18.012, 0.648 H 12.98 C 12.944, 0.284, 12.637, 0, 12.264, 0 H 8.136 c -0.373, 0 -0.68, 0.284 -0.716, 0.648 H 2.389 c -0.398, 0 -0.72, 0.322 -0.72, 0.72 v 1.368 c 0, 0.398, 0.322, 0.72, 0.72, 0.72 h 15.623 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 1.368 C 18.731, 0.97, 18.409, 0.648, 18.012, 0.648 z"/><path d="M 3.178, 4.839 v 14.841 c 0, 0.397, 0.322, 0.72, 0.72, 0.72 h 12.604 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 4.839 H 3.178 z M 8.449, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 c -0.438, 0 -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z M 13.538, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 s -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z"/>
</g>
</svg>`;
this.css = `
#bd-settingspane-container .bda-description {
display: block;
}
#bd-settingspane-container .bda-right .ui-switch-wrapper {
right: 0;
}
#bd-settingspane-container .bda-right button {
position: absolute;
right: 0;
top: 30px;
}
#bd-settingspane-container .bda-right,
#bd-settingspane-container .bda-header {
position: relative;
}
#bd-settingspane-container .trashIcon {
display: none;
}
#bd-settingspane-container .bda-right .trashIcon,
#bd-settingspane-container .bda-header .trashIcon {
cursor: pointer;
display: block;
position: absolute;
right: 50px;
}
#bd-settingspane-container .bda-right .trashIcon {
top: 7px;
}`;
this.defaults = {
settings: {
addDeleteButton: {value:true, description:"Add a Delete Button to your Plugin and Theme List."},
confirmDelete: {value:true, description:"Ask for your confirmation before deleting a File."}
},
sortings: {
sort: {value:"name"},
order: {value:"asc"}
}
};
}
getName () {return "RepoControls";}
getDescription () {return "Lets you sort and filter your list of downloaded Themes and Plugins.";}
getVersion () {return "1.1.9";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, j) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (this.getSettingsPageType(node)) {
this.addControls(node.querySelector(".bda-slist"));
if (node && node.tagName && node.querySelector(".ui-switch")) {
var entry = this.getEntry($(".repo-controls"), $("li").has(node)[0]);
if (entry) {
if (BDFDB.getData("addDeleteButton", this, "settings")) this.addDeleteButton(entry);
this.changeTextToHTML(entry.div);
}
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layer + "[layer-id='user-settings']", {name:"innerSettingsWindowObserver",instance:observer}, {childList:true,subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
setImmediate(() => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
BDFDB.addObserver(this, node, {name:"innerSettingsWindowObserver"}, {childList:true,subtree:true});
if (this.getSettingsPageType(node)) this.addControls(node.querySelector(".bda-slist"));
}
});
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
var settingswindow = document.querySelector(BDFDB.dotCN.layer + "[layer-id='user-settings']");
if (settingswindow && this.getSettingsPageType(settingswindow)) this.addControls(settingswindow.querySelector(".bda-slist"));
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(".repo-controls, #bd-settingspane-container .trashIcon").remove();
$(".repocontrols-added").removeClass(".repocontrols-added");
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
getSettingsPageType (container) {
if (typeof container === "undefined") container = document.querySelector(BDFDB.dotCN.layer + "[layer-id='user-settings']");
if (container && container.tagName) {
var folderbutton = container.querySelector(".bd-pfbtn");
if (folderbutton) {
var buttonbar = folderbutton.parentElement;
if (buttonbar && buttonbar.tagName) {
var header = buttonbar.querySelector("h2");
if (header) {
var headerText = header.innerText.toUpperCase();
if (headerText === "PLUGINS" || headerText === "THEMES") {
return headerText[0] + headerText.slice(1).toLowerCase();
}
}
}
}
}
return null;
}
addControls (container) {
if (!container || document.querySelector(".repo-controls")) return;
var sortings = BDFDB.getAllData(this, "sortings");
var repoControls = $(this.repoControlsMarkup);
repoControls.Plugins = {};
repoControls.Themes = {};
var fs = require("fs"), folder = BDFDB.getPluginsFolder(), ending = ".plugin.js";
for (var plugin of fs.readdirSync(folder)) {
if (plugin.indexOf(ending) == plugin.length - ending.length) {
let path = folder + "/" + plugin;
let body = fs.readFileSync(path).toString();
let result = new RegExp("getName[\\s|\\t|\\n|\\r|=|>|_|:|function|\(|\)|\{|return]*([\"|\'|\`]).*\\1","gi").exec(body);
if (result) {
repoControls.Plugins[result[0].split(result[1])[1]] = {path, stats: fs.statSync(path)};
}
}
}
folder = BDFDB.getThemesFolder(), ending = ".theme.css";
for (var theme of fs.readdirSync(folder)) {
if (theme.indexOf(ending) == theme.length - ending.length) {
let path = folder + "/" + theme;
let body = fs.readFileSync(path).toString();
if (body.split("*//").length > 1 && body.split("\n").length > 1) {
let result = body.replace(new RegExp("\\s*\:\\s*", "g"), ":").replace(new RegExp("\\s*\}\\s*", "g"), "}").split('"name":"');
result = result.length > 1 ? result[1].split('",')[0].split('"}')[0] : null;
if (result) {
repoControls.Themes[result] = {path, stats: fs.statSync(path)};;
}
}
}
}
BDFDB.initElements(repoControls);
repoControls.find(".sort-filter " + BDFDB.dotCN.quickselectvalue).attr("option", sortings.sort).text(this.sortings.sort[sortings.sort]);
repoControls.find(".order-filter " + BDFDB.dotCN.quickselectvalue).attr("option", sortings.order).text(this.sortings.order[sortings.order]);
repoControls
.on("keyup." + this.getName(), BDFDB.dotCN.searchbarinput, () => {
clearTimeout(repoControls.searchTimeout);
repoControls.searchTimeout = setTimeout(() => {this.addEntries(container, repoControls);},1000);
})
.on("click." + this.getName(), BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => {
this.addEntries(container, repoControls);
})
.on("click." + this.getName(), ".btn-enableall", (e) => {
this.toggleAll(container, true);
})
.on("click." + this.getName(), ".btn-disableall", (e) => {
this.toggleAll(container, false);
})
.on("click." + this.getName(), ".sort-filter", (e) => {
this.openSortPopout(e, this.sortPopoutMarkup, container, repoControls);
})
.on("click." + this.getName(), ".order-filter", (e) => {
this.openSortPopout(e, this.orderPopoutMarkup, container, repoControls);
})
.insertBefore(container);
$(container).addClass("repocontrols-added").on("click." + this.getName(), "div[style='float: right; cursor: pointer;']", (e) => {
setImmediate(() => {
var entry = this.getEntry(repoControls, $("li").has(e.currentTarget)[0]);
if (entry) {
if (BDFDB.getData("addDeleteButton", this, "settings")) this.addDeleteButton(entry);
this.changeTextToHTML(entry.div);
}
});
});
container.entries = [];
for (let li of container.querySelectorAll("li")) {
container.entries.push(this.getEntry(repoControls, li));
}
this.addEntries(container, repoControls);
}
getEntry (repoControls, li) {
if (!repoControls || !li || !li.tagName || !li.querySelector(".bda-name")) return null;
let name, version, author, description, enabled;
if (BDFDB.zacksFork()) {
name = li.querySelector(".bda-name").textContent;
version = li.querySelector(".bda-version").textContent;
author = li.querySelector(".bda-author").textContent;
description = li.querySelector(".bda-description").textContent;
enabled = li.querySelector(".ui-switch-checkbox").checked;
}
else {
let namestring = li.querySelector(".bda-name").textContent;
name = namestring.split(" v")[0];
version = namestring.split(" v")[1].split(" by ")[0];
author = namestring.split(" by ")[1];
description = li.querySelector(".bda-description").textContent;
enabled = li.querySelector(".ui-switch-checkbox").checked;
}
let type = this.getSettingsPageType();
let pathstatscache = type ? repoControls[type][name] : null;
return {
div: li,
search: (name + " " + version + " " + author + " " + description).toUpperCase(),
origName: name,
name: (name).toUpperCase(),
version: (version).toUpperCase(),
author: (author).toUpperCase(),
description: (description).toUpperCase(),
type: type,
path: pathstatscache ? pathstatscache.path : null,
adddate: pathstatscache ? pathstatscache.stats.atime.getTime() : null,
moddate: pathstatscache ? pathstatscache.stats.mtime.getTime() : null,
enabled: enabled ? 0 : 1
};
}
addEntries (container, repoControls) {
$(container).find(".trashIcon, li").remove();
var searchstring = repoControls.find(BDFDB.dotCN.searchbarinput).val().replace(/[<|>]/g, "").toUpperCase();
var entries = container.entries;
var sortings = BDFDB.getAllData(this, "sortings");
entries = entries.filter((entry) => {return entry.search.indexOf(searchstring) > -1 ? entry : null;});
BDFDB.sortArrayByKey(entries, sortings.sort);
if (sortings.order == "desc") entries.reverse();
var settings = BDFDB.getAllData(this, "settings");
for (let entry of entries) {
container.appendChild(entry.div);
if (settings.addDeleteButton) this.addDeleteButton(entry);
this.changeTextToHTML(entry.div, searchstring);
$(entry.div).find(".ui-switch-checkbox")
.off("change." + this.getName())
.on("change." + this.getName(), (e) => {
entry.enabled = e.checked ? 0 : 1
});
}
}
addDeleteButton (entry) {
if (!entry || !entry.div || !entry.div.tagName || entry.div.querySelector(".trashIcon")) return;
$(this.deleteButtonMarkup)
.on("click." + this.getName(), () => {
var container = document.querySelector(".bda-slist");
let type = entry.type ? entry.type.slice(0, -1) : "File";
if (container && (!BDFDB.getData("confirmDelete", this, "settings") || confirm(`Are you sure you want to delete this ${type}?`))) {
require("fs").unlink(entry.path, (error) => {
if (error) {
BDFDB.showToast(`Unable to delete ${type} "${entry.origName}". Filename might not be the same as ${type}name.`, {type:"danger"});
}
else {
BDFDB.showToast(`Successfully deleted ${type} "${entry.origName}".`, {type:"success"});
BDFDB.removeFromArray(container.entries, entry);
entry.div.remove();
}
});
}
})
.on("mouseenter." + this.getName(), (e) => {
BDFDB.createTooltip("Delete File", e.currentTarget, {type:"top",selector:"repocontrols-trashicon-tooltip"});
})
.insertAfter(entry.div.querySelector(".ui-switch-wrapper"));
}
toggleAll (container, enable) {
if (confirm(`Are you sure you want to ${enable ? "enable" : "disable"} everything?`)) {
for (let header of container.querySelectorAll(".bda-header")) {
if (header.querySelector(".bda-name").textContent.toLowerCase().indexOf(this.getName().toLowerCase()) != 0) {
let switchwrap = header.querySelector(".ui-switch-wrapper");
if (switchwrap) {
let switchinner = switchwrap.querySelector(".ui-switch");
let switchinput = switchwrap.querySelector(".ui-switch-checkbox");
if (switchinner && switchinput) {
if (switchinner.classList.contains("checked") && !enable) {
switchinput.click();
}
else if (!switchinner.classList.contains("checked") && enable) {
switchinput.click();
}
}
}
}
}
}
}
changeTextToHTML (container, searchstring) {
if (!container || !container.tagName) return;
if (typeof searchstring === "undefined") {
var searchinput = document.querySelector(".repo-controls " + BDFDB.dotCN.searchbarinput);
searchstring = searchinput ? searchinput.value : "";
}
container.querySelectorAll(".bda-name, .bda-version, .bda-author, .bda-description").forEach(ele => {
if (ele.classList.contains("bda-description")) ele.style.display = "block";
ele.innerHTML = BDFDB.highlightText(ele.innerText, searchstring);
});
}
openSortPopout (e, markup, container, repoControls) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains("popout-open")) return;
wrapper.classList.add("popout-open");
var value = $(wrapper).find(BDFDB.dotCN.quickselectvalue);
var popout = $(markup);
$(BDFDB.dotCN.popouts).append(popout)
.off("click", BDFDB.dotCN.contextmenuitem)
.on("click", BDFDB.dotCN.contextmenuitem, (e2) => {
var option = $(e2.currentTarget).attr("option");
value.text($(e2.currentTarget).text());
value.attr("option", option);
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
BDFDB.saveData(popout.attr("option"), option, this, "sortings");
this.addEntries(container, repoControls);
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
});
popout
.css("left", $(wrapper).offset().left + $(wrapper).outerWidth() + "px")
.css("top", $(wrapper).offset().top + value.outerHeight() + "px")
.find(BDFDB.dotCN.contextmenu).addClass(BDFDB.getDiscordTheme());
$(document).on("mousedown.sortpopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0) {
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
}
});
}
}

View File

@ -0,0 +1,7 @@
# Reverse Image Search - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ReverseImageSearch/ReverseImageSearch.plugin.js)
Adds the option to right click an image and use an engine to reverse image search it.
Enable/Disable them in the settings.
Current engines: Baidu, Bing, Google, Karma Decay (Reddit), Sogou, TinEye, Yandex
If you want to add new search engines, simply add a new entry in the searchEngines array in the constructor. Make sure to get the right search url for the engine.

View File

@ -0,0 +1,279 @@
//META{"name":"ReverseImageSearch"}*//
class ReverseImageSearch {
initConstructor () {
this.imgUrlReplaceString = "DEVILBRO_BD_REVERSEIMAGESEARCH_REPLACE_IMAGEURL";
this.defaults = {
engines: {
_all: {value:true, name:BDFDB.getLibraryStrings().btn_all_text, url:null},
Baidu: {value:true, name:"Baidu", url:"http://image.baidu.com/pcdutu?queryImageUrl=" + this.imgUrlReplaceString},
Bing: {value:true, name:"Bing", url:"https://www.bing.com/images/search?q=imgurl:" + this.imgUrlReplaceString + "&view=detailv2&iss=sbi&FORM=IRSBIQ"},
Google: {value:true, name:"Google", url:"https://images.google.com/searchbyimage?image_url=" + this.imgUrlReplaceString},
IQDB: {value:true, name:"IQDB", url:"https://iqdb.org/?url=" + this.imgUrlReplaceString},
Reddit: {value:true, name:"Reddit", url:"http://karmadecay.com/search?q=" + this.imgUrlReplaceString},
SauceNAO: {value:true, name:"SauceNAO", url:"https://saucenao.com/search.php?db=999&url=" + this.imgUrlReplaceString},
Sogou: {value:true, name:"Sogou", url:"http://pic.sogou.com/ris?flag=1&drag=0&query=" + this.imgUrlReplaceString + "&flag=1"},
TinEye: {value:true, name:"TinEye", url:"https://tineye.com/search?url=" + this.imgUrlReplaceString},
WhatAnime: {value:true, name:"WhatAnime", url:"https://whatanime.ga/?url=" + this.imgUrlReplaceString},
Yandex: {value:true, name:"Yandex", url:"https://yandex.com/images/search?url=" + this.imgUrlReplaceString + "&rpt=imageview"}
}
};
this.messageContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} reverseimagesearch-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>Reverse Image Search</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.messageContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} reverseImageSearchSubMenu">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} alldisabled-item ${BDFDB.disCN.contextmenuitemdisabled}">
<span>REPLACE_submenu_disabled_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
${Object.keys(this.defaults.engines).map((key, i) => `<div engine="${key}" class="${BDFDB.disCN.contextmenuitem} RIS-item"><span>${this.defaults.engines[key].name}</span><div class="${BDFDB.disCN.contextmenuhint}"></div></div>`).join("")}
</div>
</div>`;
}
getName () {return "ReverseImageSearch";}
getDescription () {return "Adds a reverse image search option to the context menu.";}
getVersion () {return "3.3.7";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var engines = BDFDB.getAllData(this, "engines");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Search Engines:</h3></div><div class="DevilBro-settings-inner-list">`;
for (let key in engines) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.engines[key].name}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${engines[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"messageContextObserver",instance:observer}, {childList: true});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
// begin of own functions
changeLanguageStrings () {
this.messageContextSubMenuMarkup = this.messageContextSubMenuMarkup.replace("REPLACE_submenu_disabled_text", this.labels.submenu_disabled_text);
}
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "engines");
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".reverseimagesearch-item")) return;
var url = BDFDB.getKeyInformation({"node":context, "key":"src"});
if (url) {
if (url.indexOf("discordapp.com/assets/") == -1) {
if (url.indexOf("https://images-ext-1.discordapp.net/external/") > -1) {
if (url.split("/https/").length != 1) {
url = "https://" + url.split("/https/")[url.split("/https/").length-1];
}
else if (url.split("/http/").length != 1) {
url = "http://" + url.split("/http/")[url.split("/http/").length-1];
}
}
$(context).append(this.messageContextEntryMarkup)
.on("mouseenter", ".reverseimagesearch-item", (e) => {
this.createContextSubMenu(url, e, context);
});
BDFDB.updateContextPosition(context);
}
}
}
createContextSubMenu (imageurl, e, context) {
var messageContextSubMenu = $(this.messageContextSubMenuMarkup);
messageContextSubMenu
.on("click", ".RIS-item", (e2) => {
$(context).hide();
var engine = e2.currentTarget.getAttribute("engine");
if (engine == "_all") {
var engines = BDFDB.getAllData(this, "engines");
for (let key in engines) {
if (key != "_all" && engines[key]) window.open(this.defaults.engines[key].url.replace(this.imgUrlReplaceString, encodeURIComponent(text)), "_blank");
}
}
else {
window.open(this.defaults.engines[engine].url.replace(this.imgUrlReplaceString, encodeURIComponent(imageurl)), "_blank");
}
});
var engines = BDFDB.getAllData(this, "engines");
for (let key in engines) {
if (!engines[key]) messageContextSubMenu.find("[engine='" + key + "']").remove();
}
if (messageContextSubMenu.find(".RIS-item").length > 0) {
messageContextSubMenu.find(".alldisabled-item").remove();
}
BDFDB.appendSubMenu(e.currentTarget, messageContextSubMenu);
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
submenu_disabled_text: "Svi su onemogućeni"
};
case "da": //danish
return {
submenu_disabled_text: "Alle deaktiveret"
};
case "de": //german
return {
submenu_disabled_text: "Alle deaktiviert"
};
case "es": //spanish
return {
submenu_disabled_text: "Todo desactivado"
};
case "fr": //french
return {
submenu_disabled_text: "Tous désactivés"
};
case "it": //italian
return {
submenu_disabled_text: "Tutto disattivato"
};
case "nl": //dutch
return {
submenu_disabled_text: "Alles gedeactiveerd"
};
case "no": //norwegian
return {
submenu_disabled_text: "Alle deaktivert"
};
case "pl": //polish
return {
submenu_disabled_text: "Wszystkie wyłączone"
};
case "pt-BR": //portuguese (brazil)
return {
submenu_disabled_text: "Todos desativados"
};
case "fi": //finnish
return {
submenu_disabled_text: "Kaikki on poistettu käytöstä"
};
case "sv": //swedish
return {
submenu_disabled_text: "Alla avaktiverade"
};
case "tr": //turkish
return {
submenu_disabled_text: "Hepsi deaktive"
};
case "cs": //czech
return {
submenu_disabled_text: "Všechny deaktivované"
};
case "bg": //bulgarian
return {
submenu_disabled_text: "Всички са деактивирани"
};
case "ru": //russian
return {
submenu_disabled_text: "Все деактивированные"
};
case "uk": //ukrainian
return {
submenu_disabled_text: "Всі вимкнені"
};
case "ja": //japanese
return {
submenu_disabled_text: "すべて非アクティブ化"
};
case "zh-TW": //chinese (traditional)
return {
submenu_disabled_text: "全部停用"
};
case "ko": //korean
return {
submenu_disabled_text: "모두 비활성화 됨"
};
default: //default: english
return {
submenu_disabled_text: "All disabled"
};
}
}
}

View File

@ -0,0 +1,3 @@
# Send Large Messages - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SendLargeMessages/SendLargeMessages.plugin.js)
Opens a popout when your message is too large, which allows you to automatically send the message in several smaller messages.

View File

@ -0,0 +1,447 @@
//META{"name":"SendLargeMessages"}*//
class SendLargeMessages {
initConstructor () {
this.labels = {};
this.messageDelay = 1000; //changing at own risk, might result in bans or mutes
this.css = `
.sendlargemessages-modal textarea {
rows: 0;
cols: 0;
height: 100vw;
resize: none;
}
.sendlargemessages-modal #warning-message {
font-weight: bold;
color: red;
opacity: 1;
}
.sendlargemessages-modal #character-counter {
float: right;
color: white;
opacity: .5;
}`;
this.sendMessageModalMarkup =
`<span class="sendlargemessages-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizelarge}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">REPLACE_modal_header_text</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline} ${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.flexchild + BDFDB.disCN.modalsubinner}" style="flex: 1 1 auto;">
<textarea class="${BDFDB.disCNS.scroller + BDFDB.disCNS.inputdefault + BDFDB.disCN.input}" id="modal-inputtext"></textarea>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCNS.nowrap + BDFDB.disCNS.modalsubinner + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;">
<h5 id="warning-message" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 1 1 auto;"></h5>
<h5 id="character-counter" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 0 0 auto;"></h5>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-send ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_send_text</div>
</button>
</div>
</div>
</div>
</div>
</span>`;
}
getName () {return "SendLargeMessages";}
getDescription () {return "Opens a popout when your message is too large, which allows you to automatically send the message in several smaller messages.";}
getVersion () {return "1.4.6";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.bindEventToTextArea();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.bindEventToTextArea();
}
}
// begin of own functions
changeLanguageStrings () {
this.sendMessageModalMarkup = this.sendMessageModalMarkup.replace("REPLACE_modal_header_text", this.labels.modal_header_text);
this.sendMessageModalMarkup = this.sendMessageModalMarkup.replace("REPLACE_btn_cancel_text", this.labels.btn_cancel_text);
this.sendMessageModalMarkup = this.sendMessageModalMarkup.replace("REPLACE_btn_send_text", this.labels.btn_send_text);
}
bindEventToTextArea () {
var checkTextarea = (textarea, text) => {
if (BDFDB.getParsedLength(text) > 1950) {
textarea.selectionStart = 0;
textarea.selectionEnd = textarea.value.length;
document.execCommand("insertText", false, "");
this.showSendModal(text);
}
};
$(BDFDB.dotCNS.textareawrapchat + "textarea")
.off("input." + this.getName())
.on("input." + this.getName(), e => {
checkTextarea(e.currentTarget, e.currentTarget.value);
})
.off("paste." + this.getName())
.on("paste." + this.getName(), e => {
setImmediate(() => {
checkTextarea(e.currentTarget, e.currentTarget.value);
});
});
}
showSendModal (text) {
var sendMessageModal = $(this.sendMessageModalMarkup);
var textinput = sendMessageModal.find("#modal-inputtext");
var warning = sendMessageModal.find("#warning-message");
var counter = sendMessageModal.find("#character-counter");
var updateCounter = () => {
var parsedlength = BDFDB.getParsedLength(textinput.val());
var messageAmount = Math.ceil(parsedlength/1900);
warning.text(messageAmount > 15 ? this.labels.modal_messages_warning : "");
counter.text(parsedlength + " (" + (textinput[0].selectionEnd - textinput[0].selectionStart) + ") => " + this.labels.modal_messages_translation + ": " + messageAmount);
};
BDFDB.appendModal(sendMessageModal);
sendMessageModal
.on("click", ".btn-send", (e) => {
e.preventDefault();
var messages = this.formatText(textinput.val());
messages.forEach((message,i) => {
setTimeout(() => {
this.sendMessage(message);
if (i == messages.length-1) BDFDB.showToast(this.labels.toast_allsent_text, {type:"success"});
},this.messageDelay * i);
});
});
textinput
.val(text)
.focus()
.off("keydown." + this.getName() + " click." + this.getName())
.on("keydown." + this.getName() + " click." + this.getName(), () => {
setTimeout(() => {
updateCounter();
},10);
})
.off("mousedown." + this.getName())
.on("mousedown." + this.getName(), () => {
$(document)
.off("mouseup." + this.getName())
.on("mouseup." + this.getName(), () => {
$(document)
.off("mouseup." + this.getName())
.off("mousemove." + this.getName());
})
.off("mousemove." + this.getName())
.on("mousemove." + this.getName(), () => {
setTimeout(() => {
updateCounter();
},10);
});
});
updateCounter();
}
formatText (text) {
text = text.replace(new RegExp("\t", 'g'), " ");
var longwords = text.match(/[\S]{1800,}/gm);
for (var i in longwords) {
let longword = longwords[i];
let count1 = 0;
let shortwords = [];
longword.split("").forEach((char) => {
if (shortwords[count1] && BDFDB.getParsedLength(shortwords[count1]) >= 1800) count1++;
shortwords[count1] = shortwords[count1] ? shortwords[count1] + char : char;
});
text = text.replace(longword, shortwords.join(" "));
}
var messages = [];
var count2 = 0;
text.split(" ").forEach((word) => {
if (messages[count2] && BDFDB.getParsedLength(messages[count2] + "" + word) > 1900) count2++;
messages[count2] = messages[count2] ? messages[count2] + " " + word : word;
});
var insertCodeBlock = null, insertCodeLine = null;
for (var j = 0; j < messages.length; j++) {
if (insertCodeBlock) {
messages[j] = insertCodeBlock + messages[j];
insertCodeBlock = null;
}
else if (insertCodeLine) {
messages[j] = insertCodeLine + messages[j];
insertCodeLine = null;
}
var codeBlocks = messages[j].match(/`{3,}[\S]*\n|`{3,}/gm);
var codeLines = messages[j].match(/[^`]{0,1}`{1,2}[^`]|[^`]`{1,2}[^`]{0,1}/gm);
if (codeBlocks && codeBlocks.length % 2 == 1) {
messages[j] = messages[j] + "```";
insertCodeBlock = codeBlocks[codeBlocks.length-1] + "\n";
}
else if (codeLines && codeLines.length % 2 == 1) {
insertCodeLine = codeLines[codeLines.length-1].replace(/[^`]/g, "");
messages[j] = messages[j] + insertCodeLine;
}
}
return messages;
}
sendMessage (text) {
var textarea = document.querySelector(BDFDB.dotCNS.textareawrapchat + "textarea");
if (textarea) {
BDFDB.getOwnerInstance({"node":textarea, "name":"ChannelTextAreaForm", "up":true}).setState({textValue:text});
BDFDB.triggerSend(textarea);
}
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
toast_allsent_text: "Sve veliku poslane.",
modal_messages_translation: "Vijesti",
modal_messages_warning: "Nemojte slati previše veliku!",
modal_header_text: "Pošalji veliku poruku:",
btn_cancel_text: "Prekid",
btn_send_text: "Poslati"
};
case "da": //danish
return {
toast_allsent_text: "Alle beskeder sendes.",
modal_messages_translation: "Beskeder",
modal_messages_warning: "Send ikke for mange beskeder!",
modal_header_text: "Send stor besked:",
btn_cancel_text: "Afbryde",
btn_send_text: "Sende"
};
case "de": //german
return {
toast_allsent_text: "Alle Nachrichten versendet.",
modal_messages_translation: "Nachrichten",
modal_messages_warning: "Schicke nicht zu viele Nachrichten!",
modal_header_text: "Große Nachricht senden:",
btn_cancel_text: "Abbrechen",
btn_send_text: "Senden"
};
case "es": //spanish
return {
toast_allsent_text: "Todos los mensajes enviados.",
modal_messages_translation: "Mensajes",
modal_messages_warning: "¡No envíe demasiados mensajes!",
modal_header_text: "Enviar mensaje grande:",
btn_cancel_text: "Cancelar",
btn_send_text: "Enviar"
};
case "fr": //french
return {
toast_allsent_text: "Tous les messages envoyés",
modal_messages_translation: "Messages",
modal_messages_warning: "N'envoyez pas trop de messages!",
modal_header_text: "Envoyer un gros message:",
btn_cancel_text: "Abandonner",
btn_send_text: "Envoyer"
};
case "it": //italian
return {
toast_allsent_text: "Tutti i messaggi inviati.",
modal_messages_translation: "Messaggi",
modal_messages_warning: "Non inviare troppi messaggi!",
modal_header_text: "Invia grande messaggio:",
btn_cancel_text: "Cancellare",
btn_send_text: "Inviare"
};
case "nl": //dutch
return {
toast_allsent_text: "Alle berichten verzonden.",
modal_messages_translation: "Berichten",
modal_messages_warning: "Stuur niet te veel berichten!",
modal_header_text: "Stuur een groot bericht:",
btn_cancel_text: "Afbreken",
btn_send_text: "Sturen"
};
case "no": //norwegian
return {
toast_allsent_text: "Alle meldinger sendt.",
modal_messages_translation: "Meldinger",
modal_messages_warning: "Ikke send for mange meldinger!",
modal_header_text: "Send stor melding:",
btn_cancel_text: "Avbryte",
btn_send_text: "Sende"
};
case "pl": //polish
return {
toast_allsent_text: "Wszystkie wiadomości zostały wysłane.",
modal_messages_translation: "Wiadomości",
modal_messages_warning: "Nie wysyłaj zbyt wielu wiadomości!",
modal_header_text: "Wyślij dużą wiadomość:",
btn_cancel_text: "Anuluj",
btn_send_text: "Wyślij"
};
case "pt-BR": //portuguese (brazil)
return {
toast_allsent_text: "Todas as mensagens enviadas.",
modal_messages_translation: "Mensagens",
modal_messages_warning: "Não envie muitas mensagens!",
modal_header_text: "Enviar mensagem grande:",
btn_cancel_text: "Cancelar",
btn_send_text: "Enviar"
};
case "fi": //finnish
return {
toast_allsent_text: "Kaikki lähetetyt viestit.",
modal_messages_translation: "Viestien",
modal_messages_warning: "Älä lähetä liian monta viestiä!",
modal_header_text: "Lähetä suuri viesti:",
btn_cancel_text: "Peruuttaa",
btn_send_text: "Lähettää"
};
case "sv": //swedish
return {
toast_allsent_text: "Alla meddelanden skickade.",
modal_messages_translation: "Meddelanden",
modal_messages_warning: "Skicka inte för många meddelanden!",
modal_header_text: "Skicka stort meddelande:",
btn_cancel_text: "Avbryta",
btn_send_text: "Skicka"
};
case "tr": //turkish
return {
toast_allsent_text: "Tüm mesajlar gönderildi.",
modal_messages_translation: "Mesajları",
modal_messages_warning: "Çok fazla mesaj göndermeyin!",
modal_header_text: "Büyük mesaj gönder:",
btn_cancel_text: "Iptal",
btn_send_text: "Göndermek"
};
case "cs": //czech
return {
toast_allsent_text: "Všechny zprávy byly odeslány.",
modal_messages_translation: "Zpráv",
modal_messages_warning: "Neposílejte příliš mnoho zpráv!",
modal_header_text: "Odeslat velkou zprávu:",
btn_cancel_text: "Zrušení",
btn_send_text: "Poslat"
};
case "bg": //bulgarian
return {
toast_allsent_text: "Всички изпратени съобщения.",
modal_messages_translation: "Съобщения",
modal_messages_warning: "Не изпращайте твърде много съобщения!",
modal_header_text: "Изпратете голямо съобщение:",
btn_cancel_text: "Зъбести",
btn_send_text: "изпращам"
};
case "ru": //russian
return {
toast_allsent_text: "Все отправленные сообщения.",
modal_messages_translation: "Сообщения",
modal_messages_warning: "Не отправляйте слишком много сообщений!",
modal_header_text: "Отправить сообщение:",
btn_cancel_text: "Отмена",
btn_send_text: "Послать"
};
case "uk": //ukrainian
return {
toast_allsent_text: "Всі повідомлення надіслано.",
modal_messages_translation: "Повідомлення",
modal_messages_warning: "Не надсилайте надто багато повідомлень!",
modal_header_text: "Надіслати велике повідомлення:",
btn_cancel_text: "Скасувати",
btn_send_text: "Відправити"
};
case "ja": //japanese
return {
toast_allsent_text: "すべてのメッセージが送信されました。",
modal_messages_translation: "メッセージ",
modal_messages_warning: "あまりにも多くのメッセージを送信しないでください!",
modal_header_text: "大きなメッセージを送信する:",
btn_cancel_text: "キャンセル",
btn_send_text: "送信"
};
case "zh-TW": //chinese (traditional)
return {
toast_allsent_text: "發送的所有消息。",
modal_messages_translation: "消息",
modal_messages_warning: "不要發送太多信息!",
modal_header_text: "發送大信息:",
btn_cancel_text: "取消",
btn_send_text: "發送"
};
case "ko": //korean
return {
toast_allsent_text: "모든 메시지가 전송되었습니다.",
modal_messages_translation: "메시지",
modal_messages_warning: "너무 많은 메시지를 보내지 마십시오!",
modal_header_text: "큰 메시지 보내기:",
btn_cancel_text: "취소",
btn_send_text: "보내다"
};
default: //default: english
return {
toast_allsent_text: "All messages sent.",
modal_messages_translation: "Messages",
modal_messages_warning: "Do not send too many messages!",
modal_header_text: "Send large message:",
btn_cancel_text: "Cancel",
btn_send_text: "Send"
};
}
}
}

View File

@ -0,0 +1,12 @@
# Server Folders - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ServerFolders/ServerFolders.plugin.js)
Adds the feature to create folders to organize your servers.
- Right click a server > 'Serverfolders' > 'Create Folder' to create a folder.
- To add servers to a folder hold 'Ctrl' and drag the server onto the folder, this will add the server to the folderlist and hide it in the serverlist.
- To open a folder click the folder. A folder can only be opened when it has at least one server in it.
- To remove a server from a folder, open the folder and either right click the server > 'Serverfolders' > 'Remove Server from Folder' or hold 'Del' and click the server in the folderlist.
- Right clicking a folder gives you the option to
- Clear all notifications of the servers within the folder (greyed out if no notifications are present).
- Open the settingspopout for the folder to change the icon, the name and/or the color of the folder.
- Delete the folder.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
# Server Hider - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ServerHider/ServerHider.plugin.js)
Adds two options on your server context menu.
- You can hide the selected server.
- You can open a popout, where you can swiftly hide servers and display them again.

View File

@ -0,0 +1,606 @@
//META{"name":"ServerHider"}*//
class ServerHider {
initConstructor () {
this.labels = {};
this.css = `
.serverhider-modal .entry ${BDFDB.dotCN.guild} {
height: 50px;
position: relative;
width: 50px;
z-index: 1;
}
.serverhider-modal .entry ${BDFDB.dotCN.guildinner} {
background: #2f3136;
border-radius: 25px !important;
cursor: pointer;
font-size: 18px;
line-height: 50px;
overflow: hidden;
text-align: center;
}
.serverhider-modal .entry ${BDFDB.dotCNS.guild + BDFDB.dotCN.avatarsmallold} {
background-repeat: no-repeat;
background-size: 50px 50px;
border-radius: 0;
color: #fff;
display: block;
float: left;
margin: 0;
height: 50px;
width: 50px;
}
.serverhider-modal .entry ${BDFDB.dotCNS.guild + BDFDB.dotCN.badge} {
background-clip: padding-box;
background-color: #f04747;
border-radius: 3px;
bottom: -2px;
box-shadow: 0 1px 0 rgba(0,0,0,.25), inset 0 1px 0 hsla(0,0%,100%,.15);
color: #fff;
display: inline-block;
font-size: 12px;
font-weight: 500;
line-height: 12px;
padding: 3px 6px;
pointer-events: none;
position: absolute;
right: -2px;
text-shadow: 0 1px 0 rgba(0,0,0,.25);
}
.serverhider-modal .folderhideCheckboxWrapper {
right: 8px;
}`;
this.serverHiderModalMarkup =
`<span class="serverhider-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizemedium}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">REPLACE_modal_header_text</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.modalsubinner + BDFDB.disCN.marginbottom8} folderhideSettings" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">REPLACE_modal_folderhide_text</h3>
</div>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault} folderhideCheckboxWrapper" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} folderhideCheckbox">
</div>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} entries"></div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-save ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_ok_text</div>
</button>
<button type="button" class="btn-all ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlooklink + BDFDB.disCNS.buttoncolortransparent + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}">REPLACE_btn_all_text</div>
</button>
</div>
</div>
</div>
</div>
</span>`;
this.serverEntryMarkup =
`<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCN.marginbottom4} entry" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCNS.flexchild + BDFDB.disCNS.overflowellipsis} serverhiderName" style="flex: 1 1 auto;"></h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} serverhiderCheckbox">
</div>
</div>`;
this.dividerMarkup = `<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCN.modaldividerdefault}"></div>`;
this.serverContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} serverhider-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>REPLACE_context_serverhider_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.serverContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} serverhider-submenu">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} hideserver-item ${BDFDB.disCN.contextmenuitemdisabled}">
<span>REPLACE_submenu_hideserver_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
<div class="${BDFDB.disCN.contextmenuitem} openhidemenu-item">
<span>REPLACE_submenu_openhidemenu_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>
</div>`;
}
getName () {return "ServerHider";}
getDescription () {return "Hide Servers in your Serverlist";}
getVersion () {return "2.5.9";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Reset all Servers.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} reset-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".reset-button", () => {this.resetAll();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || BDFDB.isLibraryOutdated()) {
if (typeof BDFDB === "object") BDFDB = "";
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"serverContextObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.classList && node.classList.contains(BDFDB.disCN.guild) && !node.querySelector(BDFDB.dotCN.guildserror)) {
var info = BDFDB.getKeyInformation({"node":node, "key":"guild"});
if (info) {
var data = BDFDB.loadData(info.id, this, "servers");
if (data) {
$(node).toggle(data.visible);
}
}
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.guilds, {name:"serverListObserver",instance:observer}, {childList: true});
$(BDFDB.dotCN.guilds).on("mouseleave." + this.getName(), () => {this.updateAllServers(false);});
this.updateAllServers(true);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.readServerList().forEach(serverObj => {
if (!serverObj.div.getAttribute("folder")) $(serverObj.div).show();
});
BDFDB.unloadMessage(this);
}
}
// begin of own functions
resetAll () {
if (confirm("Are you sure you want to reset all servers?")) {
BDFDB.removeAllData(this, "servers");
BDFDB.readServerList().forEach(serverObj => {
if (!serverObj.div.getAttribute("folder")) $(serverObj.div).show();
});
}
}
changeLanguageStrings () {
this.serverContextEntryMarkup = this.serverContextEntryMarkup.replace("REPLACE_context_serverhider_text", this.labels.context_serverhider_text);
this.serverContextSubMenuMarkup = this.serverContextSubMenuMarkup.replace("REPLACE_submenu_hideserver_text", this.labels.submenu_hideserver_text);
this.serverContextSubMenuMarkup = this.serverContextSubMenuMarkup.replace("REPLACE_submenu_openhidemenu_text", this.labels.submenu_openhidemenu_text);
this.serverHiderModalMarkup = this.serverHiderModalMarkup.replace("REPLACE_modal_header_text", this.labels.modal_header_text);
this.serverHiderModalMarkup = this.serverHiderModalMarkup.replace("REPLACE_modal_folderhide_text", this.labels.modal_folderhide_text);
this.serverHiderModalMarkup = this.serverHiderModalMarkup.replace("REPLACE_btn_ok_text", this.labels.btn_ok_text);
this.serverHiderModalMarkup = this.serverHiderModalMarkup.replace("REPLACE_btn_all_text", this.labels.btn_all_text);
this.serverEntryMarkup = this.serverEntryMarkup.replace("REPLACE_btn_visible_text", this.labels.btn_visible_text);
}
onContextMenu (context) {
if (document.querySelector(".serverhider-modal") || !context || !context.tagName || !context.parentElement || context.querySelector(".serverhider-item")) return;
var info = BDFDB.getKeyInformation({"node":context, "key":"guild"});
var valid = false;
if (info && BDFDB.getKeyInformation({"node":context, "key":"displayName", "value":"GuildLeaveGroup"})) {
valid = true;
}
else if (BDFDB.getKeyInformation({"node":context, "key":"handleGuildCreate"})) {
info = {guildCreate:true};
valid = true;
}
if (valid) {
$(context).append(this.serverContextEntryMarkup)
.on("mouseenter", ".serverhider-item", (e) => {
this.createContextSubMenu(info, e, context);
});
BDFDB.updateContextPosition(context);
}
}
createContextSubMenu (info, e, context) {
var serverContextSubMenu = $(this.serverContextSubMenuMarkup);
serverContextSubMenu
.on("click", ".openhidemenu-item", () => {
$(context).hide();
this.showServerModal();
});
if (!info.guildCreate) {
serverContextSubMenu
.find(".hideserver-item")
.removeClass(BDFDB.disCN.contextmenuitemdisabled)
.on("click", () => {
$(context).hide();
this.hideServer(info);
});
}
BDFDB.appendSubMenu(e.currentTarget, serverContextSubMenu);
}
hideServer (info) {
var serverObj = BDFDB.getDivOfServer(info.id);
if (!serverObj) return;
$(serverObj.div).hide();
BDFDB.saveData(info.id, {visible:false}, this, "servers");
}
showServerModal () {
var serverObjs = BDFDB.readServerList();
var serverHiderModal = $(this.serverHiderModalMarkup);
serverHiderModal
.on("click", ".folderhideCheckbox", (e) => {
serverHiderModal.find(".hidefolder").toggle(!$(e.target).prop("checked"));
})
.on("click", ".btn-all", () => {
var hideAll = $(serverObjs[0].div).is(":visible");
for (let serverObj of serverObjs) {
$(serverObj.div).toggle(!hideAll);
BDFDB.saveData(serverObj.id, {visible:!hideAll}, this, "servers");
}
$(".serverhiderCheckbox").each((_, checkBox) => {if ($(checkBox).prop("checked") == hideAll) checkBox.click();});
});
if (!BDFDB.isPluginEnabled("ServerFolders")) serverHiderModal.find(".folderhideSettings").hide();
for (let serverObj of serverObjs) {
let badge = serverObj.div.querySelector(BDFDB.dotCN.badge);
let entry = $(this.serverEntryMarkup);
let divider = $(this.dividerMarkup);
let isHiddenByFolder = $(serverObj.div).attr("folder") ? true : false;
entry.toggleClass("hidefolder", isHiddenByFolder);
divider.toggleClass("hidefolder", isHiddenByFolder);
serverHiderModal.find(".entries").append(entry).append(divider);
entry.find(".serverhiderName")
.before(this.createCopyOfServer(serverObj))
.text(serverObj.name);
entry.find(".serverhiderCheckbox")
.prop("checked", $(serverObj.div).is(":visible"))
.on("click", (event) => {
var visible = $(event.target).prop("checked");
$(serverObj.div).toggle(visible);
BDFDB.saveData(serverObj.id, {visible:visible}, this, "servers");
});
}
BDFDB.appendModal(serverHiderModal);
}
createCopyOfServer (serverObj) {
var serverDiv = serverObj.div;
var serverCopy = serverDiv.cloneNode(true);
$(serverCopy)
.css("display", "")
.on("click." + this.getName(), (e) => {
e.preventDefault();
serverDiv.querySelector("a").click();
})
.on("contextmenu." + this.getName(), (e) => {
var handleContextMenu = BDFDB.getKeyInformation({"node":serverDiv.firstElementChild, "key":"handleContextMenu"});
if (handleContextMenu) {
var data = {
preventDefault: a=>a,
stopPropagation: a=>a,
pageX: e.pageX,
pageY: e.pageY,
};
handleContextMenu(data);
}
});
return serverCopy;
}
updateAllServers (write) {
for (let serverObj of BDFDB.readServerList()) {
var data = BDFDB.loadData(serverObj.id, this, "servers");
var visible = data && write ? data.visible : $(serverObj.div).is(":visible");
$(serverObj.div).toggle(visible);
BDFDB.saveData(serverObj.id, {visible}, this, "servers");
}
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
modal_header_text: "Upravljanje popisom poslužitelja",
modal_folderhide_text: "Nemoj prikazivati poslužitelje skrivene po narudžbi",
btn_ok_text: "OK",
btn_all_text: "Sve",
context_serverhider_text: "Vidljivost poslužitelj",
submenu_hideserver_text: "Sakrij poslužitelj",
submenu_openhidemenu_text: "Upravljanje popisom poslužitelja"
};
case "da": //danish
return {
modal_header_text: "Styring af Serverliste",
modal_folderhide_text: "Vis ingen servere, som er gemt af mapper",
btn_ok_text: "OK",
btn_all_text: "Alle",
context_serverhider_text: "Server synlighed",
submenu_hideserver_text: "Skjul Server",
submenu_openhidemenu_text: "Styre Serverliste"
};
case "de": //german
return {
modal_header_text: "Verwaltung der Serverliste",
modal_folderhide_text: "Zeige keine Server, die durch Order versteckt wurden",
btn_ok_text: "OK",
btn_all_text: "Alle",
context_serverhider_text: "Serversichtbarkeit",
submenu_hideserver_text: "Server verstecken",
submenu_openhidemenu_text: "Serverliste verwalten"
};
case "es": //spanish
return {
modal_header_text: "Administración de lista de servidores",
modal_folderhide_text: "No mostrar servidores, que están ocultos por las carpetas",
btn_ok_text: "OK",
btn_all_text: "Todo",
context_serverhider_text: "Visibilidad del servidor",
submenu_hideserver_text: "Ocultar servidor",
submenu_openhidemenu_text: "Administrar lista de servidores"
};
case "fr": //french
return {
modal_header_text: "Gestion de la liste des serveurs",
modal_folderhide_text: "Afficher aucun serveur, qui sont cachés par des dossiers",
btn_ok_text: "OK",
btn_all_text: "Tout",
context_serverhider_text: "Visibilité du serveur",
submenu_hideserver_text: "Cacher le serveur",
submenu_openhidemenu_text: "Gérer la liste des serveurs"
};
case "it": //italian
return {
modal_header_text: "Gestione dell'elenco dei server",
modal_folderhide_text: "Mostra nessun server nascosto nelle cartelle",
btn_ok_text: "OK",
btn_all_text: "Tutto",
context_serverhider_text: "Visibilità del server",
submenu_hideserver_text: "Nascondi il server",
submenu_openhidemenu_text: "Gestione elenco dei server"
};
case "nl": //dutch
return {
modal_header_text: "Beheer van de Serverlijst",
modal_folderhide_text: "Toon geen servers, die zijn verborgen door mappen",
btn_ok_text: "OK",
btn_all_text: "Alle",
context_serverhider_text: "Server zichtbaarheid",
submenu_hideserver_text: "Verberg server",
submenu_openhidemenu_text: "Beheer serverlijst"
};
case "no": //norwegian
return {
modal_header_text: "Administrasjon av serverlisten",
modal_folderhide_text: "Vis ingen servere, som er skjult av mapper",
btn_ok_text: "OK",
btn_all_text: "Alle",
context_serverhider_text: "Server synlighet",
submenu_hideserver_text: "Skjul server",
submenu_openhidemenu_text: "Administrer serverliste"
};
case "pl": //polish
return {
modal_header_text: "Zarządzanie listą serwerów",
modal_folderhide_text: "Nie pokazuj żadnych serwerów, które są ukryte w folderach",
btn_ok_text: "OK",
btn_all_text: "Wszystkie",
context_serverhider_text: "Widoczność serwera",
submenu_hideserver_text: "Ukryj serwer",
submenu_openhidemenu_text: "Zarządzaj listą serwerów"
};
case "pt-BR": //portuguese (brazil)
return {
modal_header_text: "Gerenciamento da lista de servidores",
modal_folderhide_text: "Não exiba servidores, que estão ocultos por pastas",
btn_ok_text: "OK",
btn_all_text: "Todo",
context_serverhider_text: "Visibilidade do servidor",
submenu_hideserver_text: "Ocultar servidor",
submenu_openhidemenu_text: "Gerenciar lista de servidores"
};
case "fi": //finnish
return {
modal_header_text: "Palvelinluettelon hallinta",
modal_folderhide_text: "Näytä mitään palvelimia, jotka ovat kansioiden piilossa",
btn_ok_text: "OK",
btn_all_text: "Kaikki",
context_serverhider_text: "Palvelimen näkyvyys",
submenu_hideserver_text: "Piilota palvelin",
submenu_openhidemenu_text: "Hallinnoi palvelinluetteloa"
};
case "sv": //swedish
return {
modal_header_text: "Hantering av serverlistan",
modal_folderhide_text: "Visa inga servrar, vilka är dolda av mappar",
btn_ok_text: "OK",
btn_all_text: "All",
context_serverhider_text: "Server sikt",
submenu_hideserver_text: "Dölj server",
submenu_openhidemenu_text: "Hantera serverlistan"
};
case "tr": //turkish
return {
modal_header_text: "Sunucu Listesinin Yönetimi",
modal_folderhide_text: "Klasörler tarafından gizlenen hiçbir sunucu gösterme",
btn_ok_text: "Okey",
btn_all_text: "Her",
context_serverhider_text: "Sunucu görünürlüğü",
submenu_hideserver_text: "Sunucuyu Gizle",
submenu_openhidemenu_text: "Sunucu Listesini Yönet"
};
case "cs": //czech
return {
modal_header_text: "Správa seznamu serverů",
modal_folderhide_text: "Zobrazit žádné servery, které jsou skryty podle složek",
btn_ok_text: "OK",
btn_all_text: "Vše",
context_serverhider_text: "Viditelnost serveru",
submenu_hideserver_text: "Skrýt server",
submenu_openhidemenu_text: "Správa seznamu serverů"
};
case "bg": //bulgarian
return {
modal_header_text: "Управление на списъка със сървъри",
modal_folderhide_text: "Показване на сървъри, които са скрити от папки",
btn_ok_text: "Добре",
btn_all_text: "Bсичко",
context_serverhider_text: "Видимост на сървъра",
submenu_hideserver_text: "Скриване на сървър",
submenu_openhidemenu_text: "Управление на списъка със сървъри"
};
case "ru": //russian
return {
modal_header_text: "Управление списком серверов",
modal_folderhide_text: "Показывать никакие серверы, скрытые папками",
btn_ok_text: "ОК",
btn_all_text: "Все",
context_serverhider_text: "Видимость сервера",
submenu_hideserver_text: "Скрыть сервер",
submenu_openhidemenu_text: "Управление списком серверов"
};
case "uk": //ukrainian
return {
modal_header_text: "Управління списком серверів",
modal_folderhide_text: "Не показувати жодних серверів, які приховуються папками",
btn_ok_text: "Добре",
btn_all_text: "Все",
context_serverhider_text: "Видимість сервера",
submenu_hideserver_text: "Сховати сервер",
submenu_openhidemenu_text: "Управління списком серверів"
};
case "ja": //japanese
return {
modal_header_text: "サーバリストの管理",
modal_folderhide_text: "フォルダに隠されているサーバーは表示しない",
btn_ok_text: "はい",
btn_all_text: "すべて",
context_serverhider_text: "サーバーの可視性",
submenu_hideserver_text: "サーバーを隠す",
submenu_openhidemenu_text: "サーバーリストを管理する"
};
case "zh-TW": //chinese (traditional)
return {
modal_header_text: "管理服务器列表",
modal_folderhide_text: "不顯示被文件夾隱藏的服務器",
btn_ok_text: "好",
btn_all_text: "所有",
context_serverhider_text: "服務器可見性",
submenu_hideserver_text: "隐藏服务器",
submenu_openhidemenu_text: "管理服务器列表"
};
case "ko": //korean
return {
modal_header_text: "서버 목록 관리",
modal_folderhide_text: "폴더별로 숨겨진 서버 표시 안 함",
btn_ok_text: "승인",
btn_all_text: "모든",
context_serverhider_text: "서버 가시성",
submenu_hideserver_text: "서버 숨기기",
submenu_openhidemenu_text: "서버 목록 관리"
};
default: //default: english
return {
modal_header_text: "Managing Serverlist",
modal_folderhide_text: "Show no servers, which are hidden by folders",
btn_ok_text: "OK",
btn_all_text: "All",
context_serverhider_text: "Server Visibility",
submenu_hideserver_text: "Hide Server",
submenu_openhidemenu_text: "Manage Serverlist"
};
}
}
}

View File

@ -0,0 +1,3 @@
# Show Hidden Channels - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ShowHiddenChannels/ShowHiddenChannels.plugin.js)
Displays all hidden channels that can't be accessed due to role restrictions in a new category.

View File

@ -0,0 +1,514 @@
//META{"name":"ShowHiddenChannels"}*//
class ShowHiddenChannels {
initConstructor () {
this.updateHiddenCategory = false;
this.categoryMarkup =
`<div class="container-hidden">
<div class="${BDFDB.disCN.categorycontainerdefault}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstart + BDFDB.disCNS.nowrap + BDFDB.disCNS.categorywrapperdefault + BDFDB.disCN.cursorpointer}" style="flex: 1 1 auto;">
<svg class="${BDFDB.disCNS.categoryicondefault + BDFDB.disCN.categoryicontransition}" width="12" height="12" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10"></path>
</svg>
<div class="${BDFDB.disCNS.categorynamedefault + BDFDB.disCNS.categorycolortransition + BDFDB.disCN.overflowellipsis}" style="flex: 1 1 auto;">hidden</div>
</div>
</div>
</div>`;
this.channelTextMarkup =
`<div class="${BDFDB.disCN.channelcontainerdefault}">
<div class="${BDFDB.disCNS.channelwrapperdefaulttext + BDFDB.disCN.channelwrapper}">
<div class="${BDFDB.disCNS.channelcontentdefaulttext + BDFDB.disCN.channelcontent}">
<div class="${BDFDB.disCN.marginreset}" style="flex: 0 0 auto;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" class="${BDFDB.disCNS.channelcolordefaulttext + BDFDB.disCN.channelicon}">
<path class="${BDFDB.disCN.channelbackground}" fill="currentColor" d="M7.92,4.66666667 L6.50666667,4.66666667 L6.98,2 L5.64666667,2 L5.17333333,4.66666667 L2.50666667,4.66666667 L2.27333333,6 L4.94,6 L4.23333333,10 L1.56666667,10 L1.33333333,11.3333333 L4,11.3333333 L3.52666667,14 L4.86,14 L5.33333333,11.3333333 L9.33333333,11.3333333 L8.86,14 L10.1933333,14 L10.6666667,11.3333333 L13.3333333,11.3333333 L13.5666667,10 L12.2333333,10 L8.74333333,10 L5.56666667,10 L6.27333333,6 L7.92,6 L7.92,4.66666667 Z"></path>
<path class="${BDFDB.disCN.channelforeground}" fill="currentColor" fill-rule="nonzero" d="M15.1,3.2 L15.1,2 C15.1,0.88 14.05,0 13,0 C11.95,0 10.9,0.88 10.9,2 L10.9,3.2 C10.45,3.2 10,3.68 10,4.16 L10,6.96 C10,7.52 10.45,8 10.9,8 L15.025,8 C15.55,8 16,7.52 16,7.04 L16,4.24 C16,3.68 15.55,3.2 15.1,3.2 Z M14,3 L12,3 L12,1.92857143 C12,1.35714286 12.4666667,1 13,1 C13.5333333,1 14,1.35714286 14,1.92857143 L14,3 Z"></path>
</svg>
</div>
<div class="${BDFDB.disCNS.channelnamedefaulttext + BDFDB.disCNS.channelname + BDFDB.disCN.overflowellipsis}" style="flex: 1 1 auto;"></div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginreset}" style="flex: 0 1 auto;"></div>
</div>
</div>
</div>`;
this.channelVoiceMarkup =
`<div class="${BDFDB.disCN.channelcontainerdefault}">
<div class="${BDFDB.disCNS.channelwrapperdefaultvoice + BDFDB.disCN.channelwrapper}">
<div class="${BDFDB.disCNS.channelcontentdefaultvoice + BDFDB.disCN.channelcontent}">
<div class="${BDFDB.disCN.marginreset}" style="flex: 0 0 auto;">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" class="${BDFDB.disCNS.channelcolordefaultvoice + BDFDB.disCN.channelicon}">
<path class=${BDFDB.disCN.channelbackground}" fill="currentColor" d="M13.6005009,10 C12.8887426,11.8438372 11.2906136,13.2480521 9.33333333,13.6933333 L9.33333333,12.3133333 C10.5512947,11.950895 11.5614504,11.1062412 12.1398042,10 L13.6005009,10 Z M10.7736513,8.99497564 C10.4978663,9.6613459 9.98676114,10.2040442 9.33333333,10.5133333 L9.33333333,8.99497564 L10.7736513,8.99497564 Z M2,5.84666667 L4.66666667,5.84666667 L8,2.51333333 L8,13.18 L4.66666667,9.84666667 L2,9.84666667 L2,5.84666667 Z"></path>
<path class="${BDFDB.disCN.channelforeground}" fill="currentColor" fill-rule="nonzero" d="M15.1,3.2 L15.1,2 C15.1,0.88 14.05,0 13,0 C11.95,0 10.9,0.88 10.9,2 L10.9,3.2 C10.45,3.2 10,3.68 10,4.16 L10,6.96 C10,7.52 10.45,8 10.9,8 L15.025,8 C15.55,8 16,7.52 16,7.04 L16,4.24 C16,3.68 15.55,3.2 15.1,3.2 Z M14,3 L12,3 L12,1.92857143 C12,1.35714286 12.4666667,1 13,1 C13.5333333,1 14,1.35714286 14,1.92857143 L14,3 Z"></path>
</svg>
</div>
<div class="${BDFDB.disCNS.channelnamedefaultvoice + BDFDB.disCNS.channelname + BDFDB.disCN.overflowellipsis}" style="flex: 1 1 auto;"></div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginreset}" style="flex: 0 1 auto;"></div>
</div>
</div>
</div>`;
this.channelCategoryMarkup =
`<div class="${BDFDB.disCN.channelcontainerdefault}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.cursorpointer + BDFDB.disCNS.categorywrappercollapsed + BDFDB.disCN.channelcontent}" style="flex: 1 1 auto;">
<svg class="${BDFDB.disCNS.categoryicontransition + BDFDB.disCNS.directionright + BDFDB.disCN.categoryiconcollapsed}" width="12" height="12" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="M7 10L12 15 17 10"></path>
</svg>
<div class="${BDFDB.disCNS.categorycolortransition + BDFDB.disCNS.overflowellipsis + BDFDB.disCN.categorynamecollapsed}" style="flex: 1 1 auto;"></div>
</div>
</div>`;
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:"}
}
};
}
getName () {return "ShowHiddenChannels";}
getDescription () {return "Displays channels that are hidden from you by role restrictions.";}
getVersion () {return "2.2.8";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UserStore = BDFDB.WebModules.findByProperties(["getUsers", "getUser"]);
this.MemberStore = BDFDB.WebModules.findByProperties(["getMember", "getMembers"]);
this.ChannelStore = BDFDB.WebModules.findByProperties(["getChannels", "getDMFromUserId"]);
this.GuildChannels = BDFDB.WebModules.findByProperties(["getChannels", "getDefaultChannel"]);
this.Permissions = BDFDB.WebModules.findByProperties(["Permissions", "ActivityTypes"]).Permissions;
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.className && node.className.length > 0 && node.className.indexOf("container-") > -1 && node.className.indexOf("hidden") == -1) {
this.appendToChannelList(document.querySelector(".container-hidden"));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.channels, {name:"channelListObserver",instance:observer}, {childList: true, subtree: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (this.updateHiddenCategory && node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
document.querySelectorAll(".container-hidden").forEach(category => {category.remove();});
this.displayHiddenChannels();
this.updateHiddenCategory = false;
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
this.displayHiddenChannels();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(".container-hidden").remove();
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.displayHiddenChannels();
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
this.updateHiddenCategory = true;
}
displayHiddenChannels () {
var serverObj = BDFDB.getSelectedServer();
if (serverObj) {
var serverID = serverObj.id;
if (!document.querySelector(".container-hidden.server" + serverID)) {
$(".container-hidden").remove();
var types = {
"text":0,
"voice":2,
"category":4
};
var allChannels = this.ChannelStore.getChannels();
var shownChannels = this.GuildChannels.getChannels(serverID);
var hiddenChannels = {};
for (let type in types) hiddenChannels[types[type]] = [];
for (let channelID in allChannels) {
var channel = allChannels[channelID];
if (channel.guild_id == serverID) {
var isHidden = true;
if (channel.type == types.category) {
for (let type in types) {
for (let shownChannel of shownChannels[types[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 types) {
if (!settings.showText && type == "text" || !settings.showVoice && type == "voice" || !settings.showCategory && type == "category") {
hiddenChannels[types[type]] = [];
}
BDFDB.sortArrayByKey(hiddenChannels[types[type]], "name");
count += hiddenChannels[types[type]].length;
}
hiddenChannels.count = count;
if (count > 0) {
var category = $(this.categoryMarkup)[0]
var wrapper = category.querySelector(BDFDB.dotCN.cursorpointer);
var svg = category.querySelector(BDFDB.dotCN.categoryicontransition);
var name = category.querySelector(BDFDB.dotCN.categorycolortransition);
$(category)
.addClass("server" + serverID)
.on("click", BDFDB.dotCN.categorycontainerdefault + " > " + BDFDB.dotCN.flex, (e) => {
wrapper.classList.toggle(BDFDB.disCN.categorywrapperhovered);
wrapper.classList.toggle(BDFDB.disCN.categorywrapperhoveredcollapsed);
svg.classList.toggle(BDFDB.disCN.categoryiconhovered);
svg.classList.toggle(BDFDB.disCN.categoryiconhoveredcollapsed);
svg.classList.toggle(BDFDB.disCN.directionright);
name.classList.toggle(BDFDB.disCN.categorynamehovered);
name.classList.toggle(BDFDB.disCN.categorynamehoveredcollapsed);
$(category).find(BDFDB.dotCN.channelcontainerdefault).toggle(!svg.classList.contains(BDFDB.disCN.directionright));
BDFDB.saveData(serverID, !svg.classList.contains(BDFDB.disCN.directionright), this, "categorystatus");
})
.on("mouseenter mouseleave", BDFDB.dotCN.categorycontainerdefault + " > " + BDFDB.dotCN.flex, () => {
if (!svg.classList.contains(BDFDB.disCN.directionright)) {
wrapper.classList.toggle(BDFDB.disCN.categorywrapperdefault);
wrapper.classList.toggle(BDFDB.disCN.categorywrapperhovered);
svg.classList.toggle(BDFDB.disCN.categoryicondefault);
svg.classList.toggle(BDFDB.disCN.categoryiconhovered);
name.classList.toggle(BDFDB.disCN.categorynamedefault);
name.classList.toggle(BDFDB.disCN.categorynamehovered);
}
else {
wrapper.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
wrapper.classList.toggle(BDFDB.disCN.categorywrapperhoveredcollapsed)
svg.classList.toggle(BDFDB.disCN.categoryiconcollapsed)
svg.classList.toggle(BDFDB.disCN.categoryiconhoveredcollapsed);
name.classList.toggle(BDFDB.disCN.categorynamecollapsed);
name.classList.toggle(BDFDB.disCN.categorynamehoveredcollapsed)
}
});
for (let hiddenChannel of hiddenChannels[0]) {
let channel = $(this.channelTextMarkup)[0];
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);
channelname.innerText = hiddenChannel.name;
$(channel)
.on("mouseenter mouseleave", BDFDB.dotCN.channelwrapper, (e) => {
channelwrapper.classList.toggle(BDFDB.disCN.channelwrapperdefaulttext);
channelwrapper.classList.toggle(BDFDB.disCN.channelwrapperhoveredtext);
channelicon.classList.toggle(BDFDB.disCN.channelcontentdefaulttext);
channelicon.classList.toggle(BDFDB.disCN.channelcontenthoveredtext);
channelsvg.classList.toggle(BDFDB.disCN.channelcolordefaulttext);
channelsvg.classList.toggle(BDFDB.disCN.channelcolorhoveredtext);
channelname.classList.toggle(BDFDB.disCN.channelnamedefaulttext);
channelname.classList.toggle(BDFDB.disCN.channelnamehoveredtext);
this.showAccessRoles(serverObj, hiddenChannel, e, false);
})
.on("click", () => {
BDFDB.showToast(`You can not enter the hidden textchannel ${hiddenChannel.name}.`, {type:"error"});
})
.on("contextmenu", (e) => {
this.createHiddenObjContextMenu(hiddenChannel, e);
})
.appendTo(category);
}
for (let hiddenChannel of hiddenChannels[2]) {
let channel = $(this.channelVoiceMarkup)[0];
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);
channelname.innerText = hiddenChannel.name;
$(channel)
.on("mouseenter mouseleave", BDFDB.dotCN.channelwrapper, (e) => {
channelwrapper.classList.toggle(BDFDB.disCN.channelwrapperdefaultvoice);
channelwrapper.classList.toggle(BDFDB.disCN.channelwrapperhoveredvoice);
channelicon.classList.toggle(BDFDB.disCN.channelcontentdefaultvoice);
channelicon.classList.toggle(BDFDB.disCN.channelcontenthoveredvoice);
channelsvg.classList.toggle(BDFDB.disCN.channelcolordefaultvoice);
channelsvg.classList.toggle(BDFDB.disCN.channelcolorhoveredvoice);
channelname.classList.toggle(BDFDB.disCN.channelnamedefaultvoice);
channelname.classList.toggle(BDFDB.disCN.channelnamehoveredvoice);
this.showAccessRoles(serverObj, hiddenChannel, e, false);
})
.on("click", () => {
BDFDB.showToast(`You can not enter the hidden voicechannel ${hiddenChannel.name}.`, {type:"error"});
})
.on("contextmenu", (e) => {
this.createHiddenObjContextMenu(hiddenChannel, e);
})
.appendTo(category);
}
for (let hiddenChannel of hiddenChannels[4]) {
let channel = $(this.channelCategoryMarkup)[0];
let channelwrapper = channel.querySelector(BDFDB.dotCN.categorywrappercollapsed);
let channelsvg = channel.querySelector(BDFDB.dotCN.categoryiconcollapsed);
let channelname = channel.querySelector(BDFDB.dotCN.categorynamecollapsed);
channelname.innerText = hiddenChannel.name;
$(channel)
.on("mouseenter mouseleave", BDFDB.dotCN.flex, (e) => {
channelwrapper.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
channelwrapper.classList.toggle(BDFDB.disCN.categorywrapperhoveredcollapsed);
channelsvg.classList.toggle(BDFDB.disCN.categoryiconcollapsed)
channelsvg.classList.toggle(BDFDB.disCN.categoryiconhoveredcollapsed);
channelname.classList.toggle(BDFDB.disCN.categorynamecollapsed);
channelname.classList.toggle(BDFDB.disCN.categorynamehoveredcollapsed);
this.showAccessRoles(serverObj, hiddenChannel, e, false);
})
.on("click", () => {
BDFDB.showToast(`You can not open the hidden category ${hiddenChannel.name}.`, {type:"error"});
})
.on("contextmenu", (e) => {
this.createHiddenObjContextMenu(hiddenChannel, e);
})
.appendTo(category);
}
var isOpen = BDFDB.loadData(serverID, this, "categorystatus");
isOpen = isOpen === null ? true : isOpen;
if (!isOpen) {
wrapper.classList.toggle(BDFDB.disCN.categorywrapperdefault);
wrapper.classList.toggle(BDFDB.disCN.categorywrappercollapsed);
svg.classList.toggle(BDFDB.disCN.categoryicondefault);
svg.classList.toggle(BDFDB.disCN.categoryiconcollapsed)
svg.classList.toggle(BDFDB.disCN.directionright);
name.classList.toggle(BDFDB.disCN.categorynamedefault);
name.classList.toggle(BDFDB.disCN.categorynamecollapsed);
$(category).find(BDFDB.dotCN.channelcontainerdefault).hide();
}
this.appendToChannelList(category);
}
let channelist = document.querySelector(BDFDB.dotCNS.channels + BDFDB.dotCN.scroller);
$(channelist).off("mouseenter." + this.getName());
if (BDFDB.getData("showForNormal", this, "settings")) {
$(channelist).on("mouseenter." + this.getName(), BDFDB.dotCNC.channelcontainerdefault + BDFDB.dotCN.categorycontainerdefault, (e) => {
var channel = BDFDB.getKeyInformation({"node":e.currentTarget,"key":"channel"});
if (channel) this.showAccessRoles(serverObj, channel, e, true);
});
}
}
}
}
createHiddenObjContextMenu (hiddenObj, e) {
e.preventDefault();
e.stopPropagation();
var contextMenu = $(`<div class="${BDFDB.disCN.contextmenu} ShowHiddenChannelsContextMenu"><div class="${BDFDB.disCN.contextmenuitemgroup}"><div class="${BDFDB.disCN.contextmenuitem} copyid-item"><span>${BDFDB.LanguageStrings.COPY_ID}</span><div class="${BDFDB.disCN.contextmenuhint}"></div></div></div>`);
contextMenu
.on("click." + this.getName(), ".copyid-item", (e2) => {
contextMenu.remove();
require("electron").clipboard.write({text: hiddenObj.id});
});
BDFDB.appendContextMenu(contextMenu[0], e);
}
showAccessRoles (serverObj, channel, e, allowed) {
if (e.type != "mouseenter" || !serverObj || !channel) return;
var settings = BDFDB.getAllData(this, "settings");
var myMember = this.MemberStore.getMember(serverObj.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" &&
(serverObj.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(serverObj.roles[id]);
}
else {
allowedRoles.push(serverObj.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(serverObj.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(serverObj.roles[id]);
if (serverObj.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(serverObj.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 += `<div class="${BDFDB.disCN.marginbottom4}">Topic:</div><div class="${BDFDB.disCNS.flex + BDFDB.disCN.wrap}"><div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-topic" style="border-color: rgba(255, 255, 255, 0.6); height: unset !important; padding-top: 5px; padding-bottom: 5px; max-width: ${window.outerWidth/3}px">${channel.topic}</div></div>`;
}
if (allowedRoles.length > 0 || overwrittenRoles.length > 0) {
htmlString += `<div class="${BDFDB.disCN.marginbottom4}">Allowed Roles:</div><div class="${BDFDB.disCNS.flex + BDFDB.disCN.wrap}">`;
for (let role of allowedRoles) {
let color = role.colorString ? BDFDB.color2COMP(role.colorString) : [255,255,255];
htmlString += `<div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-allowedrole" style="border-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6);"><div class="${BDFDB.disCNS.userpopoutrolecircle}" style="background-color: rgb(${color[0]}, ${color[1]}, ${color[2]});"></div><div class="${BDFDB.disCNS.userpopoutrolename}">${BDFDB.encodeToHTML(role.name)}</div></div>`;
}
for (let role of overwrittenRoles) {
let color = role.colorString ? BDFDB.color2COMP(role.colorString) : [255,255,255];
htmlString += `<div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-overwrittenrole" style="border-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6);"><div class="${BDFDB.disCNS.userpopoutrolecircle}" style="background-color: rgb(${color[0]}, ${color[1]}, ${color[2]});"></div><div class="${BDFDB.disCNS.userpopoutrolename}" style="text-decoration: line-through !important;">${BDFDB.encodeToHTML(role.name)}</div></div>`;
}
htmlString += `</div>`;
}
if (allowedUsers.length > 0) {
htmlString += `<div class="${BDFDB.disCN.marginbottom4}">Allowed Users:</div><div class="${BDFDB.disCNS.flex + BDFDB.disCN.wrap}">`;
for (let user of allowedUsers) {
let color = user.colorString ? BDFDB.color2COMP(user.colorString) : [255,255,255];
htmlString += `<div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-denieduser" style="border-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6);"><div class="${BDFDB.disCNS.userpopoutrolecircle}" style="background-color: rgb(${color[0]}, ${color[1]}, ${color[2]});"></div><div class="${BDFDB.disCNS.userpopoutrolename}">${BDFDB.encodeToHTML(user.nick ? user.nick : user.name)}</div></div>`;
}
htmlString += `</div>`;
}
if (deniedRoles.length > 0) {
htmlString += `<div class="${BDFDB.disCN.marginbottom4}">Denied Roles:</div><div class="${BDFDB.disCNS.flex + BDFDB.disCN.wrap}">`;
for (let role of deniedRoles) {
let color = role.colorString ? BDFDB.color2COMP(role.colorString) : [255,255,255];
htmlString += `<div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-deniedrole" style="border-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6);"><div class="${BDFDB.disCNS.userpopoutrolecircle}" style="background-color: rgb(${color[0]}, ${color[1]}, ${color[2]});"></div><div class="${BDFDB.disCNS.userpopoutrolename}">${BDFDB.encodeToHTML(role.name)}</div></div>`;
}
htmlString += `</div>`;
}
if (deniedUsers.length > 0) {
htmlString += `<div class="${BDFDB.disCN.marginbottom4}">Denied Users:</div><div class="${BDFDB.disCNS.flex + BDFDB.disCN.wrap}">`;
for (let user of deniedUsers) {
let color = user.colorString ? BDFDB.color2COMP(user.colorString) : [255,255,255];
htmlString += `<div class="${BDFDB.disCNS.userpopoutrole + BDFDB.disCNS.flex + BDFDB.disCNS.aligncenter + BDFDB.disCN.wrap + BDFDB.disCNS.size12 + BDFDB.disCN.weightmedium} SHC-denieduser" style="border-color: rgba(${color[0]}, ${color[1]}, ${color[2]}, 0.6);"><div class="${BDFDB.disCNS.userpopoutrolecircle}" style="background-color: rgb(${color[0]}, ${color[1]}, ${color[2]});"></div><div class="${BDFDB.disCNS.userpopoutrolename}">${BDFDB.encodeToHTML(user.nick ? user.nick : user.name)}</div></div>`;
}
htmlString += `</div>`;
}
if (htmlString) {
var tooltip = BDFDB.createTooltip(htmlString, e.currentTarget, {type:"right", selector:"showhiddenchannels-tooltip", html:true, style:`max-width: ${window.outerWidth/2}px !important;`});
tooltip.style.top = tooltip.style.top.replace("px","") - $(e.currentTarget).css("padding-bottom").replace("px","")/2 + $(e.currentTarget).css("padding-top").replace("px","")/2 + "px";
}
}
appendToChannelList (category) {
var channelList = document.querySelector(BDFDB.dotCNS.channels + BDFDB.dotCN.scroller);
if (channelList && category) channelList.insertBefore(category,channelList.lastChild);
}
}

View File

@ -0,0 +1,3 @@
# Show Image Details - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ShowImageDetails/ShowImageDetails.plugin.js)
Display the name, size and dimensions of uploaded images (does not include embed images) in the chat as an header or as a tooltip.

View File

@ -0,0 +1,189 @@
//META{"name":"ShowImageDetails"}*//
class ShowImageDetails {
initConstructor () {
this.css = `
.image-details .image-details-size {
margin: 0 10px;
}
.image-details-tooltip {
max-width: 500px;
}
.image-details-tooltip .image-details-tooltip-size {
margin: 10px 0;
}
`;
this.updateDetails = false;
this.defaults = {
settings: {
showOnHover: {value:false, description:"Show the details as Tooltip instead:"}
}
};
}
getName () {return "ShowImageDetails";}
getDescription () {return "Display the name, size and dimensions of uploaded images (does not include embed images) in the chat as an header or as a tooltip.";}
getVersion () {return "1.0.7";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && (node.querySelector(BDFDB.dotCN.message) || node.classList.contains(BDFDB.disCN.message))) {
this.addDetails(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver",instance:observer}, {childList:true, subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.removedNodes) {
change.removedNodes.forEach((node) => {
if (node && $(node).attr("layer-id") == "user-settings" && this.updateDetails) {
document.querySelectorAll(".image-details-added").forEach(image => {this.resetImage(image);});
this.addDetails(document);
this.updateDetails = false;
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
this.addDetails(document);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
document.querySelectorAll(".image-details-added").forEach(image => {this.resetImage(image);});
BDFDB.unloadMessage(this);
}
}
onSwitch () {
if (typeof BDFDB === "object") {
this.addDetails(document);
BDFDB.addObserver(this, BDFDB.dotCN.messages, {name:"chatWindowObserver"}, {childList:true, subtree:true});
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
this.updateDetails = true;
}
addDetails (container) {
let scroller = document.querySelector(BDFDB.dotCNS.chat + BDFDB.dotCN.messages);
if (!container || typeof container.querySelectorAll != "function" || !scroller) return;
var settings = BDFDB.getAllData(this, "settings");
container.querySelectorAll(BDFDB.dotCN.messageaccessory + " > " + BDFDB.dotCN.imagewrapper).forEach(image => {
var data = this.getImageData(image);
if (data) {
image.classList.add("image-details-added");
if (!settings.showOnHover) {
$(`<div class="image-details-wrapper"><div class="image-details"><a class="image-details-link" title="${data.url}" href="${data.url}" target="_blank" rel="noreferrer noopener">${data.filename}</a><label class="image-details-size ${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">${BDFDB.formatBytes(data.size)}</label><label class="image-details-dimensions ${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.modedefault + BDFDB.disCN.primary}">${data.width}x${data.height}px</label></div></div>`).insertBefore(image).append(image);
scroller.scrollTop += image.parentElement.getBoundingClientRect().height - image.getBoundingClientRect().height;
}
else {
$(image).on("mouseenter." + this.getName(), () => {
BDFDB.createTooltip(`<div class="image-details-tooltip-name">${data.filename}</div><div class="image-details-tooltip-size">${BDFDB.formatBytes(data.size)}</div><div class="image-details-tooltip-dimensions">${data.width}x${data.height}px</div>`, image, {type:"right", html:true, selector:"image-details-tooltip"});
});
}
}
});
}
resetImage (image) {
image.classList.remove("image-details-added");
$(image).off("." + this.getName());
var wrapper = image.parentElement;
if (wrapper.classList.contains("image-details-wrapper")) {
wrapper.parentElement.insertBefore(image, wrapper);
wrapper.remove();
}
}
getImageData (attachment) {
var messageInfo = BDFDB.getKeyInformation({"node":attachment,"key":"message","up":true,"time":1000});
if (messageInfo) {
var message = null, temp = attachment;
while (message == null || temp.parentElement) {
temp = temp.parentElement;
if (temp.classList && temp.classList.contains(BDFDB.disCN.message)) message = temp;
}
if (message) {
var pos = $(message).find(BDFDB.dotCN.imagewrapper).index(attachment);
var info = messageInfo.attachments;
if (info && pos > -1) info = info[pos];
return info;
}
}
}
}

View File

@ -0,0 +1,3 @@
# Spell Check - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SpellCheck/SpellCheck.plugin.js)
Adds a spellcheck to all textareas

View File

@ -0,0 +1,622 @@
//META{"name":"SpellCheck"}*//
class SpellCheck {
initConstructor () {
this.languages = {};
this.langDictionary = [];
this.dictionary = [];
this.spellCheckContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitemgroup}">
<div class="${BDFDB.disCN.contextmenuitem} similarwords-item ${BDFDB.disCN.contextmenuitemsubmenu}">
<span>REPLACE_context_similarwords_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
<div class="${BDFDB.disCN.contextmenuitem} spellcheck-item">
<span>REPLACE_context_spellcheck_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.similarWordsContextSubMenuMarkup =
`<div class="${BDFDB.disCN.contextmenu} spellcheck-submenu">
<div class="${BDFDB.disCN.contextmenuitem} nosimilars-item">
<span>REPLACE_similarwordssubmenu_none_text</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>
</div>`;
this.spellCheckLayerMarkup =
`<div class="spellcheck-overlay" style="position:absolute !important; pointer-events:none !important; background:transparent !important; color:transparent !important; text-shadow:none !important;"></div>`;
this.css =
`.spellcheck-overlay {
display: inline-block;
font-family: Whitney,Helvetica Neue,Helvetica,Arial,sans-serif;
white-space: pre-wrap !important;
word-wrap: break-word !important;
overflow-x: hidden !important;
overflow-y: scroll !important;
}
.spellcheck-overlay::-webkit-scrollbar,
.spellcheck-overlay::-webkit-scrollbar-button,
.spellcheck-overlay::-webkit-scrollbar-track,
.spellcheck-overlay::-webkit-scrollbar-track-piece,
.spellcheck-overlay::-webkit-scrollbar-thumb,
.spellcheck-overlay::-webkit-scrollbar-corner,
.spellcheck-overlay::-webkit-resizer {
visibility: hidden !important;
}
.spellcheck-overlay .spelling-error {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAADCAYAAABbNsX4AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAACNJREFUeNpi+M/A8P////8McMzAgGAg0ygqYGwAAAAA//8DAOGVJ9llMWQlAAAAAElFTkSuQmCC');
background-repeat: repeat-x;
background-position: bottom;
}`;
this.defaults = {
settings: {
disableDiscordSpellcheck: {value:true, description:"Disable Discord's internal Spellcheck:"}
},
choices: {
dictionaryLanguage: {value:"en", description:"Dictionay Language:"}
},
amounts: {
maxSimilarAmount: {value:6, description:"Maximal Amount of suggested Words:"}
}
};
}
getName () {return "SpellCheck";}
getDescription () {return "Adds a spellcheck to all textareas. Select a word and rightclick it to add it to your dictionary.";}
getVersion () {return "1.2.8";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settings = BDFDB.getAllData(this, "settings");
var choices = BDFDB.getAllData(this, "choices");
var amounts = BDFDB.getAllData(this, "amounts");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}"${settings[key] ? " checked" : ""}></div></div>`;
}
for (let key in choices) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 50%;">${this.defaults.choices[key].description}</h3><div class="${BDFDB.disCN.selectwrap}" style="flex: 1 1 auto"><div class="${BDFDB.disCNS.select + BDFDB.disCNS.selectsingle + BDFDB.disCN.selecthasvalue}" type="${key}" value="${choices[key]}"><div class="${BDFDB.disCN.selectcontrol}"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectvalue}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="padding:0;">${this.languages[choices[key]].name}</div></div><span class="${BDFDB.disCN.selectarrowzone}"><span class="${BDFDB.disCN.selectarrow}"></span></span></div></div></div></div>`;
}
for (let key in amounts) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 50%; line-height: 38px;">${this.defaults.amounts[key].description}</h3><div class="${BDFDB.disCN.inputwrapper} inputNumberWrapper ${BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn}" style="flex: 1 1 auto;"><span class="numberinput-buttons-zone"><span class="numberinput-button-up"></span><span class="numberinput-button-down"></span></span><input type="number" min="0" option="${key}" value="${amounts[key]}" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} amountInput"></div></div>`;
}
var ownDictionary = BDFDB.loadData(choices.dictionaryLanguage, this, "owndics") || [];
settingshtml += `<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Your own Dictionary:</h3><div class="DevilBro-settings-inner-list word-list ${BDFDB.disCN.marginbottom8}">`;
for (let word of ownDictionary) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryword">${word}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", BDFDB.dotCN.switchinner, () => {this.updateSettings(settingspanel);})
.on("click", BDFDB.dotCN.selectcontrol, (e) => {this.openDropdownMenu(settingspanel, e);})
.on("click", ".remove-word", (e) => {this.removeFromOwnDictionary(e);})
.on("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;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"messageContextObserver",instance:observer}, {childList: true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.tagName && node.querySelector(BDFDB.dotCN.textareainner + ":not(" + BDFDB.dotCN.textareainnerdisabled + ")")) {
this.addSpellCheck(node.querySelector(BDFDB.dotCN.textarea));
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"textareaObserver",instance:observer}, {childList: true, subtree:true});
document.querySelectorAll(BDFDB.dotCN.textarea).forEach(textarea => {this.addSpellCheck(textarea);});
this.languages = Object.assign({},BDFDB.languages);
this.languages = BDFDB.filterObject(this.languages , (lang) => {return lang.dic == true ? lang : null});
this.setDictionary(BDFDB.getData("dictionaryLanguage", this, "choices"));
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
$(".spellcheck-overlay").remove();
this.killLanguageToast();
BDFDB.unloadMessage(this);
}
}
// begin of own functions
changeLanguageStrings () {
this.spellCheckContextEntryMarkup = this.spellCheckContextEntryMarkup.replace("REPLACE_context_spellcheck_text", this.labels.context_spellcheck_text);
this.spellCheckContextEntryMarkup = this.spellCheckContextEntryMarkup.replace("REPLACE_context_similarwords_text", this.labels.context_similarwords_text);
this.similarWordsContextSubMenuMarkup = this.similarWordsContextSubMenuMarkup.replace("REPLACE_similarwordssubmenu_none_text", this.labels.similarwordssubmenu_none_text);
}
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement || context.querySelector(".spellcheck-item")) return;
var word = window.getSelection().toString();
if (word && BDFDB.getKeyInformation({"node":context, "key":"handleCutItem"}) && this.isWordNotInDictionary(word)) {
var group = $(this.spellCheckContextEntryMarkup);
$(context).append(group)
.on("click", ".spellcheck-item", (e) => {
$(context).hide();
this.addToOwnDictionary(word);
})
.on("mouseenter", ".similarwords-item", (e) => {
this.createContextSubMenu(word, e, context);
});
BDFDB.updateContextPosition(context);
}
}
createContextSubMenu (word, e, context) {
var similarWordsContextSubMenu = $(this.similarWordsContextSubMenuMarkup);
var similarWords = this.getSimilarWords(word.toLowerCase().trim());
if (similarWords.length > 0) {
similarWordsContextSubMenu.find(".nosimilars-item").remove();
for (let foundWord of similarWords.sort()) {
similarWordsContextSubMenu.append(`<div value="${foundWord}" class="${BDFDB.disCN.contextmenuitem} similarword-item"><span>${foundWord}</span><div class="${BDFDB.disCN.contextmenuhint}"></div></div>`);
}
}
var textarea = window.getSelection().getRangeAt(0).startContainer.querySelector("textarea");
similarWordsContextSubMenu
.on("click", ".similarword-item", (e) => {
$(context).hide();
this.replaceWord(textarea, word, e.currentTarget.getAttribute("value"));
});
BDFDB.appendSubMenu(e.currentTarget, similarWordsContextSubMenu);
}
replaceWord (textarea, word, replacement) {
textarea.focus();
textarea.selectionStart = 0;
textarea.selectionEnd = textarea.value.length;
if (document.activeElement == textarea) {
var firstLetter = word.charAt(0);
var isCapitalised = firstLetter.toUpperCase() == firstLetter && firstLetter.toLowerCase() != firstLetter;
replacement = isCapitalised ? replacement.charAt(0).toUpperCase() + replacement.slice(1) : replacement;
document.execCommand("insertText", false, textarea.value.replace(new RegExp(word.trim(), "i"), replacement));
$(textarea).trigger("keyup");
}
}
addToOwnDictionary (word) {
word = word.split(" ")[0].split("\n")[0].split("\r")[0].split("\t")[0];
if (word) {
var wordlow = word.toLowerCase();
var lang = BDFDB.getData("dictionaryLanguage", this, "choices");
var ownDictionary = BDFDB.loadData(lang, this, "owndics") || [];
if (!ownDictionary.includes(wordlow)) {
ownDictionary.push(wordlow);
BDFDB.saveData(lang, ownDictionary, this, "owndics");
var message = this.labels.toast_wordadd_text ?
this.labels.toast_wordadd_text.replace("${word}", word).replace("${dicname}", this.languages[lang].name) : "";
BDFDB.showToast(message, {type:"success"});
this.dictionary = this.langDictionary.concat(ownDictionary);
}
}
}
removeFromOwnDictionary (e) {
var entry = e.currentTarget.parentElement;
var word = entry.querySelector(".entryword").textContent;
entry.remove();
var lang = BDFDB.getData("dictionaryLanguage", this, "choices");
var ownDictionary = BDFDB.loadData(lang, this, "owndics") || [];
BDFDB.removeFromArray(ownDictionary, word);
BDFDB.saveData(lang, ownDictionary, this, "owndics");
this.dictionary = this.langDictionary.concat(ownDictionary);
}
openDropdownMenu (settingspanel, e) {
var selectControl = e.currentTarget;
var selectWrap = selectControl.parentElement;
if (selectWrap.classList.contains(BDFDB.disCN.selectisopen)) return;
selectWrap.classList.add(BDFDB.disCN.selectisopen);
$("li").has(selectWrap).css("overflow", "visible");
var type = selectWrap.getAttribute("type");
var selectMenu = this.createDropdownMenu(selectWrap.getAttribute("value"), type);
selectWrap.appendChild(selectMenu);
$(selectMenu).on("mousedown." + this.getName(), BDFDB.dotCN.selectoption, (e2) => {
var language = e2.currentTarget.getAttribute("value");
selectWrap.setAttribute("value", language);
selectControl.querySelector(BDFDB.dotCN.title).innerText = this.languages[language].name;
this.setDictionary(language);
BDFDB.saveData(type, language, this, "choices");
var listcontainer = settingspanel.querySelector(".word-list");
if (listcontainer) {
var ownDictionary = BDFDB.loadData(language, this, "owndics") || [];
var containerhtml = ``;
for (let word of ownDictionary) {
containerhtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryword">${word}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-word"></div></div>`;
}
listcontainer.innerHTML = containerhtml;
}
});
$(document).on("mousedown.select" + this.getName(), (e2) => {
if (e2.target.parentElement == selectMenu) return;
$(document).off("mousedown.select" + this.getName());
selectMenu.remove();
$("li").has(selectWrap).css("overflow", "auto");
setTimeout(() => {selectWrap.classList.remove(BDFDB.disCN.selectisopen);},100);
});
}
createDropdownMenu (choice, type) {
var menuhtml = `<div class="${BDFDB.disCN.selectmenuouter}"><div class="${BDFDB.disCN.selectmenu}">`;
for (var key in this.languages) {
var isSelected = key == choice ? ` ${BDFDB.disCN.selectselected}` : ``;
menuhtml += `<div value="${key}" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignbaseline + BDFDB.disCNS.nowrap + BDFDB.disCN.selectoption + isSelected}" style="flex: 1 1 auto; display:flex;"><div class="${BDFDB.disCNS.title + BDFDB.disCNS.medium + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.primary + BDFDB.disCN.weightnormal}" style="flex: 1 1 42%;">${this.languages[key].name}</div></div>`
}
menuhtml += `</div></div>`;
return $(menuhtml)[0];
}
addSpellCheck (textarea) {
if (!textarea) return;
var textareaWrap = textarea.parentElement;
if (textareaWrap && !textareaWrap.querySelector(".spellcheck-overlay")) {
var textareaInstance = BDFDB.getOwnerInstance({"node":textarea, "props":["handlePaste","saveCurrentText"], "up":true});
if (textareaInstance) {
var wrapper = $(BDFDB.dotCN.textareawrapall).has(textarea)[0];
var updateSpellcheck = () => {
$(spellcheck)
.css("visibility", "hidden")
.html(this.spellCheckText(textarea.value))
.css("left", textarea.getBoundingClientRect().left - wrapper.getBoundingClientRect().left)
.css("margin", $(textarea).css("margin"))
.css("padding", $(textarea).css("padding"))
.css("width", parseInt($(textarea).css("width")) + (parseInt($(textarea).css("height")) >= parseInt($(textarea).css("max-height")) ? 0 : 10))
.css("height", $(textarea).css("height"))
.scrollTop(textarea.scrollTop)
.css("visibility", "visible");
}
var spellcheck = $(this.spellCheckLayerMarkup)[0];
textarea.classList.forEach(classname => {spellcheck.classList.add(classname);});
textarea.setAttribute("spellcheck", !BDFDB.getData("disableDiscordSpellcheck", this, "settings"));
$(spellcheck).appendTo(textareaWrap)
updateSpellcheck();
$(textarea)
.off("keyup." + this.getName()).off("scroll." + this.getName())
.on("keyup." + this.getName(), (e) => {
clearTimeout(textarea.spellchecktimeout);
textarea.spellchecktimeout = setTimeout(() => {updateSpellcheck();},100);
})
.on("scroll." + this.getName(), (e) => {
$(spellcheck).scrollTop(textarea.scrollTop);
});
}
}
}
setDictionary (lang) {
this.dictionary = BDFDB.loadData(lang, this, "owndics") || [];
this.killLanguageToast();
this.languageToast = BDFDB.showToast("Grabbing dictionary (" + this.languages[lang].name + "). Please wait", {timeout:0});
this.languageToast.interval = setInterval(() => {
this.languageToast.textContent = this.languageToast.textContent.indexOf(".....") > -1 ? "Grabbing dictionary (" + this.languages[lang].name + "). Please wait" : this.languageToast.textContent + ".";
},500);
this.languageToast.lang = lang
require("request")("https://mwittrien.github.io/BetterDiscordAddons/Plugins/SpellCheck/dic/" + lang + ".dic", (error, response, result) => {
if (error || (response && result.toLowerCase().indexOf("<!doctype html>") > -1)) {
this.killLanguageToast();
BDFDB.showToast("Failed to grab dictionary (" + this.languages[lang].name + ").", {type: "error"});
}
else if (response && this.languageToast.lang == lang) {
this.langDictionary = result.split("\n");
this.dictionary = this.langDictionary.concat(this.dictionary);
this.dictionary = this.dictionary.map(word => word.toLowerCase());
this.killLanguageToast();
BDFDB.showToast("Successfully grabbed dictionary (" + this.languages[lang].name + ").", {type: "success"});
}
});
}
killLanguageToast () {
if (this.languageToast && typeof this.languageToast.close == "function") {
clearInterval(this.languageToast.interval);
this.languageToast.close();
}
}
spellCheckText (string) {
var htmlString = [];
string.replace(/[\n]/g, "\n ").split(" ").forEach((word, i) => {
htmlString.push(`<label class="${this.isWordNotInDictionary(word) ? "spelling-error" : "nospelling-error"}" style="color:transparent !important; text-shadow:none !important;">${BDFDB.encodeToHTML(word)}</label>`);
});
return htmlString.join(" ");
}
isWordNotInDictionary (word) {
var wordLow = word.toLowerCase();
var wordWithoutSymbols = wordLow.replace(/[0-9\µ\@\$\£\€\¥\¢\²\³\>\<\|\,\;\.\:\_\#\+\*\~\?\¿\\\´\`\}\=\]\)\[\(\{\/\&\%\§\"\!\¡\^\°\n\t\r]/g, "");
return (wordLow.indexOf("http://") != 0 && wordLow.indexOf("https://") != 0 && wordWithoutSymbols && Array.isArray(this.dictionary) && this.dictionary.length > 0 && !this.dictionary.includes(wordLow) && !this.dictionary.includes(wordWithoutSymbols));
}
getSimilarWords (word) {
var maxAmount = BDFDB.getData("maxSimilarAmount", this, "amounts"), similarWords = [];
if (maxAmount > 0) {
var sameLetterDic = this.dictionary.filter(string => string.indexOf(word.toLowerCase().charAt(0)) == 0 ? string : null);
var similarities = {};
for (let string of sameLetterDic) {
let value = this.wordSimilarity(word, string);
if (!similarities[value]) similarities[value] = [];
similarities[value].push(string);
}
var amount = 0;
for (let value of Object.keys(similarities).sort().reverse()) {
for (let similarWord of similarities[value]) {
if (amount < maxAmount && !similarWords.includes(similarWord)) {
similarWords.push(similarWord);
amount++;
}
if (amount >= maxAmount) break;
}
if (amount >= maxAmount) break;
}
}
return similarWords;
}
wordSimilarity (a, b) {
var temp;
if (a.length === 0 || b.length === 0 || a.length - b.length > 3 || b.length - a.length > 3) { return 0; }
if (a.length > b.length) {
temp = a;
a = b;
b = temp;
}
let result = 0;
let row = [...Array(a.length + 1).keys()];
for (let i = 1; i <= b.length; i++) {
result = i;
for (let j = 1; j <= a.length; j++) {
temp = row[j - 1];
row[j - 1] = result;
result = b[i - 1] === a[j - 1] ? temp : Math.min(temp + 1, Math.min(result + 1, row[j] + 1));
}
}
return (b.length - result) / b.length;
}
setLabelsByLanguage () {
switch (BDFDB.getDiscordLanguage().id) {
case "hr": //croatian
return {
context_spellcheck_text: "Dodaj u rječnik",
context_similarwords_text: "Pretraga sličnih riječi...",
similarwordssubmenu_none_text: "Nema sličnih riječi",
toast_wordadd_text: "Riječ ${word} dodana je u rječnik ${dicname}."
};
case "da": //danish
return {
context_spellcheck_text: "Tilføj til ordbog",
context_similarwords_text: "Søg lignende ord...",
similarwordssubmenu_none_text: "Ingen lignende ord",
toast_wordadd_text: "Ord ${word} tilføjet til ordbog ${dicname}."
};
case "de": //german
return {
context_spellcheck_text: "Zum Wörterbuch hinzufügen",
context_similarwords_text: "Ähnliche Wörter suchen...",
similarwordssubmenu_none_text: "Keine ähnlichen Wörter",
toast_wordadd_text: "Wort ${word} wurde zum Wörterbuch ${dicname} hinzugefügt."
};
case "es": //spanish
return {
context_spellcheck_text: "Agregar al diccionario",
context_similarwords_text: "Buscar palabras similares...",
similarwordssubmenu_none_text: "No hay palabras similares",
toast_wordadd_text: "Se agregó la palabra ${word} al diccionario ${dicname}."
};
case "fr": //french
return {
context_spellcheck_text: "Ajouter au dictionnaire",
context_similarwords_text: "Chercher des mots similaires...",
similarwordssubmenu_none_text: "Pas de mots similaires",
toast_wordadd_text: "Le mot ${word} a été ajouté au dictionnaire ${dicname}."
};
case "it": //italian
return {
context_spellcheck_text: "Aggiungi al dizionario",
context_similarwords_text: "Cerca parole simili...",
similarwordssubmenu_none_text: "Nessuna parola simile",
toast_wordadd_text: "Parola ${word} aggiunta al dizionario ${dicname}."
};
case "nl": //dutch
return {
context_spellcheck_text: "Toevoegen aan woordenboek",
context_similarwords_text: "Zoek vergelijkbare woorden...",
similarwordssubmenu_none_text: "Geen vergelijkbare woorden",
toast_wordadd_text: "Word ${word} toegevoegd aan woordenboek ${dicname}."
};
case "no": //norwegian
return {
context_spellcheck_text: "Legg til i ordbok",
context_similarwords_text: "Søk lignende ord...",
similarwordssubmenu_none_text: "Ingen lignende ord",
toast_wordadd_text: "Ord ${word} legges til ordbok ${dicname}."
};
case "pl": //polish
return {
context_spellcheck_text: "Dodaj do słownika",
context_similarwords_text: "Wyszukaj podobne słowa...",
similarwordssubmenu_none_text: "Brak podobnych słów",
toast_wordadd_text: "Słowo ${word} dodane do słownika ${dicname}."
};
case "pt-BR": //portuguese (brazil)
return {
context_spellcheck_text: "Adicionar ao dicionário",
context_similarwords_text: "Pesquisar palavras similares...",
similarwordssubmenu_none_text: "Sem palavras semelhantes",
toast_wordadd_text: "Palavra ${word} adicionado ao dicionário ${dicname}."
};
case "fi": //finnish
return {
context_spellcheck_text: "Lisää sanakirjaan",
context_similarwords_text: "Hae samankaltaisia sanoja...",
similarwordssubmenu_none_text: "Ei vastaavia sanoja",
toast_wordadd_text: "Sana ${word} lisättiin sanakirjaan ${dicname}."
};
case "sv": //swedish
return {
context_spellcheck_text: "Lägg till i ordbok",
context_similarwords_text: "Sök liknande ord...",
similarwordssubmenu_none_text: "Inga liknande ord",
toast_wordadd_text: "Ord ${word} läggs till ordbok ${dicname}."
};
case "tr": //turkish
return {
context_spellcheck_text: "Sözlükye Ekle",
context_similarwords_text: "Benzer Kelimeler Ara...",
similarwordssubmenu_none_text: "Benzer kelime yoktur",
toast_wordadd_text: "Sözcük ${word} sözlük ${dicname}'ye eklendi."
};
case "cs": //czech
return {
context_spellcheck_text: "Přidat do slovníku",
context_similarwords_text: "Hledat podobné výrazy...",
similarwordssubmenu_none_text: "Žádné podobné slova",
toast_wordadd_text: "Slovo ${word} bylo přidáno do slovníku ${dicname}."
};
case "bg": //bulgarian
return {
context_spellcheck_text: "Добави в речника",
context_similarwords_text: "Търсене на подобни думи...",
similarwordssubmenu_none_text: "Няма подобни думи",
toast_wordadd_text: "Думата ${word} е добавена към речника ${dicname}."
};
case "ru": //russian
return {
context_spellcheck_text: "Добавить в словарь",
context_similarwords_text: "Поиск похожих слов...",
similarwordssubmenu_none_text: "Нет похожих слов",
toast_wordadd_text: "Слово ${word} добавлено в словарь ${dicname}."
};
case "uk": //ukrainian
return {
context_spellcheck_text: "Додати до словника",
context_similarwords_text: "Шукати схожі слова...",
similarwordssubmenu_none_text: "Немає подібних слів",
toast_wordadd_text: "Словник ${word} додається до словника ${dicname}."
};
case "ja": //japanese
return {
context_spellcheck_text: "辞書に追加",
context_similarwords_text: "類似のワードを検索...",
similarwordssubmenu_none_text: "類似の単語はありません",
toast_wordadd_text: "単語 ${word} が辞書 ${dicname} に追加されました。"
};
case "zh-TW": //chinese (traditional)
return {
context_spellcheck_text: "添加到詞典",
context_similarwords_text: "搜索類似的單詞...",
similarwordssubmenu_none_text: "沒有類似的詞",
toast_wordadd_text: "單詞 ${word} 添加到字典 ${dicname}。"
};
case "ko": //korean
return {
context_spellcheck_text: "사전에 추가",
context_similarwords_text: "비슷한 단어 검색...",
similarwordssubmenu_none_text: "유사한 단어 없음",
toast_wordadd_text: "단어 ${word} 사전 ${dicname} 에 추가되었습니다."
};
default: //default: english
return {
context_spellcheck_text: "Add to Dictionay",
context_similarwords_text: "Search similar Words...",
similarwordssubmenu_none_text: "No similar Words",
toast_wordadd_text: "Word ${word} added to dictionary ${dicname}."
};
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
# Stalker Notifications - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/StalkerNotifications/StalkerNotifications.plugin.js)
Lets you observe the status of people that aren't your friends.

View File

@ -0,0 +1,407 @@
//META{"name":"StalkerNotifications"}*//
class StalkerNotifications {
initConstructor () {
this.stalkerOnlineList = {};
this.checkInterval = null;
this.timeLog = [];
this.timeLogModalMarkup =
`<span class="stalkernotifications-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizemedium}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset}">User LogIn/-Out Timelog</h4>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline}">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} entries">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontalreverse + BDFDB.disCNS.horizontalreverse2 + BDFDB.disCNS.directionrowreverse + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalfooter}">
<button type="button" class="btn-ok ${BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}">
<div class="${BDFDB.disCN.buttoncontents}"></div>
</button>
</div>
</div>
</div>
</div>
</span>`;
this.logEntryMarkup =
`<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCN.marginbottom4} entry" style="flex: 1 1 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCNS.flexchild + BDFDB.disCNS.overflowellipsis} log-time" style="flex: 0 0 auto;"></h3>
<div class="log-avatar"></div>
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCNS.flexchild + BDFDB.disCNS.overflowellipsis} log-description" style="flex: 1 1 auto;"></h3>
</div>`;
this.dividerMarkup = `<div class="${BDFDB.disCNS.modaldivider + BDFDB.disCN.modaldividerdefault}"></div>`;
this.css = `
.guilds > .friends-online {
cursor: pointer;
}
.stalkernotifications-modal .log-time {
width: 110px;
}
.stalkernotifications-modal .log-avatar {
width: 35px;
height: 35px;
background-size: cover;
background-position: center;
border-radius: 50%;
}
.StalkerNotifications-settings .avatar-list {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.StalkerNotifications-settings .type-toast, .StalkerNotifications-settings .type-desktop {
border-radius: 3px;
padding: 0 3px;
}
.StalkerNotifications-settings .type-toast {
background-color: #7289DA;
}
.StalkerNotifications-settings .type-desktop {
background-color: #43B581;
}
.StalkerNotifications-settings .settings-avatar.desktop {
border-color: #43B581;
}
.StalkerNotifications-settings .settings-avatar {
margin: 5px;
width: 50px;
height: 50px;
background-size: cover;
background-position: center;
border: 5px solid #7289DA;
border-radius: 50%;
box-sizing: border-box;
cursor: pointer;
}
.StalkerNotifications-settings .settings-avatar.desktop {
border-color: #43B581;
}
.StalkerNotifications-settings .settings-avatar.disabled {
border-color: #36393F;
filter: grayscale(100%) brightness(50%);
}
.StalkerNotifications-settings .settings-avatar ${BDFDB.dotCN.hovercardbutton} {
position: relative;
top: -10px;
right: -25px;
}
.StalkerNotifications-settings .settings-avatar:not(:hover) ${BDFDB.dotCN.hovercardbutton} {
opacity: 1;
}
.StalkerNotifications-settings .disable-all {
color: white;
background-color: #36393F;
}`;
this.defaults = {
settings: {
muteOnDND: {value:false, description:"Do not notify me when I am DnD:"},
onlyOnOnline: {value:false, description:"Only notify me when a User logs in:"},
openOnClick: {value:false, description:"Open the DM when you click a Notification:"}
},
amounts: {
checkInterval: {value:10, description:"Check Users every X seconds:"}
}
};
}
getName () {return "StalkerNotifications";}
getDescription () {return "Lets you observe the status of people that aren't your friends.";}
getVersion () {return "1.0.5";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var amounts = BDFDB.getAllData(this, "amounts");
var settings = BDFDB.getAllData(this, "settings");
var users = BDFDB.loadAllData(this, "users");
var notificationsound = BDFDB.loadAllData(this, "notificationsound");
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 50%; line-height: 38px;">Add User:</h3><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCN.directioncolumn}" style="flex: 1 1 auto;"><input type="text" value="" placeholder="UserID" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-userid"></div><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-adduser" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div>`;
for (let key in amounts) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCN.flexchild}" style="flex: 0 0 50%;">${this.defaults.amounts[key].description}</h3><div class="${BDFDB.disCN.inputwrapper} inputNumberWrapper ${BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn}" style="flex: 1 1 auto;"><span class="numberinput-buttons-zone"><span class="numberinput-button-up"></span><span class="numberinput-button-down"></span></span><input type="number" min="0" option="${key}" value="${amounts[key]}" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} amountInput"></div></div>`;
}
for (let key in settings) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">${this.defaults.settings[key].description}</h3><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" value="${key}" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} settings-checkbox"${settings[key] ? " checked" : ""}></div></div>`;
}
if ("Notification" in window) settingshtml += `<div class="${BDFDB.disCNS.flexchild + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h5 class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 1 1 auto;">Desktop Notification Sound:</h5><h5 class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.h5 + BDFDB.disCNS.title + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.h5defaultmargin}" style="flex: 0 0 auto;">Mute:</h5><div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;"><input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} mute-checkbox"${notificationsound.mute ? " checked" : ""}></div></div><div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCN.nowrap}" style="flex: 1 1 auto;"><div class="${BDFDB.disCNS.inputwrapper + BDFDB.disCNS.vertical + BDFDB.disCNS.flex + BDFDB.disCNS.directioncolumn + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;"><input type="text" value="${notificationsound.url ? notificationsound.url : ""}" placeholder="Url or Filepath" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16} songInput"></div><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} file-navigator" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div><input type="file" accept="audio/*,video/*" style="display:none!important;"></button><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-save btn-savesong" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Click on a Icon to toggle <label class="type-toast">Toast</label> Notifications for that User:</h3></div>`;
if ("Notification" in window) settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 1 1 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Rightclick on a Icon to toggle <label class="type-desktop">Desktop</label> Notifications for that User:</h3></div>`;
settingshtml += `<div class="avatar-list ${BDFDB.disCN.marginbottom8}">`;
for (let id in users) {
let user = this.UserUtils.getUser(id);
if (user) settingshtml += this.createSettingsAvatarHtml(user, users[id]);
}
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Batch set Users:</h3><button type="button" do-disable=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} disable-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Disable</div></button><button type="button" do-toast=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} toast-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Toast</div></button>${"Notification" in window ? `<button type="button" do-desktop=true class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorgreen + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} desktop-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Desktop</div></button>` : ``}</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Timelog of LogIns/-Outs:</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-timelog" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Timelog</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".settings-checkbox", () => {this.updateSettings(settingspanel);})
.on("click", ".btn-savesong", () => {this.saveAudio(settingspanel);})
.on("click", ".mute-checkbox", (e) => {
var notificationsound = BDFDB.loadAllData(this, "notificationsound");
notificationsound.mute = e.currentTarget.checked;
BDFDB.saveAllData(notificationsound, this, "notificationsound");
})
.on("mouseenter", ".settings-avatar", (e) => {
let user = this.UserUtils.getUser(e.currentTarget.getAttribute("user-id"));
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
BDFDB.createTooltip(data.name ? data.name : user.username, e.currentTarget, {type:"top"});
})
.on("contextmenu", ".settings-avatar", (e) => {
if (!("Notification" in window)) return;
let desktopoff = !e.currentTarget.classList.contains("desktop");
let id = e.currentTarget.getAttribute("user-id");
e.currentTarget.classList.remove("disabled");
e.currentTarget.classList.toggle("desktop", desktopoff);
BDFDB.saveData(id, {"desktop":desktopoff,"disabled":false}, this, "users");
})
.on("click", ".settings-avatar", (e) => {
if (e.target.classList.contains("remove-user")) return;
let disableoff = !e.currentTarget.classList.contains("disabled");
let id = e.currentTarget.getAttribute("user-id");
e.currentTarget.classList.remove("desktop");
e.currentTarget.classList.toggle("disabled", disableoff);
BDFDB.saveData(id, {"desktop":false,"disabled":disableoff}, this, "users");
})
.on("click", ".disable-all, .toast-all, .desktop-all", (e) => {
let button = e.currentTarget;
let disableon = button.getAttribute("do-disable");
let desktopon = button.getAttribute("do-desktop");
let users = BDFDB.loadAllData(this, "users");
settingspanel.querySelectorAll(".settings-avatar").forEach(avatar => {
let id = avatar.getAttribute("user-id");
avatar.classList.toggle("disabled", disableon);
avatar.classList.toggle("desktop", desktopon);
users[id].desktop = desktopon ? true : false;
users[id].disabled = disableon ? true : false;
});
BDFDB.saveAllData(users, this, "users");
})
.on("click", ".btn-adduser", (e) => {
let idinput = settingspanel.querySelector("#input-userid");
let user = this.UserUtils.getUser(idinput.value);
if (user) {
idinput.value = "";
BDFDB.saveData(user.id, {desktop:false,disabled:false}, this, "users");
settingspanel.querySelectorAll(".settings-avatar").forEach(entry => {entry.remove();});
let listhtml = `<div class="avatar-list ${BDFDB.disCN.marginbottom8}">`;
let users = BDFDB.loadAllData(this, "users");
for (let id in users) {
let user = this.UserUtils.getUser(id);
if (user) listhtml += this.createSettingsAvatarHtml(user, users[id]);
}
listhtml += `</div>`;
settingspanel.querySelector(".avatar-list").innerHTML = listhtml;
}
else BDFDB.showToast("Please enter a valid UserID.",{type:"error"});
})
.on("click", ".remove-user", (e) => {
BDFDB.removeData(e.currentTarget.parentElement.getAttribute("user-id"), this, "users");
settingspanel.querySelectorAll(".settings-avatar").forEach(entry => {entry.remove();});
let listhtml = `<div class="avatar-list ${BDFDB.disCN.marginbottom8}">`;
let users = BDFDB.loadAllData(this, "users");
for (let id in users) {
let user = this.UserUtils.getUser(id);
if (user) listhtml += this.createSettingsAvatarHtml(user, users[id]);
}
listhtml += `</div>`;
settingspanel.querySelector(".avatar-list").innerHTML = listhtml;
})
.on("click", ".btn-timelog", () => {
this.showTimeLog();
})
.on("input", ".amountInput", (e) => {
let input = parseInt(e.currentTarget.value);
if (!isNaN(input) && input > 0) {
BDFDB.saveData(e.currentTarget.getAttribute("option"), input, this, "amounts");
this.startInterval();
}
else e.currentTarget.value = 1;
});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.ChannelUtils = BDFDB.WebModules.findByProperties(["getDMFromUserId"]);
this.ChannelSwitchUtils = BDFDB.WebModules.findByProperties(["selectPrivateChannel"]);
this.UserMetaStore = BDFDB.WebModules.findByProperties(["getStatus", "getOnlineFriendCount"]);
this.UserUtils = BDFDB.WebModules.findByProperties(["getUsers"]);
for (let id in BDFDB.loadAllData(this, "users")) {
this.stalkerOnlineList[id] = this.UserMetaStore.getStatus(id) != "offline";
}
this.startInterval();
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
clearInterval(this.checkInterval);
BDFDB.unloadMessage(this);
}
}
// begin of own functions
updateSettings (settingspanel) {
var settings = {};
for (var input of settingspanel.querySelectorAll(BDFDB.dotCN.switchinner)) {
settings[input.value] = input.checked;
}
BDFDB.saveAllData(settings, this, "settings");
}
createSettingsAvatarHtml (user, settings) {
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
return `<div class="settings-avatar${settings.desktop ? " desktop" : ""}${settings.disabled ? " disabled" : ""}" user-id="${user.id}" style="background-image: url(${data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(user.id))});"><div class="${BDFDB.disCN.hovercardbutton} remove-user"></div></div>`;
}
startInterval () {
clearInterval(this.checkInterval);
this.checkInterval = setInterval(() => {
let settings = BDFDB.getAllData(this, "settings");
let notificationsound = BDFDB.loadAllData(this, "notificationsound");
let users = BDFDB.loadAllData(this, "users");
for (let id in users) {
let online = this.UserMetaStore.getStatus(id) != "offline";
let user = this.UserUtils.getUser(id);
if (user && this.stalkerOnlineList[id] != online && !users[id].disabled) {
this.timeLog.push({user, online, time: new Date()});
if (!(settings.onlyOnOnline && !online) && !(settings.muteOnDND && BDFDB.getUserStatus() == "dnd")) {
let data = BDFDB.loadData(user.id, "EditUsers", "users") || {};
let string = `${BDFDB.encodeToHTML(data.name ? data.name : user.username)} is ${online ? "online" : "offline"}.`;
let avatar = data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(user.id));
let openChannel = () => {
if (settings.openOnClick){
let DMid = this.ChannelUtils.getDMFromUserId(user.id);
if (DMid) {
require("electron").remote.getCurrentWindow().maximize();
this.ChannelSwitchUtils.selectPrivateChannel(DMid);
}
}
};
if (!users[id].desktop) {
let toast = BDFDB.showToast(`<div class="toast-inner"><div class="toast-avatar" style="background-image:url(${avatar});"></div><div>${string}</div></div>`, {html:true, timeout:5000, type:(online ? "success" : null), icon:false});
$(toast).on("click." + this.getName(), openChannel);
}
else {
let notificationsound = BDFDB.loadAllData(this, "notificationsound");
BDFDB.showDesktopNotification(string, {icon:avatar, timeout:5000, click:openChannel, silent:notificationsound.mute, sound:notificationsound.song});
}
}
}
this.stalkerOnlineList[id] = online;
}
},BDFDB.getData("checkInterval", this, "amounts") * 1000);
}
saveAudio (settingspanel) {
var successSavedAudio = (parsedurl, parseddata) => {
if (parsedurl && parseddata) BDFDB.showToast(`Sound was saved successfully.`, {type:"success"});
let notificationsound = BDFDB.loadAllData(this, "notificationsound");
notificationsound.url = parsedurl;
notificationsound.song = parseddata;
BDFDB.saveAllData(notificationsound, this, "notificationsound");
};
var url = settingspanel.querySelector(".songInput").value;
if (url.length == 0) {
BDFDB.showToast(`Sound was set to the default sound.`, {type:"warn"});
successSavedAudio(url, url);
}
else if (url.indexOf("http") == 0) {
require("request")(url, (error, response, result) => {
if (response) {
var type = response.headers["content-type"];
if (type && (type.indexOf("octet-stream") > -1 || type.indexOf("audio") > -1 || type.indexOf("video") > -1)) {
successSavedAudio(url, url);
return;
}
}
BDFDB.showToast("Use a valid direct link to a video or audio source. They usually end on something like .mp3, .mp4 or .wav.", {type:"danger"});
});
}
else {
require("fs").readFile(url, (error, response) => {
if (error) {
BDFDB.showToast("Could not fetch file. Please make sure the file exists.", {type:"danger"});
}
else {
successSavedAudio(url, `data:audio/mpeg;base64,${response.toString("base64")}`);
}
});
}
}
showTimeLog () {
var timeLogModal = $(this.timeLogModalMarkup);
let logs = this.timeLog.slice(0).reverse();
for (let log of logs) {
let entry = $(this.logEntryMarkup);
let divider = $(this.dividerMarkup);
let data = BDFDB.loadData(log.user.id, "EditUsers", "users") || {};
entry.find(".log-time").text(`[${log.time.toLocaleTimeString()}]`);
entry.find(".log-avatar").css("background-image", `url(${data.removeIcon ? "" : (data.url ? data.url : BDFDB.getUserAvatar(log.user.id))})`);
entry.find(".log-description").text(`${data.name ? data.name : log.user.username} is ${log.online ? "online" : "offline"}.`);
timeLogModal.find(".entries").append(entry).append(divider);
}
timeLogModal.find(BDFDB.dotCN.modaldivider + ":last-of-type").remove();
BDFDB.appendModal(timeLogModal);
}
}

View File

@ -0,0 +1,3 @@
# Steam Profile Link - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SteamProfileLink/SteamProfileLink.plugin.js)
Opens a steam profile in steam instead of a browser when clicking the steamlink in a userprofile. With the help of square.

View File

@ -0,0 +1,53 @@
//META{"name":"SteamProfileLink"}*//
class SteamProfileLink {
getName () {return "SteamProfileLink";}
getDescription () {return "Opens any Steam links in Steam instead of your internet browser.";}
getVersion () {return "1.0.3";}
getAuthor () {return "DevilBro";}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
$(document).on("click." + this.getName(), "a[href^='https://steamcommunity.'],a[href^='https://store.steampowered.']", (e) => {
if (require("electron").shell.openExternal("steam://openurl/" + e.currentTarget.href)) {
e.preventDefault();
e.stopImmediatePropagation();
}
});
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
BDFDB.unloadMessage(this);
}
}
}

View File

@ -0,0 +1,3 @@
# Theme Repo - [Download](https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/ThemeRepo/ThemeRepo.plugin.js)
Allows you to preview all themes from the theme repo and download them on the fly. Repo button is in the theme settings.

View File

@ -0,0 +1,950 @@
//META{"name":"ThemeRepo"}*//
class ThemeRepo {
initConstructor () {
this.sortings = {
sort: {
name: "Name",
author: "Author",
version: "Version",
description: "Description",
state: "Update State",
fav: "Favorites"
},
order: {
asc: "Ascending",
desc: "Descending"
}
};
this.loading = false;
this.grabbedThemes = [];
this.foundThemes = [];
this.loadedThemes = {};
this.updateInterval;
this.themeFixerCSS = `#friends, .noChannel-Z1DQK7, .activityFeed-HeiGwL, .lfg-3xoFkI, .app, .layers-3iHuyZ, .layer-3QrUeG, .container-2lgZY8, .content-region, .guilds-wrapper, .search-l1Wz-Q .search-bar, .chat .inner-zqa7da, .search-results-wrap, .search-results-wrap .search-header, .search-results-wrap .search-result-message.hit, .sidebar-region, .ui-standard-sidebar-view, .channels-Ie2l6A, .container-2Thooq {background: rgba(0,0,0,0.3) !important;} .search-results-wrap .search-result-message.hit {box-shadow:none !important;} .titleBar-AC4pGV::after {content:""; position:absolute; z-index:-1; top:0; left:0; right:0; width:100%; height:22px; background: rgba(0,0,0,0.8) !important;} #friends .friends-table, .members-1998pB, .loading-316uYQ, .chat .content, .chat form, .chat, .content .flex-spacer, .messages-wrapper, .typing-2GQL18, .container-PNkimc, .headerBar-UHpsPw, .titleBar-AC4pGV, .titleWrapper-1l0xT9 .title-3qD0b-, .search-results-wrap .search-result::before, .search-results-wrap .search-result::after, .search-results-wrap .channel-name {background: transparent !important;} ::-webkit-scrollbar-thumb {border-color: transparent !important; background: rgba(0,0,0,0.8) !important;} ::-webkit-scrollbar, ::-webkit-scrollbar-track-piece {border-color: transparent !important; background: transparent !important;} ::-webkit-scrollbar-corner {display: none !important;}`;
this.themeRepoButtonMarkup =
`<button class="bd-pfbtn bd-themerepobutton">Theme Repo</button>`;
this.settingsContextEntryMarkup =
`<div class="${BDFDB.disCN.contextmenuitem} themerepo-item">
<span>Theme Repo</span>
<div class="${BDFDB.disCN.contextmenuhint}"></div>
</div>`;
this.frameMarkup =
`<iframe class="discordPreview" src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/DiscordPreview.html"></iframe>`;
this.themeEntryMarkup =
`<li class="themeEntry jiiks">
<div class="bda-left">
<span class="bda-name"></span>
<div class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCN.scrollerthemed}">
<div class="${BDFDB.disCN.scroller} bda-description"></div>
</div>
</div>
<div class="bda-right">
<div class="bda-header">
<svg class="favIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><path fill="none" stroke="black" d="M 19.542, 9.092 c 0.393 -0.383, 0.532 -0.946, 0.362 -1.468 c -0.17 -0.523 -0.613 -0.896 -1.157 -0.975 l -4.837 -0.703 c -0.206 -0.03 -0.384 -0.159 -0.476 -0.346 L 11.273, 1.217 c -0.243 -0.492 -0.736 -0.798 -1.285 -0.798 c -0.549, 0 -1.042, 0.306 -1.284, 0.798 L 6.541, 5.6 c -0.092, 0.187 -0.27, 0.316 -0.476, 0.346 L 1.228, 6.649 c -0.544, 0.079 -0.987, 0.452 -1.157, 0.975 c -0.17, 0.523 -0.031, 1.085, 0.362, 1.468 l 3.5, 3.411 c 0.149, 0.146, 0.218, 0.355, 0.182, 0.56 L 3.29, 17.88 c -0.073, 0.424, 0.038, 0.836, 0.312, 1.162 c 0.426, 0.507, 1.171, 0.661, 1.766, 0.348 l 4.326 -2.274 c 0.181 -0.095, 0.408 -0.094, 0.589, 0 l 4.326, 2.274 c 0.21, 0.111, 0.435, 0.167, 0.666, 0.167 c 0.423, 0, 0.824 -0.188, 1.099 -0.515 c 0.275 -0.325, 0.386 -0.738, 0.312 -1.162 l -0.826 -4.817 c -0.035 -0.205, 0.033 -0.414, 0.182 -0.56 L 19.542, 9.092 z"/></svg>
<svg class="gitIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 7.19, 16.027 c -0.139, 0.026 -0.199, 0.091 -0.182, 0.195 c 0.017, 0.104, 0.095, 0.138, 0.234, 0.104 c 0.139 -0.035, 0.199 -0.095, 0.182 -0.182 C 7.406, 16.049, 7.328, 16.01, 7.19, 16.027 z"/><path d="M 6.45, 16.131 c -0.138, 0 -0.208, 0.047 -0.208, 0.143 c 0, 0.112, 0.074, 0.16, 0.221, 0.143 c 0.138, 0, 0.208 -0.048, 0.208 -0.143 C 6.671, 16.162, 6.597, 16.114, 6.45, 16.131 z"/><path d="M 5.438, 16.092 c -0.035, 0.095, 0.022, 0.16, 0.169, 0.195 c 0.13, 0.052, 0.212, 0.026, 0.247 -0.078 c 0.026 -0.095 -0.03 -0.164 -0.169 -0.208 C 5.554, 15.967, 5.472, 15.996, 5.438, 16.092 z"/><path d="M 18.837, 1.097 C 18.106, 0.366, 17.226, 0, 16.196, 0 H 3.738 C 2.708, 0, 1.828, 0.366, 1.097, 1.097 C 0.366, 1.828, 0, 2.708, 0, 3.738 v 12.459 c 0, 1.03, 0.366, 1.91, 1.097, 2.641 c 0.731, 0.731, 1.612, 1.097, 2.641, 1.097 h 2.907 c 0.19, 0, 0.333 -0.007, 0.428 -0.019 c 0.095 -0.013, 0.19 -0.069, 0.285 -0.169 c 0.095 -0.099, 0.143 -0.244, 0.143 -0.435 c 0 -0.026 -0.002 -0.32 -0.007 -0.883 c -0.004 -0.562 -0.007 -1.008 -0.007 -1.337 l -0.298, 0.052 c -0.19, 0.035 -0.43, 0.05 -0.72, 0.045 c -0.29 -0.004 -0.59 -0.035 -0.902 -0.091 c -0.312 -0.056 -0.601 -0.186 -0.87 -0.389 c -0.268 -0.203 -0.458 -0.469 -0.571 -0.798 l -0.13 -0.299 c -0.086 -0.199 -0.223 -0.419 -0.409 -0.662 c -0.186 -0.242 -0.374 -0.407 -0.564 -0.493 l -0.091 -0.065 c -0.06 -0.043 -0.117 -0.095 -0.169 -0.156 c -0.052 -0.061 -0.091 -0.121 -0.117 -0.182 c -0.026 -0.061 -0.004 -0.11, 0.065 -0.149 c 0.069 -0.039, 0.195 -0.058, 0.376 -0.058 l 0.259, 0.039 c 0.173, 0.035, 0.387, 0.138, 0.642, 0.311 c 0.255, 0.173, 0.465, 0.398, 0.629, 0.675 c 0.199, 0.355, 0.439, 0.625, 0.72, 0.811 c 0.281, 0.186, 0.565, 0.279, 0.85, 0.279 s 0.532 -0.022, 0.74 -0.065 c 0.208 -0.043, 0.402 -0.108, 0.584 -0.195 c 0.078 -0.58, 0.29 -1.025, 0.636 -1.337 c -0.493 -0.052 -0.936 -0.13 -1.33 -0.234 c -0.394 -0.104 -0.8 -0.272 -1.22 -0.506 c -0.42 -0.234 -0.768 -0.523 -1.045 -0.87 c -0.277 -0.346 -0.504 -0.8 -0.681 -1.363 c -0.177 -0.562 -0.266 -1.211 -0.266 -1.947 c 0 -1.047, 0.342 -1.938, 1.025 -2.673 c -0.32 -0.787 -0.29 -1.67, 0.091 -2.647 c 0.251 -0.078, 0.623 -0.019, 1.116, 0.175 c 0.493, 0.195, 0.854, 0.361, 1.084, 0.5 c 0.229, 0.138, 0.413, 0.255, 0.552, 0.35 c 0.805 -0.225, 1.635 -0.337, 2.492 -0.337 c 0.856, 0, 1.687, 0.112, 2.492, 0.337 l 0.493 -0.311 c 0.338 -0.208, 0.735 -0.398, 1.194 -0.571 c 0.459 -0.173, 0.809 -0.221, 1.051 -0.143 c 0.389, 0.978, 0.424, 1.86, 0.104, 2.647 c 0.683, 0.735, 1.025, 1.627, 1.025, 2.673 c 0, 0.735 -0.089, 1.387 -0.266, 1.953 c -0.177, 0.567 -0.406, 1.021 -0.688, 1.363 c -0.281, 0.342 -0.632, 0.629 -1.051, 0.863 c -0.42, 0.234 -0.826, 0.402 -1.22, 0.506 c -0.394, 0.104 -0.837, 0.182 -1.33, 0.234 c 0.45, 0.389, 0.675, 1.003, 0.675, 1.843 v 3.102 c 0, 0.147, 0.021, 0.266, 0.065, 0.357 c 0.044, 0.091, 0.113, 0.153, 0.208, 0.188 c 0.096, 0.035, 0.18, 0.056, 0.253, 0.065 c 0.074, 0.009, 0.18, 0.013, 0.318, 0.013 h 2.907 c 1.029, 0, 1.91 -0.366, 2.641 -1.097 c 0.731 -0.731, 1.097 -1.612, 1.097 -2.641 V 3.738 C 19.933, 2.708, 19.568, 1.827, 18.837, 1.097 z"/><path d="M 3.945, 14.509 c -0.06, 0.043 -0.052, 0.112, 0.026, 0.208 c 0.087, 0.086, 0.156, 0.1, 0.208, 0.039 c 0.061 -0.043, 0.052 -0.112 -0.026 -0.208 C 4.066, 14.47, 3.997, 14.457, 3.945, 14.509 z"/><path d="M 3.517, 14.184 c -0.026, 0.061, 0.004, 0.113, 0.091, 0.156 c 0.069, 0.043, 0.126, 0.035, 0.169 -0.026 c 0.026 -0.061 -0.004 -0.113 -0.091 -0.156 C 3.599, 14.132, 3.543, 14.141, 3.517, 14.184 z"/><path d="M 4.348, 15.015 c -0.078, 0.043 -0.078, 0.121, 0, 0.234 c 0.078, 0.113, 0.151, 0.143, 0.221, 0.091 c 0.078 -0.061, 0.078 -0.143, 0 -0.247 C 4.499, 14.981, 4.425, 14.954, 4.348, 15.015 z"/><path d="M 4.802, 15.599 c -0.078, 0.069 -0.061, 0.151, 0.052, 0.247 c 0.104, 0.104, 0.19, 0.117, 0.259, 0.039 c 0.069 -0.069, 0.052 -0.151 -0.052 -0.246 C 4.958, 15.534, 4.871, 15.521, 4.802, 15.599 z"/></g></svg>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault} previewCheckboxWrapper" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} previewCheckbox">
</div>
</div>
<div class="bda-footer">
<svg class="trashIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 18.012, 0.648 H 12.98 C 12.944, 0.284, 12.637, 0, 12.264, 0 H 8.136 c -0.373, 0 -0.68, 0.284 -0.716, 0.648 H 2.389 c -0.398, 0 -0.72, 0.322 -0.72, 0.72 v 1.368 c 0, 0.398, 0.322, 0.72, 0.72, 0.72 h 15.623 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 1.368 C 18.731, 0.97, 18.409, 0.648, 18.012, 0.648 z"/><path d="M 3.178, 4.839 v 14.841 c 0, 0.397, 0.322, 0.72, 0.72, 0.72 h 12.604 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 4.839 H 3.178 z M 8.449, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 c -0.438, 0 -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z M 13.538, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 s -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z"/></g></svg>
<button class="btn-download bda-settings-button">Download</button>
</div>
</div>
</li>`;
this.themeEntryZackMarkup =
`<li class="themeEntry settings-closed ui-switch-item zack">
<div class="bda-header">
<span class="bda-header-title">
<span class="bda-name"></span> v<span class="bda-version"></span> by <span class="bda-author"></span>
</span>
<svg class="favIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><path fill="none" stroke="black" d="M 19.542, 9.092 c 0.393 -0.383, 0.532 -0.946, 0.362 -1.468 c -0.17 -0.523 -0.613 -0.896 -1.157 -0.975 l -4.837 -0.703 c -0.206 -0.03 -0.384 -0.159 -0.476 -0.346 L 11.273, 1.217 c -0.243 -0.492 -0.736 -0.798 -1.285 -0.798 c -0.549, 0 -1.042, 0.306 -1.284, 0.798 L 6.541, 5.6 c -0.092, 0.187 -0.27, 0.316 -0.476, 0.346 L 1.228, 6.649 c -0.544, 0.079 -0.987, 0.452 -1.157, 0.975 c -0.17, 0.523 -0.031, 1.085, 0.362, 1.468 l 3.5, 3.411 c 0.149, 0.146, 0.218, 0.355, 0.182, 0.56 L 3.29, 17.88 c -0.073, 0.424, 0.038, 0.836, 0.312, 1.162 c 0.426, 0.507, 1.171, 0.661, 1.766, 0.348 l 4.326 -2.274 c 0.181 -0.095, 0.408 -0.094, 0.589, 0 l 4.326, 2.274 c 0.21, 0.111, 0.435, 0.167, 0.666, 0.167 c 0.423, 0, 0.824 -0.188, 1.099 -0.515 c 0.275 -0.325, 0.386 -0.738, 0.312 -1.162 l -0.826 -4.817 c -0.035 -0.205, 0.033 -0.414, 0.182 -0.56 L 19.542, 9.092 z"/></svg>
<svg class="gitIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 7.19, 16.027 c -0.139, 0.026 -0.199, 0.091 -0.182, 0.195 c 0.017, 0.104, 0.095, 0.138, 0.234, 0.104 c 0.139 -0.035, 0.199 -0.095, 0.182 -0.182 C 7.406, 16.049, 7.328, 16.01, 7.19, 16.027 z"/><path d="M 6.45, 16.131 c -0.138, 0 -0.208, 0.047 -0.208, 0.143 c 0, 0.112, 0.074, 0.16, 0.221, 0.143 c 0.138, 0, 0.208 -0.048, 0.208 -0.143 C 6.671, 16.162, 6.597, 16.114, 6.45, 16.131 z"/><path d="M 5.438, 16.092 c -0.035, 0.095, 0.022, 0.16, 0.169, 0.195 c 0.13, 0.052, 0.212, 0.026, 0.247 -0.078 c 0.026 -0.095 -0.03 -0.164 -0.169 -0.208 C 5.554, 15.967, 5.472, 15.996, 5.438, 16.092 z"/><path d="M 18.837, 1.097 C 18.106, 0.366, 17.226, 0, 16.196, 0 H 3.738 C 2.708, 0, 1.828, 0.366, 1.097, 1.097 C 0.366, 1.828, 0, 2.708, 0, 3.738 v 12.459 c 0, 1.03, 0.366, 1.91, 1.097, 2.641 c 0.731, 0.731, 1.612, 1.097, 2.641, 1.097 h 2.907 c 0.19, 0, 0.333 -0.007, 0.428 -0.019 c 0.095 -0.013, 0.19 -0.069, 0.285 -0.169 c 0.095 -0.099, 0.143 -0.244, 0.143 -0.435 c 0 -0.026 -0.002 -0.32 -0.007 -0.883 c -0.004 -0.562 -0.007 -1.008 -0.007 -1.337 l -0.298, 0.052 c -0.19, 0.035 -0.43, 0.05 -0.72, 0.045 c -0.29 -0.004 -0.59 -0.035 -0.902 -0.091 c -0.312 -0.056 -0.601 -0.186 -0.87 -0.389 c -0.268 -0.203 -0.458 -0.469 -0.571 -0.798 l -0.13 -0.299 c -0.086 -0.199 -0.223 -0.419 -0.409 -0.662 c -0.186 -0.242 -0.374 -0.407 -0.564 -0.493 l -0.091 -0.065 c -0.06 -0.043 -0.117 -0.095 -0.169 -0.156 c -0.052 -0.061 -0.091 -0.121 -0.117 -0.182 c -0.026 -0.061 -0.004 -0.11, 0.065 -0.149 c 0.069 -0.039, 0.195 -0.058, 0.376 -0.058 l 0.259, 0.039 c 0.173, 0.035, 0.387, 0.138, 0.642, 0.311 c 0.255, 0.173, 0.465, 0.398, 0.629, 0.675 c 0.199, 0.355, 0.439, 0.625, 0.72, 0.811 c 0.281, 0.186, 0.565, 0.279, 0.85, 0.279 s 0.532 -0.022, 0.74 -0.065 c 0.208 -0.043, 0.402 -0.108, 0.584 -0.195 c 0.078 -0.58, 0.29 -1.025, 0.636 -1.337 c -0.493 -0.052 -0.936 -0.13 -1.33 -0.234 c -0.394 -0.104 -0.8 -0.272 -1.22 -0.506 c -0.42 -0.234 -0.768 -0.523 -1.045 -0.87 c -0.277 -0.346 -0.504 -0.8 -0.681 -1.363 c -0.177 -0.562 -0.266 -1.211 -0.266 -1.947 c 0 -1.047, 0.342 -1.938, 1.025 -2.673 c -0.32 -0.787 -0.29 -1.67, 0.091 -2.647 c 0.251 -0.078, 0.623 -0.019, 1.116, 0.175 c 0.493, 0.195, 0.854, 0.361, 1.084, 0.5 c 0.229, 0.138, 0.413, 0.255, 0.552, 0.35 c 0.805 -0.225, 1.635 -0.337, 2.492 -0.337 c 0.856, 0, 1.687, 0.112, 2.492, 0.337 l 0.493 -0.311 c 0.338 -0.208, 0.735 -0.398, 1.194 -0.571 c 0.459 -0.173, 0.809 -0.221, 1.051 -0.143 c 0.389, 0.978, 0.424, 1.86, 0.104, 2.647 c 0.683, 0.735, 1.025, 1.627, 1.025, 2.673 c 0, 0.735 -0.089, 1.387 -0.266, 1.953 c -0.177, 0.567 -0.406, 1.021 -0.688, 1.363 c -0.281, 0.342 -0.632, 0.629 -1.051, 0.863 c -0.42, 0.234 -0.826, 0.402 -1.22, 0.506 c -0.394, 0.104 -0.837, 0.182 -1.33, 0.234 c 0.45, 0.389, 0.675, 1.003, 0.675, 1.843 v 3.102 c 0, 0.147, 0.021, 0.266, 0.065, 0.357 c 0.044, 0.091, 0.113, 0.153, 0.208, 0.188 c 0.096, 0.035, 0.18, 0.056, 0.253, 0.065 c 0.074, 0.009, 0.18, 0.013, 0.318, 0.013 h 2.907 c 1.029, 0, 1.91 -0.366, 2.641 -1.097 c 0.731 -0.731, 1.097 -1.612, 1.097 -2.641 V 3.738 C 19.933, 2.708, 19.568, 1.827, 18.837, 1.097 z"/><path d="M 3.945, 14.509 c -0.06, 0.043 -0.052, 0.112, 0.026, 0.208 c 0.087, 0.086, 0.156, 0.1, 0.208, 0.039 c 0.061 -0.043, 0.052 -0.112 -0.026 -0.208 C 4.066, 14.47, 3.997, 14.457, 3.945, 14.509 z"/><path d="M 3.517, 14.184 c -0.026, 0.061, 0.004, 0.113, 0.091, 0.156 c 0.069, 0.043, 0.126, 0.035, 0.169 -0.026 c 0.026 -0.061 -0.004 -0.113 -0.091 -0.156 C 3.599, 14.132, 3.543, 14.141, 3.517, 14.184 z"/><path d="M 4.348, 15.015 c -0.078, 0.043 -0.078, 0.121, 0, 0.234 c 0.078, 0.113, 0.151, 0.143, 0.221, 0.091 c 0.078 -0.061, 0.078 -0.143, 0 -0.247 C 4.499, 14.981, 4.425, 14.954, 4.348, 15.015 z"/><path d="M 4.802, 15.599 c -0.078, 0.069 -0.061, 0.151, 0.052, 0.247 c 0.104, 0.104, 0.19, 0.117, 0.259, 0.039 c 0.069 -0.069, 0.052 -0.151 -0.052 -0.246 C 4.958, 15.534, 4.871, 15.521, 4.802, 15.599 z"/></g></svg>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault} previewCheckboxWrapper" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} previewCheckbox">
</div>
</div>
<div class="bda-description-wrap ${BDFDB.disCN.scrollerwrap}">
<div class="bda-description ${BDFDB.disCN.scroller}" style="display: block;"></div>
</div>
<div class="bda-footer">
<span class="bda-links"></span>
<svg class="trashIcon" version="1.1" xmlns="http://www.w3.org/2000/svg" width="20px" height="20px"><g fill="white"><path d="M 18.012, 0.648 H 12.98 C 12.944, 0.284, 12.637, 0, 12.264, 0 H 8.136 c -0.373, 0 -0.68, 0.284 -0.716, 0.648 H 2.389 c -0.398, 0 -0.72, 0.322 -0.72, 0.72 v 1.368 c 0, 0.398, 0.322, 0.72, 0.72, 0.72 h 15.623 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 1.368 C 18.731, 0.97, 18.409, 0.648, 18.012, 0.648 z"/><path d="M 3.178, 4.839 v 14.841 c 0, 0.397, 0.322, 0.72, 0.72, 0.72 h 12.604 c 0.398, 0, 0.72 -0.322, 0.72 -0.72 V 4.839 H 3.178 z M 8.449, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 c -0.438, 0 -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z M 13.538, 15.978 c 0, 0.438 -0.355, 0.794 -0.794, 0.794 s -0.794 -0.355 -0.794 -0.794 V 8.109 c 0 -0.438, 0.355 -0.794, 0.794 -0.794 c 0.438, 0, 0.794, 0.355, 0.794, 0.794 V 15.978 z"/></g></svg>
<button class="btn-download bda-settings-button">Download</button>
</div>
</li>`;
this.themeRepoModalMarkup =
`<span class="themerepo-modal DevilBro-modal">
<div class="${BDFDB.disCN.backdrop}"></div>
<div class="${BDFDB.disCN.modal}">
<div class="${BDFDB.disCN.modalinner}">
<div class="${BDFDB.disCNS.modalsub + BDFDB.disCN.modalsizelarge}">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.modalheader}" style="flex: 0 0 auto; padding: 20px 20px 0 20px;">
<div class="${BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">
<h4 class="${BDFDB.disCNS.h4 + BDFDB.disCNS.headertitle + BDFDB.disCNS.size16 + BDFDB.disCNS.height20 + BDFDB.disCNS.weightsemibold + BDFDB.disCNS.defaultcolor + BDFDB.disCNS.h4defaultmargin + BDFDB.disCN.marginreset} themeAmount">Theme Repository</h4>
<div class="${BDFDB.disCNS.modalguildname + BDFDB.disCNS.small + BDFDB.disCNS.size12 + BDFDB.disCNS.height16 + BDFDB.disCN.primary}"></div>
</div>
<svg class="${BDFDB.disCNS.modalclose + BDFDB.disCN.flexchild}" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 12 12">
<g fill="none" fill-rule="evenodd">
<path d="M0 0h12v12H0"></path>
<path class="fill" fill="currentColor" d="M9.5 3.205L8.795 2.5 6 5.295 3.205 2.5l-.705.705L5.295 6 2.5 8.795l.705.705L6 6.705 8.795 9.5l.705-.705L6.705 6"></path>
</g>
</svg>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCNS.modalheader + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto; padding: 10px 20px 0px 20px;">
<div tab="themes" class="tab selected">Themes</div>
<div tab="settings" class="tab">Settings</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.searchbar + BDFDB.disCN.size14}" style="flex: 1 1 auto; margin: -15px 5px 0 0;">
<input class="${BDFDB.disCNS.searchbarinput + BDFDB.disCN.flexchild}" value="" placeholder="Search for ..." style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.searchbariconwrap + BDFDB.disCN.flexchild}">
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCNS.searchbareyeglass + BDFDB.disCN.searchbarvisible}"/>
<i class="${BDFDB.disCNS.searchbaricon + BDFDB.disCN.searchbarclear}"/>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="padding-bottom: 15px;">
<div class="${BDFDB.disCN.quickselectlabel}">Sort by:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} sort-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.sort)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.sort[Object.keys(this.sortings.sort)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselect}" style="padding-bottom: 15px;">
<div class="${BDFDB.disCN.quickselectlabel}">Order:</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.quickselectclick} order-filter" style="flex: 0 0 auto;">
<div option="${Object.keys(this.sortings.order)[0]}" class="${BDFDB.disCN.quickselectvalue}">${this.sortings.order[Object.keys(this.sortings.order)[0]]}</div>
<div class="${BDFDB.disCN.quickselectarrow}"></div>
</div>
</div>
</div>
<div tab="themes" class="${BDFDB.disCNS.scrollerwrap + BDFDB.disCNS.modalcontent + BDFDB.disCNS.scrollerthemed + BDFDB.disCN.themeghosthairline} tab-content">
<div class="${BDFDB.disCNS.scroller + BDFDB.disCN.modalsubinner} ui-standard-sidebar-view">
<ul class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCN.nowrap} bda-slist themes" style="flex: 1 1 auto;"></ul>
</div>
</div>
<div tab="settings" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directioncolumn + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCN.modalsubinner} tab-content" style="flex: 1 1 auto;">
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">You can toggle this menu with the "Ctrl" key to take a better look at the preview.</h3>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Preview in light mode</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-darklight">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Include Custom CSS in Preview</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-customcss">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Include ThemeFixer CSS in Preview</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-themefixer">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Download ThemeFixer</h3>
<button type="button" id="download-themefixer" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow}" style="flex: 0 0 auto;">
<div class="${BDFDB.disCN.buttoncontents}">Download</div>
</button>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide updated Themes.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="updated" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hideupdated">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide outdated Themes.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="outdated" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hideoutdated">
</div>
</div>
<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Hide downloadable Themes.</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" value="downloadable" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner} hide-checkbox" id="input-hidedownloadable">
</div>
</div>
<div id="RNMoption" class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;">
<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Apply Theme after Download (Restart-No-More needed)</h3>
<div class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.switchenabled + BDFDB.disCNS.switch + BDFDB.disCNS.switchvalue + BDFDB.disCNS.switchsizedefault + BDFDB.disCNS.switchsize + BDFDB.disCN.switchthemedefault}" style="flex: 0 0 auto;">
<input type="checkbox" class="${BDFDB.disCNS.switchinnerenabled + BDFDB.disCN.switchinner}" id="input-rnmstart">
</div>
</div>
</div>
</div>
</div>
</div>
</span>`;
this.sortPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} themerepo-sort-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.sort).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.sort[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.orderPopoutMarkup =
`<div class="${BDFDB.disCNS.popout + BDFDB.disCNS.popoutbottomright + BDFDB.disCN.popoutnoshadow} themerepo-order-popout" style="position: fixed; z-index: 1100; visibility: visible; transform: translateX(-100%) translateY(0%) translateZ(0px);">
<div>
<div class="${BDFDB.disCN.contextmenu} quickSelectPopout">
<div class="${BDFDB.disCN.contextmenuitemgroup}">
${Object.keys(this.sortings.order).map((key, i) => `<div option="${key}" class="${BDFDB.disCN.contextmenuitem}">${this.sortings.order[key]}</div>`).join("")}
</div>
</div>
</div>
</div>`;
this.css = `
.discordPreview {
width: 100vw !important;
height: 100vh !important;
position: absolute !important;
z-index: 3400 !important;
}
.discordPreview ~ ${BDFDB.dotCN.appmount} {
position: absolute !important;
top: 0 !important;
}
.themerepo-sort-popout,
.themerepo-order-popout,
.themerepo-favicon-tooltip,
.themerepo-giticon-tooltip {
z-index: 3600 !important;
}
.themerepo-modal {
position: relative !important;
z-index: 3500 !important;
}
.themerepo-modal ${BDFDB.dotCN.modalinner} {
min-height: 100%;
}
.themerepo-modal .themeEntry.zack {
overflow: visible !important;
}
.themerepo-modal .themeEntry .gitIcon,
.themerepo-modal .themeEntry .favIcon,
.themerepo-modal .themeEntry .trashIcon {
margin-right: 5px;
cursor: pointer;
}
.themerepo-modal .themeEntry .trashIcon,
.themerepo-modal .themeEntry .favIcon {
margin-left: auto;
}
.themerepo-modal .themeEntry .favIcon path {
stroke: yellow;
fill: none;
}
.themerepo-modal .themeEntry .favIcon.favorized path {
stroke: yellow;
fill: yellow;
}
.themerepo-modal .themeEntry.downloadable .trashIcon {
display: none;
}
.themerepo-modal .themeEntry.downloadable .btn-download {
background-color: rgb(114, 137, 218) !important;
margin-left: auto !important;
}
.themerepo-modal .themeEntry.outdated .btn-download {
background-color: rgb(240, 71, 71) !important;
margin-left: 0 !important;
}
.themerepo-modal .themeEntry.updated .btn-download {
background-color: rgb(67, 181, 129) !important;
margin-left: 0 !important;
}
.themerepo-trashicon-tooltip{
z-index: 3500!important;
}
.themerepo-modal .themeEntry.jiiks .bda-right {
flex: 1 1 auto;
}
.themerepo-modal .themeEntry.jiiks .bda-header,
.themerepo-modal .themeEntry.jiiks .bda-footer {
display: flex;
align-items: center;
margin: 0 !important;
}
.themerepo-modal .themeEntry.jiiks .bda-footer {
margin-top: 33% !important;
}
.themerepo-modal .themeEntry.jiiks .previewCheckboxWrapper {
margin-right: 5px;
}`;
}
getName () {return "ThemeRepo";}
getDescription () {return "Allows you to preview all themes from the theme repo and download them on the fly. Repo button is in the theme settings.";}
getVersion () {return "1.5.2";}
getAuthor () {return "DevilBro";}
getSettingsPanel () {
if (!this.started || typeof BDFDB !== "object") return;
var settingshtml = `<div class="${this.getName()}-settings DevilBro-settings"><div class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.size18 + BDFDB.disCNS.height24 + BDFDB.disCNS.weightnormal + BDFDB.disCN.marginbottom8}">${this.getName()}</div><div class="DevilBro-settings-inner">`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 0 0 auto;">Add Theme:</h3><input type="text" placeholder="Insert Raw Github Link of Theme (https://raw.githubusercontent.com/...)" class="${BDFDB.disCNS.inputdefault + BDFDB.disCNS.input + BDFDB.disCN.size16}" id="input-themeurl" style="flex: 1 1 auto;"><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} btn-add btn-addtheme" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}"></div></button></div>`;
settingshtml += `<h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Your additional Theme List:</h3><div class="DevilBro-settings-inner-list theme-list ${BDFDB.disCN.marginbottom8}">`;
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
if (ownlist) for (let url of ownlist) {
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryurl">${url}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-theme"></div></div>`;
}
settingshtml += `</div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom8}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Force all Themes to be fetched again.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorbrand + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} refresh-button" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Refresh</div></button></div>`;
settingshtml += `<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.horizontal + BDFDB.disCNS.horizontal2 + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.aligncenter + BDFDB.disCNS.nowrap + BDFDB.disCN.marginbottom20}" style="flex: 0 0 auto;"><h3 class="${BDFDB.disCNS.titledefault + BDFDB.disCNS.title + BDFDB.disCNS.marginreset + BDFDB.disCNS.weightmedium + BDFDB.disCNS.size16 + BDFDB.disCNS.height24 + BDFDB.disCN.flexchild}" style="flex: 1 1 auto;">Remove all added Themes from your own list.</h3><button type="button" class="${BDFDB.disCNS.flexchild + BDFDB.disCNS.button + BDFDB.disCNS.buttonlookfilled + BDFDB.disCNS.buttoncolorred + BDFDB.disCNS.buttonsizemedium + BDFDB.disCN.buttongrow} remove-all" style="flex: 0 0 auto;"><div class="${BDFDB.disCN.buttoncontents}">Reset</div></button></div>`;
settingshtml += `</div></div>`;
var settingspanel = $(settingshtml)[0];
BDFDB.initElements(settingspanel);
$(settingspanel)
.on("click", ".btn-addtheme", () => {this.addThemeToOwnList(settingspanel);})
.on("keyup", "#input-themeurl", (e) => {if (e.which == 13) this.addThemeToOwnList(settingspanel);})
.on("click", ".remove-theme", (e) => {this.removeThemeFromOwnList(e);})
.on("click", ".remove-all", () => {this.removeAllFromOwnList(settingspanel);})
.on("click", ".refresh-button", () => {this.loadThemes();});
return settingspanel;
}
//legacy
load () {}
start () {
var libraryScript = null;
if (typeof BDFDB !== "object" || typeof BDFDB.isLibraryOutdated !== "function" || BDFDB.isLibraryOutdated()) {
libraryScript = document.querySelector('head script[src="https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js"]');
if (libraryScript) libraryScript.remove();
libraryScript = document.createElement("script");
libraryScript.setAttribute("type", "text/javascript");
libraryScript.setAttribute("src", "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.js");
document.head.appendChild(libraryScript);
}
this.startTimeout = setTimeout(() => {this.initialize();}, 30000);
if (typeof BDFDB === "object" && typeof BDFDB.isLibraryOutdated === "function") this.initialize();
else libraryScript.addEventListener("load", () => {this.initialize();});
}
initialize () {
if (typeof BDFDB === "object") {
BDFDB.loadMessage(this);
this.UserUtils = BDFDB.WebModules.findByProperties(["getUsers"]);
this.IconUtils = BDFDB.WebModules.findByProperties(["getUserAvatarURL"]);
var observer = null;
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, j) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
this.checkIfThemesPage(node);
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layer + "[layer-id='user-settings']", {name:"innerSettingsWindowObserver",instance:observer}, {childList:true,subtree:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
setImmediate(() => {
if (node && node.tagName && node.getAttribute("layer-id") == "user-settings") {
BDFDB.addObserver(this, node, {name:"innerSettingsWindowObserver"}, {childList:true,subtree:true});
this.checkIfThemesPage(node);
}
});
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.layers, {name:"settingsWindowObserver",instance:observer}, {childList:true});
observer = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu)) {
this.onContextMenu(node);
}
});
}
}
);
});
BDFDB.addObserver(this, BDFDB.dotCN.appmount, {name:"settingsContextObserver",instance:observer}, {childList: true});
var settingswindow = document.querySelector(BDFDB.dotCN.layer + "[layer-id='user-settings']");
if (settingswindow) this.checkIfThemesPage(settingswindow);
this.loadThemes();
this.updateInterval = setInterval(() => {this.checkForNewThemes();},1000*60*30);
}
else {
console.error(this.getName() + ": Fatal Error: Could not load BD functions!");
}
}
stop () {
if (typeof BDFDB === "object") {
clearInterval(this.updateInterval);
$(".discordPreview, .themerepo-modal, .bd-themerepobutton").remove();
BDFDB.unloadMessage(this);
}
}
// begin of own functions
onContextMenu (context) {
if (!context || !context.tagName || !context.parentElement) return;
for (let entry of context.querySelectorAll(BDFDB.dotCN.contextmenuitem)) {
if (entry.textContent == "BetterDiscord") {
let innerObserver = new MutationObserver((changes, _) => {
changes.forEach(
(change, i) => {
if (change.addedNodes) {
change.addedNodes.forEach((node) => {
if (node && node.nodeType == 1 && node.className.includes(BDFDB.disCN.contextmenu) && !node.querySelector(".themerepo-item")) {
var innerEntries = node.querySelectorAll(BDFDB.dotCN.contextmenuitem);
$(this.settingsContextEntryMarkup)
.on("click", () => {
if (!this.loading) $(context).hide();
this.openThemeRepoModal();
})
.insertAfter(innerEntries[innerEntries.length-1]);
$(node).css("top", $(context).css("top").replace("px","") - $(node).outerHeight() + $(context).outerHeight());
}
});
}
}
);
});
innerObserver.observe(entry, {childList: true});
break;
}
}
}
addThemeToOwnList (settingspanel) {
var themeUrlInput = settingspanel.querySelector("#input-themeurl");
var themeList = settingspanel.querySelector(".theme-list");
if (themeUrlInput && themeList) {
var url = themeUrlInput.value;
themeUrlInput.value = null;
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
if (!ownlist.includes(url)) {
ownlist.push(url);
BDFDB.saveData("ownlist", ownlist, this, "ownlist");
$(`<div class="${BDFDB.disCNS.flex + BDFDB.disCNS.flex2 + BDFDB.disCNS.vertical + BDFDB.disCNS.directionrow + BDFDB.disCNS.justifystart + BDFDB.disCNS.alignstretch + BDFDB.disCNS.nowrap + BDFDB.disCNS.margintop4 + BDFDB.disCNS.marginbottom4 + BDFDB.disCN.hovercard}"><div class="${BDFDB.disCN.hovercardinner}"><div class="${BDFDB.disCNS.description + BDFDB.disCNS.formtext + BDFDB.disCNS.note + BDFDB.disCNS.margintop4 + BDFDB.disCNS.modedefault + BDFDB.disCNS.primary + BDFDB.disCN.ellipsis} entryurl">${url}</div></div><div class="${BDFDB.disCN.hovercardbutton} remove-theme"></div></div>`).appendTo(themeList);
}
}
}
removeThemeFromOwnList (e) {
var entry = e.currentTarget.parentElement;
var url = entry.querySelector(".entryurl").textContent;
entry.remove();
var ownlist = BDFDB.loadData("ownlist", this, "ownlist") || [];
BDFDB.removeFromArray(ownlist, url);
BDFDB.saveData("ownlist", ownlist, this, "ownlist");
}
removeAllFromOwnList (settingspanel) {
if (confirm("Are you sure you want to remove all added Themes from your own list?")) {
BDFDB.saveData("ownlist", [], this, "ownlist");
settingspanel.querySelectorAll(BDFDB.dotCN.hovercard).forEach(ele => {ele.remove();});
}
}
checkIfThemesPage (container) {
if (container && container.tagName) {
var folderbutton = container.querySelector(".bd-pfbtn");
if (folderbutton) {
var buttonbar = folderbutton.parentElement;
if (buttonbar && buttonbar.tagName) {
var header = buttonbar.querySelector("h2");
if (header && header.innerText.toUpperCase() === "THEMES") {
this.addThemeRepoButton(buttonbar);
}
}
}
}
}
addThemeRepoButton (container) {
if (container && !container.querySelector(".bd-themerepobutton")) {
$(container).find(".bda-description").css("display", "block");
$(this.themeRepoButtonMarkup)
.insertAfter(container.querySelector(".bd-pfbtn"))
.on("click", () => {
this.openThemeRepoModal();
})
.on("mouseenter", (e) => {
BDFDB.createTooltip("Open Theme Repo", e.currentTarget, {type:"top",selector:"themerepo-button-tooltip"});
});
}
}
openThemeRepoModal (showOnlyOutdated = false) {
if (this.loading) {
BDFDB.showToast(`Themes are still being fetched. Try again in some seconds.`, {type:"danger"});
return;
}
var frame = $(this.frameMarkup)[0];
var lightTheme = BDFDB.getDiscordTheme() == "theme-light";
var themeRepoModal = $(this.themeRepoModalMarkup);
themeRepoModal.updateModal = true;
themeRepoModal.enableSearch = false;
var hiddenSettings = BDFDB.loadAllData(this, "hidden");
themeRepoModal.find("#input-darklight").prop("checked", lightTheme);
themeRepoModal.find("#input-customcss").prop("checked", false);
themeRepoModal.find("#input-themefixer").prop("checked", false);
themeRepoModal.find("#input-hideupdated").prop("checked", hiddenSettings.updated || showOnlyOutdated);
themeRepoModal.find("#input-hideoutdated").prop("checked", hiddenSettings.outdated && !showOnlyOutdated);
themeRepoModal.find("#input-hidedownloadable").prop("checked", hiddenSettings.downloadable || showOnlyOutdated);
if (!BDFDB.isRestartNoMoreEnabled()) themeRepoModal.find("#RNMoption").remove();
else themeRepoModal.find("#input-rnmstart").prop("checked", BDFDB.loadData("RNMstart", this, "settings"));
themeRepoModal
.on("keyup." + this.getName(), BDFDB.dotCN.searchbarinput, () => {
clearTimeout(themeRepoModal.searchTimeout);
themeRepoModal.searchTimeout = setTimeout(() => {this.addThemeEntries(themeRepoModal, frame);},1000);
})
.on("click." + this.getName(), BDFDB.dotCN.searchbarclear + BDFDB.dotCN.searchbarvisible, () => {
clearTimeout(themeRepoModal.searchTimeout);
themeRepoModal.searchTimeout = setTimeout(() => {this.addThemeEntries(themeRepoModal, frame);},1000);
})
.on("click." + this.getName(), BDFDB.dotCNC.modalclose + BDFDB.dotCN.backdrop, () => {
frame.remove();
$(document).off("keyup." + this.getName());
$(window).off("message." + this.getName());
})
.on("click." + this.getName(), ".sort-filter", (e) => {
this.openSortPopout(e, this.sortPopoutMarkup, themeRepoModal, frame);
})
.on("click." + this.getName(), ".order-filter", (e) => {
this.openSortPopout(e, this.orderPopoutMarkup, themeRepoModal, frame);
})
.on("change." + this.getName(), "#input-darklight", (e) => {
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:$(e.target).prop("checked")},"*");
})
.on("change." + this.getName(), "#input-customcss", (e) => {
var customCSS = document.querySelector("style#customcss");
if (customCSS && customCSS.innerText.length > 0)
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"CustomCSS",checked:$(e.target).prop("checked"),css:customCSS.innerText},"*");
})
.on("change." + this.getName(), "#input-themefixer", (e) => {
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"ThemeFixer",checked:$(e.target).prop("checked"),css:this.themeFixerCSS},"*");
})
.on("click." + this.getName(), "#download-themefixer", (e) => {
this.createThemeFile("ThemeFixer.theme.css", `//META{"name":"ThemeFixer","description":"ThemeFixerCSS for transparent themes","author":"DevilBro","version":"1.0.1"}*//\n\n` + this.themeFixerCSS);
})
.on("change." + this.getName(), ".hide-checkbox", (e) => {
var hideButton = $(e.currentTarget);
hiddenSettings[hideButton.val()] = hideButton.prop("checked");
BDFDB.saveAllData(hiddenSettings, this, "hidden");
})
.on("change." + this.getName(), "#input-rnmstart", (e) => {
BDFDB.saveData("RNMstart", $(e.currentTarget).prop("checked"), this, "settings");
})
.on("click." + this.getName(), ".tab[tab=themes]:not(.selected)", (e) => {
this.addThemeEntries(themeRepoModal, frame);
});
$(document).off("keyup." + this.getName())
.on("keyup." + this.getName(), (e) => {
keyPressed(e.which);
});
$(window).off("message." + this.getName())
.on("message." + this.getName(), (e) => {
e = e.originalEvent;
if (typeof e.data === "object" && e.data.origin == "DiscordPreview") {
switch (e.data.reason) {
case "OnLoad":
var user = this.UserUtils.getCurrentUser();
if (!user) return;
var username = user.username;
var id = user.id;
var avatar = "url(" + (((user.avatar ? "" : "https://discordapp.com") + this.IconUtils.getUserAvatarURL(user)).split("?size")[0]) + ");";
var discriminator = user.discriminator;
var nativecss = document.querySelector("head link[rel='stylesheet'][integrity]");
nativecss = nativecss && nativecss.href ? nativecss.href : null;
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"OnLoad",username,id,avatar,discriminator,nativecss},"*");
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"DarkLight",checked:lightTheme},"*");
break;
case "KeyUp":
keyPressed(e.data.key);
break;
}
}
});
this.createThemeEntries(themeRepoModal, frame);
BDFDB.appendModal(themeRepoModal);
$(frame).insertBefore(BDFDB.dotCN.appmount);
function keyPressed (key) {
if (key == 17 && !themeRepoModal.find(BDFDB.dotCN.searchbarinput).is(":focus")) themeRepoModal.toggle();
if (key == 27) frame.remove();
}
}
openSortPopout (e, markup, modal, frame) {
var wrapper = e.currentTarget;
if (wrapper.classList.contains("popout-open")) return;
wrapper.classList.add("popout-open");
var value = $(wrapper).find(BDFDB.dotCN.quickselectvalue);
var popout = $(markup);
$(BDFDB.dotCN.popouts).append(popout)
.off("click", BDFDB.dotCN.contextmenuitem)
.on("click", BDFDB.dotCN.contextmenuitem, (e2) => {
value.text($(e2.currentTarget).text());
value.attr("option", $(e2.currentTarget).attr("option"));
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
this.addThemeEntries(modal, frame);
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
});
popout
.css("left", $(wrapper).offset().left + $(wrapper).outerWidth() + "px")
.css("top", $(wrapper).offset().top + value.outerHeight() + "px")
.find(BDFDB.dotCN.contextmenu).addClass(BDFDB.getDiscordTheme());
$(document).on("mousedown.sortpopout" + this.getName(), (e2) => {
if (popout.has(e2.target).length == 0) {
$(document).off("mousedown.sortpopout" + this.getName());
popout.remove();
setTimeout(() => {wrapper.classList.remove("popout-open");},300);
}
});
}
createThemeEntries (modal, frame) {
var favorites = BDFDB.loadAllData(this, "favorites");
modal.entries = [];
for (let url in this.loadedThemes) {
let theme = this.loadedThemes[url];
let div = BDFDB.zacksFork() ? $(this.themeEntryZackMarkup) : $(this.themeEntryMarkup);
var installedTheme = window.bdthemes[this.loadedThemes[url].name];
if (installedTheme && installedTheme.author.toUpperCase() == theme.author.toUpperCase()) {
if (installedTheme.version != theme.version) {
theme.state = 1;
div.addClass("outdated")
.find(".btn-download").text("Outdated");
}
else {
theme.state = 0;
div.addClass("updated")
.find(".btn-download").text("Updated");
}
}
else {
theme.state = 2;
div.addClass("downloadable")
.find(".btn-download").text("Download");
}
if (favorites[url]) {
theme.fav = 0;
div.find(".favIcon")[0].classList.add("favorized");
}
else {
theme.fav = 1;
div.find(".favIcon")[0].classList.remove("favorized");
}
modal.entries.push({
div: div,
url: theme.url,
search: (theme.name + " " + theme.version + " " + theme.author + " " + theme.description).toUpperCase(),
name: theme.name,
version: theme.version,
author: theme.author,
description: theme.description,
fav: theme.fav,
state: theme.state,
css: theme.css
});
}
this.addThemeEntries(modal, frame);
}
addThemeEntries (modal, frame) {
if (typeof modal.entries != "object") return;
modal.find(".themeEntry").remove();
var searchstring = modal.find(BDFDB.dotCN.searchbarinput).val().replace(/[<|>]/g, "").toUpperCase();
var entries = modal.entries;
if (modal.find("#input-hideupdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 0 ? entry : null;});
if (modal.find("#input-hideoutdated").prop("checked")) entries = entries.filter((entry) => {return entry.state != 1 ? entry : null;});
if (modal.find("#input-hidedownloadable").prop("checked")) entries = entries.filter((entry) => {return entry.state != 2 ? entry : null;});
entries = entries.filter((entry) => {return entry.search.indexOf(searchstring) > -1 ? entry : null;});
BDFDB.sortArrayByKey(entries, modal.find(".sort-filter " + BDFDB.dotCN.quickselectvalue).attr("option"));
if (modal.find(".order-filter " + BDFDB.dotCN.quickselectvalue).attr("option") == "desc") entries.reverse();
modal.find(".themeAmount").text("Theme Repository " + entries.length + "/" + Object.keys(this.loadedThemes).length + " Themes");
var container = modal.find(".themes");
entries.forEach((entry) => {
var div = entry.div;
var values = [entry.name, entry.version, entry.author, entry.description];
if (searchstring.length > 0) {
for (let i in values) values[i] = BDFDB.highlightText(values[i], searchstring);
}
if (BDFDB.zacksFork()) {
div.find(".bda-name").html(values[0]);
div.find(".bda-version").html(values[1]);
div.find(".bda-author").html(values[2]);
}
else {
div.find(".bda-name").html(values[0] + " v" + values[1] + " by " + values[2]);
}
div.find(".bda-description").html(values[3]);
div
.on("change." + this.getName(), ".previewCheckbox", (e) => {
modal.find(".previewCheckbox").not(e.target).prop("checked", false);
modal.find(".previewCheckbox").each((_, checkBox) => {
$(checkBox.parentElement)
.toggleClass("valueChecked-3Bzkbm", $(checkBox).prop("checked"))
.toggleClass("valueUnchecked-XR6AOk", $(checkBox).prop("checked"));
});
frame.contentWindow.postMessage({origin:"ThemeRepo",reason:"NewTheme",checked:$(e.target).prop("checked"),css:entry.css},"*");
})
.on("click." + this.getName(), ".favIcon", (e) => {
e.currentTarget.classList.toggle("favorized");
if (e.currentTarget.classList.contains("favorized")) {
entry.fav = 0;
BDFDB.saveData(entry.url, true, this, "favorites");
}
else {
entry.fav = 1;
BDFDB.removeData(entry.url, this, "favorites");
}
})
.on("click." + this.getName(), ".gitIcon", (e) => {
var giturl = null;
if (entry.url.indexOf("https://raw.githubusercontent.com") == 0) {
var temp = entry.url.replace("//raw.githubusercontent", "//github").split("/");
temp.splice(5, 0, "blob");
giturl = temp.join("/");
}
else if (entry.url.indexOf("https://gist.githubusercontent.com/") == 0) {
giturl = entry.url.replace("//gist.githubusercontent", "//gist.github").split("/raw/")[0];
}
if (giturl) {
window.open(giturl, "_blank");
}
})
.on("click." + this.getName(), ".trashIcon", () => {
if (div.hasClass("outdated") || div.hasClass("updated")) {
entry.state = 2;
div.removeClass("outdated").removeClass("updated").addClass("downloadable")
.find(".btn-download").text("Download");
this.deleteThemeFile(entry);
if (!BDFDB.isRestartNoMoreEnabled()) this.removeTheme(entry);
}
})
.on("mouseenter." + this.getName(), ".favIcon", (e) => {
BDFDB.createTooltip("Favorize", e.currentTarget, {type:"top",selector:"themerepo-favicon-tooltip"});
})
.on("mouseenter." + this.getName(), ".gitIcon", (e) => {
BDFDB.createTooltip("Go to Git", e.currentTarget, {type:"top",selector:"themerepo-giticon-tooltip"});
})
.on("mouseenter." + this.getName(), ".trashIcon", (e) => {
BDFDB.createTooltip("Delete Themefile", e.currentTarget, {type:"top",selector:"themerepo-trashicon-tooltip"});
})
.on("click." + this.getName(), ".btn-download", () => {
entry.state = 0;
this.downloadTheme(entry);
div.removeClass("downloadable").removeClass("outdated").addClass("updated")
.find(".btn-download").text("Updated");
if (modal.find("#input-rnmstart").prop("checked")) setTimeout(() => {this.applyTheme(entry);},3000);
});
container.append(div);
});
}
loadThemes () {
var getThemeInfo, outdated = 0, i = 0;
var tags = ["name","description","author","version"];
let request = require("request");
request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/ThemeList.txt", (error, response, result) => {
if (response) {
this.loadedThemes = {};
this.grabbedThemes = result.split("\n");
this.foundThemes = this.grabbedThemes.concat(BDFDB.loadData("ownlist", this, "ownlist") || []);
this.loading = true;
getThemeInfo(() => {
this.loading = false;
console.log("ThemeRepo: Finished fetching Themes.");
if (document.querySelector(".bd-themerepobutton")) BDFDB.showToast(`Finished fetching Themes.`, {type:"success"});
if (outdated > 0) {
var text = `${outdated} of your Themes ${outdated == 1 ? "is" : "are"} outdated. Check:`;
var bar = BDFDB.createNotificationsBar(text,{type:"danger",btn:"ThemeRepo",selector:"themerepo-notice"});
$(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => {
this.openThemeRepoModal(true);
e.delegateTarget.querySelector(BDFDB.dotCN.noticedismiss).click();
});
}
if (BDFDB.myData.id == "278543574059057154") {
let wrongUrls = [];
for (let url of this.foundThemes) if (url && !this.loadedThemes[url]) wrongUrls.push(url);
if (wrongUrls.length > 0) {
var bar = BDFDB.createNotificationsBar(`ThemeRepo: ${wrongUrls.length} Themes${wrongUrls.length > 1 ? "s" : ""} could not be loaded.`, {type:"danger",btn:"List"});
$(bar).on("click." + this.getName(), BDFDB.dotCN.noticebutton, (e) => {
var toast = BDFDB.showToast(wrongUrls.join("\n"),{type:"error"});
toast.style.overflow = "hidden";
console.log(wrongUrls.length == 1 ? wrongUrls[0] : wrongUrls);
});
}
}
});
}
});
getThemeInfo = (callback) => {
if (i >= this.foundThemes.length) {
callback();
return;
}
let url = this.foundThemes[i].replace(new RegExp("[\\r|\\n|\\t]", "g"), "");
this.foundThemes[i] = url;
request(url, (error, response, body) => {
if (response) {
let theme = {};
let text = body;
if (text.split("*//").length > 1 && text.split("\n").length > 1) {
for (let tag of tags) {
let result = text.replace(new RegExp("\\s*\:\\s*", "g"), ":").replace(new RegExp("\\s*\}\\s*", "g"), "}").split('"' + tag + '":"');
result = result.length > 1 ? result[1].split('",')[0].split('"}')[0] : null;
result = result && tag != "version" ? result.charAt(0).toUpperCase() + result.slice(1) : result;
theme[tag] = result;
}
let valid = true;
for (let tag of tags) {
if (theme[tag] === null) valid = false;
}
if (valid) {
theme.css = text.split("\n").slice(1).join("\n").replace(new RegExp("[\\r|\\n|\\t]", "g"), "");
theme.url = url;
this.loadedThemes[url] = theme;
var installedTheme = window.bdthemes[theme.name];
if (installedTheme && installedTheme.author.toUpperCase() == theme.author.toUpperCase() && installedTheme.version != theme.version) outdated++;
}
}
}
i++;
getThemeInfo(callback);
});
}
}
checkForNewThemes () {
let request = require("request");
request("https://mwittrien.github.io/BetterDiscordAddons/Plugins/ThemeRepo/res/ThemeList.txt", (error, response, result) => {
if (response && !BDFDB.equals(result.split("\n"), this.grabbedThemes)) this.loadThemes();
});
}
downloadTheme (entry) {
let request = require("request");
request(entry.url, (error, response, body) => {
if (error) {
BDFDB.showToast(`Unable to download Theme "${entry.name}".`, {type:"danger"});
}
else {
let filename = entry.url.split("/");
this.createThemeFile(filename[filename.length - 1], body);
}
});
}
createThemeFile (filename, content) {
let fileSystem = require("fs");
let path = require("path");
var file = path.join(BDFDB.getThemesFolder(), filename);
fileSystem.writeFile(file, content, (error) => {
if (error) {
BDFDB.showToast(`Unable to save Theme "${filename}".`, {type:"danger"});
}
else {
BDFDB.showToast(`Successfully saved Theme "${filename}".`, {type:"success"});
}
});
}
applyTheme (entry) {
var name = entry.name;
if (BDFDB.isThemeEnabled(name) == false) {
$(`style#${name}`).remove();
$("head").append(`<style id=${name}>${entry.css}</style>`);
themeCookie[name] = true;
themeModule.saveThemeData();
console.log("ThemeRepo: applied Theme " + name);
}
}
deleteThemeFile (entry) {
let fileSystem = require("fs");
let path = require("path");
let filename = entry.url.split("/");
filename = filename[filename.length - 1];
var file = path.join(BDFDB.getThemesFolder(), filename);
fileSystem.unlink(file, (error) => {
if (error) {
BDFDB.showToast(`Unable to delete Theme "${filename}".`, {type:"danger"});
}
else {
BDFDB.showToast(`Successfully deleted Theme "${filename}".`, {type:"success"});
}
});
}
removeTheme (entry) {
var name = entry.name;
if (BDFDB.isThemeEnabled(name) == true) {
$(`style#${name}`).remove();
themeCookie[name] = false;
delete bdthemes[name];
themeModule.saveThemeData();
console.log("ThemeRepo: removed Theme " + name);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
window.onload = function () {
window.parent.postMessage({origin:"DiscordPreview",reason:"OnLoad"},"*");
};
window.onkeyup = function (e) {
window.parent.postMessage({origin:"DiscordPreview",reason:"KeyUp",key:e.which},"*");
};
window.onmessage = function (e) {
if (typeof e.data === "object" && e.data.origin == "ThemeRepo") {
switch (e.data.reason) {
case "OnLoad":
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("REPLACE_USERNAMESMALL", "g"), e.data.username.toLowerCase());
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("REPLACE_USERNAME", "g"), e.data.username);
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("REPLACE_USERID", "g"), e.data.id);
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("REPLACE_AVATAR", "g"), e.data.avatar.split('"').join(''));
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("REPLACE_DISCRIMINATOR", "g"), e.data.discriminator);
if (e.data.nativecss) {
var theme = document.createElement("link");
theme.classList.add(e.data.reason);
theme.rel = "stylesheet";
theme.href = e.data.nativecss;
document.head.appendChild(theme);
}
document.body.firstElementChild.style.display = "flex";
break;
case "NewTheme":
case "CustomCSS":
case "ThemeFixer":
document.querySelectorAll("style." + e.data.reason).forEach(theme => theme.remove());
if (e.data.checked) {
var theme = document.createElement("style");
theme.classList.add(e.data.reason);
theme.innerText = e.data.css;
document.head.appendChild(theme);
}
break;
case "DarkLight":
if (e.data.checked) {
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("theme-dark", "g"), "theme-light");
}
else {
document.body.innerHTML = document.body.innerHTML.replace(new RegExp("theme-light", "g"), "theme-dark");
}
break;
}
}
};

Some files were not shown because too many files have changed in this diff Show More