module.exports = (Plugin, Api, Vendor) => { if (typeof BDFDB !== "object") global.BDFDB = {$: Vendor.$, BDv2Api: Api}; const {$} = Vendor; return class extends Plugin { initConstructor () { this.stalkerOnlineList = {}; this.checkInterval = null; this.timeLog = []; this.timeLogModalMarkup = `

User LogIn/-Out Timelog

`; this.logEntryMarkup = `

`; this.dividerMarkup = `
`; this.css = ` .guilds > .friends-online { cursor: pointer; } .stalkernotifications-modal .log-time { width: 100px; } .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:"} } }; } onStart () { 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();}); return true; } 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(["getStatuses", "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(); return true; } else { console.error(this.name + ": Fatal Error: Could not load BD functions!"); return false; } } onStop () { if (typeof BDFDB === "object") { clearInterval(this.checkInterval); BDFDB.unloadMessage(this); return true; } else { return false; } } // 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 `
`; } 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(`
${string}
`, {html:true, timeout:5000, type:(online ? "success" : null), icon:false}); $(toast).on("click." + this.name, 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); } getSettingsPanel () { 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 = `
`; settingshtml += `

Add User:

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

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

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

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

`; } if ("Notification" in window) settingshtml += `
Desktop Notification Sound:
Mute:
`; settingshtml += `

Click on a Icon to toggle Notifications for that User:

`; if ("Notification" in window) settingshtml += `

Rightclick on a Icon to toggle Notifications for that User:

`; settingshtml += `
`; for (let id in users) { let user = this.UserUtils.getUser(id); if (user) settingshtml += this.createSettingsAvatarHtml(user, users[id]); } settingshtml += `
`; settingshtml += `

Batch set Users:

${"Notification" in window ? `` : ``}
`; settingshtml += `

Timelog of LogIns/-Outs:

`; settingshtml += `
`; var settingspanel = $(settingshtml)[0]; $(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 = `
`; 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 += `
`; 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 = `
`; 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 += `
`; 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; } } };