//META{"name":"latencyDisplay"}*// /*@cc_on @if (@_jscript) // Offer to self-install for clueless users that try to run this directly. var shell = WScript.CreateObject("WScript.Shell"); var fs = new ActiveXObject("Scripting.FileSystemObject"); var pathPlugins = shell.ExpandEnvironmentStrings("%APPDATA%\\BetterDiscord\\plugins"); var pathSelf = WScript.ScriptFullName; shell.Popup("It looks like you mistakenly tried to run me directly. (don't do that!)", 0, "I'm a plugin for BetterDiscord", 0x30); if (fs.GetParentFolderName(pathSelf) === fs.GetAbsolutePathName(pathPlugins)) shell.Popup("I'm in the correct folder already.\nJust reload Discord with Ctrl+R.", 0, "I'm already installed", 0x40); else if (!fs.FolderExists(pathPlugins)) shell.Popup("I can't find the BetterDiscord plugins folder.\nAre you sure it's even installed?", 0, "Can't install myself", 0x10); else if (shell.Popup("Should I copy myself to BetterDiscord's plugins folder for you?", 0, "Do you need some help?", 0x34) === 6) { fs.CopyFile(pathSelf, fs.BuildPath(pathPlugins, fs.GetFileName(pathSelf)), true); shell.Exec("explorer " + pathPlugins); shell.Popup("I'm installed!\nJust reload Discord with Ctrl+R.", 0, "Successfully installed", 0x40); } WScript.Quit(); @else @*/ function latencyDisplay(){} // https://github.com/tony311/betterdiscord-plugins latencyDisplay.prototype.getName = function() { return "Latency Display"; } latencyDisplay.prototype.getDescription = function() { return "Displays live latency on the connection info button."; } latencyDisplay.prototype.getVersion = function() { return "1.0.6"; } latencyDisplay.prototype.getAuthor = function() { return "TonyLemur"; } latencyDisplay.prototype.load = function() {} latencyDisplay.prototype.unload = function() {} latencyDisplay.prototype.onMessage = function() {} latencyDisplay.prototype.onSwitch = function() {} latencyDisplay.prototype.start = function() { var self = this; // Inject some custom CSS BdApi.clearCSS("latencyDisplay"); BdApi.injectCSS("latencyDisplay", "#voice-connection .btn-info:after { background-image:none; }" + ".btn-info { vertical-align:top; }" ); var OptionsPlugin = this.getOptionsPlugin(); this.options = new OptionsPlugin({ plugin: this, storageKey: "latency", defaults: { address: {value:"google.com", type:"text", label:"Address to ping"}, port: {value:80, type:"number", label:"Port to ping"}, rate: {value:3, type:"range", label:"How often to ping (in seconds)", min:0.1, max:10, step:0.1 }, samples: {value:1, type:"range", label:"Number of times to ping per request", min:1, max:5}, colors_red: {value:800, type:"range", label:"Latency red threshold (in ms)", min:10, max:3000, step:1}, colors_orange: {value:500, type:"range", label:"Latency orange threshold (in ms)", min:10, max:3000, step:10}, colors_yellow: {value:200, type:"range", label:"Latency yellow threshold (in ms)", min:10, max:3000, step:10}, }, onSave:function(key,value){ if (key == "port" && (value<1 || value>65535)) self.options.set("port", 80); clearInterval(self.intervalPing); self.intervalPing = setInterval(function(){ self.doPing() }, self.options.get("rate")*1000); }, onReset:function(){ clearInterval(self.intervalPing); self.intervalPing = setInterval(function(){ self.doPing() }, self.options.get("rate")*1000); self.doPing(); }, }); this.options.load(); if (this.options.get("port") < 1 || this.options.get("port") > 65535) this.options.set("port", 80); // Set up pinging this.intervalPing = setInterval(function(){ self.doPing() }, this.options.get("rate")*1000); this.doPing(); } latencyDisplay.prototype.stop = function() { // Remove our custom CSS BdApi.clearCSS("latencyDisplay"); clearInterval(this.intervalPing); clearInterval(this.intervalClear); } latencyDisplay.prototype.getSettingsPanel = function() { if (this.options) return this.options.settingsHTML(); } latencyDisplay.prototype.doPing = function() { var self = this; ping.ping({ address: this.options.get("address"), port: this.options.get("port"), timeout: 5000, samples: this.options.get("samples"), }, function(err, result){ var latency = Math.round(result.avg); var color = "#19ff00"; if (latency >= self.options.get("colors_red")) color = "#ff0000"; else if (latency >= self.options.get("colors_orange")) color = "#ffbe00"; else if (latency >= self.options.get("colors_yellow")) color = "#f9ff00"; $(".btn-info").first().css("color", color).text(latency); // Clear out the display after a second of not receiving anything to show that it's not updating clearTimeout(self.intervalClear); self.intervalClear = setTimeout(self.clearPing, self.options.get("rate")*1000 + 1000); }); } latencyDisplay.prototype.clearPing = function() { $(".btn-info").first().text(""); } // Tony's OptionsPlugin Helper ///////////////////////////////////// // https://github.com/tony311/betterdiscord-optionshelper ////////// latencyDisplay.prototype.getOptionsPlugin = function(){ var OptionsPlugin = function(params){ // Constructor params.defaults = params.defaults || {}; $.each(params.defaults, function(key,option) { if (option.type == "range") { option.min = (option.min === undefined) ? 0 : option.min; option.max = (option.max === undefined) ? 100 : option.max; option.step = (option.step === undefined || option.step == 0) ? 1 : option.step; option.percent = (option.percent === undefined) ? false : option.percent; } }); this.options = this._clone(params.defaults); this.defaults = this._clone(params.defaults); this.plugin = params.plugin; this.saveCallback = params.onSave; this.resetCallback = params.onReset; this.pluginName = params.plugin.getName(); this.pluginShortName = this.pluginName.replace(/[^a-zA-Z0-9-_]/g,"").toLowerCase(); this.storageKey = params.storageKey || this.pluginShortName + "-options"; // Save a reference to this options instance in the original plugin params.plugin._optionsplugin = this; // Hook into the plugin's observer event and extend it to clean up our listeners when the settings window is hidden this.oldObserver = params.plugin.observer; var self = this; params.plugin.observer = function(e){ if (e.removedNodes[0] && e.removedNodes[0].id == "bd-psm-id") { $(document).off("keydown.optionsplugin").off("mouseup.optionsplugin").off("mousemove.optionsplugin"); } if (self.oldObserver) self.oldObserver.bind(self.plugin,e)(); } BdApi.clearCSS(`optionsplugin-${this.pluginShortName}`); BdApi.injectCSS(`optionsplugin-${this.pluginShortName}`, ` .optionsplugin-${this.pluginShortName}-title { font-size:18pt; font-weight:bold; margin-bottom:5px; } #optionsplugin-${this.pluginShortName} .help-text { margin:5px 0px; } .optionsplugin-${this.pluginShortName}-buttons { width:100%; margin-top:5px; } .optionsplugin-${this.pluginShortName}-buttons button { float:right; } #optionsplugin-${this.pluginShortName}-defaults { margin-right:5px; color:#ddd !important; background:#949494 !important; } .slider-handle span.hovered { opacity:1 !important; } `); }; OptionsPlugin.prototype.getDefaults = function(){ // Get default options object return this.defaults; }; OptionsPlugin.prototype.get = function(name){ // Get a value if (!this.options[name]) return; return this.options[name].value; }; OptionsPlugin.prototype.set = function(name,value){ // Set a value if (!this.options[name]) this.options[name] = {}; this.options[name].value = value; this.save(); }; OptionsPlugin.prototype.getAll = function(){ // Get all options return this.options; }; OptionsPlugin.prototype.simpleOptions = function(){ // Get options as a key=value object (used for bdPluginStorage) var simpleoptions = {}; $.each(this.options, function(key, option){ simpleoptions[key] = option.value; }); return simpleoptions; }; OptionsPlugin.prototype.save = function(){ // Save options to bdPluginStorage var self = this; $.each(this.simpleOptions(), function(key, value){ bdPluginStorage.set(self.storageKey, key, value); }); }; OptionsPlugin.prototype.load = function(){ // Load options from bdPluginStorage this.options = this._clone(this.defaults); var self = this; $.each(this.options, function(key, option){ if (self.options[key]) { var value = bdPluginStorage.get(self.storageKey, key); if (value !== null) { self.options[key].value = value; } } }); }; OptionsPlugin.prototype.reset = function(){ // Reset options to defaults this.options = this._clone(this.defaults); this.save(); } OptionsPlugin.prototype._setFromForm = function(elem){ // Save an element's value. elem = null to save all inputs var key = $(elem).attr("data-optionsplugin-name"); var value; if ($(elem).attr("type") == "checkbox") value = $(elem).prop("checked"); else if ($(elem).attr("type") == "number" || $(elem).attr("type") == "range") { value = parseFloat($(elem).val(), 10); } else value = $(elem).val(); this.options[key].value = value; this.save(); if (this.saveCallback) this.saveCallback(key, value); } OptionsPlugin.prototype._resetSettings = function(){ // Called when "Defaults" button is clicked var self = this; $.each(this.defaults, function(key, option){ var input = $(`#${self.pluginShortName}-settings-${key}`); if (option.type == "range") { input.attr("value", option.value).trigger("change"); } else if (option.type == "toggle") { input.prop("checked", option.value).trigger("change"); } else if (option.type == "select") { input.val(option.value).trigger("change"); } else input.attr("value", option.value).trigger("change"); }); if (this.resetCallback) this.resetCallback(); } OptionsPlugin.prototype.settingsHTML = function(){ // Returns the settings panel (call this in getSettingsPanel()) var self = this; var html = `